diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..412eeda --- /dev/null +++ b/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e4332de --- /dev/null +++ b/.gitignore @@ -0,0 +1,72 @@ +############ +## Windows +############ + +# Windows image file caches +Thumbs.db +*.o + +# Folder config file +Desktop.ini + +################# +## Visual Studio +################# + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +# User-specific files +**/Debug +**/Release +**/packages +**/.vs +*.tlog +*.obj +*.log +*.lastbuildstate +*.manifest +*.cache +*.users +*.user +*.res +*.opendb +*.db +*.unsuccessfulbuild +*.ipch +*.pdb +*.exp +*.ilk +*.idb +*.opensdf +*.sdf +*.u2d +*.suo +*.tiff +*.aps + +################ +# Linux and OSX +############### +\.DS* +*.so +*.d + + +# Created by https://www.gitignore.io + +### Xcode ### +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.xcuserstate + diff --git a/ERRORS_AND_WARNINGS.md b/ERRORS_AND_WARNINGS.md new file mode 100644 index 0000000..6c6f030 --- /dev/null +++ b/ERRORS_AND_WARNINGS.md @@ -0,0 +1,56 @@ +# Return Codes and Warning Flags # + +## Return Codes ## + +ITM supports the following list of return codes. + +| Value | Const Name | Description | +| ------|----------------------------------|--------------| +| 0 | `SUCCESS` | Successful execution | +| 1 | `SUCCESS_WITH_WARNINGS` | Successful execution, but warning flags set | +| 1000 | `ERROR__TX_TERMINAL_HEIGHT` | TX terminal height is out of range | +| 1001 | `ERROR__RX_TERMINAL_HEIGHT` | RX terminal height is out of range | +| 1002 | `ERROR__INVALID_RADIO_CLIMATE` | Invalid value for radio climate | +| 1003 | `ERROR__INVALID_TIME` | Time percentage is out of range | +| 1004 | `ERROR__INVALID_LOCATION` | Location percentage is out of range | +| 1005 | `ERROR__INVALID_SITUATION` | Situation percentage is out of range | +| 1006 | `ERROR__INVALID_CONFIDENCE` | Confidence percentage is out of range | +| 1007 | `ERROR__INVALID_RELIABILITY` | Reliability percentage is out of range | +| 1008 | `ERROR__REFRACTIVITY` | Refractivity is out of range | +| 1009 | `ERROR__FREQUENCY` | Frequency is out of range | +| 1010 | `ERROR__POLARIZATION` | Invalid value for polarization | +| 1011 | `ERROR__EPSILON` | Epsilon is out of range | +| 1012 | `ERROR__SIGMA` | Sigma is out of range | +| 1013 | `ERROR__GROUND_IMPEDANCE` | The imaginary portion of the complex impedance is larger than the real portion | +| 1014 | `ERROR__MDVAR` | Invalid value for mode of variability | +| 1015 | `ERROR__MDVAR_BROADCAST_MODE` | Broadcast variability modes are not supported in confidence/reliability functions | +| 1016 | `ERROR__EFFECTIVE_EARTH` | Internally computed effective earth radius is invalid | +| 1017 | `ERROR__PATH_DISTANCE` | Path distance is out of range | +| 1018 | `ERROR__DELTA_H` | Delta H (terrain irregularity parameter) is out of range | +| 1019 | `ERROR__TX_SITING_CRITERIA` | Invalid value for TX siting criteria | +| 1020 | `ERROR__RX_SITING_CRITERIA` | Invalid value for RX siting criteria | +| 1021 | `ERROR__SURFACE_REFRACTIVITY_SMALL` | Internally computed surface refractivity value is too small | +| 1022 | `ERROR__SURFACE_REFRACTIVITY_LARGE` | Internally computed surface refractivity value is too large | + +## Warning Flags ## + +In addition to return codes, ITM supports return warning flags to the caller. Warning flags are bitwise set, allowing the ITM model to return multiple warnings for a single function call. Warning flags only need to be parsed if a return code of `SUCCESS_WITH_WARNINGS` is returned by a function call. + +| Value | Const Name | Description | +| -------|----------------------------------|--------------| +| 0x0000 | `NO_WARNINGS` | No warning flags | +| 0x0001 | `WARN__TX_TERMINAL_HEIGHT` | TX terminal height is near its limits | +| 0x0002 | `WARN__RX_TERMINAL_HEIGHT` | RX terminal height is near its limits | +| 0x0004 | `WARN__FREQUENCY` | Frequency is near its limits | +| 0x0008 | `WARN__PATH_DISTANCE_TOO_BIG_1` | Path distance is near its upper limit | +| 0x0010 | `WARN__PATH_DISTANCE_TOO_BIG_2` | Path distance is large - care must be taken with result | +| 0x0020 | `WARN__PATH_DISTANCE_TOO_SMALL_1` | Path distance is near its lower limit | +| 0x0040 | `WARN__PATH_DISTANCE_TOO_SMALL_2` | Path distance is small - care must be taken with result +| 0x0080 | `WARN__TX_HORIZON_ANGLE` | TX horizon angle is large - small angle approximations could break down | +| 0x0100 | `WARN__RX_HORIZON_ANGLE` | RX horizon angle is large - small angle approximations could break down | +| 0x0200 | `WARN__TX_HORIZON_DISTANCE_1` | TX horizon distance is less than 1/10 of the smooth earth horizon distance | +| 0x0400 | `WARN__RX_HORIZON_DISTANCE_1` | RX horizon distance is less than 1/10 of the smooth earth horizon distance | +| 0x0800 | `WARN__TX_HORIZON_DISTANCE_2` | TX horizon distance is greater than 3 times the smooth earth horizon distance | +| 0x1000 | `WARN__RX_HORIZON_DISTANCE_2` | RX horizon distance is greater than 3 times the smooth earth horizon distance | +| 0x2000 | `WARN__EXTREME_VARIABILITIES` | One of the provided variabilities is located far in the tail of its distribution | +| 0x4000 | `WARN__SURFACE_REFRACTIVITY` | Internally computed surface refractivity value is small - care must be taken with result | diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..12746a1 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,14 @@ +SOFTWARE DISCLAIMER / RELEASE + +This software was developed by employees of the National Telecommunications and Information Administration (NTIA), an agency of the Federal Government and is provided to you as a public service. Pursuant to Title 15 United States Code Section 105, works of NTIA employees are not subject to copyright protection within the United States. + +The software is provided by NTIA “AS IS.” NTIA MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT AND DATA ACCURACY. NTIA does not warrant or make any representations regarding the use of the software or the results thereof, including but not limited to the correctness, accuracy, reliability or usefulness of the software. + +To the extent that NTIA holds rights in countries other than the United States, you are hereby granted the non-exclusive irrevocable and unconditional right to print, publish, prepare derivative works and distribute the NTIA software, in any medium, or authorize others to do so on your behalf, on a royalty-free basis throughout the World. + +You may improve, modify, and create derivative works of the software or any portion of the software, and you may copy and distribute such modifications or works. Modified works should carry a notice stating that you changed the software and should note the date and nature of any such change. + +You are solely responsible for determining the appropriateness of using and distributing the software and you assume all risks associated with its use, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and the unavailability or interruption of operation. This software is not intended to be used in any situation where a failure could cause risk of injury or damage to property. + +Please provide appropriate acknowledgments of NTIA’s creation of the software in any copies or derivative works of this software. + diff --git a/README.md b/README.md index 55ce412..55f0ced 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,115 @@ -# itm -The Irregular Terrain Model (ITM) +# ITS Irregular Terrain Model (ITM) # + +This code repository contains the ITS Irregular Terrain Model (ITM). ITM predicts terrestrial radiowave propagation for frequencies between 20 MHz and 20 GHz based on electromagnetic theory and empirical models developed by Anita Longley and Phil Rice. Propagation mechanisms considered include free space loss, diffraction, and troposcatter. Specifically, ITM predicts attenuation as a function of distance (greater than 1 km), terminal heights, meteorological conditions, terrain effects, and the variability of the signal in time and in space. + +**Note**: Verion 1.3 of this code base is functionally identical to version 1.2.2 of the FORTRAN source, which has been archived [here](https://github.com/NTIA/itm-longley-rice). ITS plans to apply all future ITM updates to this C++ code base. + +## Quick Start ## + +Users of ITM have two options to immediately begin using ITM: + +1. The ITM software is made available to the user as a precombiled DLL in the [Release](https://github.com/NTIA/itm/releases) page. A user can add this DLL to their own software project as a dependency and call ITM through its function definitions. Additionally, a C#/.NET software wrapper is provided. Distribution and updates of this wrapper code are provided through the published [NuGet package](https://github.com/NTIA/itm/packages). + +2. A supporting command-line driver is also included in this repository, with its own corresponding [readme](cmdREADME.md). This tool allows a user to call ITM without any programming required through the use of ASCII input/output files. + +A select set of example inputs and outputs are provide for testing purposes. This is not a comprehensive validation test set. For ITM in Point-to-Point Prediction Mode, [p2p.csv](p2p.csv) defines the set of inputs and outputs with [pfls.csv](pfls.csv) containing the corresponding set of terrain profiles. For Area Prediction Mode, inputs and outputs are defined in [area.csv](area.csv). + +## Inputs ## + +ITM can be called in either Area Prediction Mode or Point-to-Point Prediction Mode. Additionally, variabilities can be defined by either time/location/situation or confidence/reliability. The below inputs are organized accordingly. + +### Common Inputs ### + +| Variable | Type | Units | Limits | Description | +|-------------------|--------|-------|--------------|--------------| +| `h_tx__meter` | double | meter | 0.5 <= `h_tx__meter` <= 3000 | Structural height of the TX | +| `h_rx__meter` | double | meter | 0.5 <= `h_rx__meter` <= 3000 | Structural height of the RX | +| `climate` | int | | enum | Radio climate of the path | +| `N_0` | double | N-Units | 250 <= `N_0` <= 400 | Minimum monthly mean surface refractivity reduced to sea level | +| `f__mhz` | double | MHz | 20 <= `f__mhz` <= 20000 | Frequency | +| `pol` | int | | enum | Polarization | +| `epsilon` | double | | 1 < `epsilon` | Relative permittivity | +| `sigma` | double | S/m | 0 < `sigma` | Conductivity | +| `mdvar` | int | | enum | Mode of variability Additionally, +10 if location variability is to be eliminated, and +20 if direct situation variability is to be eliminated | + +### Point-to-Point Mode Specific Inputs ### + +| Variable | Type | Units | Limits | Description | +|-------------------|--------|-------|--------------|--------------| +| `pfl` | double[] | | | Terrain profile data in PFL format, from TX to RX | + +### Area Mode Inputs ### + +| Variable | Type | Units | Limits | Description | +|-------------------|--------|-------|--------------|--------------| +| `d__km` | double | km | 0 < `d__km` | Path distance | +| `delta_h__meter` | double | meter | 0 <= `delta_h__meter` | Terrain irregularity parameter | +| `tx_siting_criteria` | int | | enum | Siting criteria of TX | +| `rx_siting_criteria` | int | | enum | Siting criteria of RX | + +### Variability Inputs ### + +A user either supplies values for time/location/situation or confidence/reliability. + +| Variable | Type | Units | Limits | Description | +|-------------------|--------|-------|--------------|--------------| +| `time` | double | | 0 < `time` < 100 | Time variability | +| `location` | double | | 0 < `location` < 100 | Location variability | +| `situation` | double | | 0 < `situation` < 100 | Situation variability | +| `confidence` | double | | 0 < `confidence` < 100 | Confidence variability | +| `reliability` | double | | 0 < `reliability` < 100 | Reliability variability | + +## Outputs ## + +| Variable | Type | Units | Description | +|---------------|--------|-------|-------------| +| `A__db` | double | dB | Basic transmission loss | +| `warnings` | int | | Warning flags | + +## Intermediate Values ## + +Internal intermediate values can be extracted from ITM via functions that are suffixed with `_Ex`. These functions will populate the `IntermediateValues` data structure with intermediate values from the ITM calculations. + +| Variable | Type | Units | Description | +|------------------|-----------|-------------|-------------| +| `theta_hzn` | double[] | radians | Terminal horizon angles | +| `d_hzn__meter` | double[] | meter | Terminal horizon distances | +| `h_e__meter` | double[] | meter | Effective terminal heights | +| `N_s` | double | N-Units | Surface refractivity | +| `delta_h__meter` | double | meter | Terrain irregularity parameter | +| `A_ref__db` | double | dB | Reference attenuation | +| `A_fs__db` | double | dB | Free space basic transmission loss | +| `d__km` | double | km | Path distance | +| `mode` | int | | Mode of propagation | + +## Error Codes and Warning Flags ## + +ITM supports a defined list of error codes and warning flags. A complete list can be found [here](ERRORS_AND_WARNINGS.md). + +## Notes on Code Style ## + +* In general, variables follow the naming convention in which a single underscore denotes a subscript (pseudo-LaTeX format), and where a double underscore is followed by the units, i.e. h_tx__meter. +* Variables are named to match their corresponding mathematical variables in the underlying references. +* Wherever possible, equation numbers and source documentation are provided. + +## Configure and Build ## + +### C++ Software ### + +The software is designed to be built into a DLL (or corresponding library for non-Windows systems). The source code can be built for any OS that supports the standard C++ libraries. A Visual Studio 2019 project file is provided for Windows users to support the build process and configuration. + +### C#/.NET Wrapper Software ### + +The .NET support of ITM consists of a simple pass-through wrapper around the native DLL. It is compiled to target .NET Framework 4.7.2. + +## References ## + +* G.A. Hufford, A.G. Longley, W.A. Kissick, [A Guide to the Use of the ITS Irregular Terrain Model in the Area Prediction Mode](https://www.its.bldrdoc.gov/publications/details.aspx?pub=2091), NTIA Technical Report TR-82-100, April 1982. +* G.A. Hufford, [The ITS Irregular Terrain Model, version 1.2.2 Algorithm](https://www.its.bldrdoc.gov/media/50676/itm_alg.pdf). +* G.A. Hufford, [1985 ITM Memo](https://www.its.bldrdoc.gov/media/50675/Hufford_1985_Memo.pdf), Dr. George Hufford's 1985 Memo describing the changes to ITM version 1.2.1 (dated April, 1979) in ITM version 1.2.2 (dated September, 1984) +* G.A. Hufford, [The Irregular Terrain Model](https://www.its.bldrdoc.gov/media/50674/itm.pdf), The "definitive" representation of the ITS Irregular Terrain Model. It contains both the source code and rather extensive documentation. +* A.G. Longley and P.L. Rice, [Prediction of Tropospheric Radio Transmission Loss Over Irregular Terrain: A Computer Method - 1968](https://www.its.bldrdoc.gov/publications/details.aspx?pub=2784), NTIA Technical Report ERL 79-ITS 67, July 1968. + +## Contact ## + +For technical questions about ITM, contact Paul McKenna, (303) 497-3474, pmckenna@ntia.gov. diff --git a/cmdREADME.md b/cmdREADME.md new file mode 100644 index 0000000..81247a3 --- /dev/null +++ b/cmdREADME.md @@ -0,0 +1,108 @@ +# ITM Command-line Driver # + +This readme explains the use of the ITM command-line driver. This is a supplemental software tool to allow a user to call the ITM DLL from the command-line with inputs specified in supporting file formats. + +## Input Files ## + +Inputs to the command-line driver are specified in an ASCII text file using the common `key,value` format. Each line holds a single `key,value` combination, with the `key` representing the model input variable name and the `value` representing its value. The driver will automatically detect whether ITM should be called specifying variability in time/location/situation or confidence/reliability based on the input parameters specified. + +## Output Files ## + +After parsing the inputs and calling ITM, the command-line driver will generate an output report file containing the results. This results file contains inputs params, output params, and human-readable supporting documentation. + +## Execution ## + +Executing the ITM command-line driver requires specifying input arguments, defined in the below table: + +| Flag | Type | Required? | Description | +|---------|--------|-----------|--------------| +| `-i` | string | True | File specifying model input parameters in `key,value` format | +| `-o` | string | True | Filename where output results should be written | +| `-mode` | enum | True | Specify the prediction mode of ITM. | +| `-t` | string | False | File containing terrain information in PFL format. Only needed if using point-to-point mode | +| `-dbg` | | False | If flag is specified, the intermediate data structure values will be written to the output file | + +Input arguments are not case sensitive and do not have to be specified in a certain order. A generic example of calling the ITM command-line driver is: + +``` +ITMDrvr.exe -i -t -o -mode P2P +``` + +### Examples ### + +| Input File | Terrain File | Output File | Arguments | +|------------|--------------|-------------|-----------| +| [`i_p2ptls.txt`](/cmd_examples/i_p2ptls.txt) | [`pfl.txt`](/cmd_examples/pfl.txt) | [`o_p2ptls.txt`](/cmd_examples/o_p2ptls.txt) | `-i i_p2ptls.txt -t pfl.txt -o o_p2ptls.txt -mode P2P -dbg` | +| [`i_p2pcr.txt`](/cmd_examples/i_p2pcr.txt) | [`pfl.txt`](/cmd_examples/pfl.txt) | [`o_p2pcr.txt`](/cmd_examples/o_p2pcr.txt) | `-i i_p2pcr.txt -t pfl.txt -o o_p2pcr.txt -mode P2P -dbg` | +| [`i_p2pcr_tbl.txt`](/cmd_examples/i_p2pcr_tbl.txt) | [`pfl.txt`](/cmd_examples/pfl.txt) | [`o_p2pcr_tbl.txt`](/cmd_examples/o_p2pcr_tbl.txt) | `-i i_p2pcr_tbl.txt -t pfl.txt -o o_p2pcr_tbl.txt -mode P2P -dbg` | +| [`i_areatls.txt`](/cmd_examples/i_areatls.txt) | | [`o_areatls.txt`](/cmd_examples/o_areatls.txt) | `-i i_areatls.txt -o o_areatls.txt -mode AREA -dbg` | +| [`i_areacr.txt`](/cmd_examples/i_areacr.txt) | | [`o_areacr.txt`](/cmd_examples/o_areacr.txt) | `-i i_areacr.txt -o i_areacr.txt -mode AREA -dbg` | +| [`i_areacr_tbl.txt`](/cmd_examples/i_areacr_tbl.txt) | | [`o_areacr_tbl.txt`](/cmd_examples/o_areacr_tbl.txt) | `-i i_areacr_tbl.txt -o o_areacr_tbl.txt -mode AREA` | + +## Command-line Driver Errors ## + +In addition to the ITM DLL [errors](ERRORS_AND_WARNINGS.md), the ITM command-line driver defines the following list of return codes. + +### General Errors ### + +| Value | Const Name | Description | +| ------|-----------------------------------|--------------| +| 0 | `SUCCESS` | Successful execution | +| 1001 | `DRVRERR__DLL_LOADING` | Failed to load itm.dll | +| 1002 | `DRVRERR__MAJOR_VERSION_MISMATCH` | The major version number of the ITM driver and DLL do not match | +| 1003 | `DRVRERR__INVALID_OPTION` | Unknown option specified | +| 1004 | `DRVRERR__GET_P2P_TLS_FUNC_LOADING` | Failed to load point-to-point TLS function | +| 1005 | `DRVRERR__GET_P2P_CR_FUNC_LOADING` | Failed to load point-to-point CR function | +| 1006 | `DRVRERR__GET_AREA_TLS_FUNC_LOADING` | Failed to load area TLS function | +| 1007 | `DRVRERR__GET_AREA_CR_FUNC_LOADING` | Failed to load area CR function | +| 1008 | `DRVRERR__PARSE_MODE_VALUE` | Invalid value for `-mode` argument | + +### Input File Parsing Errors ### + +| Value | Const Name | Description | +| ------|-----------------------------------|--------------| +| 1101 | `DRVRERR__PARSE_HTX` | Unable to parse transmitter height | +| 1102 | `DRVRERR__PARSE_HRX` | Unable to parse receiver height | +| 1103 | `DRVRERR__PARSE_CLIMATE` | Unable to parse climate | +| 1104 | `DRVRERR__PARSE_N0` | Unable to parse refractivity | +| 1105 | `DRVRERR__PARSE_FREQ` | Unable to parse frequency | +| 1106 | `DRVRERR__PARSE_POL` | Unable to parse polarization | +| 1107 | `DRVRERR__PARSE_EPSILON` | Unable to parse relative permittivity | +| 1108 | `DRVRERR__PARSE_SIGMA` | Unable to parse conductivity | +| 1109 | `DRVRERR__PARSE_MDVAR` | Unable to parse mode of variability | +| 1110 | `DRVRERR__PARSE_TIME` | Unable to parse time | +| 1111 | `DRVRERR__PARSE_LOCATION` | Unable to parse location | +| 1112 | `DRVRERR__PARSE_SITUATION` | Unable to parse situation | +| 1113 | `DRVRERR__PARSE_CONFIDENCE` | Unable to parse confidence | +| 1114 | `DRVRERR__PARSE_RELIABILITY` | Unable to parse reliability | +| 1115 | `DRVRERR__PARSE_TX_SITE` | Unable to parse transmitter siting criteria | +| 1116 | `DRVRERR__PARSE_RX_SITE` | Unable to parse receiver siting criteria | +| 1117 | `DRVRERR__PARSE_DKM` | Unable to parse path distance | +| 1118 | `DRVRERR__PARSE_DELTAH` | Unable to parse terrain irregularity parameter | +| 1119 | `DRVRERR__PARSE_INCOMPLETE_DISTANCES` | Invalid specification of multiple distance values | + +### Validation Errors ### + +Driver validation errors occur when required input parameters are missing. The validation of the parameters values does not occur until _after_ they are passed to ITM. + +| Value | Const Name | Description | +| ------|-----------------------------------|--------------| +| 1201 | `DRVRERR__VALIDATION_MODE` | Prediction mode is not specified | +| 1202 | `DRVRERR__VALIDATION_IN_FILE` | Input parameter file is not specified | +| 1203 | `DRVRERR__VALIDATION_OUT_FILE` | Output file is not specified | +| 1204 | `DRVRERR__VALIDATION_TERRAIN_FILE` | Terrain file is not specified | +| 1205 | `DRVRERR__VALIDATION_HTX` | Transmitter height (`h_tx__meter`) is required but missing from input parameter file | +| 1206 | `DRVRERR__VALIDATION_HRX` | Receiver height (`h_rx__meter`) is required but missing from input parameter file | +| 1207 | `DRVRERR__VALIDATION_CLIMATE` | Radio climate (`climate`) is required but missing from input parameter file | +| 1208 | `DRVRERR__VALIDATION_N0` | Refractivity (`N_0`) is required but missing from input parameter file | +| 1209 | `DRVRERR__VALIDATION_FMHZ` | Frequency (`f__mhz`) is required but missing from input parameter file | +| 1210 | `DRVRERR__VALIDATION_POL` | Polarization (`pol`) is required but missing from input parameter file | +| 1211 | `DRVRERR__VALIDATION_EPSILON` | Relative permittivity (`epsilon`) is required but missing from input parameter file | +| 1212 | `DRVRERR__VALIDATION_SIGMA` | Conductivity (`sigma`) is required but missing from input parameter file | +| 1213 | `DRVRERR__VALIDATION_MDVAR` | Mode of variability (`mdvar`) is required but missing from input parameter file | +| 1214 | `DRVRERR__VALIDATION_TLS_AND_CR` | Provided both time/location/situation parameters and confidence/reliability | +| 1215 | `DRVRERR__VALIDATION_TLS_OR_CR` | Must provide time/location/situation parameters or confidence/reliability | +| 1216 | `DRVRERR__VALIDATION_HTX_SITE` | Transmitter siting criteria (`tx_siting_criteria`) is required but missing from input parameter file | +| 1217 | `DRVRERR__VALIDATION_RTX_SITE` | Receiver siting criteria (`rx_siting_criteria`) is required but missing from input parameter file | +| 1218 | `DRVRERR__VALIDATION_DKM` | Path distance (`d__km`) is required but missing from input parameter file | +| 1219 | `DRVRERR__VALIDATION_DELTAH` | Terrain irregularity parameter (`delta_h`) is required but missing from input parameter file | diff --git a/cmd_examples/i_areacr.txt b/cmd_examples/i_areacr.txt new file mode 100644 index 0000000..634f3e1 --- /dev/null +++ b/cmd_examples/i_areacr.txt @@ -0,0 +1,41 @@ +itm.dll Version v1.3 +ITMDrvr.exe Version v1.3.0 +Date Generated Mon Sep 21 22:01:28 2020 +Input Arguments -i i_areacr.txt -o i_areacr.txt -mode area -dbg + +Inputs +h_tx__meter 3 (meters) +h_rx__meter 3 (meters) +tx_site_criteria 0 [Random] +rx_site_criteria 0 [Random] +d__km 1 (km) +delta_h__meter 0 (meters) +climate 5 [Continental Temperate] +N_0 301.00 (N-Units) +f__mhz 10000.00 (MHz) +pol 1 [Vertical] +epsilon 15 +sigma 0.005 +mdvar 3 [Broadcast Mode] +confidence 77 +reliability 90 +Mode Area + +Results +ITM Warning Flags 0x0000 [No Warnings] +ITM Return Code 0 [Success - No Errors] +Basic Transmission Loss 118.3 (dB) + +Intermediate Values +Free Space 112.5 (dB) +d__km 1.000 (km) +theta_hzn_tx -0.841 (mrad) +theta_hzn_rx -0.841 (mrad) +d_hzn_tx__meter 7138 (meters) +d_hzn_rx__meter 7138 (meters) +h_e_tx__meter 3.0 (meters) +h_e_rx__meter 3.0 (meters) +N_s 301.0 (N-Units) +delta_h__meter 0.0 (meters) +A_ref__db 0.0 (dB) +Mode of Propagation 1 [Line of Sight] diff --git a/cmd_examples/i_areacr_tbl.txt b/cmd_examples/i_areacr_tbl.txt new file mode 100644 index 0000000..2652756 --- /dev/null +++ b/cmd_examples/i_areacr_tbl.txt @@ -0,0 +1,15 @@ +h_tx__meter,3 +h_rx__meter,3 +tx_site_criteria,0 +rx_site_criteria,0 +d__km,10,100,10,1000,100 +delta_h__meter,0 +climate,5 +N_0,301 +f__mhz,10000 +pol,1 +epsilon,15 +sigma,0.005 +mdvar,3 +reliability,90 +confidence,50,75,90 \ No newline at end of file diff --git a/cmd_examples/i_areatls.txt b/cmd_examples/i_areatls.txt new file mode 100644 index 0000000..e0feb48 --- /dev/null +++ b/cmd_examples/i_areatls.txt @@ -0,0 +1,16 @@ +h_tx__meter,15 +h_rx__meter,3 +tx_site_criteria,0 +rx_site_criteria,0 +d__km,10 +delta_h__meter,20 +climate,5 +N_0,301 +f__mhz,3500 +pol,1 +epsilon,15 +sigma,0.005 +mdvar,1 +time,50 +location,50 +situation,50 \ No newline at end of file diff --git a/cmd_examples/i_p2pcr.txt b/cmd_examples/i_p2pcr.txt new file mode 100644 index 0000000..55d1307 --- /dev/null +++ b/cmd_examples/i_p2pcr.txt @@ -0,0 +1,11 @@ +h_tx__meter,15 +h_rx__meter,3 +climate,5 +N_0,301 +f__mhz,3500 +pol,1 +epsilon,15 +sigma,0.005 +mdvar,1 +confidence,50 +reliability,50 \ No newline at end of file diff --git a/cmd_examples/i_p2pcr_tbl.txt b/cmd_examples/i_p2pcr_tbl.txt new file mode 100644 index 0000000..3327ef8 --- /dev/null +++ b/cmd_examples/i_p2pcr_tbl.txt @@ -0,0 +1,11 @@ +h_tx__meter,15 +h_rx__meter,3 +climate,5 +N_0,301 +f__mhz,3500 +pol,1 +epsilon,15 +sigma,0.005 +mdvar,1 +confidence,10,60,90 +reliability,10,65,90 \ No newline at end of file diff --git a/cmd_examples/i_p2ptls.txt b/cmd_examples/i_p2ptls.txt new file mode 100644 index 0000000..8128955 --- /dev/null +++ b/cmd_examples/i_p2ptls.txt @@ -0,0 +1,12 @@ +h_tx__meter,15 +h_rx__meter,3 +climate,5 +N_0,301 +f__mhz,3500 +pol,1 +epsilon,15 +sigma,0.005 +mdvar,1 +time,50 +location,50 +situation,50 \ No newline at end of file diff --git a/cmd_examples/o_areacr_tbl.txt b/cmd_examples/o_areacr_tbl.txt new file mode 100644 index 0000000..0fd6b9e --- /dev/null +++ b/cmd_examples/o_areacr_tbl.txt @@ -0,0 +1,49 @@ +itm.dll Version v1.3 +ITMDrvr.exe Version v1.3.0 +Date Generated Mon Sep 21 22:01:35 2020 +Input Arguments -i i_areacr_tbl.txt -o o_areacr_tbl.txt -mode area + +Inputs +h_tx__meter 3 (meters) +h_rx__meter 3 (meters) +tx_site_criteria 0 [Random] +rx_site_criteria 0 [Random] +d__km 10,100,10,1000,100 +delta_h__meter 0 (meters) +climate 5 [Continental Temperate] +N_0 301.00 (N-Units) +f__mhz 10000.00 (MHz) +pol 1 [Vertical] +epsilon 15 +sigma 0.005 +mdvar 3 [Broadcast Mode] +confidence 50,75,90 +reliability 90 +Mode Area + +Results +ITM Warning Flags 0x0000 [No Warnings] +ITM Return Code 0 [Success - No Errors] + +Basic Transmission Loss Results (dB) +Distance Free with Confidence + (km) Space 50 75 90 +10 132.4 147.0 151.7 155.9 +20 138.5 174.9 179.2 183.1 +30 142.0 198.7 202.9 206.7 +40 144.5 213.0 217.3 221.0 +50 146.4 215.8 220.0 223.8 +60 148.0 218.1 222.4 226.1 +70 149.4 220.1 224.4 228.1 +80 150.5 221.9 226.1 229.9 +90 151.5 223.4 227.7 231.4 +100 152.4 224.8 229.0 232.7 +200 158.5 234.6 238.5 241.9 +300 162.0 243.6 247.2 250.4 +400 164.5 252.0 255.6 258.7 +500 166.4 260.0 263.5 266.6 +600 168.0 267.5 271.0 274.1 +700 169.4 274.8 278.3 281.4 +800 170.5 281.9 285.3 288.4 +900 171.5 288.8 292.3 295.4 +1000 172.4 295.6 299.1 302.2 diff --git a/cmd_examples/o_areatls.txt b/cmd_examples/o_areatls.txt new file mode 100644 index 0000000..3652e83 --- /dev/null +++ b/cmd_examples/o_areatls.txt @@ -0,0 +1,42 @@ +itm.dll Version v1.3 +ITMDrvr.exe Version v1.3.0 +Date Generated Mon Sep 21 22:01:21 2020 +Input Arguments -i i_areatls.txt -o o_areatls.txt -mode area -dbg + +Inputs +h_tx__meter 15 (meters) +h_rx__meter 3 (meters) +tx_site_criteria 0 [Random] +rx_site_criteria 0 [Random] +d__km 10 (km) +delta_h__meter 20 (meters) +climate 5 [Continental Temperate] +N_0 301.00 (N-Units) +f__mhz 3500.00 (MHz) +pol 1 [Vertical] +epsilon 15 +sigma 0.005 +mdvar 1 [Accidental Mode] +time 50 +location 50 +situation 50 +Mode Area + +Results +ITM Warning Flags 0x0000 [No Warnings] +ITM Return Code 0 [Success - No Errors] +Basic Transmission Loss 134.5 (dB) + +Intermediate Values +Free Space 123.3 (dB) +d__km 10.000 (km) +theta_hzn_tx -1.811 (mrad) +theta_hzn_rx -0.567 (mrad) +d_hzn_tx__meter 14722 (meters) +d_hzn_rx__meter 6206 (meters) +h_e_tx__meter 15.0 (meters) +h_e_rx__meter 3.0 (meters) +N_s 301.0 (N-Units) +delta_h__meter 20.0 (meters) +A_ref__db 11.2 (dB) +Mode of Propagation 1 [Line of Sight] diff --git a/cmd_examples/o_p2pcr.txt b/cmd_examples/o_p2pcr.txt new file mode 100644 index 0000000..689123d --- /dev/null +++ b/cmd_examples/o_p2pcr.txt @@ -0,0 +1,38 @@ +itm.dll Version v1.3 +ITMDrvr.exe Version v1.3.0 +Date Generated Mon Sep 21 22:01:05 2020 +Input Arguments -i i_p2pcr.txt -t pfl.txt -o o_p2pcr.txt -mode p2p -dbg + +Inputs +h_tx__meter 15 (meters) +h_rx__meter 3 (meters) +climate 5 [Continental Temperate] +N_0 301.00 (N-Units) +f__mhz 3500.00 (MHz) +pol 1 [Vertical] +epsilon 15 +sigma 0.005 +mdvar 1 [Accidental Mode] +confidence 50 +reliability 50 +Mode Point-to-Point +Terrain File pfl.txt + +Results +ITM Warning Flags 0x0000 [No Warnings] +ITM Return Code 0 [Success - No Errors] +Basic Transmission Loss 114.5 (dB) + +Intermediate Values +Free Space 114.5 (dB) +d__km 3.635 (km) +theta_hzn_tx -1.949 (mrad) +theta_hzn_rx -0.856 (mrad) +d_hzn_tx__meter 14868 (meters) +d_hzn_rx__meter 6494 (meters) +h_e_tx__meter 15.0 (meters) +h_e_rx__meter 3.0 (meters) +N_s 251.5 (N-Units) +delta_h__meter 3.2 (meters) +A_ref__db 0.0 (dB) +Mode of Propagation 1 [Line of Sight] diff --git a/cmd_examples/o_p2pcr_tbl.txt b/cmd_examples/o_p2pcr_tbl.txt new file mode 100644 index 0000000..12c681c --- /dev/null +++ b/cmd_examples/o_p2pcr_tbl.txt @@ -0,0 +1,44 @@ +itm.dll Version v1.3 +ITMDrvr.exe Version v1.3.0 +Date Generated Mon Sep 21 22:01:12 2020 +Input Arguments -i i_p2pcr_tbl.txt -t pfl.txt -o o_p2pcr_tbl.txt -mode p2p -dbg + +Inputs +h_tx__meter 15 (meters) +h_rx__meter 3 (meters) +climate 5 [Continental Temperate] +N_0 301.00 (N-Units) +f__mhz 3500.00 (MHz) +pol 1 [Vertical] +epsilon 15 +sigma 0.005 +mdvar 1 [Accidental Mode] +confidence 10,60,90 +reliability 10,65,90 +Mode Point-to-Point +Terrain File pfl.txt + +Results +ITM Warning Flags 0x0000 [No Warnings] +ITM Return Code 0 [Success - No Errors] + +Basic Transmission Loss Results (dB) +Reliability with Confidence + 10 60 90 +10 110.9 117.2 129.1 +65 110.9 117.4 129.2 +90 110.9 117.5 129.3 + +Intermediate Values +Free Space 114.5 (dB) +d__km 3.635 (km) +theta_hzn_tx -1.949 (mrad) +theta_hzn_rx -0.856 (mrad) +d_hzn_tx__meter 14868 (meters) +d_hzn_rx__meter 6494 (meters) +h_e_tx__meter 15.0 (meters) +h_e_rx__meter 3.0 (meters) +N_s 251.5 (N-Units) +delta_h__meter 3.2 (meters) +A_ref__db 0.0 (dB) +Mode of Propagation 1 [Line of Sight] diff --git a/cmd_examples/o_p2ptls.txt b/cmd_examples/o_p2ptls.txt new file mode 100644 index 0000000..27f1632 --- /dev/null +++ b/cmd_examples/o_p2ptls.txt @@ -0,0 +1,39 @@ +itm.dll Version v1.3 +ITMDrvr.exe Version v1.3.0 +Date Generated Mon Sep 21 22:00:35 2020 +Input Arguments -i i_p2ptls.txt -t pfl.txt -o o_p2ptls.txt -mode p2p -dbg + +Inputs +h_tx__meter 15 (meters) +h_rx__meter 3 (meters) +climate 5 [Continental Temperate] +N_0 301.00 (N-Units) +f__mhz 3500.00 (MHz) +pol 1 [Vertical] +epsilon 15 +sigma 0.005 +mdvar 1 [Accidental Mode] +time 50 +location 50 +situation 50 +Mode Point-to-Point +Terrain File pfl.txt + +Results +ITM Warning Flags 0x0000 [No Warnings] +ITM Return Code 0 [Success - No Errors] +Basic Transmission Loss 114.5 (dB) + +Intermediate Values +Free Space 114.5 (dB) +d__km 3.635 (km) +theta_hzn_tx -1.949 (mrad) +theta_hzn_rx -0.856 (mrad) +d_hzn_tx__meter 14868 (meters) +d_hzn_rx__meter 6494 (meters) +h_e_tx__meter 15.0 (meters) +h_e_rx__meter 3.0 (meters) +N_s 251.5 (N-Units) +delta_h__meter 3.2 (meters) +A_ref__db 0.0 (dB) +Mode of Propagation 1 [Line of Sight] diff --git a/cmd_examples/pfl.txt b/cmd_examples/pfl.txt new file mode 100644 index 0000000..6b13b88 --- /dev/null +++ b/cmd_examples/pfl.txt @@ -0,0 +1 @@ +142,25.6,1692,1692,1693,1693,1693,1693,1693,1693,1694,1694,1694,1694,1694,1694,1694,1694,1694,1695,1695,1695,1695,1695,1695,1695,1695,1696,1696,1696,1696,1696,1696,1697,1697,1697,1697,1697,1697,1697,1697,1697,1697,1698,1698,1698,1698,1698,1698,1698,1698,1698,1698,1699,1699,1699,1699,1699,1699,1700,1700,1700,1700,1700,1700,1700,1701,1701,1701,1701,1701,1701,1702,1702,1702,1702,1702,1702,1702,1702,1703,1703,1703,1703,1703,1703,1703,1703,1703,1704,1704,1704,1704,1704,1704,1704,1704,1705,1705,1705,1705,1705,1705,1705,1705,1705,1705,1706,1706,1706,1706,1706,1706,1706,1706,1706,1707,1707,1707,1707,1707,1707,1707,1708,1708,1708,1708,1708,1708,1708,1708,1709,1709,1709,1709,1709,1710,1710,1710,1710,1710,1710,1710,1710,1709 \ No newline at end of file diff --git a/dotnet/Enums.cs b/dotnet/Enums.cs new file mode 100644 index 0000000..29b6afd --- /dev/null +++ b/dotnet/Enums.cs @@ -0,0 +1,200 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ITS.Propagation +{ + /// + /// The Irregular Terrain Model (ITM) + /// + public static partial class ITM + { + /// + /// Polarization + /// + public enum Polarization : int + { + /// + /// Horizontal Polarization + /// + Horizontal = 0, + + /// + /// Vertical Polarization + /// + Vertical = 1 + } + + /// + /// ITM Radio Climate + /// + public enum Climate : int + { + /// + /// Equatorial + /// + Equatorial = 1, + + /// + /// Continental Subtropical + /// + ContinentalSubtropical = 2, + + /// + /// Maritime Subtropical + /// + MaritimeSubtropical = 3, + + /// + /// Desert + /// + Desert = 4, + + /// + /// Continetal Temperate + /// + ContinentalTemperate = 5, + + /// + /// Maritime Temperate over Land + /// + MaritimeTemperateOverLand = 6, + + /// + /// Maritime Temperate over Sea + /// + MaritimeTemperateOverSea = 7 + } + + /// + /// ITM Warning Flags + /// + [Flags] + public enum Warnings : long + { + /// + /// No warnings + /// + NoWarnings = 0x0000, + + /// + /// TX terminal height is near its limits + /// + TxTerminalHeight = 0x0001, + + /// + /// RX terminal height is near its limits + /// + RxTerminalHeight = 0x0002, + + /// + /// Frequency is near its limits + /// + Frequency = 0x0004, + + /// + /// Path distance is near its upper limit + /// + PathDistanceTooBig1 = 0x0008, + + /// + /// Path distance is large - care must be taken with result + /// + PathDistanceTooBig2 = 0x0010, + + /// + /// Path distance is near its lower limit + /// + PathDistanceTooSmall1 = 0x0020, + + /// + /// Path distance is small - care must be taken with result + /// + PathDistanceTooSmall2 = 0x0040, + + /// + /// TX horizon angle is large - small angle approximations could break down + /// + TxHorizonAngle = 0x0080, + + /// + /// RX horizon angle is large - small angle approximations could break down + /// + RxHorizonAngle = 0x0100, + + /// + /// TX horizon distance is less than 1/10 of the smooth earth horizon distance + /// + TxHorizonDistance1 = 0x0200, + + /// + /// RX horizon distance is less than 1/10 of the smooth earth horizon distance + /// + RxHorizonDistance1 = 0x0400, + + /// + /// TX horizon distance is greater than 3 times the smooth earth horizon distance + /// + TxHorizonDistance2 = 0x0800, + + /// + /// RX horizon distance is greater than 3 times the smooth earth horizon distance + /// + RxHorizonDistance2 = 0x1000, + + /// + /// One of the provided variabilities is located far in the tail of its distribution + /// + ExtremeVariabilities = 0x2000 + } + + /// + /// Terminal Siting Criteria + /// + public enum SitingCriteria : int + { + /// + /// Random + /// + Random = 0, + + /// + /// Careful + /// + Careful = 1, + + /// + /// Very careful + /// + VeryCareful = 2 + } + + /// + /// The Mode of Propagation + /// + public enum ModeOfPropagation : int + { + /// + /// Not Set + /// + NotSet = 0, + + /// + /// Line of Sight + /// + LineOfSight = 1, + + /// + /// Diffraction + /// + Diffraction = 2, + + /// + /// Troposcatter + /// + Troposcatter = 3 + } + } +} diff --git a/dotnet/ITM.cs b/dotnet/ITM.cs new file mode 100644 index 0000000..fe43780 --- /dev/null +++ b/dotnet/ITM.cs @@ -0,0 +1,681 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace ITS.Propagation +{ + /// + /// The Irregular Terrain Model (ITM) + /// + public static partial class ITM + { + private const string ITM_x86_DLL_NAME = "itm_x86.dll"; + private const string ITM_x64_DLL_NAME = "itm_x64.dll"; + + #region 32-Bit P/Invoke Definitions + + [DllImport(ITM_x86_DLL_NAME, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "ITM_P2P_TLS")] + private static extern int ITM_TLS_x86(double h_tx__meter, double h_rx__meter, [MarshalAs(UnmanagedType.LPArray)] double[] pfl, + int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, int mdvar, double time, double location, + double situation, out double A__db, out long warnings); + + [DllImport(ITM_x86_DLL_NAME, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "ITM_P2P_TLS_Ex")] + private static extern int ITM_TLS_Ex_x86(double h_tx__meter, double h_rx__meter, [MarshalAs(UnmanagedType.LPArray)] double[] pfl, + int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, int mdvar, double time, double location, + double situation, out double A__db, out long warnings, out IntermediateValues interValues); + + [DllImport(ITM_x86_DLL_NAME, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "ITM_P2P_CR")] + private static extern int ITM_CR_x86(double h_tx__meter, double h_rx__meter, [MarshalAs(UnmanagedType.LPArray)] double[] pfl, + int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, int mdvar, double confidence, + double reliability, out double A__db, out long warnings); + + [DllImport(ITM_x86_DLL_NAME, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "ITM_P2P_CR_Ex")] + private static extern int ITM_CR_Ex_x86(double h_tx__meter, double h_rx__meter, [MarshalAs(UnmanagedType.LPArray)] double[] pfl, + int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, int mdvar, double confidence, + double reliability, out double A__db, out long warnings, out IntermediateValues interValues); + + [DllImport(ITM_x86_DLL_NAME, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "ITM_AREA_TLS")] + private static extern int ITM_AREA_TLS_x86(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, + double d__km, double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double time, double location, double situation, out double A__db, out long warnings); + + [DllImport(ITM_x86_DLL_NAME, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "ITM_AREA_TLS_Ex")] + private static extern int ITM_AREA_TLS_Ex_x86(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, + double d__km, double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double time, double location, double situation, out double A__db, out long warnings, + out IntermediateValues interValues); + + [DllImport(ITM_x86_DLL_NAME, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "ITM_AREA_CR")] + private static extern int ITM_AREA_CR_x86(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, + double d__km, double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double confidence, double reliability, out double A__db, out long warnings); + + [DllImport(ITM_x86_DLL_NAME, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "ITM_AREA_CR_Ex")] + private static extern int ITM_AREA_CR_Ex_x86(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, + double d__km, double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double confidence, double reliability, out double A__db, out long warnings, out IntermediateValues interValues); + + #endregion + + #region 64-Bit P/Invoke Definitions + + [DllImport(ITM_x64_DLL_NAME, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "ITM_P2P_TLS")] + private static extern int ITM_TLS_x64(double h_tx__meter, double h_rx__meter, [MarshalAs(UnmanagedType.LPArray)] double[] pfl, + int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, int mdvar, double time, double location, + double situation, out double A__db, out long warnings); + + [DllImport(ITM_x64_DLL_NAME, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "ITM_P2P_TLS_Ex")] + private static extern int ITM_TLS_Ex_x64(double h_tx__meter, double h_rx__meter, [MarshalAs(UnmanagedType.LPArray)] double[] pfl, + int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, int mdvar, double time, double location, + double situation, out double A__db, out long warnings, out IntermediateValues interValues); + + [DllImport(ITM_x64_DLL_NAME, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "ITM_P2P_CR")] + private static extern int ITM_CR_x64(double h_tx__meter, double h_rx__meter, [MarshalAs(UnmanagedType.LPArray)] double[] pfl, + int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, int mdvar, double confidence, + double reliability, out double A__db, out long warnings); + + [DllImport(ITM_x64_DLL_NAME, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "ITM_P2P_CR_Ex")] + private static extern int ITM_CR_Ex_x64(double h_tx__meter, double h_rx__meter, [MarshalAs(UnmanagedType.LPArray)] double[] pfl, + int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, int mdvar, double confidence, + double reliability, out double A__db, out long warnings, out IntermediateValues interValues); + + [DllImport(ITM_x64_DLL_NAME, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "ITM_AREA_TLS")] + private static extern int ITM_AREA_TLS_x64(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, + double d__km, double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double time, double location, double situation, out double A__db, out long warnings); + + [DllImport(ITM_x64_DLL_NAME, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "ITM_AREA_TLS_Ex")] + private static extern int ITM_AREA_TLS_Ex_x64(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, + double d__km, double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double time, double location, double situation, out double A__db, out long warnings, + out IntermediateValues interValues); + + [DllImport(ITM_x64_DLL_NAME, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "ITM_AREA_CR")] + private static extern int ITM_AREA_CR_x64(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, + double d__km, double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double confidence, double reliability, out double A__db, out long warnings); + + [DllImport(ITM_x64_DLL_NAME, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "ITM_AREA_CR_Ex")] + private static extern int ITM_AREA_CR_Ex_x64(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, + double d__km, double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double confidence, double reliability, out double A__db, out long warnings, out IntermediateValues interValues); + + #endregion + + private delegate int ITM_TLS_Delegate(double h_tx__meter, double h_rx__meter, [MarshalAs(UnmanagedType.LPArray)] double[] pfl, + int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, int mdvar, double time, double location, + double situation, out double A__db, out long warnings); + + private delegate int ITM_TLS_Ex_Delegate(double h_tx__meter, double h_rx__meter, [MarshalAs(UnmanagedType.LPArray)] double[] pfl, + int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, int mdvar, double time, double location, + double situation, out double A__db, out long warnings, out IntermediateValues interValues); + + private delegate int ITM_CR_Delegate(double h_tx__meter, double h_rx__meter, [MarshalAs(UnmanagedType.LPArray)] double[] pfl, + int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, int mdvar, double confidence, + double reliability, out double A__db, out long warnings); + + private delegate int ITM_CR_Ex_Delegate(double h_tx__meter, double h_rx__meter, [MarshalAs(UnmanagedType.LPArray)] double[] pfl, + int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, int mdvar, double confidence, + double reliability, out double A__db, out long warnings, out IntermediateValues interValues); + + private delegate int ITM_AREA_TLS_Delegate(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, + double d__km, double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double time, double location, double situation, out double A__db, out long warnings); + + private delegate int ITM_AREA_TLS_Ex_Delegate(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, + double d__km, double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double time, double location, double situation, out double A__db, out long warnings, + out IntermediateValues interValues); + + private delegate int ITM_AREA_CR_Delegate(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, + double d__km, double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double confidence, double reliability, out double A__db, out long warnings); + + private delegate int ITM_AREA_CR_Ex_Delegate(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, + double d__km, double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double confidence, double reliability, out double A__db, out long warnings, out IntermediateValues interValues); + + private static ITM_TLS_Delegate ITM_TLS_Invoke; + private static ITM_TLS_Ex_Delegate ITM_TLS_Ex_Invoke; + private static ITM_CR_Delegate ITM_CR_Invoke; + private static ITM_CR_Ex_Delegate ITM_CR_Ex_Invoke; + private static ITM_AREA_TLS_Delegate ITM_AREA_TLS_Invoke; + private static ITM_AREA_TLS_Ex_Delegate ITM_AREA_TLS_Ex_Invoke; + private static ITM_AREA_CR_Delegate ITM_AREA_CR_Invoke; + private static ITM_AREA_CR_Ex_Delegate ITM_AREA_CR_Ex_Invoke; + + static ITM() + { + if (Environment.Is64BitProcess) + { + ITM_TLS_Invoke = ITM_TLS_x64; + ITM_TLS_Ex_Invoke = ITM_TLS_Ex_x64; + ITM_CR_Invoke = ITM_CR_x64; + ITM_CR_Ex_Invoke = ITM_CR_Ex_x64; + ITM_AREA_TLS_Invoke = ITM_AREA_TLS_x64; + ITM_AREA_TLS_Ex_Invoke = ITM_AREA_TLS_Ex_x64; + ITM_AREA_CR_Invoke = ITM_AREA_CR_x64; + ITM_AREA_CR_Ex_Invoke = ITM_AREA_CR_Ex_x64; + } + else + { + ITM_TLS_Invoke = ITM_TLS_x86; + ITM_TLS_Ex_Invoke = ITM_TLS_Ex_x86; + ITM_CR_Invoke = ITM_CR_x86; + ITM_CR_Ex_Invoke = ITM_CR_Ex_x86; + ITM_AREA_TLS_Invoke = ITM_AREA_TLS_x86; + ITM_AREA_TLS_Ex_Invoke = ITM_AREA_TLS_Ex_x86; + ITM_AREA_CR_Invoke = ITM_AREA_CR_x86; + ITM_AREA_CR_Ex_Invoke = ITM_AREA_CR_Ex_x86; + } + } + + #region Point-to-Point TLS + + /// + /// Point-to-point mode functionality, with variability specified with time/location/situation (TLS) + /// + /// Structural height of the TX, in meters + /// Structural height of the RX, in meters + /// Terrain data, in PFL format + /// Radio climate + /// Refractivity, in N-Units + /// Frequency, in MHz + /// Polarization + /// Relative permittivity + /// Conductivity + /// Mode of variability + /// Time percentage + /// Location percentage + /// Situation percentage + /// Basic transmission loss, in dB + /// Warning flags + /// Error code + public static int ITM_P2P_TLS(double h_tx__meter, double h_rx__meter, double[] pfl, int climate, double N_0, double f__mhz, + int pol, double epsilon, double sigma, int mdvar, double time, double location, double situation, + out double A__db, out long warnings) + { + return ITM_TLS_Invoke(h_tx__meter, h_rx__meter, pfl, climate, N_0, f__mhz, pol, epsilon, sigma, mdvar, time, + location, situation, out A__db, out warnings); + } + + /// + /// Point-to-point mode functionality, with variability specified with time/location/situation (TLS) + /// + /// Structural height of the TX, in meters + /// Structural height of the RX, in meters + /// Terrain data, in PFL format + /// Radio climate + /// Refractivity, in N-Units + /// Frequency, in MHz + /// Polarization + /// Relative permittivity + /// Conductivity + /// Mode of variability + /// Time percentage + /// Location percentage + /// Situation percentage + /// Basic transmission loss, in dB + /// Warning flags + /// Struct of intermediate values + /// Error code + public static int ITM_P2P_TLS_Ex(double h_tx__meter, double h_rx__meter, double[] pfl, int climate, double N_0, double f__mhz, + int pol, double epsilon, double sigma, int mdvar, double time, double location, double situation, + out double A__db, out long warnings, out IntermediateValues interValues) + { + return ITM_TLS_Ex_Invoke(h_tx__meter, h_rx__meter, pfl, climate, N_0, f__mhz, pol, epsilon, sigma, mdvar, time, + location, situation, out A__db, out warnings, out interValues); + } + + /// + /// Point-to-point mode functionality, with variability specified with time/location/situation (TLS) + /// + /// Structural height of the TX, in meters + /// Structural height of the RX, in meters + /// Terrain data, in PFL format + /// Radio climate + /// Refractivity, in N-Units + /// Frequency, in MHz + /// Polarization + /// Relative permittivity + /// Conductivity + /// Mode of variability + /// Time percentage + /// Location percentage + /// Situation percentage + /// Basic transmission loss, in dB + /// Warning flags + /// Error code + public static int ITM_P2P_TLS(double h_tx__meter, double h_rx__meter, double[] pfl, Climate climate, double N_0, double f__mhz, + Polarization pol, double epsilon, double sigma, int mdvar, double time, double location, double situation, + out double A__db, out Warnings warnings) + { + int rtn = ITM_P2P_TLS(h_tx__meter, h_rx__meter, pfl, (int)climate, N_0, f__mhz, (int)pol, epsilon, sigma, mdvar, time, + location, situation, out A__db, out long warns); + + warnings = (Warnings)warns; + return rtn; + } + + /// + /// Point-to-point mode functionality, with variability specified with time/location/situation (TLS) + /// + /// Structural height of the TX, in meters + /// Structural height of the RX, in meters + /// Terrain data, in PFL format + /// Radio climate + /// Refractivity, in N-Units + /// Frequency, in MHz + /// Polarization + /// Relative permittivity + /// Conductivity + /// Mode of variability + /// Time percentage + /// Location percentage + /// Situation percentage + /// Basic transmission loss, in dB + /// Warning flags + /// Struct of intermediate values + /// Error code + public static int ITM_P2P_TLS_Ex(double h_tx__meter, double h_rx__meter, double[] pfl, Climate climate, double N_0, double f__mhz, + Polarization pol, double epsilon, double sigma, int mdvar, double time, double location, double situation, + out double A__db, out Warnings warnings, out IntermediateValues interValues) + { + int rtn = ITM_P2P_TLS_Ex(h_tx__meter, h_rx__meter, pfl, (int)climate, N_0, f__mhz, (int)pol, epsilon, sigma, mdvar, time, + location, situation, out A__db, out long warns, out interValues); + + warnings = (Warnings)warns; + return rtn; + } + + #endregion + + #region Point-to-Point CR + + /// + /// Point-to-point mode functionality, with variability specified with confidence/reliability (CR) + /// + /// Structural height of the TX, in meters + /// Structural height of the RX, in meters + /// Terrain data, in PFL format + /// Radio climate + /// Refractivity, in N-Units + /// Frequency, in MHz + /// Polarization + /// Relative permittivity + /// Conductivity + /// Mode of variability + /// Confidence percentage + /// Reliability percentage + /// Basic transmission loss, in dB + /// Warning flags + /// Error code + public static int ITM_P2P_CR(double h_tx__meter, double h_rx__meter, double[] pfl, int climate, double N_0, double f__mhz, + int pol, double epsilon, double sigma, int mdvar, double confidence, double reliability, out double A__db, out long warnings) + { + return ITM_CR_Invoke(h_tx__meter, h_rx__meter, pfl, climate, N_0, f__mhz, pol, epsilon, sigma, mdvar, + confidence, reliability, out A__db, out warnings); + } + + /// + /// Point-to-point mode functionality, with variability specified with confidence/reliability (CR) + /// + /// Structural height of the TX, in meters + /// Structural height of the RX, in meters + /// Terrain data, in PFL format + /// Radio climate + /// Refractivity, in N-Units + /// Frequency, in MHz + /// Polarization + /// Relative permittivity + /// Conductivity + /// Mode of variability + /// Confidence percentage + /// Reliability percentage + /// Basic transmission loss, in dB + /// Warning flags + /// Struct of intermediate values + /// Error code + public static int ITM_P2P_CR_Ex(double h_tx__meter, double h_rx__meter, double[] pfl, int climate, double N_0, double f__mhz, + int pol, double epsilon, double sigma, int mdvar, double confidence, double reliability, out double A__db, out long warnings, + out IntermediateValues interValues) + { + return ITM_CR_Ex_Invoke(h_tx__meter, h_rx__meter, pfl, climate, N_0, f__mhz, pol, epsilon, sigma, mdvar, + confidence, reliability, out A__db, out warnings, out interValues); + } + + /// + /// Point-to-point mode functionality, with variability specified with confidence/reliability (CR) + /// + /// Structural height of the TX, in meters + /// Structural height of the RX, in meters + /// Terrain data, in PFL format + /// Radio climate + /// Refractivity, in N-Units + /// Frequency, in MHz + /// Polarization + /// Relative permittivity + /// Conductivity + /// Mode of variability + /// Confidence percentage + /// Reliability percentage + /// Basic transmission loss, in dB + /// Warning flags + /// Error code + public static int ITM_P2P_CR(double h_tx__meter, double h_rx__meter, double[] pfl, Climate climate, double N_0, + double f__mhz, Polarization pol, double epsilon, double sigma, int mdvar, double confidence, double reliability, + out double A__db, out Warnings warnings) + { + int rtn = ITM_P2P_CR(h_tx__meter, h_rx__meter, pfl, (int)climate, N_0, f__mhz, (int)pol, epsilon, sigma, mdvar, + confidence, reliability, out A__db, out long warns); + + warnings = (Warnings)warns; + return rtn; + } + + /// + /// Point-to-point mode functionality, with variability specified with confidence/reliability (CR) + /// + /// Structural height of the TX, in meters + /// Structural height of the RX, in meters + /// Terrain data, in PFL format + /// Radio climate + /// Refractivity, in N-Units + /// Frequency, in MHz + /// Polarization + /// Relative permittivity + /// Conductivity + /// Mode of variability + /// Confidence percentage + /// Reliability percentage + /// Basic transmission loss, in dB + /// Warning flags + /// Struct of intermediate values + /// Error code + public static int ITM_P2P_CR_Ex(double h_tx__meter, double h_rx__meter, double[] pfl, Climate climate, double N_0, + double f__mhz, Polarization pol, double epsilon, double sigma, int mdvar, double confidence, double reliability, + out double A__db, out Warnings warnings, out IntermediateValues interValues) + { + int rtn = ITM_P2P_CR_Ex(h_tx__meter, h_rx__meter, pfl, (int)climate, N_0, f__mhz, (int)pol, epsilon, sigma, mdvar, + confidence, reliability, out A__db, out long warns, out interValues); + + warnings = (Warnings)warns; + return rtn; + } + + #endregion + + #region Area TLS + + /// + /// Area mode functionality + /// + /// Structural height of the TX, in meters + /// Structural height of the RX, in meters + /// Siting criteria of the TX + /// Siting criteria of the RX + /// Path distance, in km + /// Terrain irregularity parameter + /// Radio climate + /// Refractivity, in N-Units + /// Frequency, in MHz + /// Polarization + /// Relative permittivity + /// Conductivity + /// Mode of variability + /// Time percentage + /// Location percentage + /// Situation percentage + /// Basic transmission loss, in dB + /// Warning flags + /// Error code + public static int ITM_AREA_TLS(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, + double d__km, double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double time, double location, double situation, out double A__db, out long warnings) + { + return ITM_AREA_TLS_Invoke(h_tx__meter, h_rx__meter, tx_site_criteria, rx_site_criteria, d__km, delta_h__meter, + climate, N_0, f__mhz, pol, epsilon, sigma, mdvar, time, location, situation, out A__db, out warnings); + } + + /// + /// Area mode functionality + /// + /// Structural height of the TX, in meters + /// Structural height of the RX, in meters + /// Siting criteria of the TX + /// Siting criteria of the RX + /// Path distance, in km + /// Terrain irregularity parameter + /// Radio climate + /// Refractivity, in N-Units + /// Frequency, in MHz + /// Polarization + /// Relative permittivity + /// Conductivity + /// Mode of variability + /// Time percentage + /// Location percentage + /// Situation percentage + /// Basic transmission loss, in dB + /// Warning flags + /// Error code + public static int ITM_AREA_TLS(double h_tx__meter, double h_rx__meter, SitingCriteria tx_site_criteria, + SitingCriteria rx_site_criteria, double d__km, double delta_h__meter, Climate climate, double N_0, + double f__mhz, Polarization pol, double epsilon, double sigma, int mdvar, double time, double location, + double situation, out double A__db, out Warnings warnings) + { + int rtn = ITM_AREA_TLS(h_tx__meter, h_rx__meter, (int)tx_site_criteria, (int)rx_site_criteria, d__km, delta_h__meter, + (int)climate, N_0, f__mhz, (int)pol, epsilon, sigma, mdvar, time, location, situation, out A__db, out long warns); + + warnings = (Warnings)warns; + return rtn; + } + + /// + /// Area mode functionality + /// + /// Structural height of the TX, in meters + /// Structural height of the RX, in meters + /// Siting criteria of the TX + /// Siting criteria of the RX + /// Path distance, in km + /// Terrain irregularity parameter + /// Radio climate + /// Refractivity, in N-Units + /// Frequency, in MHz + /// Polarization + /// Relative permittivity + /// Conductivity + /// Mode of variability + /// Time percentage + /// Location percentage + /// Situation percentage + /// Basic transmission loss, in dB + /// Warning flags + /// Struct of intermediate values + /// Error code + public static int ITM_AREA_TLS_Ex(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, + double d__km, double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double time, double location, double situation, out double A__db, out long warnings, + out IntermediateValues interValues) + { + return ITM_AREA_TLS_Ex_Invoke(h_tx__meter, h_rx__meter, tx_site_criteria, rx_site_criteria, d__km, delta_h__meter, + climate, N_0, f__mhz, pol, epsilon, sigma, mdvar, time, location, situation, out A__db, out warnings, + out interValues); + } + + /// + /// Area mode functionality + /// + /// Structural height of the TX, in meters + /// Structural height of the RX, in meters + /// Siting criteria of the TX + /// Siting criteria of the RX + /// Path distance, in km + /// Terrain irregularity parameter + /// Radio climate + /// Refractivity, in N-Units + /// Frequency, in MHz + /// Polarization + /// Relative permittivity + /// Conductivity + /// Mode of variability + /// Time percentage + /// Location percentage + /// Situation percentage + /// Basic transmission loss, in dB + /// Warning flags + /// Struct of intermediate values + /// Error code + public static int ITM_AREA_TLS_Ex(double h_tx__meter, double h_rx__meter, SitingCriteria tx_site_criteria, + SitingCriteria rx_site_criteria, double d__km, double delta_h__meter, Climate climate, double N_0, + double f__mhz, Polarization pol, double epsilon, double sigma, int mdvar, double time, double location, + double situation, out double A__db, out Warnings warnings, out IntermediateValues interValues) + { + int rtn = ITM_AREA_TLS_Ex(h_tx__meter, h_rx__meter, (int)tx_site_criteria, (int)rx_site_criteria, d__km, + delta_h__meter, (int)climate, N_0, f__mhz, (int)pol, epsilon, sigma, mdvar, time, location, situation, + out A__db, out long warns, out interValues); + + warnings = (Warnings)warns; + return rtn; + } + + #endregion + + #region Area CR + + /// + /// Area mode functionality + /// + /// Structural height of the TX, in meters + /// Structural height of the RX, in meters + /// Siting criteria of the TX + /// Siting criteria of the RX + /// Path distance, in km + /// Terrain irregularity parameter + /// Radio climate + /// Refractivity, in N-Units + /// Frequency, in MHz + /// Polarization + /// Relative permittivity + /// Conductivity + /// Mode of variability + /// Confidence percentage + /// Reliability percentage + /// Basic transmission loss, in dB + /// Warning flags + /// Error code + public static int ITM_AREA_CR(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, + double d__km, double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double confidence, double reliability, out double A__db, out long warnings) + { + return ITM_AREA_CR_Invoke(h_tx__meter, h_rx__meter, tx_site_criteria, rx_site_criteria, d__km, delta_h__meter, + climate, N_0, f__mhz, pol, epsilon, sigma, mdvar, confidence, reliability, out A__db, out warnings); + } + + /// + /// Area mode functionality + /// + /// Structural height of the TX, in meters + /// Structural height of the RX, in meters + /// Siting criteria of the TX + /// Siting criteria of the RX + /// Path distance, in km + /// Terrain irregularity parameter + /// Radio climate + /// Refractivity, in N-Units + /// Frequency, in MHz + /// Polarization + /// Relative permittivity + /// Conductivity + /// Mode of variability + /// Confidence percentage + /// Reliability percentage + /// Basic transmission loss, in dB + /// Warning flags + /// Error code + public static int ITM_AREA_CR(double h_tx__meter, double h_rx__meter, SitingCriteria tx_site_criteria, + SitingCriteria rx_site_criteria, double d__km, double delta_h__meter, Climate climate, double N_0, + double f__mhz, Polarization pol, double epsilon, double sigma, int mdvar, double confidence, double reliability, + out double A__db, out Warnings warnings) + { + int rtn = ITM_AREA_CR(h_tx__meter, h_rx__meter, (int)tx_site_criteria, (int)rx_site_criteria, d__km, delta_h__meter, + (int)climate, N_0, f__mhz, (int)pol, epsilon, sigma, mdvar, confidence, reliability, out A__db, out long warns); + + warnings = (Warnings)warns; + return rtn; + } + + /// + /// Area mode functionality + /// + /// Structural height of the TX, in meters + /// Structural height of the RX, in meters + /// Siting criteria of the TX + /// Siting criteria of the RX + /// Path distance, in km + /// Terrain irregularity parameter + /// Radio climate + /// Refractivity, in N-Units + /// Frequency, in MHz + /// Polarization + /// Relative permittivity + /// Conductivity + /// Mode of variability + /// Confidence percentage + /// Reliability percentage + /// Basic transmission loss, in dB + /// Warning flags + /// Struct of intermediate values + /// Error code + public static int ITM_AREA_CR_Ex(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, + double d__km, double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double confidence, double reliability, out double A__db, out long warnings, + out IntermediateValues interValues) + { + return ITM_AREA_CR_Ex_Invoke(h_tx__meter, h_rx__meter, tx_site_criteria, rx_site_criteria, d__km, delta_h__meter, + climate, N_0, f__mhz, pol, epsilon, sigma, mdvar, confidence, reliability, out A__db, out warnings, + out interValues); + } + + /// + /// Area mode functionality + /// + /// Structural height of the TX, in meters + /// Structural height of the RX, in meters + /// Siting criteria of the TX + /// Siting criteria of the RX + /// Path distance, in km + /// Terrain irregularity parameter + /// Radio climate + /// Refractivity, in N-Units + /// Frequency, in MHz + /// Polarization + /// Relative permittivity + /// Conductivity + /// Mode of variability + /// Confidence percentage + /// Reliability percentage + /// Basic transmission loss, in dB + /// Warning flags + /// Struct of intermediate values + /// Error code + public static int ITM_AREA_CR_Ex(double h_tx__meter, double h_rx__meter, SitingCriteria tx_site_criteria, + SitingCriteria rx_site_criteria, double d__km, double delta_h__meter, Climate climate, double N_0, + double f__mhz, Polarization pol, double epsilon, double sigma, int mdvar, double confidence, double reliability, + out double A__db, out Warnings warnings, out IntermediateValues interValues) + { + int rtn = ITM_AREA_CR_Ex(h_tx__meter, h_rx__meter, (int)tx_site_criteria, (int)rx_site_criteria, d__km, + delta_h__meter, (int)climate, N_0, f__mhz, (int)pol, epsilon, sigma, mdvar, confidence, reliability, + out A__db, out long warns, out interValues); + + warnings = (Warnings)warns; + return rtn; + } + + #endregion + } +} diff --git a/dotnet/ITMIntermediateValues.cs b/dotnet/ITMIntermediateValues.cs new file mode 100644 index 0000000..bf74e31 --- /dev/null +++ b/dotnet/ITMIntermediateValues.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace ITS.Propagation +{ + /// + /// The Irregular Terrain Model (ITM) + /// + public static partial class ITM + { + /// + /// Intermediate values from ITM + /// + [StructLayout(LayoutKind.Sequential)] + public struct IntermediateValues + { + /// + /// Terminal horizon angles, in radians + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public double[] theta_hzn__rad; + + /// + /// Terminal horizon distances, in meters + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public double[] d_hzn__meter; + + /// + /// Terminal effective heights, in meters + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public double[] h_e__meter; + + /// + /// Surface refractivity, in N-Units + /// + public double N_s; + + /// + /// Terrain irregularity parameter, in meters + /// + public double delta_h__meter; + + /// + /// Reference attenuation, in dB + /// + public double A_ref__db; + + /// + /// Free space basic transmission loss, in dB + /// + public double A_fs__db; + + /// + /// Path distance, in km + /// + public double d__km; + + /// + /// Mode of propagation + /// + public ModeOfPropagation Mode; + } + } +} diff --git a/dotnet/ITS.Propagation.ITM.csproj b/dotnet/ITS.Propagation.ITM.csproj new file mode 100644 index 0000000..a4e38a8 --- /dev/null +++ b/dotnet/ITS.Propagation.ITM.csproj @@ -0,0 +1,51 @@ + + + + + Debug + AnyCPU + {B9E48BA2-5009-432D-9A35-3BADEC118E1C} + Library + Properties + ITS.Propagation + ITS.Propagation.ITM + v4.7.2 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + bin\Release\ITS.Propagation.ITM.xml + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dotnet/ITS.Propagation.ITM.sln b/dotnet/ITS.Propagation.ITM.sln new file mode 100644 index 0000000..b8da733 --- /dev/null +++ b/dotnet/ITS.Propagation.ITM.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30413.136 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ITS.Propagation.ITM", "ITS.Propagation.ITM.csproj", "{B9E48BA2-5009-432D-9A35-3BADEC118E1C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B9E48BA2-5009-432D-9A35-3BADEC118E1C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B9E48BA2-5009-432D-9A35-3BADEC118E1C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B9E48BA2-5009-432D-9A35-3BADEC118E1C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B9E48BA2-5009-432D-9A35-3BADEC118E1C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {13FCBAF4-A7A4-4CE4-A75B-80A9A96456F4} + EndGlobalSection +EndGlobal diff --git a/dotnet/Properties/AssemblyInfo.cs b/dotnet/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..35dd6bb --- /dev/null +++ b/dotnet/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ITS.Propagation.ITM")] +[assembly: AssemblyDescription("Irregular Terrain Model (ITM)")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Institute for Telecommunication Sciences")] +[assembly: AssemblyProduct("ITS.Propagation.ITM")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("b9e48ba2-5009-432d-9a35-3badec118e1c")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.3.0.0")] +[assembly: AssemblyFileVersion("1.3.0.0")] diff --git a/include/Enums.h b/include/Enums.h new file mode 100644 index 0000000..c5eb52b --- /dev/null +++ b/include/Enums.h @@ -0,0 +1,39 @@ + +// +// ENUMERATION VALUES +/////////////////////////////////////////////// + +#define SINGLE_MESSAGE_MODE 0 +#define ACCIDENTAL_MODE 1 +#define MOBILE_MODE 2 +#define BROADCAST_MODE 3 + +// List of valid polarizations +#define POLARIZATION__HORIZONTAL 0 +#define POLARIZATION__VERTICAL 1 + +// List of valid siting criteria +#define SITING_CRITERIA__RANDOM 0 +#define SITING_CRITERIA__CAREFUL 1 +#define SITING_CRITERIA__VERY_CAREFUL 2 + +// List of valid radio climates +#define CLIMATE__EQUATORIAL 1 +#define CLIMATE__CONTINENTAL_SUBTROPICAL 2 +#define CLIMATE__MARITIME_SUBTROPICAL 3 +#define CLIMATE__DESERT 4 +#define CLIMATE__CONTINENTAL_TEMPERATE 5 +#define CLIMATE__MARITIME_TEMPERATE_OVER_LAND 6 +#define CLIMATE__MARITIME_TEMPERATE_OVER_SEA 7 + +// List of valid modes of propagation +#define MODE__NOT_SET 0 +#define MODE__LINE_OF_SIGHT 1 +#define MODE__DIFFRACTION 2 +#define MODE__TROPOSCATTER 3 + +// List of modes of variability +#define MDVAR__SINGLE_MESSAGE_MODE 0 +#define MDVAR__ACCIDENTAL_MODE 1 +#define MDVAR__MOBILE_MODE 2 +#define MDVAR__BROADCAST_MODE 3 \ No newline at end of file diff --git a/include/Errors.h b/include/Errors.h new file mode 100644 index 0000000..fe53034 --- /dev/null +++ b/include/Errors.h @@ -0,0 +1,30 @@ + +/////////////////////////////////////////////// +// ERROR CODES + +#define SUCCESS 0 +#define NO_WARNINGS 0 +#define SUCCESS_WITH_WARNINGS 1 + +#define ERROR__TX_TERMINAL_HEIGHT 1000 // TX terminal height is out of range +#define ERROR__RX_TERMINAL_HEIGHT 1001 // RX terminal height is out of range +#define ERROR__INVALID_RADIO_CLIMATE 1002 // Invalid value for radio climate +#define ERROR__INVALID_TIME 1003 // Time percentage is out of range +#define ERROR__INVALID_LOCATION 1004 // Location percentage is out of range +#define ERROR__INVALID_SITUATION 1005 // Situation percentage is out of range +#define ERROR__INVALID_CONFIDENCE 1006 // Confidence percentage is out of range +#define ERROR__INVALID_RELIABILITY 1007 // Reliability percentage is out of range +#define ERROR__REFRACTIVITY 1008 // Refractivity is out of range +#define ERROR__FREQUENCY 1009 // Frequency is out of range +#define ERROR__POLARIZATION 1010 // Invalid value for polarization +#define ERROR__EPSILON 1011 // Epsilon is out of range +#define ERROR__SIGMA 1012 // Sigma is out of range +#define ERROR__GROUND_IMPEDANCE 1013 // The imaginary portion of the complex impedance is larger than the real portion +#define ERROR__MDVAR 1014 // Invalid value for mode of variability +#define ERROR__EFFECTIVE_EARTH 1016 // Internally computed effective earth radius is invalid +#define ERROR__PATH_DISTANCE 1017 // Path distance is out of range +#define ERROR__DELTA_H 1018 // Delta H (terrain irregularity parameter) is out of range +#define ERROR__TX_SITING_CRITERIA 1019 // Invalid value for TX siting criteria +#define ERROR__RX_SITING_CRITERIA 1020 // Invalid value for RX siting criteria +#define ERROR__SURFACE_REFRACTIVITY_SMALL 1021 // Internally computed surface refractivity value is too small +#define ERROR__SURFACE_REFRACTIVITY_LARGE 1022 // Internally computed surface refractivity value is too large diff --git a/include/Warnings.h b/include/Warnings.h new file mode 100644 index 0000000..bc76b05 --- /dev/null +++ b/include/Warnings.h @@ -0,0 +1,19 @@ + +/////////////////////////////////////////////// +// WARNING FLAGS + +#define WARN__TX_TERMINAL_HEIGHT 0x0001 // TX terminal height is near its limits +#define WARN__RX_TERMINAL_HEIGHT 0x0002 // RX terminal height is near its limits +#define WARN__FREQUENCY 0x0004 // Frequency is near its limits +#define WARN__PATH_DISTANCE_TOO_BIG_1 0x0008 // Path distance is near its upper limit +#define WARN__PATH_DISTANCE_TOO_BIG_2 0x0010 // Path distance is large - care must be taken with result +#define WARN__PATH_DISTANCE_TOO_SMALL_1 0x0020 // Path distance is near its lower limit +#define WARN__PATH_DISTANCE_TOO_SMALL_2 0x0040 // Path distance is small - care must be taken with result +#define WARN__TX_HORIZON_ANGLE 0x0080 // TX horizon angle is large - small angle approximations could break down +#define WARN__RX_HORIZON_ANGLE 0x0100 // RX horizon angle is large - small angel approximations could break down +#define WARN__TX_HORIZON_DISTANCE_1 0x0200 // TX horizon distance is less than 1/10 of the smooth earth horizon distance +#define WARN__RX_HORIZON_DISTANCE_1 0x0400 // RX horizon distance is less than 1/10 of the smooth earth horizon distance +#define WARN__TX_HORIZON_DISTANCE_2 0x0800 // TX horizon distance is greater than 3 times the smooth earth horizon distance +#define WARN__RX_HORIZON_DISTANCE_2 0x1000 // RX horizon distance is greater than 3 times the smooth earth horizon distance +#define WARN__EXTREME_VARIABILITIES 0x2000 // One of the provided variabilities is located far in the tail of its distribution +#define WARN__SURFACE_REFRACTIVITY 0x4000 // Internally computed surface refractivity value is small - care must be taken with result diff --git a/include/itm.h b/include/itm.h new file mode 100644 index 0000000..7ad1fbc --- /dev/null +++ b/include/itm.h @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include + +using namespace std; + +// Export the DLL functions as "C" and not C++ +#define DLLEXPORT extern "C" __declspec(dllexport) +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#define DIM(x, y) (((x) > (y)) ? (x - y) : (0)) + +#define PI 3.1415926535897932384 +#define SQRT2 sqrt(2) +#define a_0__meter 6370e3 +#define a_9000__meter 9000e3 +#define THIRD 1.0 / 3.0 + +#define MODE__P2P 0 +#define MODE__AREA 1 + + +///////////////////////////// +// Data Structures + +struct IntermediateValues +{ + double theta_hzn[2]; // Terminal horizon angles + double d_hzn__meter[2]; // Terminal horizon distances, in meters + double h_e__meter[2]; // Terminal effective heights, in meters + double N_s; // Surface refractivity, in N-Units + double delta_h__meter; // Terrain irregularity parameter, in meters + double A_ref__db; // Reference attenuation, in dB + double A_fs__db; // Free space basic transmission loss, in dB + double d__km; // Path distance, in km + int mode; // Mode of propagation value +}; + +///////////////////////////// +// Main ITM Functions + +DLLEXPORT int ITM_P2P_TLS(double h_tx__meter, double h_rx__meter, double pfl[], int climate, double N_0, double f__mhz, + int pol, double epsilon, double sigma, int mdvar, double time, double location, double situation, + double *A__db, long *warnings); +DLLEXPORT int ITM_P2P_TLS_Ex(double h_tx__meter, double h_rx__meter, double pfl[], int climate, double N_0, double f__mhz, + int pol, double epsilon, double sigma, int mdvar, double time, double location, double situation, + double *A__db, long *warnings, IntermediateValues *interValues); +DLLEXPORT int ITM_P2P_CR(double h_tx__meter, double h_rx__meter, double pfl[], int climate, double N_0, double f__mhz, + int pol, double epsilon, double sigma, int mdvar, double confidence, double reliability, + double *A__db, long *warnings); +DLLEXPORT int ITM_P2P_CR_Ex(double h_tx__meter, double h_rx__meter, double pfl[], int climate, double N_0, double f__mhz, + int pol, double epsilon, double sigma, int mdvar, double confidence, double reliability, + double *A__db, long *warnings, IntermediateValues *interValues); +DLLEXPORT int ITM_AREA_TLS(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, double d__km, + double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double time, double location, double situation, double *A__db, long *warnings); +DLLEXPORT int ITM_AREA_TLS_Ex(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, double d__km, + double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double time, double location, double situation, double *A__db, long *warnings, IntermediateValues *interValues); +DLLEXPORT int ITM_AREA_CR(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, double d__km, + double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double confidence, double reliability, double *A__db, long *warnings); +DLLEXPORT int ITM_AREA_CR_Ex(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, double d__km, + double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double confidence, double reliability, double *A__db, long *warnings, IntermediateValues *interValues); + +///////////////////////////// +// ITM Helper Functions + +DLLEXPORT double ComputeDeltaH(double pfl[], double d_start__meter, double d_end__meter); +DLLEXPORT double DiffractionLoss(double d__meter, double d_hzn__meter[2], double h_e__meter[2], complex Z_g, + double a_e__meter, double delta_h__meter, double h__meter[2], int mode, double theta_los, double d_sML__meter, double f__mhz); +DLLEXPORT double FFunction(double td); +DLLEXPORT void FindHorizons(double pfl[], double a_e__meter, double h__meter[2], double theta_hzn[2], double d_hzn__meter[2]); +DLLEXPORT double FreeSpaceLoss(double d__meter, double f__mhz); +DLLEXPORT double FresnelIntegral(double v2); +DLLEXPORT double H0Function(double r, double eta_s); +DLLEXPORT double HeightFunction(double x__meter, double K); +DLLEXPORT void InitializeArea(int site_criteria[2], double gamma_e, double delta_h__meter, + double h__meter[2], double h_e__meter[2], double d_hzn__meter[2], double theta_hzn[2]); +DLLEXPORT void InitializePointToPoint(double f__mhz, double h_sys__meter, double N_0, int polarization, double epsilon, + double sigma, complex *Z_g, double *gamma_e, double *N_s); +DLLEXPORT double InverseComplementaryCumulativeDistributionFunction(double q); +DLLEXPORT double KnifeEdgeDiffraction(double d__meter, double f__mhz, double a_e__meter, double theta_los, double d_hzn__meter[2]); +DLLEXPORT void LinearLeastSquaresFit(double pfl[], double d_start, double d_end, double *fit_y1, double *fit_y2); +DLLEXPORT double LineOfSightLoss(double d__meter, double h_e__meter[2], complex Z_g, double delta_h__meter, + double M_d, double A_d0, double d_sML__meter, double f__mhz); +DLLEXPORT int LongleyRice(double theta_hzn[2], double f__mhz, complex Z_g, double d_hzn__meter[2], double h_e__meter[2], + double gamma_e, double N_s, double delta_h__meter, double h__meter[2], double d__meter, int mode, double *A_ref__db, + long *warnings, int *propmode); +DLLEXPORT void QuickPfl(double pfl[], double gamma_e, double h__meter[2], double theta_hzn[2], double d_hzn__meter[2], + double h_e__meter[2], double *delta_h__meter, double *d__meter); +DLLEXPORT double SigmaHFunction(double delta_h__meter); +DLLEXPORT double SmoothEarthDiffraction(double d__meter, double f__mhz, double a_e__meter, double theta_los, + double d_hzn__meter[2], double h_e__meter[2], complex Z_g); +DLLEXPORT double TerrainRoughness(double d__meter, double delta_h__meter); +DLLEXPORT double TroposcatterLoss(double d__meter, double theta_hzn[2], double d_hzn__meter[2], double h_e__meter[2], + double a_e__meter, double N_s, double f__mhz, double theta_los, double *h0); +DLLEXPORT int ValidateInputs(double h_tx__meter, double h_rx__meter, int climate, double time, + double location, double situation, double N_0, double f__mhz, int pol, + double epsilon, double sigma, int mdvar, long *warnings); +DLLEXPORT double Variability(double time, double location, double situation, double h_e__meter[2], double delta_h__meter, + double f__mhz, double d__meter, double A_ref__db, int climate, int mdvar, long *warnings); diff --git a/src/ComputeDeltaH.cpp b/src/ComputeDeltaH.cpp new file mode 100644 index 0000000..0f4aae4 --- /dev/null +++ b/src/ComputeDeltaH.cpp @@ -0,0 +1,84 @@ +#include "..\include\itm.h" + +/*============================================================================= + | + | Description: Compute the terrain irregularity parameter, delta_h + | + | Input: pfl[] - Terrain data + | d_start__meter - Distance into the terrain profile to start + | considering data, in meters + | d_end__meter - Distance into the terrain profile to end + | considering data, in meters + | + | Outputs: [None] + | + | Returns: delta_h__meter - Terrain irregularity parameter, in meters + | + *===========================================================================*/ +double ComputeDeltaH(double pfl[], double d_start__meter, double d_end__meter) +{ + double s[247] = { 0 }; // Temp pfl data array + + int np = (int)pfl[0]; + double x_start = d_start__meter / pfl[1]; // index to start considering terrain points + double x_end = d_end__meter / pfl[1]; // index to stop considering terrain points + + // if there are less than 2 terrain points, return delta_h = 0 + if (x_end - x_start < 2.0) + return 0; + + int p10 = (int)(0.1 * (x_end - x_start + 8.0)); + p10 = MIN(MAX(4, p10), 25); // 10% index + + int n = 10 * p10 - 5; + int p90 = n - p10; // 90% index + + double np_s = n - 1; + s[0] = np_s; + s[1] = 1.0; + + x_end = (x_end - x_start) / np_s; + int i = (int)x_start; + x_start -= float(i + 1.0); + + for (int j = 0; j < n; j++) + { + while (x_start > 0.0 && (i + 1) < np) + { + x_start--; + i++; + } + + s[j + 2] = pfl[i + 3] + (pfl[i + 3] - pfl[i + 2]) * x_start; + + x_start += x_end; + } + + double fit_y1, fit_y2; + LinearLeastSquaresFit(s, 0.0, np_s, &fit_y1, &fit_y2); + + fit_y2 = (fit_y2 - fit_y1) / np_s; + + std::vector diffs; + + // compute the difference between fitted line and actual data + for (int j = 0; j < n; j++) + { + diffs.push_back(s[j + 2] - fit_y1); + + fit_y1 += fit_y2; + } + + std::nth_element(diffs.begin(), diffs.begin() + p10 - 1, diffs.end(), std::greater()); + double q10 = diffs[p10 - 1]; + + std::nth_element(diffs.begin(), diffs.begin() + p90, diffs.end(), std::greater()); + double q90 = diffs[p90]; + + double delta_h_d__meter = q10 - q90; + + // [ERL 79-ITS 67, Eqn 3], inverted + double delta_h__meter = delta_h_d__meter / (1.0 - 0.8 * exp(-(d_end__meter - d_start__meter) / 50e3)); + + return delta_h__meter; +} \ No newline at end of file diff --git a/src/DiffractionLoss.cpp b/src/DiffractionLoss.cpp new file mode 100644 index 0000000..dc3a669 --- /dev/null +++ b/src/DiffractionLoss.cpp @@ -0,0 +1,69 @@ +#include "..\include\itm.h" + +/*============================================================================= + | + | Description: Compute the diffraction loss at a specified distance + | + | Input: d__meter - Path distance, in meters + | d_hzn__meter[2] - Horizon distances, in meters + | h_e__meter[2] - Effective terminal heights, in meters + | Z_g - Complex ground impedance + | a_e__meter - Effective earth radius, in meters + | delta_h__meter - Terrain irregularity parameter, in meters + | h__meter[2] - Terminal heights, in meters + | mode - Area or Point-to-Point mode flag + | theta_los - Angular distance of line-of-sight region + | d_sML__meter - Maximum line-of-sight distance for + | a smooth earth, in meters + | f__mhz - Frequency, in MHz + | + | Outputs: [None] + | + | Returns: A_d__db - Diffraction loss, in dB + | + *===========================================================================*/ +double DiffractionLoss(double d__meter, double d_hzn__meter[2], double h_e__meter[2], complex Z_g, double a_e__meter, + double delta_h__meter, double h__meter[2], int mode, double theta_los, double d_sML__meter, double f__mhz) +{ + double A_k__db = KnifeEdgeDiffraction(d__meter, f__mhz, a_e__meter, theta_los, d_hzn__meter); + + double A_se__db = SmoothEarthDiffraction(d__meter, f__mhz, a_e__meter, theta_los, d_hzn__meter, h_e__meter, Z_g); + + ////////////////// + // Terrain clutter + + // Terrain roughness term, using d_sML__meter, per [ERL 79-ITS 67, page 3-13] + double delta_h_dsML__meter = TerrainRoughness(d_sML__meter, delta_h__meter); + + double sigma_h_d__meter = SigmaHFunction(delta_h_dsML__meter); + + // Clutter factor + // [ERL 79-ITS 67, Eqn 3.38c] + double A_fo__db = MIN(15.0, 5 * log10(1.0 + 1e-5 * h__meter[0] * h__meter[1] * f__mhz * sigma_h_d__meter)); + + ////////////////////////////// + // Combined diffraction losses + + // compute the weighting factor in the following calculations + + double delta_h_d__meter = TerrainRoughness(d__meter, delta_h__meter); + + double q = h__meter[0] * h__meter[1]; + double qk = h_e__meter[0] * h_e__meter[1] - q; + + // For low antennas with known path parameters, C ~= 10 [ERL 79-ITS 67, page 3-8] + if (mode == MODE__P2P) + q += 10.0; + + double term1 = sqrt(1.0 + qk / q); // square root term in [ERL 79-ITS 67, Eqn 2.23] + + double d_ML__meter = d_hzn__meter[0] + d_hzn__meter[1]; // Maximum line-of-sight distance for actual path + q = (term1 + (-theta_los * a_e__meter + d_ML__meter) / d__meter) * MIN(delta_h_d__meter * f__mhz / 47.7, 6283.2); + + // weighting factor [ERL 17-ITS 67, Eqn 3.23] + double w = 25.1 / (25.1 + sqrt(q)); + + double A_d__db = w * A_se__db + (1.0 - w) * A_k__db + A_fo__db; + + return A_d__db; +} \ No newline at end of file diff --git a/src/FindHorizons.cpp b/src/FindHorizons.cpp new file mode 100644 index 0000000..7beb29a --- /dev/null +++ b/src/FindHorizons.cpp @@ -0,0 +1,61 @@ +#include "..\include\itm.h" + +/*============================================================================= + | + | Description: Compute the radio horizon's of the terminals + | + | Input: pfl[] - Terrain data + | a_e__meter - Effective earth radius, in meters + | h__meter[2] - Terminal structural heights, in meters + | + | Outputs: theta_hzn[2] - Terminal radio horizon angle, in radians + | d_hzn__meter[2] - Terminal radio horizon distance, in meters + | + | Returns: [None] + | + *===========================================================================*/ +void FindHorizons(double pfl[], double a_e__meter, double h__meter[2], double theta_hzn[2], double d_hzn__meter[2]) +{ + int np = int(pfl[0]); + double xi = pfl[1]; + + double d__meter = pfl[0] * pfl[1]; + + // compute radials (ignore radius of earth since it cancels out in the later math) + double z_tx__meter = pfl[2] + h__meter[0]; + double z_rx__meter = pfl[np + 2] + h__meter[1]; + + // set the terminal horizon angles as if the terminals are line-of-sight + // [TN101, Eq 6.15] + theta_hzn[0] = (z_rx__meter - z_tx__meter) / d__meter - d__meter / (2 * a_e__meter); + theta_hzn[1] = -(z_rx__meter - z_tx__meter) / d__meter - d__meter / (2 * a_e__meter); + + d_hzn__meter[0] = d__meter; + d_hzn__meter[1] = d__meter; + + double d_tx__meter = 0.0; + double d_rx__meter = d__meter; + + double theta_tx, theta_rx; + + for (int i = 1; i < np; i++) + { + d_tx__meter = d_tx__meter + xi; + d_rx__meter = d_rx__meter - xi; + + theta_tx = (pfl[i + 2] - z_tx__meter) / d_tx__meter - d_tx__meter / (2 * a_e__meter); + theta_rx = -(z_rx__meter - pfl[i + 2]) / d_rx__meter - d_rx__meter / (2 * a_e__meter); + + if (theta_tx > theta_hzn[0]) + { + theta_hzn[0] = theta_tx; + d_hzn__meter[0] = d_tx__meter; + } + + if (theta_rx > theta_hzn[1]) + { + theta_hzn[1] = theta_rx; + d_hzn__meter[1] = d_rx__meter; + } + } +} \ No newline at end of file diff --git a/src/FreeSpaceLoss.cpp b/src/FreeSpaceLoss.cpp new file mode 100644 index 0000000..0981ec7 --- /dev/null +++ b/src/FreeSpaceLoss.cpp @@ -0,0 +1,18 @@ +#include "..\include\itm.h" + +/*============================================================================= + | + | Description: Free space basic transmission loss equation + | + | Input: d__meter - Path distance, in meters + | f__mhz - Frequency, in MHz + | + | Outputs: [None] + | + | Returns: A_fs__db - Free space basic transmission loss, in dB + | + *===========================================================================*/ +double FreeSpaceLoss(double d__meter, double f__mhz) +{ + return 32.45 + 20.0 * log10(f__mhz) + 20.0 * log10(d__meter / 1000.0); +} \ No newline at end of file diff --git a/src/FresnelIntegral.cpp b/src/FresnelIntegral.cpp new file mode 100644 index 0000000..0726d1b --- /dev/null +++ b/src/FresnelIntegral.cpp @@ -0,0 +1,22 @@ +#include "..\include\itm.h" + +/*============================================================================= + | + | Description: Approximate to ideal knife edge diffraction loss + | + | Input: v2 - v^2 parameter + | + | Outputs: [None] + | + | Returns: A(v, 0) - Loss, in dB + | + *===========================================================================*/ +double FresnelIntegral(double v2) +{ + // Note: v2 is v^2, so 5.76 is actually comparing v to 2.4 + + if (v2 < 5.76) + return 6.02 + 9.11 * sqrt(v2) - 1.27 * v2; // [TN101v2, Eqn III.24b] and [ERL 79-ITS 67, Eqn 3.27a & 3.27b] + else + return 12.953 + 10 * log10(v2); // [TN101v2, Eqn III.24c] and [ERL 79-ITS 67, Eqn 3.27a & 3.27b] +} \ No newline at end of file diff --git a/src/H0Function.cpp b/src/H0Function.cpp new file mode 100644 index 0000000..b1ae842 --- /dev/null +++ b/src/H0Function.cpp @@ -0,0 +1,51 @@ +#include "..\include\itm.h" + +/*============================================================================= + | + | Description: Curve fit helper function to approximate H_0() + | + | Input: j - eta_s curve + | r - Input parameter r_1,2 + | + | Outputs: [None] + | + | Returns: H_01(r, j) - in dB + | + *===========================================================================*/ +double H0Curve(int j, double r) +{ + // values from [Algorithm, 6.13] + double a[] = { 25.0, 80.0, 177.0, 395.0, 705.0 }; + double b[] = { 24.0, 45.0, 68.0, 80.0, 105.0 }; + + return 10 * log10(1 + a[j] * pow(1 / r, 4) + b[j] * pow(1.0 / r, 2)); // related to TN101v2, Eqn III.49, but from [Algorithm, 6.13] +} + + +/*============================================================================= + | + | Description: Troposcatter frequency gain function, H_0(), from + | [TN101v1, Ch 9.2] + | + | Input: r - Input parameter r_1,2 + | eta_s - Parameter eta_s + | + | Outputs: [None] + | + | Returns: H_0() - in dB + | + *===========================================================================*/ +double H0Function(double r, double eta_s) +{ + eta_s = MIN(MAX(eta_s, 1), 5); // range 1 <= eta_s <= 5 + + int i = int(eta_s); // integer part of eta_s + double q = eta_s - i; // decimal part of eta_s + + double result = H0Curve(i - 1, r); + + if (q != 0.0) // interpolate with next curve, if needed + result = (1.0 - q) * result + q * H0Curve(i, r); + + return result; +} diff --git a/src/InitializeArea.cpp b/src/InitializeArea.cpp new file mode 100644 index 0000000..8d1ffc8 --- /dev/null +++ b/src/InitializeArea.cpp @@ -0,0 +1,55 @@ +#include "..\include\itm.h" +#include "..\include\Enums.h" + +/*============================================================================= + | + | Description: Initialize area mode calculations + | + | Input: site_criteria[2] - Siting criteria of the terminals + | + 0 : SITING_CRITERIA__RANDOM + | + 1 : SITING_CRITERIA__CAREFUL + | + 2 : SITING_CRITERIA__VERY_CAREFUL + | gamma_e - Curvature of the effective earth + | delta_h__meter - Terrain irregularity parameter, in meters + | h__meter[2] - Terminal structural heights, in meters + | + | Outputs: h_e__meter[2] - Effective terminal heights, in meters + | d_hzn__meter[2] - Terminal horizon distances, in meters + | theta_hzn[2] - Terminal horizon angle + | + | Returns: [None] + | + *===========================================================================*/ +void InitializeArea(int site_criteria[2], double gamma_e, double delta_h__meter, + double h__meter[2], double h_e__meter[2], double d_hzn__meter[2], double theta_hzn[2]) +{ + for (int i = 0; i < 2; i++) + { + if (site_criteria[i] == SITING_CRITERIA__RANDOM) + h_e__meter[i] = h__meter[i]; + else + { + double B; + + if (site_criteria[i] == SITING_CRITERIA__CAREFUL) + B = 4.0; + else // SITING_CRITERIA__VERY_CAREFUL + B = 9.0; + + if (h__meter[i] < 5.0) + B = B * sin(0.1 * PI * h__meter[i]); + + // [Algorithm, Eqn 3.2] + h_e__meter[i] = h__meter[i] + (1.0 + B) * exp(-MIN(20.0, 2.0 * h__meter[i] / MAX(1e-3, delta_h__meter))); + } + + double d_Ls__meter = sqrt(2.0 * h_e__meter[i] / gamma_e); + + // [Algorithm, Eqn 3.3] + double H_3__meter = 5; + d_hzn__meter[i] = d_Ls__meter * exp(-0.07 * sqrt(delta_h__meter / MAX(h_e__meter[i], H_3__meter))); + + // [Algorithm, Eqn 3.4] + theta_hzn[i] = (0.65 * delta_h__meter * (d_Ls__meter / d_hzn__meter[i] - 1.0) - 2.0 * h_e__meter[i]) / d_Ls__meter; + } +} \ No newline at end of file diff --git a/src/InitializePointToPoint.cpp b/src/InitializePointToPoint.cpp new file mode 100644 index 0000000..b001477 --- /dev/null +++ b/src/InitializePointToPoint.cpp @@ -0,0 +1,47 @@ +#include "..\include\itm.h" +#include "..\include\Enums.h" + +/*============================================================================= + | + | Description: Initialize parameters for point-to-point mode + | + | Input: f__mhz - Frequency, in MHz + | h_sys__meter - Average height of the path above + | mean sea level, in meters + | N_0 - Refractivity, in N-Units + | pol - Polarization + | + 0 : POLARIZATION__HORIZONTAL + | + 1 : POLARIZATION__VERTICAL + | epsilon - Relative permittivity + | sigma - Conductivity + | + | Outputs: Z_g - Complex ground impedance + | gamma_e - Curvature of the effective earth + | N_s - Surface refractivity, in N-Units + | + | Returns: [None] + | + *===========================================================================*/ +void InitializePointToPoint(double f__mhz, double h_sys__meter, double N_0, int pol, + double epsilon, double sigma, complex *Z_g, double *gamma_e, double *N_s) +{ + // gamma_a is the curvature of the actual earth, ~1 / 6370 km + double gamma_a = 157e-9; + + // scale the refractivity based on the elevation above mean sea level + if (h_sys__meter == 0.0) + *N_s = N_0; + else + *N_s = N_0 * exp(-h_sys__meter / 9460.0); // [TN101, Eq 4.3] + + // gamma_e is the curvature of the effective earth + *gamma_e = gamma_a * (1.0 - 0.04665 * exp(*N_s / 179.3)); // [TN101, Eq 4.4], reworked + + // complex relative permittivity + complex ep_r = complex(epsilon, 18000 * sigma / f__mhz); + + *Z_g = sqrt(ep_r - 1.0); // ground impedance (horizontal polarization) + + if (pol == POLARIZATION__VERTICAL) // adjust for vertical polarization + *Z_g = *Z_g / ep_r; +} \ No newline at end of file diff --git a/src/InverseComplementaryCumulativeDistributionFunction.cpp b/src/InverseComplementaryCumulativeDistributionFunction.cpp new file mode 100644 index 0000000..68b0436 --- /dev/null +++ b/src/InverseComplementaryCumulativeDistributionFunction.cpp @@ -0,0 +1,41 @@ +#include "..\include\itm.h" + +/*============================================================================= + | + | Description: This function computes the inverse complementary + | cumulative distribution function approximation as + | described in Formula 26.2.23 in Abramowitz & Stegun. + | This approximation has an error of + | abs(epsilon(p)) < 4.5e-4 + | + | Input: q - Quantile, 0.0 < q < 1.0 + | + | Outputs: [None] + | + | Returns: Q_q - Q(q)^-1 + | + *===========================================================================*/ +double InverseComplementaryCumulativeDistributionFunction(double q) +{ + double C_0 = 2.515516; + double C_1 = 0.802853; + double C_2 = 0.010328; + double D_1 = 1.432788; + double D_2 = 0.189269; + double D_3 = 0.001308; + + double x = q; + if (q > 0.5) + x = 1.0 - x; + + double T_x = sqrt(-2.0 * log(x)); + + double zeta_x = ((C_2 * T_x + C_1) * T_x + C_0) / (((D_3 * T_x + D_2) * T_x + D_1) * T_x + 1.0); + + double Q_q = T_x - zeta_x; + + if (q > 0.5) + Q_q = -Q_q; + + return Q_q; +} diff --git a/src/KnifeEdgeDiffraction.cpp b/src/KnifeEdgeDiffraction.cpp new file mode 100644 index 0000000..4cec35c --- /dev/null +++ b/src/KnifeEdgeDiffraction.cpp @@ -0,0 +1,33 @@ +#include "..\include\itm.h" + +/*============================================================================= + | + | Description: Compute the knife-edge diffraction loss + | + | Input: d__meter - Distance of interest, in meters + | f__mhz - Frequency, in MHz + | a_e__meter - Effective earth radius, in meters + | theta_los - Angular distance of line-of-sight region + | d_hzn__meter[2] - Horizon distances, in meters + | + | Outputs: [None] + | + | Returns: A_k__db - Knife-edge diffraction loss, in dB + | + *===========================================================================*/ +double KnifeEdgeDiffraction(double d__meter, double f__mhz, double a_e__meter, double theta_los, double d_hzn__meter[2]) +{ + double d_ML__meter = d_hzn__meter[0] + d_hzn__meter[1]; // Maximum line-of-sight distance for actual path + double theta_nlos = d__meter / a_e__meter - theta_los; // Angular distance of diffraction region [Algorithm, Eqn 4.12] + + double d_nlos__meter = d__meter - d_ML__meter; // Diffraction distance, in meters + + // 1 / (4 pi) = 0.0795775 + // [TN101, Eqn I.7] + double v_1 = 0.0795775 * (f__mhz / 47.7) * pow(theta_nlos, 2) * d_hzn__meter[0] * d_nlos__meter / (d_nlos__meter + d_hzn__meter[0]); + double v_2 = 0.0795775 * (f__mhz / 47.7) * pow(theta_nlos, 2) * d_hzn__meter[1] * d_nlos__meter / (d_nlos__meter + d_hzn__meter[1]); + + double A_k__db = FresnelIntegral(v_1) + FresnelIntegral(v_2); // [TN101, Eqn I.1] + + return A_k__db; +} \ No newline at end of file diff --git a/src/LineOfSightLoss.cpp b/src/LineOfSightLoss.cpp new file mode 100644 index 0000000..e8c7a73 --- /dev/null +++ b/src/LineOfSightLoss.cpp @@ -0,0 +1,63 @@ +#include "..\include\itm.h" + +/*============================================================================= + | + | Description: Compute the loss in the line-of-sight region + | + | Input: d__meter - Path distance, in meters + | h_e__meter[2] - Terminal effective heights, in meters + | Z_g - Complex surface transfer impedance + | delta_h__meter - Terrain irregularity parameter + | M_d - Diffraction slope + | A_d0 - Diffraction intercept + | d_sML__meter - Maximum line-of-sight distance for + | a smooth earth, in meters + | f__mhz - Frequency, in MHz + | + | Outputs: [None] + | + | Returns: A_los__db - Loss, in dB + | + *===========================================================================*/ +double LineOfSightLoss(double d__meter, double h_e__meter[2], complex Z_g, double delta_h__meter, + double M_d, double A_d0, double d_sML__meter, double f__mhz) +{ + double delta_h_d__meter = TerrainRoughness(d__meter, delta_h__meter); + + double sigma_h_d__meter = SigmaHFunction(delta_h_d__meter); + + // wavenumber, k + double wn = f__mhz / 47.7; + + // [Algorithm, Eqn 4.46] + double sin_psi = (h_e__meter[0] + h_e__meter[1]) / sqrt(pow(d__meter, 2) + pow(h_e__meter[0] + h_e__meter[1], 2)); + + // [Algorithm, Eqn 4.47] + complex R_e = (sin_psi - Z_g) / (sin_psi + Z_g) * exp(-MIN(10.0, wn * sigma_h_d__meter * sin_psi)); + + // q = Magnitude of R_e', [Algorithm, Eqn 4.48] + double q = pow(R_e.real(), 2) + pow(R_e.imag(), 2); + if (q < 0.25 || q < sin_psi) + R_e = R_e * sqrt(sin_psi / q); + + // phase difference between rays, [Algorithm, Eqn 4.49] + double delta_phi = wn * 2.0 * h_e__meter[0] * h_e__meter[1] / d__meter; + + // [Algorithm, Eqn 4.50] + if (delta_phi > PI / 2.0) + delta_phi = PI - pow(PI / 2.0, 2) / delta_phi; + + // Two-ray attenuation + complex rr = complex(cos(delta_phi), -sin(delta_phi)) + R_e; + double A_t__db = -10 * log10(pow(rr.real(), 2) + pow(rr.imag(), 2)); + + // Extended diffraction attenuation + double A_d__db = M_d * d__meter + A_d0; + + // weighting factor + double w = 1 / (1 + f__mhz * delta_h__meter / MAX(10e3, d_sML__meter)); + + double A_los__db = w * A_t__db + (1 - w) * A_d__db; + + return A_los__db; +} \ No newline at end of file diff --git a/src/LinearLeastSquaresFit.cpp b/src/LinearLeastSquaresFit.cpp new file mode 100644 index 0000000..65f2829 --- /dev/null +++ b/src/LinearLeastSquaresFit.cpp @@ -0,0 +1,52 @@ +#include "..\include\itm.h" + +/*============================================================================= + | + | Description: Perform a linear least squares fit to the terrain data + | + | Input: pfl[2] - Input data array, in pfl format + | d_start - Start distance + | d_end - End distance + | + | Outputs: fit_y1 - Fitted y1 value + | fit_y2 - Fitted y2 value + | + | Returns: [None] + | + *===========================================================================*/ +void LinearLeastSquaresFit(double pfl[], double d_start, double d_end, double *fit_y1, double *fit_y2) +{ + int np = (int)pfl[0]; + + int i_start = int(fdim(d_start / pfl[1], 0.0)); + int i_end = np - int(fdim(np, d_end / pfl[1])); + + if (i_end <= i_start) + { + i_start = (int)fdim(i_start, 1.0); + i_end = np - (int)fdim(np, i_end + 1.0); + } + + double x_length = i_end - i_start; + + double mid_shifted_index = -0.5 * x_length; + double mid_shifted_end = i_end + mid_shifted_index; + + double sum_y = 0.5 * (pfl[i_start + 2] + pfl[i_end + 2]); + double scaled_sum_y = 0.5 * (pfl[i_start + 2] - pfl[i_end + 2]) * mid_shifted_index; + + for (int i = 2; i <= x_length; i++) + { + i_start++; + mid_shifted_index++; + + sum_y += pfl[i_start + 2]; + scaled_sum_y += pfl[i_start + 2] * mid_shifted_index; + } + + sum_y = sum_y / x_length; + scaled_sum_y = scaled_sum_y * 12.0 / ((x_length * x_length + 2.0) * x_length); + + *fit_y1 = sum_y - scaled_sum_y * mid_shifted_end; + *fit_y2 = sum_y + scaled_sum_y * (np - mid_shifted_end); +} \ No newline at end of file diff --git a/src/LongleyRice.cpp b/src/LongleyRice.cpp new file mode 100644 index 0000000..88fdda0 --- /dev/null +++ b/src/LongleyRice.cpp @@ -0,0 +1,225 @@ +#include "..\include\itm.h" +#include "..\include\Enums.h" +#include "..\include\Errors.h" +#include "..\include\Warnings.h" + +/*============================================================================= + | + | Description: Compute the reference attenuation, using the + | Longley-Rice method + | + | Input: theta_hzn[2] - Terminal horizon angles + | f__mhz - Frequency, in MHz + | Z_g - Complex surface transfer impedance + | d_hzn__meter[2] - Terminal horizon distances, in meters + | h_e__meter[2] - Effective terminal heights, in meters + | gamma_e - Curvature of the effective earth + | N_s - Surface refractivity, in N-Units + | delta_h__meter - Terrain irregularity parameter + | h__meter[2] - Terminal structural heights, in meters + | d__meter - Path distance, in meters + | mode - Mode of operation (P2P or Area) + | + | Outputs: A_ref__db - Reference attenuation, in dB + | warnings - Warning flags + | propmode - Mode of propagation value + | + | Returns: error - Error code + | + *===========================================================================*/ +int LongleyRice(double theta_hzn[2], double f__mhz, complex Z_g, double d_hzn__meter[2], + double h_e__meter[2], double gamma_e, double N_s, double delta_h__meter, double h__meter[2], + double d__meter, int mode, double *A_ref__db, long *warnings, int *propmode) +{ + // effective earth radius + double a_e__meter = 1 / gamma_e; + + double d_hzn_s__meter[2]; + // Terrestrial smooth earth horizon distance approximation + for (int i = 0; i < 2; i++) + d_hzn_s__meter[i] = sqrt(2.0 * h_e__meter[i] * a_e__meter); + + // Maximum line-of-sight distance for smooth earth + double d_sML__meter = d_hzn_s__meter[0] + d_hzn_s__meter[1]; + + // Maximum line-of-sight distance for actual path + double d_ML__meter = d_hzn__meter[0] + d_hzn__meter[1]; + + // Angular distance of line-of-sight region + double theta_los = -MAX(theta_hzn[0] + theta_hzn[1], -d_ML__meter / a_e__meter); + + // Check validity of small angle approximation + if (abs(theta_hzn[0]) > 200e-3) + *warnings |= WARN__TX_HORIZON_ANGLE; + if (abs(theta_hzn[1]) > 200e-3) + *warnings |= WARN__RX_HORIZON_ANGLE; + + // Checks that the actual horizon distance can't be less than 1/10 of the smooth earth horizon distance + if (d_hzn__meter[0] < 0.1 * d_hzn_s__meter[0]) + *warnings |= WARN__TX_HORIZON_DISTANCE_1; + if (d_hzn__meter[1] < 0.1 * d_hzn_s__meter[1]) + *warnings |= WARN__RX_HORIZON_DISTANCE_1; + + // Checks that the actual horizon distance can't be greater than 3 times the smooth earth horizon distance + if (d_hzn__meter[0] > 3.0 * d_hzn_s__meter[0]) + *warnings |= WARN__TX_HORIZON_DISTANCE_2; + if (d_hzn__meter[1] > 3.0 * d_hzn_s__meter[1]) + *warnings |= WARN__RX_HORIZON_DISTANCE_2; + + // Check the surface refractivity + if (N_s < 150) + return ERROR__SURFACE_REFRACTIVITY_SMALL; + if (N_s > 400) + return ERROR__SURFACE_REFRACTIVITY_LARGE; + if (N_s < 250) // 150 <= N_s < 250 + *warnings |= WARN__SURFACE_REFRACTIVITY; + + // Check effective earth size + if (a_e__meter < 4000000 || a_e__meter > 13333333) + return ERROR__EFFECTIVE_EARTH; + + // Check ground impedance + if (Z_g.real() <= abs(Z_g.imag())) + return ERROR__GROUND_IMPEDANCE; + + // Select two distances far in the diffraction region + double d_3__meter = MAX(d_sML__meter, d_ML__meter + 5.0 * pow(pow(a_e__meter, 2) / f__mhz, 1.0 / 3.0)); + double d_4__meter = d_3__meter + 10.0 * pow(pow(a_e__meter, 2) / f__mhz, 1.0 / 3.0); + + // Compute the diffraction loss at the two distances + double A_3__db = DiffractionLoss(d_3__meter, d_hzn__meter, h_e__meter, Z_g, a_e__meter, delta_h__meter, h__meter, mode, theta_los, d_sML__meter, f__mhz); + double A_4__db = DiffractionLoss(d_4__meter, d_hzn__meter, h_e__meter, Z_g, a_e__meter, delta_h__meter, h__meter, mode, theta_los, d_sML__meter, f__mhz); + + // Compute the slope and intercept of the diffraction line + double M_d = (A_4__db - A_3__db) / (d_4__meter - d_3__meter); + double A_d0__db = A_3__db - M_d * d_3__meter; + + double d_min__meter = abs(h_e__meter[0] - h_e__meter[1]) / 200e-3; + + if (d__meter < d_min__meter) + *warnings |= WARN__PATH_DISTANCE_TOO_SMALL_1; + if (d__meter < 1e3) + *warnings |= WARN__PATH_DISTANCE_TOO_SMALL_2; + if (d__meter > 1000e3) + *warnings |= WARN__PATH_DISTANCE_TOO_BIG_1; + if (d__meter > 2000e3) + *warnings |= WARN__PATH_DISTANCE_TOO_BIG_2; + + // if the path distance is less than the maximum smooth earth line of sight distance... + if (d__meter < d_sML__meter) + { + // Compute the diffraction loss at the maximum smooth earth line of sight distance + double A_sML__db = d_sML__meter * M_d + A_d0__db; + + // [ERL 79-ITS 67, Eqn 3.16a], in meters instead of km and with MIN() part below + double d_0__meter = 0.04 * f__mhz * h_e__meter[0] * h_e__meter[1]; + + double d_1__meter; + if (A_d0__db >= 0.0) + { + d_0__meter = MIN(d_0__meter, 0.5 * d_ML__meter); // other part of [ERL 79-ITS 67, Eqn 3.16a] + d_1__meter = d_0__meter + 0.25 * (d_ML__meter - d_0__meter); // [ERL 79-ITS 67, Eqn 3.16d] + } + else + d_1__meter = MAX(-A_d0__db / M_d, 0.25 * d_ML__meter); + + double A_1__db = LineOfSightLoss(d_1__meter, h_e__meter, Z_g, delta_h__meter, M_d, A_d0__db, d_sML__meter, f__mhz); + + bool flag = false; + + double kHat_1__db_per_meter = 0; + double kHat_2__db_per_meter = 0; + + if (d_0__meter < d_1__meter) + { + double A_0__db = LineOfSightLoss(d_0__meter, h_e__meter, Z_g, delta_h__meter, M_d, A_d0__db, d_sML__meter, f__mhz); + + double q = log(d_sML__meter / d_0__meter); + + // [ERL 79-ITS 67, Eqn 3.20] + kHat_2__db_per_meter = MAX(0.0, ((d_sML__meter - d_0__meter) * (A_1__db - A_0__db) - (d_1__meter - d_0__meter) * (A_sML__db - A_0__db)) / ((d_sML__meter - d_0__meter) * log(d_1__meter / d_0__meter) - (d_1__meter - d_0__meter) * q)); + + flag = A_d0__db > 0.0 || kHat_2__db_per_meter > 0.0; + + if (flag) + { + // [ERL 79-ITS 67, Eqn 3.21] + kHat_1__db_per_meter = (A_sML__db - A_0__db - kHat_2__db_per_meter * q) / (d_sML__meter - d_0__meter); + + if (kHat_1__db_per_meter < 0.0) + { + kHat_1__db_per_meter = 0.0; + kHat_2__db_per_meter = DIM(A_sML__db, A_0__db) / q; + + if (kHat_2__db_per_meter == 0.0) + kHat_1__db_per_meter = M_d; + } + } + } + + if (!flag) + { + kHat_1__db_per_meter = DIM(A_sML__db, A_1__db) / (d_sML__meter - d_1__meter); + kHat_2__db_per_meter = 0.0; + + if (kHat_1__db_per_meter == 0.0) + kHat_1__db_per_meter = M_d; + } + + double A_o__db = A_sML__db - kHat_1__db_per_meter * d_sML__meter - kHat_2__db_per_meter * log(d_sML__meter); + + // [ERL 79-ITS 67, Eqn 3.19] + *A_ref__db = A_o__db + kHat_1__db_per_meter * d__meter + kHat_2__db_per_meter * log(d__meter); + *propmode = MODE__LINE_OF_SIGHT; + } + else // this is a trans-horizon path + { + // select to points far into the troposcatter region + double d_5__meter = d_ML__meter + 200e3; + double d_6__meter = d_ML__meter + 400e3; + + // Compute the troposcatter loss at the two distances + double h0 = -1; + double A_6__db = TroposcatterLoss(d_6__meter, theta_hzn, d_hzn__meter, h_e__meter, a_e__meter, N_s, f__mhz, theta_los, &h0); + double A_5__db = TroposcatterLoss(d_5__meter, theta_hzn, d_hzn__meter, h_e__meter, a_e__meter, N_s, f__mhz, theta_los, &h0); + + double M_s, A_s0__db, d_x__meter; + + // if we got a reasonable prediction value back... + if (A_5__db < 1000.0) + { + // Compute the slope of the troposcatter line + M_s = (A_6__db - A_5__db) / 200e3; + + // Find the diffraction-troposcatter transition distance + d_x__meter = MAX(MAX(d_sML__meter, d_ML__meter + 1.088 * pow(pow(a_e__meter, 2) / f__mhz, 1.0 / 3.0) * log(f__mhz)), (A_5__db - A_d0__db - M_s * d_5__meter) / (M_d - M_s)); + + // Compute the intercept of the troposcatter line + A_s0__db = (M_d - M_s) * d_x__meter + A_d0__db; + } + else + { + // troposcatter gives no real results - so use diffraction line parameters for tropo line + M_s = M_d; + A_s0__db = A_d0__db; + d_x__meter = 10e6; + } + + // Determine if its diffraction or troposcatter and compute the loss + if (d__meter > d_x__meter) + { + *A_ref__db = M_s * d__meter + A_s0__db; + *propmode = MODE__DIFFRACTION; + } + else + { + *A_ref__db = M_d * d__meter + A_d0__db; + *propmode = MODE__TROPOSCATTER; + } + } + + // Don't allow a negative loss + *A_ref__db = MAX(*A_ref__db, 0.0); + + return SUCCESS; +} \ No newline at end of file diff --git a/src/QuickPfl.cpp b/src/QuickPfl.cpp new file mode 100644 index 0000000..6f4c942 --- /dev/null +++ b/src/QuickPfl.cpp @@ -0,0 +1,83 @@ +#include "..\include\itm.h" + +/*============================================================================= + | + | Description: Extract parameters from the terrain pfl + | + | Input: pfl[2] - Terrain data in pfl format + | gamma_e - Effective earth curvature + | h__meter[2] - Terminal structural heights, in meters + | + | Outputs: theta_hzn[2] - Terminal horizon angles + | d_hzn__meter[2] - Terminal horizon distances, in meters + | h_e__meter[2] - Effective terminal heights, in meters + | delta_h__meter - Terrain irregularity parameter + | d__meter - Path distance, in meters + | + | Returns: [None] + | + *===========================================================================*/ +void QuickPfl(double pfl[], double gamma_e, double h__meter[2], double theta_hzn[2], + double d_hzn__meter[2], double h_e__meter[2], double *delta_h__meter, double *d__meter) +{ + double fit_tx, fit_rx, q; + double d_start__meter; + double d_end__meter; + + *d__meter = pfl[0] * pfl[1]; + + int np = int(pfl[0]); + + double a_e__meter = 1 / gamma_e; // effective earth radius + + FindHorizons(pfl, a_e__meter, h__meter, theta_hzn, d_hzn__meter); + + // "In our own work we have sometimes said that consideration of terrain elevations should begin at a point about 15 times the tower height" + // - [Hufford, 1982] Page 25 + d_start__meter = MIN(15.0 * h__meter[0], 0.1 * d_hzn__meter[0]); // take lesser: 10% of horizon distance or 15x terminal height + d_end__meter = *d__meter - MIN(15.0 * h__meter[1], 0.1 * d_hzn__meter[1]); // << ditto, but measured from the far end of the link >> + + *delta_h__meter = ComputeDeltaH(pfl, d_start__meter, d_end__meter); + + if (d_hzn__meter[0] + d_hzn__meter[1] > 1.5 * *d__meter) + { + // The combined horizon distance is at least 50% larger than the total path distance + // -> so we are well within the line-of-sight range + + LinearLeastSquaresFit(pfl, d_start__meter, d_end__meter, &fit_tx, &fit_rx); + + h_e__meter[0] = h__meter[0] + fdim(pfl[2], fit_tx); + h_e__meter[1] = h__meter[1] + fdim(pfl[np + 2], fit_rx); + + for (int i = 0; i < 2; i++) + d_hzn__meter[i] = sqrt(2.0 * h_e__meter[i] * a_e__meter) * exp(-0.07 * sqrt(*delta_h__meter / MAX(h_e__meter[i], 5.0))); + + double combined_horizons__meter = d_hzn__meter[0] + d_hzn__meter[1]; + if (combined_horizons__meter <= *d__meter) + { + q = pow(*d__meter / combined_horizons__meter, 2); + + for (int i = 0; i < 2; i++) + { + h_e__meter[i] = h_e__meter[i] * q; + d_hzn__meter[i] = sqrt(2.0 * h_e__meter[i] * a_e__meter) * exp(-0.07 * sqrt(*delta_h__meter / MAX(h_e__meter[i], 5.0))); + } + } + + for (int i = 0; i < 2; i++) + { + q = sqrt(2.0 * h_e__meter[i] * a_e__meter); + theta_hzn[i] = (0.65 * *delta_h__meter * (q / d_hzn__meter[i] - 1.0) - 2.0 * h_e__meter[i]) / q; + } + } + else + { + double dummy = 0; + + LinearLeastSquaresFit(pfl, d_start__meter, 0.9 * d_hzn__meter[0], &fit_tx, &dummy); + h_e__meter[0] = h__meter[0] + fdim(pfl[2], fit_tx); + + LinearLeastSquaresFit(pfl, *d__meter - 0.9 * d_hzn__meter[1], d_end__meter, &dummy, &fit_rx); + h_e__meter[1] = h__meter[1] + fdim(pfl[np + 2], fit_rx); + } +} \ No newline at end of file diff --git a/src/SigmaHFunction.cpp b/src/SigmaHFunction.cpp new file mode 100644 index 0000000..066b4ea --- /dev/null +++ b/src/SigmaHFunction.cpp @@ -0,0 +1,19 @@ +#include "..\include\itm.h" + +/*============================================================================= + | + | Description: Compute sigma_h + | + | Input: delta_h__meter - Terrain irregularity parameter + | + | Outputs: [None] + | + | Returns: sigma_h_meter - sigma_h + | + *===========================================================================*/ +double SigmaHFunction(double delta_h__meter) +{ + // "RMS deviation of terrain and terrain clutter within the limits of the first Fresnel zone in the dominant reflecting plane" + // [ERL 79-ITS 67, Eqn 3.6a] + return 0.78 * delta_h__meter * exp(-0.5 * pow(delta_h__meter, 0.25)); +} \ No newline at end of file diff --git a/src/SmoothEarthDiffraction.cpp b/src/SmoothEarthDiffraction.cpp new file mode 100644 index 0000000..25b480e --- /dev/null +++ b/src/SmoothEarthDiffraction.cpp @@ -0,0 +1,116 @@ +#include "..\include\itm.h" + +/*============================================================================= + | + | Description: Compute the smooth earth diffraction loss using the + | Vogler 3-radii method + | + | Input: d__meter - Path distance, in meters + | f__mhz - Frequency, in MHz + | a_e__meter - Effective earth radius, in meters + | theta_los - Angular distance of line-of-sight region + | d_hzn__meter[2] - Horizon distances, in meters + | h_e__meter[2] - Effective terminal heights, in meters + | Z_g - Complex ground impedance + | + | Outputs: [None] + | + | Returns: A_r__db - Smooth-earth diffraction loss, in dB + | + *===========================================================================*/ +double SmoothEarthDiffraction(double d__meter, double f__mhz, double a_e__meter, double theta_los, + double d_hzn__meter[2], double h_e__meter[2], complex Z_g) +{ + double a__meter[3]; + double d__km[3]; + double F_x__db[2]; + double K[3]; + double B_0[3]; + double x__km[3]; + double C_0[3]; + + double theta_nlos = d__meter / a_e__meter - theta_los; // [Algorithm, Eqn 4.12] + double d_ML__meter = d_hzn__meter[0] + d_hzn__meter[1]; // Maximum line-of-sight distance for actual path + + // compute 3 radii + a__meter[0] = (d__meter - d_ML__meter) / (d__meter / a_e__meter - theta_los); // which is a_e__meter when theta_los = d_ML__meter / a_e__meter + a__meter[1] = 0.5 * pow(d_hzn__meter[0], 2) / h_e__meter[0]; // Compute the radius of the effective earth for terminal j using[Volger 1964, Eqn 3] re - arranged + a__meter[2] = 0.5 * pow(d_hzn__meter[1], 2) / h_e__meter[1]; // Compute the radius of the effective earth for terminal j using[Volger 1964, Eqn 3] re - arranged + + d__km[0] = (a__meter[0] * theta_nlos) / 1000.0; // angular distance of the "diffraction path" + d__km[1] = d_hzn__meter[0] / 1000.0; + d__km[2] = d_hzn__meter[1] / 1000.0; + + for (int i = 0; i < 3; i++) + { + // C_0 is the ratio of the 4/3 earth to effective earth (technically Vogler 1964 ratio is 4/3 to effective earth k value), all raised to the (1/3) power. + // C_0 = (4 / 3k) ^ (1 / 3) [Vogler 1964, Eqn 2] + C_0[i] = pow((4.0 / 3.0) * a_0__meter / a__meter[i], THIRD); + + // [Vogler 1964, Eqn 6a / 7a] + K[i] = 0.017778 * C_0[i] * pow(f__mhz, -THIRD) / abs(Z_g); + + // compute B_0 for each radius + // [Vogler 1964, Fig 4] + B_0[i] = 1.607 - K[i]; + } + + // compute x__km for each radius [Vogler 1964, Eqn 2] + x__km[1] = B_0[1] * pow(C_0[1], 2) * pow(f__mhz, THIRD) * d__km[1]; + x__km[2] = B_0[2] * pow(C_0[2], 2) * pow(f__mhz, THIRD) * d__km[2]; + x__km[0] = B_0[0] * pow(C_0[0], 2) * pow(f__mhz, THIRD) * d__km[0] + x__km[1] + x__km[2]; + + // compute height gain functions + F_x__db[0] = HeightFunction(x__km[1], K[1]); + F_x__db[1] = HeightFunction(x__km[2], K[2]); + + // compute distance function + double G_x__db = 0.05751 * x__km[0] - 10.0 * log10(x__km[0]); // [TN101, Eqn 8.4] & [Volger 1964, Eqn 13] + + return G_x__db - F_x__db[0] - F_x__db[1] - 20; // [Algorithm, Eqn 4.20] & [Volger 1964] +} + +/*============================================================================= + | + | Description: Height Function, F(x, K) for smooth earth diffraction + | + | Input: x__km - Normalized distance, in meters + | K - K value + | + | Outputs: [None] + | + | Returns: F(x, K) - in dB + | + *===========================================================================*/ +double HeightFunction(double x__km, double K) +{ + double w; + double result; + + if (x__km < 200.0) + { + w = -log(K); + + if (K < 1e-5 || x__km * pow(w, 3) > 5495.0) + { + result = -117.0; + + if (x__km > 1.0) + result = 17.372 * log(x__km) + result; + } + else + result = 2.5e-5 * pow(x__km, 2) / K - 8.686 * w - 15.0; + } + else + { + result = 0.05751 * x__km - 4.343 * log(x__km); + + if (x__km < 2000) + { + w = 0.0134 * x__km * exp(-0.005 * x__km); + result = (1.0 - w) * result + w * (17.372 * log(x__km) - 117.0); + } + } + + return result; +} \ No newline at end of file diff --git a/src/TerrainRoughness.cpp b/src/TerrainRoughness.cpp new file mode 100644 index 0000000..d4acc35 --- /dev/null +++ b/src/TerrainRoughness.cpp @@ -0,0 +1,19 @@ +#include "..\include\itm.h" + +/*============================================================================= + | + | Description: Compute delta_h_d + | + | Input: d__meter - Path distance, in meters + | delta_h__meter - Terrain irregularity parameter + | + | Outputs: [None] + | + | Returns: delta_h_d - Terrain irregularity of path + | + *===========================================================================*/ +double TerrainRoughness(double d__meter, double delta_h__meter) +{ + // [ERL 79-ITS 67, Eqn 3], with distance in meters instead of kilometers + return delta_h__meter * (1.0 - 0.8 * exp(-d__meter / 50e3)); +} \ No newline at end of file diff --git a/src/TroposcatterLoss.cpp b/src/TroposcatterLoss.cpp new file mode 100644 index 0000000..b2e4fd0 --- /dev/null +++ b/src/TroposcatterLoss.cpp @@ -0,0 +1,116 @@ +#include "..\include\itm.h" + +/*============================================================================= + | + | Description: The attenuation function, F(th * d) + | + | Input: td - theta * distance + | + | Outputs: [None] + | + | Returns: F() - in dB + | + *===========================================================================*/ +double FFunction(double td) +{ + // constants from [Algorithm, 6.9] + double a[] = { 133.4, 104.6, 71.8 }; + double b[] = { 0.332e-3, 0.212e-3, 0.157e-3 }; + double c[] = { -10, -2.5, 5 }; + + int i; + + // select the set of values to use + if (td <= 10e3) // <= 10 km + i = 0; + else if (td <= 70e3) // 10 km to 70 km + i = 1; + else // > 70 km + i = 2; + + double F_0 = a[i] + b[i] * td + c[i] * log10(td); // [Algorithm, 6.9] + + return F_0; +} + +/*============================================================================= + | + | Description: Troposcatter loss + | + | Input: d__meter - Path distance, in meters + | theta_hzn[2] - Terminal horizon angles + | d_hzn__meter[2] - Terminal horizon distances, in meters + | h_e__meter[2] - Effective terminal heights, in meters + | a_e__meter - Effective earth radius, in meters + | N_s - Surface refractivity, in N-Units + | f__mhz - Frequency, in MHz + | theta_los - Angular distance of LOS region + | + | Outputs: h0 - H_0() value + | + | Returns: F() - in dB + | + *===========================================================================*/ +double TroposcatterLoss(double d__meter, double theta_hzn[2], double d_hzn__meter[2], double h_e__meter[2], + double a_e__meter, double N_s, double f__mhz, double theta_los, double *h0) +{ + double H_0; + + // wavenumber, k + double wn = f__mhz / 47.7; + + if (*h0 > 15.0) // short-circuit calculations if already greater than 15 dB + H_0 = *h0; + else + { + double ad = d_hzn__meter[0] - d_hzn__meter[1]; + double rr = h_e__meter[1] / h_e__meter[0]; + + if (ad < 0.0) // ensure correct frame of reference + { + ad = -ad; + rr = 1.0 / rr; + } + + double theta = theta_hzn[0] + theta_hzn[1] + d__meter / a_e__meter; // angular distance, in radians + + // [TN101, Eqn 9.4a] + double r_1 = 2.0 * wn * theta * h_e__meter[0]; + double r_2 = 2.0 * wn * theta * h_e__meter[1]; + + if (r_1 < 0.2 && r_2 < 0.2) + return 1001; // "If both r_1 and r_2 are less than 0.2 the function A_scat is not defined (or is infinite)" [Algorithm, page 11] + + double s = (d__meter - ad) / (d__meter + ad); // asymmetry parameter + + // "In all of this, we truncate the values of s and q at 0.1 and 10" [Algorithm, page 16] + double q = MIN(MAX(0.1, rr / s), 10.0); // TN101, Eqn 9.5 + s = MAX(0.1, s); // TN101, Eqn 9.5 + + double h_0__meter = (d__meter - ad) * (d__meter + ad) * theta * 0.25 / d__meter; // height of cross-over, [Algorithm, 4.66] [TN101v1, 9.3b] + + double Z_0__meter = 1.7556e3; // Scale height, [Algorithm, 4.67] + double Z_1__meter = 8.0e3; // [Algorithm, 4.67] + double eta_s = (h_0__meter / Z_0__meter) * (1.0 + (0.031 - N_s * 2.32e-3 + pow(N_s, 2) * 5.67e-6) * exp(-pow(MIN(1.7, h_0__meter / Z_1__meter), 6))); // Scattering efficiency factor, eta_s [TN101 Eqn 9.3a] + + double H_00 = (H0Function(r_1, eta_s) + H0Function(r_2, eta_s)) / 2; // First term in TN101v1, Eqn 9.5 + double Delta_H_0 = MIN(H_00, 6.0 * (0.6 - log10(MAX(eta_s, 1.0))) * log10(s) * log10(q)); + + H_0 = H_00 + Delta_H_0; // TN101, Eqn 9.5 + H_0 = MAX(H_0, 0.0); // "If Delta_H_0 would make H_0 negative, use H_0 = 0" [TN101v1, p9.4] + + if (eta_s < 1.0) // if <=1, interpolate with the special case of eta_s = 0 + H_0 = eta_s * H_0 + (1.0 - eta_s) * 10 * log10(pow((1.0 + SQRT2 / r_1) * (1.0 + SQRT2 / r_2), 2) * (r_1 + r_2) / (r_1 + r_2 + 2 * SQRT2)); + + // "If, at d_5, calculations show that H_0 will exceed 15 dB, they are replaced by the value it has at d_6" [Algorithm, page 12] + if (H_0 > 15.0 && *h0 >= 0.0) + H_0 = *h0; + } + + *h0 = H_0; + double th = d__meter / a_e__meter - theta_los; + + double D_0__meter = 40e3; // [Algorithm, 6.8] + double H__meter = 47.7; // [Algorithm, 4.63] + return FFunction(th * d__meter) + 10 * log10(wn * H__meter * pow(th, 4)) - 0.1 * (N_s - 301.0) * exp(-th * d__meter / D_0__meter) + H_0; // [Algorithm, 4.63] +} \ No newline at end of file diff --git a/src/ValidateInputs.cpp b/src/ValidateInputs.cpp new file mode 100644 index 0000000..c300fb7 --- /dev/null +++ b/src/ValidateInputs.cpp @@ -0,0 +1,100 @@ +#include "..\include\itm.h" +#include "..\include\Enums.h" +#include "..\include\Errors.h" +#include "..\include\Warnings.h" + +/*============================================================================= + | + | Description: Perform input parameter validation. This function only + | applies to the set of variables common to both ITM + | point-to-point mode and area mode. + | + | Input: h_tx__meter - Structural height of the TX, in meters + | h_rx__meter - Structural height of the RX, in meters + | climate - Radio climate enum + | + 1 : CLIMATE__EQUATORIAL + | + 2 : CLIMATE__CONTINENTAL_SUBTROPICAL + | + 3 : CLIMATE__MARITIME_SUBTROPICAL + | + 4 : CLIMATE__DESERT + | + 5 : CLIMATE__CONTINENTAL_TEMPERATE + | + 6 : CLIMATE__MARITIME_TEMPERATE_OVER_LAND + | + 7 : CLIMATE__MARITIME_TEMPERATE_OVER_SEA + | time - Time percentage, 0 < time < 100 + | location - Location percentage, 0 < location < 100 + | situation - Situation percentage, 0 < situation < 100 + | N_0 - Refractivity, in N-Units + | f__mhz - Frequency, in MHz + | pol - Polarization + | + 0 : POLARIZATION__HORIZONTAL + | + 1 : POLARIZATION__VERTICAL + | epsilon - Relative permittivity + | sigma - Conductivity + | mdvar - Mode of variability + | + | Outputs: warnings - Warning messages + | + | Returns: [None] + | + *===========================================================================*/ +int ValidateInputs(double h_tx__meter, double h_rx__meter, int climate, double time, + double location, double situation, double N_0, double f__mhz, int pol, + double epsilon, double sigma, int mdvar, long *warnings) +{ + if (h_tx__meter < 1.0 || h_tx__meter > 1000.0) + *warnings |= WARN__TX_TERMINAL_HEIGHT; + + if (h_tx__meter < 0.5 || h_tx__meter > 3000.0) + return ERROR__TX_TERMINAL_HEIGHT; + + if (h_rx__meter < 1.0 || h_rx__meter > 1000.0) + *warnings |= WARN__RX_TERMINAL_HEIGHT; + + if (h_rx__meter < 0.5 || h_rx__meter > 3000.0) + return ERROR__RX_TERMINAL_HEIGHT; + + if (climate != CLIMATE__EQUATORIAL && + climate != CLIMATE__CONTINENTAL_SUBTROPICAL && + climate != CLIMATE__MARITIME_SUBTROPICAL && + climate != CLIMATE__DESERT && + climate != CLIMATE__CONTINENTAL_TEMPERATE && + climate != CLIMATE__MARITIME_TEMPERATE_OVER_LAND && + climate != CLIMATE__MARITIME_TEMPERATE_OVER_SEA) + return ERROR__INVALID_RADIO_CLIMATE; + + if (N_0 < 250 || N_0 > 400) + return ERROR__REFRACTIVITY; + + if (f__mhz < 40.0 || f__mhz > 10000.0) + *warnings |= WARN__FREQUENCY; + + if (f__mhz < 20 || f__mhz > 20000) + return ERROR__FREQUENCY; + + if (pol != POLARIZATION__HORIZONTAL && + pol != POLARIZATION__VERTICAL) + return ERROR__POLARIZATION; + + if (epsilon < 1) + return ERROR__EPSILON; + + if (sigma <= 0) + return ERROR__SIGMA; + + if ((mdvar < 0) || + (mdvar > 3 && mdvar < 10) || + (mdvar > 13 && mdvar < 20) || + (mdvar > 23 && mdvar < 30) || + (mdvar > 33)) + return ERROR__MDVAR; + + if (situation <= 0 || situation >= 100) + return ERROR__INVALID_SITUATION; + + if (time <= 0 || time >= 100) + return ERROR__INVALID_TIME; + + if (location <= 0 || location >= 100) + return ERROR__INVALID_LOCATION; + + return SUCCESS; +} diff --git a/src/Variability.cpp b/src/Variability.cpp new file mode 100644 index 0000000..fa1d699 --- /dev/null +++ b/src/Variability.cpp @@ -0,0 +1,220 @@ +#include "..\include\itm.h" +#include "..\include\Enums.h" +#include "..\include\Warnings.h" + +/*============================================================================= + | + | Description: Curve helper function for TN101v2 Eqn III.69 & III.70 + | + | Input: c1, c2, x1, x2, x3 - Curve fit parameters + | d_e__metre - Effective distance, in meters + | + | Outputs: [None] + | + | Returns: Curve value - in dB + | + *===========================================================================*/ +double Curve(double c1, double c2, double x1, double x2, double x3, double d_e__meter) +{ + return (c1 + c2 / (1.0 + pow((d_e__meter - x2) / x3, 2))) * (pow(d_e__meter / x1, 2)) / (1.0 + (pow(d_e__meter / x1, 2))); +} + +/*============================================================================= + | + | Description: Compute the variability loss + | + | Input: time - Time percentage, 0 < time < 1 + | location - Location percentage, 0 < location < 1 + | situation - Situation percentage, 0 < situation < 1 + | h_e__meter[2] - Effective antenna heights, in meters + | delta_h__meter - Terrain irregularity parameter + | f__mhz - Frequency, in MHz + | d__meter - Path distance, in meters + | A_ref__db - Reference attenuation, in dB + | climate - Radio climate enum + | + 1 : CLIMATE__EQUATORIAL + | + 2 : CLIMATE__CONTINENTAL_SUBTROPICAL + | + 3 : CLIMATE__MARITIME_SUBTROPICAL + | + 4 : CLIMATE__DESERT + | + 5 : CLIMATE__CONTINENTAL_TEMPERATE + | + 6 : CLIMATE__MARITIME_TEMPERATE_OVER_LAND + | + 7 : CLIMATE__MARITIME_TEMPERATE_OVER_SEA + | mdvar - Mode of variability + | + | Outputs: warnings - Warning flags + | + | Returns: F() - in dB + | + *===========================================================================*/ +double Variability(double time, double location, double situation, double h_e__meter[2], double delta_h__meter, + double f__mhz, double d__meter, double A_ref__db, int climate, int mdvar, long *warnings) +{ + // Asymptotic values from TN101, Fig 10.13 + // -> approximate to TN101v2 Eqn III.69 & III.70 + // -> to describe the curves for each climate + double all_year[5][7] = + { + { -9.67, -0.62, 1.26, -9.21, -0.62, -0.39, 3.15 }, + { 12.7, 9.19, 15.5, 9.05, 9.19, 2.86, 857.9 }, + { 144.9e3, 228.9e3, 262.6e3, 84.1e3, 228.9e3, 141.7e3, 2222.e3 }, + { 190.3e3, 205.2e3, 185.2e3, 101.1e3, 205.2e3, 315.9e3, 164.8e3 }, + { 133.8e3, 143.6e3, 99.8e3, 98.6e3, 143.6e3, 167.4e3, 116.3e3 } + }; + + double bsm1[] = { 2.13, 2.66, 6.11, 1.98, 2.68, 6.86, 8.51 }; + double bsm2[] = { 159.5, 7.67, 6.65, 13.11, 7.16, 10.38, 169.8 }; + double xsm1[] = { 762.2e3, 100.4e3, 138.2e3, 139.1e3, 93.7e3, 187.8e3, 609.8e3 }; + double xsm2[] = { 123.6e3, 172.5e3, 242.2e3, 132.7e3, 186.8e3, 169.6e3, 119.9e3 }; + double xsm3[] = { 94.5e3, 136.4e3, 178.6e3, 193.5e3, 133.5e3, 108.9e3, 106.6e3 }; + + double bsp1[] = { 2.11, 6.87, 10.08, 3.68, 4.75, 8.58, 8.43 }; + double bsp2[] = { 102.3, 15.53, 9.60, 159.3, 8.12, 13.97, 8.19 }; + double xsp1[] = { 636.9e3, 138.7e3, 165.3e3, 464.4e3, 93.2e3, 216.0e3, 136.2e3 }; + double xsp2[] = { 134.8e3, 143.7e3, 225.7e3, 93.1e3, 135.9e3, 152.0e3, 188.5e3 }; + double xsp3[] = { 95.6e3, 98.6e3, 129.7e3, 94.2e3, 113.4e3, 122.7e3, 122.9e3 }; + + double C_D[] = { 1.224, 0.801, 1.380, 1.000, 1.224, 1.518, 1.518 }; // [Algorithm, Table 5.1], C_d + double z_D[] = { 1.282, 2.161, 1.282, 20.0, 1.282, 1.282, 1.282 }; // [Algorithm, Table 5.1], z_d + + double bfm1[] = { 1.0, 1.0, 1.0, 1.0, 0.92, 1.0, 1.0 }; + double bfm2[] = { 0.0, 0.0, 0.0, 0.0, 0.25, 0.0, 0.0 }; + double bfm3[] = { 0.0, 0.0, 0.0, 0.0, 1.77, 0.0, 0.0 }; + + double bfp1[] = { 1.0, 0.93, 1.0, 0.93, 0.93, 1.0, 1.0 }; + double bfp2[] = { 0.0, 0.31, 0.0, 0.19, 0.31, 0.0, 0.0 }; + double bfp3[] = { 0.0, 2.00, 0.0, 1.79, 2.00, 0.0, 0.0 }; + + double z_T = InverseComplementaryCumulativeDistributionFunction(time); + double z_L = InverseComplementaryCumulativeDistributionFunction(location); + double z_S = InverseComplementaryCumulativeDistributionFunction(situation); + + climate--; // 0-based indexes + + double wn = f__mhz / 47.7; + + // compute the effective distance + double d_ex__meter = sqrt(2 * a_9000__meter * h_e__meter[0]) + sqrt(2 * a_9000__meter * h_e__meter[1]) + pow((575.7e12 / wn), THIRD); // [Algorithm, Eqn 5.3] + + double d_e__meter; + if (d__meter < d_ex__meter) + d_e__meter = 130e3 * d__meter / d_ex__meter; + else + d_e__meter = 130e3 + d__meter - d_ex__meter; + + ////////////////////////////////// + // situation variability calcs + + // if mdvar >= 20, then "Direct situation variability is to be eliminated as it should when + // considering interference problems. Note that there may still be a + // small residual situation variability" [Hufford, 1982] + bool plus20 = mdvar >= 20; + if (plus20) + mdvar -= 20; + + double sigma_S; + if (plus20) + sigma_S = 0.0; + else + { + double D__meter = 100e3; // Scale distance, D = 100 km + sigma_S = 5.0 + 3.0 * exp(-d_e__meter / D__meter); // [Algorithm, Eqn 5.10] + } + + // + ////////////////////////////////// + + + bool plus10 = mdvar >= 10; + if (plus10) + mdvar -= 10; + + double V_med__db = Curve(all_year[0][climate], all_year[1][climate], all_year[2][climate], all_year[3][climate], all_year[4][climate], d_e__meter); + + if (mdvar == SINGLE_MESSAGE_MODE) + { + z_T = z_S; + z_L = z_S; + } + else if (mdvar == ACCIDENTAL_MODE) + z_L = z_S; + else if (mdvar == MOBILE_MODE) + z_L = z_T; + // else using Broadcast Mode (no additional operations) + + if (fabs(z_T) > 3.10 || fabs(z_L) > 3.10 || fabs(z_S) > 3.10) + *warnings |= WARN__EXTREME_VARIABILITIES; + + ////////////////////////////////// + // location variability calcs + + double sigma_L; + if (plus10) + sigma_L = 0.0; + else + { + double delta_h_d__meter = TerrainRoughness(d__meter, delta_h__meter); + + sigma_L = 10.0 * wn * delta_h_d__meter / (wn * delta_h_d__meter + 13.0); // Context of [Algorithm, Eqn 5.9] + } + double Y_L = sigma_L * z_L; + + // + ////////////////////////////////// + + ////////////////////////////////// + // time variability calcs + + double q = log(0.133 * wn); + double g_minus = bfm1[climate] + bfm2[climate] / (pow(bfm3[climate] * q, 2) + 1.0); + double g_plus = bfp1[climate] + bfp2[climate] / (pow(bfp3[climate] * q, 2) + 1.0); + + double sigma_T_minus = Curve(bsm1[climate], bsm2[climate], xsm1[climate], xsm2[climate], xsm3[climate], d_e__meter) * g_minus; + double sigma_T_plus = Curve(bsp1[climate], bsp2[climate], xsp1[climate], xsp2[climate], xsp3[climate], d_e__meter) * g_plus; + + double sigma_TD = C_D[climate] * sigma_T_plus; + double tgtd = (sigma_T_plus - sigma_TD) * z_D[climate]; + + double sigma_T; + if (z_T < 0.0) + sigma_T = sigma_T_minus; + else if (z_T <= z_D[climate]) + sigma_T = sigma_T_plus; + else + sigma_T = sigma_TD + tgtd / z_T; + double Y_T = sigma_T * z_T; + + // + ///////////////////////////////// + + double Y_S_temp = pow(sigma_S, 2) + pow(Y_T, 2) / (7.8 + pow(z_S, 2)) + pow(Y_L, 2) / (24.0 + pow(z_S, 2)); // Part of [Algorithm, Eqn 5.11] + + double Y_R, Y_S; + if (mdvar == SINGLE_MESSAGE_MODE) + { + Y_R = 0.0; + Y_S = sqrt(pow(sigma_T, 2) + pow(sigma_L, 2) + Y_S_temp) * z_S; + } + else if (mdvar == ACCIDENTAL_MODE) + { + Y_R = Y_T; + Y_S = sqrt(pow(sigma_L, 2) + Y_S_temp) * z_S; + } + else if (mdvar == MOBILE_MODE) + { + Y_R = sqrt(pow(sigma_T, 2) + pow(sigma_L, 2)) * z_T; + Y_S = sqrt(Y_S_temp) * z_S; + } + else // BROADCAST_MODE + { + Y_R = Y_T + Y_L; + Y_S = sqrt(Y_S_temp) * z_S; + } + + double result = A_ref__db - V_med__db - Y_R - Y_S; + + // [Algorithm, Eqn 52] + if (result < 0.0) + result = result * (29.0 - result) / (29.0 - 10.0 * result); + + return result; +} \ No newline at end of file diff --git a/src/itm_area.cpp b/src/itm_area.cpp new file mode 100644 index 0000000..756ece7 --- /dev/null +++ b/src/itm_area.cpp @@ -0,0 +1,301 @@ +#include "..\include\itm.h" +#include "..\include\Enums.h" +#include "..\include\Errors.h" + +/*============================================================================= + | + | Description: The ITS Irregular Terrain Model (ITM). This function + | exposes area mode functionality, with variability + | specified with time/location/situation (TLS). + | + | Input: h_tx__meter - Structural height of the TX, in meters + | h_rx__meter - Structural height of the RX, in meters + | tx_site_criteria - Siting criteria of the TX + | + 0 : SITING_CRITERIA__RANDOM + | + 1 : SITING_CRITERIA__CAREFUL + | + 2 : SITING_CRITERIA__VERY_CAREFUL + | rx_site_criteria - Siting criteria of the RX + | + 0 : SITING_CRITERIA__RANDOM + | + 1 : SITING_CRITERIA__CAREFUL + | + 2 : SITING_CRITERIA__VERY_CAREFUL + | d__km - Path distance, in km + | delta_h__meter - Terrain irregularity parameter + | climate - Radio climate + | + 1 : CLIMATE__EQUATORIAL + | + 2 : CLIMATE__CONTINENTAL_SUBTROPICAL + | + 3 : CLIMATE__MARITIME_SUBTROPICAL + | + 4 : CLIMATE__DESERT + | + 5 : CLIMATE__CONTINENTAL_TEMPERATE + | + 6 : CLIMATE__MARITIME_TEMPERATE_OVER_LAND + | + 7 : CLIMATE__MARITIME_TEMPERATE_OVER_SEA + | N_0 - Refractivity, in N-Units + | f__mhz - Frequency, in MHz + | pol - Polarization + | + 0 : POLARIZATION__HORIZONTAL + | + 1 : POLARIZATION__VERTICAL + | epsilon - Relative permittivity + | sigma - Conductivity + | mdvar - Mode of variability + | time - Time percentage, 0 < time < 100 + | location - Location percentage, 0 < location < 100 + | situation - Situation percentage, 0 < situation < 100 + | + | Outputs: A__db - Basic transmission loss, in dB + | warnings - Warning flags + | + | Returns: error - Error code + | + *===========================================================================*/ +int ITM_AREA_TLS(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, double d__km, + double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double time, double location, double situation, double *A__db, long *warnings) +{ + IntermediateValues interValues; + + return ITM_AREA_TLS_Ex(h_tx__meter, h_rx__meter, tx_site_criteria, rx_site_criteria, d__km, delta_h__meter, climate, + N_0, f__mhz, pol, epsilon, sigma, mdvar, time, location, situation, A__db, warnings, &interValues); +} + +/*============================================================================= + | + | Description: The ITS Irregular Terrain Model (ITM). This function + | exposes area mode functionality, with variability + | specified with time/location/situation (TLS) + | + | Input: h_tx__meter - Structural height of the TX, in meters + | h_rx__meter - Structural height of the RX, in meters + | tx_site_criteria - Siting criteria of the TX + | + 0 : SITING_CRITERIA__RANDOM + | + 1 : SITING_CRITERIA__CAREFUL + | + 2 : SITING_CRITERIA__VERY_CAREFUL + | rx_site_criteria - Siting criteria of the RX + | + 0 : SITING_CRITERIA__RANDOM + | + 1 : SITING_CRITERIA__CAREFUL + | + 2 : SITING_CRITERIA__VERY_CAREFUL + | d__km - Path distance, in km + | delta_h__meter - Terrain irregularity parameter + | climate - Radio climate + | + 1 : CLIMATE__EQUATORIAL + | + 2 : CLIMATE__CONTINENTAL_SUBTROPICAL + | + 3 : CLIMATE__MARITIME_SUBTROPICAL + | + 4 : CLIMATE__DESERT + | + 5 : CLIMATE__CONTINENTAL_TEMPERATE + | + 6 : CLIMATE__MARITIME_TEMPERATE_OVER_LAND + | + 7 : CLIMATE__MARITIME_TEMPERATE_OVER_SEA + | N_0 - Refractivity, in N-Units + | f__mhz - Frequency, in MHz + | pol - Polarization + | + 0 : POLARIZATION__HORIZONTAL + | + 1 : POLARIZATION__VERTICAL + | epsilon - Relative permittivity + | sigma - Conductivity + | mdvar - Mode of variability + | time - Time percentage, 0 < time < 100 + | location - Location percentage, 0 < location < 100 + | situation - Situation percentage, 0 < situation < 100 + | + | Outputs: A__db - Basic transmission loss, in dB + | warnings - Warning flags + | interValues - Struct of intermediate values + | + | Returns: error - Error code + | + *===========================================================================*/ +int ITM_AREA_TLS_Ex(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, double d__km, + double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double time, double location, double situation, double *A__db, long *warnings, IntermediateValues *interValues) +{ + *warnings = NO_WARNINGS; + + // inital input validation check - some validation occurs later in calculations + int rtn = ValidateInputs(h_tx__meter, h_rx__meter, climate, time, location, situation, N_0, f__mhz, pol, epsilon, sigma, mdvar, warnings); + if (rtn != SUCCESS) + return rtn; + + // switch from percentages to ratios + time /= 100; + location /= 100; + situation /= 100; + + // additional area mode parameter validation checks + if (d__km <= 0) + return ERROR__PATH_DISTANCE; + if (delta_h__meter < 0) + return ERROR__DELTA_H; + if (tx_site_criteria != SITING_CRITERIA__RANDOM && + tx_site_criteria != SITING_CRITERIA__CAREFUL && + tx_site_criteria != SITING_CRITERIA__VERY_CAREFUL) + return ERROR__TX_SITING_CRITERIA; + if (rx_site_criteria != SITING_CRITERIA__RANDOM && + rx_site_criteria != SITING_CRITERIA__CAREFUL && + rx_site_criteria != SITING_CRITERIA__VERY_CAREFUL) + return ERROR__RX_SITING_CRITERIA; + + int site_criteria[2] = { tx_site_criteria, rx_site_criteria }; + double h__meter[2] = { h_tx__meter, h_rx__meter }; + interValues->d__km = d__km; + + double theta_hzn[2]; + double d_hzn__meter[2]; + double h_e__meter[2]; + complex Z_g; + double N_s; + double gamma_e; + double A_ref__db = 0; + + InitializePointToPoint(f__mhz, 0.0, N_0, pol, epsilon, sigma, &Z_g, &gamma_e, &N_s); + + InitializeArea(site_criteria, gamma_e, delta_h__meter, h__meter, h_e__meter, d_hzn__meter, theta_hzn); + + double d__meter = d__km * 1000; + int propmode = MODE__NOT_SET; + rtn = LongleyRice(theta_hzn, f__mhz, Z_g, d_hzn__meter, h_e__meter, gamma_e, N_s, delta_h__meter, h__meter, d__meter, MODE__AREA, + &A_ref__db, warnings, &propmode); + if (rtn != SUCCESS) + return rtn; + + double A_fs__db = FreeSpaceLoss(d__meter, f__mhz); + + *A__db = A_fs__db + Variability(time, location, situation, h_e__meter, delta_h__meter, f__mhz, d__meter, A_ref__db, climate, mdvar, warnings); + + // Save off intermediate values + interValues->A_ref__db = A_ref__db; + interValues->A_fs__db = A_fs__db; + interValues->delta_h__meter = delta_h__meter; + interValues->d_hzn__meter[0] = d_hzn__meter[0]; + interValues->d_hzn__meter[1] = d_hzn__meter[1]; + interValues->h_e__meter[0] = h_e__meter[0]; + interValues->h_e__meter[1] = h_e__meter[1]; + interValues->N_s = N_s; + interValues->theta_hzn[0] = theta_hzn[0]; + interValues->theta_hzn[1] = theta_hzn[1]; + interValues->mode = propmode; + + if (*warnings != NO_WARNINGS) + return SUCCESS_WITH_WARNINGS; + + return SUCCESS; +} + +/*============================================================================= + | + | Description: The ITS Irregular Terrain Model (ITM). This function + | exposes area mode functionality, with variability + | specified with confidence/reliability (CR). + | + | Input: h_tx__meter - Structural height of the TX, in meters + | h_rx__meter - Structural height of the RX, in meters + | tx_site_criteria - Siting criteria of the TX + | + 0 : SITING_CRITERIA__RANDOM + | + 1 : SITING_CRITERIA__CAREFUL + | + 2 : SITING_CRITERIA__VERY_CAREFUL + | rx_site_criteria - Siting criteria of the RX + | + 0 : SITING_CRITERIA__RANDOM + | + 1 : SITING_CRITERIA__CAREFUL + | + 2 : SITING_CRITERIA__VERY_CAREFUL + | d__km - Path distance, in km + | delta_h__meter - Terrain irregularity parameter + | climate - Radio climate + | + 1 : CLIMATE__EQUATORIAL + | + 2 : CLIMATE__CONTINENTAL_SUBTROPICAL + | + 3 : CLIMATE__MARITIME_SUBTROPICAL + | + 4 : CLIMATE__DESERT + | + 5 : CLIMATE__CONTINENTAL_TEMPERATE + | + 6 : CLIMATE__MARITIME_TEMPERATE_OVER_LAND + | + 7 : CLIMATE__MARITIME_TEMPERATE_OVER_SEA + | N_0 - Refractivity, in N-Units + | f__mhz - Frequency, in MHz + | pol - Polarization + | + 0 : POLARIZATION__HORIZONTAL + | + 1 : POLARIZATION__VERTICAL + | epsilon - Relative permittivity + | sigma - Conductivity + | mdvar - Mode of variability + | confidence - Confidence percentage, 0 < confidence < 100 + | reliability - Reliability percentage, 0 < reliability < 100 + | + | Outputs: A__db - Basic transmission loss, in dB + | warnings - Warning flags + | + | Returns: error - Error code + | + *===========================================================================*/ +int ITM_AREA_CR(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, double d__km, + double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double confidence, double reliability, double *A__db, long *warnings) +{ + IntermediateValues interValues; + + int rtn = ITM_AREA_TLS_Ex(h_tx__meter, h_rx__meter, tx_site_criteria, rx_site_criteria, d__km, + delta_h__meter, climate, N_0, f__mhz, pol, epsilon, sigma, + mdvar, reliability, 50, confidence, A__db, warnings, &interValues); + + // convert TLS error codes for time and situation into CR error codes for confidence and reliability, if needed + if (rtn == ERROR__INVALID_TIME) + return ERROR__INVALID_RELIABILITY; + if (rtn == ERROR__INVALID_SITUATION) + return ERROR__INVALID_CONFIDENCE; + else + return rtn; +} + +/*============================================================================= + | + | Description: The ITS Irregular Terrain Model (ITM). This function + | exposes area mode functionality, with variability + | specified with confidence/reliability (CR). + | + | Input: h_tx__meter - Structural height of the TX, in meters + | h_rx__meter - Structural height of the RX, in meters + | tx_site_criteria - Siting criteria of the TX + | + 0 : SITING_CRITERIA__RANDOM + | + 1 : SITING_CRITERIA__CAREFUL + | + 2 : SITING_CRITERIA__VERY_CAREFUL + | rx_site_criteria - Siting criteria of the RX + | + 0 : SITING_CRITERIA__RANDOM + | + 1 : SITING_CRITERIA__CAREFUL + | + 2 : SITING_CRITERIA__VERY_CAREFUL + | d__km - Path distance, in km + | delta_h__meter - Terrain irregularity parameter + | climate - Radio climate + | + 1 : CLIMATE__EQUATORIAL + | + 2 : CLIMATE__CONTINENTAL_SUBTROPICAL + | + 3 : CLIMATE__MARITIME_SUBTROPICAL + | + 4 : CLIMATE__DESERT + | + 5 : CLIMATE__CONTINENTAL_TEMPERATE + | + 6 : CLIMATE__MARITIME_TEMPERATE_OVER_LAND + | + 7 : CLIMATE__MARITIME_TEMPERATE_OVER_SEA + | N_0 - Refractivity, in N-Units + | f__mhz - Frequency, in MHz + | pol - Polarization + | + 0 : POLARIZATION__HORIZONTAL + | + 1 : POLARIZATION__VERTICAL + | epsilon - Relative permittivity + | sigma - Conductivity + | mdvar - Mode of variability + | confidence - Confidence percentage, 0 < confidence < 100 + | reliability - Reliability percentage, 0 < reliability < 100 + | + | Outputs: A__db - Basic transmission loss, in dB + | warnings - Warning flags + | interValues - Struct of intermediate values + | + | Returns: error - Error code + | + *===========================================================================*/ +int ITM_AREA_CR_Ex(double h_tx__meter, double h_rx__meter, int tx_site_criteria, int rx_site_criteria, double d__km, + double delta_h__meter, int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double confidence, double reliability, double *A__db, long *warnings, IntermediateValues *interValues) +{ + int rtn = ITM_AREA_TLS_Ex(h_tx__meter, h_rx__meter, tx_site_criteria, rx_site_criteria, d__km, + delta_h__meter, climate, N_0, f__mhz, pol, epsilon, sigma, + mdvar, reliability, 50, confidence, A__db, warnings, interValues); + + // convert TLS error codes for time and situation into CR error codes for confidence and reliability, if needed + if (rtn == ERROR__INVALID_TIME) + return ERROR__INVALID_RELIABILITY; + if (rtn == ERROR__INVALID_SITUATION) + return ERROR__INVALID_CONFIDENCE; + else + return rtn; +} \ No newline at end of file diff --git a/src/itm_p2p.cpp b/src/itm_p2p.cpp new file mode 100644 index 0000000..41becdc --- /dev/null +++ b/src/itm_p2p.cpp @@ -0,0 +1,252 @@ +#include "..\include\itm.h" +#include "..\include\Enums.h" +#include "..\include\Errors.h" + +/*============================================================================= + | + | Description: The ITS Irregular Terrain Model (ITM). This function + | exposes point-to-point mode functionality, with variability + | specified with time/location/situation (TLS). + | + | Input: h_tx__meter - Structural height of the TX, in meters + | h_rx__meter - Structural height of the RX, in meters + | pfl[2] - Terrain data, in PFL format + | climate - Radio climate + | + 1 : CLIMATE__EQUATORIAL + | + 2 : CLIMATE__CONTINENTAL_SUBTROPICAL + | + 3 : CLIMATE__MARITIME_SUBTROPICAL + | + 4 : CLIMATE__DESERT + | + 5 : CLIMATE__CONTINENTAL_TEMPERATE + | + 6 : CLIMATE__MARITIME_TEMPERATE_OVER_LAND + | + 7 : CLIMATE__MARITIME_TEMPERATE_OVER_SEA + | N_0 - Refractivity, in N-Units + | f__mhz - Frequency, in MHz + | pol - Polarization + | + 0 : POLARIZATION__HORIZONTAL + | + 1 : POLARIZATION__VERTICAL + | epsilon - Relative permittivity + | sigma - Conductivity + | mdvar - Mode of variability + | time - Time percentage, 0 < time < 100 + | location - Location percentage, 0 < location < 100 + | situation - Situation percentage, 0 < situation < 100 + | + | Outputs: A__db - Basic transmission loss, in dB + | warnings - Warning flags + | + | Returns: error - Error code + | + *===========================================================================*/ +int ITM_P2P_TLS(double h_tx__meter, double h_rx__meter, double pfl[], int climate, double N_0, double f__mhz, + int pol, double epsilon, double sigma, int mdvar, double time, double location, double situation, + double *A__db, long *warnings) +{ + IntermediateValues interValues; + + return ITM_P2P_TLS_Ex(h_tx__meter, h_rx__meter, pfl, climate, N_0, f__mhz, pol, epsilon, sigma, mdvar, + time, location, situation, A__db, warnings, &interValues); +} + +/*============================================================================= + | + | Description: The ITS Irregular Terrain Model (ITM). This function + | exposes point-to-point mode functionality, with variability + | specified with confidence/reliability (CR). + | + | Input: h_tx__meter - Structural height of the TX, in meters + | h_rx__meter - Structural height of the RX, in meters + | pfl[2] - Terrain data, in PFL format + | climate - Radio climate + | + 1 : CLIMATE__EQUATORIAL + | + 2 : CLIMATE__CONTINENTAL_SUBTROPICAL + | + 3 : CLIMATE__MARITIME_SUBTROPICAL + | + 4 : CLIMATE__DESERT + | + 5 : CLIMATE__CONTINENTAL_TEMPERATE + | + 6 : CLIMATE__MARITIME_TEMPERATE_OVER_LAND + | + 7 : CLIMATE__MARITIME_TEMPERATE_OVER_SEA + | N_0 - Refractivity, in N-Units + | f__mhz - Frequency, in MHz + | pol - Polarization + | + 0 : POLARIZATION__HORIZONTAL + | + 1 : POLARIZATION__VERTICAL + | epsilon - Relative permittivity + | sigma - Conductivity + | mdvar - Mode of variability + | confidence - Confidence percentage, 0 < confidence < 100 + | reliability - Reliability percentage, 0 < reliability < 100 + | + | Outputs: A__db - Basic transmission loss, in dB + | warnings - Warning flags + | + | Returns: error - Error code + | + *===========================================================================*/ +int ITM_P2P_CR(double h_tx__meter, double h_rx__meter, double pfl[], int climate, double N_0, double f__mhz, + int pol, double epsilon, double sigma, int mdvar, double confidence, double reliability, + double *A__db, long *warnings) +{ + IntermediateValues interValues; + + int rtn = ITM_P2P_TLS_Ex(h_tx__meter, h_rx__meter, pfl, climate, N_0, f__mhz, pol, epsilon, sigma, mdvar, + reliability, 50, confidence, A__db, warnings, &interValues); + + // convert TLS error codes for time and situation into CR error codes for confidence and reliability, if needed + if (rtn == ERROR__INVALID_TIME) + return ERROR__INVALID_RELIABILITY; + if (rtn == ERROR__INVALID_SITUATION) + return ERROR__INVALID_CONFIDENCE; + else + return rtn; +} + +/*============================================================================= + | + | Description: The ITS Irregular Terrain Model (ITM). This function + | exposes point-to-point mode functionality, with variability + | specified with confidence/reliability (CR). + | + | Input: h_tx__meter - Structural height of the TX, in meters + | h_rx__meter - Structural height of the RX, in meters + | pfl[2] - Terrain data, in PFL format + | climate - Radio climate + | + 1 : CLIMATE__EQUATORIAL + | + 2 : CLIMATE__CONTINENTAL_SUBTROPICAL + | + 3 : CLIMATE__MARITIME_SUBTROPICAL + | + 4 : CLIMATE__DESERT + | + 5 : CLIMATE__CONTINENTAL_TEMPERATE + | + 6 : CLIMATE__MARITIME_TEMPERATE_OVER_LAND + | + 7 : CLIMATE__MARITIME_TEMPERATE_OVER_SEA + | N_0 - Refractivity, in N-Units + | f__mhz - Frequency, in MHz + | pol - Polarization + | + 0 : POLARIZATION__HORIZONTAL + | + 1 : POLARIZATION__VERTICAL + | epsilon - Relative permittivity + | sigma - Conductivity + | mdvar - Mode of variability + | confidence - Confidence percentage, 0 < confidence < 100 + | reliability - Reliability percentage, 0 < reliability < 100 + | + | Outputs: A__db - Basic transmission loss, in dB + | warnings - Warning flags + | interValues - Struct of intermediate values + | + | Returns: error - Error code + | + *===========================================================================*/ +int ITM_P2P_CR_Ex(double h_tx__meter, double h_rx__meter, double pfl[], int climate, double N_0, double f__mhz, + int pol, double epsilon, double sigma, int mdvar, double confidence, double reliability, + double *A__db, long *warnings, IntermediateValues *interValues) +{ + int rtn = ITM_P2P_TLS_Ex(h_tx__meter, h_rx__meter, pfl, climate, N_0, f__mhz, pol, epsilon, sigma, mdvar, + reliability, 50, confidence, A__db, warnings, interValues); + + // convert TLS error codes for time and situation into CR error codes for confidence and reliability, if needed + if (rtn == ERROR__INVALID_TIME) + return ERROR__INVALID_RELIABILITY; + if (rtn == ERROR__INVALID_SITUATION) + return ERROR__INVALID_CONFIDENCE; + else + return rtn; +} + +/*============================================================================= + | + | Description: The ITS Irregular Terrain Model (ITM). This function + | exposes point-to-point mode functionality, with variability + | specified with time/location/situation (TLS). + | + | Input: h_tx__meter - Structural height of the TX, in meters + | h_rx__meter - Structural height of the RX, in meters + | pfl[2] - Terrain data, in PFL format + | climate - Radio climate enum + | N_0 - Refractivity, in N-Units + | f__mhz - Frequency, in MHz + | pol - Polarization enum + | epsilon - Relative permittivity + | sigma - Conductivity + | mdvar - Mode of variability + | time - Time percentage, 0 < time < 100 + | location - Location percentage, 0 < location < 100 + | situation - Situation percentage, 0 < situation < 100 + | + | Outputs: A__db - Basic transmission loss, in dB + | warnings - Warning flags + | interValues - Struct of intermediate values + | + | Returns: error - Error code + | + *===========================================================================*/ +int ITM_P2P_TLS_Ex(double h_tx__meter, double h_rx__meter, double pfl[], int climate, double N_0, double f__mhz, + int pol, double epsilon, double sigma, int mdvar, double time, double location, double situation, + double *A__db, long *warnings, IntermediateValues *interValues) +{ + double N_s; // Surface refractivity, in N-Units + double gamma_e; // Curvature of the effective earth + double delta_h__meter; // Terrain irregularity parameter + double d__meter; // Path distance, in meters + complex Z_g; // Ground impedance + double theta_hzn[2]; // Terminal horizon angles + double d_hzn__meter[2]; // Terminal horizon distances + double h_e__meter[2]; // Terminal effective heights + + *warnings = NO_WARNINGS; // Initialize to no warnings + + // initial input validation check - some validation occurs later in calculations + int rtn = ValidateInputs(h_tx__meter, h_rx__meter, climate, time, location, situation, N_0, f__mhz, pol, epsilon, sigma, mdvar, warnings); + if (rtn != SUCCESS) + return rtn; + + interValues->d__km = (pfl[0] * pfl[1]) / 1000; + + int np = int(pfl[0]); // number of points in the pfl + + // switch from percentages to ratios + time /= 100; + location /= 100; + situation /= 100; + + // compute the average path height, ignoring first and last 10% + int p10 = int(0.1 * np); // 10% of np + double h_sys__meter = 0; // Height of the system above mean sea level + + for (int i = p10; i <= np - p10; i++) + h_sys__meter += pfl[i + 2]; + + h_sys__meter = h_sys__meter / (np - 2 * p10 + 1); + + InitializePointToPoint(f__mhz, h_sys__meter, N_0, pol, epsilon, sigma, &Z_g, &gamma_e, &N_s); + + double h__meter[2] = { h_tx__meter, h_rx__meter }; + QuickPfl(pfl, gamma_e, h__meter, theta_hzn, d_hzn__meter, h_e__meter, &delta_h__meter, &d__meter); + + // Reference attenuation, in dB + double A_ref__db = 0; + int propmode = MODE__NOT_SET; + rtn = LongleyRice(theta_hzn, f__mhz, Z_g, d_hzn__meter, h_e__meter, gamma_e, N_s, delta_h__meter, h__meter, d__meter, MODE__P2P, + &A_ref__db, warnings, &propmode); + if (rtn != SUCCESS) + return rtn; + + double A_fs__db = FreeSpaceLoss(d__meter, f__mhz); + + *A__db = Variability(time, location, situation, h_e__meter, delta_h__meter, f__mhz, d__meter, A_ref__db, climate, mdvar, warnings) + A_fs__db; + + // Save off intermediate values + interValues->A_ref__db = A_ref__db; + interValues->A_fs__db = A_fs__db; + interValues->delta_h__meter = delta_h__meter; + interValues->d_hzn__meter[0] = d_hzn__meter[0]; + interValues->d_hzn__meter[1] = d_hzn__meter[1]; + interValues->h_e__meter[0] = h_e__meter[0]; + interValues->h_e__meter[1] = h_e__meter[1]; + interValues->N_s = N_s; + interValues->theta_hzn[0] = theta_hzn[0]; + interValues->theta_hzn[1] = theta_hzn[1]; + interValues->mode = propmode; + + if (*warnings != NO_WARNINGS) + return SUCCESS_WITH_WARNINGS; + + return SUCCESS; +}; diff --git a/win32/ITMDrvr/AreaMode.cpp b/win32/ITMDrvr/AreaMode.cpp new file mode 100644 index 0000000..c5d6400 --- /dev/null +++ b/win32/ITMDrvr/AreaMode.cpp @@ -0,0 +1,465 @@ +#include "ITMDrvr.h" +#include "AreaMode.h" +#include "Tags.h" +#include "Reporting.h" +#include "Common.h" + +// ITM DLL Functions +typedef int(__stdcall *itm_area_tls_ex_func)(double h_tx__meter, double h_rx__meter, + int tx_site_criteria, int rx_site_criteria, double d__km, double delta_h__meter, + int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double time, double location, double situation, double *A__db, + long *warnings, struct IntermediateValues *interValues); + +typedef int(__stdcall *itm_area_cr_ex_func)(double h_tx__meter, double h_rx__meter, + int tx_site_criteria, int rx_site_criteria, double d__km, double delta_h__meter, + int climate, double N_0, double f__mhz, int pol, double epsilon, double sigma, + int mdvar, double confidence, double reliability, double *A__db, + long *warnings, struct IntermediateValues *interValues); + +// Local Globals +itm_area_tls_ex_func itm_area_tls_ex; +itm_area_cr_ex_func itm_area_cr_ex; + +/*============================================================================= + | + | Description: Top-level control function for Area mode operation + | + | Input: params - Driver input parameter struct + | area_params - Area input parameter struct + | + | Output: inter_vals - ITM intermediate values struct + | A__db - Basic transmission loss, in dB + | warnings - ITM return warning flags + | + | Returns: rtn - Return error code + | + *===========================================================================*/ +int CallAreaMode(DrvrParams* params, AreaParams* area_params, IntermediateValues* inter_vals, + vector* A__db, vector* A_fs__db, long* warnings) { + int rtn = ParseAreaInputFile(params->in_file, area_params); + if (rtn != SUCCESS) + return rtn; + + rtn = ValidateAreaInputs(area_params); + if (rtn != SUCCESS) + return rtn; + + *warnings = 0; + + double ADB; + long WARN; + if (area_params->mode == VARY_TLS) { + for (int i = 0; i < area_params->d__km.size(); i++) { + for (int j = 0; j < area_params->situation.size(); j++) { + rtn = itm_area_tls_ex( + area_params->h_tx__meter, + area_params->h_rx__meter, + area_params->tx_site_criteria, + area_params->rx_site_criteria, + area_params->d__km[i], + area_params->delta_h__meter, + area_params->climate, + area_params->N_0, + area_params->f__mhz, + area_params->pol, + area_params->epsilon, + area_params->sigma, + area_params->mdvar, + area_params->time, + area_params->location, + area_params->situation[j], + &ADB, + &WARN, + inter_vals); + + A__db->push_back(ADB); + *warnings = *warnings | WARN; + } + + A_fs__db->push_back(inter_vals->A_fs__db); + } + + // confidence is situation variability + area_params->confidence = area_params->situation; + } + else { + for (int i = 0; i < area_params->d__km.size(); i++) { + for (int j = 0; j < area_params->confidence.size(); j++) { + rtn = itm_area_cr_ex( + area_params->h_tx__meter, + area_params->h_rx__meter, + area_params->tx_site_criteria, + area_params->rx_site_criteria, + area_params->d__km[i], + area_params->delta_h__meter, + area_params->climate, + area_params->N_0, + area_params->f__mhz, + area_params->pol, + area_params->epsilon, + area_params->sigma, + area_params->mdvar, + area_params->confidence[j], + area_params->reliability, + &ADB, + &WARN, + inter_vals); + + A__db->push_back(ADB); + *warnings = *warnings | WARN; + } + + + A_fs__db->push_back(inter_vals->A_fs__db); + } + + } + + return rtn; +} + +/*============================================================================= + | + | Description: Load Area functions from the ITM DLL + | + | Input: hLib - DLL handle + | + | Output: [void] + | + | Returns: rtn - Return error code + | + *===========================================================================*/ +int LoadAreaFunctions(HINSTANCE hLib) { + itm_area_tls_ex = (itm_area_tls_ex_func)GetProcAddress((HMODULE)hLib, "ITM_AREA_TLS_Ex"); + if (itm_area_tls_ex == nullptr) + return DRVRERR__GET_AREA_TLS_FUNC_LOADING; + + itm_area_cr_ex = (itm_area_cr_ex_func)GetProcAddress((HMODULE)hLib, "ITM_AREA_CR_Ex"); + if (itm_area_tls_ex == nullptr) + return DRVRERR__GET_AREA_CR_FUNC_LOADING; + + return SUCCESS; +} + +/*============================================================================= + | + | Description: Parse Area input parameter file + | + | Input: in_file - Path to Area input parameter file + | + | Output: area_params - Area input parameter struct + | + | Returns: rtn - Return error code + | + *===========================================================================*/ +int ParseAreaInputFile(const char* in_file, AreaParams* area_params) { + ifstream file; + file.open(in_file); + string line; + + while (getline(file, line)) { + int i = line.find(","); + + string key = line.substr(0, i); + string value = line.substr(i + 1); + + transform(key.begin(), key.end(), key.begin(), ::tolower); + + if (key.compare(TAG__HTX) == 0) { + if (ParseDouble(value.c_str(), &area_params->h_tx__meter) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_HTX, TAG__HTX); + } + } + else if (key.compare(TAG__HRX) == 0) { + if (ParseDouble(value.c_str(), &area_params->h_rx__meter) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_HRX, TAG__HRX); + } + } + else if (key.compare(TAG__TX_SITE) == 0) { + if (ParseInteger(value.c_str(), &area_params->tx_site_criteria) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_TX_SITE, TAG__TX_SITE); + } + } + else if (key.compare(TAG__RX_SITE) == 0) { + if (ParseInteger(value.c_str(), &area_params->rx_site_criteria) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_RX_SITE, TAG__RX_SITE); + } + } + else if (key.compare(TAG__DKM) == 0) { + int s = 0, e = 0, i_p = 0; + do { + e = value.find(',', s); + string str = value.substr(s, e); + + double p; + if (ParseDouble(str.c_str(), &p) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_DKM, TAG__DKM); + } + + area_params->d_format[i_p] = p; + i_p++; + + s = e + 1; + } while (e != value.npos && i_p < 5); + + // check if all 5 distance params were provided + // -> or if the user just provided a single distance + if (i_p == 1) { + area_params->d__km.push_back(area_params->d_format[0]); + } + else if (i_p != 5) { + return ParsingErrorHelper(DRVRERR__PARSE_INCOMPLETE_DISTANCES, TAG__DKM); + } + else { + // generate the list of distances + // data is formatted as: + // D0, D1, DS1, D2, DS2, which can be described as distances D0 to D1 + // in increments of DS1, and then from D1 to D2 in increments of DS2 + + // first do loop + int i1 = 0; + double d__km; + do { + d__km = area_params->d_format[0] + i1 * area_params->d_format[2]; + area_params->d__km.push_back(d__km); + i1++; + } while (d__km < area_params->d_format[1]); + + // second do loop + int i2 = 0; + do { + d__km += area_params->d_format[4]; + area_params->d__km.push_back(d__km); + i2++; + } while (d__km < area_params->d_format[3]); + } + } + else if (key.compare(TAG__DELTAH) == 0) { + if (ParseDouble(value.c_str(), &area_params->delta_h__meter) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_DELTAH, TAG__DELTAH); + } + } + else if (key.compare(TAG__CLIMATE) == 0) { + if (ParseInteger(value.c_str(), &area_params->climate) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_CLIMATE, TAG__CLIMATE); + } + } + else if (key.compare("n_0") == 0) { + if (ParseDouble(value.c_str(), &area_params->N_0) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_N0, TAG__N0); + } + } + else if (key.compare(TAG__FREQ) == 0) { + if (ParseDouble(value.c_str(), &area_params->f__mhz) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_FREQ, TAG__FREQ); + } + } + else if (key.compare(TAG__POL) == 0) { + if (ParseInteger(value.c_str(), &area_params->pol) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_POL, TAG__POL); + } + } + else if (key.compare(TAG__EPSILON) == 0) { + if (ParseDouble(value.c_str(), &area_params->epsilon) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_EPSILON, TAG__EPSILON); + } + } + else if (key.compare(TAG__SIGMA) == 0) { + if (ParseDouble(value.c_str(), &area_params->sigma) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_SIGMA, TAG__SIGMA); + } + } + else if (key.compare(TAG__MDVAR) == 0) { + if (ParseInteger(value.c_str(), &area_params->mdvar) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_MDVAR, TAG__MDVAR); + } + } + else if (key.compare(TAG__TIME) == 0) { + if (ParseDouble(value.c_str(), &area_params->time) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_TIME, TAG__TIME); + } + } + else if (key.compare(TAG__LOCATION) == 0) { + if (ParseDouble(value.c_str(), &area_params->location) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_LOCATION, TAG__LOCATION); + } + } + else if (key.compare(TAG__SITUATION) == 0) { + int s = 0, e = 0; + do { + e = value.find(',', s); + string str = value.substr(s, e); + + double situation; + if (ParseDouble(str.c_str(), &situation) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_SITUATION, TAG__SITUATION); + } + + area_params->situation.push_back(situation); + s = e + 1; + } while (e != value.npos); + } + else if (key.compare(TAG__CONFIDENCE) == 0) { + int s = 0, e = 0; + do { + e = value.find(',', s); + string str = value.substr(s, e); + + double confidence; + if (ParseDouble(str.c_str(), &confidence) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_CONFIDENCE, TAG__CONFIDENCE); + } + + area_params->confidence.push_back(confidence); + s = e + 1; + } while (e != value.npos); + } + else if (key.compare(TAG__RELIABILITY) == 0) { + if (ParseDouble(value.c_str(), &area_params->reliability) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_RELIABILITY, TAG__RELIABILITY); + } + } + else { + printf("Unknown area mode input parameter '%s'. Skipping line...\n", key.c_str()); + } + } + + file.close(); + + return SUCCESS; +} + +/*============================================================================= + | + | Description: Validate Area input parameters. This function only validates + | that required parameters are present - not that they are + | valid values. The ITM DLL performs validation to ensure + | the parameters are within valid range. + | + | Input: area_params - Area input parameter struct + | + | Output: [void] + | + | Returns: rtn - Return error code + | + *===========================================================================*/ +int ValidateAreaInputs(AreaParams* area_params) { + if (area_params->h_tx__meter == NOT_SET) + return Validate_RequiredErrMsgHelper(TAG__HTX, DRVRERR__VALIDATION_HTX); + + if (area_params->h_rx__meter == NOT_SET) + return Validate_RequiredErrMsgHelper(TAG__HRX, DRVRERR__VALIDATION_HTX); + + if (area_params->tx_site_criteria == NOT_SET) + return Validate_RequiredErrMsgHelper(TAG__TX_SITE, DRVRERR__VALIDATION_HTX_SITE); + + if (area_params->rx_site_criteria == NOT_SET) + return Validate_RequiredErrMsgHelper(TAG__RX_SITE, DRVRERR__VALIDATION_RTX_SITE); + + if (area_params->d__km.size() == 0) + return Validate_RequiredErrMsgHelper(TAG__DKM, DRVRERR__VALIDATION_DKM); + + if (area_params->delta_h__meter == NOT_SET) + return Validate_RequiredErrMsgHelper(TAG__DELTAH, DRVRERR__VALIDATION_DELTAH); + + if (area_params->climate == NOT_SET) + return Validate_RequiredErrMsgHelper(TAG__CLIMATE, DRVRERR__VALIDATION_CLIMATE); + + if (area_params->N_0 == NOT_SET) + return Validate_RequiredErrMsgHelper(TAG__N0, DRVRERR__VALIDATION_N0); + + if (area_params->f__mhz == NOT_SET) + return Validate_RequiredErrMsgHelper(TAG__FREQ, DRVRERR__VALIDATION_FMHZ); + + if (area_params->pol == NOT_SET) + return Validate_RequiredErrMsgHelper(TAG__POL, DRVRERR__VALIDATION_POL); + + if (area_params->epsilon == NOT_SET) + return Validate_RequiredErrMsgHelper(TAG__EPSILON, DRVRERR__VALIDATION_EPSILON); + + if (area_params->sigma == NOT_SET) + return Validate_RequiredErrMsgHelper(TAG__SIGMA, DRVRERR__VALIDATION_SIGMA); + + if (area_params->mdvar == NOT_SET) + return Validate_RequiredErrMsgHelper(TAG__MDVAR, DRVRERR__VALIDATION_MDVAR); + + // infer TLS vs CR calling + bool isTLS = (area_params->time != NOT_SET && area_params->location != NOT_SET && area_params->situation.size() > 0); + bool isCR = (area_params->confidence.size() > 0 && area_params->reliability != NOT_SET); + + if (isTLS && isCR) + return GeneralErrorMsgHelper("Provided both time/location/situation parameters and confidence/reliability", DRVRERR__VALIDATION_TLS_AND_CR); + + if (!isTLS && !isCR) + return GeneralErrorMsgHelper("Must provide time/location/situation parameters or confidence/reliability", DRVRERR__VALIDATION_TLS_OR_CR); + + if (isTLS) + area_params->mode = VARY_TLS; + else + area_params->mode = VARY_CR; + + return SUCCESS; +} + +/*============================================================================= + | + | Description: Write Area inputs to the report file + | + | Input: fp - File pointer + | area_params - Area input parameter struct + | + | Output: [void] + | + | Returns: [void] + | + *===========================================================================*/ +void WriteAreaInputs(FILE* fp, AreaParams* area_params) { + fprintf_s(fp, "%-24s %-12g %s\n", TAG__HTX, area_params->h_tx__meter, UNITS__METER); + fprintf_s(fp, "%-24s %-12g %s\n", TAG__HRX, area_params->h_rx__meter, UNITS__METER); + fprintf_s(fp, "%-24s %-12i ", TAG__TX_SITE, area_params->tx_site_criteria); + PrintSitingCriteriaLabel(fp, area_params->tx_site_criteria); + fprintf_s(fp, "%-24s %-12i ", TAG__RX_SITE, area_params->rx_site_criteria); + PrintSitingCriteriaLabel(fp, area_params->rx_site_criteria); + if (area_params->d__km.size() == 1) { + fprintf_s(fp, "%-24s %-12g %s\n", TAG__DKM, area_params->d__km.front(), UNITS__KM); + } + else { + fprintf_s(fp, "%-24s %g,%g,%g,%g,%g\n", + TAG__DKM, + area_params->d_format[0], + area_params->d_format[1], + area_params->d_format[2], + area_params->d_format[3], + area_params->d_format[4]); + } + fprintf_s(fp, "%-24s %-12g %s\n", TAG__DELTAH, area_params->delta_h__meter, UNITS__METER); + fprintf_s(fp, "%-24s %-12i ", TAG__CLIMATE, area_params->climate); + PrintClimateLabel(fp, area_params->climate); + fprintf_s(fp, "%-24s %-12.2f %s\n", TAG__N0, area_params->N_0, UNITS__NUNIT); + fprintf_s(fp, "%-24s %-12.2f %s\n", TAG__FREQ, area_params->f__mhz, UNITS__MHZ); + fprintf_s(fp, "%-24s %-12i ", TAG__POL, area_params->pol); + PrintPolarizationLabel(fp, area_params->pol); + fprintf_s(fp, "%-24s %g\n", TAG__EPSILON, area_params->epsilon); + fprintf_s(fp, "%-24s %g\n", TAG__SIGMA, area_params->sigma); + fprintf_s(fp, "%-24s %-12i ", TAG__MDVAR, area_params->mdvar); + PrintMdvarLabel(fp, area_params->mdvar); + if (area_params->mode == VARY_TLS) { + fprintf_s(fp, "%-24s %g\n", TAG__TIME, area_params->time); + fprintf_s(fp, "%-24s %g\n", TAG__LOCATION, area_params->location); + fprintf_s(fp, "%-24s ", TAG__SITUATION); + for (int i = 0; i < area_params->situation.size() - 1; i++) { + fprintf_s(fp, "%g,", area_params->situation[i]); + } + fprintf_s(fp, "%g\n", area_params->situation.back()); + } + else { + fprintf_s(fp, "%-24s ", TAG__CONFIDENCE); + for (int i = 0; i < area_params->confidence.size() - 1; i++) { + fprintf_s(fp, "%g,", area_params->confidence[i]); + } + fprintf_s(fp, "%g\n", area_params->confidence.back()); + + fprintf_s(fp, "%-24s %g\n", TAG__RELIABILITY, area_params->reliability); + } +} diff --git a/win32/ITMDrvr/AreaMode.h b/win32/ITMDrvr/AreaMode.h new file mode 100644 index 0000000..d58c777 --- /dev/null +++ b/win32/ITMDrvr/AreaMode.h @@ -0,0 +1,11 @@ + + +// +// FUNCTIONS +/////////////////////////////////////////////// +int ParseAreaInputFile(const char* in_file, AreaParams* area_params); +int ValidateAreaInputs(AreaParams* area_params); +int CallAreaMode(DrvrParams* params, AreaParams* area_params, IntermediateValues* inter_vals, + vector* A__db, vector* A_fs__db, long* warnings); +void WriteAreaInputs(FILE* fp, AreaParams* area_params); +int LoadAreaFunctions(HINSTANCE hLib); diff --git a/win32/ITMDrvr/Common.cpp b/win32/ITMDrvr/Common.cpp new file mode 100644 index 0000000..5055779 --- /dev/null +++ b/win32/ITMDrvr/Common.cpp @@ -0,0 +1,70 @@ +#include "ITMDrvr.h" +#include "Common.h" + +/*============================================================================= + | + | Description: Parse an integer value read from the input parameter file + | + | Input: str - Input file value as string + | + | Output: value - Input file value converted to int + | + | Returns: rtn - Return error code + | + *===========================================================================*/ +int ParseInteger(const char* str, int* value) { + size_t t; + + try { + *value = ::stoi(str, &t, 10); + } catch (...) { + // error parsing the input string value + return ERROR; + } + + // verify the entire string was parsed, and a trailing char wasn't omitted + if (strlen(str) != t) + return ERROR; + + return SUCCESS; +} + +/*============================================================================= + | + | Description: Parse a double value read from the input parameter file + | + | Input: str - Input file value as string + | + | Output: value - Input file value converted to double + | + | Returns: rtn - Return error code + | + *===========================================================================*/ +int ParseDouble(const char* str, double* value) { + try { + *value = ::stod(str, nullptr); + } + catch (...) { + // error parsing the input string value + return ERROR; + } + + return SUCCESS; +} + +/*============================================================================= + | + | Description: Common error handling function + | + | Input: err - Error parsing code + | msg - Error message + | + | Output: [void] + | + | Returns: rtn - Error code from input param + | + *===========================================================================*/ +int ParsingErrorHelper(int err, const char* msg) { + printf_s("DrvrErr %i: Unable to parse '%s' value.\n", err, msg); + return err; +} diff --git a/win32/ITMDrvr/Common.h b/win32/ITMDrvr/Common.h new file mode 100644 index 0000000..53eaa50 --- /dev/null +++ b/win32/ITMDrvr/Common.h @@ -0,0 +1,5 @@ + + +int ParseInteger(const char* str, int* value); +int ParseDouble(const char* str, double* value); +int ParsingErrorHelper(int err, const char* msg); diff --git a/win32/ITMDrvr/ITMDrvr.cpp b/win32/ITMDrvr/ITMDrvr.cpp new file mode 100644 index 0000000..d22c232 --- /dev/null +++ b/win32/ITMDrvr/ITMDrvr.cpp @@ -0,0 +1,512 @@ +#include "ITMDrvr.h" +#include "PointToPointMode.h" +#include "AreaMode.h" +#include "Labels.h" +#include "Tags.h" +#include "Reporting.h" +#include "..\..\include\Enums.h" +#include "..\..\include\Errors.h" +#include "..\..\include\Warnings.h" + +int dllVerMajor = NOT_SET; +int dllVerMinor = NOT_SET; +int drvrVerMajor = NOT_SET; +int drvrVerMinor = NOT_SET; +int drvrVerDrvr = NOT_SET; + +wchar_t buf[TIME_SIZE]; + +/*============================================================================= + | + | Description: Main function of the ITM driver executable + | + *===========================================================================*/ +int main(int argc, char** argv) { + int rtn; + DrvrParams params; + + // Get the time + time_t t = time(NULL); + _wctime_s(buf, TIME_SIZE, &t); + + rtn = ParseArguments(argc, argv, ¶ms); + if (rtn == DRVR__RETURN_SUCCESS) + return SUCCESS; + if (rtn) { + Help(); + return rtn; + } + + // validate command line inputs + rtn = ValidateInputs(¶ms); + if (rtn) + { + printf_s("\n"); + Help(); + return rtn; + } + + rtn = LoadDLL(); + if (rtn) + return rtn; + + + // validate input file inputs + vector A__db; + vector A_fs__db; + long warnings; + IntermediateValues inter_vals; + P2PParams p2p_params; + AreaParams area_params; + + if (params.mode == MODE_P2P) + rtn = CallP2PMode(¶ms, &p2p_params, &inter_vals, &A__db, &warnings); + else { + rtn = CallAreaMode(¶ms, &area_params, &inter_vals, &A__db, &A_fs__db, &warnings); + } + + if (rtn >= 1100) // these are driver errors + return rtn; + + // print results to file + FILE* fp; + int err = fopen_s(&fp, params.out_file, "w"); + if (err != 0) { + printf_s("Error opening output file. Exiting.\n"); + return err; + } + else { + fprintf_s(fp, "itm.dll Version v%i.%i\n", dllVerMajor, dllVerMinor); + fprintf_s(fp, "ITMDrvr.exe Version v%i.%i.%i\n", drvrVerMajor, drvrVerMinor, drvrVerDrvr); + fwprintf_s(fp, L"Date Generated %s", buf); + fprintf_s(fp, "Input Arguments "); + for (int i = 1; i < argc; i++) { + fprintf_s(fp, "%s ", argv[i]); + } + fprintf_s(fp, "\n\n"); + fprintf_s(fp, "Inputs\n"); + if (params.mode == MODE_P2P) { + WriteP2PInputs(fp, &p2p_params); + fprintf_s(fp, "Mode Point-to-Point\n"); + fprintf_s(fp, "Terrain File %s\n", params.terrain_file); + } + else { + WriteAreaInputs(fp, &area_params); + fprintf_s(fp, "Mode Area\n"); + } + + fprintf_s(fp, "\n"); + + if (rtn != SUCCESS && rtn != SUCCESS_WITH_WARNINGS) { + fprintf_s(fp, "ITM Error %-12i ", rtn); + PrintErrorMsgLabel(fp, rtn); + } + else { + fprintf_s(fp, "Results\n"); + fprintf_s(fp, "ITM Warning Flags 0x%.4X ", warnings); + PrintWarningMessages(fp, warnings); + fprintf_s(fp, "ITM Return Code %-12i ", rtn); + PrintErrorMsgLabel(fp, rtn); + if (A__db.size() == 1) { + fprintf_s(fp, "Basic Transmission Loss %-12.1f %s\n", A__db.front(), UNITS__DB); + } + else { + // print table + if (params.mode == MODE_P2P) { + fprintf_s(fp, "\nBasic Transmission Loss Results %s\n", UNITS__DB); + fprintf_s(fp, "Reliability with Confidence\n"); + fprintf_s(fp, " "); + for (int i = 0; i < p2p_params.confidence.size(); i++) { + fprintf_s(fp, "%-10g", p2p_params.confidence[i]); + } + fprintf_s(fp, "\n"); + for (int i = 0; i < p2p_params.reliability.size(); i++) { + fprintf_s(fp, "%-15g", p2p_params.reliability[i]); + + for (int j = 0; j < p2p_params.confidence.size(); j++) { + fprintf_s(fp, "%-10.1f", A__db[i * p2p_params.confidence.size() + j]); + } + fprintf_s(fp, "\n"); + } + } + else { + fprintf_s(fp, "\nBasic Transmission Loss Results %s\n", UNITS__DB); + fprintf_s(fp, "Distance Free with Confidence\n"); + fprintf_s(fp, " %s Space ", UNITS__KM); + for (int i = 0; i < area_params.confidence.size(); i++) { + fprintf_s(fp, "%-10g", area_params.confidence[i]); + } + fprintf_s(fp, "\n"); + for (int i = 0; i < area_params.d__km.size(); i++) { + fprintf_s(fp, "%-13g", area_params.d__km[i]); + + fprintf_s(fp, "%-10.1f", A_fs__db[i]); + + for (int j = 0; j < area_params.confidence.size(); j++) { + fprintf_s(fp, "%-10.1f", A__db[i * area_params.confidence.size() + j]); + } + fprintf_s(fp, "\n"); + } + } + } + + if (params.DBG && + (params.mode == MODE_P2P || (params.mode == MODE_AREA && A__db.size() == 1))) { + fprintf_s(fp, "\n"); + fprintf_s(fp, "Intermediate Values\n"); + fprintf_s(fp, "Free Space %-12.1f %s\n", inter_vals.A_fs__db, UNITS__DB); + fprintf_s(fp, "d__km %-12.3f %s\n", inter_vals.d__km, UNITS__KM); + fprintf_s(fp, "theta_hzn_tx %-12.3f %s\n", inter_vals.theta_hzn[0] * 1000, UNITS__MRAD); + fprintf_s(fp, "theta_hzn_rx %-12.3f %s\n", inter_vals.theta_hzn[1] * 1000, UNITS__MRAD); + fprintf_s(fp, "d_hzn_tx__meter %-12.0f %s\n", inter_vals.d_hzn__meter[0], UNITS__METER); + fprintf_s(fp, "d_hzn_rx__meter %-12.0f %s\n", inter_vals.d_hzn__meter[1], UNITS__METER); + fprintf_s(fp, "h_e_tx__meter %-12.1f %s\n", inter_vals.h_e__meter[0], UNITS__METER); + fprintf_s(fp, "h_e_rx__meter %-12.1f %s\n", inter_vals.h_e__meter[1], UNITS__METER); + fprintf_s(fp, "N_s %-12.1f %s\n", inter_vals.N_s, UNITS__NUNIT); + fprintf_s(fp, "delta_h__meter %-12.1f %s\n", inter_vals.delta_h__meter, UNITS__METER); + fprintf_s(fp, "A_ref__db %-12.1f %s\n", inter_vals.A_ref__db, UNITS__DB); + fprintf_s(fp, "Mode of Propagation %-12i ", inter_vals.mode); + switch (inter_vals.mode) { + case 1: fprintf_s(fp, "[%s]\n", LBL__LINE_OF_SITE); + break; + case 2: fprintf_s(fp, "[%s]\n", LBL__DIFFRACTION); + break; + case 3: fprintf_s(fp, "[%s]\n", LBL__TROPOSCATTER); + break; + } + } + } + + fclose(fp); + } +} + +/*============================================================================= + | + | Description: Parse the command line arguments + | + | Input: argc - Number of arguments + | argv - Command line arguments + | + | Output: params - Structure with user input params + | + | Returns: SUCCESS, or error code encountered + | + *===========================================================================*/ +int ParseArguments(int argc, char** argv, DrvrParams* params) { + for (int i = 1; i < argc; i++) { + Lowercase(argv[i]); + + if (Match("-i", argv[i])) { + sprintf_s(params->in_file, "%s", argv[i + 1]); + i++; + } + else if (Match("-o", argv[i])) { + sprintf_s(params->out_file, "%s", argv[i + 1]); + i++; + } + else if (Match("-t", argv[i])) { + sprintf_s(params->terrain_file, "%s", argv[i + 1]); + i++; + } + else if (Match("-mode", argv[i])) + { + Lowercase(argv[i + 1]); + + if (Match("p2p", argv[i + 1])) + params->mode = MODE_P2P; + else if (Match("area", argv[i + 1])) + params->mode = MODE_AREA; + else + return ParseErrorMsgHelper("-mode [mode]", DRVRERR__PARSE_MODE_VALUE); + + i++; + } + else if (Match("-dbg", argv[i])) { + params->DBG = true; + } + else if (Match("-v", argv[i])) { + Version(); + return DRVR__RETURN_SUCCESS; + } + else if (Match("-h", argv[i])) { + Help(); + return DRVR__RETURN_SUCCESS; + } + else { + printf_s("Unknown option: %s\n", argv[i]); + return DRVRERR__INVALID_OPTION; + } + } + + return SUCCESS; +} + +/*============================================================================= + | + | Description: Convert the char array to lower case + | + | Input/Output: argv - value + | + | Returns: [Void] + | + *===========================================================================*/ +void Lowercase(char* argv) { + for (int i = 0; i < strlen(argv); i++) + argv[i] = tolower(argv[i]); +} + +/*============================================================================= + | + | Description: Compare to strings to see if they match + | + | Input: opt - Given char array + | arg - Expected char array + | + | Returns: True/False + | + *===========================================================================*/ +bool Match(const char* opt, char* arg) { + if (strcmp(opt, arg) == 0) + return true; + return false; +} + +/*============================================================================= + | + | Description: Print help instructions to the terminal + | + | Input: [Void] + | + | Returns: [Void] + | + *===========================================================================*/ +void Help() { + printf_s("\n"); + printf_s("Usage: ITMDrvr.exe [Options]\n"); + printf_s("Options (not case sensitive)\n"); + printf_s("\t-i :: Input file name\n"); + printf_s("\t-t :: Terrain file name\n"); + printf_s("\t-o :: Output file name\n"); + printf_s("\t-mode :: Mode of operation [P2P, AREA]\n"); + printf_s("\t-dbg :: Dump intermediate values to output file [optional]\n"); + printf_s("\n"); + printf_s("Examples:\n"); + printf_s("\tITMDrvr.exe -i inputs.txt -t terrain.txt -o results.txt -mode P2P\n"); + printf_s("\n"); +}; + +/*============================================================================= + | + | Description: Print version information to the terminal + | + | Input: [Void] + | + | Returns: [Void] + | + *===========================================================================*/ +void Version() { + printf_s("*******************************************************\n"); + printf_s("Institute for Telecommunications Sciences - Boulder, CO\n"); + printf_s("\tITM Driver Version: %i.%i\n", drvrVerMajor, drvrVerMinor); + printf_s("\tITM DLL Version: %i.%i\n", dllVerMajor, dllVerMinor); + wprintf_s(L"Time: %s", buf); + printf_s("*******************************************************\n"); +} + +/*============================================================================= + | + | Description: Helper function to format and print error messages + | encountered during command argument parsing + | + | Input: opt - Command flag in error + | err - Error code + | + | Returns: Error code + | + *===========================================================================*/ +int ParseErrorMsgHelper(const char* opt, int err) { + printf_s("DrvrErr %i: Unable to parse %s value.\n", err, opt); + return err; +} + +/*============================================================================= + | + | Description: Helper function to format and print error messages + | encountered during driver execution + | + | Input: msg - Command flag in error + | err - Error code + | + | Returns: Error code + | + *===========================================================================*/ +int GeneralErrorMsgHelper(const char* msg, int err) { + printf_s("DrvrErr %i: %s.\n", err, msg); + return err; +} + +/*============================================================================= + | + | Description: Validate that the required inputs are present for the + | mode specified by the user. This function DOES NOT + | check the validity of the parameter values - only that + | required parameters have been specified by the user + | + | Input: params - Structure with user input parameters + | + | Returns: SUCCESS, or error code encountered + | + *===========================================================================*/ +int ValidateInputs(DrvrParams* params) { + if (params->mode == NOT_SET) + return Validate_RequiredErrMsgHelper("-mode", DRVRERR__VALIDATION_MODE); + + if (strlen(params->in_file) == 0) + return Validate_RequiredErrMsgHelper("-i", DRVRERR__VALIDATION_IN_FILE); + + if (strlen(params->out_file) == 0) + return Validate_RequiredErrMsgHelper("-o", DRVRERR__VALIDATION_OUT_FILE); + + if (params->mode == MODE_P2P) { + if (strlen(params->terrain_file) == 0) + return Validate_RequiredErrMsgHelper("-t", DRVRERR__VALIDATION_TERRAIN_FILE); + } + + return SUCCESS; +} + +/*============================================================================= + | + | Description: Helper function to format and print error messages + | encountered during validation of input parameters + | + | Input: opt - Command flag in error + | err - Error code + | + | Returns: Error code + | + *===========================================================================*/ +int Validate_RequiredErrMsgHelper(const char* opt, int err) { + printf_s("DrvrError %i: Option %s is required but was not provided\n", err, opt); + return err; +} + +/*============================================================================= + | + | Description: Loads the ITM DLL + | + | Input: [void] + | + | Returns: [void] + | + *===========================================================================*/ +int LoadDLL() { + HINSTANCE hLib = LoadLibrary(TEXT("itm.dll")); + + if (hLib == NULL) + return DRVRERR__DLL_LOADING; + + GetDLLVersionInfo(); + GetDrvrVersionInfo(); + if (dllVerMajor != drvrVerMajor) + return DRVRERR__MAJOR_VERSION_MISMATCH; + + // Grab the functions in the DLL + int rtn = LoadP2PFunctions(hLib); + if (rtn != SUCCESS) + return rtn; + + rtn = LoadAreaFunctions(hLib); + if (rtn != SUCCESS) + return rtn; + + return SUCCESS; +} + +/*============================================================================= + | + | Description: Get the version information of the P.528 DLL + | + | Input: [void] + | + | Returns: [void] + | + *===========================================================================*/ +void GetDLLVersionInfo() { + DWORD verHandle = NULL; + UINT size = 0; + LPBYTE lpBuffer = NULL; + DWORD verSize = GetFileVersionInfoSize(TEXT("itm.dll"), &verHandle); + + if (verSize != NULL) + { + LPSTR verData = new char[verSize]; + + if (GetFileVersionInfo(TEXT("itm.dll"), verHandle, verSize, verData)) + { + if (VerQueryValue(verData, TEXT("\\"), (VOID FAR* FAR*)&lpBuffer, &size)) + { + if (size) + { + VS_FIXEDFILEINFO *verInfo = (VS_FIXEDFILEINFO *)lpBuffer; + if (verInfo->dwSignature == 0xfeef04bd) + { + dllVerMajor = (verInfo->dwFileVersionMS >> 16) & 0xffff; + dllVerMinor = (verInfo->dwFileVersionMS >> 0) & 0xffff; + } + } + } + } + + delete[] verData; + } + + return; +} + +/*============================================================================= + | + | Description: Get the version information of this driver + | + | Input: [void] + | + | Returns: [void] + | + *===========================================================================*/ +void GetDrvrVersionInfo() +{ + DWORD verHandle = NULL; + UINT size = 0; + LPBYTE lpBuffer = NULL; + WCHAR fileName[MAX_PATH]; + + GetModuleFileName(NULL, fileName, MAX_PATH); + DWORD verSize = GetFileVersionInfoSize(fileName, &verHandle); + + if (verSize != NULL) + { + LPSTR verData = new char[verSize]; + + if (GetFileVersionInfo(fileName, verHandle, verSize, verData)) + { + if (VerQueryValue(verData, L"\\", (VOID FAR * FAR*) &lpBuffer, &size)) + { + if (size) + { + VS_FIXEDFILEINFO* verInfo = (VS_FIXEDFILEINFO*)lpBuffer; + if (verInfo->dwSignature == 0xfeef04bd) + { + drvrVerMajor = (verInfo->dwFileVersionMS >> 16) & 0xffff; + drvrVerMinor = (verInfo->dwFileVersionMS >> 0) & 0xffff; + drvrVerDrvr = (verInfo->dwFileVersionLS >> 16) & 0xffff; + } + } + } + } + + delete[] verData; + } + + return; +} \ No newline at end of file diff --git a/win32/ITMDrvr/ITMDrvr.h b/win32/ITMDrvr/ITMDrvr.h new file mode 100644 index 0000000..4f56ea0 --- /dev/null +++ b/win32/ITMDrvr/ITMDrvr.h @@ -0,0 +1,171 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +// +// CONSTANTS +/////////////////////////////////////////////// + +#define MODE_P2P 0 +#define MODE_AREA 1 + +#define VARY_TLS 0 +#define VARY_CR 1 +#define TIME_SIZE 26 + +// +// GENERAL ERRORS AND RETURN VALUES +/////////////////////////////////////////////// + +#define NOT_SET -1 +#define ERROR -1 +#define SUCCESS 0 +#define SUCCESS_WITH_WARNINGS 1 +#define DRVR__RETURN_SUCCESS 1000 + +#define DRVRERR__DLL_LOADING 1001 +#define DRVRERR__MAJOR_VERSION_MISMATCH 1002 +#define DRVRERR__INVALID_OPTION 1003 +#define DRVRERR__GET_P2P_TLS_FUNC_LOADING 1004 +#define DRVRERR__GET_P2P_CR_FUNC_LOADING 1005 +#define DRVRERR__GET_AREA_TLS_FUNC_LOADING 1006 +#define DRVRERR__GET_AREA_CR_FUNC_LOADING 1007 +#define DRVRERR__PARSE_MODE_VALUE 1008 +// Input File Parsing Errors (1100-1199) +#define DRVRERR__PARSE_HTX 1101 +#define DRVRERR__PARSE_HRX 1102 +#define DRVRERR__PARSE_CLIMATE 1103 +#define DRVRERR__PARSE_N0 1104 +#define DRVRERR__PARSE_FREQ 1105 +#define DRVRERR__PARSE_POL 1106 +#define DRVRERR__PARSE_EPSILON 1107 +#define DRVRERR__PARSE_SIGMA 1108 +#define DRVRERR__PARSE_MDVAR 1109 +#define DRVRERR__PARSE_TIME 1110 +#define DRVRERR__PARSE_LOCATION 1111 +#define DRVRERR__PARSE_SITUATION 1112 +#define DRVRERR__PARSE_CONFIDENCE 1113 +#define DRVRERR__PARSE_RELIABILITY 1114 +#define DRVRERR__PARSE_TX_SITE 1115 +#define DRVRERR__PARSE_RX_SITE 1116 +#define DRVRERR__PARSE_DKM 1117 +#define DRVRERR__PARSE_DELTAH 1118 +#define DRVRERR__PARSE_INCOMPLETE_DISTANCES 1119 +// Validation Errors (1200-1299) +#define DRVRERR__VALIDATION_MODE 1201 +#define DRVRERR__VALIDATION_IN_FILE 1202 +#define DRVRERR__VALIDATION_OUT_FILE 1203 +#define DRVRERR__VALIDATION_TERRAIN_FILE 1204 +#define DRVRERR__VALIDATION_HTX 1205 +#define DRVRERR__VALIDATION_HRX 1206 +#define DRVRERR__VALIDATION_CLIMATE 1207 +#define DRVRERR__VALIDATION_N0 1208 +#define DRVRERR__VALIDATION_FMHZ 1209 +#define DRVRERR__VALIDATION_POL 1210 +#define DRVRERR__VALIDATION_EPSILON 1211 +#define DRVRERR__VALIDATION_SIGMA 1212 +#define DRVRERR__VALIDATION_MDVAR 1213 +#define DRVRERR__VALIDATION_TLS_AND_CR 1214 +#define DRVRERR__VALIDATION_TLS_OR_CR 1215 +#define DRVRERR__VALIDATION_HTX_SITE 1216 +#define DRVRERR__VALIDATION_RTX_SITE 1217 +#define DRVRERR__VALIDATION_DKM 1218 +#define DRVRERR__VALIDATION_DELTAH 1219 + +// +// DATA STRUCTURES +/////////////////////////////////////////////// + +struct DrvrParams { + char terrain_file[256] = { 0 }; // Terrain file + char in_file[256] = { 0 }; // Input file + char out_file[256] = { 0 }; // Output file + + int mode = NOT_SET; // Mode (P2P, AREA) + bool DBG = false; // Dump intermediate values to file? +}; + +struct P2PParams { + double h_tx__meter = NOT_SET; + double h_rx__meter = NOT_SET; + int climate = NOT_SET; + double N_0 = NOT_SET; + double f__mhz = NOT_SET; + int pol = NOT_SET; + double epsilon = NOT_SET; + double sigma = NOT_SET; + int mdvar = NOT_SET; + double time = NOT_SET; + double location = NOT_SET; + double situation = NOT_SET; + + vector confidence; + vector reliability; + + int mode = NOT_SET; +}; + +struct AreaParams { + double h_tx__meter = NOT_SET; + double h_rx__meter = NOT_SET; + int tx_site_criteria = NOT_SET; + int rx_site_criteria = NOT_SET; + double delta_h__meter = NOT_SET; + int climate = NOT_SET; + double N_0 = NOT_SET; + double f__mhz = NOT_SET; + int pol = NOT_SET; + double epsilon = NOT_SET; + double sigma = NOT_SET; + int mdvar = NOT_SET; + double time = NOT_SET; + double location = NOT_SET; + double reliability = NOT_SET; + + double d_format[5] = { 0 }; + + vector d__km; + vector confidence; + vector situation; + + int mode = NOT_SET; +}; + +struct IntermediateValues +{ + double theta_hzn[2]; // Terminal horizon angles + double d_hzn__meter[2]; // Terminal horizon distances, in meters + double h_e__meter[2]; // Terminal effective heights, in meters + double N_s; // Surface refractivity, in N-Units + double delta_h__meter; // Terrain irregularity parameter, in meters + double A_ref__db; // Reference attenuation, in dB + double A_fs__db; // Free space basic transmission loss, in dB + double d__km; // Path distance, in km + int mode; // Mode of propagation value +}; + +// +// FUNCTIONS +/////////////////////////////////////////////// + +int ParseArguments(int argc, char** argv, DrvrParams* params); +void Lowercase(char* argv); +bool Match(const char* opt, char* arg); +void Help(); +void Version(); +int ParseErrorMsgHelper(const char* opt, int err); +int ValidateInputs(DrvrParams* params); +int Validate_RequiredErrMsgHelper(const char* opt, int err); + + +int LoadDLL(); +void GetDLLVersionInfo(); +void GetDrvrVersionInfo(); +int GeneralErrorMsgHelper(const char* msg, int err); diff --git a/win32/ITMDrvr/ITMDrvr.rc b/win32/ITMDrvr/ITMDrvr.rc new file mode 100644 index 0000000..9b5d085 --- /dev/null +++ b/win32/ITMDrvr/ITMDrvr.rc @@ -0,0 +1,99 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,3,0,0 + PRODUCTVERSION 1,3,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "The Institute for Telecommunication Sciences" + VALUE "FileDescription", "Irregular Terrain Model (ITM) Driver" + VALUE "FileVersion", "1.3.0.0" + VALUE "InternalName", "ITMDrvr.exe" + VALUE "OriginalFilename", "ITMDrvr.exe" + VALUE "ProductName", "Irregular Terrain Model (ITM) Driver" + VALUE "ProductVersion", "1.3.0.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/win32/ITMDrvr/ITMDrvr.vcxproj b/win32/ITMDrvr/ITMDrvr.vcxproj new file mode 100644 index 0000000..b33bedd --- /dev/null +++ b/win32/ITMDrvr/ITMDrvr.vcxproj @@ -0,0 +1,180 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + 16.0 + Win32Proj + {2e012ae1-2a12-4d6d-9f11-80fcf6aa2dd8} + ITMDrvr + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)..\bin\x86\$(Configuration)\ + + + false + $(SolutionDir)..\bin\x86\$(Configuration)\ + + + true + $(SolutionDir)..\bin\x64\$(Configuration)\ + + + false + $(SolutionDir)..\bin\x64\$(Configuration)\ + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + + + + Console + true + version.lib;%(AdditionalDependencies) + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + + + + Console + true + true + true + version.lib;%(AdditionalDependencies) + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + + + + Console + true + version.lib;%(AdditionalDependencies) + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + + + + Console + true + true + true + version.lib;%(AdditionalDependencies) + + + + + + \ No newline at end of file diff --git a/win32/ITMDrvr/ITMDrvr.vcxproj.filters b/win32/ITMDrvr/ITMDrvr.vcxproj.filters new file mode 100644 index 0000000..15796e7 --- /dev/null +++ b/win32/ITMDrvr/ITMDrvr.vcxproj.filters @@ -0,0 +1,65 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Resource Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/win32/ITMDrvr/Labels.h b/win32/ITMDrvr/Labels.h new file mode 100644 index 0000000..2416300 --- /dev/null +++ b/win32/ITMDrvr/Labels.h @@ -0,0 +1,78 @@ + +/////////////////////////////////////////////// +// LABELS + +#define LBL__SUCCESS "Success - No Errors" +#define LBL__SUCCESS_WITH_WARNINGS "Success - but with warnings" +#define LBL__NO_WARNINGS "No Warnings" + +// Modes of propagation +#define LBL__LINE_OF_SITE "Line of Sight" +#define LBL__DIFFRACTION "Diffraction" +#define LBL__TROPOSCATTER "Troposcatter" + +// Polarization +#define LBL__POLARIZATION_HORIZONTAL "Horizontal" +#define LBL__POLARIZATION_VERTICAL "Vertical" + +// Terminal siting criteria +#define LBL__SITING_CRITERIA_RANDOM "Random" +#define LBL__SITING_CRITERIA_CAREFUL "Careful" +#define LBL__SITING_CRITERIA_VERY_CAREFUL "Very Careful" + +// Radio climates +#define LBL__CLIMATE_EQUATORIAL "Equatorial" +#define LBL__CLIMATE_CONTINENTAL_SUBTROPICAL "Continental Subtropical" +#define LBL__CLIMATE_MARITIME_SUBTROPICAL "Maritime Subtropical" +#define LBL__CLIMATE_DESERT "Desert" +#define LBL__CLIMATE_CONTINENTAL_TEMPERATE "Continental Temperate" +#define LBL__CLIMATE_MARITIME_TEMPERATE_OVER_LAND "Maritime Temperate over Land" +#define LBL__CLIMATE_MARITIME_TEMPERATE_OVER_SEA "Maritime Temperate over Sea" + +// Mode of variabilities +#define LBL__MDVAR_SINGLE_MESSAGE_MODE "Single Message Mode" +#define LBL__MDVAR_ACCIDENTAL_MODE "Accidental Mode" +#define LBL__MDVAR_MOBILE_MODE "Mobile Mode" +#define LBL__MDVAR_BROADCAST_MODE "Broadcast Mode" + +// Errors +#define LBL__ERROR_INVALID_VALUE "Invalid Value" +#define LBL__ERROR_TX_TERMINAL_HEIGHT "TX terminal height is out of range" +#define LBL__ERROR_RX_TERMINAL_HEIGHT "RX terminal height is out of range" +#define LBL__ERROR_INVALID_RADIO_CLIMATE "Invalid value for radio climate" +#define LBL__ERROR_INVALID_TIME "Time percentage is out of range" +#define LBL__ERROR_INVALID_LOCATION "Location percentage is out of range" +#define LBL__ERROR_INVALID_SITUATION "Situation percentage is out of range" +#define LBL__ERROR_INVALID_CONFIDENCE "Confidence percentage is out of range" +#define LBL__ERROR_INVALID_RELIABILITY "Reliability percentage is out of range" +#define LBL__ERROR_REFRACTIVITY "Refractivity is out of range" +#define LBL__ERROR_FREQUENCY "Frequency is out of range" +#define LBL__ERROR_POLARIZATION "Invalid value for polarization" +#define LBL__ERROR_EPSILON "Epsilon is out of range" +#define LBL__ERROR_SIGMA "Sigma is out of range" +#define LBL__ERROR_GROUND_IMPEDANCE "The imaginary portion of the complex impedance is larger than the real portion" +#define LBL__ERROR_MDVAR "Invalid value for mode of variability" +#define LBL__ERROR_EFFECTIVE_EARTH "Internally computed effective earth radius is invalid" +#define LBL__ERROR_PATH_DISTANCE "Path distance is out of range" +#define LBL__ERROR_DELTA_H "Delta H (terrain irregularity parameter) is out of range" +#define LBL__ERROR_TX_SITING_CRITERIA "Invalid value for TX siting criteria" +#define LBL__ERROR_RX_SITING_CRITERIA "Invalid value for RX siting criteria" +#define LBL__ERROR_SURFACE_REFRACTIVITY_SMALL "Internally computed surface refractivity value is too small" +#define LBL__ERROR_SURFACE_REFRACTIVITY_LARGE "Internally computed surface refractivity value is too large" + +// Warnings +#define LBL__WARN_TX_TERMINAL_HEIGHT "TX terminal height is near its limits" +#define LBL__WARN_RX_TERMINAL_HEIGHT "RX terminal height is near its limits" +#define LBL__WARN_FREQUENCY "Frequency is near its limits" +#define LBL__WARN_PATH_DISTANCE_TOO_BIG_1 "Path distance is near its upper limit" +#define LBL__WARN_PATH_DISTANCE_TOO_BIG_2 "Path distance is large - care must be taken with result" +#define LBL__WARN_PATH_DISTANCE_TOO_SMALL_1 "Path distance is near its lower limit" +#define LBL__WARN_PATH_DISTANCE_TOO_SMALL_2 "Path distance is small - care must be taken with result" +#define LBL__WARN_TX_HORIZON_ANGLE "TX horizon angle is large - small angle approximations could break down" +#define LBL__WARN_RX_HORIZON_ANGLE "RX horizon angle is large - small angel approximations could break down" +#define LBL__WARN_TX_HORIZON_DISTANCE_1 "TX horizon distance is less than 1/10 of the smooth earth horizon distance" +#define LBL__WARN_RX_HORIZON_DISTANCE_1 "RX horizon distance is less than 1/10 of the smooth earth horizon distance" +#define LBL__WARN_TX_HORIZON_DISTANCE_2 "TX horizon distance is greater than 3 times the smooth earth horizon distance" +#define LBL__WARN_RX_HORIZON_DISTANCE_2 "RX horizon distance is greater than 3 times the smooth earth horizon distance" +#define LBL__WARN_EXTREME_VARIABILITIES "One of the provided variabilities is located far in the tail of its distribution" +#define LBL__WARN_SURFACE_REFRACTIVITY "Internally computed surface refractivity value is small - care must be taken with result" diff --git a/win32/ITMDrvr/PointToPointMode.cpp b/win32/ITMDrvr/PointToPointMode.cpp new file mode 100644 index 0000000..632dfc6 --- /dev/null +++ b/win32/ITMDrvr/PointToPointMode.cpp @@ -0,0 +1,391 @@ +#include "ITMDrvr.h" +#include "PointToPointMode.h" +#include "Tags.h" +#include "Reporting.h" +#include "Common.h" + +// ITM DLL Functions +typedef int(__stdcall *itm_p2p_tls_ex_func)(double h_tx__meter, double h_rx__meter, + double pfl[], int climate, double N_0, double f__mhz, int pol, double epsilon, + double sigma, int mdvar, double time, double location, double situation, + double *A__db, long *warnings, struct IntermediateValues *interValues); + +typedef int(__stdcall *itm_p2p_cr_ex_func)(double h_tx__meter, double h_rx__meter, + double pfl[], int climate, double N_0, double f__mhz, int pol, double epsilon, + double sigma, int mdvar, double confidence, double reliability, + double *A__db, long *warnings, struct IntermediateValues *interValues); + +// Local Globals +itm_p2p_tls_ex_func itm_p2p_tls_ex; +itm_p2p_cr_ex_func itm_p2p_cr_ex; + +/*============================================================================= + | + | Description: Top-level control function for P2P mode operation + | + | Input: params - Driver input parameter struct + | + | Output: p2p_params - P2P input parameter struct + | inter_vals - ITM intermediate values struct + | A__db - Basic transmission loss, in dB + | warnings - ITM return warning flags + | + | Returns: rtn - Return error code + | + *===========================================================================*/ +int CallP2PMode(DrvrParams* params, P2PParams* p2p_params, IntermediateValues* inter_vals, vector* A__db, long* warnings) { + int rtn = ParseP2PInputFile(params->in_file, p2p_params); + if (rtn != SUCCESS) + return rtn; + + rtn = ValidateP2PInputs(p2p_params); + if (rtn != SUCCESS) + return rtn; + + vector pfl; + ParseTerrainFile(params->terrain_file, &pfl); + + double ADB; + if (p2p_params->mode == VARY_TLS) { + rtn = itm_p2p_tls_ex( + p2p_params->h_tx__meter, + p2p_params->h_rx__meter, + &pfl[0], + p2p_params->climate, + p2p_params->N_0, + p2p_params->f__mhz, + p2p_params->pol, + p2p_params->epsilon, + p2p_params->sigma, + p2p_params->mdvar, + p2p_params->time, + p2p_params->location, + p2p_params->situation, + &ADB, + warnings, + inter_vals); + + A__db->push_back(ADB); + } + else { + long WARN; + *warnings = 0; + + for (int i = 0; i < p2p_params->reliability.size(); i++) { + for (int j = 0; j < p2p_params->confidence.size(); j++) { + rtn = itm_p2p_cr_ex( + p2p_params->h_tx__meter, + p2p_params->h_rx__meter, + &pfl[0], + p2p_params->climate, + p2p_params->N_0, + p2p_params->f__mhz, + p2p_params->pol, + p2p_params->epsilon, + p2p_params->sigma, + p2p_params->mdvar, + p2p_params->confidence[j], + p2p_params->reliability[i], + &ADB, + &WARN, + inter_vals); + + A__db->push_back(ADB); + *warnings = *warnings | WARN; + } + } + + } + + return rtn; +} + +/*============================================================================= + | + | Description: Load P2P functions from the ITM DLL + | + | Input: hLib - DLL handle + | + | Output: [void] + | + | Returns: rtn - Return error code + | + *===========================================================================*/ +int LoadP2PFunctions(HINSTANCE hLib) { + itm_p2p_tls_ex = (itm_p2p_tls_ex_func)GetProcAddress((HMODULE)hLib, "ITM_P2P_TLS_Ex"); + if (itm_p2p_tls_ex == nullptr) + return DRVRERR__GET_P2P_TLS_FUNC_LOADING; + + itm_p2p_cr_ex = (itm_p2p_cr_ex_func)GetProcAddress((HMODULE)hLib, "ITM_P2P_CR_Ex"); + if (itm_p2p_cr_ex == nullptr) + return DRVRERR__GET_P2P_CR_FUNC_LOADING; + + return SUCCESS; +} + +/*============================================================================= + | + | Description: Parse P2P input parameter file + | + | Input: in_file - Path to P2P input parameter file + | + | Output: p2p_params - P2P input parameter struct + | + | Returns: rtn - Return error code + | + *===========================================================================*/ +int ParseP2PInputFile(const char* in_file, P2PParams *p2p_params) { + ifstream file; + file.open(in_file); + string line; + + while (getline(file, line)) { + int i = line.find(","); + + string key = line.substr(0, i); + string value = line.substr(i + 1); + + transform(key.begin(), key.end(), key.begin(), ::tolower); + + if (key.compare(TAG__HTX) == 0) { + if (ParseDouble(value.c_str(), &p2p_params->h_tx__meter) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_HTX, TAG__HTX); + } + } + else if (key.compare(TAG__HRX) == 0) { + if (ParseDouble(value.c_str(), &p2p_params->h_rx__meter) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_HRX, TAG__HRX); + } + } + else if (key.compare(TAG__CLIMATE) == 0) { + if (ParseInteger(value.c_str(), &p2p_params->climate) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_CLIMATE, TAG__CLIMATE); + } + } + else if (key.compare("n_0") == 0) { + if (ParseDouble(value.c_str(), &p2p_params->N_0) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_N0, TAG__N0); + } + } + else if (key.compare(TAG__FREQ) == 0) { + if (ParseDouble(value.c_str(), &p2p_params->f__mhz) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_FREQ, TAG__FREQ); + } + } + else if (key.compare(TAG__POL) == 0) { + if (ParseInteger(value.c_str(), &p2p_params->pol) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_POL, TAG__POL); + } + } + else if (key.compare(TAG__EPSILON) == 0) { + if (ParseDouble(value.c_str(), &p2p_params->epsilon) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_EPSILON, TAG__EPSILON); + } + } + else if (key.compare(TAG__SIGMA) == 0) { + if (ParseDouble(value.c_str(), &p2p_params->sigma) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_SIGMA, TAG__SIGMA); + } + } + else if (key.compare(TAG__MDVAR) == 0) { + if (ParseInteger(value.c_str(), &p2p_params->mdvar) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_MDVAR, TAG__MDVAR); + } + } + else if (key.compare(TAG__TIME) == 0) { + if (ParseDouble(value.c_str(), &p2p_params->time) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_TIME, TAG__TIME); + } + } + else if (key.compare(TAG__LOCATION) == 0) { + if (ParseDouble(value.c_str(), &p2p_params->location) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_LOCATION, TAG__LOCATION); + } + } + else if (key.compare(TAG__SITUATION) == 0) { + if (ParseDouble(value.c_str(), &p2p_params->situation) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_SITUATION, TAG__SITUATION); + } + } + else if (key.compare(TAG__CONFIDENCE) == 0) { + int s = 0, e = 0; + do { + e = value.find(',', s); + string str = value.substr(s, e); + + double confidence; + if (ParseDouble(str.c_str(), &confidence) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_CONFIDENCE, TAG__CONFIDENCE); + } + + p2p_params->confidence.push_back(confidence); + s = e + 1; + } while (e != value.npos); + } + else if (key.compare(TAG__RELIABILITY) == 0) { + int s = 0, e = 0; + do { + e = value.find(',', s); + string str = value.substr(s, e); + + double reliability; + if (ParseDouble(str.c_str(), &reliability) == ERROR) { + return ParsingErrorHelper(DRVRERR__PARSE_RELIABILITY, TAG__RELIABILITY); + } + + p2p_params->reliability.push_back(reliability); + s = e + 1; + } while (e != value.npos); + } + else { + printf("Unknown input parameter\n"); + } + } + + file.close(); + + return SUCCESS; +} + +/*============================================================================= + | + | Description: Parse terrain file + | + | Input: terrain_file - Path to file containing PFL + | + | Output: pfl - PFL array + | + | Returns: [void] + | + *===========================================================================*/ +void ParseTerrainFile(const char* terrain_file, vector* pfl) { + ifstream file; + file.open(terrain_file); + string line; + getline(file, line); + + int i_start, i_end; + + i_end = line.find(","); + int np = ::atoi((line.substr(0, i_end)).c_str()); + + pfl->push_back(np); + + for (int i = 0; i < np + 1; i++) { + i_start = i_end + 1; + + i_end = line.find(",", i_start); + + pfl->push_back(::atof((line.substr(i_start, i_end)).c_str())); + } + + i_start = i_end + 1; + pfl->push_back(::atof((line.substr(i_start)).c_str())); + + file.close(); +} + +/*============================================================================= + | + | Description: Validate P2P input parameters. This function only validates + | that required parameters are present - not that they are + | valid values. The ITM DLL performs validation to ensure + | the parameters are within valid range. + | + | Input: p2p_params - P2P input parameter struct + | + | Output: [void] + | + | Returns: rtn - Return error code + | + *===========================================================================*/ +int ValidateP2PInputs(P2PParams* p2p_params) { + if (p2p_params->h_tx__meter == NOT_SET) + return Validate_RequiredErrMsgHelper(TAG__HTX, DRVRERR__VALIDATION_HTX); + + if (p2p_params->h_rx__meter == NOT_SET) + return Validate_RequiredErrMsgHelper(TAG__HRX, DRVRERR__VALIDATION_HTX); + + if (p2p_params->climate == NOT_SET) + return Validate_RequiredErrMsgHelper(TAG__CLIMATE, DRVRERR__VALIDATION_CLIMATE); + + if (p2p_params->N_0 == NOT_SET) + return Validate_RequiredErrMsgHelper(TAG__N0, DRVRERR__VALIDATION_N0); + + if (p2p_params->f__mhz == NOT_SET) + return Validate_RequiredErrMsgHelper(TAG__FREQ, DRVRERR__VALIDATION_FMHZ); + + if (p2p_params->pol == NOT_SET) + return Validate_RequiredErrMsgHelper(TAG__POL, DRVRERR__VALIDATION_POL); + + if (p2p_params->epsilon == NOT_SET) + return Validate_RequiredErrMsgHelper(TAG__EPSILON, DRVRERR__VALIDATION_EPSILON); + + if (p2p_params->sigma == NOT_SET) + return Validate_RequiredErrMsgHelper(TAG__SIGMA, DRVRERR__VALIDATION_SIGMA); + + if (p2p_params->mdvar == NOT_SET) + return Validate_RequiredErrMsgHelper(TAG__MDVAR, DRVRERR__VALIDATION_MDVAR); + + // infer TLS vs CR calling + bool isTLS = (p2p_params->time != NOT_SET && p2p_params->location != NOT_SET && p2p_params->situation != NOT_SET); + bool isCR = (p2p_params->confidence.size() > 0 && p2p_params->reliability.size() > 0); + + if (isTLS && isCR) + return GeneralErrorMsgHelper("Provided both time/location/situation parameters and confidence/reliability", DRVRERR__VALIDATION_TLS_AND_CR); + + if (!isTLS && !isCR) + return GeneralErrorMsgHelper("Must provide time/location/situation parameters or confidence/reliability", DRVRERR__VALIDATION_TLS_OR_CR); + + if (isTLS) + p2p_params->mode = VARY_TLS; + else + p2p_params->mode = VARY_CR; + + return SUCCESS; +} + +/*============================================================================= + | + | Description: Write P2P inputs to the report file + | + | Input: fp - File pointer + | p2p_params - P2P input parameter struct + | + | Output: [void] + | + | Returns: [void] + | + *===========================================================================*/ +void WriteP2PInputs(FILE* fp, P2PParams* p2p_params) { + fprintf_s(fp, "%-24s %-12.2g %s\n", TAG__HTX, p2p_params->h_tx__meter, UNITS__METER); + fprintf_s(fp, "%-24s %-12.2g %s\n", TAG__HRX, p2p_params->h_rx__meter, UNITS__METER); + fprintf_s(fp, "%-24s %-12i ", TAG__CLIMATE, p2p_params->climate); + PrintClimateLabel(fp, p2p_params->climate); + fprintf_s(fp, "%-24s %-12.2f %s\n", TAG__N0, p2p_params->N_0, UNITS__NUNIT); + fprintf_s(fp, "%-24s %-12.2f %s\n", TAG__FREQ, p2p_params->f__mhz, UNITS__MHZ); + fprintf_s(fp, "%-24s %-12i ", TAG__POL, p2p_params->pol); + PrintPolarizationLabel(fp, p2p_params->pol); + fprintf_s(fp, "%-24s %.2g\n", TAG__EPSILON, p2p_params->epsilon); + fprintf_s(fp, "%-24s %.2g\n", TAG__SIGMA, p2p_params->sigma); + fprintf_s(fp, "%-24s %-12i ", TAG__MDVAR, p2p_params->mdvar); + PrintMdvarLabel(fp, p2p_params->mdvar); + if (p2p_params->mode == VARY_TLS) { + fprintf_s(fp, "%-24s %.2g\n", TAG__TIME, p2p_params->time); + fprintf_s(fp, "%-24s %.2g\n", TAG__LOCATION, p2p_params->location); + fprintf_s(fp, "%-24s %.2g\n", TAG__SITUATION, p2p_params->situation); + } + else { + fprintf_s(fp, "%-24s ", TAG__CONFIDENCE); + for (int i = 0; i < p2p_params->confidence.size() - 1; i++) { + fprintf_s(fp, "%.2g,", p2p_params->confidence[i]); + } + fprintf_s(fp, "%.2g\n", p2p_params->confidence.back()); + + fprintf_s(fp, "%-24s ", TAG__RELIABILITY); + for (int i = 0; i < p2p_params->reliability.size() - 1; i++) { + fprintf_s(fp, "%.2g,", p2p_params->reliability[i]); + } + fprintf_s(fp, "%.2g\n", p2p_params->reliability.back()); + } +} diff --git a/win32/ITMDrvr/PointToPointMode.h b/win32/ITMDrvr/PointToPointMode.h new file mode 100644 index 0000000..574d486 --- /dev/null +++ b/win32/ITMDrvr/PointToPointMode.h @@ -0,0 +1,11 @@ + + +// +// FUNCTIONS +/////////////////////////////////////////////// +int ParseP2PInputFile(const char* in_file, P2PParams *p2p_params); +int ValidateP2PInputs(P2PParams* p2p_params); +int CallP2PMode(DrvrParams* params, P2PParams* p2p_params, IntermediateValues* inter_vals, vector* A__db, long* warnings); +void WriteP2PInputs(FILE* fp, P2PParams* p2p_params); +int LoadP2PFunctions(HINSTANCE hLib); +void ParseTerrainFile(const char* terrain_file, vector* pfl); diff --git a/win32/ITMDrvr/Reporting.cpp b/win32/ITMDrvr/Reporting.cpp new file mode 100644 index 0000000..e411a9c --- /dev/null +++ b/win32/ITMDrvr/Reporting.cpp @@ -0,0 +1,307 @@ +#include "Reporting.h" +#include "Labels.h" +#include "..\..\include\Enums.h" +#include "..\..\include\Errors.h" +#include "..\..\include\Warnings.h" + +bool need_buffer = false; + +/*============================================================================= + | + | Description: Print text messages corresponding to any warning flags + | + | Input: fp - File pointer + | warnings - Warning flags + | + | Output: [void] + | + | Returns: [void] + | + *===========================================================================*/ +void PrintWarningMessages(FILE* fp, long warnings) { + if (warnings == 0) { + PrintLabel(fp, LBL__NO_WARNINGS); + } + else { + if (warnings & WARN__TX_TERMINAL_HEIGHT) PrintWarningHelper(fp, LBL__WARN_TX_TERMINAL_HEIGHT); + if (warnings & WARN__RX_TERMINAL_HEIGHT) PrintWarningHelper(fp, LBL__WARN_RX_TERMINAL_HEIGHT); + if (warnings & WARN__FREQUENCY) PrintWarningHelper(fp, LBL__WARN_FREQUENCY); + if (warnings & WARN__PATH_DISTANCE_TOO_BIG_1) PrintWarningHelper(fp, LBL__WARN_PATH_DISTANCE_TOO_BIG_1); + if (warnings & WARN__PATH_DISTANCE_TOO_BIG_2) PrintWarningHelper(fp, LBL__WARN_PATH_DISTANCE_TOO_BIG_2); + if (warnings & WARN__PATH_DISTANCE_TOO_SMALL_1) PrintWarningHelper(fp, LBL__WARN_PATH_DISTANCE_TOO_SMALL_1); + if (warnings & WARN__PATH_DISTANCE_TOO_SMALL_2) PrintWarningHelper(fp, LBL__WARN_PATH_DISTANCE_TOO_SMALL_2); + if (warnings & WARN__TX_HORIZON_ANGLE) PrintWarningHelper(fp, LBL__WARN_TX_HORIZON_ANGLE); + if (warnings & WARN__RX_HORIZON_ANGLE) PrintWarningHelper(fp, LBL__WARN_RX_HORIZON_ANGLE); + if (warnings & WARN__TX_HORIZON_DISTANCE_1) PrintWarningHelper(fp, LBL__WARN_TX_HORIZON_DISTANCE_1); + if (warnings & WARN__RX_HORIZON_DISTANCE_1) PrintWarningHelper(fp, LBL__WARN_RX_HORIZON_DISTANCE_1); + if (warnings & WARN__TX_HORIZON_DISTANCE_2) PrintWarningHelper(fp, LBL__WARN_TX_HORIZON_DISTANCE_2); + if (warnings & WARN__RX_HORIZON_DISTANCE_2) PrintWarningHelper(fp, LBL__WARN_RX_HORIZON_DISTANCE_2); + if (warnings & WARN__EXTREME_VARIABILITIES) PrintWarningHelper(fp, LBL__WARN_EXTREME_VARIABILITIES); + if (warnings & WARN__SURFACE_REFRACTIVITY) PrintWarningHelper(fp, LBL__WARN_SURFACE_REFRACTIVITY); + } +} + +/*============================================================================= + | + | Description: Formatting helper function for the printing text messages + | corresponding to any warning flags + | + | Input: fp - File pointer + | lbl - Warning flag text message + | + | Output: [void] + | + | Returns: [void] + | + *===========================================================================*/ +void PrintWarningHelper(FILE* fp, const char* lbl) { + if (need_buffer) { + fprintf_s(fp, " "); + } + need_buffer = true; + + PrintLabel(fp, lbl); +} + +/*============================================================================= + | + | Description: Print text message corresponding to radio climate value + | + | Input: fp - File pointer + | climate - Radio climate + | + | Output: [void] + | + | Returns: [void] + | + *===========================================================================*/ +void PrintClimateLabel(FILE* fp, int climate) { + switch (climate) { + case CLIMATE__EQUATORIAL: + PrintLabel(fp, LBL__CLIMATE_EQUATORIAL); + break; + case CLIMATE__CONTINENTAL_SUBTROPICAL: + PrintLabel(fp, LBL__CLIMATE_CONTINENTAL_SUBTROPICAL); + break; + case CLIMATE__MARITIME_SUBTROPICAL: + PrintLabel(fp, LBL__CLIMATE_MARITIME_SUBTROPICAL); + break; + case CLIMATE__DESERT: + PrintLabel(fp, LBL__CLIMATE_DESERT); + break; + case CLIMATE__CONTINENTAL_TEMPERATE: + PrintLabel(fp, LBL__CLIMATE_CONTINENTAL_TEMPERATE); + break; + case CLIMATE__MARITIME_TEMPERATE_OVER_LAND: + PrintLabel(fp, LBL__CLIMATE_MARITIME_TEMPERATE_OVER_LAND); + break; + case CLIMATE__MARITIME_TEMPERATE_OVER_SEA: + PrintLabel(fp, LBL__CLIMATE_MARITIME_TEMPERATE_OVER_SEA); + break; + default: + PrintLabel(fp, LBL__ERROR_INVALID_VALUE); + break; + } +} + +/*============================================================================= + | + | Description: Print text message corresponding to TX siting criteria value + | + | Input: fp - File pointer + | tx_siting_criteria - TX siting criteria + | + | Output: [void] + | + | Returns: [void] + | + *===========================================================================*/ +void PrintSitingCriteriaLabel(FILE* fp, int tx_siting_criteria) { + switch (tx_siting_criteria) + { + case SITING_CRITERIA__RANDOM: + PrintLabel(fp, LBL__SITING_CRITERIA_RANDOM); + break; + case SITING_CRITERIA__CAREFUL: + PrintLabel(fp, LBL__SITING_CRITERIA_CAREFUL); + break; + case SITING_CRITERIA__VERY_CAREFUL: + PrintLabel(fp, LBL__SITING_CRITERIA_VERY_CAREFUL); + break; + default: + PrintLabel(fp, LBL__ERROR_INVALID_VALUE); + break; + } +} + +/*============================================================================= + | + | Description: Print text message corresponding to polarization value + | + | Input: fp - File pointer + | pol - Polarization + | + | Output: [void] + | + | Returns: [void] + | + *===========================================================================*/ +void PrintPolarizationLabel(FILE* fp, int pol) { + switch (pol) { + case POLARIZATION__HORIZONTAL: + PrintLabel(fp, LBL__POLARIZATION_HORIZONTAL); + break; + case POLARIZATION__VERTICAL: + PrintLabel(fp, LBL__POLARIZATION_VERTICAL); + break; + default: + PrintLabel(fp, LBL__ERROR_INVALID_VALUE); + break; + } +} + +/*============================================================================= + | + | Description: Print text message corresponding to mdvar value + | + | Input: fp - File pointer + | mdvar - Mode of variability + | + | Output: [void] + | + | Returns: [void] + | + *===========================================================================*/ +void PrintMdvarLabel(FILE* fp, int mdvar) { + if (mdvar >= 20) { + mdvar -= 20; + } + + if (mdvar >= 10) { + mdvar -= 10; + } + + switch (mdvar) { + case MDVAR__SINGLE_MESSAGE_MODE: + PrintLabel(fp, LBL__MDVAR_SINGLE_MESSAGE_MODE); + break; + case MDVAR__ACCIDENTAL_MODE: + PrintLabel(fp, LBL__MDVAR_ACCIDENTAL_MODE); + break; + case MDVAR__MOBILE_MODE: + PrintLabel(fp, LBL__MDVAR_MOBILE_MODE); + break; + case MDVAR__BROADCAST_MODE: + PrintLabel(fp, LBL__MDVAR_BROADCAST_MODE); + break; + default: + PrintLabel(fp, LBL__ERROR_INVALID_VALUE); + break; + } +} + +/*============================================================================= + | + | Description: Print text message corresponding error codes + | + | Input: fp - File pointer + | err - Error code + | + | Output: [void] + | + | Returns: [void] + | + *===========================================================================*/ +void PrintErrorMsgLabel(FILE* fp, int err) { + switch (err) + { + case SUCCESS: + PrintLabel(fp, LBL__SUCCESS); + break; + case SUCCESS_WITH_WARNINGS: + PrintLabel(fp, LBL__SUCCESS_WITH_WARNINGS); + break; + case ERROR__TX_TERMINAL_HEIGHT: + PrintLabel(fp, LBL__ERROR_TX_TERMINAL_HEIGHT); + break; + case ERROR__RX_TERMINAL_HEIGHT: + PrintLabel(fp, LBL__ERROR_RX_TERMINAL_HEIGHT); + break; + case ERROR__INVALID_RADIO_CLIMATE: + PrintLabel(fp, LBL__ERROR_INVALID_RADIO_CLIMATE); + break; + case ERROR__INVALID_TIME: + PrintLabel(fp, LBL__ERROR_INVALID_TIME); + break; + case ERROR__INVALID_LOCATION: + PrintLabel(fp, LBL__ERROR_INVALID_LOCATION); + break; + case ERROR__INVALID_SITUATION: + PrintLabel(fp, LBL__ERROR_INVALID_SITUATION); + break; + case ERROR__INVALID_CONFIDENCE: + PrintLabel(fp, LBL__ERROR_INVALID_CONFIDENCE); + break; + case ERROR__INVALID_RELIABILITY: + PrintLabel(fp, LBL__ERROR_INVALID_RELIABILITY); + break; + case ERROR__REFRACTIVITY: + PrintLabel(fp, LBL__ERROR_REFRACTIVITY); + break; + case ERROR__FREQUENCY: + PrintLabel(fp, LBL__ERROR_FREQUENCY); + break; + case ERROR__POLARIZATION: + PrintLabel(fp, LBL__ERROR_POLARIZATION); + break; + case ERROR__EPSILON: + PrintLabel(fp, LBL__ERROR_EPSILON); + break; + case ERROR__SIGMA: + PrintLabel(fp, LBL__ERROR_SIGMA); + break; + case ERROR__GROUND_IMPEDANCE: + PrintLabel(fp, LBL__ERROR_GROUND_IMPEDANCE); + break; + case ERROR__MDVAR: + PrintLabel(fp, LBL__ERROR_MDVAR); + break; + case ERROR__EFFECTIVE_EARTH: + PrintLabel(fp, LBL__ERROR_EFFECTIVE_EARTH); + break; + case ERROR__PATH_DISTANCE: + PrintLabel(fp, LBL__ERROR_PATH_DISTANCE); + break; + case ERROR__DELTA_H: + PrintLabel(fp, LBL__ERROR_DELTA_H); + break; + case ERROR__TX_SITING_CRITERIA: + PrintLabel(fp, LBL__ERROR_TX_SITING_CRITERIA); + break; + case ERROR__RX_SITING_CRITERIA: + PrintLabel(fp, LBL__ERROR_RX_SITING_CRITERIA); + break; + case ERROR__SURFACE_REFRACTIVITY_SMALL: + PrintLabel(fp, LBL__ERROR_SURFACE_REFRACTIVITY_SMALL); + break; + case ERROR__SURFACE_REFRACTIVITY_LARGE: + PrintLabel(fp, LBL__ERROR_SURFACE_REFRACTIVITY_LARGE); + break; + } +} + +/*============================================================================= +| +| Description: Helper function to standardize printing of text labels to file +| +| Input: fp - File pointer +| lbl - Text message +| +| Output: [void] +| +| Returns: [void] +| +*===========================================================================*/ +void PrintLabel(FILE* fp, const char* lbl) { + fprintf_s(fp, "[%s]\n", lbl); +} \ No newline at end of file diff --git a/win32/ITMDrvr/Reporting.h b/win32/ITMDrvr/Reporting.h new file mode 100644 index 0000000..74255f2 --- /dev/null +++ b/win32/ITMDrvr/Reporting.h @@ -0,0 +1,23 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +// +// FUNCTIONS +/////////////////////////////////////////////// + +void PrintClimateLabel(FILE* fp, int climate); +void PrintPolarizationLabel(FILE* fp, int pol); +void PrintLabel(FILE* fp, const char* lbl); +void PrintErrorMsgLabel(FILE* fp, int err); +void PrintSitingCriteriaLabel(FILE* fp, int tx_siting_criteria); +void PrintWarningMessages(FILE* fp, long warnings); +void PrintWarningHelper(FILE* fp, const char* lbl); +void PrintMdvarLabel(FILE* fp, int mdvar); diff --git a/win32/ITMDrvr/Tags.h b/win32/ITMDrvr/Tags.h new file mode 100644 index 0000000..118f1f3 --- /dev/null +++ b/win32/ITMDrvr/Tags.h @@ -0,0 +1,30 @@ + +// +// INPUT FILE TAGS +/////////////////////////////////////////////// + +#define TAG__HTX "h_tx__meter" +#define TAG__HRX "h_rx__meter" +#define TAG__CLIMATE "climate" +#define TAG__N0 "N_0" +#define TAG__FREQ "f__mhz" +#define TAG__POL "pol" +#define TAG__EPSILON "epsilon" +#define TAG__SIGMA "sigma" +#define TAG__MDVAR "mdvar" +#define TAG__TIME "time" +#define TAG__LOCATION "location" +#define TAG__SITUATION "situation" +#define TAG__CONFIDENCE "confidence" +#define TAG__RELIABILITY "reliability" +#define TAG__TX_SITE "tx_site_criteria" +#define TAG__RX_SITE "rx_site_criteria" +#define TAG__DKM "d__km" +#define TAG__DELTAH "delta_h__meter" + +#define UNITS__METER "(meters)" +#define UNITS__KM "(km)" +#define UNITS__NUNIT "(N-Units)" +#define UNITS__MHZ "(MHz)" +#define UNITS__DB "(dB)" +#define UNITS__MRAD "(mrad)" diff --git a/win32/ITMDrvr/resource.h b/win32/ITMDrvr/resource.h new file mode 100644 index 0000000..a1dfb25 --- /dev/null +++ b/win32/ITMDrvr/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by ITMDrvr.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/win32/itm.sln b/win32/itm.sln new file mode 100644 index 0000000..1ea368f --- /dev/null +++ b/win32/itm.sln @@ -0,0 +1,44 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30413.136 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "itm", "itm\itm.vcxproj", "{97A0B789-BC70-4C1E-988D-4D16A590930B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ITMDrvr", "ITMDrvr\ITMDrvr.vcxproj", "{2E012AE1-2A12-4D6D-9F11-80FCF6AA2DD8}" + ProjectSection(ProjectDependencies) = postProject + {97A0B789-BC70-4C1E-988D-4D16A590930B} = {97A0B789-BC70-4C1E-988D-4D16A590930B} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {97A0B789-BC70-4C1E-988D-4D16A590930B}.Debug|x64.ActiveCfg = Debug|x64 + {97A0B789-BC70-4C1E-988D-4D16A590930B}.Debug|x64.Build.0 = Debug|x64 + {97A0B789-BC70-4C1E-988D-4D16A590930B}.Debug|x86.ActiveCfg = Debug|Win32 + {97A0B789-BC70-4C1E-988D-4D16A590930B}.Debug|x86.Build.0 = Debug|Win32 + {97A0B789-BC70-4C1E-988D-4D16A590930B}.Release|x64.ActiveCfg = Release|x64 + {97A0B789-BC70-4C1E-988D-4D16A590930B}.Release|x64.Build.0 = Release|x64 + {97A0B789-BC70-4C1E-988D-4D16A590930B}.Release|x86.ActiveCfg = Release|Win32 + {97A0B789-BC70-4C1E-988D-4D16A590930B}.Release|x86.Build.0 = Release|Win32 + {2E012AE1-2A12-4D6D-9F11-80FCF6AA2DD8}.Debug|x64.ActiveCfg = Debug|x64 + {2E012AE1-2A12-4D6D-9F11-80FCF6AA2DD8}.Debug|x64.Build.0 = Debug|x64 + {2E012AE1-2A12-4D6D-9F11-80FCF6AA2DD8}.Debug|x86.ActiveCfg = Debug|Win32 + {2E012AE1-2A12-4D6D-9F11-80FCF6AA2DD8}.Debug|x86.Build.0 = Debug|Win32 + {2E012AE1-2A12-4D6D-9F11-80FCF6AA2DD8}.Release|x64.ActiveCfg = Release|x64 + {2E012AE1-2A12-4D6D-9F11-80FCF6AA2DD8}.Release|x64.Build.0 = Release|x64 + {2E012AE1-2A12-4D6D-9F11-80FCF6AA2DD8}.Release|x86.ActiveCfg = Release|Win32 + {2E012AE1-2A12-4D6D-9F11-80FCF6AA2DD8}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {21FE1AD0-B7BA-4E67-B3AB-8CDBEA7D2DA7} + EndGlobalSection +EndGlobal diff --git a/win32/itm/itm.def b/win32/itm/itm.def new file mode 100644 index 0000000..49ec055 --- /dev/null +++ b/win32/itm/itm.def @@ -0,0 +1,10 @@ +LIBRARY +EXPORTS + ITM_P2P_TLS + ITM_P2P_TLS_Ex + ITM_P2P_CR + ITM_P2P_CR_Ex + ITM_AREA_TLS + ITM_AREA_TLS_Ex + ITM_AREA_CR + ITM_AREA_CR_Ex \ No newline at end of file diff --git a/win32/itm/itm.rc b/win32/itm/itm.rc new file mode 100644 index 0000000..fe21c9d --- /dev/null +++ b/win32/itm/itm.rc @@ -0,0 +1,99 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,3,0,0 + PRODUCTVERSION 1,3,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "The Institute for Telecommunication Sciences" + VALUE "FileDescription", "Irregular Terrain Model (ITM)" + VALUE "FileVersion", "1.3.0.0" + VALUE "InternalName", "itm.dll" + VALUE "OriginalFilename", "itm.dll" + VALUE "ProductName", "Irregular Terrain Model (ITM)" + VALUE "ProductVersion", "1.3.0.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/win32/itm/itm.vcxproj b/win32/itm/itm.vcxproj new file mode 100644 index 0000000..0c5ebef --- /dev/null +++ b/win32/itm/itm.vcxproj @@ -0,0 +1,214 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 16.0 + Win32Proj + {97a0b789-bc70-4c1e-988d-4d16a590930b} + itm + 10.0 + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)..\bin\x86\$(Configuration)\ + + + false + $(SolutionDir)..\bin\x86\$(Configuration)\ + + + true + $(SolutionDir)..\bin\x64\$(Configuration)\ + + + false + $(SolutionDir)..\bin\x64\$(Configuration)\ + + + + Level3 + true + WIN32;_DEBUG;ITM_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + + + MultiThreadedDebug + StdCall + + + Windows + true + false + itm.def + + + + + Level3 + true + true + true + WIN32;NDEBUG;ITM_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + + + MultiThreaded + StdCall + + + Windows + true + true + true + false + itm.def + + + + + Level3 + true + _DEBUG;ITM_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + + + MultiThreadedDebug + StdCall + + + Windows + true + false + itm.def + + + + + Level3 + true + true + true + NDEBUG;ITM_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + + + MultiThreaded + StdCall + + + Windows + true + true + true + false + itm.def + + + + + + \ No newline at end of file diff --git a/win32/itm/itm.vcxproj.filters b/win32/itm/itm.vcxproj.filters new file mode 100644 index 0000000..076a913 --- /dev/null +++ b/win32/itm/itm.vcxproj.filters @@ -0,0 +1,112 @@ + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Resource Files + + + + + {1675474d-f084-486c-95c0-c16dce95b0d7} + + + {22edb284-a3a2-494c-8a0d-31e4d3efbdb5} + + + {da86b266-2685-417a-8605-c829f8c094a8} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Resource Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/win32/itm/resource.h b/win32/itm/resource.h new file mode 100644 index 0000000..e6320fd --- /dev/null +++ b/win32/itm/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by itm.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif