├── .gitattributes ├── .gitignore ├── EphData ├── ABPO00MDG_R_20200950000_01D_GN.rnx ├── BOR100POL_R_20200950000_01D_GN.rnx ├── BRDC00IGS_R_20211700000_01D_MN.rnx ├── JFNG00CHN_R_20200950000_01D_GN.rnx ├── JPLM00USA_R_20200950000_01D_GN.rnx ├── MGUE00ARG_R_20200950000_01D_GN.rnx └── OWMG00NZL_R_20200950000_01D_GN.rnx ├── IFdataGen ├── CMakeLists.txt ├── GNSS_Signal_Calculations.md ├── IFdataGen.cpp ├── IFdataGen.sln ├── IFdataGen.vcxproj ├── IFdataGen.vcxproj.filters ├── IFdataGen.vcxproj.user ├── README.md ├── configs │ ├── BDS_GAL_B3I_E6.json │ ├── GPS_BDS_GAL_GLO_L1CA_L1C_B1C_B1I_E1_G1.json │ ├── GPS_BDS_GAL_GLO_L2C_B2I_B2b_E5b_G2.json │ ├── GPS_BDS_GAL_L1CA_L1C_B1C_B1I_E1.json │ ├── GPS_BDS_GAL_L1CA_L1C_B1C_E1.json │ ├── GPS_BDS_GAL_L5_B2a_E5a.json │ └── IfGenTest.json └── images │ └── CMakeIntegrationPopup.png ├── JsonObsGen ├── JsonObsGen.cpp └── test_obs2.json ├── README.md ├── SignalSim Design Description.pdf ├── SignalSim JSON format specification.pdf ├── SignalSim输入信息JSON规范文档.pdf ├── SignalSim输入信息XML规范文档.pdf ├── XmlObsGen ├── CMakeLists.txt ├── ObsGen.cpp ├── reference.kml ├── reference.pos ├── test.o ├── test.pos ├── test_obs.xml ├── test_obs2.xml └── test_pos.xml ├── inc ├── Almanac.h ├── BCNav1Bit.h ├── BCNav2Bit.h ├── BCNav3Bit.h ├── BCNavBit.h ├── BasicTypes.h ├── CNav2Bit.h ├── CNavBit.h ├── ComplexNumber.h ├── ConstVal.h ├── Coordinate.h ├── D1D2NavBit.h ├── FNavBit.h ├── GNavBit.h ├── GnssTime.h ├── INavBit.h ├── JsonInterpreter.h ├── JsonParser.h ├── LNavBit.h ├── NavBit.h ├── NavData.h ├── PilotBit.h ├── PowerControl.h ├── PrnGenerate.h ├── Rinex.h ├── SatIfSignal.h ├── SatelliteParam.h ├── SatelliteSignal.h ├── SignalSim.h ├── Tracking.h ├── Trajectory.h ├── XmlElement.h └── XmlInterpreter.h ├── src ├── Almanac.cpp ├── BCNav1Bit.cpp ├── BCNav2Bit.cpp ├── BCNav3Bit.cpp ├── BCNavBit.cpp ├── CNav2Bit.cpp ├── CNavBit.cpp ├── ComplexNumber.cpp ├── Coordinate.cpp ├── D1D2NavBit.cpp ├── FNavBit.cpp ├── GNavBit.cpp ├── GnssTime.cpp ├── INavBit.cpp ├── JsonInterpreter.cpp ├── JsonParser.cpp ├── LNavBit.cpp ├── MemoryCode.dat ├── NavBit.cpp ├── NavData.cpp ├── PilotBit.cpp ├── PowerControl.cpp ├── PrnGenerate.cpp ├── Rinex.cpp ├── SatIfSignal.cpp ├── SatelliteParam.cpp ├── SatelliteSignal.cpp ├── Trajectory.cpp ├── XmlArguments.cpp ├── XmlElement.cpp └── XmlInterpreter.cpp └── 卫星信号仿真平台SignalSim设计说明.pdf /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vs 2 | IFdataGen/out/build -------------------------------------------------------------------------------- /IFdataGen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMake project for IFdataGen, include source and define project-specific logic here. 2 | cmake_minimum_required (VERSION 3.8) 3 | 4 | # Enable Hot Reload for MSVC compilers if supported. 5 | if (POLICY CMP0141) 6 | cmake_policy(SET CMP0141 NEW) 7 | set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$,$>,$<$:EditAndContinue>,$<$:ProgramDatabase>>") 8 | endif() 9 | 10 | # Declare the project name 11 | project ("IFdataGen") 12 | 13 | # Include directories for header files 14 | include_directories(../inc) 15 | 16 | # Add source files to the project 17 | add_executable (IFdataGen 18 | "IFdataGen.cpp" 19 | "../src/SatIfSignal.cpp" 20 | "../src/Almanac.cpp" 21 | "../src/BCNav1Bit.cpp" 22 | "../src/BCNav2Bit.cpp" 23 | "../src/BCNav3Bit.cpp" 24 | "../src/BCNavBit.cpp" 25 | "../src/CNav2Bit.cpp" 26 | "../src/CNavBit.cpp" 27 | "../src/ComplexNumber.cpp" 28 | "../src/Coordinate.cpp" 29 | "../src/D1D2NavBit.cpp" 30 | "../src/FNavBit.cpp" 31 | "../src/GNavBit.cpp" 32 | "../src/GnssTime.cpp" 33 | "../src/INavBit.cpp" 34 | "../src/JsonInterpreter.cpp" 35 | "../src/JsonParser.cpp" 36 | "../src/LNavBit.cpp" 37 | "../src/NavBit.cpp" 38 | "../src/NavData.cpp" 39 | "../src/PilotBit.cpp" 40 | "../src/PowerControl.cpp" 41 | "../src/PrnGenerate.cpp" 42 | "../src/Rinex.cpp" 43 | "../src/SatelliteParam.cpp" 44 | "../src/SatelliteSignal.cpp" 45 | "../src/Trajectory.cpp" 46 | "../src/XmlArguments.cpp" 47 | "../src/XmlElement.cpp" 48 | "../src/XmlInterpreter.cpp" 49 | ) 50 | 51 | # Specify the C++ standard if CMake version is >= 3.12 52 | if (CMAKE_VERSION VERSION_GREATER 3.12) 53 | set_property(TARGET IFdataGen PROPERTY CXX_STANDARD 20) 54 | endif() 55 | 56 | # TODO: Add tests and install targets if needed. 57 | -------------------------------------------------------------------------------- /IFdataGen/GNSS_Signal_Calculations.md: -------------------------------------------------------------------------------- 1 | # Detailed GNSS Signal Frequency Planning Calculations 2 | 3 | This document provides the detailed mathematical calculations behind the center frequencies and bandwidths for generation of **`IF Signal`** via **`IFDataGen`** package for multiple GNSS signal combinations. 4 | 5 | ## 1. L1CA + L1C + B1C + E1 6 | 7 | ### 1.1 Signal Frequencies and Bandwidths 8 | 9 | - L1CA: 1575.42 MHz, bandwidth 2.046 MHz (1574.397–1576.443 MHz) 10 | - L1C: 1575.42 MHz, bandwidth 4.092 MHz (1573.374–1577.466 MHz) 11 | - B1C: 1575.42 MHz, bandwidth 4.092 MHz (1573.374–1577.466 MHz) 12 | - E1: 1575.42 MHz, bandwidth 4.092 MHz (1573.374–1577.466 MHz) 13 | 14 | ### 1.2 Frequency Range Analysis 15 | 16 | - All four signals share the same center frequency: 1575.42 MHz 17 | - Lowest frequency: L1C/B1C/E1's lower edge = 1573.374 MHz 18 | - Highest frequency: L1C/B1C/E1's upper edge = 1577.466 MHz 19 | - Total frequency span = 1577.466 - 1573.374 = 4.092 MHz 20 | 21 | ### 1.3 Center Frequency Calculation 22 | 23 | - Center frequency = 1575.42 MHz (already perfectly aligned) 24 | - Required bandwidth = 4.092 MHz (to capture all BOC modulated signals) 25 | - No further optimization needed as the signals perfectly overlap at their center frequencies 26 | 27 | ### 1.4 Sampling Frequency Calculation 28 | 29 | - Minimum Fs = 4.092 MHz (theoretical minimum for complex sampling) 30 | - Recommended Fs = 5-6 MHz (to accommodate filter roll-off and implementation margin) 31 | - For better processing gain, Fs = 8-10 MHz can be used 32 | 33 | ## 2. L1CA + L1C + B1C + B1I + E1 34 | 35 | ### 2.1 Signal Frequencies and Bandwidths 36 | 37 | - L1CA: 1575.42 MHz, bandwidth 2.046 MHz (1574.397–1576.443 MHz) 38 | - L1C: 1575.42 MHz, bandwidth 4.092 MHz (1573.374–1577.466 MHz) 39 | - B1C: 1575.42 MHz, bandwidth 4.092 MHz (1573.374–1577.466 MHz) 40 | - E1: 1575.42 MHz, bandwidth 4.092 MHz (1573.374–1577.466 MHz) 41 | - B1I: 1561.098 MHz, bandwidth 4.092 MHz (1559.052–1563.144 MHz) 42 | 43 | ### 2.2 Frequency Range Analysis 44 | 45 | - Lowest frequency: B1I's lower edge = 1559.052 MHz 46 | - Highest frequency: L1C/B1C/E1's upper edge = 1577.466 MHz 47 | - Total frequency span = 1577.466 - 1559.052 = 18.414 MHz 48 | 49 | ### 2.3 Center Frequency Calculation 50 | 51 | - Midpoint center frequency = (1559.052 + 1577.466) / 2 = 1568.259 MHz ≈ 1568.26 MHz 52 | - Required bandwidth = 18.414 MHz ≈ 18.41 MHz 53 | - Verification: 54 | - Distance to lower edge: 1568.26 - 1559.052 = 9.208 MHz 55 | - Distance to upper edge: 1577.466 - 1568.26 = 9.206 MHz 56 | - Required full bandwidth = 9.208 + 9.206 = 18.414 MHz ≈ 18.41 MHz 57 | 58 | ### 2.4 Sampling Frequency Calculation 59 | 60 | - Minimum Fs = 18.41 MHz (theoretical minimum for complex sampling) 61 | - Recommended Fs = 20-25 MHz (to accommodate filter roll-off and implementation margin) 62 | 63 | ## 3. L1CA + L1C + B1C + B1I + E1 + G1 64 | 65 | ### 3.1 Signal Frequencies and Bandwidths 66 | 67 | - L1CA: 1575.42 MHz, bandwidth 2.046 MHz (1574.397–1576.443 MHz) 68 | - L1C: 1575.42 MHz, bandwidth 4.092 MHz (1573.374–1577.466 MHz) 69 | - B1C: 1575.42 MHz, bandwidth 4.092 MHz (1573.374–1577.466 MHz) 70 | - E1: 1575.42 MHz, bandwidth 4.092 MHz (1573.374–1577.466 MHz) 71 | - B1I: 1561.098 MHz, bandwidth 4.092 MHz (1559.052–1563.144 MHz) 72 | - G1 (GLONASS): 73 | - Center frequency: ~1602 MHz (varies by satellite channel) 74 | - Channel formula: 1602 + k × 0.5625 MHz, where k = -7 to +6 75 | - Bandwidth per channel: ~1 MHz 76 | - Full band range: 1598.0625 MHz to 1605.375 MHz 77 | 78 | ### 3.2 Frequency Range Analysis 79 | 80 | - Lowest frequency: B1I's lower edge = 1559.052 MHz 81 | - Highest frequency: G1's upper edge = 1605.375 MHz 82 | - Total frequency span = 1605.375 - 1559.052 = 46.323 MHz 83 | 84 | ### 3.3 Center Frequency Calculation 85 | 86 | - Midpoint center frequency = (1559.052 + 1605.375) / 2 = 1582.2135 MHz ≈ 1582.21 MHz 87 | - Required bandwidth = 46.323 MHz ≈ 46.32 MHz 88 | - Verification: 89 | - Distance to lower edge: 1582.21 - 1559.052 = 23.158 MHz 90 | - Distance to upper edge: 1605.375 - 1582.21 = 23.165 MHz 91 | - Required full bandwidth = 23.158 + 23.165 = 46.323 MHz ≈ 46.32 MHz 92 | 93 | ### 3.4 Sampling Frequency Calculation 94 | 95 | - Minimum Fs = 46.32 MHz (theoretical minimum for complex sampling) 96 | - Recommended Fs = 50-60 MHz (to accommodate filter roll-off and implementation margin) 97 | - For practical implementation, Fs = 50 MHz is typically used for this frequency combination 98 | 99 | ## 4. L2C + B2I + B2b + E5b + G2 100 | 101 | ### 4.1 Signal Frequencies and Bandwidths 102 | 103 | - L2C (GPS): 1227.60 MHz, bandwidth 2.046 MHz (1226.577–1228.623 MHz) 104 | - B2I (BeiDou): 1207.14 MHz, bandwidth 4.092 MHz (1205.094–1209.186 MHz) 105 | - B2b (BeiDou): 1207.14 MHz, bandwidth 20.46 MHz (1196.91–1217.37 MHz) 106 | - E5b (Galileo): 1207.14 MHz, bandwidth 20.46 MHz (1196.91–1217.37 MHz) 107 | - G2 (GLONASS): 108 | - Center frequency: ~1246 MHz (varies by satellite channel) 109 | - Channel formula: 1246 + k × 0.4375 MHz, where k = -7 to +6 110 | - Bandwidth per channel: ~0.8 MHz 111 | - Full band range: 1242.9375 MHz to 1248.625 MHz 112 | 113 | ### 4.2 Frequency Range Analysis 114 | 115 | - Lowest frequency: B2b/E5b's lower edge = 1196.91 MHz 116 | - Highest frequency: G2's upper edge = 1248.625 MHz 117 | - Total frequency span = 1248.625 - 1196.91 = 51.715 MHz 118 | 119 | ### 4.3 Center Frequency Calculation 120 | 121 | - Midpoint center frequency = (1196.91 + 1248.625) / 2 = 1222.7675 MHz ≈ 1222.77 MHz 122 | - Required bandwidth = 51.715 MHz ≈ 51.72 MHz 123 | - Verification: 124 | - Distance to lower edge: 1222.77 - 1196.91 = 25.86 MHz 125 | - Distance to upper edge: 1248.625 - 1222.77 = 25.855 MHz 126 | - Required full bandwidth = 25.86 + 25.855 = 51.715 MHz ≈ 51.72 MHz 127 | 128 | ### 4.4 Sampling Frequency Calculation 129 | 130 | - Minimum Fs = 51.72 MHz (theoretical minimum for complex sampling) 131 | - Recommended Fs = 55-60 MHz (to accommodate filter roll-off and implementation margin) 132 | 133 | ## 5. L5 + B2a + E5a 134 | 135 | ### 5.1 Signal Frequencies and Bandwidths 136 | 137 | - L5 (GPS): 1176.45 MHz, bandwidth 20.46 MHz (1166.22–1186.68 MHz) 138 | - B2a (BeiDou): 1176.45 MHz, bandwidth 20.46 MHz (1166.22–1186.68 MHz) 139 | - E5a (Galileo): 1176.45 MHz, bandwidth 20.46 MHz (1166.22–1186.68 MHz) 140 | 141 | ### 5.2 Frequency Range Analysis 142 | 143 | - All three signals have identical center frequencies and bandwidths 144 | - Lowest frequency: 1166.22 MHz (shared by all signals) 145 | - Highest frequency: 1186.68 MHz (shared by all signals) 146 | - Total frequency span = 1186.68 - 1166.22 = 20.46 MHz 147 | 148 | ### 5.3 Center Frequency Calculation 149 | 150 | - Center frequency = 1176.45 MHz (already perfectly aligned) 151 | - Required bandwidth = 20.46 MHz 152 | - No further optimization needed as the signals perfectly overlap 153 | 154 | ### 5.4 Sampling Frequency Calculation 155 | 156 | - Minimum Fs = 20.46 MHz (theoretical minimum for complex sampling) 157 | - Recommended Fs = 25-30 MHz (to accommodate filter roll-off and implementation margin) 158 | 159 | ## 6. B3I + E6 160 | 161 | ### 6.1 Signal Frequencies and Bandwidths 162 | 163 | - B3I (BeiDou): 1268.52 MHz, bandwidth 20.46 MHz (1258.29–1278.75 MHz) 164 | - E6 (Galileo): 1278.75 MHz, bandwidth 40.92 MHz (1258.29–1299.21 MHz) 165 | 166 | ### 6.2 Frequency Range Analysis 167 | 168 | - Lowest frequency: B3I/E6 lower edge = 1258.29 MHz (they share the same lower edge) 169 | - Highest frequency: E6 upper edge = 1299.21 MHz 170 | - Total frequency span = 1299.21 - 1258.29 = 40.92 MHz 171 | 172 | ### 6.3 Center Frequency Calculation 173 | 174 | - Midpoint center frequency = (1258.29 + 1299.21) / 2 = 1278.75 MHz 175 | - Required bandwidth = 40.92 MHz 176 | - Verification: 177 | - Distance to lower edge: 1278.75 - 1258.29 = 20.46 MHz 178 | - Distance to upper edge: 1299.21 - 1278.75 = 20.46 MHz 179 | - Required full bandwidth = 20.46 + 20.46 = 40.92 MHz 180 | 181 | ### 6.4 Sampling Frequency Calculation 182 | 183 | - Minimum Fs = 40.92 MHz (theoretical minimum for complex sampling) 184 | - Recommended Fs = 45-50 MHz (to accommodate filter roll-off and implementation margin) 185 | -------------------------------------------------------------------------------- /IFdataGen/IFdataGen.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.6.33723.286 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IFdataGen", "IFdataGen.vcxproj", "{8939F7F4-C8F3-4867-9CB4-1F896402CFD0}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {8939F7F4-C8F3-4867-9CB4-1F896402CFD0}.Debug|x64.ActiveCfg = Debug|x64 17 | {8939F7F4-C8F3-4867-9CB4-1F896402CFD0}.Debug|x64.Build.0 = Debug|x64 18 | {8939F7F4-C8F3-4867-9CB4-1F896402CFD0}.Debug|x86.ActiveCfg = Debug|Win32 19 | {8939F7F4-C8F3-4867-9CB4-1F896402CFD0}.Debug|x86.Build.0 = Debug|Win32 20 | {8939F7F4-C8F3-4867-9CB4-1F896402CFD0}.Release|x64.ActiveCfg = Release|x64 21 | {8939F7F4-C8F3-4867-9CB4-1F896402CFD0}.Release|x64.Build.0 = Release|x64 22 | {8939F7F4-C8F3-4867-9CB4-1F896402CFD0}.Release|x86.ActiveCfg = Release|Win32 23 | {8939F7F4-C8F3-4867-9CB4-1F896402CFD0}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {4385FE45-3423-47D9-9D04-85CB17B79D72} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /IFdataGen/IFdataGen.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {8939f7f4-c8f3-4867-9cb4-1f896402cfd0} 25 | IFdataGen 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | true 77 | WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 78 | true 79 | ..\inc 80 | 81 | 82 | Console 83 | true 84 | 85 | 86 | 87 | 88 | Level3 89 | true 90 | true 91 | true 92 | WIN32;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 93 | true 94 | ..\inc 95 | 96 | 97 | Console 98 | true 99 | true 100 | true 101 | 102 | 103 | 104 | 105 | Level3 106 | true 107 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 108 | true 109 | 110 | 111 | Console 112 | true 113 | 114 | 115 | 116 | 117 | Level3 118 | true 119 | true 120 | true 121 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 122 | true 123 | 124 | 125 | Console 126 | true 127 | true 128 | true 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | -------------------------------------------------------------------------------- /IFdataGen/IFdataGen.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | Header Files 47 | 48 | 49 | Header Files 50 | 51 | 52 | Header Files 53 | 54 | 55 | Header Files 56 | 57 | 58 | Header Files 59 | 60 | 61 | Header Files 62 | 63 | 64 | Header Files 65 | 66 | 67 | Header Files 68 | 69 | 70 | Header Files 71 | 72 | 73 | Header Files 74 | 75 | 76 | Header Files 77 | 78 | 79 | Header Files 80 | 81 | 82 | Header Files 83 | 84 | 85 | Header Files 86 | 87 | 88 | Header Files 89 | 90 | 91 | Header Files 92 | 93 | 94 | Header Files 95 | 96 | 97 | Header Files 98 | 99 | 100 | Header Files 101 | 102 | 103 | Header Files 104 | 105 | 106 | Header Files 107 | 108 | 109 | 110 | 111 | Source Files 112 | 113 | 114 | Source Files 115 | 116 | 117 | Source Files 118 | 119 | 120 | Source Files 121 | 122 | 123 | Source Files 124 | 125 | 126 | Source Files 127 | 128 | 129 | Source Files 130 | 131 | 132 | Source Files 133 | 134 | 135 | Source Files 136 | 137 | 138 | Source Files 139 | 140 | 141 | Source Files 142 | 143 | 144 | Source Files 145 | 146 | 147 | Source Files 148 | 149 | 150 | Source Files 151 | 152 | 153 | Source Files 154 | 155 | 156 | Source Files 157 | 158 | 159 | Source Files 160 | 161 | 162 | Source Files 163 | 164 | 165 | Source Files 166 | 167 | 168 | Source Files 169 | 170 | 171 | Source Files 172 | 173 | 174 | Source Files 175 | 176 | 177 | Source Files 178 | 179 | 180 | Source Files 181 | 182 | 183 | Source Files 184 | 185 | 186 | Source Files 187 | 188 | 189 | Source Files 190 | 191 | 192 | Source Files 193 | 194 | 195 | 196 | 197 | Source Files 198 | 199 | 200 | -------------------------------------------------------------------------------- /IFdataGen/IFdataGen.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | WindowsLocalDebugger 7 | 8 | 9 | 10 | 11 | WindowsLocalDebugger 12 | 13 | -------------------------------------------------------------------------------- /IFdataGen/configs/BDS_GAL_B3I_E6.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1.0, 3 | "description": "test file for IF data generation", 4 | "time": { 5 | "type": "UTC", 6 | "year": 2021, 7 | "month": 6, 8 | "day": 19, 9 | "hour": 10, 10 | "minute": 5, 11 | "second": 30 12 | }, 13 | "trajectory": { 14 | "name": "test scenario", 15 | "initPosition": { 16 | "type": "LLA", 17 | "format": "d", 18 | "longitude": -121.915773, 19 | "latitude": 37.352721, 20 | "altitude": 20 21 | }, 22 | "initVelocity": { 23 | "type": "SCU", 24 | "speed": 5, 25 | "course": 318.91 26 | }, 27 | "trajectoryList": [ 28 | { 29 | "type": "Const", 30 | "time": 0.2 31 | } 32 | 33 | ] 34 | }, 35 | "ephemeris": { 36 | "type": "RINEX", 37 | "name": "..\/..\/..\/..\/EphData\/BRDC00IGS_R_20211700000_01D_MN.rnx" 38 | }, 39 | "output": { 40 | "type": "IFdata", 41 | "format": "IQ8", 42 | "sampleFreq": 30.75, 43 | "centerFreq": 1273.64, 44 | "name": "BDS_GAL_B3I_E6_8.bin", 45 | "config": { 46 | "elevationMask": 3 47 | }, 48 | "systemSelect": [ 49 | { 50 | "system": "BDS", 51 | "signal": "B3I", 52 | "enable": true 53 | }, 54 | { 55 | "system": "Galileo", 56 | "signal": "E6", 57 | "enable": true 58 | } 59 | ] 60 | }, 61 | "power": { 62 | "noiseFloor": -172, 63 | "initPower": { 64 | "unit": "dBHz", 65 | "value": 47 66 | }, 67 | "elevationAdjust": false 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /IFdataGen/configs/GPS_BDS_GAL_GLO_L1CA_L1C_B1C_B1I_E1_G1.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1.0, 3 | "description": "test file for IF data generation", 4 | "time": { 5 | "type": "UTC", 6 | "year": 2021, 7 | "month": 6, 8 | "day": 19, 9 | "hour": 10, 10 | "minute": 5, 11 | "second": 30 12 | }, 13 | "trajectory": { 14 | "name": "test scenario", 15 | "initPosition": { 16 | "type": "LLA", 17 | "format": "d", 18 | "longitude": -121.915773, 19 | "latitude": 37.352721, 20 | "altitude": 20 21 | }, 22 | "initVelocity": { 23 | "type": "SCU", 24 | "speed": 5, 25 | "course": 318.91 26 | }, 27 | "trajectoryList": [ 28 | { 29 | "type": "Const", 30 | "time": 0.2 31 | } 32 | 33 | ] 34 | }, 35 | "ephemeris": { 36 | "type": "RINEX", 37 | "name": "..\/..\/..\/..\/EphData\/BRDC00IGS_R_20211700000_01D_MN.rnx" 38 | }, 39 | "output": { 40 | "type": "IFdata", 41 | "format": "IQ8", 42 | "sampleFreq": 46.329, 43 | "centerFreq": 1582.2105, 44 | "name": "GPS_BDS_GAL_GLO_L1CA_L1C_B1C_B1I_E1_G1_8.bin", 45 | "config": { 46 | "elevationMask": 3 47 | }, 48 | "systemSelect": [ 49 | { 50 | "system": "GPS", 51 | "signal": "L1CA", 52 | "enable": true 53 | }, 54 | { 55 | "system": "GPS", 56 | "signal": "L1C", 57 | "enable": true 58 | }, 59 | 60 | { 61 | "system": "BDS", 62 | "signal": "B1C", 63 | "enable": true 64 | }, 65 | { 66 | "system": "BDS", 67 | "signal": "B1I", 68 | "enable": true 69 | }, 70 | { 71 | "system": "Galileo", 72 | "signal": "E1", 73 | "enable": true 74 | }, 75 | { 76 | "system": "GLONASS", 77 | "signal": "G1", 78 | "enable": true 79 | } 80 | ] 81 | }, 82 | "power": { 83 | "noiseFloor": -172, 84 | "initPower": { 85 | "unit": "dBHz", 86 | "value": 47 87 | }, 88 | "elevationAdjust": false 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /IFdataGen/configs/GPS_BDS_GAL_GLO_L2C_B2I_B2b_E5b_G2.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1.0, 3 | "description": "test file for IF data generation", 4 | "time": { 5 | "type": "UTC", 6 | "year": 2021, 7 | "month": 6, 8 | "day": 19, 9 | "hour": 10, 10 | "minute": 5, 11 | "second": 30 12 | }, 13 | "trajectory": { 14 | "name": "test scenario", 15 | "initPosition": { 16 | "type": "LLA", 17 | "format": "d", 18 | "longitude": -121.915773, 19 | "latitude": 37.352721, 20 | "altitude": 20 21 | }, 22 | "initVelocity": { 23 | "type": "SCU", 24 | "speed": 5, 25 | "course": 318.91 26 | }, 27 | "trajectoryList": [ 28 | { 29 | "type": "Const", 30 | "time": 0.2 31 | } 32 | 33 | ] 34 | }, 35 | "ephemeris": { 36 | "type": "RINEX", 37 | "name": "..\/..\/..\/..\/EphData\/BRDC00IGS_R_20211700000_01D_MN.rnx" 38 | }, 39 | "output": { 40 | "type": "IFdata", 41 | "format": "IQ8", 42 | "sampleFreq": 53.49, 43 | "centerFreq": 1221.88, 44 | "name": "GPS_BDS_GAL_GLO_L2C_B2I_B2b_E5b_G2_8.bin", 45 | "config": { 46 | "elevationMask": 3 47 | }, 48 | "systemSelect": [ 49 | { 50 | "system": "GPS", 51 | "signal": "L2C", 52 | "enable": true 53 | }, 54 | { 55 | "system": "BDS", 56 | "signal": "B2I", 57 | "enable": true 58 | }, 59 | { 60 | "system": "BDS", 61 | "signal": "B2b", 62 | "enable": true 63 | }, 64 | { 65 | "system": "Galileo", 66 | "signal": "E5b", 67 | "enable": true 68 | }, 69 | { 70 | "system": "GLONASS", 71 | "signal": "G2", 72 | "enable": true 73 | } 74 | ] 75 | }, 76 | "power": { 77 | "noiseFloor": -172, 78 | "initPower": { 79 | "unit": "dBHz", 80 | "value": 47 81 | }, 82 | "elevationAdjust": false 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /IFdataGen/configs/GPS_BDS_GAL_L1CA_L1C_B1C_B1I_E1.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1.0, 3 | "description": "test file for IF data generation", 4 | "time": { 5 | "type": "UTC", 6 | "year": 2021, 7 | "month": 6, 8 | "day": 19, 9 | "hour": 10, 10 | "minute": 5, 11 | "second": 30 12 | }, 13 | "trajectory": { 14 | "name": "test scenario", 15 | "initPosition": { 16 | "type": "LLA", 17 | "format": "d", 18 | "longitude": -121.915773, 19 | "latitude": 37.352721, 20 | "altitude": 20 21 | }, 22 | "initVelocity": { 23 | "type": "SCU", 24 | "speed": 5, 25 | "course": 318.91 26 | }, 27 | "trajectoryList": [ 28 | { 29 | "type": "Const", 30 | "time": 0.2 31 | } 32 | 33 | ] 34 | }, 35 | "ephemeris": { 36 | "type": "RINEX", 37 | "name": "..\/..\/..\/..\/EphData\/BRDC00IGS_R_20211700000_01D_MN.rnx" 38 | }, 39 | "output": { 40 | "type": "IFdata", 41 | "format": "IQ8", 42 | "sampleFreq": 18.48, 43 | "centerFreq": 1568.286, 44 | "name": "GPS_BDS_GAL_L1CA_L1C_B1C_B1I_E1_8.bin", 45 | "config": { 46 | "elevationMask": 3 47 | }, 48 | "systemSelect": [ 49 | { 50 | "system": "GPS", 51 | "signal": "L1CA", 52 | "enable": true 53 | }, 54 | { 55 | "system": "GPS", 56 | "signal": "L1C", 57 | "enable": true 58 | }, 59 | 60 | { 61 | "system": "BDS", 62 | "signal": "B1C", 63 | "enable": true 64 | }, 65 | { 66 | "system": "BDS", 67 | "signal": "B1I", 68 | "enable": true 69 | }, 70 | { 71 | "system": "Galileo", 72 | "signal": "E1", 73 | "enable": true 74 | } 75 | ] 76 | }, 77 | "power": { 78 | "noiseFloor": -172, 79 | "initPower": { 80 | "unit": "dBHz", 81 | "value": 47 82 | }, 83 | "elevationAdjust": false 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /IFdataGen/configs/GPS_BDS_GAL_L1CA_L1C_B1C_E1.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1.0, 3 | "description": "test file for IF data generation", 4 | "time": { 5 | "type": "UTC", 6 | "year": 2021, 7 | "month": 6, 8 | "day": 19, 9 | "hour": 10, 10 | "minute": 5, 11 | "second": 30 12 | }, 13 | "trajectory": { 14 | "name": "test scenario", 15 | "initPosition": { 16 | "type": "LLA", 17 | "format": "d", 18 | "longitude": -121.915773, 19 | "latitude": 37.352721, 20 | "altitude": 20 21 | }, 22 | "initVelocity": { 23 | "type": "SCU", 24 | "speed": 5, 25 | "course": 318.91 26 | }, 27 | "trajectoryList": [ 28 | { 29 | "type": "Const", 30 | "time": 0.2 31 | } 32 | 33 | ] 34 | }, 35 | "ephemeris": { 36 | "type": "RINEX", 37 | "name": "..\/..\/..\/..\/EphData\/BRDC00IGS_R_20211700000_01D_MN.rnx" 38 | }, 39 | "output": { 40 | "type": "IFdata", 41 | "format": "IQ8", 42 | "sampleFreq": 4.092, 43 | "centerFreq": 1575.42, 44 | "name": "GPS_BDS_GAL_L1CA_L1C_B1C_E1_8.bin", 45 | "config": { 46 | "elevationMask": 3 47 | }, 48 | "systemSelect": [ 49 | { 50 | "system": "GPS", 51 | "signal": "L1CA", 52 | "enable": true 53 | }, 54 | { 55 | "system": "GPS", 56 | "signal": "L1C", 57 | "enable": true 58 | }, 59 | 60 | { 61 | "system": "BDS", 62 | "signal": "B1C", 63 | "enable": true 64 | }, 65 | { 66 | "system": "Galileo", 67 | "signal": "E1", 68 | "enable": true 69 | } 70 | ] 71 | }, 72 | "power": { 73 | "noiseFloor": -172, 74 | "initPower": { 75 | "unit": "dBHz", 76 | "value": 47 77 | }, 78 | "elevationAdjust": false 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /IFdataGen/configs/GPS_BDS_GAL_L5_B2a_E5a.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1.0, 3 | "description": "test file for IF data generation", 4 | "time": { 5 | "type": "UTC", 6 | "year": 2021, 7 | "month": 6, 8 | "day": 19, 9 | "hour": 10, 10 | "minute": 5, 11 | "second": 30 12 | }, 13 | "trajectory": { 14 | "name": "test scenario", 15 | "initPosition": { 16 | "type": "LLA", 17 | "format": "d", 18 | "longitude": -121.915773, 19 | "latitude": 37.352721, 20 | "altitude": 20 21 | }, 22 | "initVelocity": { 23 | "type": "SCU", 24 | "speed": 5, 25 | "course": 318.91 26 | }, 27 | "trajectoryList": [ 28 | { 29 | "type": "Const", 30 | "time": 0.2 31 | } 32 | 33 | ] 34 | }, 35 | "ephemeris": { 36 | "type": "RINEX", 37 | "name": "..\/..\/..\/..\/EphData\/BRDC00IGS_R_20211700000_01D_MN.rnx" 38 | }, 39 | "output": { 40 | "type": "IFdata", 41 | "format": "IQ8", 42 | "sampleFreq": 24, 43 | "centerFreq": 1176.45, 44 | "name": "GPS_BDS_GAL_L5_B2a_E5a_8.bin", 45 | "config": { 46 | "elevationMask": 3 47 | }, 48 | "systemSelect": [ 49 | { 50 | "system": "GPS", 51 | "signal": "L5", 52 | "enable": true 53 | }, 54 | { 55 | "system": "BDS", 56 | "signal": "B2a", 57 | "enable": true 58 | }, 59 | { 60 | "system": "Galileo", 61 | "signal": "E5a", 62 | "enable": true 63 | } 64 | ] 65 | }, 66 | "power": { 67 | "noiseFloor": -172, 68 | "initPower": { 69 | "unit": "dBHz", 70 | "value": 47 71 | }, 72 | "elevationAdjust": false 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /IFdataGen/configs/IfGenTest.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1.0, 3 | "description": "test file for IF data generation", 4 | "time": { 5 | "type": "UTC", 6 | "year": 2021, 7 | "month": 6, 8 | "day": 19, 9 | "hour": 10, 10 | "minute": 5, 11 | "second": 30 12 | }, 13 | "trajectory": { 14 | "name": "test scenario", 15 | "initPosition": { 16 | "type": "LLA", 17 | "format": "d", 18 | "longitude": -121.915773, 19 | "latitude": 37.352721, 20 | "altitude": 20 21 | }, 22 | "initVelocity": { 23 | "type": "SCU", 24 | "speed": 5, 25 | "course": 318.91 26 | }, 27 | "trajectoryList": [ 28 | { 29 | "type": "Const", 30 | "time": 0.2 31 | }, 32 | { 33 | "type": "Jerk", 34 | "time": 0.2, 35 | "acceleration": 0.2 36 | }, 37 | { 38 | "type": "ConstAcc", 39 | "time": 0.1, 40 | "acceleration": 0.2 41 | } 42 | ] 43 | }, 44 | "ephemeris": { 45 | "type": "RINEX", 46 | "name": "..\/..\/..\/..\/EphData\/BRDC00IGS_R_20211700000_01D_MN.rnx" 47 | }, 48 | "output": { 49 | "type": "IFdata", 50 | "format": "IQ8", 51 | "sampleFreq": 25, 52 | "centerFreq": 1580, 53 | "name": "IfGenTest8.bin", 54 | "config": { 55 | "elevationMask": 3 56 | }, 57 | "systemSelect": [ 58 | { 59 | "system": "GPS", 60 | "signal": "L1CA", 61 | "enable": true 62 | }, 63 | { 64 | "system": "BDS", 65 | "signal": "B1C", 66 | "enable": false 67 | }, 68 | { 69 | "system": "BDS", 70 | "signal": "B1I", 71 | "enable": false 72 | }, 73 | { 74 | "system": "Galileo", 75 | "enable": false 76 | }, 77 | { 78 | "system": "GLONASS", 79 | "enable": false 80 | } 81 | ] 82 | }, 83 | "power": { 84 | "noiseFloor": -172, 85 | "initPower": { 86 | "unit": "dBHz", 87 | "value": 47 88 | }, 89 | "elevationAdjust": false 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /IFdataGen/images/CMakeIntegrationPopup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/globsky/SignalSim/3f82005b3b69a3c22218bda4fb133b34a79098a0/IFdataGen/images/CMakeIntegrationPopup.png -------------------------------------------------------------------------------- /JsonObsGen/test_obs2.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1.0, 3 | "description": "test file with the same settings as test_obs2.xml", 4 | "time": { 5 | "type": "UTC", 6 | "year": 2021, 7 | "month": 6, 8 | "day": 19, 9 | "hour": 10, 10 | "minute": 5, 11 | "second": 30 12 | }, 13 | "trajectory": { 14 | "name": "test flight", 15 | "initPosition": { 16 | "type": "LLA", 17 | "format": "d", 18 | "longitude": -121.915773, 19 | "latitude": 37.352721, 20 | "altitude": 20 21 | }, 22 | "initVelocity": { 23 | "type": "SCU", 24 | "speed": 5, 25 | "course": 318.91 26 | }, 27 | "trajectoryList": [ 28 | { 29 | "type": "Const", 30 | "time": 5 31 | }, 32 | { 33 | "type": "Jerk", 34 | "time": 3, 35 | "acceleration": 3 36 | }, 37 | { 38 | "type": "ConstAcc", 39 | "time": 20, 40 | "acceleration": 3 41 | }, 42 | { 43 | "type": "Jerk", 44 | "time": 6, 45 | "acceleration": 0 46 | }, 47 | { 48 | "type": "VerticalAcc", 49 | "speed": 20, 50 | "acceleration": 2 51 | }, 52 | { 53 | "type": "Const", 54 | "time": 100 55 | }, 56 | { 57 | "type": "VerticalAcc", 58 | "speed": 0, 59 | "acceleration": 1 60 | }, 61 | { 62 | "type": "Const", 63 | "time": 30 64 | }, 65 | { 66 | "type": "HorizontalTurn", 67 | "acceleration": 2, 68 | "angle": 225 69 | }, 70 | { 71 | "type": "Const", 72 | "time": 200 73 | }, 74 | { 75 | "type": "HorizontalTurn", 76 | "time": 120, 77 | "angle": -45 78 | }, 79 | { 80 | "type": "VerticalAcc", 81 | "speed": 0, 82 | "acceleration": 0.1 83 | }, 84 | { 85 | "type": "Const", 86 | "time": 120 87 | }, 88 | { 89 | "type": "HorizontalTurn", 90 | "radius": 4676.66, 91 | "angle": -180 92 | }, 93 | { 94 | "type": "Const", 95 | "time": 10 96 | }, 97 | { 98 | "type": "VerticalAcc", 99 | "speed": -20, 100 | "acceleration": -1 101 | }, 102 | { 103 | "type": "Const", 104 | "time": 19.384785 105 | }, 106 | { 107 | "type": "VerticalAcc", 108 | "speed": 0, 109 | "acceleration": 0.10811 110 | }, 111 | { 112 | "type": "VerticalAcc", 113 | "speed": 0, 114 | "time": 1 115 | }, 116 | { 117 | "type": "Const", 118 | "time": 2 119 | }, 120 | { 121 | "type": "Jerk", 122 | "acceleration": -6, 123 | "time": 3 124 | }, 125 | { 126 | "type": "ConstAcc", 127 | "speed": 10, 128 | "acceleration": -6 129 | }, 130 | { 131 | "type": "Const", 132 | "time": 5 133 | } 134 | ] 135 | }, 136 | "ephemeris": { 137 | "type": "RINEX", 138 | "name": "..\/EphData\/BRDC00IGS_R_20211700000_01D_MN.rnx" 139 | }, 140 | "output": { 141 | "type": "observation", 142 | "format": "RINEX", 143 | "name": "test2.o", 144 | "interval": 1, 145 | "config": { 146 | "elevationMask": 3, 147 | "maskOut": [ 148 | { 149 | "system": "GPS", 150 | "svid": [ 151 | 10, 152 | 20, 153 | 21 154 | ] 155 | }, 156 | { 157 | "system": "Galileo", 158 | "svid": 3 159 | } 160 | ] 161 | }, 162 | "systemSelect": [ 163 | { 164 | "system": "GPS", 165 | "signal": "L1CA", 166 | "enable": true 167 | }, 168 | { 169 | "system": "GPS", 170 | "signal": "L2C", 171 | "enable": false 172 | }, 173 | { 174 | "system": "BDS", 175 | "enable": true 176 | }, 177 | { 178 | "system": "BDS", 179 | "signal": "B3I", 180 | "enable": false 181 | }, 182 | { 183 | "system": "Galileo", 184 | "enable": true 185 | }, 186 | { 187 | "system": "GLONASS", 188 | "enable": false 189 | } 190 | ] 191 | }, 192 | "power": { 193 | "noiseFloor": -172, 194 | "initPower": { 195 | "unit": "dBHz", 196 | "value": 47 197 | }, 198 | "elevationAdjust": false, 199 | "signalPower": [ 200 | { 201 | "system": "GPS", 202 | "powerValue": { 203 | "time": 0, 204 | "unit": "dBm", 205 | "value": -125 206 | } 207 | }, 208 | { 209 | "system": "GPS", 210 | "svid": 4, 211 | "powerValue": [ 212 | { 213 | "time": 10, 214 | "unit": "dBHz", 215 | "value": 45 216 | }, 217 | { 218 | "time": 20, 219 | "unit": "dBHz", 220 | "value": 40 221 | }, 222 | { 223 | "time": 30, 224 | "unit": "dBHz", 225 | "value": 35 226 | }, 227 | { 228 | "time": 40, 229 | "unit": "dBHz", 230 | "value": 30 231 | }, 232 | { 233 | "time": 50, 234 | "unit": "dBHz", 235 | "value": 28 236 | }, 237 | { 238 | "time": 60, 239 | "unit": "dBHz", 240 | "value": 26 241 | }, 242 | { 243 | "time": 70, 244 | "unit": "dBHz", 245 | "value": 24 246 | }, 247 | { 248 | "time": 80, 249 | "unit": "dBHz", 250 | "value": 22 251 | }, 252 | { 253 | "time": 90, 254 | "unit": "dBHz", 255 | "value": 20 256 | }, 257 | { 258 | "time": 100, 259 | "unit": "dBHz", 260 | "value": -1 261 | } 262 | ] 263 | } 264 | ] 265 | } 266 | } 267 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SignalSim 2 | 3 | A multi-stage GNSS signal and data simulator 4 | 5 | This is a GNSS signal and data simulator and generator to help the development of GNSS receivers. 6 | 7 | This program supports multiple stages of simulation output: 8 | 9 | 1. **Reference trajectory of receiver** (as standard reference result) 10 | 2. **Observation** (helps to debug and test PVT program) 11 | 3. **Baseband correlation result** (combined with local channel configuration parameters, helps to debug baseband tracking and control program) 12 | 4. **Digital IF result** (helps to debug baseband process algorithm) 13 | 5. **A realtime GNSS signal simulator** (with hardware signal interpolation and up converter) 14 | 15 | ## System Capabilities 16 | 17 | SignalSim provides comprehensive support for multi-constellation GNSS simulation with the following capabilities: 18 | 19 | ### Constellation Support 20 | 21 | - **GPS**: Full constellation of 32 satellites 22 | - **BeiDou (BDS)**: Complete constellation of 63 satellites 23 | - **Galileo**: Full constellation of 36 satellites 24 | - **GLONASS**: Complete constellation of 24 satellites 25 | 26 | ### Technical Specifications 27 | 28 | - **Constellation**: Support GPS, BDS, GLONASS and Galileo, QZSS/IRNSS interface reserved for future expansion 29 | - **Multiple frequency bands**: Support for L1/L2/L5, B1/B2/B3, E1/E5/E6, G1/G2 30 | - **Data formats**: RINEX 2/3/4 support for observation and navigation data 31 | - **Configuration**: JSON-based scenario configuration 32 | - **Signal generation**: Digital IF samples with configurable sampling rate and bit depth 33 | 34 | SignalSim is designed for both educational and professional use, with commercial licensing available for advanced features. 35 | 36 | ## Signal Support and Testing Status 37 | 38 | The following table shows the current testing status of various GNSS signals in SignalSim: 39 | 40 | ## Key Components 41 | 42 | ### IFdataGen 43 | 44 | The IF Data Generator component creates GNSS Intermediate Frequency (IF) sample files that can be used with RF front-ends or GNSS software-defined radio applications. For detailed information on building and using this component, see the [IFdataGen README](./IFdataGen/README.md). 45 | 46 | ### JsonObsGen 47 | 48 | The JSON Observation Generator creates GNSS observation data based on JSON configuration files. This component replaced the older XML-based generator. 49 | 50 | ### Library Core 51 | 52 | The core libraries provide fundamental GNSS data processing capabilities including: 53 | 54 | - Ephemeris and almanac parsing 55 | - Navigation bit stream generation 56 | - Satellite signal modeling 57 | - RINEX file handling 58 | - Trajectory calculation 59 | 60 | --- 61 | 62 | ## Change List 63 | 64 | ### 2025 65 | 66 | - **6/6/2025** 67 | - Add `configs` folder with examples `.json` files for multiple constellations. 68 | - Explain how to set center frequency and bandwidth for each constellation in the [IFdataGen GNSS_Signal_Calculations](./IFdataGen/GNSS_Signal_Calculations.md). 69 | - Expand unit and integration tests for signal generation and update the test matrix accordingly. 70 | - Update [IFdataGen README](./IFdataGen/README.md) with new examples and configuration guidance. 71 | 72 | 73 | - **5/14/2025** 74 | - Rewrite BCNAV1/2/3 navigation data stream generation method (ephemeris generation completed, almanac in next release) 75 | - Rename `PrnCode` to `PrnGenerate` 76 | - Add variable valid in struct GPS_ALMANAC and redefine contents of variable flag 77 | 78 | - **5/6/2025** 79 | - Relocate shared RINEX data files from `/XmlObsGen` to root 80 | - Relocate SatIfSignal.h and SatIfSignal.cpp from `IFdataGen/` to `inc/` and `src/` 81 | 82 | - **4/22/2025** 83 | - Enhanced documentation with updated main `README.md` 84 | - Added `CMakeLists.txt` to support `IFdataGen` builds 85 | - Fixed initial bugs in `IFdataGen.cpp` implementation 86 | - Implemented command-line support for JSON configuration files 87 | - Created detailed `README.md` in `IFdataGen` folder with demo instructions and usage examples 88 | - Integrated `EphData` folder into `IFdataGen` Folder 89 | 90 | - **3/11/2025** 91 | - Demo program to generate IF signal is added with sample .json config file 92 | - Most common signals are supported but with only limited verification 93 | - Following signals will be only available with commercial license: L1P/L2P, E5 AltBOC, TMBOC, ACEBOC, QMBOX, LEX CSK 94 | - Multi-thread version which runs dozen times faster only available with commercial license 95 | 96 | - **1/28/2025** 97 | - Bug fix and improvements on almanac data stream composition 98 | - Fix bug on possible incorrect week number in data stream of I/NAV and F/NAV if almanac of some satellite missing 99 | - Fix bug on incorrect week number set in data stream 100 | - Second parameter of function CompleteAlmanac() uses UTC time 101 | - Add BDS GEO satellite ephemeris to almanac conversion 102 | - Add GLONASS satellite ephemeris to almanac conversion 103 | 104 | - **1/15/2025** 105 | - Rearrange some definitions and declarations 106 | - Change FREQ_INDEX_XXX definitions to SIGNAL_INDEX_XXX for better discrimination of signals at same frequency 107 | - Key word extension in JSON for future IF data generation support 108 | 109 | ### 2024 110 | 111 | - **10/20/2024** 112 | - Add JSON format scenario control file to replace XML format 113 | - Add JsonParser.cpp/JsonParser.h to read JSON data structure from file 114 | - Add JsonInterpreter.cpp/JsonInterpreter.h to translate JSON data structure to scenario control 115 | - Add a JsonObsGen project that has the same output using test_obs2.json (same parameters as test_obs2.xml used in XmlObsGen project) 116 | 117 | - **10/5/2024** 118 | - CMakeLists.txt added to XmlObsGen folder to guide how to build project using cmake 119 | - Minor fixes 120 | 121 | - **10/1/2024** 122 | - New CNavBit class for CNAV bit stream generation 123 | - Expand URA index range to support corresponding data field in CNAV 124 | - L2CM and L5I signal use CNAV data modulation 125 | - **9/21/2024** 126 | 127 | - Add Galileo E5a F/NAV data modulation support 128 | - Bug fix of group delay and signal modulation phase in B2b signal 129 | 130 | - **6/5/2024** 131 | - Add almanac word (word 7~10) to Galileo E1 data stream 132 | - Add Reed-Solomon encoded ephemeris (word 17~20) to Galileo E1 data stream 133 | - Bug fixes on E1 ephemeris word and TOW composition 134 | 135 | - **2/29/2024** 136 | - Enable almanac read and data stream generation containing almanac subframe/string 137 | - Change function parameter of SetAlmanac() in NavBit and all derived classes 138 | - Add functions to read almanac file in Almanac.cpp 139 | - Add array to store almanacs in CNavData class 140 | - Add functions to read almanac files and convert ephemeris to almanac in CNavData class 141 | - Ephemeris to almanac conversion for GLONASS and BDS GEO satellites will be added in future version 142 | - The time parameter of FindEphemeris() and FindGloEphemeris() definition changes to follow corresponding system 143 | - Add almanac subframe/string generation for D1/D2, LNAC and GNAV data stream 144 | 145 | - **1/6/2024** 146 | - Add GPS L1C CNAV2 navigation stream generation class 147 | - Fix bugs in BDS D1/D2 navigation stream generation 148 | - Add L1C/L5/E6 support into CSatelliteSignal class 149 | - Observation support multi-frequency in structure and RINEX output 150 | 151 | ### 2023 152 | 153 | - **11/27/2023** 154 | - Change BCNavBit to virtual class and derive three classes for B-CNAV1/2/3 data stream 155 | - Combine iode2/iode3 to iode in ephemeris structure 156 | - Add B-CNAV2 and B-CNAV3 support in CSatelliteSignal 157 | - Modify GetTravelTime() and GetCarrierPhase() to use correct group delay 158 | 159 | - **11/13/2023** 160 | - Add support to RINEX 4 format navigation file 161 | - Modify Rinex.cpp to support RINEX 4 format data set 162 | - Expand and modify GPS_EPHEMERIS structure to support ephemeris from different navigation data format 163 | - Calculate clock/delay for different frequency with corresponding parameters 164 | 165 | - **10/28/2023** 166 | - Replace UnscaleDouble and roundi/roundu with UnscaleInt/UnscaleUint 167 | - Add UnscaleLong/UnscaleULong to better support data fields longer than 32bit (C-NAV and BC-NAV) 168 | 169 | - **9/19/2023** 170 | - Add complex_number class 171 | - Add E5 support 172 | - Add dummy F/NAV data stream generation 173 | - Satellite signal generation allows NULL pointer for data bit to generate all 0 modulation data 174 | 175 | - **8/30/2023** 176 | - Add GLONASS satellite parameter and raw measurement calculation 177 | - Add GLONASS slot/freq output to RINEX file 178 | - Add GLONASS GNAV data stream composition 179 | - Leap second correction in CSatelliteSignal 180 | - Update the PDF file for design description 181 | 182 | - **8/24/2023** 183 | - Add Galileo I/NAV data stream generation class 184 | - Add inter-signal correction (delay between different frequencies) support in XML format 185 | 186 | - **8/15/2023** 187 | - Add pilot bit generation function 188 | - Remove pilot bit generation in NavBit and CSatelliteSignal class 189 | - GetFrameData() method in NavBit (and derived classes) no longer supports pilot bit generation 190 | 191 | - **8/9/2023** 192 | - Add a new class CSatelliteSignal to get data/pilot modulation 193 | - Add a new NavBit derived class D1D2NavBit to generate BDS2 data stream 194 | - Call to GetFrameData() in NavBit class will be obsolete in the future 195 | 196 | - **7/28/2023** 197 | - Modifications to comply with stricter syntax checking 198 | - Add SignalSim.h to include all necessary header files for package users 199 | 200 | - **1/23/2023** 201 | - Add some variables and functions for future multi-frequency support 202 | - Minor bug fix on satellite acc calculation for GEO satellite 203 | 204 | ### 2022 205 | 206 | - **2/12/2022** 207 | - Bug fix on B-CNAV1 stream generation 208 | - Option to use Vel/Acc to calculate satellite position 209 | 210 | - **1/5/2022** 211 | - Add support for B-CNAV2 data stream generation 212 | 213 | ### 2021 214 | 215 | - **12/14/2021** 216 | - Fix bug of CN0 assign incorrect value during satellite add/remove 217 | - Add support for system select 218 | 219 | - **12/8/2021** 220 | - Add support for B1C and E1C 221 | 222 | - **11/25/2021** 223 | - Restore CN0 field in SATELLITE_PARAM structure as stored CN0 224 | 225 | - **9/30/2021** 226 | - Add satellite signal power control support in XML 227 | - Add RINEX output functions 228 | 229 | - **8/30/2021** 230 | - Fix bug of TOW add extra 1 when put into LNAV data stream 231 | - Fix bug of not put in week number in LNAV data stream 232 | - Use complete GNSS time to get LNAV data stream 233 | 234 | - **8/13/2021** 235 | - Change format of GNSS_TIME to improve accuracy 236 | - Add GetTransmitTime() method 237 | - Remove obsolete file 238 | 239 | - **8/4/2021** 240 | - Add class NavBit and LNavBit to generate GPS LNAV data stream 241 | 242 | - **7/5/2021** 243 | - Add XML format trajectory output 244 | - Add support to load BDS ionosphere parameter in RINEX header 245 | - Add support to load GPS/BDS/Galileo UTC parameters in RINEX header 246 | - Add support to load BDS/Galileo ephemeris in RINEX file 247 | - Optimize XML file content interpreter 248 | 249 | - **7/1/2021** 250 | - An optimized initial version re-published on github 251 | 252 | --- 253 | -------------------------------------------------------------------------------- /SignalSim Design Description.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/globsky/SignalSim/3f82005b3b69a3c22218bda4fb133b34a79098a0/SignalSim Design Description.pdf -------------------------------------------------------------------------------- /SignalSim JSON format specification.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/globsky/SignalSim/3f82005b3b69a3c22218bda4fb133b34a79098a0/SignalSim JSON format specification.pdf -------------------------------------------------------------------------------- /SignalSim输入信息JSON规范文档.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/globsky/SignalSim/3f82005b3b69a3c22218bda4fb133b34a79098a0/SignalSim输入信息JSON规范文档.pdf -------------------------------------------------------------------------------- /SignalSim输入信息XML规范文档.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/globsky/SignalSim/3f82005b3b69a3c22218bda4fb133b34a79098a0/SignalSim输入信息XML规范文档.pdf -------------------------------------------------------------------------------- /XmlObsGen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMakeList.txt : CMake project for XmlObsGen.cmake, include source and define 2 | # project specific logic here. 3 | # 4 | cmake_minimum_required (VERSION 3.8) 5 | 6 | # Enable Hot Reload for MSVC compilers if supported. 7 | if (POLICY CMP0141) 8 | cmake_policy(SET CMP0141 NEW) 9 | set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$,$>,$<$:EditAndContinue>,$<$:ProgramDatabase>>") 10 | endif() 11 | 12 | project ("XmlObsGen.cmake") 13 | 14 | include_directories(../inc) 15 | 16 | # Add source to this project's executable. 17 | add_executable (XmlObsGen.cmake 18 | "ObsGen.cpp" 19 | "../src/Almanac.cpp" 20 | "../src/Coordinate.cpp" 21 | "../src/GnssTime.cpp" 22 | "../src/NavData.cpp" 23 | "../src/PowerControl.cpp" 24 | "../src/Rinex.cpp" 25 | "../src/SatelliteParam.cpp" 26 | "../src/Trajectory.cpp" 27 | "../src/XmlArguments.cpp" 28 | "../src/XmlElement.cpp" 29 | "../src/XmlInterpreter.cpp" 30 | ) 31 | 32 | if (CMAKE_VERSION VERSION_GREATER 3.12) 33 | set_property(TARGET XmlObsGen.cmake PROPERTY CXX_STANDARD 20) 34 | endif() 35 | 36 | # TODO: Add tests and install targets if needed. 37 | -------------------------------------------------------------------------------- /XmlObsGen/test_obs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | -121.915773 15 | 37.352721 16 | 20 17 | 18 | 19 | 5 20 | 318.91 21 | 22 | 23 | 24 | 5 25 | 26 | 27 | 3 28 | 3 29 | 30 | 31 | 20 32 | 3 33 | 34 | 35 | 6 36 | 0 37 | 38 | 39 | 20 40 | 2 41 | 42 | 43 | 100 44 | 45 | 46 | 0 47 | 1 48 | 49 | 50 | 30 51 | 52 | 53 | 2 54 | 225 55 | 56 | 57 | 200 58 | 59 | 60 | 120 61 | -45 62 | 63 | 64 | 0 65 | 0.1 66 | 67 | 68 | 120 69 | 70 | 71 | 4676.66 72 | -180 73 | 74 | 75 | 10 76 | 77 | 78 | -20 79 | -1 80 | 81 | 82 | 19.384785 83 | 84 | 85 | 0 86 | 0.10811 87 | 88 | 89 | 0 90 | 1 91 | 92 | 93 | 2 94 | 95 | 96 | -6 97 | 3 98 | 99 | 100 | 10 101 | -6 102 | 103 | 104 | 5 105 | 106 | 107 | 108 | EphData/JPLM00USA_R_20200950000_01D_GN.rnx 109 | 110 | 1 111 | test.o 112 | 113 | 10 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /XmlObsGen/test_obs2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | -121.915773 15 | 37.352721 16 | 20 17 | 18 | 19 | 5 20 | 318.91 21 | 22 | 23 | 24 | 5 25 | 26 | 27 | 3 28 | 3 29 | 30 | 31 | 20 32 | 3 33 | 34 | 35 | 6 36 | 0 37 | 38 | 39 | 20 40 | 2 41 | 42 | 43 | 100 44 | 45 | 46 | 0 47 | 1 48 | 49 | 50 | 30 51 | 52 | 53 | 2 54 | 225 55 | 56 | 57 | 200 58 | 59 | 60 | 120 61 | -45 62 | 63 | 64 | 0 65 | 0.1 66 | 67 | 68 | 120 69 | 70 | 71 | 4676.66 72 | -180 73 | 74 | 75 | 10 76 | 77 | 78 | -20 79 | -1 80 | 81 | 82 | 19.384785 83 | 84 | 85 | 0 86 | 0.10811 87 | 88 | 89 | 0 90 | 1 91 | 92 | 93 | 2 94 | 95 | 96 | -6 97 | 3 98 | 99 | 100 | 10 101 | -6 102 | 103 | 104 | 5 105 | 106 | 107 | 108 | ../EphData/BRDC00IGS_R_20211700000_01D_MN.rnx 109 | 110 | 1 111 | test2.o 112 | 113 | 3 114 | 115 | true 116 | false 117 | true 118 | false 119 | true 120 | false 121 | 122 | 123 | 124 | -172 125 | 47 126 | false 127 | 128 | 129 | 130 | -125 131 | 132 | 133 | 134 | 45 135 | 136 | 40 137 | 138 | 35 139 | 140 | 30 141 | 142 | 28 143 | 144 | 26 145 | 146 | 24 147 | 148 | 22 149 | 150 | 20 151 | 152 | default 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /XmlObsGen/test_pos.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | -121.915773 15 | 37.352721 16 | 20 17 | 18 | 19 | 5 20 | 318.91 21 | 22 | 23 | 24 | 5 25 | 26 | 27 | 3 28 | 3 29 | 30 | 31 | 20 32 | 3 33 | 34 | 35 | 6 36 | 0 37 | 38 | 39 | 20 40 | 2 41 | 42 | 43 | 100 44 | 45 | 46 | 0 47 | 1 48 | 49 | 50 | 30 51 | 52 | 53 | 2 54 | 225 55 | 56 | 57 | 200 58 | 59 | 60 | 120 61 | -45 62 | 63 | 64 | 0 65 | 0.1 66 | 67 | 68 | 120 69 | 70 | 71 | 4676.66 72 | -180 73 | 74 | 75 | 10 76 | 77 | 78 | -20 79 | -1 80 | 81 | 82 | 19.384785 83 | 84 | 85 | 0 86 | 0.10811 87 | 88 | 89 | 0 90 | 1 91 | 92 | 93 | 2 94 | 95 | 96 | -6 97 | 3 98 | 99 | 100 | 10 101 | -6 102 | 103 | 104 | 5 105 | 106 | 107 | 108 | EphData/ABPO00MDG_R_20200950000_01D_GN.rnx 109 | EphData/BOR100POL_R_20200950000_01D_GN.rnx 110 | EphData/JFNG00CHN_R_20200950000_01D_GN.rnx 111 | EphData/JPLM00USA_R_20200950000_01D_GN.rnx 112 | EphData/MGUE00ARG_R_20200950000_01D_GN.rnx 113 | EphData/OWMG00NZL_R_20200950000_01D_GN.rnx 114 | 115 | 0.5 116 | reference2.pos 117 | 118 | 3 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /inc/Almanac.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // Almanac.h: 3 | // Declaration of almanac file read/write/convert functions 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __ALMANAC_H__ 10 | #define __ALMANAC_H__ 11 | 12 | #include 13 | #include "BasicTypes.h" 14 | 15 | enum AlmanacType { AlmanacUnknown = 0, AlmanacGps, AlmanacBds, AlmanacGalileo, AlmanacGlonass }; 16 | 17 | AlmanacType CheckAlmnanacType(FILE *fp); 18 | int ReadAlmanacGps(FILE *fp, GPS_ALMANAC Almanac[]); 19 | int ReadAlmanacBds(FILE *fp, GPS_ALMANAC Almanac[]); 20 | int ReadAlmanacGalileo(FILE *fp, GPS_ALMANAC Almanac[]); 21 | int ReadAlmanacGlonass(FILE *fp, GLONASS_ALMANAC Almanac[]); 22 | GPS_ALMANAC GetAlmanacFromEphemeris(PGPS_EPHEMERIS Eph, int week, int toa); 23 | GLONASS_ALMANAC GetAlmanacFromEphemeris(PGLONASS_EPHEMERIS Eph, int day, int leap_year); 24 | 25 | #endif // __RINEX_H__ 26 | -------------------------------------------------------------------------------- /inc/BCNav1Bit.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // BCNav1Bit.h: 3 | // Declaration of navigation bit synthesis class for B-CNAV1 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __BCNAV1_BIT_H__ 10 | #define __BCNAV1_BIT_H__ 11 | 12 | #include "BCNavBit.h" 13 | 14 | #define B1C_SUBFRAME2_SYMBOL_LENGTH 100 15 | #define B1C_SUBFRAME3_SYMBOL_LENGTH 44 16 | 17 | class BCNav1Bit : public BCNavBit 18 | { 19 | public: 20 | BCNav1Bit(); 21 | ~BCNav1Bit(); 22 | 23 | int GetFrameData(GNSS_TIME StartTime, int svid, int Param, int *NavBits); 24 | 25 | private: 26 | unsigned int BdsSubframe3[63][11]; // 63 SVs, 264bits in subframe 3, 24bits (4 symbols) in bit23~0 of each DWORD MSB first, lowest address first 27 | 28 | static const unsigned int BCH_prn_table[64]; // BCH encode table for SVID 29 | static const unsigned long long BCH_soh_table[256]; // BCH encode table for SOH 30 | static const char B1CMatrixGen2[B1C_SUBFRAME2_SYMBOL_LENGTH*B1C_SUBFRAME2_SYMBOL_LENGTH+1]; 31 | static const char B1CMatrixGen3[B1C_SUBFRAME3_SYMBOL_LENGTH*B1C_SUBFRAME3_SYMBOL_LENGTH+1]; 32 | 33 | void ComposeSubframe2(int week, int how, int svid, unsigned int Frame2Data[25]); 34 | }; 35 | 36 | #endif // __BCNAV1_BIT_H__ 37 | -------------------------------------------------------------------------------- /inc/BCNav2Bit.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // BCNav2Bit.h: 3 | // Declaration of navigation bit synthesis class for B-CNAV2 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __BCNAV2_BIT_H__ 10 | #define __BCNAV2_BIT_H__ 11 | 12 | #include "BCNavBit.h" 13 | 14 | #define B2a_SYMBOL_LENGTH 48 15 | 16 | class BCNav2Bit : public BCNavBit 17 | { 18 | public: 19 | BCNav2Bit(); 20 | ~BCNav2Bit(); 21 | 22 | int GetFrameData(GNSS_TIME StartTime, int svid, int Param, int *NavBits); 23 | 24 | private: 25 | static const char B2aMatrixGen[B2a_SYMBOL_LENGTH*B2a_SYMBOL_LENGTH+1]; 26 | static const int MessageOrder[20]; 27 | 28 | void ComposeMessage(int MessageType, int week, int sow, int svid, unsigned int FrameData[]); 29 | }; 30 | 31 | #endif // __BCNAV2_BIT_H__ 32 | -------------------------------------------------------------------------------- /inc/BCNav3Bit.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // BCNav3Bit.h: 3 | // Declaration of navigation bit synthesis class for B-CNAV3 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __BCNAV3_BIT_H__ 10 | #define __BCNAV3_BIT_H__ 11 | 12 | #include "BCNavBit.h" 13 | 14 | #define B2b_SYMBOL_LENGTH 81 15 | 16 | class BCNav3Bit : public BCNavBit 17 | { 18 | public: 19 | BCNav3Bit(); 20 | ~BCNav3Bit(); 21 | 22 | int GetFrameData(GNSS_TIME StartTime, int svid, int Param, int *NavBits); 23 | 24 | private: 25 | 26 | static const char B2bMatrixGen[B2b_SYMBOL_LENGTH*B2b_SYMBOL_LENGTH+1]; 27 | static const int MessageOrder[6]; 28 | 29 | void ComposeMessage(int MessageType, int week, int sow, int svid, unsigned int FrameData[]); 30 | }; 31 | 32 | #endif // __BCNAV3_BIT_H__ 33 | -------------------------------------------------------------------------------- /inc/BCNavBit.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // BCNavBit.h: 3 | // Declaration of navigation bit synthesis class for BDS3 navigation bit 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __BCNAV_BIT_H__ 10 | #define __BCNAV_BIT_H__ 11 | 12 | #include "NavBit.h" 13 | 14 | class BCNavBit : public NavBit 15 | { 16 | public: 17 | BCNavBit(); 18 | ~BCNavBit(); 19 | 20 | int SetEphemeris(int svid, PGPS_EPHEMERIS Eph); 21 | int SetAlmanac(GPS_ALMANAC Alm[]); 22 | int SetIonoUtc(PIONO_PARAM IonoParam, PUTC_PARAM UtcParam) { return 0; }; 23 | 24 | int AppendWord(unsigned int *Dest, int StartBit, unsigned int *Src, int Length); 25 | int AssignBits(unsigned int Data, int BitNumber, int BitStream[]); 26 | int AppendCRC(unsigned int DataStream[], int Length); 27 | int LDPCEncode(int SymbolStream[], int SymbolLength, const char *MatrixGen); 28 | int GF6IntMul(int a, int b); 29 | 30 | unsigned int Ephemeris1[63][9]; // IODE + ephemeris I (211 bits) 31 | unsigned int Ephemeris2[63][10]; // ephemeris II (222 bits) 32 | unsigned int ClockParam[63][4]; // clock + IODC 33 | unsigned int IntegrityFlags[63]; // SISMAI + B1C/B2a/B2b DIF/SIF/AIF (13 bits) 34 | unsigned int TgsIscParam[63][3]; // TGD+ISC for B1C/B2a/B2b 35 | unsigned int ReducedAlmanac[63][2]; // reduced almanac (38 bits) 36 | unsigned int MidiAlmanac[63][7]; // midi almanac (156 bits) 37 | unsigned int BdGimIono[4]; // BDGIM ionosphere parameters (74 bits) 38 | unsigned int BdtUtcParam[5]; // BDT-UTC parameters (97 bits) 39 | unsigned int EopParam[6]; // EOP parameters (138 bits) 40 | unsigned int BgtoParam[7][3]; // BGTO parameters (68 bits) 41 | 42 | private: 43 | static const unsigned int crc24q[256]; // CRC24Q table 44 | static const unsigned int e2v_table[128]; 45 | static const unsigned int v2e_table[64]; 46 | 47 | int FillBdsAlmanacPage(PGPS_ALMANAC Almanac, unsigned int MidiAlm[8], unsigned int ReducedAlm[2]); 48 | }; 49 | 50 | #endif // __BCNAV_BIT_H__ 51 | -------------------------------------------------------------------------------- /inc/CNav2Bit.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // CNav2Bit.h: 3 | // Declaration of navigation bit synthesis class for CNAV2 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __CNAV2_BIT_H__ 10 | #define __CNAV2_BIT_H__ 11 | 12 | #include "NavBit.h" 13 | 14 | #define L1C_SUBFRAME2_SYMBOL_LENGTH 600 15 | #define L1C_SUBFRAME3_SYMBOL_LENGTH 274 16 | 17 | class CNav2Bit : public NavBit 18 | { 19 | public: 20 | CNav2Bit(); 21 | ~CNav2Bit(); 22 | 23 | int GetFrameData(GNSS_TIME StartTime, int svid, int Param, int *NavBits); 24 | int SetEphemeris(int svid, PGPS_EPHEMERIS Eph); 25 | int SetAlmanac(GPS_ALMANAC Alm[]) { return 0; }; 26 | int SetIonoUtc(PIONO_PARAM IonoParam, PUTC_PARAM UtcParam) { return 0; }; 27 | 28 | private: 29 | unsigned int Subframe2[32][18]; // 32 SVs, 576bits in subframe 2, 32bits in each DWORD MSB first, lowest address first 30 | unsigned int Subframe3[50][9]; // reserve 50 subframe3 contents, 32bits in each DWORD MSB first, lowest address first 31 | 32 | static const unsigned long long BCH_toi_table[256]; // BCH encode table for TOI 33 | static const unsigned int L1CMatrixGen2[L1C_SUBFRAME2_SYMBOL_LENGTH*19]; 34 | static const unsigned int L1CMatrixGen3[L1C_SUBFRAME3_SYMBOL_LENGTH*9]; 35 | 36 | void ComposeSubframe2(PGPS_EPHEMERIS Eph, unsigned int Subframe2[18]); 37 | void LDPCEncode(unsigned int Stream[], int bits[], int SymbolLength, int TableSize, const unsigned int MatrixGen[]); 38 | int XorBits(unsigned int Data); 39 | }; 40 | 41 | #endif // __CNAV2_BIT_H__ 42 | -------------------------------------------------------------------------------- /inc/CNavBit.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // CNavBit.h: 3 | // Declaration of navigation bit synthesis class for CNAV 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __CNAV_BIT_H__ 10 | #define __CNAV_BIT_H__ 11 | 12 | #include "NavBit.h" 13 | 14 | class CNavBit : public NavBit 15 | { 16 | public: 17 | CNavBit(); 18 | ~CNavBit(); 19 | 20 | int GetFrameData(GNSS_TIME StartTime, int svid, int Param, int *NavBits); 21 | int SetEphemeris(int svid, PGPS_EPHEMERIS Eph); 22 | int SetAlmanac(GPS_ALMANAC Alm[]); 23 | int SetIonoUtc(PIONO_PARAM IonoParam, PUTC_PARAM UtcParam); 24 | 25 | private: 26 | // Arrays allocate bits align with the method of putting 276bits (without CRC) of a message into 9 DWORD according to following table 27 | // WORD sequence: DWORD0 DWORD1 DWORD2 DWORD3 DWORD4 DWORD5 DWORD6 DWORD7 DWORD8 28 | // bit order: 1-20 21-52 53-84 85-116 117-148 149-180 181-212 213-244 245-276 29 | unsigned int EphMessage[32][2][9]; // 32 SVs, Message 10/11 each has 276bits from bit19 DWORD0 to bit0 DWORD8 30 | unsigned int MidiAlm[32][4]; // 32 SVs, Message 37, 128bits from bit0 DWORD5 to bit0 DWORD8 31 | unsigned int ReducedAlm[32], TOA; // 32 SVs, 31bit each, TOA combines WNa (13bit) and toa (8bit) in DWORD4 21LSB 32 | unsigned int ClockMessage[32][4]; // 32 SVs, Clock fields (top through af2) 89bits from bit13 DWORD1 to bit21 DWORD4 33 | unsigned int DelayMessage[32][3]; // 32 SVs, Group delay fields 65bits from bit20 DWORD4 to bit20 DWORD6 34 | unsigned int IonoMessage[3]; // 84bits from bit19 DWORD6 to bit0 DWORD8 (include last 12 reserved bits) 35 | unsigned int UTCMessage[4]; // 98bits from bit20 DWORD4 to bit19 DWORD7 36 | 37 | // save convolutional encode state 38 | unsigned char ConvEncodeBitsL2[32]; 39 | unsigned char ConvEncodeBitsL5[32]; 40 | 41 | int ComposeEphWords(PGPS_EPHEMERIS Ephemeris, unsigned int EphData[2][9], unsigned int ClockData[4], unsigned int DelayData[3]); 42 | int ComposeAlmWords(GPS_ALMANAC Almanac[], unsigned int &ReducedAlmData, unsigned int MidiAlmData[6]); 43 | void GetMessageData(int svid, int message, int TOW, unsigned int Data[9]); 44 | unsigned char ConvolutionEncodePair(unsigned char &ConvEncodeBits, unsigned int &EncodeWord); 45 | }; 46 | 47 | #endif // __CNAV_BIT_H__ 48 | -------------------------------------------------------------------------------- /inc/ComplexNumber.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // ComplexNumber.h: 3 | // Definition of complex number and operators 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #if !defined (__COMPLEX_NUMBER_H__) 10 | #define __COMPLEX_NUMBER_H__ 11 | 12 | class complex_number 13 | { 14 | public: 15 | double real; 16 | double imag; 17 | 18 | complex_number() { real = imag = 0.; }; 19 | complex_number(double real_part, double imag_part); 20 | complex_number operator + (const complex_number data) const; 21 | void operator += (const complex_number data); 22 | complex_number operator - (const complex_number data) const; 23 | void operator -= (const complex_number data); 24 | complex_number operator * (const complex_number data) const; 25 | void operator *= (const complex_number data); 26 | complex_number operator * (const double data); 27 | void operator *= (const double data); 28 | double abs(); 29 | complex_number conj(); 30 | }; 31 | 32 | #endif //!defined(__COMPLEX_NUMBER_H__) 33 | -------------------------------------------------------------------------------- /inc/ConstVal.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // ConstVal.h: 3 | // Definition of constant values 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #if !defined(__CONST_VALUES_H__) 10 | #define __CONST_VALUES_H__ 11 | 12 | // constant value for generally use 13 | #define LIGHT_SPEED 299792458. 14 | #define PI 3.14159265358979323846264338328 15 | #define PI2 (2 * PI) 16 | #define RAD2DEG(r) (r * (180. / PI)) 17 | #define DEG2RAD(d) (d * (PI / 180.)) 18 | 19 | // constant values of WGS84 20 | #define WGS_PI 3.1415926535898 // WGS 84 value of pi 21 | #define WGS_AXIS_A 6378137.0 // A - WGS-84 earth's semi major axis 22 | #define WGS_AXIS_B 6356752.3142451795 // B - WGS-84 earth's semi minor axis 23 | #define WGS_E1_SQR 0.006694379990141317 // 1-(B/A)^2, 1st numerical eccentricity 24 | #define WGS_E2_SQR 0.006739496742276435 // (A/B)^2-1, 2nd numerical eccentricity 25 | #define WGS_SQRT_GM 19964981.8432173887 // square root of GM 26 | #define WGS_OMEGDOTE 7.2921151467e-5 // earth rotate rate 27 | #define WGS_F_GTR -4.442807633e-10 // factor of general theory of relativity 28 | 29 | // constant values of CGS2000 30 | #define CGCS2000_SQRT_GM 19964980.3856652962 // square root of GM 31 | #define CGCS2000_OMEGDOTE 7.292115e-5 // earth rotate rate 32 | 33 | // constant values of PZ90 34 | #define PZ90_AE 6378136.0 // PZ90 Ae 35 | #define PZ90_AE2 (PZ90_AE * PZ90_AE) // square of PZ90 Ae 36 | #define PZ90_GM 3.9860044e+14 // PZ90 gravitational constant 37 | #define PZ90_C20 1082.63e-6 // Second zonal coefficient of spherical harmonic expansion 38 | #define PZ90_C20AE2 (PZ90_C20 * PZ90_AE2) // product of PZ90_C20 and PZ90_AE2 39 | #define PZ90_OMEGDOTE 7.292115e-5 // earth rotate rate 40 | 41 | // constant values of signal frequency 42 | #define FREQ_GPS_L1 1575420000 43 | #define FREQ_GPS_L2 1227600000 44 | #define FREQ_GPS_L5 1176450000 45 | #define FREQ_BDS_B1C 1575420000 46 | #define FREQ_BDS_B1I 1561098000 47 | #define FREQ_BDS_B2I 1207140000 48 | #define FREQ_BDS_B3I 1268520000 49 | #define FREQ_BDS_B2a 1176450000 50 | #define FREQ_BDS_B2b 1207140000 51 | #define FREQ_BDS_B2ab 1191795000 52 | #define FREQ_GAL_E1 1575420000 53 | #define FREQ_GAL_E5a 1176450000 54 | #define FREQ_GAL_E5b 1207140000 55 | #define FREQ_GAL_E5 1191795000 56 | #define FREQ_GAL_E6 1278750000 57 | #define FREQ_GLO_G1 1602000000 58 | #define FREQ_GLO_G2 1246000000 59 | #define FREQ_GLO_G3 1202025000 60 | 61 | #endif //!defined(__CONST_VALUES_H__) 62 | -------------------------------------------------------------------------------- /inc/Coordinate.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // Coordinate.h: 3 | // Coordinate related functions (Ephemeris to position, Geometry distance etc.) 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #if !defined (__COORDINATE_H__) 10 | #define __COORDINATE_H__ 11 | 12 | #include "BasicTypes.h" 13 | 14 | double GpsClockCorrection(PGPS_EPHEMERIS Eph, double TransmitTime); 15 | double GlonassClockCorrection(PGLONASS_EPHEMERIS Eph, double TransmitTime); 16 | bool GpsSatPosSpeedEph(GnssSystem system, double TransmitTime, PGPS_EPHEMERIS pEph, PKINEMATIC_INFO pPosVel, double Acc[3]); 17 | bool GlonassSatPosSpeedEph(double TransmitTime, PGLONASS_EPHEMERIS pEph, PKINEMATIC_INFO pPosVel, double Acc[3]); 18 | LLA_POSITION EcefToLla(KINEMATIC_INFO ecef_pos); 19 | KINEMATIC_INFO LlaToEcef(LLA_POSITION lla_pos); 20 | CONVERT_MATRIX CalcConvMatrix(KINEMATIC_INFO Position); 21 | CONVERT_MATRIX CalcConvMatrix(LLA_POSITION Position); 22 | void SpeedEnuToCourse(LOCAL_SPEED &Speed); 23 | void SpeedCourseToEnu(LOCAL_SPEED &Speed); 24 | void SpeedEcefToLocal(CONVERT_MATRIX ConvertMatrix, KINEMATIC_INFO PosVel, LOCAL_SPEED &Speed); 25 | void SpeedLocalToEcef(CONVERT_MATRIX ConvertMatrix, LOCAL_SPEED Speed, KINEMATIC_INFO &PosVel); 26 | void SpeedLocalToEcef(LLA_POSITION lla_pos, LOCAL_SPEED Speed, KINEMATIC_INFO &PosVel); 27 | void SatElAz(PLLA_POSITION PositionLla, double LosVector[3], double *Elevation, double *Azimuth); 28 | void SatElAz(PKINEMATIC_INFO Receiver, PKINEMATIC_INFO Satellite, double *Elevation, double *Azimuth); 29 | double GeometryDistance(const double *UserPos, const double *SatPos, double LosVector[3]); 30 | double GeometryDistance(const PKINEMATIC_INFO UserPosVel, const PKINEMATIC_INFO SatPosVel, double LosVector[3]); 31 | double SatRelativeSpeed(PKINEMATIC_INFO Receiver, PKINEMATIC_INFO Satellite); 32 | double GpsIonoDelay(PIONO_PARAM IonoParam, double time, double Lat, double Lon, double Elevation, double Azimuth); 33 | double TropoDelay(double Lat, double Altitude, double Elevation); 34 | 35 | #endif //!defined(__COORDINATE_H__) 36 | -------------------------------------------------------------------------------- /inc/D1D2NavBit.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // D1D2NavBit.h: 3 | // Declaration of navigation bit synthesis class for BDS2 D1/D2 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __D1D2NAV_BIT_H__ 10 | #define __D1D2NAV_BIT_H__ 11 | 12 | #include "NavBit.h" 13 | 14 | class D1D2NavBit : public NavBit 15 | { 16 | public: 17 | D1D2NavBit(); 18 | ~D1D2NavBit(); 19 | 20 | int GetFrameData(GNSS_TIME StartTime, int svid, int Param, int *NavBits); 21 | int SetEphemeris(int svid, PGPS_EPHEMERIS Eph); 22 | int SetAlmanac(GPS_ALMANAC Alm[]); 23 | int SetIonoUtc(PIONO_PARAM IonoParam, PUTC_PARAM UtcParam); 24 | 25 | private: 26 | unsigned int BdsStream123[53][3*9]; // 53 MEO/IGSO SVs, WORD 2-10 in each 3 subframes 27 | unsigned int BdsStreamAlm[63][9]; // WORD 3-10 of Almanac 28 | unsigned int BdsStreamInfo[4][9]; // page 7~10 of subframe 5 29 | unsigned int BdsStreamHealth[3][9]; // page 24 of subframe 5 (AmID = 01~11) 30 | unsigned int BdsStreamD2[10][10*4]; // 10 GEO SVs, WORD 2-5 in each 10 subframes 31 | IONO_PARAM IonoParamSave; // Ionosphere parameters saved to put into subframe 1 32 | static const unsigned int BCHPoly[4]; 33 | 34 | int ComposeBdsStream123(PGPS_EPHEMERIS Ephemeris, PIONO_PARAM IonoParam, unsigned int Stream[3*9]); 35 | int ComposeBdsStreamD2(PGPS_EPHEMERIS Ephemeris, PIONO_PARAM IonoParam, unsigned int Stream[10*4]); 36 | int FillBdsAlmanacPage(PGPS_ALMANAC Almanac, unsigned int Stream[9]); 37 | int FillBdsHealthPage(PGPS_ALMANAC Almanac, int Length, unsigned int Stream[9]); 38 | unsigned int GetBCH(unsigned int word); 39 | unsigned int Interleave(unsigned int data); 40 | }; 41 | 42 | #endif // __D1D2NAV_BIT_H__ 43 | -------------------------------------------------------------------------------- /inc/FNavBit.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // FNavBit.h: 3 | // Declaration of navigation bit synthesis class for F/NAV 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __FNAV_BIT_H__ 10 | #define __FNAV_BIT_H__ 11 | 12 | #include "NavBit.h" 13 | 14 | class FNavBit : public NavBit 15 | { 16 | public: 17 | FNavBit(); 18 | ~FNavBit(); 19 | 20 | int GetFrameData(GNSS_TIME StartTime, int svid, int Param, int *NavBits); 21 | int SetEphemeris(int svid, PGPS_EPHEMERIS Eph); 22 | int SetAlmanac(GPS_ALMANAC Alm[]); 23 | int SetIonoUtc(PIONO_PARAM IonoParam, PUTC_PARAM UtcParam); 24 | 25 | private: 26 | unsigned int GalEphData[36][4][7]; // 36 SVs, PageType 1~4, each page has 214bits before CRC, leaving 10MSB of first DWORD as 0s 27 | unsigned int GalAlmData[12][2][7]; // 36 SVs, PageType 5~6, each page has 214bits before CRC, leaving 10MSB of first DWORD as 0s 28 | unsigned int GalUtcData[4]; // GST-UTC part in PageType 4, from bit5 index0 to bit3 index3 totally 99 bits 29 | unsigned int GalIonoData[2]; // Iono correction part in PageType 1, from bit15 index0 to bit7 index1 totally 41 bits 30 | 31 | static const int SyncPattern[12]; 32 | 33 | int ComposeEphWords(PGPS_EPHEMERIS Ephemeris, unsigned int EphData[4][7]); 34 | int ComposeAlmWords(GPS_ALMANAC Almanac[], unsigned int AlmData[2][7], int week); 35 | void GetPageData(int svid, int page, int subframe, unsigned int GST, unsigned int Data[7]); 36 | unsigned char GalConvolutionEncode(unsigned char &ConvEncodeBits, unsigned int &EncodeWord); 37 | }; 38 | 39 | #endif // __FNAV_BIT_H__ 40 | -------------------------------------------------------------------------------- /inc/GNavBit.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // GNavBit.h: 3 | // Declaration of navigation bit synthesis class for GNAV 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __GNAV_BIT_H__ 10 | #define __GNAV_BIT_H__ 11 | 12 | #include "NavBit.h" 13 | 14 | class GNavBit : public NavBit 15 | { 16 | public: 17 | GNavBit(); 18 | ~GNavBit(); 19 | 20 | int GetFrameData(GNSS_TIME StartTime, int svid, int Param, int *NavBits); 21 | int SetEphemeris(int svid, PGPS_EPHEMERIS Eph); 22 | int SetAlmanac(GPS_ALMANAC Alm[]); 23 | int SetIonoUtc(PIONO_PARAM IonoParam, PUTC_PARAM UtcParam); 24 | 25 | private: 26 | // string contents: 3DOWRD to hold 85bits with index 0 bit20 as first bit to index 2 bit0 as last bit 27 | // index bit20 always 0, index 2 bit 7~0 left as 0s to fill page number and check sum 28 | unsigned int StringEph[24][4][3]; // 24 SVs, String 1~4 and 85bits for each string 29 | unsigned int StringAlm[5][11][3]; // 5 frames, string 5~15 and 85bits for each string 30 | static const unsigned int CheckSumTable[8][3]; 31 | 32 | int ComposeStringEph(PGLONASS_EPHEMERIS Ephemeris, unsigned int String[][3]); 33 | int ComposeStringAlm(PGLONASS_ALMANAC Almanac, int slot, unsigned int StringEven[3], unsigned int StringOdd[3]); 34 | unsigned int CheckSum(unsigned int Data[3]); 35 | }; 36 | 37 | #endif // __GNAV_BIT_H__ 38 | -------------------------------------------------------------------------------- /inc/GnssTime.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // GnssTime.h: 3 | // Definition of functions to do convertion between GNSS time 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #if !defined (__GNSS_TIME_H__) 10 | #define __GNSS_TIME_H__ 11 | 12 | #include "BasicTypes.h" 13 | 14 | BOOL GetLeapSecond(unsigned int Seconds, int &LeapSecond); 15 | UTC_TIME GpsTimeToUtc(GNSS_TIME GnssTime, BOOL UseLeapSecond = TRUE); 16 | UTC_TIME GlonassTimeToUtc(GLONASS_TIME GlonassTime); 17 | UTC_TIME BdsTimeToUtc(GNSS_TIME GnssTime); 18 | UTC_TIME GalileoTimeToUtc(GNSS_TIME GnssTime); 19 | GNSS_TIME UtcToGpsTime(UTC_TIME UtcTime, BOOL UseLeapSecond = TRUE); 20 | GLONASS_TIME UtcToGlonassTime(UTC_TIME UtcTime); 21 | GNSS_TIME UtcToBdsTime(UTC_TIME UtcTime); 22 | GNSS_TIME UtcToGalileoTime(UTC_TIME UtcTime); 23 | 24 | #endif //!defined(__GNSS_TIME_H__) 25 | -------------------------------------------------------------------------------- /inc/INavBit.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // INavBit.h: 3 | // Declaration of navigation bit synthesis class for I/NAV 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __INAV_BIT_H__ 10 | #define __INAV_BIT_H__ 11 | 12 | #include "NavBit.h" 13 | 14 | class INavBit : public NavBit 15 | { 16 | public: 17 | INavBit(); 18 | ~INavBit(); 19 | 20 | int GetFrameData(GNSS_TIME StartTime, int svid, int Param, int *NavBits); 21 | int SetEphemeris(int svid, PGPS_EPHEMERIS Eph); 22 | int SetAlmanac(GPS_ALMANAC Alm[]); 23 | int SetIonoUtc(PIONO_PARAM IonoParam, PUTC_PARAM UtcParam); 24 | 25 | private: 26 | /* unsigned int GpsStream123[32][3*8]; // 32 SVs, WORD 3-10 in each 3 subframes 27 | unsigned int GpsStream45[2][25][8]; // WORD 3-10 in 25 pages of 2 subframes 28 | static const unsigned char ParityTable[6][16]; 29 | static const unsigned int ParityAdjust[4]; 30 | 31 | int ComposeGpsStream123(PGPS_EPHEMERIS Ephemeris, unsigned int Stream[3*8]); 32 | int FillGpsAlmanacPage(PGPS_ALMANAC Almanac, unsigned int Stream[8]);*/ 33 | unsigned int GalEphData[36][5*4]; // 36 SVs, Word1~5 as ephemeris, 4 DWORD each Word 34 | unsigned int GalAlmData[12][4*4]; // 36 SVs, Word7~10 as almanac, 4 DWORD each Word 35 | unsigned int GalRsVector[36][4*4]; // 36 Svs, Word17~20 as Reed-Solomon parity vector 36 | unsigned int GalUtcData[4]; // for Word6 37 | unsigned int GalSpareData[4]; // for Word0 38 | unsigned int GalDummyData[4]; // for Word63 39 | 40 | static const int WordAllocationE1[15]; 41 | static const int WordAllocationE5[15]; 42 | static const int SyncPattern[10]; 43 | static const unsigned char RsGenerateMatrix[60][58]; 44 | static const unsigned char Oct2Power[256]; // with first element never used 45 | static const unsigned char Power2Oct[510]; // two round of 255 element 46 | 47 | int ComposeEphWords(PGPS_EPHEMERIS Ephemeris, unsigned int *EphData); 48 | int ComposeAlmWords(GPS_ALMANAC Almanac[], unsigned int *AlmData, int week); 49 | unsigned int *GetWordData(int svid, int Word, int subframe); 50 | unsigned char GalConvolutionEncode(unsigned char &ConvEncodeBits, unsigned int &EncodeWord); 51 | unsigned char GF8IntMul(unsigned char a, unsigned char b); 52 | void GenerateParityVector(unsigned char InformationVector[58], unsigned char ParityVector[60]); 53 | void ComposeParityWords(unsigned int *EphData, unsigned int *ParityData); 54 | }; 55 | 56 | #endif // __INAV_BIT_H__ 57 | -------------------------------------------------------------------------------- /inc/JsonInterpreter.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // JsonInterpreter.h: 3 | // Declaration of functions to interprete JSON object tree 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __JSON_INTERPRETER_H__ 10 | #define __JSON_INTERPRETER_H__ 11 | 12 | #include 13 | 14 | #include "BasicTypes.h" 15 | #include "JsonParser.h" 16 | #include "GnssTime.h" 17 | #include "Trajectory.h" 18 | #include "NavData.h" 19 | #include "Coordinate.h" 20 | #include "PowerControl.h" 21 | #include "Tracking.h" 22 | 23 | BOOL AssignParameters(JsonObject *Object, PUTC_TIME UtcTime, PLLA_POSITION StartPos, PLOCAL_SPEED StartVel, CTrajectory *Trajectory, CNavData *NavData, POUTPUT_PARAM OutputParam, CPowerControl *PowerControl, PDELAY_CONFIG DelayConfig); 24 | 25 | #endif // __JSON_INTERPRETER_H__ 26 | -------------------------------------------------------------------------------- /inc/JsonParser.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // JsonParser.h: 3 | // JSON stream process class declaration 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #if !defined __JSON_PARSER_H__ 10 | #define __JSON_PARSER_H__ 11 | 12 | #include 13 | 14 | #define MAX_KEY_LENGTH (32-1) 15 | #define MAX_STRING_LENGTH (192-1) 16 | 17 | #define OBJ_ARRAY_INC_SIZE 128 18 | 19 | typedef union 20 | { 21 | double d_data; 22 | long long int l_data; 23 | } JSON_NUMBER_UNION; 24 | 25 | //---------------------------------------------------------------------- 26 | // JsonObject is basic unit holding a key/value combination or value only 27 | // Depending on the type of value, Type can be one of enum ValueType 28 | // The key string is stored in Key and is empty string for value only 29 | // For different value type the value is stored as following 30 | // ValueTypeObject: the value is a serial of JsonObject putting as 31 | // a link list starting at pObjectContent and concatenated with pNextObject 32 | // ValueTypeArray: the value is a serial of value only JsonObject putting as 33 | // a link list starting at pObjectContent and concatenated with pNextObject 34 | // ValueTypeString: the value is put in String 35 | // ValueTypeIntNumber: the long long int type value is put in Number.l_data 36 | // ValueTypeFloatNumber: the double type value is put in Number.d_data 37 | // ValueTypeTrue: the value is true 38 | // ValueTypeFalse: the value is false 39 | // ValueTypeNull: the value is null 40 | //---------------------------------------------------------------------- 41 | 42 | struct JsonObject 43 | { 44 | // define type of value 45 | enum ValueType { ValueTypeNull, ValueTypeObject, ValueTypeArray, ValueTypeString, ValueTypeIntNumber, ValueTypeFloatNumber, ValueTypeTrue, ValueTypeFalse }; 46 | 47 | char Key[MAX_KEY_LENGTH+1]; 48 | ValueType Type; 49 | JsonObject *pNextObject; // pointer to next key/value pair with same parent object or in same array 50 | JsonObject *pObjectContent; // pointer to content if value type is object or array 51 | JSON_NUMBER_UNION Number; 52 | char String[MAX_STRING_LENGTH+1]; 53 | }; 54 | 55 | class JsonStream; 56 | typedef int(JsonStream::*GetStream)(void *source); 57 | 58 | //---------------------------------------------------------------------- 59 | // JsonStream is a class to process JSON stream including read/write JSON file 60 | // or from other sources, traverse JSON stream as a tree etc. 61 | // After a complete JSON file/stream is loaded, the most top object is stored 62 | // as a value only JsonObject at RootObject 63 | // The instances of JsonObject withinthe tree will be allocated an increse automatically 64 | // To traverse an object, call CurObject = GetFirstObject(Object) to get the 65 | // first key/value combination and call CurObject = GetFirstObject(CurObject) 66 | // to get following key/value combinations until get NULL pointer 67 | //---------------------------------------------------------------------- 68 | class JsonStream 69 | { 70 | public: 71 | JsonStream(); 72 | ~JsonStream(); 73 | 74 | void DeleteTree(JsonObject *Object); 75 | int ReadFile(const char *File); 76 | int WriteFile(const char *File); 77 | JsonObject *ParseObject(int IsObject, GetStream GetStreamFunc, void *source); 78 | JsonObject *GetRootObject() { return RootObject; } 79 | static JsonObject *GetFirstObject(JsonObject *CurObject) { return CurObject->pObjectContent; } 80 | static JsonObject *GetNextObject(JsonObject *CurObject) { return CurObject->pNextObject; } 81 | 82 | private: 83 | JsonObject *RootObject; 84 | char stream[256]; // read file buffer 85 | const char *p; // pointer of current processing character in stream 86 | 87 | JsonObject *GetNewObject(); 88 | int GetFileStream(void *source); 89 | int CopyString(char *dest, int MaxLength); 90 | int IsWhiteSpace(const char ch); 91 | char EscapeCharacter(); 92 | int GetValueContent(JsonObject *Object); 93 | int GetNumber(JsonObject *Object); 94 | 95 | int OutputObject(FILE *fp, JsonObject *Object, int Depth, int HasKey); 96 | int OutputKeyValue(FILE *fp, JsonObject *Object, int Depth, int HasKey); 97 | int OutputString(FILE *fp, const char *str); 98 | 99 | }; 100 | 101 | 102 | #endif //__JSON_PARSER_H__ 103 | -------------------------------------------------------------------------------- /inc/LNavBit.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // LNavBit.h: 3 | // Declaration of navigation bit synthesis class for LNAV 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __LNAV_BIT_H__ 10 | #define __LNAV_BIT_H__ 11 | 12 | #include "NavBit.h" 13 | 14 | class LNavBit : public NavBit 15 | { 16 | public: 17 | LNavBit(); 18 | ~LNavBit(); 19 | 20 | int GetFrameData(GNSS_TIME StartTime, int svid, int Param, int *NavBits); 21 | int SetEphemeris(int svid, PGPS_EPHEMERIS Eph); 22 | int SetAlmanac(GPS_ALMANAC Alm[]); 23 | int SetIonoUtc(PIONO_PARAM IonoParam, PUTC_PARAM UtcParam); 24 | 25 | private: 26 | unsigned int GpsStream123[32][3*8]; // 32 SVs, WORD 3-10 in each 3 subframes 27 | unsigned int GpsStream45[2][25][8]; // WORD 3-10 in 25 pages of 2 subframes 28 | static const unsigned char ParityTable[6][16]; 29 | static const unsigned int ParityAdjust[4]; 30 | static const int PageId[2][25]; 31 | 32 | int ComposeGpsStream123(PGPS_EPHEMERIS Ephemeris, unsigned int Stream[3*8]); 33 | int FillGpsAlmanacPage(PGPS_ALMANAC Almanac, unsigned int Stream[8]); 34 | int FillGpsHealthPage(GPS_ALMANAC Almanac[], unsigned int Stream4[8], unsigned int Stream5[8]); 35 | unsigned int GpsGetParity(unsigned int word); 36 | }; 37 | 38 | #endif // __LNAV_BIT_H__ 39 | -------------------------------------------------------------------------------- /inc/NavBit.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // NavBit.h: 3 | // Declaration of navigation bit synthesis base class 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __NAV_BIT_H__ 10 | #define __NAV_BIT_H__ 11 | 12 | #include "BasicTypes.h" 13 | 14 | #define COMPOSE_BITS(data, start, width) (((data) & ((1UL << (width)) - 1)) << (start)) 15 | 16 | typedef union 17 | { 18 | double d_data; 19 | unsigned int i_data[2]; 20 | } DOUBLE_INT_UNION; 21 | 22 | class NavBit 23 | { 24 | public: 25 | enum NavParamType { ParamTypeSTO, ParamTypeEOP, ParamTypeIonKModel, ParamTypeIonGModel, ParamTypeIonBModel }; 26 | 27 | NavBit(); 28 | ~NavBit(); 29 | 30 | virtual int GetFrameData(GNSS_TIME StartTime, int svid, int Param, int *NavBits) = 0; // Param reserved for same Navigation bit structure in different signal 31 | virtual int SetEphemeris(int svid, PGPS_EPHEMERIS Eph) = 0; 32 | virtual int SetAlmanac(GPS_ALMANAC Alm[]) = 0; 33 | virtual int SetIonoUtc(PIONO_PARAM IonoParam, PUTC_PARAM UtcParam) = 0; 34 | virtual int SetNavParam(NavParamType ParamType, void *Param) { return 0; } 35 | int roundi(double data); 36 | int roundu(double data); 37 | double UnscaleDouble(double value, int scale); 38 | int UnscaleInt(double value, int scale); 39 | unsigned int UnscaleUint(double value, int scale); 40 | long long int UnscaleLong(double value, int scale); 41 | unsigned long long int UnscaleULong(double value, int scale); 42 | int AssignBits(unsigned int Data, int BitNumber, int BitStream[]); 43 | unsigned char ConvolutionEncode(unsigned char EncodeBits); 44 | unsigned int Crc24qEncode(unsigned int *BitStream, int Length); 45 | 46 | static const unsigned char ConvEncodeTable[256]; 47 | static const unsigned int Crc24q[256]; 48 | }; 49 | 50 | #endif // __NAV_BIT_H__ 51 | -------------------------------------------------------------------------------- /inc/NavData.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // NavData.h: 3 | // Declaration of navigation data processing class 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __NAV_DATA_H__ 10 | #define __NAV_DATA_H__ 11 | 12 | #include "BasicTypes.h" 13 | #include "Rinex.h" 14 | 15 | #define EPH_NUMBER_INC 100 16 | 17 | class CNavData 18 | { 19 | public: 20 | static const int GpsSatNumber = 32; 21 | static const int BdsSatNumber = 63; 22 | static const int GalileoSatNumber = 36; 23 | static const int GlonassSatNumber = 24; 24 | 25 | CNavData(); 26 | ~CNavData(); 27 | 28 | bool AddNavData(NavDataType Type, void *NavData); 29 | PGPS_EPHEMERIS FindEphemeris(GnssSystem system, GNSS_TIME time, int svid, int IgnoreTimeLimit = 0, unsigned char FirstPrioritySource = 0); 30 | PGLONASS_EPHEMERIS FindGloEphemeris(GLONASS_TIME GlonassTime, int slot); 31 | PGPS_ALMANAC GetGpsAlmanac() { return GpsAlmanac; } 32 | PGPS_ALMANAC GetBdsAlmanac() { return BdsAlmanac; } 33 | PGPS_ALMANAC GetGalileoAlmanac() { return GalileoAlmanac; } 34 | PGLONASS_ALMANAC GetGlonassAlmanac() { return GlonassAlmanac; } 35 | PIONO_PARAM GetGpsIono() { return &GpsIono; } 36 | PIONO_PARAM GetBdsIono() { return &BdsIono[0]; } 37 | PIONO_PARAM GetGalileoIono() { return (PIONO_PARAM)&GalileoIono; } 38 | PUTC_PARAM GetGpsUtcParam() { return &GpsUtcParam; } 39 | PUTC_PARAM GetBdsUtcParam() { return &BdsUtcParam; } 40 | PUTC_PARAM GetGalileoUtcParam() { return &GalileoUtcParam; } 41 | int GetGlonassSlotFreq(int slot) { return (slot > 0 && slot <= 24) ? GlonassSlotFreq[slot-1] : 7; } 42 | void ReadNavFile(char *filename); 43 | void ReadAlmFile(char *filename); 44 | void CompleteAlmanac(GnssSystem system, UTC_TIME time); 45 | void CompleteGlonassAlmanac(GLONASS_TIME time); 46 | 47 | private: 48 | int GpsEphemerisNumber; 49 | int BdsEphemerisNumber; 50 | int GalileoEphemerisNumber; 51 | int GlonassEphemerisNumber; 52 | int GpsEphemerisPoolSize; 53 | int BdsEphemerisPoolSize; 54 | int GalileoEphemerisPoolSize; 55 | int GlonassEphemerisPoolSize; 56 | PGPS_EPHEMERIS GpsEphemerisPool; 57 | PGPS_EPHEMERIS BdsEphemerisPool; 58 | PGPS_EPHEMERIS GalileoEphemerisPool; 59 | PGLONASS_EPHEMERIS GlonassEphemerisPool; 60 | GPS_ALMANAC GpsAlmanac[GpsSatNumber]; 61 | GPS_ALMANAC BdsAlmanac[BdsSatNumber]; 62 | GPS_ALMANAC GalileoAlmanac[GalileoSatNumber]; 63 | GLONASS_ALMANAC GlonassAlmanac[GlonassSatNumber]; 64 | IONO_PARAM GpsIono; 65 | IONO_PARAM BdsIono[24]; 66 | IONO_NEQUICK GalileoIono; 67 | UTC_PARAM GpsUtcParam; 68 | UTC_PARAM BdsUtcParam; 69 | UTC_PARAM GalileoUtcParam; 70 | // UTC_PARAM GalileoGpsParam; 71 | int GlonassSlotFreq[24]; // FreqID for each slot 72 | }; 73 | 74 | #endif // __NAV_DATA_H__ 75 | -------------------------------------------------------------------------------- /inc/PilotBit.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // PilotBit.h: 3 | // Pilot channel secondary bit for different signal 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #if !defined (__PILOT_BIT_H__) 10 | #define __PILOT_BIT_H__ 11 | 12 | #include "BasicTypes.h" 13 | 14 | const unsigned int *GetPilotBits(GnssSystem System, int SatSignal, int svid, int &Length); 15 | 16 | #endif //!defined(__PILOT_BIT_H__) 17 | -------------------------------------------------------------------------------- /inc/PowerControl.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // PowerControl.h: 3 | // Declaration of signal power control class 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __POWER_CONTROL_H__ 10 | #define __POWER_CONTROL_H__ 11 | 12 | #include "BasicTypes.h" 13 | 14 | typedef struct 15 | { 16 | int system; 17 | int svid; 18 | int time; 19 | double CN0; 20 | } SIGNAL_POWER, *PSIGNAL_POWER; 21 | 22 | enum ElevationAdjust { ElevationAdjustNone, ElevationAdjustSinSqrtFade }; 23 | 24 | class CPowerControl 25 | { 26 | public: 27 | CPowerControl(); 28 | ~CPowerControl(); 29 | enum ElevationAdjust Adjust; 30 | double NoiseFloor; 31 | double InitCN0; 32 | int ArraySize; 33 | int NextIndex; 34 | PSIGNAL_POWER PowerControlArray; 35 | int TimeElapsMs; 36 | 37 | void AddControlElement(PSIGNAL_POWER pControlElement); 38 | void Sort(); 39 | void ResetTime(); 40 | int GetPowerControlList(int TimeStepMs, PSIGNAL_POWER &PowerList); 41 | }; 42 | 43 | #endif // __POWER_CONTROL_H__ 44 | -------------------------------------------------------------------------------- /inc/PrnGenerate.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // PrnGenerate.h: 3 | // Declaration of PRN code generation class 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __PRN_GENERATE_H__ 10 | #define __PRN_GENERATE_H__ 11 | 12 | #include "BasicTypes.h" 13 | 14 | class LsfrSequence 15 | { 16 | public: 17 | LsfrSequence(unsigned int InitState, unsigned int Polynomial, int Length); 18 | ~LsfrSequence(); 19 | void Initial(); 20 | int GetOutput(); 21 | 22 | private: 23 | unsigned int mInitState; 24 | unsigned int mCurrentState; 25 | unsigned int mPolynomial; 26 | unsigned int mOutputMask; 27 | }; 28 | 29 | struct PrnAttribute 30 | { 31 | int ChipRate; // chips per millisecond 32 | int DataPeriod; // PRN period for data channel in millisecond 33 | int PilotPeriod;// PRN period for pilot channel in millisecond 34 | unsigned int Attribute; // defined as following 35 | }; 36 | #define PRN_ATTRIBUTE_BOC 1 37 | #define PRN_ATTRIBUTE_TMD 2 38 | 39 | class PrnGenerate 40 | { 41 | public: 42 | PrnGenerate(GnssSystem System, int SignalIndex, int Svid); 43 | ~PrnGenerate(); 44 | 45 | int *DataPrn, *PilotPrn; 46 | const PrnAttribute* Attribute; 47 | 48 | private: 49 | int *GetGoldCode(unsigned int G1Init, unsigned int G1Poly, unsigned int G2Init, unsigned int G2Poly, int Length, int Depth, int ResetPos); 50 | void LegendreSequence(int *Data, int Length); 51 | int *GetL1CWeil(int InsertPoint, int PhaseDiff); 52 | int *GetB1CWeil(int TruncationPoint, int PhaseDiff); 53 | int *GetMemorySequence(const unsigned int *BinarySequence, int SectorLength); 54 | 55 | static const unsigned int L1CAPrnInit[32]; 56 | static const unsigned int L5IPrnInit[32]; 57 | static const unsigned int L5QPrnInit[32]; 58 | static const unsigned int L2CMPrnInit[32]; 59 | static const unsigned int L2CLPrnInit[32]; 60 | static const unsigned int B1IPrnInit[63]; 61 | static const unsigned int B3IPrnInit[63]; 62 | static const unsigned int B2aDPrnInit[63]; 63 | static const unsigned int B2aPPrnInit[63]; 64 | static const unsigned int B2bPrnInit[63]; 65 | static const unsigned int E5aIPrnInit[50]; 66 | static const unsigned int E5aQPrnInit[50]; 67 | static const unsigned int E5bIPrnInit[50]; 68 | static const unsigned int E5bQPrnInit[50]; 69 | static const int B1CDataTruncation[63]; 70 | static const int B1CDataPhaseDiff[63]; 71 | static const int B1CPilotTruncation[63]; 72 | static const int B1CPilotPhaseDiff[63]; 73 | static const int L1CDataInsertIndex[63]; 74 | static const int L1CDataPhaseDiff[63]; 75 | static const int L1CPilotInsertIndex[63]; 76 | static const int L1CPilotPhaseDiff[63]; 77 | static const unsigned int E1MemoryCode[100*128]; 78 | static const unsigned int E6MemoryCode[100*160]; 79 | static const PrnAttribute PrnAttributes[]; 80 | }; 81 | 82 | #endif // __PRN_GENERATE_H__ 83 | -------------------------------------------------------------------------------- /inc/Rinex.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // Rinex.h: 3 | // Declaration of RINEX file read/write functions 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __RINEX_H__ 10 | #define __RINEX_H__ 11 | 12 | #include 13 | #include "BasicTypes.h" 14 | 15 | #define RINEX_MAX_FREQ 3 16 | 17 | typedef struct 18 | { 19 | int MajorVersion; 20 | int MinorVersion; 21 | unsigned int HeaderFlag; 22 | char Program[20]; 23 | char Agency[20]; 24 | UTC_TIME DateTime; 25 | char Comment[60]; 26 | char MakerName[60]; 27 | char MakerNumber[60]; 28 | char MakerType[60]; 29 | char Observer[60]; 30 | char ReceiverType[60]; 31 | char AntennaType[60]; 32 | double ApproxPos[3]; 33 | double AntennaDelta[3]; 34 | // each system output maximum observation of 3 frequencies 35 | // bit0~3 as mask for PSR/ADR/Doppler/CN0 respectively, bit4~7 as channel select (I/Q/D/P etc.), bit8~12 as frequency select 36 | unsigned int SysObsTypeGps[RINEX_MAX_FREQ]; 37 | unsigned int SysObsTypeGlonass[RINEX_MAX_FREQ]; 38 | unsigned int SysObsTypeBds[RINEX_MAX_FREQ]; 39 | unsigned int SysObsTypeGalileo[RINEX_MAX_FREQ]; 40 | UTC_TIME FirstObs; 41 | UTC_TIME LastObs; 42 | unsigned int GlonassSlotMask; 43 | int GlonassFreqNumber[24]; 44 | int LeapSecond; 45 | double Interval; 46 | } RINEX_HEADER, *PRINEX_HEADER; 47 | 48 | // definition for HeaderFlag field 49 | #define RINEX_HEADER_PGM 0x00000001 50 | #define RINEX_HEADER_AGENCY 0x00000002 51 | #define RINEX_HEADER_DATE 0x00000004 52 | #define RINEX_HEADER_COMMENT 0x00000008 53 | #define RINEX_HEADER_MK_NAME 0x00000010 54 | #define RINEX_HEADER_MK_NUMBER 0x00000020 55 | #define RINEX_HEADER_MK_TYPE 0x00000040 56 | #define RINEX_HEADER_OBSERVER 0x00000080 57 | #define RINEX_HEADER_RCVR_TYPE 0x00000100 58 | #define RINEX_HEADER_ANT_TYPE 0x00000200 59 | #define RINEX_HEADER_APPROX_POS 0x00001000 60 | #define RINEX_HEADER_ANT_DELTA 0x00002000 61 | #define RINEX_HEADER_SLOT_FREQ 0x00004000 62 | #define RINEX_HEADER_FIRST_OBS 0x00010000 63 | #define RINEX_HEADER_LAST_OBS 0x00020000 64 | 65 | // definitions commonly used for SysObsTypexxx 66 | #define OBS_TYPE_MASK_PSR 0x1 67 | #define OBS_TYPE_MASK_ADR 0x2 68 | #define OBS_TYPE_MASK_DOP 0x4 69 | #define OBS_TYPE_MASK_CN0 0x8 70 | #define OBS_TYPE_MASK_ALL 0xf 71 | #define OBS_CHANNEL_GPS_CA (0x0 << 4) 72 | #define OBS_CHANNEL_GPS_L1CD (0x1 << 4) 73 | #define OBS_CHANNEL_GPS_L1CP (0x2 << 4) 74 | #define OBS_CHANNEL_GPS_L1CDP (0x3 << 4) 75 | #define OBS_CHANNEL_GPS_L2CM (0x2 << 4) 76 | #define OBS_CHANNEL_GPS_L2CL (0x3 << 4) 77 | #define OBS_CHANNEL_GPS_L2CML (0x4 << 4) 78 | #define OBS_CHANNEL_GPS_L2P (0x5 << 4) 79 | #define OBS_CHANNEL_GPS_L2Z (0x6 << 4) 80 | #define OBS_CHANNEL_GLO_CA (0x0 << 4) 81 | #define OBS_CHANNEL_GAL_E1B (0x1 << 4) 82 | #define OBS_CHANNEL_GAL_E1C (0x2 << 4) 83 | #define OBS_CHANNEL_GAL_E1BC (0x3 << 4) 84 | #define OBS_CHANNEL_I (0x0 << 4) 85 | #define OBS_CHANNEL_Q (0x1 << 4) 86 | #define OBS_CHANNEL_IQ (0x2 << 4) 87 | #define OBS_CHANNEL_D (0x0 << 4) 88 | #define OBS_CHANNEL_P (0x1 << 4) 89 | #define OBS_CHANNEL_DP (0x2 << 4) 90 | /*#define OBS_FREQUENCY_GPS_L1 (0x0 << 8) 91 | #define OBS_FREQUENCY_GPS_L2 (0x1 << 8) 92 | #define OBS_FREQUENCY_GPS_L5 (0x2 << 8) 93 | #define OBS_FREQUENCY_GLO_G1 (0x0 << 8) 94 | #define OBS_FREQUENCY_GLO_G2 (0x1 << 8) 95 | #define OBS_FREQUENCY_GAL_E1 (0x0 << 8) 96 | #define OBS_FREQUENCY_GAL_E5a (0x1 << 8) 97 | #define OBS_FREQUENCY_GAL_E5b (0x2 << 8) 98 | #define OBS_FREQUENCY_GAL_E5 (0x3 << 8) 99 | #define OBS_FREQUENCY_GAL_E6 (0x4 << 8) 100 | #define OBS_FREQUENCY_BDS_B1C (0x0 << 8) 101 | #define OBS_FREQUENCY_BDS_B1 (0x1 << 8) 102 | #define OBS_FREQUENCY_BDS_B2 (0x2 << 8) 103 | #define OBS_FREQUENCY_BDS_B3 (0x3 << 8) 104 | #define OBS_FREQUENCY_BDS_B2a (0x4 << 8) 105 | #define OBS_FREQUENCY_BDS_B2b (0x5 << 8)*/ 106 | 107 | enum NavDataType { 108 | NavDataEnd = 0, NavDataUnknown, 109 | NavDataGpsIono, NavDataBdsIonoA, NavDataBdsIonoB, NavDataGalileoIono, 110 | NavDataGpsUtc, NavDataBdsUtc, NavDataGalileoUtc, NavDataGalileoGps, NavDataLeapSecond, 111 | NavDataGlonassFreq, 112 | NavDataGpsLnav, NavDataGpsCnav, NavDataGpsCnav2, 113 | NavDataBdsD1D2, NavDataBdsCnav1, NavDataBdsCnav2, NavDataBdsCnav3, 114 | NavDataGalileoINav, NavDataGalileoFNav, 115 | NavDataNavICLnav, 116 | NavDataGlonassFdma, 117 | NavDataSbasNav, 118 | NavDataIonGps, NavDataIonBds, NavDataIonBdgim, NavDataIonGalileo, NavDataIonQzss, NavDataIonIrnss, 119 | }; 120 | 121 | NavDataType LoadNavFileHeader(FILE *fp_nav, void *NavData); 122 | NavDataType LoadNavFileContents(FILE *fp_nav, void *NavData); 123 | void OutputHeader(FILE *fp, PRINEX_HEADER Header); 124 | void OutputObservation(FILE *fp, UTC_TIME time, int TotalObsNumber, SAT_OBSERVATION Observations[]); 125 | 126 | #endif // __RINEX_H__ 127 | -------------------------------------------------------------------------------- /inc/SatIfSignal.h: -------------------------------------------------------------------------------- 1 | #include "BasicTypes.h" 2 | #include "ComplexNumber.h" 3 | #include "PrnGenerate.h" 4 | #include "NavBit.h" 5 | #include "SatelliteSignal.h" 6 | 7 | class CSatIfSignal 8 | { 9 | public: 10 | CSatIfSignal(int MsSampleNumber, int SatIfFreq, GnssSystem SatSystem, int SatSignalIndex, unsigned char SatId); 11 | ~CSatIfSignal(); 12 | void InitState(GNSS_TIME CurTime, PSATELLITE_PARAM pSatParam, NavBit* pNavData); 13 | void GetIfSample(GNSS_TIME CurTime); 14 | complex_number *SampleArray; 15 | 16 | private: 17 | int SampleNumber; // sample number within 1ms 18 | int IfFreq; // must be multiple of 500 (for GLONASS) or 1000 (other signal) 19 | GnssSystem System; 20 | int SignalIndex; 21 | int Svid; 22 | PrnGenerate* PrnSequence; 23 | int DataLength, PilotLength; 24 | CSatelliteSignal SatelliteSignal; 25 | PSATELLITE_PARAM SatParam; 26 | double StartCarrierPhase, EndCarrierPhase; 27 | GNSS_TIME StartTransmitTime, EndTransmitTime, SignalTime; 28 | complex_number DataSignal, PilotSignal; 29 | int GlonassHalfCycle, HalfCycleFlag; 30 | 31 | complex_number GetPrnValue(double &CurChip, double CodeStep); 32 | complex_number GetRotateValue(double & CurPhase, double PhaseStep); 33 | }; 34 | -------------------------------------------------------------------------------- /inc/SatelliteParam.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // SatelliteParam.h: 3 | // Definition of functions to calculate satellite parameters 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #if !defined (__SATELLITE_PARAM_H__) 10 | #define __SATELLITE_PARAM_H__ 11 | 12 | #include "ConstVal.h" 13 | #include "BasicTypes.h" 14 | #include "PowerControl.h" 15 | 16 | int GetVisibleSatellite(KINEMATIC_INFO Position, GNSS_TIME time, OUTPUT_PARAM OutputParam, GnssSystem system, PGPS_EPHEMERIS Eph[], int Number, PGPS_EPHEMERIS EphVisible[]); 17 | int GetGlonassVisibleSatellite(KINEMATIC_INFO Position, GLONASS_TIME time, OUTPUT_PARAM OutputParam, PGLONASS_EPHEMERIS Eph[], int Number, PGLONASS_EPHEMERIS EphVisible[]); 18 | void GetSatelliteParam(KINEMATIC_INFO PositionEcef, LLA_POSITION PositionLla, GNSS_TIME time, GnssSystem system, PGPS_EPHEMERIS Eph, PIONO_PARAM IonoParam, PSATELLITE_PARAM SatelliteParam); 19 | void GetSatelliteCN0(int PowerListCount, SIGNAL_POWER PowerList[], double DefaultCN0, enum ElevationAdjust Adjust, PSATELLITE_PARAM SatelliteParam); 20 | double GetWaveLength(int system, int SignalIndex, int FreqID); 21 | double GetTravelTime(PSATELLITE_PARAM SatelliteParam, int SignalIndex); 22 | double GetCarrierPhase(PSATELLITE_PARAM SatelliteParam, int SignalIndex); 23 | double GetDoppler(PSATELLITE_PARAM SatelliteParam, int SignalIndex); 24 | GNSS_TIME GetTransmitTime(GNSS_TIME ReceiverTime, double TravelTime); 25 | 26 | #endif //!defined(__SATELLITE_PARAM_H__) 27 | -------------------------------------------------------------------------------- /inc/SatelliteSignal.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // SatelliteSignal.h: 3 | // Definition of functions to calculate satellite signal with data/pilot modulation 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #if !defined (__SATELLITE_SIGNAL_H__) 10 | #define __SATELLITE_SIGNAL_H__ 11 | 12 | #include "BasicTypes.h" 13 | #include "ComplexNumber.h" 14 | #include "SatelliteParam.h" 15 | #include "NavBit.h" 16 | 17 | struct SignalAttribute 18 | { 19 | int CodeLength; // PRN length in unit of millisecond 20 | int NHLength; // length of one data bit in unit of PRN period 21 | int NHCode; // NH for data modulation 22 | int FrameLength; // length of frame/subframe in unit of millisecond 23 | // int SecondaryLength; // length of secondary code 24 | // int SecondarySize; // size of secondary code array for one SV in DWORD (0 if all SV uses the same secondary code) 25 | // const unsigned int *SecondaryCode; // array of secondary code 26 | }; 27 | 28 | class CSatelliteSignal 29 | { 30 | public: 31 | CSatelliteSignal(); 32 | ~CSatelliteSignal(); 33 | 34 | BOOL SetSignalAttribute(GnssSystem System, int SignalIndex, NavBit *pNavData, int svid); 35 | BOOL GetSatelliteSignal(GNSS_TIME TransmitTime, complex_number &DataSignal, complex_number &PilotSignal); 36 | 37 | // signal attributes 38 | GnssSystem SatSystem; 39 | int SatSignal; 40 | int Svid; 41 | NavBit *NavData; 42 | const SignalAttribute* Attribute; 43 | 44 | // variables used to calculate modulated signal 45 | int CurrentFrame; // frame number of data stream filling in Bits 46 | int CurrentBitIndex; // bit index used for current ms correlation result 47 | int DataBits[1800]; // maximum 1800 encoded data bit for one subframe/page 48 | 49 | // constant arrays for signal attributes and NH code 50 | static const SignalAttribute SignalAttributes[32]; 51 | }; 52 | 53 | #endif //!defined(__SATELLITE_SIGNAL_H__) 54 | -------------------------------------------------------------------------------- /inc/SignalSim.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // SignalSim.h: 3 | // All included files to use SignalSim package 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __SIGNAL_SIM_H__ 10 | #define __SIGNAL_SIM_H__ 11 | 12 | #include "ConstVal.h" 13 | #include "BasicTypes.h" 14 | #include "Trajectory.h" 15 | #include "GnssTime.h" 16 | #include "PilotBit.h" 17 | #include "NavData.h" 18 | #include "LNavBit.h" 19 | #include "CNavBit.h" 20 | #include "CNav2Bit.h" 21 | #include "INavBit.h" 22 | #include "FNavBit.h" 23 | #include "D1D2NavBit.h" 24 | #include "BCNav1Bit.h" 25 | #include "BCNav2Bit.h" 26 | #include "BCNav3Bit.h" 27 | #include "GNavBit.h" 28 | #include "JsonParser.h" 29 | #include "XmlInterpreter.h" 30 | #include "JsonInterpreter.h" 31 | #include "SatelliteParam.h" 32 | #include "SatelliteSignal.h" 33 | #include "SatIfSignal.h" 34 | #include "Coordinate.h" 35 | 36 | #endif // __SIGNAL_SIM_H__ 37 | -------------------------------------------------------------------------------- /inc/Tracking.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // Tracking.h: 3 | // Declaration of functions for tracking configuration and implementation 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __TRACKING_H__ 10 | #define __TRACKING_H__ 11 | 12 | #include "BasicTypes.h" 13 | 14 | typedef struct 15 | { 16 | int ChannelNumber; 17 | int CorNumber; 18 | double NoiseFloor; 19 | } BASEBAND_CONFIG, *PBASEBAND_CONFIG; 20 | 21 | typedef struct 22 | { 23 | int Enable; // 0:default, 1:auto, 2:enable 24 | int CorInterval; 25 | int PeakCor; 26 | double InitFreqError; 27 | double InitPhaseError; 28 | double InitCodeError; 29 | double SnrRatio; 30 | } CHANNEL_INIT_PARAM, *PCHANNEL_INIT_PARAM; 31 | 32 | 33 | 34 | 35 | #endif // __TRACKING_H__ 36 | -------------------------------------------------------------------------------- /inc/Trajectory.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // Trajectory.h: 3 | // Declaration of trajectory processing class 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __TRAJECTORY_H__ 10 | #define __TRAJECTORY_H__ 11 | 12 | #include "BasicTypes.h" 13 | 14 | #define TRAJECTORY_NO_ERR 0 15 | #define TRAJECTORY_UNKNOWN_TYPE 1 16 | #define TRAJECTORY_TYPE_MISMATCH 2 17 | #define TRAJECTORY_INVALID_PARAM 3 18 | #define TRAJECTORY_ZERO_SPEED 4 19 | #define TRAJECTORY_ACC_JERK 1 20 | #define TRAJECTORY_ZERO_ACC 2 21 | #define TRAJECTORY_ZERO_ACCRATE 3 22 | #define TRAJECTORY_ZERO_DEGREE 4 23 | #define TRAJECTORY_NEGATIVE 5 24 | 25 | enum TrajectoryType { TrajTypeUnknown = 0, TrajTypeConstSpeed, TrajTypeConstAcc, TrajTypeVerticalAcc, TrajTypeJerk, TrajTypeHorizontalCircular }; 26 | enum TrajectoryDataType { TrajDataTimeSpan = 0, TrajDataAcceleration, TrajDataSpeed, TrajDataAccRate, TrajDataAngle, TrajDataAngularRate, TrajDataRadius }; 27 | 28 | class CTrajectorySegment 29 | { 30 | public: 31 | CTrajectorySegment(); 32 | ~CTrajectorySegment(); 33 | #if 0 34 | static LLA_POSITION EcefToLla(KINEMATIC_INFO ecef_pos); 35 | static KINEMATIC_INFO LlaToEcef(LLA_POSITION lla_pos); 36 | static CONVERT_MATRIX CalcConvMatrix(KINEMATIC_INFO Position); 37 | static CONVERT_MATRIX CalcConvMatrix(LLA_POSITION Position); 38 | static void SpeedEnuToCourse(LOCAL_SPEED &Speed); 39 | static void SpeedCourseToEnu(LOCAL_SPEED &Speed); 40 | static void SpeedEcefToLocal(CONVERT_MATRIX ConvertMatrix, KINEMATIC_INFO PosVel, LOCAL_SPEED &Speed); 41 | static void SpeedLocalToEcef(CONVERT_MATRIX ConvertMatrix, LOCAL_SPEED Speed, KINEMATIC_INFO &PosVel); 42 | #endif 43 | static TrajectoryType GetTrajectoryType(CTrajectorySegment *pTrajectory); 44 | void GetSpeedProjection(double projection[3]); 45 | void InitSegment(CTrajectorySegment *PrevSegment); 46 | virtual int SetSegmentParam(CTrajectorySegment *PrevSegment, TrajectoryDataType DataType1, double Data1, TrajectoryDataType DataType2, double Data2) = 0; 47 | virtual KINEMATIC_INFO GetPosVel(double RelativeTime) = 0; 48 | 49 | KINEMATIC_INFO m_StartPosVel; 50 | LOCAL_SPEED m_LocalSpeed; 51 | CONVERT_MATRIX m_ConvertMatrix; 52 | // double m_StartTime; 53 | double m_TimeSpan; 54 | CTrajectorySegment *m_pNextTrajectory; 55 | }; 56 | 57 | class CTrajectoryConstSpeed : public CTrajectorySegment 58 | { 59 | public: 60 | int SetSegmentParam(CTrajectorySegment *PrevSegment, TrajectoryDataType DataType1, double Data1, TrajectoryDataType DataType2, double Data2); 61 | KINEMATIC_INFO GetPosVel(double RelativeTime); 62 | }; 63 | 64 | class CTrajectoryConstAcc : public CTrajectorySegment 65 | { 66 | public: 67 | double m_ax, m_ay, m_az; 68 | int SetSegmentParam(CTrajectorySegment *PrevSegment, TrajectoryDataType DataType1, double Data1, TrajectoryDataType DataType2, double Data2); 69 | KINEMATIC_INFO GetPosVel(double RelativeTime); 70 | }; 71 | 72 | class CTrajectoryVerticalAcc : public CTrajectorySegment 73 | { 74 | public: 75 | double m_ax, m_ay, m_az; 76 | int SetSegmentParam(CTrajectorySegment *PrevSegment, TrajectoryDataType DataType1, double Data1, TrajectoryDataType DataType2, double Data2); 77 | KINEMATIC_INFO GetPosVel(double RelativeTime); 78 | }; 79 | 80 | class CTrajectoryJerk : public CTrajectorySegment 81 | { 82 | public: 83 | KINEMATIC_INFO m_Acc; // initial acceleration in x, y, z and acceleration rate in vx, vy, vz 84 | int SetSegmentParam(CTrajectorySegment *PrevSegment, TrajectoryDataType DataType1, double Data1, TrajectoryDataType DataType2, double Data2); 85 | KINEMATIC_INFO GetPosVel(double RelativeTime); 86 | }; 87 | 88 | class CTrajectoryHorizontalCircular : public CTrajectorySegment 89 | { 90 | public: 91 | double m_AngularRate; 92 | int SetSegmentParam(CTrajectorySegment *PrevSegment, TrajectoryDataType DataType1, double Data1, TrajectoryDataType DataType2, double Data2); 93 | KINEMATIC_INFO GetPosVel(double RelativeTime); 94 | }; 95 | 96 | class CTrajectory 97 | { 98 | public: 99 | CTrajectory(); 100 | ~CTrajectory(); 101 | 102 | void SetInitPosVel(KINEMATIC_INFO InitPosVel); 103 | void SetInitPosVel(LLA_POSITION InitPosition, LOCAL_SPEED InitVelocity, bool IsEnu); 104 | 105 | void ClearTrajectoryList(); 106 | int AppendTrajectory(TrajectoryType TrajType, TrajectoryDataType DataType1, double Data1, TrajectoryDataType DataType2, double Data2); 107 | void ResetTrajectoryTime(); 108 | BOOL GetNextPosVelECEF(double TimeStep, KINEMATIC_INFO &PosVel); 109 | BOOL GetNextPosVelLLA(double TimeStep, LLA_POSITION &Position, LOCAL_SPEED &Velocity); 110 | double GetTimeLength(); 111 | void SetTrajectoryName(char *Name); 112 | char *GetTrajectoryName() { return TrajectoryName; } 113 | 114 | private: 115 | KINEMATIC_INFO m_InitPosVel; 116 | LOCAL_SPEED m_InitLocalSpeed; 117 | CTrajectorySegment *m_pTrajectoryList; 118 | CTrajectorySegment *m_pCurrentTrajectory; 119 | double RelativeTime; 120 | char TrajectoryName[128]; 121 | 122 | CTrajectorySegment *GetLastSegment(); 123 | }; 124 | 125 | #endif // __TRAJECTORY_H__ 126 | -------------------------------------------------------------------------------- /inc/XmlElement.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // XmlElement.h: 3 | // Declaration of XML file operation class 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #if !defined __XML_ELEMENT_H__ 10 | #define __XML_ELEMENT_H__ 11 | 12 | #include 13 | 14 | #define DICT_ITEM_INC 8 15 | #define MAX_KEY_LENGTH (32-1) 16 | #define MAX_VALUE_LENGTH (96-1) 17 | #define MAX_TAG_LENGTH (64-1) 18 | #define MAX_TEXT_LENGTH (192-1) 19 | #define MAX_HEADER_LENGTH (256-1) 20 | #define MAX_COMMENT_LENGTH (256-1) 21 | 22 | struct DictItem 23 | { 24 | char key[MAX_KEY_LENGTH+1]; 25 | char value[MAX_VALUE_LENGTH+1]; 26 | }; 27 | 28 | // dictionary class, array of key/value couple without order 29 | class CSimpleDict 30 | { 31 | public: 32 | CSimpleDict(); 33 | ~CSimpleDict(); 34 | CSimpleDict& operator=(const CSimpleDict& dict); 35 | bool Add(char *key, char *value); 36 | bool Delete(char *key); 37 | int Find(const char *key); 38 | 39 | int DictItemNumber; 40 | DictItem *Dictionary; 41 | private: 42 | int DictArraySize; 43 | }; 44 | 45 | // XML element class 46 | class CXmlElement 47 | { 48 | public: 49 | CXmlElement(); 50 | CXmlElement(CXmlElement &element); 51 | CXmlElement(char *tag, char *text); 52 | ~CXmlElement(); 53 | bool DeleteTree(); 54 | bool RemoveElement(int index); 55 | CXmlElement *GetElement(int index); 56 | CXmlElement *EnumSubElement(CXmlElement *PrevSubElement); 57 | bool parse_string(char *string, bool with_tag); 58 | char *process_tag(char *string); 59 | bool output(FILE *fp, int indent); 60 | bool AppendElement(CXmlElement element); 61 | bool AppendElement(char *tag, char *text); 62 | bool InsertElement(int index, CXmlElement element); 63 | bool SetTag(char *tag); 64 | bool SetText(char *text); 65 | char *GetTag() { return tag; } 66 | char *GetText() { return text; } 67 | CSimpleDict *GetAttributes() { return &Attributes; } 68 | 69 | private: 70 | char tag[MAX_TAG_LENGTH+1]; 71 | char text[MAX_TEXT_LENGTH+1]; 72 | int iChildNumber; 73 | CSimpleDict Attributes; 74 | CXmlElement *ChildElements; 75 | CXmlElement *SiblingElements; 76 | bool Completed; 77 | }; 78 | 79 | // XML tree class 80 | class CXmlElementTree 81 | { 82 | public: 83 | char header[MAX_HEADER_LENGTH+1]; 84 | char comment[MAX_COMMENT_LENGTH+1]; 85 | 86 | CXmlElementTree(); 87 | CXmlElementTree(CXmlElement element); 88 | ~CXmlElementTree(); 89 | void SetRootElement(CXmlElement element); 90 | void ClearTree(); 91 | bool parse(const char *filename); 92 | bool write(const char *filename); 93 | CXmlElement *getroot() { return root; } 94 | 95 | private: 96 | CXmlElement *root; 97 | char *found_header(char *string); 98 | char *found_comment(char *string); 99 | bool found_tag(char *string); 100 | }; 101 | 102 | #endif //__XML_ELEMENT_H__ -------------------------------------------------------------------------------- /inc/XmlInterpreter.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // XmlInterpreter.h: 3 | // Declaration of functions to interprete XML element tree 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #ifndef __XML_INTERPRETER_H__ 10 | #define __XML_INTERPRETER_H__ 11 | 12 | #include 13 | #include "XmlElement.h" 14 | #include "Trajectory.h" 15 | #include "NavData.h" 16 | #include "PowerControl.h" 17 | #include "Tracking.h" 18 | 19 | typedef int (*TagProcessFunction)(void *); 20 | 21 | typedef struct 22 | { 23 | const char *key; 24 | const char **values; 25 | int value_size; 26 | int default_value; 27 | } ATTRIBUTE_TYPE, *PATTRIBUTE_TYPE; 28 | 29 | typedef struct 30 | { 31 | const char *TagName; 32 | TagProcessFunction ProcessFunction; 33 | void *Parameter; 34 | } ELEMENT_PROCESS, *PELEMENT_PROCESS; 35 | 36 | typedef struct 37 | { 38 | PATTRIBUTE_TYPE *AttributeList; 39 | int AttributeNumber; 40 | ELEMENT_PROCESS *ProcessList; 41 | int ProcessListNumber; 42 | } INTERPRETE_PARAM, *PINTERPRETE_PARAM; 43 | 44 | int ElementProcTime(void *Param); 45 | int ElementProcTrajectory(void *Param); 46 | int ElementProcEphemeris(void *Param); 47 | int ElementProcOutput(void *Param); 48 | int ElementProcBasebandConfig(void *Param); 49 | int ElementProcSatInitParam(void *Param); 50 | 51 | extern PATTRIBUTE_TYPE InitTimeAttributes[]; 52 | extern PATTRIBUTE_TYPE TrajectoryAttributes[]; 53 | extern PATTRIBUTE_TYPE InitPosTypeAttributes[]; 54 | extern PATTRIBUTE_TYPE LatLonTypeAttributes[]; 55 | extern PATTRIBUTE_TYPE InitVelTypeAttributes[]; 56 | extern PATTRIBUTE_TYPE SpeedUnitAttributes[]; 57 | extern PATTRIBUTE_TYPE CourseUnitAttributes[]; 58 | extern PATTRIBUTE_TYPE EphAttributes[]; 59 | extern PATTRIBUTE_TYPE OutputAttributes[]; 60 | extern PATTRIBUTE_TYPE SatelliteAttributes[]; 61 | extern PATTRIBUTE_TYPE BasebandConfigAttributes[]; 62 | extern PATTRIBUTE_TYPE ElevationMaskAttributes[]; 63 | extern PATTRIBUTE_TYPE SystemAttributes[]; 64 | extern PATTRIBUTE_TYPE FreqIDAttributes[]; 65 | extern PATTRIBUTE_TYPE ChannelInitAttributes[]; 66 | 67 | extern const char *StartTimeElements[]; 68 | extern const char *StartPosElements[]; 69 | extern const char *StartVelElements[]; 70 | extern const char *TrajectoryElements[]; 71 | extern const char *TrajectoryTypeElements[]; 72 | extern const char *TrajectoryArgumentElements[]; 73 | extern const char *OutputParamElements[]; 74 | extern const char *PowerControlElements[]; 75 | extern const char *PowerParamElements[]; 76 | extern const char *SignalPowerElements[]; 77 | extern const char *DelayConfigElements[]; 78 | extern const char *ConfigParamElements[]; 79 | extern const char *BasebandConfigElements[]; 80 | extern const char *SatInitElements[]; 81 | 82 | BOOL AssignStartTime(CXmlElement *Element, UTC_TIME &UtcTime); 83 | BOOL SetTrajectory(CXmlElement *Element, LLA_POSITION &StartPos, LOCAL_SPEED &StartVel, CTrajectory &Trajectory); 84 | BOOL SetOutputParam(CXmlElement *Element, OUTPUT_PARAM &OutputParam); 85 | BOOL SetPowerControl(CXmlElement *Element, CPowerControl &PowerControl); 86 | BOOL SetDelayConfig(CXmlElement *Element, DELAY_CONFIG &DelayConfig); 87 | BOOL SetBasebandConfig(CXmlElement *Element, BASEBAND_CONFIG &BasebandConfig); 88 | BOOL SetSatInitParam(CXmlElement *Element, CHANNEL_INIT_PARAM SatInitParam[]); 89 | BOOL AssignParameters(CXmlElement *RootElement, PUTC_TIME UtcTime, PLLA_POSITION StartPos, PLOCAL_SPEED StartVel, CTrajectory *Trajectory, CNavData *NavData, POUTPUT_PARAM OutputParam, CPowerControl *PowerControl, PDELAY_CONFIG DelayConfig); 90 | 91 | int FindAttribute(char *key, PATTRIBUTE_TYPE *AttributeList); 92 | int GetAttributeIndex(char *value, PATTRIBUTE_TYPE Attribute); 93 | int GetElementIndex(const char *tag, const char **ElementList); 94 | int FindTagIndex(char *Tag, ELEMENT_PROCESS *ProcessList, int ProcessListNumber); 95 | int ProcessElement(CXmlElement *Element, PINTERPRETE_PARAM InterpreteParam); 96 | 97 | int ElementProcTime(void *Param); 98 | int ElementProcTrajectory(void *Param); 99 | int ElementProcEphemeris(void *Param); 100 | int ElementProcOutput(void *Param); 101 | int ElementProcBasebandConfig(void *Param); 102 | int ElementProcSatInitParam(void *Param); 103 | 104 | #endif // __XML_INTERPRETER_H__ 105 | -------------------------------------------------------------------------------- /src/BCNav2Bit.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // BCNav2Bit.h: 3 | // Implementation of navigation bit synthesis class for B-CNAV2 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #include 10 | #include "ConstVal.h" 11 | #include "BCNav2Bit.h" 12 | 13 | const char BCNav2Bit::B2aMatrixGen[B2a_SYMBOL_LENGTH*B2a_SYMBOL_LENGTH+1] = { 14 | "h[0G@Y0i^R20[;aG09YT>0c0GbQN" 16 | "8KZ0>810<PCMQ0K0jn2j0=ng0KgM=1C0Png9^j0PD0F0dijD[" 20 | "U8H0^UL0FF6`?0>0@N0F``0I_OlZ=?i0]LGW0RC>l0Y0Wf`5" 21 | "RW0d1N0OIO:T070[TMD0RTX0`X:R_O0OTX@9W0IG050>9NGY" 22 | "O`05Ud0A810<7jI>0Z0nH0<110V5L`Rl0UbZU0\\bG0>9c\\EP0nb9C]m0n80R0fJU8_" 26 | "kKQ0>81077jI>0Z0nH0<110V5L`Rl0h=@0MRMaN0S0FDkQ0PD10o1aPlM0RN1E5Q0cf0i0@VQf<" 30 | "en10beN0>>a2H0?0:`0>NN0FUWS]fH[0;N1K0C6?S0@0Oc28" 31 | "RW0d1N0OIO:T070[TFD0lhX0`X:R_O0OTX@>W0IG050N9DGY" 32 | ">]0WiC02jZ`U050=UKC0eUf05V`e\\Z0jU52h]0j[0`0ATC[R" 33 | "o5F0No?011T\\20G0Ub0I\\\\01J4WV5Ik0<^?S0EgGi0d0S=Nf" 34 | "Rj0IoD0Q_[j0_J060e9DJY" 35 | "nS;0?nV0QQBF10Z0cI0SFF0<82bCS]l06GV`0[jZb0J0`W?K" 36 | "NFi0RNj0AA_gR0[0^603aa0X`70J01`^>2" 38 | "h260Zh70TTPi^R@0[;aG09YT>0c0HbVN" 42 | "Jk>0`JH0GGRLF0I0e\\0GLL01oSK<8F50QbH40gTIK0M04nLc" 43 | "]803NK0Y259Z0I06ZiB0]ZT0hT9]m502ZTY[802`0U0b[K`j" 44 | "gi01:90Vo37W0f02WGS0KWL0LL7KZ30oWLVIi0o@0R0_I9@M" 45 | "2?j0R2A033_g[0i0\\E0?gg0X`0DaAV0oJiZ0O0VHRI" 46 | "3YW0c3h0SSI=50K0jn0O==0Si:o`YO90N8he01G4<0a0emcd" 47 | "Z60`Yj0>PCFn0K0jn2j0=n40KgM=1C0PnK>^60PD0F0dijD[" 48 | "Pe0RKn0jlU[D0Z0nHCn01Ho0ZoO1XU0lHoj6n0lh0[045nh8" 49 | "8l]0>870<W" 50 | "Fo0^Sc0@[@AI0\\0Q_WR0U_70k7AU[@0[I7XKR0O40Y0cgR4T" 51 | "kO<0Ik?07]i1<0V05>07??0;cbLgK<40T?Q\\053V`080^h14" 52 | "5h09d30g>g1k0i02CY206C40i416eg0>C4GD20>M0Q0HN2M`" 53 | "FZD0j?X0YMnij0P0HA0YXX09>gR_;YQ0UBmT0H8960L0E7iQ" 54 | "kK0MmX0oFWHc030`R9`0CRS03SHCUE0FRS1Y`0Fd0@0?L`IN" 55 | "LI30T`[0BBJET0i02C0X660AN;V9>XG0YR[702oAc0l0]?EH" 56 | "fO<0Ik?07]i1I0V05>07??0;cbLgK740TFQ\\053V`080^h14" 57 | "NF0Kn:0dTd6L0@0IYc<0DYH0@H6Dhd0TYHak<0f=030:7<=V" 58 | "=l70H=I0ZZA>;0]0kF0ZII0Qn`\\64;D0aI<20jB]\\0c0NO>h" 59 | "g40P?\\0S1SUE0]03Em90KWB0LBUgoS0SEBed401H0c0\\d9HM" 60 | "T[0G@Y00HHgb`010_^0kbb0H:SO7kGc0V2>l0aE130m0lnL=" 62 | }; 63 | 64 | // assume message broadcase cycle is 60s (20 frames) with following MesType order 65 | const int BCNav2Bit::MessageOrder[20] = { 66 | 10, 11, 30, 34, 10, 11, 30, 34, 10, 11, 30, 34, 10, 11, 30, 34, 10, 11, 30, 34, 67 | }; 68 | 69 | BCNav2Bit::BCNav2Bit() 70 | { 71 | } 72 | 73 | BCNav2Bit::~BCNav2Bit() 74 | { 75 | } 76 | 77 | int BCNav2Bit::GetFrameData(GNSS_TIME StartTime, int svid, int Param, int *NavBits) 78 | { 79 | int i; 80 | int sow, MessageType; 81 | unsigned int FrameData[12]; 82 | int Symbols[96]; 83 | 84 | // data channel 85 | if (svid < 1 || svid > 63) 86 | return 1; 87 | 88 | sow = StartTime.MilliSeconds / 3000; // SOW with scale factor 3s 89 | MessageType = MessageOrder[sow % 20]; 90 | ComposeMessage(MessageType, StartTime.Week, sow, svid, FrameData); 91 | AppendCRC(FrameData, 12); 92 | // assign each 6bit into Symbols array 93 | for (i = 0; i < 12; i ++) 94 | { 95 | Symbols[i*4+0] = (FrameData[i] >> 18) & 0x3f; 96 | Symbols[i*4+1] = (FrameData[i] >> 12) & 0x3f; 97 | Symbols[i*4+2] = (FrameData[i] >> 6) & 0x3f; 98 | Symbols[i*4+3] = FrameData[i] & 0x3f; 99 | } 100 | LDPCEncode(Symbols, B2a_SYMBOL_LENGTH, B2aMatrixGen); // do LDPC encode 101 | AssignBits(0xe24de8, 24, NavBits); // Preamble 102 | for (i = 0; i < 96; i ++) 103 | AssignBits(Symbols[i], 6, NavBits + 24 + i * 6); // 96 encoded symbols 104 | return 0; 105 | } 106 | 107 | // 288 bits subframe information divided int 12 WORDs 108 | // each WORD has 24bits in 24LSB of unsigned int data in FrameData[] 109 | // bit order is MSB first (from bit23) and least index first 110 | // each 24bits divided into four 6bit symbols in LDPC encode 111 | void BCNav2Bit::ComposeMessage(int MessageType, int week, int sow, int svid, unsigned int FrameData[]) 112 | { 113 | // first fill in PRN/MesType/SOW 114 | FrameData[0] = COMPOSE_BITS(svid, 18, 6); 115 | FrameData[0] |= COMPOSE_BITS(MessageType, 12, 6); 116 | FrameData[0] |= COMPOSE_BITS(sow >> 6, 0, 12); 117 | FrameData[1] = COMPOSE_BITS(sow, 18, 6); 118 | 119 | switch (MessageType) 120 | { 121 | case 10: 122 | FrameData[1] |= COMPOSE_BITS(week, 5, 13); 123 | FrameData[1] |= COMPOSE_BITS(IntegrityFlags[svid-1] >> 5, 2, 3); // B2a DIF/SIF/AIF 124 | FrameData[2] = COMPOSE_BITS(IntegrityFlags[svid-1] >> 13, 0, 2); // SISMAI 125 | FrameData[2] |= COMPOSE_BITS(IntegrityFlags[svid-1] >> 11, 22, 2); // SISMAI 126 | FrameData[2] |= COMPOSE_BITS(IntegrityFlags[svid-1] >> 2, 19, 3); // B1C DIF/SIF/AIF 127 | AppendWord(&FrameData[2], 5, Ephemeris1[svid-1], 211); 128 | break; 129 | case 11: 130 | // HS filled with 2 zeros 131 | FrameData[1] |= COMPOSE_BITS(IntegrityFlags[svid-1] >> 5, 13, 3); // B2a DIF/SIF/AIF 132 | FrameData[1] |= COMPOSE_BITS(IntegrityFlags[svid-1] >> 11, 9, 4); // SISMAI 133 | FrameData[1] |= COMPOSE_BITS(IntegrityFlags[svid-1] >> 2, 6, 3); // B1C DIF/SIF/AIF 134 | AppendWord(&FrameData[1], 18, Ephemeris2[svid-1], 222); 135 | break; 136 | case 30: 137 | // HS filled with 2 zeros 138 | FrameData[1] |= COMPOSE_BITS(IntegrityFlags[svid-1] >> 5, 13, 3); // B2a DIF/SIF/AIF 139 | FrameData[1] |= COMPOSE_BITS(IntegrityFlags[svid-1] >> 11, 9, 4); // SISMAI 140 | FrameData[1] |= COMPOSE_BITS(IntegrityFlags[svid-1] >> 2, 6, 3); // B1C DIF/SIF/AIF 141 | AppendWord(&FrameData[1], 18, ClockParam[svid-1], 69); 142 | FrameData[4] |= COMPOSE_BITS(ClockParam[svid-1][3] >> 1, 0, 9); // IODC 143 | FrameData[5] = COMPOSE_BITS(ClockParam[svid-1][3], 23, 1); // IODC 144 | FrameData[6] = FrameData[7] = FrameData[8] = FrameData[9] = FrameData[10] = 0; // fill rest of 143bits with 0 145 | break; 146 | case 34: 147 | // HS filled with 2 zeros 148 | FrameData[1] |= COMPOSE_BITS(IntegrityFlags[svid-1] >> 5, 13, 3); // B2a DIF/SIF/AIF 149 | FrameData[1] |= COMPOSE_BITS(IntegrityFlags[svid-1] >> 11, 9, 4); // SISMAI 150 | FrameData[1] |= COMPOSE_BITS(IntegrityFlags[svid-1] >> 2, 6, 3); // B1C DIF/SIF/AIF 151 | // SISAI filled with 22 zeros 152 | FrameData[2] = 0; 153 | AppendWord(&FrameData[2], 16, ClockParam[svid-1], 69); 154 | FrameData[4] |= COMPOSE_BITS(ClockParam[svid-1][3], 1, 10); // IODC 155 | FrameData[6] = FrameData[7] = FrameData[8] = FrameData[9] = FrameData[10] = 0; // fill rest of 121bits with 0 156 | break; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/BCNav3Bit.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // BCNav3Bit.h: 3 | // Implementation of navigation bit synthesis class for B-CNAV3 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #include 10 | #include "ConstVal.h" 11 | #include "BCNav3Bit.h" 12 | 13 | const char BCNav3Bit::B2bMatrixGen[B2b_SYMBOL_LENGTH*B2b_SYMBOL_LENGTH+1] = { 14 | "nXGb3[3O=iTXeNSoUElQT5ORV7NkfXXf4cY?je6GhghdCLgg`UViO>0DegkheCFEYO68^:@A\\kimGdkZZ" 15 | "ITMHn67]^=W_G6lbP_idWU]H7e6H>E8d?lS@@`eje2VA@`Uh9NL=LQhD`M9V`ZAc4]oGh2M5RTkgj:JXM" 16 | ">N:P]^LE_79\\]JPUZSjD9TfnS=_g5\\9;AE4E246o644HKd>D95:f:JDF87g>oKoXIWhfDJ7b^NN?DaT58" 17 | "XF5@>HmD3?VFg_ZCG`Ml^2DbKW_jieFl[[]\\1g^5^2dC\\J2QUEK?a=0Wg24dg3n`]DLA:T1IojGV5bj=S" 18 | "adnR`Yjl<21P5YFQkQ:81W6RjKYSgP18^l>l97KoKBB_;?WI=;]2]VIcTn=o73Hb?iS6IVnKYd\\Joh4UT" 19 | "FLeDZ2\\aCLMbZdDmQl[YMg=OlnJE6bb6BaGa`ZCeCSF?WmSYMkeLeo0I5SEFe6Ek5" 20 | "1Em>DR]e`846DRK2Y2XW4@H>]_R:I64Pne;eTL_i_;;j\\liWd\\b8bNW9FmdiLGFfiL1jl2BiT7hWYYW`KU7dcOQO[:oAF[[?aQPQ;0eE[h:cA]2UBXR1359IhP@QohaE" 22 | "[H=X1I9djGZHC:7E>b8OL\\dXSl:XBoHOA7V`FCL=L\\YE`C\\;@RSGTk0lC\\KYCmcbVd2iJ6F?U_>J=NXkW" 23 | "3o4]lU@LC4<:lU]6h6?Z<`XBdbCN[:eb7SoEWHGl9WWD;o2iU0?=WRH7l_O>hSHmV4kMUL5RZJ8[Z=G5`j1HhHg0oG5:aGTPkbRf;jIeO3X4AYncme" 26 | "UYVH=m9O]cFM=ZHGnXb?FKgaXE]WCMFfLOJOP3SQS33:jGU?FCVYVZ?_63WUQjQNJ[Bg?ZcdmYYe?4KC6" 27 | "_a\\hETEfUgVaP4nMC;8IVof<1H4@eaae=:3QRPZ\\575BQS77OD1gY`0iP7>5PQN;3fZJKmd6l@gj\\B@FF" 28 | "7XeZK[6RFhLk;[2>J>MUL5RZ68[Z[3?UFg_@JE`M:UBKb`WfjKFFTY[][1235327<\\J2:US5?5=:;42j7a\\nD]bLK:=RIGj?V5iBS4" 30 | "J6bKagc=_E[6DSAdR]5G7;=VH?S:UC6GneXogO5ZMTBKIO39G9bFBV_o5?LmfjC[c]_Xd>aOl6NLQ;2>" 32 | "9Zhk]7]UY;HZinJB<>o\\HdU1^2nmDQZ\\_PaGViIhH?@RG8??=3^;X40Ei?N@iGS>aUIMc[jQ5m7iBQR" 34 | "YXH2_[A=FeLB_I2bJ6K`Lc;Z6]Ff;BBUl=M=ia8H8aaPTbY`LA[BFnR@fVacnUY7]ll]6;LYW>5mZ=`^kB==XFm4m90NJ=7`>kMnLc5`i8Hhj742m^7oo" 36 | "Hc3FkTZ8DdSQ^Gm8D>Z5Z2FGOaCBhD4TmGnbSASYAhJhAAU7HJFG7;^;NjAShkB6[o^PU3RO;6=haZQ^n5i[;K8mEXog>6C4UE2CDb@ZB:10doCV4oEHRmhgfLJ_i`n39>Yn77" 40 | "k`V=Bb4gUAYC;bme]eF7Y6l=4abK8Lj7XgdggJa?aOO1oM6PdM[NQNfSZG1K`dUCggjKeoA>" 42 | "PiGbe[3O=i`XeNbLUElQT5ORE7?kfXXf4cY?je=G=gPdCLgg`UGiG>0D]gkPeCFOYR6P^a@A\\kimGdkZ]" 43 | "ZSdV4WTE1O^S?XLGh=Po^fEV:eXV;iSo7LN5K?cdcfRG5?f\\3>FOFY0e?f_R?a9=NE8Q3HKlBjh[dkVYJ" 44 | "X@Sjh_m\\R?Veh_ZCKCclVNAjm^_LieVlH\\]\\Jg^5^ddnE;5Q4Ea?aTQW[S45gYg1;DLAQTS^_@G85bN=[" 45 | "7?5@gH>[3?UFg_@JE`M:UBDb`WfjiFFiY[][1g35327<\\J22US5?5=0;42j7g\\nD]bLK:NRIGj?V5ijS4" 46 | "T^UabLXBR\\F^QmH;`hifSlBan8maCM^f661ONQSUSl3;OQl?d4kMUL5RZ68[Z=G5`:1HhHg`oGe:aGTPkbRf;`IeO3X4AYncme" 48 | "nJO;SeoN6OQ@SC;alaH]Q23AMX6`j@Q4GN9NU9\\R\\99fTVn]Qjg3gC]8BO`nRPRIVDm3]CO:eJJ=]L2jB" 49 | "e9<1YPY`4D[9fFLI=3\\C[h`jTgFKO99ONW_;mfA=TD`]0UfiKbfBZ3_jAlHckMGKD:<@K66" 50 | ":4H[>KS;YHXl>9[DFDRiXVe_nUY7olX?6;=;W=Z`Z==^dB`iXdmem9iNJH7`MkMaBc:ei9HhK442i]VoJ" 51 | "H2od`^`iE2KN7YX9;OA8KCihkcYRgNNg3T>eb7SoEWHGl9WWD;o2iU0?7WRB7l_O>hSHmV4kMUL5RZ68[Z=G5`j1HhHg`oGe:aGTPkbRf;jIeO3X4AYncme" 53 | "@R2OCa=8o63R9hjPgQcH]Z8;>FhUJTRH__B7E9V2]ZfP7KZ[lM>6d\\0A9ZGf9obQB8V:4YDTWUg32;U\\1" 54 | "nbZk3NKC@im2c" 55 | "fURVO@_2NU]JOZVQ4YG7]b[mYiE^[JJ`F2n2:DNRNDfkdQD7]ARURa7=XD^fSd6>nmM[7aKo@^UcR`^AX" 56 | "UMVH9D9NSYiM=I\\knXbRiKN[gEIW4MM4LOJ]P=BV^3U:jG33FngYNZ0_=3W^=jQXJNBh?fcd1WYeV:WCC" 57 | "E`=C2DB[Q^GWaD>Z5W@nGK[CBhDCTm`nR>?SSVhJh=C[3<:U=eDVJS3Ha7f7Kf]9]ffbMA2[3Jd:dY[`_1V2959ENk8:[Y1lhOO^[;_AFQnLAcO" 60 | "A:l[KJPbT>7UKJQRWRfh7`B[P2J\\3U7h?bZboE2k2mm8a]k6gOPlldcU\\U@0GklaIVO:B14Wn9K]2`a\\FUCack" 62 | "HaPFYT6UN5SCYTW`9`AOS:?FZJTeGCSD8U]Ug\\J3J]][bh3OSb^5^LOMIPm3\\V\\nhQVNAjm^RLieVlH\\d\\Jd^5^ddnE;5QVEa?aTQW[S45gYg1;9XAQTSU_@@8QbNi[" 66 | "LlD3hShCWi]lND`]::" 67 | ";O9QWiCTIK\\O1i`FScd_\\kTQo5iQVjO_<`2nn1595k6Fn1kN[H?K?P0@1ke61gDc^T=][GU4XASB98fPU" 68 | ";O9QWiCTIK\\c]i`FScd_\\kTQo5iQVjO_<`2nn1595k6Fn1kN[H?K?EN@1ke61gDc^T=][GU4XASB98fPU" 69 | "9kL6bncGjLTfb[6B^B]CTFMm:HjIDfT\\7G@G8@HhH@@S3EhCT3XMX[CKPLNhi_iVEJ9MC[L=nkklC1FDP" 70 | "?`@mN2N3a`WL;9AM]4B5WR3KcfUTELLEXgFU^;l@aO?1hMOOY]@`3_0>;OT?;hJ4FKl?P7V\\dT`H@1T88" 71 | "_97?nPM4ZfIdnQ?]8A^>IWE6AaZORdI=\\4o4DXlIR797Q>JCfO_<[QfmP99U>SWRC" 72 | "8A1^XiX4n3gAULl@_ahZ5W@nGK[CBhDCTm`nRS?SSVhJhe6gk5" 75 | "ODZIPd\\^WmBDk?Un9[NaBj^ACR?lKYDa2heXMk3ZBjLnX>j_HcCmf70:kjgLkX;[e^34G58YFl9oZAlEE" 76 | "_hF@E4kQdgj;G4XM1M^Ij7J@kV4neWaITQ3QQPV\\V55NDi7A>DYgYmAHPF>\\P=NRifZJAmF64hCL\\<]`F" 77 | "MQKcZ;Z_9]?Q38CjVF@b?m_H2`8PY:j15>>nX2]AS0a3>L:31lF6_Gdfi[8DdSQ=Gm81>H5B2FGOaCB6Q4ammnbS@SYAh;hAJUiHJFGT;M;<_@MBFGccGVIKBn\\e31ol4UgooRb353j0hmoFl\\U[1A5P@HC>_8R8DJ@3Shbj>XWH@6mA\\AF\\jQj\\\\]feQJ@f=P=kJTKaEQc`cde24SJkaj>GGZJB3WK" 83 | ";O9QWiCTIK\\c]i`FScd_\\kTQC5iQVjO_<`2nn1595G6Fn1kN[H?K?EN@1Ue61gDc^T=]NGU4XASB98fPU" 84 | "Y5Na\\=kIBNRc\\jaAbA;6R>9d@MBFPcRLVIoIno1[1oo4igl6Ri393j6hmNFl[U[Pm" 85 | ";>k:F?FYX>2IEJMoaNdh2jY^WOJ[3II39iZ=HE\\km`;Vbo``_ak>Yn0]E`[mEb8NZ^\\BegTG@[>7kV[ll" 86 | "fL;8[2lKJjMT=2D_Q_G]MRK8lC28kbi]BaPaa@CFCSS?a@RY7:ejeoY<@;7F@W?AmKE=Yo;3NLX\\F6gH;" 87 | "JM;>8DdSQ=Gm8<>H5B2FGOaCB6Q4TmmnbS@SYAh;hAAUiHJFGT;M;SdJ]_Sgg" 89 | "i?nAHGMm[1Q?Re;aF^Y4\\bmAlheAj@?4B;7NIR\\n\\b9aNRb]:Tl1gc0hRbW9RPf^7m`3oCI>_JFQnLAcO" 90 | "7XeZ_[6=FhLB_[2>J>MULc;Z68[fmYiE^`JJ`F2nE:ONRNDfkdQDD]ARURa0=XD^fOd6>nmM[79Ko<^UcR`^AX" 92 | "Gb_9Qoo[]6dQNQK[DFDL?XQe_nZKcolX?6;j;WMZ`Z==^dBQi1dmCm9iIJH1`MkAaB57ei9HgK4E2`]VbJ" 95 | }; 96 | 97 | // assume message broadcase cycle is 6s (6 frames) with following MesType order 98 | const int BCNav3Bit::MessageOrder[6] = { 99 | 10, 0, 30, 0, 40, 0, 100 | }; 101 | 102 | 103 | BCNav3Bit::BCNav3Bit() 104 | { 105 | } 106 | 107 | BCNav3Bit::~BCNav3Bit() 108 | { 109 | } 110 | 111 | int BCNav3Bit::GetFrameData(GNSS_TIME StartTime, int svid, int Param, int *NavBits) 112 | { 113 | int i; 114 | int sow; 115 | unsigned int FrameData[21]; 116 | int Symbols[162]; 117 | 118 | // data channel 119 | if (svid < 1 || svid > 63) 120 | return 1; 121 | 122 | sow = StartTime.MilliSeconds / 1000; 123 | ComposeMessage(MessageOrder[sow % 6], StartTime.Week, sow, svid, FrameData); 124 | AppendCRC(FrameData, 21); 125 | // assign each 6bit into Symbols array 126 | Symbols[0] = FrameData[0] & 0x3f; 127 | for (i = 0; i < 20; i ++) 128 | { 129 | Symbols[i*4+1] = (FrameData[i+1] >> 18) & 0x3f; 130 | Symbols[i*4+2] = (FrameData[i+1] >> 12) & 0x3f; 131 | Symbols[i*4+3] = (FrameData[i+1] >> 6) & 0x3f; 132 | Symbols[i*4+4] = FrameData[i+1] & 0x3f; 133 | } 134 | LDPCEncode(Symbols, B2b_SYMBOL_LENGTH, B2bMatrixGen); // do LDPC encode 135 | AssignBits(0xeb90, 16, NavBits); // Preamble 136 | AssignBits(svid, 6, NavBits + 16); // PRN 137 | AssignBits(0, 6, NavBits + 22); // reserved 138 | for (i = 0; i < 162; i ++) 139 | AssignBits(Symbols[i], 6, NavBits + 28 + i * 6); // 162 encoded symbols 140 | return 0; 141 | } 142 | 143 | // 486 bits subframe information divided int 21 WORDs 144 | // each WORD has 24bits in 24LSB of unsigned int data in FrameData[] 145 | // bit order is MSB first (from bit23) and least index first 146 | // each 24bits divided into four 6bit symbols in LDPC encode 147 | // FrameData[0] only has 6 valid bits in LSB 148 | void BCNav3Bit::ComposeMessage(int MessageType, int week, int sow, int svid, unsigned int FrameData[]) 149 | { 150 | // first fill in MessageType 151 | FrameData[0] = MessageType & 0x3f; 152 | 153 | switch (MessageType) 154 | { 155 | case 0: 156 | FrameData[1] = COMPOSE_BITS(sow, 4, 20); 157 | memset(&FrameData[2], 0x5a, sizeof(unsigned int) * 18); 158 | break; 159 | case 10: 160 | AppendWord(&FrameData[1], 16, Ephemeris1[svid-1], 211); // with extra IODE put in FrameData[1] 161 | AppendWord(&FrameData[10], 11, Ephemeris2[svid-1], 222); 162 | FrameData[19] |= COMPOSE_BITS(IntegrityFlags[svid-1] >> 8, 4, 3); // B2a DIF/SIF/AIF 163 | FrameData[19] |= COMPOSE_BITS(IntegrityFlags[svid-1] >> 11, 0, 4); // SISMAI 164 | FrameData[1] = COMPOSE_BITS(sow, 4, 20); 165 | break; 166 | case 30: 167 | FrameData[1] = COMPOSE_BITS(sow, 4, 20); 168 | FrameData[1] |= COMPOSE_BITS(week >> 9, 0, 4); 169 | FrameData[2] = COMPOSE_BITS(week, 15, 9); 170 | AppendWord(&FrameData[2], 13, ClockParam[svid-1], 69); 171 | FrameData[5] |= COMPOSE_BITS(TgsIscParam[svid-1][2], 2, 12); 172 | AppendWord(&FrameData[5], 22, BdGimIono, 74); 173 | AppendWord(&FrameData[9], 0, BdtUtcParam, 97); 174 | AppendWord(&FrameData[13], 1, EopParam, 138); 175 | FrameData[19] = 0; // SISAI_oc, SISAI_oe and HS filled with 0 176 | break; 177 | case 40: 178 | FrameData[1] = COMPOSE_BITS(sow, 4, 20); 179 | memset(&FrameData[2], 0, sizeof(unsigned int) * 18); 180 | break; 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/ComplexNumber.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // ComplexNumber.h: 3 | // complex number operator implementation 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #include 10 | #include "ComplexNumber.h" 11 | 12 | complex_number::complex_number(double real_part, double imag_part) : real(real_part), imag(imag_part) 13 | { 14 | } 15 | 16 | complex_number complex_number::operator + (const complex_number data) const 17 | { 18 | complex_number result = *this; 19 | result += data; 20 | return result; 21 | } 22 | 23 | void complex_number::operator += (const complex_number data) 24 | { 25 | this->real += data.real; 26 | this->imag += data.imag; 27 | } 28 | 29 | complex_number complex_number::operator - (const complex_number data) const 30 | { 31 | complex_number result = *this; 32 | result -= data; 33 | return result; 34 | } 35 | 36 | void complex_number::operator -= (const complex_number data) 37 | { 38 | this->real -= data.real; 39 | this->imag -= data.imag; 40 | } 41 | 42 | complex_number complex_number::operator * (const complex_number data) const 43 | { 44 | complex_number result = *this; 45 | result *= data; 46 | return result; 47 | } 48 | 49 | void complex_number::operator *= (const complex_number data) 50 | { 51 | complex_number temp = *this; 52 | 53 | this->real = temp.real * data.real - temp.imag * data.imag; 54 | this->imag = temp.real * data.imag + temp.imag * data.real; 55 | } 56 | 57 | complex_number complex_number::operator * (const double data) 58 | { 59 | complex_number result = *this; 60 | result *= data; 61 | return result; 62 | } 63 | 64 | void complex_number::operator *= (const double data) 65 | { 66 | complex_number temp = *this; 67 | 68 | this->real = temp.real * data; 69 | this->imag = temp.imag * data; 70 | } 71 | 72 | double complex_number::abs() 73 | { 74 | return sqrt(this->real * this->real + this->imag * this->imag); 75 | } 76 | 77 | complex_number complex_number::conj() 78 | { 79 | return complex_number(real, -imag); 80 | } 81 | -------------------------------------------------------------------------------- /src/GNavBit.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // LNavBit.h: 3 | // Implementation of navigation bit synthesis class for LNAV 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #include 10 | #include 11 | #include "ConstVal.h" 12 | #include "GNavBit.h" 13 | 14 | const unsigned int GNavBit::CheckSumTable[8][3] = { 15 | { 0x000aaaab, 0x55555556, 0xaaad5b01, }, 16 | { 0x000ccccd, 0x9999999b, 0x33366d02, }, 17 | { 0x0000f0f1, 0xe1e1e1e3, 0xc3c78e04, }, 18 | { 0x0000ff01, 0xfe01fe03, 0xfc07f008, }, 19 | { 0x000f0001, 0xfffe0003, 0xfff80010, }, 20 | { 0x00000001, 0xfffffffc, 0x00000020, }, 21 | { 0x000ffffe, 0x00000000, 0x00000040, }, 22 | { 0x000fffff, 0xffffffff, 0xffffffff, }, 23 | }; 24 | 25 | GNavBit::GNavBit() 26 | { 27 | memset(StringEph, 0x0, sizeof(StringEph)); 28 | memset(StringAlm, 0x0, sizeof(StringAlm)); 29 | } 30 | 31 | GNavBit::~GNavBit() 32 | { 33 | } 34 | 35 | int GNavBit::GetFrameData(GNSS_TIME StartTime, int svid, int Param, int *NavBits) 36 | { 37 | int i, string, frame, bit; 38 | unsigned int* data, Stream[3]; 39 | 40 | if (svid < 1 || svid > 24) 41 | return 1; 42 | 43 | string = StartTime.MilliSeconds / 2000; 44 | frame = (string / 15) % 2880; // frame within one day 45 | string %= 15; 46 | 47 | if (string < 4) // Ephemeris string 48 | data = StringEph[svid - 1][string]; 49 | else 50 | data = StringAlm[frame % 5][string - 4]; 51 | 52 | // left shift 8bit for check sum space and add word m as string number 53 | Stream[0] = (data[0] & 0xfffff); 54 | Stream[1] = data[1]; 55 | Stream[2] = data[2] & 0xffffff00; 56 | if (string == 0) // first string, place tk here 57 | { 58 | Stream[0] |= ((frame / 120) << 7); // hours 59 | Stream[0] |= (frame % 120); // 30 seconds 60 | } 61 | else if (string >= 4) 62 | Stream[0] |= (string + 1) << 16; 63 | 64 | // add check sum and put 85 bits to NavBits position 85~169 (leave first 85 places for meander code expansion) 65 | Stream[2] |= CheckSum(Stream); 66 | AssignBits(Stream[0], 21, NavBits + 85); 67 | AssignBits(Stream[1], 32, NavBits + 106); 68 | AssignBits(Stream[2], 32, NavBits + 138); 69 | // do relative coding 70 | bit = 0; // first bit of the string is always 0 71 | for (i = 86; i < 170; i++) 72 | bit = NavBits[i] = (bit ^ NavBits[i]); 73 | // expand to meander code 74 | for (i = 0; i < 85; i++) 75 | { 76 | NavBits[i * 2] = NavBits[i + 85]; 77 | NavBits[i * 2 + 1] = 1 - NavBits[i + 85]; 78 | } 79 | // append time mark 80 | AssignBits(0x3e375096, 30, NavBits + 170); 81 | 82 | return 0; 83 | } 84 | 85 | int GNavBit::SetEphemeris(int svid, PGPS_EPHEMERIS Eph) 86 | { 87 | if (svid < 1 || svid > 24 || !Eph || !Eph->flag) 88 | return 0; 89 | ComposeStringEph((PGLONASS_EPHEMERIS)Eph, StringEph[svid-1]); 90 | return svid; 91 | } 92 | 93 | int GNavBit::SetAlmanac(GPS_ALMANAC Alm[]) 94 | { 95 | PGLONASS_ALMANAC GloAlm = (PGLONASS_ALMANAC)Alm; 96 | int i, frame, string; 97 | 98 | for (i = 0; i < 24; i ++) 99 | if (GloAlm->flag == 1) 100 | break; 101 | if (i == 24) 102 | return 0; 103 | 104 | // compose string 5 for each frame (t_c and t_GPS set to 0) 105 | StringAlm[0][0][0] = StringAlm[1][0][0] = StringAlm[2][0][0] = StringAlm[3][0][0] = StringAlm[4][0][0] = (5 << 16) | COMPOSE_BITS(GloAlm[i].day, 5, 11); 106 | StringAlm[0][0][1] = StringAlm[1][0][1] = StringAlm[2][0][1] = StringAlm[3][0][1] = StringAlm[4][0][1] = COMPOSE_BITS(GloAlm[i].leap_year >> 1, 0, 4); 107 | StringAlm[0][0][2] = StringAlm[1][0][2] = StringAlm[2][0][2] = StringAlm[3][0][2] = StringAlm[4][0][2] = ((GloAlm[i].leap_year & 1) << 31) | 0x100; 108 | for (i = 0; i < 24; i ++) 109 | { 110 | frame = i / 5; 111 | string = (i % 5) * 2 + 6; 112 | ComposeStringAlm((PGLONASS_ALMANAC)Alm + i, i + 1, StringAlm[frame][string-5], StringAlm[frame][string-4]); 113 | StringAlm[frame][string - 5][0] |= ((string << 16) | ((i + 1) << 8)); 114 | StringAlm[frame][string - 4][0] |= ((string + 1) << 16); 115 | } 116 | 117 | return 0; 118 | } 119 | 120 | int GNavBit::SetIonoUtc(PIONO_PARAM IonoParam, PUTC_PARAM UtcParam) 121 | { 122 | return 0; 123 | } 124 | 125 | int GNavBit::ComposeStringEph(PGLONASS_EPHEMERIS Ephemeris, unsigned int String[][3]) 126 | { 127 | unsigned int UintValue; 128 | 129 | // string 1 130 | String[0][0] = (1 << 16) | COMPOSE_BITS(Ephemeris->P, 12, 2); 131 | // String[0][0] |= COMPOSE_BITS(Ephemeris->tk, 0, 12); 132 | UintValue = UnscaleUint(fabs(Ephemeris->vx) / 1000, -20); UintValue |= (Ephemeris->vx < 0) ? (1 << 23) : 0; 133 | String[0][1] = COMPOSE_BITS(UintValue, 8, 24); 134 | UintValue = UnscaleUint(fabs(Ephemeris->ax) / 1000, -30); UintValue |= (Ephemeris->ax < 0) ? (1 << 4) : 0; 135 | String[0][1] |= COMPOSE_BITS(UintValue, 3, 5); 136 | UintValue = UnscaleUint(fabs(Ephemeris->x) / 1000, -11); UintValue |= (Ephemeris->x < 0) ? (1 << 26) : 0; 137 | String[0][1] |= COMPOSE_BITS(UintValue >> 24, 0, 3); 138 | String[0][2] = COMPOSE_BITS(UintValue, 8, 24); 139 | // string 2 140 | String[1][0] = (2 << 16) | COMPOSE_BITS(Ephemeris->Bn, 13, 3); 141 | String[1][0] |= COMPOSE_BITS(Ephemeris->P >> 2, 12, 1); 142 | UintValue = Ephemeris->tb / 900; 143 | String[1][0] |= COMPOSE_BITS(UintValue, 5, 7); 144 | UintValue = UnscaleUint(fabs(Ephemeris->vy) / 1000, -20); UintValue |= (Ephemeris->vy < 0) ? (1 << 23) : 0; 145 | String[1][1] = COMPOSE_BITS(UintValue, 8, 24); 146 | UintValue = UnscaleUint(fabs(Ephemeris->ay) / 1000, -30); UintValue |= (Ephemeris->ay < 0) ? (1 << 4) : 0; 147 | String[1][1] |= COMPOSE_BITS(UintValue, 3, 5); 148 | UintValue = UnscaleUint(fabs(Ephemeris->y) / 1000, -11); UintValue |= (Ephemeris->y < 0) ? (1 << 26) : 0; 149 | String[1][1] |= COMPOSE_BITS(UintValue >> 24, 0, 3); 150 | String[1][2] = COMPOSE_BITS(UintValue, 8, 24); 151 | // string 3 152 | String[2][0] = (3 << 16) | COMPOSE_BITS(Ephemeris->P >> 3, 15, 1); 153 | UintValue = UnscaleUint(fabs(Ephemeris->gamma), -40); UintValue |= (Ephemeris->gamma < 0) ? (1 << 10) : 0; 154 | String[2][0] |= COMPOSE_BITS(UintValue, 4, 11); 155 | String[2][0] |= COMPOSE_BITS(Ephemeris->P >> 5, 0, 3); 156 | UintValue = UnscaleUint(fabs(Ephemeris->vz) / 1000, -20); UintValue |= (Ephemeris->vz < 0) ? (1 << 23) : 0; 157 | String[2][1] = COMPOSE_BITS(UintValue, 8, 24); 158 | UintValue = UnscaleUint(fabs(Ephemeris->az) / 1000, -30); UintValue |= (Ephemeris->az < 0) ? (1 << 4) : 0; 159 | String[2][1] |= COMPOSE_BITS(UintValue, 3, 5); 160 | UintValue = UnscaleUint(fabs(Ephemeris->z) / 1000, -11); UintValue |= (Ephemeris->z < 0) ? (1 << 26) : 0; 161 | String[2][1] |= COMPOSE_BITS(UintValue >> 24, 0, 3); 162 | String[2][2] = COMPOSE_BITS(UintValue, 8, 24); 163 | // string 4 164 | UintValue = UnscaleUint(fabs(Ephemeris->tn), -30); UintValue |= (Ephemeris->tn < 0) ? (1 << 21) : 0; 165 | String[3][0] = (4 << 16) | COMPOSE_BITS(UintValue >> 6, 0, 16); 166 | String[3][1] = COMPOSE_BITS(UintValue, 26, 6); 167 | UintValue = UnscaleUint(fabs(Ephemeris->dtn), -30); UintValue |= (Ephemeris->dtn < 0) ? (1 << 4) : 0; 168 | String[3][1] |= COMPOSE_BITS(UintValue, 21, 5); 169 | String[3][1] |= COMPOSE_BITS(Ephemeris->En, 16, 5); 170 | String[3][1] |= COMPOSE_BITS(Ephemeris->P >> 4, 1, 1); 171 | String[3][1] |= COMPOSE_BITS(Ephemeris->Ft >> 3, 0, 1); 172 | String[3][2] = COMPOSE_BITS(Ephemeris->Ft, 29, 3); 173 | String[3][2] |= COMPOSE_BITS(Ephemeris->day, 15, 11); 174 | String[3][2] |= COMPOSE_BITS(Ephemeris->n, 10, 5); 175 | String[3][2] |= COMPOSE_BITS(Ephemeris->M, 8, 2); 176 | 177 | return 0; 178 | } 179 | 180 | int GNavBit::ComposeStringAlm(PGLONASS_ALMANAC Almanac, int slot, unsigned int StreamEven[3], unsigned int StreamOdd[3]) 181 | { 182 | unsigned int UintValue; 183 | 184 | if (!Almanac->flag) 185 | { 186 | StreamEven[2] = StreamEven[1] = StreamEven[0] = StreamOdd[2] = StreamOdd[1] = StreamOdd[0] = 0; 187 | return 0; 188 | } 189 | // first string 190 | StreamEven[0] = COMPOSE_BITS(Almanac->flag, 15, 1); 191 | StreamEven[0] |= COMPOSE_BITS(1, 13, 2); // Mn=01 for GLONASS-M 192 | StreamEven[0] |= COMPOSE_BITS(slot, 8, 5); 193 | UintValue = UnscaleInt(fabs(Almanac->clock_error), -18); UintValue |= (Almanac->clock_error < 0) ? (1 << 9) : 0; 194 | StreamEven[0] |= COMPOSE_BITS((UintValue >> 2), 0, 8); 195 | StreamEven[1] = COMPOSE_BITS(UintValue, 30, 2); 196 | UintValue = UnscaleUint(fabs(Almanac->lambda), -20); UintValue |= (Almanac->lambda < 0) ? (1 << 20) : 0; 197 | StreamEven[1] |= COMPOSE_BITS(UintValue, 9, 21); 198 | UintValue = UnscaleUint(fabs(Almanac->di), -20); UintValue |= (Almanac->di < 0) ? (1 << 17) : 0; 199 | StreamEven[1] |= COMPOSE_BITS(UintValue >> 9, 0, 9); 200 | StreamEven[2] = COMPOSE_BITS(UintValue, 23, 9); 201 | UintValue = UnscaleUint(Almanac->ecc, -20); 202 | StreamEven[2] |= COMPOSE_BITS(UintValue, 8, 15); 203 | // second string 204 | UintValue = UnscaleUint(fabs(Almanac->w), -15); UintValue |= (Almanac->w < 0) ? (1 << 15) : 0; 205 | StreamOdd[0] = COMPOSE_BITS(UintValue, 0, 16); 206 | UintValue = UnscaleUint(fabs(Almanac->t), -5); 207 | StreamOdd[1] = COMPOSE_BITS(UintValue, 11, 21); 208 | UintValue = UnscaleUint(fabs(Almanac->dt), -9); UintValue |= (Almanac->dt < 0) ? (1 << 21) : 0; 209 | StreamOdd[1] |= COMPOSE_BITS(UintValue >> 11, 0, 11); 210 | StreamOdd[2] = COMPOSE_BITS(UintValue, 21, 11); 211 | UintValue = UnscaleUint(fabs(Almanac->dt_dot), -14); UintValue |= (Almanac->dt < 0) ? (1 << 6) : 0; 212 | StreamOdd[2] |= COMPOSE_BITS(UintValue, 14, 7); 213 | StreamOdd[2] |= COMPOSE_BITS(Almanac->freq, 9, 5); 214 | return 0; 215 | } 216 | 217 | // calculate check sum on data 218 | // the data bit number from 84 to 1 placed are bit19~0 in data[0] 219 | // then bit31~0 in data[1] and bit31~0 in data[2] 220 | // put the hamming code bits in 8 LSB in data[2] will return 0 if check success 221 | // or put 0 in 8 LSB of data[0] will return humming code bits 222 | unsigned int GNavBit::CheckSum(unsigned int Data[3]) 223 | { 224 | unsigned int CheckSumValue = 0; 225 | unsigned int xor_value; 226 | int i; 227 | 228 | Data[2] &= ~0xf; // clear checksum bits 229 | // calculate parity value 230 | for (i = 0; i < 8; i ++) 231 | { 232 | xor_value = (Data[0] & CheckSumTable[i][0]) ^ (Data[1] & CheckSumTable[i][1]) ^ ((Data[2] | CheckSumValue) & CheckSumTable[i][2]); 233 | // calculate bit 1 number 234 | xor_value = (xor_value & 0x55555555) + ((xor_value & 0xaaaaaaaa) >> 1); 235 | xor_value = (xor_value & 0x33333333) + ((xor_value & 0xcccccccc) >> 2); 236 | xor_value = (xor_value & 0x0f0f0f0f) + ((xor_value & 0xf0f0f0f0) >> 4); 237 | xor_value = (xor_value & 0x000f000f) + ((xor_value & 0x0f000f00) >> 8); 238 | xor_value = (xor_value & 0x0000000f) + ((xor_value & 0x000f0000) >> 16); 239 | CheckSumValue |= ((xor_value & 1) << i); 240 | } 241 | 242 | return CheckSumValue; 243 | } 244 | -------------------------------------------------------------------------------- /src/GnssTime.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // GnssTime.cpp: 3 | // Convertion between GNSS time 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | #include 9 | 10 | #include "ConstVal.h" 11 | #include "BasicTypes.h" 12 | 13 | static int DaysAcc[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; 14 | 15 | unsigned int InsertTime[] = { 46828800, 78364801, 109900802, 173059203, 252028804, 315187205, 16 | 346723206, 393984007, 425520008, 457056009, 504489610, 551750411, 17 | 599184012, 820108813, 914803214, 1025136015, 1119744016, 1167264017 }; 18 | 19 | UTC_TIME GlonassTimeToUtc(GLONASS_TIME GlonassTime); 20 | GLONASS_TIME UtcToGlonassTime(UTC_TIME UtcTime); 21 | 22 | BOOL GetLeapSecond(unsigned int Seconds, int &LeapSecond) 23 | { 24 | int len = sizeof(InsertTime) / sizeof(unsigned int), i; 25 | 26 | for (i = 0; i < len; i ++) 27 | { 28 | if (Seconds <= InsertTime[i]) 29 | { 30 | LeapSecond = i; 31 | return (Seconds == InsertTime[i]); 32 | } 33 | } 34 | LeapSecond = len; 35 | return FALSE; 36 | } 37 | 38 | // This program handles the date from Jan. 1, 1984 00:00:00.00 UTC till year 2099 39 | // date after 2020/12/31 may not have correct leap second correction 40 | UTC_TIME GpsTimeToUtc(GNSS_TIME GnssTime, BOOL UseLeapSecond = TRUE) 41 | { 42 | int Days, LeapSecond = 0; 43 | BOOL AtLeapSecond = UseLeapSecond; 44 | GLONASS_TIME GlonassTime; 45 | UTC_TIME time; 46 | 47 | // calculate total days and seconds 48 | // to prevent seconds less than zero after leap second adjust 49 | // add seconds of one week 50 | GlonassTime.Day = (GnssTime.Week - 1) * 7; 51 | GlonassTime.MilliSeconds = GnssTime.MilliSeconds + 604800000; 52 | GlonassTime.SubMilliSeconds = GnssTime.SubMilliSeconds; 53 | if (UseLeapSecond) 54 | AtLeapSecond = GetLeapSecond((unsigned int)(GnssTime.Week * 604800 + GnssTime.MilliSeconds / 1000), LeapSecond); 55 | GlonassTime.MilliSeconds -= (AtLeapSecond ? (LeapSecond + 1) : LeapSecond) * 1000; 56 | 57 | Days = GlonassTime.MilliSeconds / 86400000; 58 | GlonassTime.Day += Days; 59 | GlonassTime.MilliSeconds -= Days * 86400000; 60 | GlonassTime.Day -= 208 * 7; 61 | // calculate year 62 | GlonassTime.LeapYear = GlonassTime.Day / (366 + 365 * 3); 63 | GlonassTime.Day -= GlonassTime.LeapYear * (366 + 365 * 3); 64 | GlonassTime.LeapYear -= 2; 65 | GlonassTime.Day += 1; 66 | GlonassTime.MilliSeconds += 10800000; 67 | 68 | time = GlonassTimeToUtc(GlonassTime); 69 | if (AtLeapSecond) 70 | time.Second += 1; 71 | 72 | return time; 73 | } 74 | 75 | GNSS_TIME UtcToGpsTime(UTC_TIME UtcTime, BOOL UseLeapSecond = TRUE) 76 | { 77 | GLONASS_TIME GlonassTime; 78 | GNSS_TIME time; 79 | int TotalDays, LeapSecond = 0; 80 | BOOL NextDay = (UtcTime.Hour == 0 && UtcTime.Minute == 0 && ((int)UtcTime.Second) == 0); 81 | BOOL AtLeapSecond; 82 | unsigned int TotalSeconds, TempSeconds; 83 | 84 | GlonassTime = UtcToGlonassTime(UtcTime); 85 | TotalDays = (GlonassTime.LeapYear + 3) * (366 + 365 * 3) + GlonassTime.Day - 6; 86 | TotalSeconds = TempSeconds = TotalDays * 86400 + GlonassTime.MilliSeconds / 1000 - 10800; 87 | // time.MilliSeconds = TotalDays * 86400 + GlonassTime.Seconds - 10800.; 88 | // Seconds = (unsigned int)time.Seconds; 89 | if (UseLeapSecond) 90 | { 91 | AtLeapSecond = GetLeapSecond(TempSeconds, LeapSecond); 92 | TempSeconds += LeapSecond; 93 | AtLeapSecond = GetLeapSecond(TempSeconds, LeapSecond); 94 | TotalSeconds += (AtLeapSecond && NextDay) ? (LeapSecond + 1) : LeapSecond; 95 | } 96 | time.Week = TotalSeconds / 604800; 97 | time.MilliSeconds = TotalSeconds - time.Week * 604800; 98 | time.MilliSeconds = time.MilliSeconds * 1000 + GlonassTime.MilliSeconds % 1000; 99 | time.SubMilliSeconds = GlonassTime.SubMilliSeconds; 100 | 101 | return time; 102 | } 103 | 104 | UTC_TIME GlonassTimeToUtc(GLONASS_TIME GlonassTime) 105 | { 106 | int i, Seconds, LeapDay = 0; 107 | UTC_TIME time; 108 | 109 | GlonassTime.MilliSeconds -= 10800000; 110 | if (GlonassTime.MilliSeconds < 0) 111 | { 112 | GlonassTime.MilliSeconds += 86400000; 113 | GlonassTime.Day --; 114 | } 115 | GlonassTime.LeapYear *= 4; 116 | GlonassTime.Day --; 117 | if (GlonassTime.Day >= (366 + 365 * 2)) 118 | { 119 | GlonassTime.Day -= (366 + 365 * 2); 120 | GlonassTime.LeapYear += 3; 121 | } 122 | else if (GlonassTime.Day >= (366 + 365)) 123 | { 124 | GlonassTime.Day -= (366 + 365); 125 | GlonassTime.LeapYear += 2; 126 | } 127 | else if (GlonassTime.Day >= 366) 128 | { 129 | GlonassTime.Day -= 366; 130 | GlonassTime.LeapYear ++; 131 | } 132 | else if (GlonassTime.Day >= 60) 133 | GlonassTime.Day --; 134 | else if (GlonassTime.Day == 59) 135 | LeapDay = 1; 136 | 137 | for (i = 1; i < 12; i ++) 138 | { 139 | if (GlonassTime.Day < DaysAcc[i]) 140 | break; 141 | } 142 | if (LeapDay) 143 | { 144 | time.Month = 2; 145 | time.Day = 29; 146 | } 147 | else 148 | { 149 | time.Month = i; 150 | time.Day = GlonassTime.Day - (DaysAcc[i-1] - 1); 151 | } 152 | time.Year = 1992 + GlonassTime.LeapYear; 153 | Seconds = GlonassTime.MilliSeconds / 1000; 154 | time.Hour = Seconds / 3600; 155 | Seconds -= time.Hour * 3600; 156 | time.Minute = Seconds / 60; 157 | Seconds = GlonassTime.MilliSeconds % 60000; 158 | time.Second = (Seconds + GlonassTime.SubMilliSeconds) / 1000.; 159 | 160 | return time; 161 | } 162 | 163 | GLONASS_TIME UtcToGlonassTime(UTC_TIME UtcTime) 164 | { 165 | int Years, Days; 166 | GLONASS_TIME time; 167 | double MilliSeconds = (UtcTime.Second * 1000); 168 | 169 | time.MilliSeconds = (((UtcTime.Hour * 60) + UtcTime.Minute) * 60000 + (int)MilliSeconds) + 10800000; 170 | time.SubMilliSeconds = MilliSeconds - (int)MilliSeconds; 171 | Years = UtcTime.Year - 1992; 172 | Days = DaysAcc[UtcTime.Month - 1] + UtcTime.Day - 1; 173 | if ((Years % 4) != 0 || Days >= 59) 174 | Days ++; 175 | Days += (Years % 4) * 365; 176 | time.Day = Days + 1; 177 | time.LeapYear = Years / 4; 178 | 179 | return time; 180 | } 181 | 182 | GNSS_TIME UtcToBdsTime(UTC_TIME UtcTime) 183 | { 184 | GNSS_TIME time = UtcToGpsTime(UtcTime); 185 | 186 | if (time.MilliSeconds >= 14000) 187 | { 188 | time.MilliSeconds -= 14000; 189 | time.Week -= 1356; 190 | } 191 | else 192 | { 193 | time.MilliSeconds += (604800000 - 14000); 194 | time.Week -= 1357; 195 | } 196 | 197 | return time; 198 | } 199 | 200 | GNSS_TIME UtcToGalileoTime(UTC_TIME UtcTime) 201 | { 202 | GNSS_TIME time = UtcToGpsTime(UtcTime); 203 | 204 | time.Week -= 1024; 205 | return time; 206 | } 207 | 208 | UTC_TIME BdsTimeToUtc(GNSS_TIME GnssTime) 209 | { 210 | GnssTime.MilliSeconds += 14000; 211 | GnssTime.Week += 1356; 212 | return GpsTimeToUtc(GnssTime); 213 | } 214 | 215 | UTC_TIME GalileoTimeToUtc(GNSS_TIME GnssTime) 216 | { 217 | GnssTime.Week += 1024; 218 | return GpsTimeToUtc(GnssTime); 219 | } 220 | -------------------------------------------------------------------------------- /src/JsonParser.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // JsonParser.cpp: 3 | // JSON stream process class implementation 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #include 10 | #include 11 | #include 12 | #include "JsonParser.h" 13 | 14 | JsonStream::JsonStream() 15 | { 16 | RootObject = NULL; 17 | stream[0] = '\0'; 18 | p = stream; 19 | } 20 | 21 | JsonStream::~JsonStream() 22 | { 23 | if (RootObject) 24 | DeleteTree(RootObject); 25 | } 26 | 27 | void JsonStream::DeleteTree(JsonObject *Object) 28 | { 29 | JsonObject *NextObject; 30 | 31 | do 32 | { 33 | if (Object->Type == JsonObject::ValueTypeObject || Object->Type == JsonObject::ValueTypeArray) 34 | DeleteTree(Object->pObjectContent); 35 | NextObject = Object->pNextObject; 36 | delete Object; 37 | } while ((Object = NextObject) != NULL); 38 | } 39 | 40 | int JsonStream::ReadFile(const char *File) 41 | { 42 | FILE *fp = fopen(File, "r"); 43 | 44 | if (fp == NULL) 45 | return -1; 46 | p = stream; 47 | RootObject = ParseObject(0, &JsonStream::GetFileStream, (void *)fp); 48 | fclose(fp); 49 | 50 | return 0; 51 | } 52 | 53 | int JsonStream::WriteFile(const char *File) 54 | { 55 | FILE *fp = fopen(File, "w"); 56 | 57 | if (fp == NULL) 58 | return -1; 59 | if (RootObject != NULL) 60 | { 61 | OutputObject(fp, RootObject->pObjectContent, 1, 1); 62 | } 63 | fclose(fp); 64 | 65 | return 0; 66 | } 67 | 68 | JsonObject *JsonStream::ParseObject(int IsObject, GetStream GetStreamFunc, void *source) 69 | { 70 | JsonObject *Object = NULL, *CurObject = NULL; 71 | int stage = IsObject ? 0 : 3; 72 | 73 | if (!IsObject) // for array, create new object list 74 | { 75 | CurObject = Object = GetNewObject(); 76 | if (Object == NULL) 77 | return NULL; 78 | } 79 | 80 | while (1) 81 | { 82 | if (*p == '\0') 83 | if ((this->*GetStreamFunc)(source) < 0) 84 | break; 85 | if (*p == '\0') 86 | continue; 87 | 88 | switch (stage) 89 | { 90 | case 0: // waiting for '{' 91 | if (*p == '{') 92 | { 93 | stage = 1; 94 | CurObject = Object = GetNewObject(); 95 | if (Object == NULL) 96 | return NULL; 97 | } 98 | break; 99 | case 1: // waiting for '\"' as start of key 100 | if (*p == '\"') 101 | { 102 | CopyString(CurObject->Key, MAX_KEY_LENGTH); 103 | if (strcmp(CurObject->Key, "elevationAdjust") == 0) 104 | stage = stage; 105 | stage = 2; 106 | } 107 | break; 108 | case 2: // waiting for ':' 109 | if (*p == ':') 110 | stage = 3; 111 | break; 112 | case 3: // waiting for value 113 | if (*p == '{') // value is an object 114 | { 115 | CurObject->Type = JsonObject::ValueTypeObject; 116 | CurObject->pObjectContent = ParseObject(1, GetStreamFunc, source); 117 | } 118 | else if (*p == '[') // value is an array 119 | { 120 | p ++; 121 | CurObject->Type = JsonObject::ValueTypeArray; 122 | CurObject->pObjectContent = ParseObject(0, GetStreamFunc, source); 123 | } 124 | else if (!IsWhiteSpace(*p)) 125 | GetValueContent(CurObject); 126 | else 127 | break; 128 | stage = 4; 129 | break; 130 | case 4: // determine whether end of object or next key/value pair 131 | if (*p == '}' || *p == ']') 132 | return Object; 133 | else if (*p == ',') 134 | { 135 | CurObject->pNextObject = GetNewObject(); 136 | if (CurObject->pNextObject == NULL) 137 | return Object; 138 | CurObject = CurObject->pNextObject; 139 | stage = IsObject ? 1 : 3; // go to next key/value pair or value 140 | } 141 | } 142 | p ++; 143 | } 144 | 145 | return Object; 146 | } 147 | 148 | JsonObject *JsonStream::GetNewObject() 149 | { 150 | JsonObject *Object = new JsonObject; 151 | Object->Key[0] = '\0'; 152 | Object->Type = JsonObject::ValueTypeNull; // initialize with NULL object 153 | Object->pNextObject = Object->pObjectContent = NULL; 154 | return Object; 155 | } 156 | 157 | int JsonStream::GetFileStream(void *source) 158 | { 159 | FILE *fp = (FILE *)source; 160 | 161 | if (feof(fp)) 162 | return -1; 163 | fgets(stream, 255, fp); 164 | p = stream; 165 | return 1; 166 | } 167 | 168 | int JsonStream::CopyString(char *dest, int MaxLength) 169 | { 170 | int Length = 0; 171 | 172 | p ++; // skip starting '\"' 173 | while (*p != '\0' && *p != '\"') 174 | { 175 | if (Length < MaxLength) 176 | { 177 | if (*p == '\\') 178 | *dest ++ = EscapeCharacter(); 179 | else 180 | *dest ++ = *p; 181 | Length ++; 182 | } 183 | p ++; 184 | } 185 | *dest = '\0'; 186 | if (*p == '\0') 187 | p --; 188 | return Length; 189 | } 190 | 191 | int JsonStream::IsWhiteSpace(const char ch) 192 | { 193 | if (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t') 194 | return 1; 195 | else 196 | return 0; 197 | } 198 | 199 | char JsonStream::EscapeCharacter() 200 | { 201 | int hex; 202 | char ch = *(++p); 203 | 204 | switch (ch) 205 | { 206 | case '\"': // ASCII 22 207 | case '\\': // ASCII 5C 208 | case '/': // ASCII 2F 209 | return ch; 210 | case 'b': // ASCII 08 211 | return '\b'; 212 | case 'f': // ASCII 0C 213 | return '\f'; 214 | case 'n': // ASCII 0A 215 | return '\n'; 216 | case 'r': // ASCII 0D 217 | return '\r'; 218 | case 't': // ASCII 09 219 | return '\t'; 220 | case 'u': 221 | hex = ((int)(*(p+1)) << 24) | ((int)(*(p+2)) << 16) | ((int)(*(p+3)) << 8) | ((int)(*(p+4)) << 0); 222 | p += 4; 223 | return (char)hex; 224 | } 225 | return '\0'; 226 | } 227 | 228 | int JsonStream::GetValueContent(JsonObject *Object) 229 | { 230 | if (*p == '\"') // value is string 231 | { 232 | Object->Type = JsonObject::ValueTypeString; 233 | return CopyString(Object->String, MAX_STRING_LENGTH); 234 | } 235 | else if (*p == '-' || (*p >= '0' && *p <= '9')) // value is number 236 | return GetNumber(Object); 237 | else if (*p == 't' || *p == 'T') 238 | Object->Type = JsonObject::ValueTypeTrue; 239 | else if (*p == 'f' || *p == 'F') 240 | Object->Type = JsonObject::ValueTypeFalse; 241 | else if (*p == 'n' || *p == 'N') 242 | Object->Type = JsonObject::ValueTypeNull; 243 | Object->pObjectContent = NULL; 244 | 245 | while (*p != '\0' && *p != ',' && !(IsWhiteSpace(*p))) 246 | p ++; 247 | p --; 248 | return 0; 249 | } 250 | 251 | int JsonStream::GetNumber(JsonObject *Object) 252 | { 253 | int section = 0, exp = 0, sign = 0, exp_sign = 0, finish = 0; 254 | double fraction = 0.1; 255 | 256 | Object->Type = JsonObject::ValueTypeIntNumber; 257 | Object->Number.l_data = 0; 258 | if (*p == '-') 259 | { 260 | sign = 1; 261 | p ++; 262 | } 263 | while (*p != '\0') 264 | { 265 | switch (section) 266 | { 267 | case 0: // integer part 268 | if (*p >= '0' && *p <= '9') 269 | Object->Number.l_data = Object->Number.l_data * 10 + (*p - '0'); 270 | else if (*p == '.' || *p == 'e' || *p == 'E') 271 | { 272 | Object->Number.d_data = (double)Object->Number.l_data; 273 | Object->Type = JsonObject::ValueTypeFloatNumber; 274 | section = (*p == '.') ? 1 : 2; 275 | } 276 | else 277 | finish = 1; 278 | break; 279 | case 1: // fraction part 280 | if (*p >= '0' && *p <= '9') 281 | { 282 | Object->Number.d_data += fraction * (*p - '0'); 283 | fraction *= 0.1; 284 | } 285 | else if (*p == 'e' || *p == 'E') 286 | section = 2; 287 | else 288 | finish = 1; 289 | break; 290 | case 2: // exponent part 291 | if (*p == '+' || *p == '-') 292 | exp_sign = (*p == '-') ? 1 : 0; 293 | else if (*p >= '0' && *p <= '9') 294 | exp = exp * 10 + (*p - '0'); 295 | else 296 | finish = 1; 297 | break; 298 | } 299 | if (finish) 300 | { 301 | p --; 302 | break; 303 | } 304 | p ++; 305 | } 306 | if (Object->Type == JsonObject::ValueTypeFloatNumber) 307 | { 308 | if (exp_sign) 309 | exp = -exp; 310 | Object->Number.d_data *= pow(10., (double)exp); 311 | if (sign) 312 | Object->Number.d_data = -Object->Number.d_data; 313 | } 314 | else if (sign) // negative integer 315 | Object->Number.l_data = -Object->Number.l_data; 316 | 317 | return 0; 318 | } 319 | 320 | int JsonStream::OutputObject(FILE *fp, JsonObject *Object, int Depth, int HasKey) 321 | { 322 | int i; 323 | 324 | if (HasKey) 325 | fprintf(fp, "{\n"); 326 | else 327 | fprintf(fp, "[\n"); 328 | while (Object) 329 | { 330 | OutputKeyValue(fp, Object, Depth, HasKey); 331 | Object = Object->pNextObject; 332 | if (Object) 333 | fprintf(fp, ",\n"); 334 | } 335 | fputc('\n', fp); 336 | for (i = 0; i < Depth - 1; i ++) 337 | fputc('\t', fp); 338 | fputc(HasKey ? '}' : ']', fp); 339 | return 0; 340 | } 341 | 342 | int JsonStream::OutputKeyValue(FILE *fp, JsonObject *Object, int Depth, int HasKey) 343 | { 344 | int i; 345 | 346 | if (Object == NULL) 347 | return -1; 348 | for (i = 0; i < Depth; i ++) 349 | fputc('\t', fp); 350 | if (HasKey) 351 | { 352 | OutputString(fp, Object->Key); 353 | fprintf(fp, ": "); 354 | } 355 | switch (Object->Type) 356 | { 357 | case JsonObject::ValueTypeObject: 358 | OutputObject(fp, Object->pObjectContent, Depth + 1, 1); 359 | break; 360 | case JsonObject::ValueTypeArray: 361 | OutputObject(fp, Object->pObjectContent, Depth + 1, 0); 362 | break; 363 | case JsonObject::ValueTypeString: 364 | OutputString(fp, Object->String); 365 | break; 366 | case JsonObject::ValueTypeIntNumber: 367 | fprintf(fp, "%lld", Object->Number.l_data); 368 | break; 369 | case JsonObject::ValueTypeFloatNumber: 370 | fprintf(fp, "%lf", Object->Number.d_data); 371 | break; 372 | case JsonObject::ValueTypeTrue: 373 | fprintf(fp, "true"); 374 | break; 375 | case JsonObject::ValueTypeFalse: 376 | fprintf(fp, "false"); 377 | break; 378 | case JsonObject::ValueTypeNull: 379 | fprintf(fp, "null"); 380 | break; 381 | } 382 | 383 | return 0; 384 | } 385 | 386 | int JsonStream::OutputString(FILE *fp, const char *str) 387 | { 388 | fputc('\"', fp); 389 | while (*str) 390 | { 391 | switch (*str) 392 | { 393 | case '\b': 394 | fputc('\\', fp); fputc('b', fp); break; 395 | case '\t': 396 | fputc('\\', fp); fputc('t', fp); break; 397 | case '\n': 398 | fputc('\\', fp); fputc('n', fp); break; 399 | case '\f': 400 | fputc('\\', fp); fputc('f', fp); break; 401 | case '\r': 402 | fputc('\\', fp); fputc('r', fp); break; 403 | case '\"': 404 | fputc('\\', fp); fputc('\"', fp); break; 405 | case '/': 406 | fputc('\\', fp); fputc('/', fp); break; 407 | case '\\': 408 | fputc('\\', fp); fputc('\\', fp); break; 409 | default: 410 | if (*str < 0x20 || *str >= 0x7f) 411 | fprintf(fp, "\\u%04x", (unsigned int)(*str)); 412 | else 413 | fputc(*str, fp); 414 | } 415 | str ++; 416 | } 417 | fputc('\"', fp); 418 | return 0; 419 | } 420 | -------------------------------------------------------------------------------- /src/NavBit.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // NavBit.h: 3 | // Implementation of navigation bit synthesis base class 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #include "NavBit.h" 10 | 11 | // following table generate by MATLAB code: 12 | // encdata=(0:255)'; 13 | // bindata=dec2bin(encdata,8)-'0'; 14 | // for i=1:256 15 | // G11=mod(bindata(i,1)+bindata(i,4)+bindata(i,5)+bindata(i,6)+bindata(i,7),2); 16 | // G21=mod(bindata(i,1)+bindata(i,2)+bindata(i,4)+bindata(i,5)+bindata(i,7),2); 17 | // G10=mod(bindata(i,2)+bindata(i,5)+bindata(i,6)+bindata(i,7)+bindata(i,8),2); 18 | // G20=mod(bindata(i,2)+bindata(i,3)+bindata(i,5)+bindata(i,6)+bindata(i,8),2); 19 | // encbits(i,:)=[G21 G11 G20 G10 G11 G21 G10 G20]; 20 | // end 21 | // enchex=encbits(:,1)*128+encbits(:,2)*64+encbits(:,3)*32+encbits(:,4)*16+encbits(:,5)*8+encbits(:,6)*4+encbits(:,7)*2+encbits(:,8); 22 | // enchex=dec2hex(enchex,2); 23 | const unsigned char NavBit::ConvEncodeTable[256] = { 24 | 0x00, 0x33, 0xde, 0xed, 0x7b, 0x48, 0xa5, 0x96, 0xff, 0xcc, 0x21, 0x12, 0x84, 0xb7, 0x5a, 0x69, 25 | 0xcc, 0xff, 0x12, 0x21, 0xb7, 0x84, 0x69, 0x5a, 0x33, 0x00, 0xed, 0xde, 0x48, 0x7b, 0x96, 0xa5, 26 | 0x21, 0x12, 0xff, 0xcc, 0x5a, 0x69, 0x84, 0xb7, 0xde, 0xed, 0x00, 0x33, 0xa5, 0x96, 0x7b, 0x48, 27 | 0xed, 0xde, 0x33, 0x00, 0x96, 0xa5, 0x48, 0x7b, 0x12, 0x21, 0xcc, 0xff, 0x69, 0x5a, 0xb7, 0x84, 28 | 0xb7, 0x84, 0x69, 0x5a, 0xcc, 0xff, 0x12, 0x21, 0x48, 0x7b, 0x96, 0xa5, 0x33, 0x00, 0xed, 0xde, 29 | 0x7b, 0x48, 0xa5, 0x96, 0x00, 0x33, 0xde, 0xed, 0x84, 0xb7, 0x5a, 0x69, 0xff, 0xcc, 0x21, 0x12, 30 | 0x96, 0xa5, 0x48, 0x7b, 0xed, 0xde, 0x33, 0x00, 0x69, 0x5a, 0xb7, 0x84, 0x12, 0x21, 0xcc, 0xff, 31 | 0x5a, 0x69, 0x84, 0xb7, 0x21, 0x12, 0xff, 0xcc, 0xa5, 0x96, 0x7b, 0x48, 0xde, 0xed, 0x00, 0x33, 32 | 0xcc, 0xff, 0x12, 0x21, 0xb7, 0x84, 0x69, 0x5a, 0x33, 0x00, 0xed, 0xde, 0x48, 0x7b, 0x96, 0xa5, 33 | 0x00, 0x33, 0xde, 0xed, 0x7b, 0x48, 0xa5, 0x96, 0xff, 0xcc, 0x21, 0x12, 0x84, 0xb7, 0x5a, 0x69, 34 | 0xed, 0xde, 0x33, 0x00, 0x96, 0xa5, 0x48, 0x7b, 0x12, 0x21, 0xcc, 0xff, 0x69, 0x5a, 0xb7, 0x84, 35 | 0x21, 0x12, 0xff, 0xcc, 0x5a, 0x69, 0x84, 0xb7, 0xde, 0xed, 0x00, 0x33, 0xa5, 0x96, 0x7b, 0x48, 36 | 0x7b, 0x48, 0xa5, 0x96, 0x00, 0x33, 0xde, 0xed, 0x84, 0xb7, 0x5a, 0x69, 0xff, 0xcc, 0x21, 0x12, 37 | 0xb7, 0x84, 0x69, 0x5a, 0xcc, 0xff, 0x12, 0x21, 0x48, 0x7b, 0x96, 0xa5, 0x33, 0x00, 0xed, 0xde, 38 | 0x5a, 0x69, 0x84, 0xb7, 0x21, 0x12, 0xff, 0xcc, 0xa5, 0x96, 0x7b, 0x48, 0xde, 0xed, 0x00, 0x33, 39 | 0x96, 0xa5, 0x48, 0x7b, 0xed, 0xde, 0x33, 0x00, 0x69, 0x5a, 0xb7, 0x84, 0x12, 0x21, 0xcc, 0xff, 40 | }; 41 | 42 | 43 | const unsigned int NavBit::Crc24q[256] = { 44 | 0x00000000u, 0x01864CFBu, 0x028AD50Du, 0x030C99F6u, 0x0493E6E1u, 0x0515AA1Au, 0x061933ECu, 0x079F7F17u, 45 | 0x08A18139u, 0x0927CDC2u, 0x0A2B5434u, 0x0BAD18CFu, 0x0C3267D8u, 0x0DB42B23u, 0x0EB8B2D5u, 0x0F3EFE2Eu, 46 | 0x10C54E89u, 0x11430272u, 0x124F9B84u, 0x13C9D77Fu, 0x1456A868u, 0x15D0E493u, 0x16DC7D65u, 0x175A319Eu, 47 | 0x1864CFB0u, 0x19E2834Bu, 0x1AEE1ABDu, 0x1B685646u, 0x1CF72951u, 0x1D7165AAu, 0x1E7DFC5Cu, 0x1FFBB0A7u, 48 | 0x200CD1E9u, 0x218A9D12u, 0x228604E4u, 0x2300481Fu, 0x249F3708u, 0x25197BF3u, 0x2615E205u, 0x2793AEFEu, 49 | 0x28AD50D0u, 0x292B1C2Bu, 0x2A2785DDu, 0x2BA1C926u, 0x2C3EB631u, 0x2DB8FACAu, 0x2EB4633Cu, 0x2F322FC7u, 50 | 0x30C99F60u, 0x314FD39Bu, 0x32434A6Du, 0x33C50696u, 0x345A7981u, 0x35DC357Au, 0x36D0AC8Cu, 0x3756E077u, 51 | 0x38681E59u, 0x39EE52A2u, 0x3AE2CB54u, 0x3B6487AFu, 0x3CFBF8B8u, 0x3D7DB443u, 0x3E712DB5u, 0x3FF7614Eu, 52 | 0x4019A3D2u, 0x419FEF29u, 0x429376DFu, 0x43153A24u, 0x448A4533u, 0x450C09C8u, 0x4600903Eu, 0x4786DCC5u, 53 | 0x48B822EBu, 0x493E6E10u, 0x4A32F7E6u, 0x4BB4BB1Du, 0x4C2BC40Au, 0x4DAD88F1u, 0x4EA11107u, 0x4F275DFCu, 54 | 0x50DCED5Bu, 0x515AA1A0u, 0x52563856u, 0x53D074ADu, 0x544F0BBAu, 0x55C94741u, 0x56C5DEB7u, 0x5743924Cu, 55 | 0x587D6C62u, 0x59FB2099u, 0x5AF7B96Fu, 0x5B71F594u, 0x5CEE8A83u, 0x5D68C678u, 0x5E645F8Eu, 0x5FE21375u, 56 | 0x6015723Bu, 0x61933EC0u, 0x629FA736u, 0x6319EBCDu, 0x648694DAu, 0x6500D821u, 0x660C41D7u, 0x678A0D2Cu, 57 | 0x68B4F302u, 0x6932BFF9u, 0x6A3E260Fu, 0x6BB86AF4u, 0x6C2715E3u, 0x6DA15918u, 0x6EADC0EEu, 0x6F2B8C15u, 58 | 0x70D03CB2u, 0x71567049u, 0x725AE9BFu, 0x73DCA544u, 0x7443DA53u, 0x75C596A8u, 0x76C90F5Eu, 0x774F43A5u, 59 | 0x7871BD8Bu, 0x79F7F170u, 0x7AFB6886u, 0x7B7D247Du, 0x7CE25B6Au, 0x7D641791u, 0x7E688E67u, 0x7FEEC29Cu, 60 | 0x803347A4u, 0x81B50B5Fu, 0x82B992A9u, 0x833FDE52u, 0x84A0A145u, 0x8526EDBEu, 0x862A7448u, 0x87AC38B3u, 61 | 0x8892C69Du, 0x89148A66u, 0x8A181390u, 0x8B9E5F6Bu, 0x8C01207Cu, 0x8D876C87u, 0x8E8BF571u, 0x8F0DB98Au, 62 | 0x90F6092Du, 0x917045D6u, 0x927CDC20u, 0x93FA90DBu, 0x9465EFCCu, 0x95E3A337u, 0x96EF3AC1u, 0x9769763Au, 63 | 0x98578814u, 0x99D1C4EFu, 0x9ADD5D19u, 0x9B5B11E2u, 0x9CC46EF5u, 0x9D42220Eu, 0x9E4EBBF8u, 0x9FC8F703u, 64 | 0xA03F964Du, 0xA1B9DAB6u, 0xA2B54340u, 0xA3330FBBu, 0xA4AC70ACu, 0xA52A3C57u, 0xA626A5A1u, 0xA7A0E95Au, 65 | 0xA89E1774u, 0xA9185B8Fu, 0xAA14C279u, 0xAB928E82u, 0xAC0DF195u, 0xAD8BBD6Eu, 0xAE872498u, 0xAF016863u, 66 | 0xB0FAD8C4u, 0xB17C943Fu, 0xB2700DC9u, 0xB3F64132u, 0xB4693E25u, 0xB5EF72DEu, 0xB6E3EB28u, 0xB765A7D3u, 67 | 0xB85B59FDu, 0xB9DD1506u, 0xBAD18CF0u, 0xBB57C00Bu, 0xBCC8BF1Cu, 0xBD4EF3E7u, 0xBE426A11u, 0xBFC426EAu, 68 | 0xC02AE476u, 0xC1ACA88Du, 0xC2A0317Bu, 0xC3267D80u, 0xC4B90297u, 0xC53F4E6Cu, 0xC633D79Au, 0xC7B59B61u, 69 | 0xC88B654Fu, 0xC90D29B4u, 0xCA01B042u, 0xCB87FCB9u, 0xCC1883AEu, 0xCD9ECF55u, 0xCE9256A3u, 0xCF141A58u, 70 | 0xD0EFAAFFu, 0xD169E604u, 0xD2657FF2u, 0xD3E33309u, 0xD47C4C1Eu, 0xD5FA00E5u, 0xD6F69913u, 0xD770D5E8u, 71 | 0xD84E2BC6u, 0xD9C8673Du, 0xDAC4FECBu, 0xDB42B230u, 0xDCDDCD27u, 0xDD5B81DCu, 0xDE57182Au, 0xDFD154D1u, 72 | 0xE026359Fu, 0xE1A07964u, 0xE2ACE092u, 0xE32AAC69u, 0xE4B5D37Eu, 0xE5339F85u, 0xE63F0673u, 0xE7B94A88u, 73 | 0xE887B4A6u, 0xE901F85Du, 0xEA0D61ABu, 0xEB8B2D50u, 0xEC145247u, 0xED921EBCu, 0xEE9E874Au, 0xEF18CBB1u, 74 | 0xF0E37B16u, 0xF16537EDu, 0xF269AE1Bu, 0xF3EFE2E0u, 0xF4709DF7u, 0xF5F6D10Cu, 0xF6FA48FAu, 0xF77C0401u, 75 | 0xF842FA2Fu, 0xF9C4B6D4u, 0xFAC82F22u, 0xFB4E63D9u, 0xFCD11CCEu, 0xFD575035u, 0xFE5BC9C3u, 0xFFDD8538u, 76 | }; 77 | 78 | NavBit::NavBit() 79 | { 80 | } 81 | 82 | NavBit::~NavBit() 83 | { 84 | } 85 | int NavBit::roundi(double data) 86 | { 87 | if (data >= 0) 88 | return (int)(data + 0.5); 89 | else 90 | return (int)(data - 0.5); 91 | } 92 | 93 | int NavBit::roundu(double data) 94 | { 95 | return (unsigned int)(data + 0.5); 96 | } 97 | 98 | double NavBit::UnscaleDouble(double value, int scale) 99 | { 100 | DOUBLE_INT_UNION data; 101 | 102 | data.d_data = value; 103 | data.i_data[1] -= (scale << 20); 104 | return data.d_data; 105 | } 106 | 107 | int NavBit::UnscaleInt(double value, int scale) 108 | { 109 | long long int long_value = UnscaleLong(value, scale); 110 | return (int)long_value; 111 | } 112 | 113 | unsigned int NavBit::UnscaleUint(double value, int scale) 114 | { 115 | unsigned long long int long_value = UnscaleULong(value, scale); 116 | return (unsigned int)long_value; 117 | } 118 | 119 | long long int NavBit::UnscaleLong(double value, int scale) 120 | { 121 | DOUBLE_INT_UNION *data = (DOUBLE_INT_UNION *)(&value); 122 | long long int fraction; 123 | int sign; 124 | 125 | sign = (data->i_data[1] & 0x80000000); 126 | fraction = (long long int)UnscaleULong(value, scale); 127 | return (sign ? -fraction : fraction); 128 | } 129 | 130 | unsigned long long int NavBit::UnscaleULong(double value, int scale) 131 | { 132 | DOUBLE_INT_UNION *data = (DOUBLE_INT_UNION *)(&value); 133 | unsigned long long int fraction; 134 | int exp, shift; 135 | 136 | exp = ((data->i_data[1] & 0x7ff00000) >> 20); 137 | data->i_data[1] &= 0xfffff; // clear sign/exp 138 | fraction = *(long long *)(&value); 139 | if (exp == 0 && fraction == 0) 140 | return 0; 141 | fraction |= 0x10000000000000LL; // add 1. part 142 | shift = 1074 - exp + scale; 143 | fraction += (1LL << shift); // round 144 | fraction >>= (shift + 1); 145 | return fraction; 146 | } 147 | 148 | // put bit in Data from MSB ot LSB into BitStream, bit order from bit(BitNumber-1) to bit(0) of Data 149 | int NavBit::AssignBits(unsigned int Data, int BitNumber, int BitStream[]) 150 | { 151 | int i; 152 | 153 | Data <<= (32 - BitNumber); 154 | for (i = 0; i < BitNumber; i++) 155 | { 156 | BitStream[i] = (Data & 0x80000000) ? 1 : 0; 157 | Data <<= 1; 158 | } 159 | 160 | return BitNumber; 161 | } 162 | 163 | // do 2bit convolution encode at the same time 164 | // EncodeBits bit 7~2 is current state 165 | // EncodeBits bit1 and bit0 are new incomming bits with bit1 comes first 166 | // return value are generated encoded bit with following order 167 | // G21 G11 G20 G10 G11 G21 G10 G20 (G11 and G21 are encoded bits using bit1, G10 and G20 are encoded bits using bit0) 168 | // so 4MSB of return value are 4 encoded bits with G2/G1 order 169 | // 4LSB of return value are 4 encoded bits with G1/G2 order 170 | unsigned char NavBit::ConvolutionEncode(unsigned char EncodeBits) 171 | { 172 | return ConvEncodeTable[EncodeBits]; 173 | } 174 | 175 | // Length is number of bits in BitStream to do CRC24Q encode 176 | // input BitStream filled with MSB first and start from index 0 177 | // if encoded bits does not fit all bits in BitStream (Length is not multiple of 32) 178 | // 0s need to be filled first (at MSBs of BitStream[0]) to make sure last encoded bits 179 | // in bit0 of last index of BitStream array (this is because encoding 0 into all zero 180 | // state CRC24Q encode does not change encoder status) 181 | unsigned int NavBit::Crc24qEncode(unsigned int *BitStream, int Length) 182 | { 183 | int i, ByteNum; 184 | unsigned int Data, crc_result = 0; 185 | 186 | ByteNum = ((Length + 31) / 32) * 4; 187 | Data = BitStream[0]; 188 | for (i = 0; i < ByteNum; i ++) 189 | { 190 | crc_result = (crc_result << 8) ^ Crc24q[(Data >> 24) ^ (unsigned char)(crc_result >> 16)]; 191 | Data <<= 8; 192 | if ((i & 3) == 3) // move to next bit 193 | Data = BitStream[(i >> 2) + 1]; 194 | } 195 | 196 | return crc_result & 0xffffff; 197 | } 198 | -------------------------------------------------------------------------------- /src/PowerControl.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // PowerControl.cpp: 3 | // Definition of signal power control class 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | #include 9 | #include 10 | 11 | #include "ConstVal.h" 12 | #include "PowerControl.h" 13 | 14 | CPowerControl::CPowerControl() 15 | { 16 | ArraySize = 0; 17 | PowerControlArray = NULL; 18 | Adjust = ElevationAdjustNone; 19 | NoiseFloor = -172.; 20 | InitCN0 = 47.; 21 | } 22 | 23 | CPowerControl::~CPowerControl() 24 | { 25 | if (PowerControlArray) 26 | free(PowerControlArray); 27 | } 28 | 29 | void CPowerControl::AddControlElement(PSIGNAL_POWER pControlElement) 30 | { 31 | // allocate array or expand size 32 | if (!PowerControlArray) 33 | PowerControlArray = (PSIGNAL_POWER)malloc(100 * sizeof(SIGNAL_POWER)); 34 | else if ((ArraySize % 100) == 0) 35 | PowerControlArray = (PSIGNAL_POWER)realloc(PowerControlArray, (ArraySize + 100) * sizeof(SIGNAL_POWER)); 36 | 37 | memcpy(PowerControlArray + ArraySize, pControlElement, sizeof(SIGNAL_POWER)); 38 | ArraySize ++; 39 | } 40 | 41 | void CPowerControl::Sort() 42 | { 43 | int i, j; 44 | int min_index; 45 | SIGNAL_POWER temp; 46 | 47 | for (i = 0; i < ArraySize - 1; i ++) 48 | { 49 | min_index = i; 50 | for (j = i + 1; j < ArraySize; j ++) 51 | { 52 | if (PowerControlArray[j].time < PowerControlArray[min_index].time) 53 | min_index = j; 54 | } 55 | // swap min time element to position i 56 | if (min_index != i) 57 | { 58 | temp = PowerControlArray[i]; 59 | PowerControlArray[i] = PowerControlArray[min_index]; 60 | PowerControlArray[min_index] = temp; 61 | } 62 | } 63 | } 64 | 65 | void CPowerControl::ResetTime() 66 | { 67 | TimeElapsMs = 0; 68 | NextIndex = 0; 69 | } 70 | 71 | int CPowerControl::GetPowerControlList(int TimeStepMs, PSIGNAL_POWER &PowerList) 72 | { 73 | int InitIndex = NextIndex; 74 | 75 | PowerList = PowerControlArray + NextIndex; 76 | TimeElapsMs += TimeStepMs; 77 | 78 | while (NextIndex < ArraySize) 79 | { 80 | if (PowerControlArray[NextIndex].time > TimeElapsMs) 81 | break; 82 | NextIndex ++; 83 | } 84 | 85 | return NextIndex - InitIndex; 86 | } 87 | -------------------------------------------------------------------------------- /src/SatIfSignal.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "SatIfSignal.h" 5 | 6 | CSatIfSignal::CSatIfSignal(int MsSampleNumber, int SatIfFreq, GnssSystem SatSystem, int SatSignalIndex, unsigned char SatId) : SampleNumber(MsSampleNumber), IfFreq(SatIfFreq), System(SatSystem), SignalIndex(SatSignalIndex), Svid((int)SatId) 7 | { 8 | SampleArray = new complex_number[SampleNumber]; 9 | PrnSequence = new PrnGenerate(System, SignalIndex, Svid); 10 | SatParam = NULL; 11 | DataLength = PrnSequence->Attribute->DataPeriod * PrnSequence->Attribute->ChipRate; 12 | PilotLength = PrnSequence->Attribute->PilotPeriod * PrnSequence->Attribute->ChipRate; 13 | GlonassHalfCycle = ((IfFreq % 1000) != 0) ? 1 : 0; 14 | } 15 | 16 | CSatIfSignal::~CSatIfSignal() 17 | { 18 | delete[] SampleArray; 19 | SampleArray = NULL; 20 | delete PrnSequence; 21 | PrnSequence = NULL; 22 | } 23 | 24 | void CSatIfSignal::InitState(GNSS_TIME CurTime, PSATELLITE_PARAM pSatParam, NavBit* pNavData) 25 | { 26 | SatParam = pSatParam; 27 | if (!SatelliteSignal.SetSignalAttribute(System, SignalIndex, pNavData, Svid)) 28 | SatelliteSignal.NavData = (NavBit*)0; // if system/frequency and navigation data not match, set pointer to NULL 29 | StartCarrierPhase = GetCarrierPhase(SatParam, SignalIndex); 30 | SignalTime = StartTransmitTime = GetTransmitTime(CurTime, GetTravelTime(SatParam, SignalIndex)); 31 | SatelliteSignal.GetSatelliteSignal(SignalTime, DataSignal, PilotSignal); 32 | HalfCycleFlag = 0; 33 | } 34 | 35 | void CSatIfSignal::GetIfSample(GNSS_TIME CurTime) 36 | { 37 | int i, TransmitMsDiff; 38 | double CurPhase, PhaseStep, CurChip, CodeDiff, CodeStep; 39 | const PrnAttribute* CodeAttribute = PrnSequence->Attribute; 40 | complex_number IfSample; 41 | double Amp = pow(10, (SatParam->CN0 - 3000) / 1000.) / sqrt(SampleNumber); 42 | 43 | if (!SatParam) 44 | return; 45 | SignalTime = StartTransmitTime; 46 | SatelliteSignal.GetSatelliteSignal(SignalTime, DataSignal, PilotSignal); 47 | EndCarrierPhase = GetCarrierPhase(SatParam, SignalIndex); 48 | EndTransmitTime = GetTransmitTime(CurTime, GetTravelTime(SatParam, SignalIndex)); 49 | 50 | // calculate start/end signal phase and phase step (actual local signal phase is negative ADR) 51 | PhaseStep = (StartCarrierPhase - EndCarrierPhase) / SampleNumber; 52 | PhaseStep += IfFreq / 1000. / SampleNumber; 53 | CurPhase = StartCarrierPhase - (int)StartCarrierPhase; 54 | CurPhase = 1 - CurPhase; // carrier is fractional part of negative of travel time, equvalent to 1 minus positive fractional part 55 | StartCarrierPhase = EndCarrierPhase; 56 | if (GlonassHalfCycle) // for GLONASS odd number FreqID, nominal IF result in half cycle toggle every 1ms 57 | { 58 | CurPhase += HalfCycleFlag ? 0.5 : 0.0; 59 | HalfCycleFlag = 1 - HalfCycleFlag; 60 | } 61 | 62 | // get PRN count for each sample 63 | TransmitMsDiff = EndTransmitTime.MilliSeconds - StartTransmitTime.MilliSeconds; 64 | if (TransmitMsDiff < 0) 65 | TransmitMsDiff += 86400000; 66 | CodeDiff = (TransmitMsDiff + EndTransmitTime.SubMilliSeconds - StartTransmitTime.SubMilliSeconds) * CodeAttribute->ChipRate; 67 | CodeStep = CodeDiff / SampleNumber; // code increase between each sample 68 | CurChip = (StartTransmitTime.MilliSeconds % CodeAttribute->PilotPeriod + StartTransmitTime.SubMilliSeconds) * CodeAttribute->ChipRate; 69 | StartTransmitTime = EndTransmitTime; 70 | 71 | for (i = 0; i < SampleNumber; i ++) 72 | { 73 | SampleArray[i] = GetPrnValue(CurChip, CodeStep) * GetRotateValue(CurPhase, PhaseStep) * Amp; 74 | } 75 | } 76 | 77 | complex_number CSatIfSignal::GetPrnValue(double& CurChip, double CodeStep) 78 | { 79 | int ChipCount = (int)CurChip; 80 | int DataChip, PilotChip; 81 | complex_number PrnValue; 82 | int IsBoc = (PrnSequence->Attribute->Attribute) & PRN_ATTRIBUTE_BOC; 83 | 84 | DataChip = ChipCount % DataLength; 85 | if (IsBoc) 86 | DataChip /= 2; 87 | PrnValue = DataSignal * (PrnSequence->DataPrn[DataChip] ? -1 : 1); 88 | if (PrnSequence->PilotPrn) 89 | { 90 | PilotChip = ChipCount % PilotLength; 91 | if (IsBoc) 92 | PilotChip /= 2; 93 | PrnValue += PilotSignal * (PrnSequence->PilotPrn[PilotChip] ? -1 : 1); 94 | } 95 | if (IsBoc && (ChipCount & 1)) // second half of BOC code 96 | PrnValue *= -1; 97 | CurChip += CodeStep; 98 | // check whether go beyond next code period (pilot code period multiple of data code period, so only check data period) 99 | if ((((int)CurChip) % DataLength) < DataChip) 100 | { 101 | SignalTime.MilliSeconds += PrnSequence->Attribute->DataPeriod; 102 | SatelliteSignal.GetSatelliteSignal(SignalTime, DataSignal, PilotSignal); 103 | } 104 | return PrnValue; 105 | } 106 | 107 | complex_number CSatIfSignal::GetRotateValue(double& CurPhase, double PhaseStep) 108 | { 109 | complex_number Rotate = complex_number(cos(CurPhase * PI2), sin(CurPhase * PI2)); 110 | CurPhase += PhaseStep; 111 | return Rotate; 112 | } 113 | -------------------------------------------------------------------------------- /src/SatelliteSignal.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // SatelliteSignal.cpp: 3 | // Implementation of functions to calculate satellite signal with data/pilot modulation 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #include 10 | #include 11 | 12 | #include "GnssTime.h" 13 | #include "SatelliteSignal.h" 14 | #include "LNavBit.h" 15 | #include "CNavBit.h" 16 | #include "CNav2Bit.h" 17 | #include "INavBit.h" 18 | #include "FNavBit.h" 19 | #include "D1D2NavBit.h" 20 | #include "BCNav1Bit.h" 21 | #include "BCNav2Bit.h" 22 | #include "BCNav3Bit.h" 23 | #include "GNavBit.h" 24 | #include "PilotBit.h" 25 | 26 | const SignalAttribute CSatelliteSignal::SignalAttributes[32] = { 27 | // CodeLength NHLength NHCode FrameLength 28 | { 1, 20, 0x0, 6000, }, // index 0 for LNAV 29 | { 10, 1, 0x0, 18000, }, // index 1 for CNAV2 30 | { 20, 1, 0x0, 12000, }, // index 2 for CNAV L2C 31 | { 1, 10, 0x2b0, 6000, }, // index 3 for CNAV L5 32 | { 10, 1, 0x0, 18000, }, // index 4 for BCNAV1 33 | { 1, 20, 0x72b20, 6000, }, // index 5 for D1 34 | { 1, 2, 0x0, 600, }, // index 6 for D2 35 | { 1, 5, 0x8, 3000, }, // index 7 for BCNAV2 36 | { 1, 1, 0x0, 1000, }, // index 8 for BCNAV3 37 | { 4, 1, 0x0, 2000, }, // index 9 for I/NAV E1 38 | { 1, 20, 0x97421, 10000, }, // index 10 for FNAV 39 | { 1, 4, 0x7, 2000, }, // index 11 for I/NAV E5b 40 | { 1, 1, 0x0, 1000, }, // index 12 for CNAV E6 41 | { 1, 10, 0x0, 2000, }, // index 13 for GNAV 42 | }; 43 | 44 | CSatelliteSignal::CSatelliteSignal() 45 | { 46 | CurrentFrame = Svid = -1; 47 | NavData = (NavBit *)0; 48 | } 49 | 50 | CSatelliteSignal::~CSatelliteSignal() 51 | { 52 | } 53 | 54 | BOOL CSatelliteSignal::SetSignalAttribute(GnssSystem System, int SignalIndex, NavBit *pNavData, int svid) 55 | { 56 | // member variable assignment 57 | SatSystem = System; 58 | SatSignal = SignalIndex; 59 | NavData = pNavData; 60 | Svid = svid; 61 | CurrentFrame = -1; // reset current frame to force fill DataBits[] on next call to GetSatelliteSignal() 62 | memset(DataBits, 0, sizeof(DataBits)); 63 | 64 | // signal and navigation bit match 65 | switch (SatSystem) 66 | { 67 | case GpsSystem: 68 | switch (SatSignal) 69 | { 70 | case SIGNAL_INDEX_L1CA: 71 | Attribute = &SignalAttributes[0]; 72 | return NavData ? ((typeid(*NavData) == typeid(LNavBit)) ? TRUE : FALSE) : TRUE; 73 | case SIGNAL_INDEX_L1C: 74 | Attribute = &SignalAttributes[1]; 75 | return NavData ? ((typeid(*NavData) == typeid(CNav2Bit)) ? TRUE : FALSE) : TRUE; 76 | case SIGNAL_INDEX_L2C: 77 | Attribute = &SignalAttributes[2]; 78 | return NavData ? ((typeid(*NavData) == typeid(CNavBit)) ? TRUE : FALSE) : TRUE; 79 | case SIGNAL_INDEX_L5: 80 | Attribute = &SignalAttributes[3]; 81 | return NavData ? ((typeid(*NavData) == typeid(CNavBit)) ? TRUE : FALSE) : TRUE; 82 | default: return FALSE; // unknown FreqIndex 83 | } 84 | case BdsSystem: 85 | switch (SatSignal) 86 | { 87 | case SIGNAL_INDEX_B1C: 88 | Attribute = &SignalAttributes[4]; 89 | return NavData ? ((typeid(*NavData) == typeid(BCNav1Bit)) ? TRUE : FALSE) : TRUE; 90 | case SIGNAL_INDEX_B1I: 91 | case SIGNAL_INDEX_B2I: 92 | case SIGNAL_INDEX_B3I: 93 | Attribute = ((Svid < 6) || (Svid > 58)) ? &SignalAttributes[6] : &SignalAttributes[5]; 94 | return NavData ? ((typeid(*NavData) == typeid(D1D2NavBit)) ? TRUE : FALSE) : TRUE; 95 | case SIGNAL_INDEX_B2a: 96 | Attribute = &SignalAttributes[7]; 97 | return NavData ? ((typeid(*NavData) == typeid(BCNav2Bit)) ? TRUE : FALSE) : TRUE; 98 | case SIGNAL_INDEX_B2b: 99 | Attribute = &SignalAttributes[8]; 100 | return NavData ? ((typeid(*NavData) == typeid(BCNav3Bit)) ? TRUE : FALSE) : TRUE; 101 | default: return FALSE; // unknown FreqIndex 102 | } 103 | case GalileoSystem: 104 | switch (SatSignal) 105 | { 106 | case SIGNAL_INDEX_E1 : 107 | Attribute = &SignalAttributes[9]; 108 | return NavData ? ((typeid(*NavData) == typeid(INavBit)) ? TRUE : FALSE) : TRUE; 109 | case SIGNAL_INDEX_E5a: 110 | Attribute = &SignalAttributes[10]; 111 | return NavData ? ((typeid(*NavData) == typeid(FNavBit)) ? TRUE : FALSE) : TRUE; 112 | case SIGNAL_INDEX_E5b: 113 | Attribute = &SignalAttributes[11]; 114 | return NavData ? ((typeid(*NavData) == typeid(INavBit)) ? TRUE : FALSE) : TRUE; 115 | case SIGNAL_INDEX_E6 : 116 | Attribute = &SignalAttributes[12]; 117 | return TRUE; 118 | // return NavData ? ((typeid(*NavData) == typeid(ENavBit)) ? TRUE : FALSE) : TRUE; 119 | default: return FALSE; // unknown FreqIndex 120 | } 121 | case GlonassSystem: 122 | switch (SatSignal) 123 | { 124 | case SIGNAL_INDEX_G1: 125 | case SIGNAL_INDEX_G2: 126 | Attribute = &SignalAttributes[13]; 127 | return NavData ? ((typeid(*NavData) == typeid(GNavBit)) ? TRUE : FALSE) : TRUE; 128 | default: return FALSE; // unknown FreqIndex 129 | } 130 | default: return FALSE; // unknown system 131 | } 132 | } 133 | 134 | #define AMPLITUDE_1_2 0.7071067811865475244 135 | #define AMPLITUDE_1_4 0.5 136 | #define AMPLITUDE_29_44 0.811844140885988713377 137 | #define AMPLITUDE_3_4 0.8660254037844386468 138 | #define AMPLITUDE_5_11 0.6741998624632421 139 | 140 | BOOL CSatelliteSignal::GetSatelliteSignal(GNSS_TIME TransmitTime, complex_number &DataSignal, complex_number &PilotSignal) 141 | { 142 | int Milliseconds; 143 | int BitLength = (Attribute->CodeLength * Attribute->NHLength); 144 | int FrameNumber, BitNumber, BitPos, SecondaryPosition; 145 | int DataBit, PilotBit = 0; 146 | int SecondaryLength; 147 | const unsigned int *SecondaryCode = GetPilotBits(SatSystem, SatSignal, Svid, SecondaryLength); 148 | int Seconds, LeapSecond; 149 | int GalileoE1Signal = (SatSystem == GalileoSystem && SatSignal == SIGNAL_INDEX_E1) ? 1 : 0; 150 | int Param = ((SatSystem == GpsSystem && SatSignal == SIGNAL_INDEX_L5) ? 1 : 0) || GalileoE1Signal; // set to 1 for E1 or L5 151 | 152 | if (Svid < 0) // attribute not yet set 153 | return FALSE; 154 | if (SatSystem == BdsSystem) // subtract leap second difference 155 | TransmitTime.MilliSeconds -= 14000; 156 | else if (SatSystem == GlonassSystem) // subtract leap second, add 3 hours 157 | { 158 | Seconds = (unsigned int)(TransmitTime.Week * 604800 + TransmitTime.MilliSeconds / 1000); 159 | GetLeapSecond(Seconds, LeapSecond); 160 | TransmitTime.MilliSeconds = (TransmitTime.MilliSeconds + 10800000 - LeapSecond * 1000) % 86400000; 161 | } 162 | if (TransmitTime.MilliSeconds < 0) // protection on negative millisecond 163 | TransmitTime.MilliSeconds += 604800000; 164 | 165 | Milliseconds = TransmitTime.MilliSeconds + (GalileoE1Signal ? 1000 : 0); // E1 page has 1000ms bias to week boundary 166 | FrameNumber = Milliseconds / Attribute->FrameLength; // subframe/page number 167 | Milliseconds %= Attribute->FrameLength; 168 | BitNumber = Milliseconds / BitLength; // current bit position within current subframe/page 169 | Milliseconds %= BitLength; 170 | BitPos = Milliseconds / Attribute->CodeLength; // coded round in data bit 171 | 172 | if (FrameNumber != CurrentFrame) 173 | { 174 | if (NavData) 175 | NavData->GetFrameData(TransmitTime, Svid, Param, DataBits); 176 | CurrentFrame = FrameNumber; 177 | } 178 | 179 | DataBit = (DataBits[BitNumber] ? -1 : 1) * ((Attribute->NHCode & (1 << BitPos)) ? -1 : 1); 180 | if (SecondaryCode) 181 | { 182 | SecondaryPosition = (TransmitTime.MilliSeconds / Attribute->CodeLength) % SecondaryLength; // position in secondary code 183 | PilotBit = (SecondaryCode[SecondaryPosition / 32] & (1 << (SecondaryPosition & 0x1f))) ? -1 : 1; 184 | } 185 | 186 | // generate DataSignal and PilotSignal 187 | // the signal of data and pilot complex value will reflect their relative amplitude and phase 188 | // if the signal has only data channel, assume the data channel has 0 phase 189 | // if the signal has both data channel and pilot channel, the pilot channel has 0 phase 190 | // the overall data+pilot power is 1 (except for the case that need to deduct BOC(6,1) element) 191 | // signal and navigation bit match 192 | switch (SatSystem) 193 | { 194 | case GpsSystem: 195 | switch (SatSignal) 196 | { 197 | case SIGNAL_INDEX_L1CA: 198 | DataSignal = complex_number((double)DataBit, 0); 199 | PilotSignal = complex_number(0, 0); 200 | break; 201 | case SIGNAL_INDEX_L1C: 202 | DataSignal = complex_number(DataBit * AMPLITUDE_1_4, 0); 203 | PilotSignal = complex_number(PilotBit * AMPLITUDE_29_44, 0); 204 | break; 205 | case SIGNAL_INDEX_L2C: 206 | DataSignal = complex_number(DataBit * AMPLITUDE_1_2, 0); 207 | PilotSignal = complex_number(AMPLITUDE_1_2, 0); 208 | break; 209 | case SIGNAL_INDEX_L5: 210 | DataSignal = complex_number(0, DataBit * AMPLITUDE_1_2); 211 | PilotSignal = complex_number(PilotBit * AMPLITUDE_1_2, 0); 212 | break; 213 | } 214 | break; 215 | case BdsSystem: 216 | switch (SatSignal) 217 | { 218 | case SIGNAL_INDEX_B1C: 219 | DataSignal = complex_number(0, -DataBit * AMPLITUDE_1_4); 220 | PilotSignal = complex_number(PilotBit * AMPLITUDE_29_44, 0); 221 | break; 222 | case SIGNAL_INDEX_B1I: 223 | case SIGNAL_INDEX_B2I: 224 | case SIGNAL_INDEX_B3I: 225 | DataSignal = complex_number((double)DataBit, 0); 226 | PilotSignal = complex_number(0, 0); 227 | break; 228 | case SIGNAL_INDEX_B2a: 229 | DataSignal = complex_number(0, -DataBit * AMPLITUDE_1_2); 230 | PilotSignal = complex_number(PilotBit * AMPLITUDE_1_2, 0); 231 | break; 232 | case SIGNAL_INDEX_B2b: 233 | DataSignal = complex_number(0, -DataBit * AMPLITUDE_1_2); // B2b nominal power is 3dB lower than B2a, phase align with B2a data 234 | PilotSignal = complex_number(0, 0); 235 | break; 236 | } 237 | break; 238 | case GalileoSystem: 239 | switch (SatSignal) 240 | { 241 | case SIGNAL_INDEX_E1 : 242 | DataSignal = complex_number(-DataBit * AMPLITUDE_1_2, 0); 243 | PilotSignal = complex_number(PilotBit * AMPLITUDE_1_2, 0); 244 | break; 245 | case SIGNAL_INDEX_E5a: 246 | case SIGNAL_INDEX_E5b: 247 | DataSignal = complex_number(0, -DataBit * AMPLITUDE_1_2); 248 | PilotSignal = complex_number(PilotBit * AMPLITUDE_1_2, 0); 249 | break; 250 | case SIGNAL_INDEX_E6 : 251 | DataSignal = complex_number(0, 0); 252 | PilotSignal = complex_number(PilotBit * AMPLITUDE_1_2, 0); 253 | break; 254 | } 255 | break; 256 | case GlonassSystem: 257 | switch (SatSignal) 258 | { 259 | case SIGNAL_INDEX_G1 : 260 | case SIGNAL_INDEX_G2 : 261 | DataSignal = complex_number((double)DataBit, 0); 262 | PilotSignal = complex_number(0, 0); 263 | break; 264 | } 265 | break; 266 | } 267 | 268 | return TRUE; 269 | } 270 | -------------------------------------------------------------------------------- /src/XmlArguments.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------- 2 | // XmlArguments.cpp: 3 | // Definition of XML file arguments (attribute keys and values, element name) 4 | // 5 | // Copyright (C) 2020-2029 by Jun Mo, All rights reserved. 6 | // 7 | //---------------------------------------------------------------------- 8 | 9 | #include "XmlInterpreter.h" 10 | 11 | const char *FlexibleName[] = { "" }; 12 | const char *SystemType[] = { "GPS", "BDS", "Galileo", "GLONASS", "UTC" }; 13 | const char *InitPosType[] = { "LLA", "ECEF" }; 14 | const char *LatLonType[] = { "d", "dm", "dms" }; 15 | const char *InitVelType[] = { "SCU", "ENU", "ECEF" }; 16 | const char *SpeedUnit[] = { "mps", "kph", "knot", "mph" }; 17 | const char *AngleUnit[] = { "degree", "rad" }; 18 | const char *EphSrc[] = { "file" }; 19 | const char *EphType[] = { "RINEX" }; 20 | const char *OutputTypeStr[] = { "position", "observation" }; 21 | const char *OutputFormatStr[] = { "ECEF", "LLA", "NMEA", "KML", "RINEX" }; 22 | const char *TimeUnit[] = { "s", "ms" }; 23 | const char *ChannelEnable[] = { "auto", "true" }; 24 | const char *FreqIDs[] = { "L1CA", "L1C", "L2C", "L2P", "L5", "", "", "", 25 | "B1C", "B1I", "B2I", "B3I", "B2a", "B2b", "", "", 26 | "E1", "E5a", "E5b", "E5", "E6", "", "", "", 27 | "G1", "G2", "G3", "", "", "", "", "", }; 28 | 29 | ATTRIBUTE_TYPE TimeTypeAttr = { "type", SystemType, sizeof(SystemType) / sizeof(char *), 0 }; 30 | ATTRIBUTE_TYPE TrajectoryNameAttr = { "name", FlexibleName, sizeof(FlexibleName) / sizeof(char *), -1 }; 31 | ATTRIBUTE_TYPE InitPosTypeAttr = { "type", InitPosType, sizeof(InitPosType) / sizeof(char *), 0 }; 32 | ATTRIBUTE_TYPE LatLonTypeAttr = { "type", LatLonType, sizeof(LatLonType) / sizeof(char *), 0 }; 33 | ATTRIBUTE_TYPE InitVelTypeAttr = { "type", InitVelType, sizeof(InitVelType) / sizeof(char *), 0 }; 34 | ATTRIBUTE_TYPE SpeedUnitAttr = { "unit", SpeedUnit, sizeof(SpeedUnit) / sizeof(char *), 0 }; 35 | ATTRIBUTE_TYPE CourseUnitAttr = { "unit", AngleUnit, sizeof(AngleUnit) / sizeof(char *), 0 }; 36 | ATTRIBUTE_TYPE EphSrcAttr = { "source", EphSrc, sizeof(EphSrc) / sizeof(char *), 0 }; 37 | ATTRIBUTE_TYPE EphTypeAttr = { "type", EphType, sizeof(EphType) / sizeof(char *), 0 }; 38 | ATTRIBUTE_TYPE OutputTypeAttr = { "type", OutputTypeStr, sizeof(OutputTypeStr) / sizeof(char *), -1 }; 39 | ATTRIBUTE_TYPE OutputFormatAttr = { "format", OutputFormatStr, sizeof(OutputFormatStr) / sizeof(char *), 0 }; 40 | ATTRIBUTE_TYPE IntervalUnitAttr = { "unit", TimeUnit, sizeof(TimeUnit) / sizeof(char *), 0 }; 41 | ATTRIBUTE_TYPE ElevationMaskAttr = { "unit", AngleUnit, sizeof(AngleUnit) / sizeof(char *), 0 }; 42 | ATTRIBUTE_TYPE SystemAttr = { "system", SystemType, sizeof(SystemType) / sizeof(char *), 0 }; 43 | ATTRIBUTE_TYPE SvidAttr = { "svid", FlexibleName, sizeof(FlexibleName) / sizeof(char *), -1 }; 44 | ATTRIBUTE_TYPE FreqIDAttr = { "freq", FreqIDs, sizeof(FreqIDs) / sizeof(char *), -1 }; 45 | ATTRIBUTE_TYPE ChannelEnableAttr = { "enable", ChannelEnable, sizeof(ChannelEnable) / sizeof(char *), 0 }; 46 | 47 | PATTRIBUTE_TYPE InitTimeAttributes[] = { &TimeTypeAttr, NULL }; 48 | PATTRIBUTE_TYPE TrajectoryAttributes[] = { &TrajectoryNameAttr, NULL }; 49 | PATTRIBUTE_TYPE InitPosTypeAttributes[] = { &InitPosTypeAttr, NULL }; 50 | PATTRIBUTE_TYPE LatLonTypeAttributes[] = { &LatLonTypeAttr, NULL }; 51 | PATTRIBUTE_TYPE InitVelTypeAttributes[] = { &InitVelTypeAttr, NULL }; 52 | PATTRIBUTE_TYPE SpeedUnitAttributes[] = { &SpeedUnitAttr, NULL }; 53 | PATTRIBUTE_TYPE CourseUnitAttributes[] = { &CourseUnitAttr, NULL }; 54 | PATTRIBUTE_TYPE EphAttributes[] = { &EphSrcAttr, &EphTypeAttr, NULL }; 55 | PATTRIBUTE_TYPE OutputAttributes[] = { &OutputTypeAttr, &OutputFormatAttr, NULL }; 56 | PATTRIBUTE_TYPE SatelliteAttributes[] = { &SystemAttr, &SvidAttr, NULL }; 57 | PATTRIBUTE_TYPE BasebandConfigAttributes[] = { &TimeTypeAttr, NULL }; 58 | PATTRIBUTE_TYPE ElevationMaskAttributes[] = { &ElevationMaskAttr, NULL }; 59 | PATTRIBUTE_TYPE SystemAttributes[] = { &SystemAttr, NULL }; 60 | PATTRIBUTE_TYPE FreqIDAttributes[] = { &SystemAttr, &FreqIDAttr, NULL }; 61 | PATTRIBUTE_TYPE ChannelInitAttributes[] = { &SystemAttr, &SvidAttr, &ChannelEnableAttr, NULL }; 62 | 63 | const char *StartTimeElements[] = { "Week", "LeapYear", "Day", "Second", "Year", "Month", "Hour", "Minute", NULL }; 64 | const char *StartPosElements[] = { "Longitude", "Latitude", "Altitude", "x", "y", "z", NULL }; 65 | const char *StartVelElements[] = { "Speed", "Course", "East", "North", "Up", NULL }; 66 | const char *TrajectoryElements[] = { "InitPosition", "InitVelocity", "TrajectoryList", NULL }; 67 | const char *TrajectoryTypeElements[] = { "Const", "ConstAcc", "VerticalAcc", "Jerk", "HorizontalTurn", NULL }; 68 | const char *TrajectoryArgumentElements[] = { "TimeSpan", "Acceleration", "Speed", "AccRate", "TurnAngle", "AngularRate", "Radius", NULL }; 69 | const char *OutputParamElements[] = { "Interval", "Name", "ConfigParam", "SystemSelect", NULL }; 70 | const char *ConfigParamElements[] = { "ElevationMask", "MaskOut", NULL }; 71 | const char *PowerControlElements[] = { "PowerParam", "SignalPower", NULL }; 72 | const char *PowerParamElements[] = { "NoiseFloor", "InitPower", "ElevationAdjust", NULL }; 73 | const char *SignalPowerElements[] = { "Time", "Power", NULL }; 74 | const char *DelayConfigElements[] = { "SystemDelay", "ReceiverDelay", NULL }; 75 | const char *BasebandConfigElements[] = { "ChannelNumber", "CorrelatorNumber", "NoiseFloor", NULL }; 76 | const char *SatInitElements[] = { "CorrelatorInterval", "PeakCorrelator", "InitFreqError", "InitPhaseError", "InitCodeError", "SNR", NULL }; 77 | 78 | ELEMENT_PROCESS RootProcess[] = { 79 | { "Time", &ElementProcTime, NULL}, 80 | { "Trajectory", &ElementProcTrajectory, NULL}, 81 | { "Ephemeris", &ElementProcEphemeris, NULL}, 82 | { "Output", &ElementProcOutput, NULL}, 83 | { "BasebandConfig", &ElementProcBasebandConfig, NULL}, 84 | { "ChannelInit", &ElementProcSatInitParam, NULL}, 85 | }; 86 | 87 | INTERPRETE_PARAM RootInterpretParam = { NULL, 0, RootProcess, sizeof(RootProcess) / sizeof(ELEMENT_PROCESS) }; 88 | INTERPRETE_PARAM InitTimeParam = { InitTimeAttributes, sizeof(InitTimeAttributes) / sizeof(PATTRIBUTE_TYPE), RootProcess, sizeof(RootProcess) / sizeof(ELEMENT_PROCESS) }; 89 | -------------------------------------------------------------------------------- /卫星信号仿真平台SignalSim设计说明.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/globsky/SignalSim/3f82005b3b69a3c22218bda4fb133b34a79098a0/卫星信号仿真平台SignalSim设计说明.pdf --------------------------------------------------------------------------------