├── .github └── workflows │ └── ci.yaml ├── .gitignore ├── LICENSE ├── README.md ├── dev ├── changelog.md ├── devops │ ├── .gitignore │ └── build-and-package.bat ├── grabber.png ├── icon │ ├── fskview-icon-16.png │ ├── fskview-icon-256.png │ ├── fskview-icon-32.png │ ├── fskview-icon-48.png │ ├── fskview-icon.ico │ └── fskview-icon.svg ├── readme.md ├── screenshot.png ├── simulation │ ├── colormap-grayscale.png │ ├── colormap-viridis.png │ └── simulation.png └── wspr-logs │ ├── ALL_WSPR_JTDX_2200mtrs.TXT │ ├── ALL_WSPR_JTDX_40mtrs.TXT │ ├── ALL_WSPR_JTDX_630mtrs.TXT │ ├── ALL_WSPR_WSJT-X_2200mtrs.TXT │ ├── ALL_WSPR_WSJT-X_40mtrs.TXT │ ├── ALL_WSPR_WSJT-X_630mtrs.TXT │ ├── jtdx-all-wspr-K3SIW.TXT │ ├── wsjtx-2.1.2-pa2ohh.txt │ ├── wsjtx-2.2.2-aj4vd.txt │ ├── wsjtx-2.2.2-df2jp.txt │ ├── wsjtx-2.2.2-nl9222.TXT │ ├── wsjtxFT-2.2.2-k4rcg.txt │ └── wspr-df2jp.txt └── src ├── FSKview.Tests ├── FSKview.Tests.csproj ├── Properties │ └── AssemblyInfo.cs ├── WsprLogFile.cs └── packages.config ├── FSKview.sln └── FSKview ├── AGC.cs ├── Annotate.cs ├── App.config ├── AudioControl.Designer.cs ├── AudioControl.cs ├── AudioControl.resx ├── FSKview.csproj ├── FTP.cs ├── FormMain.Designer.cs ├── FormMain.cs ├── FormMain.resx ├── FormSettings.Designer.cs ├── FormSettings.cs ├── FormSettings.resx ├── Listener.cs ├── Program.cs ├── ProgramSettings.cs ├── Ruler.cs ├── WsprBand.cs ├── WsprBands.cs ├── WsprLogFile.cs ├── WsprSpot.cs ├── fskview-icon.ico └── packages.config /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - master 8 | pull_request: 9 | types: [opened, synchronize, reopened] 10 | 11 | jobs: 12 | test: 13 | name: Test 14 | runs-on: windows-latest 15 | defaults: 16 | run: 17 | working-directory: ./src 18 | steps: 19 | - name: 🛒 Checkout 20 | uses: actions/checkout@v2 21 | - name: 🐢 Set up MSBuild 22 | uses: microsoft/setup-msbuild@v1.1 23 | - name: ✨ Setup .NET 5 24 | uses: actions/setup-dotnet@v1 25 | with: 26 | dotnet-version: "5.0.x" 27 | - name: ✨ Setup .NET 6 28 | uses: actions/setup-dotnet@v1 29 | with: 30 | dotnet-version: "6.0.x" 31 | - name: 🚚 Restore 32 | run: dotnet restore 33 | - name: 🛠️ Build 34 | run: dotnet build 35 | - name: 🧪 Test 36 | run: dotnet test 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ 351 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Scott W Harden 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FSKview 2 | [![CI](https://github.com/swharden/FSKview/actions/workflows/ci.yaml/badge.svg)](https://github.com/swharden/FSKview/actions/workflows/ci.yaml) 3 | 4 | **FSKview is a Windows application for generating high-resolution spectrograms** of audio data to facilitate viewing frequency-shift keyed (FSK) signals in real time. 5 | 6 | ![](dev/screenshot.png) 7 | 8 | **Download for Windows:** https://swharden.com/software/FSKview -------------------------------------------------------------------------------- /dev/changelog.md: -------------------------------------------------------------------------------- 1 | * [FSKview 1.3.0](downloads) 2 | * Improved compatibility with older versions of Windows 3 | * [FSKview-1.2.0.zip](downloads/FSKview-1.1.7.zip) 4 | * Improved support for display scaling 5 | * Added option to mark minutes with vertical lines 6 | * [FSKview-1.1.7.zip](downloads/FSKview-1.1.7.zip) 7 | * Built to use the .NET Framework 4.7.2 runtime 8 | * Improved spectral AGC 9 | * Added option to customize AGC power 10 | * [FSKview-1.1.6.zip](downloads/FSKview-1.1.6.zip) 11 | * Improved spectral AGC symmetry 12 | * [FSKview-1.1.5.zip](downloads/FSKview-1.1.5.zip) 13 | * Added experimental spectral normalization AGC option 14 | * FT4/FT8 dial frequencies are now hidden by default 15 | * [FSKview-1.1.4.zip](downloads/FSKview-1.1.4.zip) 16 | * FT4/FT8 spot labels are now placed directly on the spot 17 | * [FSKview-1.1.3.zip](downloads/FSKview-1.1.3.zip) 18 | * FT4/FT8 spots now display full message 19 | * [FSKview-1.1.2.zip](downloads/FSKview-1.1.2.zip) 20 | * additional options for vertical compression 21 | * [FSKview-1.1.0.zip](downloads/FSKview-1.1.0.zip) 22 | * corrected 160m WSPR dial frequency 23 | * [FSKview-1.0.10.zip](downloads/FSKview-1.0.10.zip) 24 | * improved alignment for FT4/FT8 spots 25 | * improved support for systems where language settings do not treat a period as decimal separator 26 | * [FSKview-1.0.9.zip](downloads/FSKview-1.0.9.zip) 27 | * improved frequency labeling of FT4/FT8 spots WSJT-X logs 28 | * [FSKview-1.0.8.zip](downloads/FSKview-1.0.8.zip) 29 | * added support for WSJT-X logs containing FT4/FT8 spots 30 | * improved parsing of WSPR logs from different programs 31 | * fix bug introduced in 1.0.7 that truncated 7-character callsigns 32 | * log parsing errors fail silently (rather than launching an error message) 33 | * [FSKview-1.0.7.zip](downloads/FSKview-1.0.7.zip) 34 | * support multiple WSPR log formats (classical WSPR, WSJT-X 2.1.2, and WSJT-X 2.2.2) 35 | * recall brightness on startup 36 | * [FSKview-1.0.6.zip](downloads/FSKview-1.0.6.zip) 37 | * saved images now display 1-minute time ticks 38 | * updated 80m WSPR dial frequency 39 | * improved FTP test dialogue 40 | * [FSKview-1.0.5c.zip](downloads/FSKview-1.0.5c.zip) 41 | * Spectrogram width and saved image height is customizable 42 | * Integrated FTP uploader 43 | * All settings persist through program restarts 44 | * Images saved to the grabs-all folder no longer have a scale bar (useful for stitching) 45 | * Display now has a "scroll" option as an alternative to the scroll/wipe behavior 46 | * Only in-band WSPR spots are shown (useful if frequency hopping) 47 | * Frequency offset adjustment for fine-tuning calibration 48 | * [FSKview-1.0.4c.zip](downloads/FSKview-1.0.4c.zip) 49 | * Increased autosave image resolution from 930x670 to 1130x914 50 | * [FSKview-1.0.4b.zip](downloads/FSKview-1.0.4b.zip) 51 | * More informative error messages 52 | * Improved support for FTP server address 53 | * Added .jpg to default list of images files (previously only .jpeg) 54 | * [FSKview-1.0.4.zip](downloads/FSKview-1.0.4.zip) 55 | * New option to customize autosave filename 56 | * Remove seconds from UTC timestamp on saved grabs 57 | * [FSKview-1.0.3.zip](downloads/FSKview-1.0.3.zip) 58 | * Improved time alignment 59 | * FTP Uploader produces quieter error messages 60 | * [FSKview-1.0.2.zip](downloads/FSKview-1.0.2.zip) 61 | * Fixed bug that stopped Spectrogram when switching audio devices 62 | * [FSKview-1.0.1.zip](downloads/FSKview-1.0.1.zip) 63 | * Improved colormaps 64 | * [FSKview-1.0.0.zip](downloads/FSKview-1.0.0.zip) 65 | * Initial release -------------------------------------------------------------------------------- /dev/devops/.gitignore: -------------------------------------------------------------------------------- 1 | *.zip -------------------------------------------------------------------------------- /dev/devops/build-and-package.bat: -------------------------------------------------------------------------------- 1 | if exist ..\..\src\FSKview\bin rmdir /s /q ..\..\src\FSKview\bin 2 | 3 | dotnet build --configuration Release ..\..\src\FSKview 4 | 5 | move ..\..\src\FSKview\bin\Release\net6.0-windows ..\..\src\FSKview\bin\Release\FSKview-win10 6 | move ..\..\src\FSKview\bin\Release\net48 ..\..\src\FSKview\bin\Release\FSKview-win7 7 | 8 | powershell "Compress-Archive -Force ..\..\src\FSKview\bin\Release\FSKview-win10 FSKview-VERSION-win10.zip" 9 | powershell "Compress-Archive -Force ..\..\src\FSKview\bin\Release\FSKview-win7 FSKview-VERSION-win7.zip" 10 | 11 | pause -------------------------------------------------------------------------------- /dev/grabber.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swharden/FSKview/75e85a8a497ba8dd5c5ef8beea1bf170bfedc1af/dev/grabber.png -------------------------------------------------------------------------------- /dev/icon/fskview-icon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swharden/FSKview/75e85a8a497ba8dd5c5ef8beea1bf170bfedc1af/dev/icon/fskview-icon-16.png -------------------------------------------------------------------------------- /dev/icon/fskview-icon-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swharden/FSKview/75e85a8a497ba8dd5c5ef8beea1bf170bfedc1af/dev/icon/fskview-icon-256.png -------------------------------------------------------------------------------- /dev/icon/fskview-icon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swharden/FSKview/75e85a8a497ba8dd5c5ef8beea1bf170bfedc1af/dev/icon/fskview-icon-32.png -------------------------------------------------------------------------------- /dev/icon/fskview-icon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swharden/FSKview/75e85a8a497ba8dd5c5ef8beea1bf170bfedc1af/dev/icon/fskview-icon-48.png -------------------------------------------------------------------------------- /dev/icon/fskview-icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swharden/FSKview/75e85a8a497ba8dd5c5ef8beea1bf170bfedc1af/dev/icon/fskview-icon.ico -------------------------------------------------------------------------------- /dev/icon/fskview-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 20 | 22 | 42 | 45 | 46 | 48 | 49 | 51 | image/svg+xml 52 | 54 | 55 | 56 | 57 | 58 | 62 | 66 | 73 | 78 | 79 | FSK 90 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /dev/readme.md: -------------------------------------------------------------------------------- 1 | ## Simulating QRSS Data 2 | 3 | Sample 10-minute recordings were generated with normally distributed noise and sine waves (of increasing SNR) were added near 1400 Hz (15-second squares, 5-second squares, and 15-second ramps, all 5 Hz high) and the signal was analyzed to produce spectrograms. 4 | 5 | Many ideas here came from PA2OHH's [Simulation of QRSS Signals](https://www.qsl.net/pa2ohh/12qrsssim1.htm). 6 | 7 | Unless otherwise stated examples use these parameters: 8 | 9 | ``` 10 | Spectrogram: 9.97 minutes 11 | FFT: 16,384 points 12 | Height: 177 px (0.37 Hz / px) 13 | Width: 1000 (0.60 sec / px) 14 | View: 1,370 Hz to 1,435 Hz 15 | ``` 16 | 17 | ### Colormap Comparison 18 | 19 | #### Grayscale 20 | ![](simulation/colormap-grayscale.png) 21 | 22 | #### Viridis 23 | ![](simulation/colormap-viridis.png) 24 | -------------------------------------------------------------------------------- /dev/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swharden/FSKview/75e85a8a497ba8dd5c5ef8beea1bf170bfedc1af/dev/screenshot.png -------------------------------------------------------------------------------- /dev/simulation/colormap-grayscale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swharden/FSKview/75e85a8a497ba8dd5c5ef8beea1bf170bfedc1af/dev/simulation/colormap-grayscale.png -------------------------------------------------------------------------------- /dev/simulation/colormap-viridis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swharden/FSKview/75e85a8a497ba8dd5c5ef8beea1bf170bfedc1af/dev/simulation/colormap-viridis.png -------------------------------------------------------------------------------- /dev/simulation/simulation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swharden/FSKview/75e85a8a497ba8dd5c5ef8beea1bf170bfedc1af/dev/simulation/simulation.png -------------------------------------------------------------------------------- /dev/wspr-logs/ALL_WSPR_JTDX_2200mtrs.TXT: -------------------------------------------------------------------------------- 1 | 200801 0624 2 -22 0.28 0.1375751 WH2XND DM33 43 0 1 0 1 331 0 2 | 200801 0632 3 -21 0.32 0.1375751 WH2XND DM33 43 0 1 0 1 402 0 3 | 200801 0640 2 -23 0.37 0.1375752 WH2XND DM33 43 0 8 0 1 304 0 4 | 200801 0648 2 -23 0.24 0.1375752 WH2XND DM33 43 0 83 0 1 3 0 5 | 200801 0656 2 -22 0.32 0.1375752 WH2XND DM33 43 0 1 0 1 71 0 6 | 200801 0700 2 -23 0.32 0.1375751 WH2XND DM33 43 0 3 0 1 165 0 7 | 200801 0708 2 -24 0.32 0.1375752 WH2XND DM33 43 0 6 0 1 191 0 8 | 200801 0716 3 -20 0.37 0.1375752 WH2XND DM33 43 0 1 0 1 514 0 9 | 200801 0724 3 -16 0.28 0.1375752 WH2XND DM33 43 0 1 0 1 531 0 10 | 200801 0732 3 -18 0.28 0.1375751 WH2XND DM33 43 0 1 0 1 455 0 11 | 200801 0740 3 -19 0.28 0.1375751 WH2XND DM33 43 0 1 0 1 558 0 12 | 200801 0748 2 -19 0.28 0.1375752 WH2XND DM33 43 0 2 0 1 290 0 13 | 200801 0756 1 -21 0.32 0.1375752 WH2XND DM33 43 0 42 0 1 46 0 14 | 200801 0800 2 -24 0.41 0.1375752 WH2XND DM33 43 0 209 0 1 -61 0 15 | 200801 0808 1 -27 0.28 0.1375751 WH2XND DM33 43 0 1 48 1 810 1 16 | 200801 0824 2 -22 0.41 0.1375752 WH2XND DM33 43 0 2 0 1 220 0 17 | 200801 0832 2 -21 0.37 0.1375751 WH2XND DM33 43 0 1 0 1 239 0 18 | 200801 0840 2 -22 0.41 0.1375752 WH2XND DM33 43 0 2 0 1 175 0 19 | 200801 0848 3 -21 0.32 0.1375751 WH2XND DM33 43 0 1 0 1 366 0 20 | 200801 0856 2 -21 0.32 0.1375751 WH2XND DM33 43 0 1 0 1 439 0 21 | 200801 0900 2 -22 0.32 0.1375751 WH2XND DM33 43 0 1 0 1 322 0 22 | 200801 0916 4 -16 0.32 0.1375751 WH2XND DM33 43 0 1 0 1 622 0 23 | 200801 0924 3 -20 0.37 0.1375752 WH2XND DM33 43 0 1 0 1 491 0 24 | 200801 0932 3 -20 0.37 0.1375751 WH2XND DM33 43 0 9 0 1 386 0 25 | 200801 0948 3 -19 0.32 0.1375751 WH2XND DM33 43 0 1 0 1 389 0 26 | 200801 0956 2 -24 0.32 0.1375752 WH2XND DM33 43 0 1 0 1 181 0 27 | 200801 1000 3 -19 0.28 0.1375751 WH2XND DM33 43 0 1 0 1 429 0 28 | 200801 1008 2 -18 0.32 0.1375752 WH2XND DM33 43 0 15 0 1 326 0 29 | 200801 1016 3 -17 0.28 0.1375751 WH2XND DM33 43 0 1 0 1 563 0 30 | 200801 1024 3 -18 0.32 0.1375751 WH2XND DM33 43 0 1 0 1 485 0 31 | 200801 1032 3 -17 0.32 0.1375752 WH2XND DM33 43 0 1 0 1 483 0 32 | 200801 1040 4 -15 0.28 0.1375752 WH2XND DM33 43 0 1 0 1 597 0 33 | 200801 1048 5 -11 0.32 0.1375751 WH2XND DM33 43 0 1 0 1 673 0 34 | 200801 1056 5 -12 0.28 0.1375752 WH2XND DM33 43 0 1 0 1 664 0 35 | 200801 1100 5 -16 0.28 0.1375751 WH2XND DM33 43 0 1 0 1 652 0 36 | 200801 1108 3 -20 0.28 0.1375752 WH2XND DM33 43 0 1 0 1 556 0 37 | 200801 1116 4 -19 0.32 0.1375751 WH2XND DM33 43 0 1 0 1 670 0 38 | 200801 1124 2 -23 0.37 0.1375752 WH2XND DM33 43 0 1 0 1 253 0 39 | 200801 1132 2 -25 0.24 0.1375750 WH2XND DM33 43 0 1 0 1 105 0 40 | -------------------------------------------------------------------------------- /dev/wspr-logs/ALL_WSPR_JTDX_630mtrs.TXT: -------------------------------------------------------------------------------- 1 | 200801 0216 2 -24 0.32 0.4756392 WB3AVN FM19 37 0 1 0 1 471 0 2 | 200801 0216 3 -23 0.41 0.4757244 NV4X EM77 30 -1 1 0 1 374 0 3 | 200801 0220 6 -13 0.41 0.4757191 WD8DAS EN52 30 0 1 0 1 764 0 4 | 200801 0220 2 -26 0.54 0.4757683 AE2EA FN12 23 0 4 0 1 128 0 5 | 200801 0222 1 -27 0.41 0.4757486 KE7A EM12 30 -1 91 0 1 -123 0 6 | 200801 0224 4 -19 -0.83 0.4756710 W7XU EN13 37 0 1 0 1 142 0 7 | 200801 0224 2 -25 0.49 0.4757246 NV4X EM77 30 -1 2 0 1 74 0 8 | 200801 0228 6 -13 0.49 0.4756712 W7XU EN13 37 0 1 0 1 733 0 9 | 200801 0230 6 -6 0.83 0.4755999 KB8U EN71 37 0 1 0 1 621 0 10 | 200801 0230 5 -15 0.37 0.4757192 WD8DAS EN52 30 0 1 0 1 773 0 11 | 200801 0230 1 -30 0.58 0.4757683 AE2EA FN12 23 0 1 -32 1 810 1 12 | 200801 0232 4 -16 0.49 0.4756711 W7XU EN13 37 1 1 0 1 539 0 13 | 200801 0234 2 -26 0.49 0.4757245 NV4X EM77 30 -1 5 0 1 304 0 14 | 200801 0236 6 -9 0.45 0.4756710 W7XU EN13 37 0 1 0 1 606 0 15 | 200801 0240 5 -13 0.83 0.4755999 KB8U EN71 37 0 1 0 1 496 0 16 | 200801 0240 5 -15 0.37 0.4757192 WD8DAS EN52 30 0 1 0 1 724 0 17 | 200801 0240 1 -29 0.49 0.4757482 KE7A EM12 30 -2 1 24 1 810 1 18 | 200801 0240 2 -27 0.45 0.4757682 AE2EA FN12 23 0 31 0 1 -29 0 19 | 200801 0244 2 -26 0.45 0.4757245 NV4X EM77 30 -1 1 0 1 264 0 20 | 200801 0246 5 -10 0.54 0.4756705 W7XU EN13 37 0 1 0 1 742 0 21 | 200801 0248 6 -0 0.83 0.4755999 KB8U EN71 37 0 1 0 1 786 0 22 | 200801 0250 5 -16 0.37 0.4757191 WD8DAS EN52 30 0 1 0 1 725 0 23 | 200801 0250 1 -27 0.37 0.4757680 AE2EA FN12 23 0 1 0 1 810 1 24 | 200801 0254 3 -21 0.45 0.4757245 NV4X EM77 30 -1 1 0 1 695 0 25 | 200801 0256 2 -25 0.45 0.4756276 W3TS FN10 37 -1 2 0 1 205 0 26 | 200801 0256 5 -10 0.45 0.4756705 W7XU EN13 37 0 1 0 1 680 0 27 | 200801 0300 6 -6 0.88 0.4756000 KB8U EN71 37 0 1 0 1 753 0 28 | 200801 0300 6 -8 0.49 0.4756709 W7XU EN13 37 0 1 0 1 722 0 29 | 200801 0300 5 -16 0.37 0.4757192 WD8DAS EN52 30 0 1 0 1 702 0 30 | 200801 0300 1 -27 0.45 0.4757681 AE2EA FN12 23 0 215 0 1 -85 0 31 | 200801 0302 4 -17 0.45 0.4757245 NV4X EM77 30 -1 1 0 1 694 0 32 | 200801 0304 4 -17 0.45 0.4756391 WB3AVN FM19 37 0 1 0 1 670 0 33 | 200801 0304 6 -2 0.49 0.4756709 W7XU EN13 37 0 1 0 1 747 0 34 | 200801 0308 6 -7 0.88 0.4756000 KB8U EN71 37 0 1 0 1 634 0 35 | 200801 0308 2 -25 0.45 0.4757244 NV4X EM77 30 -1 2 0 1 142 0 36 | 200801 0310 3 -20 0.41 0.4756390 WB3AVN FM19 37 0 1 0 1 597 0 37 | 200801 0310 5 -14 0.41 0.4757192 WD8DAS EN52 30 0 1 0 1 723 0 38 | 200801 0310 1 -28 0.41 0.4757680 AE2EA FN12 23 0 1 0 1 810 1 39 | 200801 0314 3 -22 0.45 0.4757244 NV4X EM77 30 -1 1 0 1 481 0 40 | 200801 0316 6 -4 0.83 0.4755999 KB8U EN71 37 0 1 0 1 547 0 41 | 200801 0316 3 -22 0.62 0.4756277 W3TS FN10 37 -1 1 0 1 437 0 42 | 200801 0316 3 -22 0.45 0.4756389 WB3AVN FM19 37 0 1 0 1 555 0 43 | 200801 0320 5 -14 0.41 0.4757191 WD8DAS EN52 30 0 1 0 1 716 0 44 | 200801 0322 2 -24 0.45 0.4757244 NV4X EM77 30 -1 2 0 1 332 0 45 | 200801 0324 6 -1 0.83 0.4755999 KB8U EN71 37 0 1 0 1 730 0 46 | 200801 0324 3 -20 0.45 0.4757378 AA5IT EM20 37 0 1 0 1 609 0 47 | 200801 0326 3 -23 0.41 0.4756390 WB3AVN FM19 37 -1 1 0 1 435 0 48 | 200801 0328 1 -30 0.37 0.4756241 K2BLA EL99 23 0 1 8 2 810 1 49 | 200801 0328 4 -20 0.41 0.4757244 NV4X EM77 30 -1 1 0 1 622 0 50 | 200801 0328 3 -21 0.41 0.4757377 AA5IT EM20 37 0 1 0 1 467 0 51 | 200801 0330 5 -14 0.37 0.4757191 WD8DAS EN52 30 0 1 0 1 680 0 52 | 200801 0330 1 -28 0.45 0.4757488 KE7A EM12 30 -1 5 0 1 103 0 53 | 200801 0332 6 -5 0.83 0.4755999 KB8U EN71 37 0 1 0 1 446 0 54 | 200801 0332 3 -23 0.45 0.4756389 WB3AVN FM19 37 0 1 0 1 354 0 55 | 200801 0332 4 -17 0.49 0.4757376 AA5IT EM20 37 0 1 0 1 687 0 56 | 200801 0334 2 -24 0.54 0.4756279 W3TS FN10 37 -2 1 0 1 314 0 57 | 200801 0334 2 -26 0.41 0.4757245 NV4X EM77 30 -1 1 0 1 158 0 58 | 200801 0336 1 -28 0.45 0.4756240 K2BLA EL99 23 0 1 0 1 810 1 59 | 200801 0338 1 -28 0.49 0.4757221 W0IOO EN10 27 -1 1 -8 1 810 1 60 | 200801 0338 2 -23 0.45 0.4757376 AA5IT EM20 37 0 1 0 1 382 0 61 | 200801 0338 2 -25 0.49 0.4757488 KE7A EM12 30 -1 3 0 1 165 0 62 | 200801 0340 6 -7 0.83 0.4755999 KB8U EN71 37 0 1 0 1 578 0 63 | 200801 0340 4 -17 0.45 0.4756389 WB3AVN FM19 37 0 1 0 1 687 0 64 | 200801 0340 5 -15 0.37 0.4757192 WD8DAS EN52 30 0 1 0 1 709 0 65 | 200801 0344 1 -29 0.37 0.4756241 K2BLA EL99 23 0 1 0 3 810 1 66 | 200801 0344 2 -23 0.32 0.4756277 W3TS FN10 37 -2 15 0 1 114 0 67 | 200801 0344 2 -23 0.49 0.4757246 NV4X EM77 30 -1 1 0 1 459 0 68 | 200801 0350 4 -15 0.37 0.4757192 WD8DAS EN52 30 0 1 0 1 733 0 69 | 200801 0350 2 -24 0.49 0.4757244 NV4X EM77 30 0 1 0 1 273 0 70 | 200801 0350 4 -16 0.45 0.4757373 AA5IT EM20 37 0 1 0 1 695 0 71 | 200801 0350 2 -25 0.37 0.4757683 AE2EA FN12 23 0 2 0 1 209 0 72 | 200801 0352 5 -15 0.92 0.4756000 KB8U EN71 37 0 1 0 1 531 0 73 | 200801 0352 2 -26 0.41 0.4756240 K2BLA EL99 23 0 27 0 1 0 0 74 | 200801 0352 3 -21 0.49 0.4756270 W3TS FN10 37 -2 1 0 1 310 0 75 | 200801 0356 1 -27 0.41 0.4756388 WB3AVN FM19 37 0 1 0 1 810 1 76 | 200801 0356 2 -21 0.45 0.4757242 NV4X EM77 30 0 1 0 1 147 0 77 | 200801 0356 5 -13 0.49 0.4757374 AA5IT EM20 37 0 1 0 1 741 0 78 | 200801 0400 4 -14 0.32 0.4757192 WD8DAS EN52 30 0 1 0 1 685 0 79 | 200801 0400 1 -28 0.45 0.4757681 AE2EA FN12 23 0 1 -8 1 810 1 80 | 200801 0402 4 -16 0.45 0.4757373 AA5IT EM20 37 0 1 0 1 648 0 81 | 200801 0406 3 -19 0.32 0.4756389 WB3AVN FM19 37 0 1 0 1 640 0 82 | 200801 0406 3 -21 0.45 0.4757245 NV4X EM77 30 -1 1 0 1 566 0 83 | 200801 0408 2 -23 0.41 0.4757373 AA5IT EM20 37 0 1 0 1 389 0 84 | 200801 0410 5 -11 0.88 0.4756000 KB8U EN71 37 0 1 0 1 602 0 85 | 200801 0410 5 -14 0.37 0.4757191 WD8DAS EN52 30 0 1 0 1 685 0 86 | 200801 0410 2 -25 0.45 0.4757681 AE2EA FN12 23 0 3 0 1 277 0 87 | 200801 0412 2 -23 0.37 0.4756242 K2BLA EL99 23 0 4 0 1 98 0 88 | 200801 0412 3 -19 0.45 0.4756275 W3TS FN10 37 0 1 0 1 249 0 89 | 200801 0412 3 -22 0.37 0.4757374 AA5IT EM20 37 0 1 0 1 351 0 90 | 200801 0414 4 -15 0.41 0.4757245 NV4X EM77 30 -1 1 0 1 662 0 91 | 200801 0416 4 -18 0.45 0.4756389 WB3AVN FM19 37 0 1 0 1 678 0 92 | 200801 0418 4 -13 0.41 0.4756708 W7XU EN13 37 0 1 0 1 96 0 93 | 200801 0420 5 -8 0.92 0.4756000 KB8U EN71 37 0 1 0 1 516 0 94 | 200801 0420 2 -27 0.45 0.4756241 K2BLA EL99 23 0 989 0 1 -62 0 95 | 200801 0420 5 -14 0.37 0.4757191 WD8DAS EN52 30 0 1 0 1 699 0 96 | 200801 0420 2 -26 0.45 0.4757248 NV4X EM77 30 0 1 0 1 810 1 97 | 200801 0420 2 -26 0.37 0.4757681 AE2EA FN12 23 0 880 0 1 -98 0 98 | 200801 0422 2 -22 0.45 0.4756270 W3TS FN10 37 -1 1 0 1 220 0 99 | 200801 0422 5 -15 0.41 0.4756711 W7XU EN13 37 0 1 0 1 663 0 100 | 200801 0428 6 -10 0.88 0.4755999 KB8U EN71 37 0 1 0 1 488 0 101 | 200801 0428 2 -25 0.45 0.4756241 K2BLA EL99 23 0 1 0 1 249 0 102 | 200801 0428 1 -27 0.32 0.4756389 WB3AVN FM19 37 0 1 32 1 810 1 103 | 200801 0428 3 -24 0.45 0.4757246 NV4X EM77 30 -1 1 0 1 316 0 104 | 200801 0430 5 -14 0.37 0.4757191 WD8DAS EN52 30 0 1 0 1 724 0 105 | 200801 0430 3 -21 0.45 0.4757681 AE2EA FN12 23 0 1 0 1 626 0 106 | 200801 0432 4 -16 0.45 0.4756271 W3TS FN10 37 -1 1 0 1 645 0 107 | 200801 0432 1 -29 0.45 0.4757192 W0IOO EN10 27 -1 1 -8 1 810 1 108 | 200801 0434 4 -18 0.41 0.4756388 WB3AVN FM19 37 0 1 0 1 590 0 109 | 200801 0434 4 -18 0.45 0.4756727 W7XU EN13 37 0 1 0 1 59 0 110 | 200801 0436 2 -22 0.32 0.4756241 K2BLA EL99 23 0 1 0 1 472 0 111 | 200801 0436 1 -29 0.37 0.4757482 KE7A EM12 30 -1 1 8 1 810 1 112 | 200801 0438 6 -9 0.92 0.4756000 KB8U EN71 37 0 1 0 1 636 0 113 | 200801 0438 2 -26 0.41 0.4757245 NV4X EM77 30 -1 1 0 1 177 0 114 | 200801 0438 2 -23 0.37 0.4758030 N8CGY EN74 33 0 55 0 1 -53 0 115 | 200801 0440 5 -14 0.41 0.4757192 WD8DAS EN52 30 0 1 0 1 724 0 116 | 200801 0440 1 -28 0.45 0.4757481 KE7A EM12 30 0 1 -8 1 810 1 117 | 200801 0440 4 -19 0.41 0.4757681 AE2EA FN12 23 0 1 0 1 632 0 118 | 200801 0442 3 -20 0.45 0.4756274 W3TS FN10 37 -1 1 0 1 486 0 119 | 200801 0442 1 -27 0.54 0.4758029 N8CGY EN74 33 0 1 -8 2 810 1 120 | 200801 0444 2 -25 0.41 0.4756241 K2BLA EL99 23 0 1 0 1 400 0 121 | 200801 0444 3 -23 0.49 0.4756389 WB3AVN FM19 37 0 1 0 1 379 0 122 | 200801 0444 5 -14 0.24 0.4756704 W7XU EN13 37 0 1 0 1 520 0 123 | 200801 0448 1 -29 0.45 0.4756942 ZF1EJ EK99 33 0 1 0 1 810 1 124 | 200801 0448 2 -26 0.45 0.4757246 NV4X EM77 30 -1 1 0 1 227 0 125 | 200801 0450 6 -8 0.92 0.4756000 KB8U EN71 37 0 1 0 1 486 0 126 | 200801 0450 2 -25 0.15 0.4756707 W7XU EN13 37 0 1 0 1 294 0 127 | 200801 0450 5 -14 0.37 0.4757191 WD8DAS EN52 30 0 1 0 1 722 0 128 | 200801 0450 1 -27 0.37 0.4757486 KE7A EM12 30 0 23 0 1 106 0 129 | 200801 0450 3 -22 0.45 0.4757681 AE2EA FN12 23 0 1 0 1 512 0 130 | 200801 0450 2 -25 0.37 0.4758029 N8CGY EN74 33 0 829 0 1 -166 0 131 | 200801 0452 1 -26 0.41 0.4756242 K2BLA EL99 23 0 1 0 1 810 1 132 | 200801 0452 1 -28 0.37 0.4757194 W0IOO EN10 27 -1 4302 0 1 -247 0 133 | 200801 0456 2 -24 0.41 0.4756389 WB3AVN FM19 37 0 1 0 1 342 0 134 | 200801 0458 5 -14 0.19 0.4756705 W7XU EN13 37 0 1 0 1 640 0 135 | 200801 0458 4 -20 0.41 0.4757488 KE7A EM12 30 -1 1 0 1 670 0 136 | 200801 0500 6 -3 0.71 0.4756000 KB8U EN71 37 0 1 0 1 632 0 137 | 200801 0500 5 -15 0.15 0.4757192 WD8DAS EN52 30 0 1 0 1 678 0 138 | 200801 0502 1 -26 0.41 0.4758031 N8CGY EN74 33 0 1 0 1 810 1 139 | 200801 0504 6 -9 0.32 0.4756388 WB3AVN FM19 37 0 1 0 1 733 0 140 | 200801 0504 5 -15 0.32 0.4756707 W7XU EN13 37 0 1 0 1 464 0 141 | 200801 0504 2 -26 0.32 0.4757489 KE7A EM12 30 -1 1 0 1 202 0 142 | 200801 0508 4 -20 0.32 0.4757488 KE7A EM12 30 -1 1 0 1 590 0 143 | 200801 0510 5 -13 0.28 0.4756707 W7XU EN13 37 0 1 0 1 641 0 144 | 200801 0510 5 -13 0.28 0.4757192 WD8DAS EN52 30 0 1 0 1 710 0 145 | 200801 0510 1 -26 0.37 0.4757245 NV4X EM77 30 0 1 0 1 810 1 146 | 200801 0510 2 -24 0.45 0.4757681 AE2EA FN12 23 0 1 0 1 371 0 147 | 200801 0512 6 -8 0.88 0.4755999 KB8U EN71 37 0 1 0 1 592 0 148 | 200801 0512 2 -28 0.32 0.4756240 K2BLA EL99 23 0 1 0 1 810 1 149 | 200801 0512 3 -19 0.37 0.4756276 W3TS FN10 37 -2 1 0 1 554 0 150 | 200801 0512 2 -26 0.32 0.4757487 KE7A EM12 30 -1 1 0 1 343 0 151 | 200801 0512 2 -24 0.28 0.4758031 N8CGY EN74 33 0 45 0 1 25 0 152 | 200801 0514 5 -14 0.37 0.4756388 WB3AVN FM19 37 0 1 0 1 715 0 153 | 200801 0514 5 -15 0.32 0.4756708 W7XU EN13 37 0 1 0 1 639 0 154 | 200801 0518 3 -21 0.32 0.4757245 NV4X EM77 30 -1 1 0 1 488 0 155 | 200801 0520 2 -24 0.28 0.4756240 K2BLA EL99 23 0 1 0 1 463 0 156 | 200801 0520 4 -19 0.11 0.4756705 W7XU EN13 37 0 1 0 1 440 0 157 | 200801 0520 6 -12 0.28 0.4757191 WD8DAS EN52 30 0 1 0 1 729 0 158 | 200801 0520 3 -22 0.37 0.4757681 AE2EA FN12 23 0 1 0 1 521 0 159 | 200801 0522 2 -23 0.41 0.4756276 W3TS FN10 37 -2 3 0 1 362 0 160 | 200801 0522 4 -18 0.37 0.4756388 WB3AVN FM19 37 0 1 0 1 677 0 161 | 200801 0522 4 -19 0.41 0.4758030 N8CGY EN74 33 0 1 0 1 607 0 162 | 200801 0524 6 -5 0.88 0.4755999 KB8U EN71 37 0 1 0 1 721 0 163 | 200801 0526 5 -14 0.11 0.4756706 W7XU EN13 37 0 1 0 1 670 0 164 | 200801 0528 2 -24 0.32 0.4756241 K2BLA EL99 23 0 1 0 1 361 0 165 | 200801 0528 4 -19 0.37 0.4756387 WB3AVN FM19 37 0 1 0 1 654 0 166 | 200801 0528 2 -27 0.24 0.4757192 W0IOO EN10 27 -2 17 0 1 65 0 167 | 200801 0530 5 -13 0.28 0.4757190 WD8DAS EN52 30 0 1 0 1 710 0 168 | 200801 0530 3 -21 0.37 0.4757681 AE2EA FN12 23 0 1 0 1 535 0 169 | 200801 0532 6 -6 0.88 0.4756000 KB8U EN71 37 0 1 0 1 543 0 170 | 200801 0532 6 -13 0.32 0.4756705 W7XU EN13 37 0 1 0 1 667 0 171 | 200801 0532 1 -31 0.28 0.4757241 NV4X EM77 30 0 1 0 1 810 1 172 | 200801 0536 5 -12 0.32 0.4756707 W7XU EN13 37 0 1 0 1 701 0 173 | 200801 0538 3 -20 0.37 0.4756389 WB3AVN FM19 37 0 1 0 1 629 0 174 | 200801 0540 6 -10 0.32 0.4756708 W7XU EN13 37 0 1 0 1 763 0 175 | 200801 0540 5 -15 0.28 0.4757193 WD8DAS EN52 30 0 1 0 1 746 0 176 | 200801 0540 2 -23 0.32 0.4757681 AE2EA FN12 23 0 1 0 1 427 0 177 | 200801 0542 1 -26 0.37 0.4756269 W3TS FN10 37 -2 5 0 1 33 0 178 | 200801 0542 2 -25 0.32 0.4757184 W0IOO EN10 27 -1 2 0 1 407 0 179 | 200801 0544 7 -4 0.88 0.4755999 KB8U EN71 37 0 1 0 1 712 0 180 | 200801 0544 1 -30 0.41 0.4756242 K2BLA EL99 23 0 1 -24 2 810 1 181 | 200801 0546 1 -28 0.37 0.4756389 WB3AVN FM19 37 0 1 0 1 810 1 182 | 200801 0546 1 -27 0.37 0.4758030 N8CGY EN74 33 0 1 16 1 810 1 183 | 200801 0548 2 -25 0.28 0.4757246 NV4X EM77 30 -1 3 0 1 36 0 184 | 200801 0548 2 -26 0.41 0.4757488 KE7A EM12 30 -1 10 0 1 2 0 185 | 200801 0550 1 -24 0.32 0.4756270 W3TS FN10 37 -2 23 0 1 -14 0 186 | 200801 0550 5 -14 0.28 0.4757193 WD8DAS EN52 30 0 1 0 1 737 0 187 | 200801 0552 2 -26 0.28 0.4756241 K2BLA EL99 23 0 1 0 1 216 0 188 | 200801 0554 1 -28 0.41 0.4757486 KE7A EM12 30 -1 1 0 1 810 1 189 | 200801 0556 7 -5 0.92 0.4755999 KB8U EN71 37 0 1 0 1 700 0 190 | 200801 0556 5 -17 0.37 0.4756703 W7XU EN13 37 1 1 0 1 568 0 191 | 200801 0556 1 -29 0.37 0.4757185 W0IOO EN10 27 0 1 0 1 810 1 192 | 200801 0556 2 -26 0.41 0.4757245 NV4X EM77 30 -1 7 0 1 17 0 193 | 200801 0558 3 -20 0.37 0.4756390 WB3AVN FM19 37 0 1 0 1 475 0 194 | 200801 0558 1 -30 0.41 0.4756946 ZF1EJ EK99 33 0 1 0 1 810 1 195 | 200801 0558 2 -25 0.32 0.4757484 KE7A EM12 30 0 3 0 1 139 0 196 | 200801 0600 5 -15 0.28 0.4757191 WD8DAS EN52 30 0 1 0 1 726 0 197 | 200801 0604 2 -26 0.32 0.4756241 K2BLA EL99 23 0 1 0 1 158 0 198 | 200801 0606 2 -27 0.37 0.4757244 NV4X EM77 30 -1 1 0 1 810 1 199 | 200801 0608 5 -16 0.32 0.4756703 W7XU EN13 37 1 1 0 1 660 0 200 | 200801 0608 2 -26 0.28 0.4757485 KE7A EM12 30 -1 7 0 1 153 0 201 | 200801 0610 2 -21 0.32 0.4756278 W3TS FN10 37 -1 1 0 1 254 0 202 | 200801 0610 5 -15 0.32 0.4756389 WB3AVN FM19 37 0 1 0 1 679 0 203 | 200801 0610 5 -14 0.28 0.4757191 WD8DAS EN52 30 0 1 0 1 720 0 204 | 200801 0610 2 -23 0.28 0.4757681 AE2EA FN12 23 0 1 0 1 178 0 205 | 200801 0612 6 -6 0.92 0.4755999 KB8U EN71 37 0 1 0 1 701 0 206 | 200801 0612 1 -26 0.37 0.4756241 K2BLA EL99 23 0 2328 0 1 -136 0 207 | 200801 0612 1 -27 0.37 0.4758031 N8CGY EN74 33 0 1 0 1 810 1 208 | 200801 0614 5 -12 0.32 0.4756705 W7XU EN13 37 0 1 0 1 653 0 209 | -------------------------------------------------------------------------------- /dev/wspr-logs/ALL_WSPR_WSJT-X_2200mtrs.TXT: -------------------------------------------------------------------------------- 1 | 200801 0624 -22 0.28 0.1375751 WH2XND DM33 43 0 0.27 1 1 0 0 16 1 340 2 | 200801 0632 -21 0.37 0.1375751 WH2XND DM33 43 0 0.32 1 1 0 0 17 1 403 3 | 200801 0640 -23 0.37 0.1375752 WH2XND DM33 43 0 0.23 1 1 0 0 14 6 295 4 | 200801 0648 -23 0.24 0.1375752 WH2XND DM33 43 0 0.21 1 1 0 1 33 1 810 5 | 200801 0656 -22 0.28 0.1375751 WH2XND DM33 43 0 0.23 1 1 0 0 31 4 22 6 | 200801 0700 -22 0.28 0.1375751 WH2XND DM33 43 0 0.27 1 1 0 0 21 2 172 7 | 200801 0708 -24 0.32 0.1375752 WH2XND DM33 43 0 0.22 1 1 0 0 19 5 175 8 | 200801 0716 -19 0.32 0.1375752 WH2XND DM33 43 0 0.34 1 1 0 0 4 1 542 9 | 200801 0724 -16 0.32 0.1375752 WH2XND DM33 43 0 0.37 1 1 0 0 5 1 540 10 | 200801 0732 -18 0.28 0.1375751 WH2XND DM33 43 0 0.37 1 1 0 0 6 1 458 11 | 200801 0740 -18 0.28 0.1375751 WH2XND DM33 43 0 0.36 1 1 0 0 5 1 558 12 | 200801 0748 -19 0.28 0.1375752 WH2XND DM33 43 0 0.28 1 1 0 0 17 2 297 13 | 200801 0756 -21 0.28 0.1375752 WH2XND DM33 43 0 0.20 1 1 0 0 28 3 100 14 | 200801 0800 -23 0.41 0.1375752 WH2XND DM33 43 0 0.23 1 1 0 0 26 199 -60 15 | 200801 0808 -26 0.28 0.1375751 WH2XND DM33 43 0 0.15 1 1 0 1 34 1 810 16 | 200801 0824 -22 0.37 0.1375752 WH2XND DM33 43 0 0.28 1 1 0 0 19 1 274 17 | 200801 0832 -21 0.37 0.1375751 WH2XND DM33 43 0 0.28 1 1 0 0 18 1 241 18 | 200801 0840 -22 0.41 0.1375752 WH2XND DM33 43 0 0.27 1 1 0 0 21 2 174 19 | 200801 0848 -21 0.32 0.1375751 WH2XND DM33 43 0 0.32 1 1 0 0 13 1 372 20 | 200801 0856 -21 0.32 0.1375751 WH2XND DM33 43 0 0.27 1 1 0 0 8 1 437 21 | 200801 0900 -21 0.32 0.1375751 WH2XND DM33 43 0 0.29 1 1 0 0 13 1 319 22 | 200801 0916 -16 0.32 0.1375751 WH2XND DM33 43 0 0.44 1 1 0 0 4 1 622 23 | 200801 0924 -20 0.37 0.1375752 WH2XND DM33 43 0 0.34 1 1 0 0 7 1 489 24 | 200801 0932 -20 0.37 0.1375751 WH2XND DM33 43 0 0.31 1 1 0 0 14 7 380 25 | 200801 0948 -19 0.28 0.1375751 WH2XND DM33 43 0 0.35 1 1 0 0 10 1 395 26 | 200801 0956 -24 0.32 0.1375752 WH2XND DM33 43 0 0.27 1 1 0 0 18 1 214 27 | 200801 1000 -18 0.28 0.1375751 WH2XND DM33 43 0 0.33 1 1 0 0 13 1 432 28 | 200801 1008 -18 0.28 0.1375752 WH2XND DM33 43 0 0.24 1 1 0 0 15 1 331 29 | 200801 1016 -17 0.28 0.1375751 WH2XND DM33 43 0 0.37 1 1 0 0 5 1 560 30 | 200801 1024 -18 0.32 0.1375751 WH2XND DM33 43 0 0.39 1 1 0 0 8 1 484 31 | 200801 1032 -17 0.28 0.1375752 WH2XND DM33 43 0 0.37 1 1 0 0 9 1 492 32 | 200801 1040 -14 0.32 0.1375752 WH2XND DM33 43 0 0.45 1 1 0 0 5 1 593 33 | 200801 1048 -11 0.28 0.1375751 WH2XND DM33 43 0 0.57 1 1 0 0 4 1 680 34 | 200801 1056 -12 0.28 0.1375752 WH2XND DM33 43 0 0.54 1 1 0 0 5 1 663 35 | 200801 1100 -16 0.32 0.1375751 WH2XND DM33 43 0 0.51 1 1 0 0 4 1 667 36 | 200801 1108 -19 0.28 0.1375752 WH2XND DM33 43 0 0.38 1 1 0 0 9 1 562 37 | 200801 1116 -19 0.32 0.1375751 WH2XND DM33 43 0 0.42 1 1 0 0 3 1 674 38 | 200801 1124 -22 0.28 0.1375751 WH2XND DM33 43 0 0.28 1 1 0 0 14 1 323 39 | 200801 1132 -25 0.24 0.1375750 WH2XND DM33 43 0 0.24 1 1 0 0 22 8 153 40 | -------------------------------------------------------------------------------- /dev/wspr-logs/ALL_WSPR_WSJT-X_630mtrs.TXT: -------------------------------------------------------------------------------- 1 | 200801 0216 -24 0.37 0.4756392 WB3AVN FM19 37 0 0.27 1 1 0 0 8 1 435 2 | 200801 0216 -23 0.41 0.4757245 NV4X EM77 30 -1 0.33 1 1 0 0 9 1 371 3 | 200801 0220 -13 0.41 0.4757191 WD8DAS EN52 30 0 0.62 1 1 0 0 0 1 758 4 | 200801 0220 -26 0.45 0.4757682 AE2EA FN12 23 0 0.20 1 1 0 0 19 1 251 5 | 200801 0222 -27 0.41 0.4757486 KE7A EM12 30 -1 0.19 1 1 0 0 35 79 -123 6 | 200801 0224 -19 -0.87 0.4756710 W7XU EN13 37 0 0.44 1 1 0 0 30 1 105 7 | 200801 0224 -25 0.49 0.4757246 NV4X EM77 30 -1 0.25 1 1 0 0 24 2 81 8 | 200801 0228 -13 0.49 0.4756712 W7XU EN13 37 0 0.60 1 1 0 0 1 1 731 9 | 200801 0230 -6 0.83 0.4755999 KB8U EN71 37 0 0.70 1 1 0 0 0 1 620 10 | 200801 0230 -14 0.37 0.4757192 WD8DAS EN52 30 0 0.58 1 1 0 0 0 1 772 11 | 200801 0230 -30 0.54 0.4757683 AE2EA FN12 23 0 0.12 2 1 -56 1 43 1 810 12 | 200801 0232 -16 0.49 0.4756711 W7XU EN13 37 1 0.50 1 1 0 0 1 1 541 13 | 200801 0234 -26 0.54 0.4757245 NV4X EM77 30 -1 0.23 1 1 0 0 16 6 313 14 | 200801 0236 -9 0.41 0.4756711 W7XU EN13 37 0 0.58 1 1 0 0 0 1 580 15 | 200801 0240 -13 0.83 0.4755999 KB8U EN71 37 0 0.53 1 1 0 0 0 1 497 16 | 200801 0240 -15 0.37 0.4757192 WD8DAS EN52 30 0 0.57 1 1 0 0 0 1 728 17 | 200801 0240 -29 0.49 0.4757482 KE7A EM12 30 -2 0.17 1 1 8 1 40 1 810 18 | 200801 0240 -26 0.45 0.4757682 AE2EA FN12 23 0 0.21 1 1 0 0 26 42 -23 19 | 200801 0244 -26 0.41 0.4757245 NV4X EM77 30 -1 0.23 1 1 0 0 18 14 140 20 | 200801 0246 -10 0.54 0.4756705 W7XU EN13 37 0 0.60 1 1 0 0 0 1 739 21 | 200801 0248 -1 0.83 0.4755999 KB8U EN71 37 0 0.69 1 1 0 0 0 1 785 22 | 200801 0250 -16 0.37 0.4757191 WD8DAS EN52 30 0 0.51 1 1 0 0 0 1 719 23 | 200801 0250 -27 0.37 0.4757680 AE2EA FN12 23 0 0.16 1 1 0 1 34 1 810 24 | 200801 0254 -21 0.49 0.4757245 NV4X EM77 30 -1 0.38 1 1 0 0 1 1 698 25 | 200801 0256 -25 0.45 0.4756276 W3TS FN10 37 -1 0.23 1 1 0 0 24 1 210 26 | 200801 0256 -10 0.45 0.4756705 W7XU EN13 37 0 0.58 1 1 0 0 0 1 684 27 | 200801 0300 -6 0.88 0.4755999 KB8U EN71 37 0 0.63 1 1 0 0 0 1 750 28 | 200801 0300 -8 0.49 0.4756709 W7XU EN13 37 0 0.62 1 1 0 0 0 1 713 29 | 200801 0300 -16 0.32 0.4757192 WD8DAS EN52 30 0 0.54 1 1 0 0 1 1 695 30 | 200801 0300 -27 0.45 0.4757681 AE2EA FN12 23 0 0.19 1 1 0 0 28 23 -32 31 | 200801 0302 -17 0.45 0.4757245 NV4X EM77 30 -1 0.44 1 1 0 0 0 1 693 32 | 200801 0304 -17 0.37 0.4756391 WB3AVN FM19 37 0 0.46 1 1 0 0 0 1 667 33 | 200801 0304 -2 0.45 0.4756709 W7XU EN13 37 0 0.62 1 1 0 0 0 1 744 34 | 200801 0308 -7 0.88 0.4756000 KB8U EN71 37 0 0.64 1 1 0 0 0 1 633 35 | 200801 0308 -25 0.45 0.4757244 NV4X EM77 30 -1 0.26 1 1 0 0 25 2 149 36 | 200801 0310 -20 0.41 0.4756390 WB3AVN FM19 37 0 0.39 1 1 0 0 4 1 590 37 | 200801 0310 -14 0.41 0.4757192 WD8DAS EN52 30 0 0.55 1 1 0 0 1 1 708 38 | 200801 0310 -27 0.45 0.4757680 AE2EA FN12 23 0 0.14 1 1 0 1 34 1 810 39 | 200801 0314 -22 0.45 0.4757244 NV4X EM77 30 -1 0.34 1 1 0 0 9 1 481 40 | 200801 0316 -4 0.83 0.4755999 KB8U EN71 37 0 0.64 1 1 0 0 2 1 548 41 | 200801 0316 -22 0.58 0.4756277 W3TS FN10 37 -1 0.29 1 1 0 0 9 1 415 42 | 200801 0316 -22 0.41 0.4756389 WB3AVN FM19 37 0 0.34 1 1 0 0 6 1 543 43 | 200801 0320 -14 0.37 0.4757191 WD8DAS EN52 30 0 0.55 1 1 0 0 1 1 706 44 | 200801 0322 -24 0.45 0.4757244 NV4X EM77 30 -1 0.27 1 1 0 0 14 3 327 45 | 200801 0326 -23 0.41 0.4756391 WB3AVN FM19 37 -1 0.32 1 1 0 0 12 1 428 46 | 200801 0328 -20 0.37 0.4757244 NV4X EM77 30 -1 0.41 1 1 0 0 6 1 589 47 | 200801 0328 -21 0.41 0.4757377 AA5IT EM20 37 0 0.35 1 1 0 0 11 1 455 48 | 200801 0330 -13 0.37 0.4757191 WD8DAS EN52 30 0 0.53 1 1 0 0 1 1 666 49 | 200801 0330 -28 0.45 0.4757488 KE7A EM12 30 0 0.16 1 1 0 0 23 10 34 50 | 200801 0332 -5 0.83 0.4756000 KB8U EN71 37 0 0.64 1 1 0 0 1 1 452 51 | 200801 0332 -23 0.45 0.4756389 WB3AVN FM19 37 0 0.32 1 1 0 0 15 1 342 52 | 200801 0332 -17 0.45 0.4757376 AA5IT EM20 37 0 0.47 1 1 0 0 0 1 681 53 | 200801 0334 -24 0.49 0.4756279 W3TS FN10 37 -2 0.25 1 1 0 0 20 1 308 54 | 200801 0334 -26 0.37 0.4757245 NV4X EM77 30 -1 0.21 1 1 0 0 24 1 126 55 | 200801 0336 -28 0.45 0.4756240 K2BLA EL99 23 0 0.16 3 1 -64 0 31 113 -120 56 | 200801 0338 -23 0.45 0.4757376 AA5IT EM20 37 0 0.29 1 1 0 0 11 1 377 57 | 200801 0338 -25 0.49 0.4757488 KE7A EM12 30 -1 0.22 1 1 0 0 19 56 139 58 | 200801 0340 -7 0.83 0.4755999 KB8U EN71 37 0 0.60 1 1 0 0 0 1 575 59 | 200801 0340 -17 0.45 0.4756389 WB3AVN FM19 37 0 0.48 1 1 0 0 0 1 685 60 | 200801 0340 -15 0.37 0.4757192 WD8DAS EN52 30 0 0.53 1 1 0 0 0 1 713 61 | 200801 0344 -29 0.37 0.4756240 K2BLA EL99 23 0 0.14 3 2 0 1 34 1 810 62 | 200801 0344 -23 0.28 0.4756278 W3TS FN10 37 -2 0.25 1 1 0 0 29 19 59 63 | 200801 0344 -23 0.49 0.4757246 NV4X EM77 30 -1 0.30 1 1 0 0 11 1 435 64 | 200801 0350 -28 0.45 0.4756390 WB3AVN FM19 37 0 0.19 1 1 -8 1 32 1 810 65 | 200801 0350 -15 0.37 0.4757192 WD8DAS EN52 30 0 0.49 1 1 0 0 0 1 726 66 | 200801 0350 -24 0.45 0.4757246 NV4X EM77 30 -1 0.19 1 1 0 0 15 2 320 67 | 200801 0350 -16 0.49 0.4757373 AA5IT EM20 37 0 0.46 1 1 0 0 1 1 686 68 | 200801 0350 -25 0.37 0.4757682 AE2EA FN12 23 0 0.23 1 1 0 0 18 2 250 69 | 200801 0352 -15 0.88 0.4756000 KB8U EN71 37 0 0.51 1 1 0 0 2 1 532 70 | 200801 0352 -21 0.41 0.4756239 K2BLA EL99 23 0 0.22 1 1 0 0 28 3 13 71 | 200801 0352 -21 0.45 0.4756269 W3TS FN10 37 -2 0.30 1 1 0 0 17 1 318 72 | 200801 0356 -27 0.37 0.4756387 WB3AVN FM19 37 0 0.18 1 1 0 1 32 1 810 73 | 200801 0356 -21 0.41 0.4757242 NV4X EM77 30 0 0.30 1 1 0 0 26 1 161 74 | 200801 0356 -13 0.49 0.4757374 AA5IT EM20 37 0 0.52 1 1 0 0 0 1 737 75 | 200801 0400 -14 0.32 0.4757192 WD8DAS EN52 30 0 0.46 1 1 0 0 0 1 688 76 | 200801 0400 -28 0.45 0.4757681 AE2EA FN12 23 0 0.16 1 1 0 1 40 1 810 77 | 200801 0402 -16 0.45 0.4757373 AA5IT EM20 37 0 0.44 1 1 0 0 1 1 635 78 | 200801 0406 -19 0.45 0.4756389 WB3AVN FM19 37 -1 0.39 1 1 0 0 2 1 634 79 | 200801 0406 -21 0.45 0.4757245 NV4X EM77 30 -1 0.36 1 1 0 0 3 1 565 80 | 200801 0408 -23 0.41 0.4757373 AA5IT EM20 37 0 0.27 1 1 0 0 15 1 386 81 | 200801 0410 -11 0.88 0.4756000 KB8U EN71 37 0 0.54 1 1 0 0 1 1 603 82 | 200801 0410 -14 0.41 0.4757191 WD8DAS EN52 30 0 0.50 1 1 0 0 0 1 672 83 | 200801 0410 -24 0.45 0.4757681 AE2EA FN12 23 0 0.26 1 1 0 0 19 3 300 84 | 200801 0412 -23 0.45 0.4756243 K2BLA EL99 23 0 0.30 1 1 0 0 19 1 221 85 | 200801 0412 -19 0.45 0.4756275 W3TS FN10 37 0 0.32 1 1 0 0 18 1 261 86 | 200801 0412 -22 0.37 0.4757374 AA5IT EM20 37 0 0.30 1 1 0 0 8 1 364 87 | 200801 0414 -15 0.41 0.4757245 NV4X EM77 30 -1 0.50 1 1 0 0 0 1 653 88 | 200801 0416 -18 0.45 0.4756389 WB3AVN FM19 37 0 0.44 1 1 0 0 1 1 674 89 | 200801 0418 -13 0.37 0.4756708 W7XU EN13 37 0 0.50 1 1 0 0 41 1 85 90 | 200801 0420 -8 0.92 0.4756000 KB8U EN71 37 0 0.60 1 1 0 0 3 1 514 91 | 200801 0420 -27 0.32 0.4756241 K2BLA EL99 23 0 0.20 1 1 0 1 36 1 810 92 | 200801 0420 -14 0.37 0.4757191 WD8DAS EN52 30 0 0.54 1 1 0 0 0 1 699 93 | 200801 0420 -26 0.45 0.4757249 NV4X EM77 30 0 0.16 1 1 0 1 46 1 810 94 | 200801 0420 -26 0.37 0.4757681 AE2EA FN12 23 0 0.20 1 1 0 1 29 1 810 95 | 200801 0422 -22 0.45 0.4756270 W3TS FN10 37 -1 0.27 1 1 0 0 16 1 225 96 | 200801 0422 -15 0.41 0.4756711 W7XU EN13 37 0 0.53 1 1 0 0 1 1 663 97 | 200801 0428 -10 0.88 0.4756000 KB8U EN71 37 0 0.60 1 1 0 0 3 1 486 98 | 200801 0428 -25 0.45 0.4756241 K2BLA EL99 23 0 0.24 1 1 0 0 18 1 256 99 | 200801 0428 -28 0.45 0.4756388 WB3AVN FM19 37 -1 0.18 1 1 0 1 32 1 810 100 | 200801 0428 -24 0.45 0.4757246 NV4X EM77 30 -1 0.30 1 1 0 0 20 1 279 101 | 200801 0430 -14 0.37 0.4757191 WD8DAS EN52 30 0 0.56 1 1 0 0 0 1 724 102 | 200801 0430 -21 0.45 0.4757681 AE2EA FN12 23 0 0.38 1 1 0 0 4 1 626 103 | 200801 0432 -16 0.49 0.4756271 W3TS FN10 37 -1 0.41 1 1 0 0 1 1 646 104 | 200801 0434 -18 0.37 0.4756388 WB3AVN FM19 37 0 0.43 1 1 0 0 2 1 582 105 | 200801 0434 -18 0.45 0.4756727 W7XU EN13 37 0 0.41 1 1 0 0 32 1 72 106 | 200801 0436 -22 0.32 0.4756241 K2BLA EL99 23 0 0.30 1 1 0 0 3 1 487 107 | 200801 0436 -28 0.37 0.4757482 KE7A EM12 30 -1 0.16 1 1 0 1 38 1 810 108 | 200801 0438 -10 0.92 0.4756000 KB8U EN71 37 0 0.62 1 1 0 0 0 1 637 109 | 200801 0438 -26 0.41 0.4757245 NV4X EM77 30 -1 0.21 1 1 0 0 22 1 194 110 | 200801 0438 -22 0.32 0.4758030 N8CGY EN74 33 0 0.27 1 1 16 0 26 52 -58 111 | 200801 0440 -14 0.41 0.4757192 WD8DAS EN52 30 0 0.55 1 1 0 0 0 1 724 112 | 200801 0440 -28 0.37 0.4757482 KE7A EM12 30 0 0.13 1 1 16 1 37 1 810 113 | 200801 0440 -19 0.37 0.4757681 AE2EA FN12 23 0 0.41 1 1 0 0 3 1 615 114 | 200801 0442 -20 0.45 0.4756274 W3TS FN10 37 -1 0.33 1 1 0 0 6 1 485 115 | 200801 0442 -27 0.54 0.4758029 N8CGY EN74 33 0 0.15 3 2 -8 1 41 1 810 116 | 200801 0444 -25 0.32 0.4756240 K2BLA EL99 23 0 0.27 1 1 0 0 11 1 382 117 | 200801 0444 -23 0.45 0.4756389 WB3AVN FM19 37 0 0.34 1 1 0 0 18 1 382 118 | 200801 0444 -14 0.24 0.4756704 W7XU EN13 37 0 0.58 1 1 0 0 0 1 520 119 | 200801 0448 -26 0.45 0.4757246 NV4X EM77 30 -1 0.22 1 1 0 0 24 1 241 120 | 200801 0450 -8 0.92 0.4756000 KB8U EN71 37 0 0.63 1 1 0 0 0 1 484 121 | 200801 0450 -25 0.15 0.4756707 W7XU EN13 37 0 0.29 1 1 0 0 16 1 295 122 | 200801 0450 -14 0.37 0.4757191 WD8DAS EN52 30 0 0.56 1 1 0 0 0 1 719 123 | 200801 0450 -27 0.37 0.4757486 KE7A EM12 30 -1 0.19 1 1 0 0 20 64 141 124 | 200801 0450 -21 0.45 0.4757681 AE2EA FN12 23 0 0.36 1 1 0 0 7 1 508 125 | 200801 0450 -25 0.32 0.4758029 N8CGY EN74 33 0 0.20 1 1 0 1 41 1 810 126 | 200801 0452 -26 0.41 0.4756242 K2BLA EL99 23 0 0.18 1 1 0 1 34 1 810 127 | 200801 0452 -28 0.37 0.4757194 W0IOO EN10 27 -1 0.19 1 1 -8 0 28 133 -138 128 | 200801 0456 -24 0.41 0.4756389 WB3AVN FM19 37 0 0.29 1 1 0 0 16 1 343 129 | 200801 0458 -14 0.19 0.4756705 W7XU EN13 37 0 0.52 1 1 0 0 0 1 638 130 | 200801 0458 -20 0.41 0.4757488 KE7A EM12 30 -1 0.42 1 1 0 0 1 1 667 131 | 200801 0500 -3 0.66 0.4756000 KB8U EN71 37 0 0.60 1 1 0 0 3 1 601 132 | 200801 0500 -15 0.15 0.4757192 WD8DAS EN52 30 0 0.49 1 1 0 0 1 1 677 133 | 200801 0502 -26 0.37 0.4758031 N8CGY EN74 33 0 0.16 3 1 8 1 45 1 810 134 | 200801 0504 -9 0.32 0.4756388 WB3AVN FM19 37 0 0.61 1 1 0 0 0 1 733 135 | 200801 0504 -15 0.32 0.4756707 W7XU EN13 37 0 0.51 1 1 0 0 7 1 458 136 | 200801 0504 -26 0.41 0.4757489 KE7A EM12 30 -1 0.24 1 1 0 0 26 1 198 137 | 200801 0508 -20 0.37 0.4757488 KE7A EM12 30 -1 0.41 1 1 0 0 7 1 577 138 | 200801 0510 -12 0.37 0.4756707 W7XU EN13 37 0 0.58 1 1 0 0 0 1 630 139 | 200801 0510 -13 0.28 0.4757192 WD8DAS EN52 30 0 0.58 1 1 0 0 1 1 703 140 | 200801 0510 -25 0.32 0.4757245 NV4X EM77 30 -1 0.24 2 1 0 1 26 1 810 141 | 200801 0510 -24 0.45 0.4757682 AE2EA FN12 23 0 0.25 1 1 0 0 12 1 373 142 | 200801 0512 -9 0.88 0.4756000 KB8U EN71 37 0 0.62 1 1 0 0 2 1 594 143 | 200801 0512 -21 0.37 0.4756244 K2BLA EL99 23 -1 0.26 1 1 0 1 46 1 810 144 | 200801 0512 -19 0.37 0.4756276 W3TS FN10 37 -2 0.36 1 1 0 0 5 1 559 145 | 200801 0512 -26 0.32 0.4757487 KE7A EM12 30 -1 0.27 1 1 0 0 17 1 333 146 | 200801 0512 -24 0.28 0.4758031 N8CGY EN74 33 0 0.25 1 1 0 0 28 57 40 147 | 200801 0514 -14 0.37 0.4756388 WB3AVN FM19 37 0 0.55 1 1 0 0 0 1 716 148 | 200801 0514 -15 0.32 0.4756708 W7XU EN13 37 0 0.53 1 1 0 0 1 1 621 149 | 200801 0518 -28 0.32 0.4757188 W0IOO EN10 27 -1 0.16 1 1 0 1 36 1 810 150 | 200801 0518 -21 0.32 0.4757245 NV4X EM77 30 -1 0.36 1 1 0 0 6 1 475 151 | 200801 0520 -24 0.28 0.4756240 K2BLA EL99 23 0 0.28 1 1 0 0 9 1 467 152 | 200801 0520 -19 0.11 0.4756705 W7XU EN13 37 0 0.41 1 1 0 0 8 1 447 153 | 200801 0520 -12 0.28 0.4757191 WD8DAS EN52 30 0 0.61 1 1 0 0 0 1 721 154 | 200801 0520 -22 0.37 0.4757681 AE2EA FN12 23 0 0.36 1 1 0 0 7 1 513 155 | 200801 0522 -23 0.32 0.4756276 W3TS FN10 37 -2 0.28 1 1 0 0 18 1 315 156 | 200801 0522 -18 0.37 0.4756388 WB3AVN FM19 37 0 0.43 1 1 0 0 0 1 684 157 | 200801 0522 -19 0.32 0.4758030 N8CGY EN74 33 0 0.41 1 1 0 0 4 1 589 158 | 200801 0524 -5 0.83 0.4755999 KB8U EN71 37 0 0.68 1 1 0 0 0 1 724 159 | 200801 0526 -14 0.11 0.4756706 W7XU EN13 37 0 0.55 1 1 0 0 0 1 667 160 | 200801 0528 -24 0.32 0.4756241 K2BLA EL99 23 0 0.27 1 1 0 0 15 1 358 161 | 200801 0528 -19 0.37 0.4756387 WB3AVN FM19 37 0 0.43 1 1 0 0 0 1 655 162 | 200801 0528 -26 0.37 0.4757198 W0IOO EN10 27 -2 0.19 1 1 0 1 43 1 810 163 | 200801 0530 -13 0.28 0.4757190 WD8DAS EN52 30 0 0.59 1 1 0 0 0 1 706 164 | 200801 0530 -21 0.32 0.4757681 AE2EA FN12 23 0 0.37 1 1 0 0 7 1 510 165 | 200801 0532 -6 0.88 0.4756000 KB8U EN71 37 0 0.69 1 1 0 0 0 1 540 166 | 200801 0532 -13 0.32 0.4756705 W7XU EN13 37 0 0.60 1 1 0 0 0 1 655 167 | 200801 0532 -30 0.28 0.4757242 NV4X EM77 30 0 0.14 1 1 0 1 40 1 810 168 | 200801 0534 -24 0.41 0.4756274 W3TS FN10 37 -2 0.17 1 1 0 1 41 1 810 169 | 200801 0536 -12 0.32 0.4756707 W7XU EN13 37 0 0.56 1 1 0 0 0 1 707 170 | 200801 0538 -20 0.28 0.4756389 WB3AVN FM19 37 0 0.39 1 1 0 0 1 1 619 171 | 200801 0540 -10 0.28 0.4756708 W7XU EN13 37 0 0.63 1 1 0 0 0 1 761 172 | 200801 0540 -15 0.28 0.4757193 WD8DAS EN52 30 0 0.56 1 1 0 0 0 1 746 173 | 200801 0540 -23 0.28 0.4757681 AE2EA FN12 23 0 0.29 1 1 0 0 10 1 408 174 | 200801 0542 -26 0.37 0.4756269 W3TS FN10 37 -2 0.20 1 1 0 0 24 5 35 175 | 200801 0542 -25 0.32 0.4757184 W0IOO EN10 27 -1 0.27 1 1 0 0 11 2 408 176 | 200801 0544 -4 0.88 0.4755999 KB8U EN71 37 0 0.71 1 1 0 0 0 1 711 177 | 200801 0544 -33 0.37 0.4756242 K2BLA EL99 23 0 0.13 3 3 -8 1 42 1 810 178 | 200801 0546 -28 0.41 0.4756388 WB3AVN FM19 37 -1 0.18 1 1 0 1 38 1 810 179 | 200801 0546 -26 0.37 0.4758029 N8CGY EN74 33 0 0.16 1 1 8 1 40 1 810 180 | 200801 0548 -25 0.28 0.4757246 NV4X EM77 30 -1 0.25 1 1 0 0 25 2 30 181 | 200801 0548 -26 0.41 0.4757488 KE7A EM12 30 -1 0.24 1 1 0 0 24 26 -56 182 | 200801 0550 -24 0.28 0.4756270 W3TS FN10 37 -2 0.20 1 1 0 0 27 14 -75 183 | 200801 0550 -14 0.28 0.4757193 WD8DAS EN52 30 0 0.57 1 1 0 0 0 1 734 184 | 200801 0552 -26 0.24 0.4756241 K2BLA EL99 23 0 0.21 1 1 0 0 22 1 150 185 | 200801 0554 -28 0.41 0.4757486 KE7A EM12 30 -1 0.15 1 1 0 1 34 1 810 186 | 200801 0556 -5 0.88 0.4755999 KB8U EN71 37 0 0.70 1 1 0 0 0 1 695 187 | 200801 0556 -17 0.32 0.4756703 W7XU EN13 37 1 0.50 1 1 0 0 3 1 568 188 | 200801 0556 -29 0.24 0.4757184 W0IOO EN10 27 0 0.16 1 1 0 1 39 1 810 189 | 200801 0556 -26 0.41 0.4757244 NV4X EM77 30 -1 0.24 1 1 0 0 28 135 2 190 | 200801 0558 -20 0.37 0.4756390 WB3AVN FM19 37 -1 0.39 1 1 0 0 9 1 428 191 | 200801 0558 -25 0.32 0.4757484 KE7A EM12 30 0 0.23 1 1 0 0 23 4 97 192 | 200801 0600 -15 0.28 0.4757191 WD8DAS EN52 30 0 0.54 1 1 0 0 0 1 712 193 | 200801 0604 -26 0.32 0.4756241 K2BLA EL99 23 0 0.24 1 1 0 0 27 4 128 194 | 200801 0606 -27 0.37 0.4757245 NV4X EM77 30 -1 0.20 1 1 0 1 34 1 810 195 | 200801 0608 -16 0.32 0.4756703 W7XU EN13 37 1 0.52 1 1 0 0 0 1 661 196 | 200801 0608 -26 0.28 0.4757485 KE7A EM12 30 -1 0.23 1 1 0 0 22 6 154 197 | 200801 0610 -21 0.28 0.4756278 W3TS FN10 37 -1 0.25 1 1 0 0 19 1 227 198 | 200801 0610 -15 0.32 0.4756390 WB3AVN FM19 37 0 0.53 1 1 0 0 1 1 680 199 | 200801 0610 -14 0.28 0.4757191 WD8DAS EN52 30 0 0.59 1 1 0 0 0 1 707 200 | 200801 0610 -23 0.28 0.4757681 AE2EA FN12 23 0 0.28 1 1 0 0 22 1 184 201 | 200801 0612 -6 0.92 0.4755999 KB8U EN71 37 0 0.69 1 1 0 0 0 1 702 202 | 200801 0612 -26 0.37 0.4756241 K2BLA EL99 23 0 0.19 1 1 0 1 34 1 810 203 | 200801 0612 -27 0.37 0.4758031 N8CGY EN74 33 0 0.18 1 1 0 1 42 1 810 204 | 200801 0614 -12 0.32 0.4756705 W7XU EN13 37 0 0.60 1 1 0 0 1 1 651 205 | -------------------------------------------------------------------------------- /dev/wspr-logs/jtdx-all-wspr-K3SIW.TXT: -------------------------------------------------------------------------------- 1 | 200731 1630 7 -8 0.37 0.4757191 WD8DAS EN52 30 0 1 0 1 809 0 2 | 200731 1640 7 -8 0.41 0.4757192 WD8DAS EN52 30 0 1 0 1 810 0 3 | 200731 1650 7 -8 0.37 0.4757192 WD8DAS EN52 30 0 1 0 1 809 0 4 | 200731 1700 7 -9 0.37 0.4757191 WD8DAS EN52 30 0 1 0 1 801 0 5 | 200731 1710 7 -8 0.37 0.4757193 WD8DAS EN52 30 0 1 0 1 809 0 6 | 200731 1720 7 -8 0.41 0.4757191 WD8DAS EN52 30 0 1 0 1 806 0 7 | 200731 1730 7 -8 0.37 0.4757192 WD8DAS EN52 30 0 1 0 1 809 0 8 | -------------------------------------------------------------------------------- /dev/wspr-logs/wsjtx-2.1.2-pa2ohh.txt: -------------------------------------------------------------------------------- 1 | 200714 0730 6 -11 -0.23 14.0970210 IZ6QQT JN63 37 1 1 0 1 487 0 2 | 200714 0730 4 -17 0.88 14.0971011 I2BJS JN45 20 1 1 0 1 571 0 3 | 200714 0730 3 -20 0.02 14.0971130 G0CCL JO02 37 -1 2 0 1 324 0 4 | 200714 0736 2 -25 1.94 14.0969956 MW0ATK IO81 37 -1 74 0 1 166 0 5 | 200714 0736 1 -30 -0.06 14.0970321 DH2HAW JO43 30 0 1 0 1 810 1 6 | 200714 0736 4 -20 -0.27 14.0970786 HB9FXK JN37 37 -1 1 0 1 554 0 7 | 200714 0736 5 -16 -0.06 14.0971127 G0CCL JO02 37 0 1 0 1 654 0 8 | 200714 0750 1 -25 0.19 14.0970236 G8MCD IO91 30 0 1 0 1 810 1 9 | 200714 0750 2 -27 -1.47 14.0970376 <...> JN59MO 30 -1 3294 0 1 -109 0 10 | 200714 0750 1 -28 -0.57 14.0970548 IK1YRA JN35 23 0 1 16 1 810 1 11 | 200714 0750 2 -27 -0.62 14.0970942 SP3JP JO71 37 0 260 0 1 -61 0 12 | 200714 0750 3 -20 0.24 14.0971017 I2BJS JN45 20 1 1 0 1 494 0 13 | 200714 0750 3 -19 -0.57 14.0971595 DG7RJ JN58 37 0 1 0 1 471 0 14 | 200714 0752 1 -28 0.96 14.0970239 G8MCD IO91 30 0 1 0 1 810 1 15 | 200714 0752 1 -30 0.07 14.0970548 IK1YRA JN35 23 0 1 8 3 810 1 16 | 200714 0754 2 -26 0.11 14.0970548 IK1YRA JN35 23 0 3 0 1 187 0 17 | 200714 0754 2 -25 -0.32 14.0970803 HB9FXK JN37 37 0 1 0 1 810 1 18 | 200714 0754 4 -17 0.07 14.0971115 G0CCL JO02 37 -1 1 0 1 486 0 19 | 200714 0754 3 -21 2.29 14.0971295 G4UGD IO83 37 0 1 0 1 441 0 20 | 200714 0756 1 -28 1.99 14.0969957 MW0ATK IO81 37 0 1 0 1 810 1 21 | 200714 0756 5 -16 -0.10 14.0970213 IZ6QQT JN63 37 1 1 0 1 509 0 22 | 200714 0756 1 -29 0.28 14.0970426 HB9EM JN36 23 0 1589 8 1 -64 0 23 | 200714 0756 3 -24 0.07 14.0970549 IK1YRA JN35 23 0 1 0 1 373 0 24 | 200714 0756 1 -28 0.92 14.0970618 DL6NL JO50 27 0 4925 0 1 -186 0 25 | 200714 0758 1 -29 0.15 14.0971075 ON7WP JO21 23 0 1 8 3 810 1 26 | 200714 0800 1 -28 0.71 14.0970617 DL6NL JO50 27 0 3503 0 1 -214 0 27 | 200714 0800 2 -25 0.07 14.0970749 I0NAA JN63 23 -2 278 0 1 -10 0 28 | 200714 0800 5 -17 0.07 14.0971101 G0CCL JO02 37 0 1 0 1 665 0 29 | 200714 0800 3 -23 2.24 14.0971298 G4UGD IO83 37 0 1 0 1 519 0 30 | 200714 0806 2 -25 -0.02 14.0970551 IK1YRA JN35 23 0 13 0 1 172 0 31 | 200714 0806 4 -17 -0.06 14.0971110 G0CCL JO02 37 0 1 0 1 613 0 32 | 200714 0808 1 -29 0.07 14.0970553 IK1YRA JN35 23 0 1 8 1 810 1 33 | 200714 0808 1 -27 0.88 14.0970612 DL6NL JO50 27 0 15 0 1 -18 0 34 | 200714 0810 5 -15 0.07 14.0970208 IZ6QQT JN63 37 2 1 0 1 466 0 35 | 200714 0810 4 -18 -0.23 14.0970819 HB9FXK JN37 37 0 1 0 1 697 0 36 | 200714 0810 1 -27 -0.02 14.0970926 ON7KB JO21 37 0 1 0 2 810 1 37 | 200714 0810 4 -13 1.05 14.0971023 I2BJS JN45 20 1 1 0 1 373 0 38 | 200714 0810 2 -25 3.05 14.0971114 M0UNI IO82 37 0 1 0 1 193 0 39 | 200714 0810 3 -23 0.15 14.0971599 DG7RJ JN58 37 0 2 0 1 309 0 40 | 200714 0812 2 -27 2.11 14.0969959 MW0ATK IO81 37 0 2405 0 1 -145 0 41 | 200714 0812 1 -29 -0.83 14.0970384 DB1NN JN59 30 -1 3839 -8 1 -113 0 42 | 200714 0812 4 -19 -0.02 14.0971095 G0CCL JO02 37 0 1 0 1 275 0 43 | 200714 0812 6 -7 0.11 14.0971119 PA0MLC/P 37 0 1 0 1 574 0 44 | 200714 0814 5 -16 2.07 14.0971299 G4UGD IO83 37 0 1 0 1 675 0 45 | 200714 0816 2 -24 0.11 14.0970552 IK1YRA JN35 23 0 1 0 1 149 0 46 | 200714 0816 1 -30 0.66 14.0970607 DL6NL JO50 27 0 1 0 1 810 1 47 | 200714 0816 2 -28 0.24 14.0971060 HB9EM JN36 23 0 1373 0 1 -115 0 48 | 200714 0818 2 -23 -0.06 14.0970554 IK1YRA JN35 23 0 1 0 1 810 1 49 | 200714 0818 2 -17 -0.10 14.0971122 G0CCL JO02 37 0 1 0 1 810 1 50 | 200714 0820 2 -28 0.66 14.0970602 DL6NL JO50 27 0 1 0 1 810 1 51 | 200714 0820 1 -28 0.02 14.0970751 I0NAA JN63 23 -3 1 0 1 810 1 52 | 200714 0820 2 -24 -0.19 14.0970823 HB9FXK JN37 37 0 1 0 1 267 0 53 | 200714 0820 2 -23 -0.49 14.0970973 F1JVV JN03 37 -1 7 0 1 -13 0 54 | 200714 0820 3 -21 2.20 14.0971301 G4UGD IO83 37 0 1 0 1 386 0 55 | 200714 0820 1 -29 0.15 14.0971600 DG7RJ JN58 37 0 1 0 1 810 1 56 | 200714 0822 3 -23 -0.10 14.0971001 HA6QL JN97 37 0 1 0 1 296 0 57 | 200714 0824 2 -23 -0.62 14.0970553 IK1YRA JN35 23 0 1290 0 1 -162 0 58 | 200714 0824 2 -20 -0.70 14.0971140 G0CCL JO02 37 0 7 0 1 83 0 59 | 200714 0826 3 -22 0.02 14.0970553 IK1YRA JN35 23 0 1 0 1 397 0 60 | 200714 0828 1 -30 0.92 14.0970241 G8MCD IO91 30 0 1 0 1 810 1 61 | 200714 0828 1 -28 0.11 14.0970431 HB9EM JN36 23 0 1 24 1 810 1 62 | 200714 0828 7 -6 0.28 14.0971120 JN33CV 37 0 1 0 1 635 0 63 | 200714 0830 4 -19 -0.02 14.0970219 IZ6QQT JN63 37 1 1 0 1 439 0 64 | 200714 0830 2 -24 0.11 14.0970554 IK1YRA JN35 23 0 1 0 1 132 0 65 | 200714 0830 1 -27 -0.27 14.0970825 HB9FXK JN37 37 0 2999 0 1 -211 0 66 | 200714 0830 1 -29 -0.02 14.0970928 ON7KB JO21 37 0 1 8 2 810 1 67 | 200714 0830 3 -17 0.88 14.0971027 I2BJS JN45 20 1 15 0 1 236 0 68 | 200714 0830 2 -22 2.97 14.0971120 M0UNI IO82 37 0 1 0 1 304 0 69 | 200714 0832 1 -28 2.11 14.0969961 MW0ATK IO81 37 0 1 0 1 810 1 70 | 200714 0832 1 -27 0.02 14.0970554 IK1YRA JN35 23 0 1 0 1 810 1 71 | 200714 0834 2 -26 0.19 14.0970419 ON7WP JO21 23 0 1 0 1 137 0 72 | 200714 0836 1 -28 -0.87 14.0970384 DB1NN JN59 30 -1 1 0 1 810 1 73 | 200714 0836 1 -28 0.71 14.0970584 DL6NL JO50 27 0 1 0 1 810 1 74 | 200714 0836 2 -25 -0.06 14.0971000 HA6QL JN97 37 0 31 0 1 38 0 75 | 200714 0836 2 -24 -0.02 14.0971141 G0CCL JO02 37 0 1 0 1 335 0 76 | 200714 0836 4 -19 2.16 14.0971302 G4UGD IO83 37 0 1 0 1 678 0 77 | -------------------------------------------------------------------------------- /dev/wspr-logs/wsjtx-2.2.2-df2jp.txt: -------------------------------------------------------------------------------- 1 | 200716 1022 -26 -0.06 10.1401327 HB4FV JN36 30 -3 0.21 1 1 -32 1 34 1 810 2 | 200716 1022 -13 -0.32 10.1402153 5Q9T JO65 37 0 0.62 1 1 0 0 4 1 549 3 | 200716 1022 -26 0.02 10.1402532 DL2NED JN59 23 -1 0.23 1 1 0 1 37 1 810 4 | 200716 1022 -20 -0.15 10.1402741 F1JSC JN03 37 0 0.45 1 1 0 0 6 1 520 5 | 200716 1024 -23 0.45 10.1402017 LA6BH JO28 33 0 0.19 1 1 0 1 32 1 810 6 | 200716 1024 -24 -0.66 10.1402063 F4GOH IN78 20 0 0.15 2 1 0 1 43 1 810 7 | 200716 1024 -26 -0.19 10.1402117 DL5RAZ JN68 13 0 0.17 1 1 0 1 37 1 810 8 | 200716 1026 -27 1.09 10.1401576 SK7CY JO66 23 0 0.19 3 2 0 0 26 119 -133 9 | 200716 1026 -27 -0.19 10.1402117 DL5RAZ JN68 13 0 0.20 1 1 0 1 39 1 810 10 | 200716 1026 -18 -0.10 10.1402610 SA7ORA JO65 33 0 0.50 1 1 0 0 8 1 438 11 | 200716 1028 -20 -0.40 10.1401544 G8UDI IO93 30 0 0.26 2 1 0 0 14 14 245 12 | 200716 1028 -8 -0.06 10.1401592 G4GVZ IO81 37 0 0.60 1 1 0 0 0 1 703 13 | 200716 1028 -14 0.45 10.1401958 DL3NGN JN59 33 0 0.27 1 1 0 0 18 1 184 14 | 200716 1028 -18 0.19 10.1402066 2E0SAE IO83 37 0 0.27 1 1 0 0 23 16 56 15 | 200716 1028 -23 -0.23 10.1402115 DL5RAZ JN68 13 0 0.13 1 1 0 1 36 1 810 16 | 200716 1028 -13 0.02 10.1402174 M0UNI IO82 37 0 0.54 1 1 0 0 1 1 547 17 | 200716 1028 -29 -0.06 10.1402412 OZ7IT JO65 10 0 0.14 1 1 0 1 37 1 810 18 | 200716 1030 -26 -0.19 10.1402116 DL5RAZ JN68 13 0 0.17 1 1 0 0 28 484 -113 19 | 200716 1030 -29 0.11 10.1402230 SM0WCF JO99 37 -1 0.21 1 1 0 1 34 1 810 20 | 200716 1030 -20 -0.23 10.1402639 IK1WVQ JN44 27 0 0.41 1 1 0 0 6 1 434 21 | 200716 1030 -32 2.58 10.1402762 OK2UGG JN89 13 0 0.12 1 1 8 1 38 1 810 22 | 200716 1032 -7 0.02 10.1401795 DM3FML JO60 37 0 0.55 1 1 0 0 26 1 166 23 | 200716 1032 -23 0.49 10.1402016 LA6BH JO28 33 -2 0.27 1 1 0 0 20 1 94 24 | 200716 1032 -22 1.01 10.1402109 OE3KFB JN78 37 0 0.22 1 1 -16 1 36 1 810 25 | 200716 1032 -28 -0.10 10.1402117 DL5RAZ JN68 13 0 0.18 3 3 -32 1 46 1 810 26 | 200716 1032 -20 -0.02 10.1402240 DL2NED JN59 23 -1 0.36 1 1 0 0 10 1 370 27 | 200716 1032 -18 -0.15 10.1402740 F1JSC JN03 37 0 0.52 1 1 0 0 4 1 536 28 | 200716 1034 -27 -0.15 10.1402116 DL5RAZ JN68 13 0 0.21 1 1 0 1 39 1 810 29 | 200716 1036 -5 -0.06 10.1401591 G4GVZ IO81 37 0 0.81 1 1 0 0 1 1 678 30 | 200716 1036 -27 1.30 10.1401763 SM7EHR JO65 23 0 0.17 1 1 -8 1 41 1 810 31 | 200716 1036 -28 -0.15 10.1402116 DL5RAZ JN68 13 0 0.17 1 1 -8 1 35 1 810 32 | 200716 1036 -17 -0.10 10.1402610 JO65SM 33 0 0.57 1 1 0 0 2 1 563 33 | 200716 1038 -22 0.41 10.1401956 DL3NGN JN59 33 0 0.21 1 1 0 1 25 1 810 34 | 200716 1040 -28 0.11 10.1401071 DL1BGE JO43 23 -2 0.17 1 1 24 1 42 1 810 35 | 200716 1040 -21 0.15 10.1401562 JN59MO 33 0 0.39 1 1 0 0 12 1 392 36 | 200716 1040 -23 -0.27 10.1402638 IK1WVQ JN44 27 0 0.27 1 1 0 0 11 1 439 37 | 200716 1040 -9 0.02 10.1402707 DG7RJ JN58 37 0 0.72 1 1 0 0 2 1 595 38 | 200716 1042 -25 -0.83 10.1402073 F4GOH IN78 20 2 0.13 1 1 0 1 39 1 810 39 | 200716 1042 -25 -0.27 10.1402116 DL5RAZ JN68 13 0 0.19 1 1 0 1 28 1 810 40 | 200716 1042 -20 -0.06 10.1402309 OH3FR KP20 33 0 0.30 1 1 0 0 10 2 355 41 | 200716 1042 -21 0.02 10.1402350 DL2NED JN59 23 -1 0.23 1 1 0 0 17 1 297 42 | 200716 1042 -19 0.07 10.1402811 GM4SFW IO77 33 0 0.48 1 1 0 0 6 1 502 43 | 200716 1044 -18 -0.19 10.1402037 M1DYP IO91 37 0 0.48 1 1 0 0 2 1 577 44 | 200716 1044 -10 -0.27 10.1402150 5Q9T JO65 37 0 0.71 1 1 0 0 1 1 641 45 | 200716 1044 -23 -0.19 10.1402287 IZ6QQT JN63 37 0 0.30 1 1 0 0 11 1 416 46 | 200716 1044 -19 -0.10 10.1402610 SA7ORA JO65 33 0 0.50 1 1 0 0 3 1 593 47 | 200716 1044 -23 -0.06 10.1402740 F1JSC JN03 37 0 0.33 1 1 0 0 19 3 210 48 | 200716 1046 -7 -0.19 10.1401324 HB4FV JN36 30 -2 0.65 1 1 0 0 1 1 651 49 | 200716 1046 -9 -0.10 10.1401590 G4GVZ IO81 37 0 0.72 1 1 0 0 1 1 617 50 | 200716 1046 -15 0.58 10.1401957 DL3NGN JN59 33 1 0.26 1 1 0 0 19 1 259 51 | 200716 1048 -18 0.11 10.1401566 DB1NN JN59 33 0 0.49 1 1 0 0 9 1 432 52 | 200716 1048 -13 0.49 10.1401969 DL3NGN JN59 33 0 0.13 3 1 -8 1 33 1 810 53 | 200716 1048 -26 -0.19 10.1402115 DL5RAZ JN68 13 0 0.16 3 2 0 1 32 1 810 54 | 200716 1048 -26 -0.15 10.1402266 OZ8PZ JO47 23 1 0.28 2 1 0 0 26 489 -19 55 | 200716 1048 -15 -0.23 10.1402288 IZ6QQT JN63 37 1 0.55 1 1 0 0 2 1 631 56 | 200716 1048 -8 0.02 10.1402706 DG7RJ JN58 37 0 0.72 1 1 0 0 1 1 594 57 | 200716 1050 -24 -0.10 10.1401860 G3YJZ IO91 27 0 0.29 1 1 0 0 18 1 296 58 | 200716 1050 -27 -0.27 10.1402114 DL5RAZ JN68 13 0 0.19 1 1 -8 1 42 1 810 59 | 200716 1050 -24 0.07 10.1402227 SM0WCF JO99 37 -1 0.29 1 1 0 0 22 8 192 60 | 200716 1050 -16 -0.36 10.1402638 IK1WVQ JN44 27 0 0.60 1 1 0 0 0 1 569 61 | 200716 1050 -32 2.58 10.1402763 OK2UGG JN89 13 0 0.16 2 1 -24 1 40 1 810 62 | 200716 1050 -28 1.05 10.1402887 SK7CY JO66 23 0 0.24 1 1 0 1 38 1 810 63 | 200716 1052 -23 0.54 10.1401572 IK2HNG JN45 23 -2 0.34 1 1 0 0 22 1 166 64 | 200716 1052 -22 -0.10 10.1402609 JO65SM 33 0 0.42 1 1 0 0 9 1 446 65 | 200716 1052 -21 0.02 10.1402800 DL2NED JN59 23 -1 0.40 1 1 0 0 15 2 393 66 | 200716 1054 -28 -0.15 10.1401207 DK8JP JO31 30 0 0.16 3 2 0 1 37 1 810 67 | 200716 1054 -10 -0.19 10.1401323 HB4FV JN36 30 -2 0.65 1 1 0 0 1 1 730 68 | 200716 1054 -19 0.15 10.1401837 HB9FXY JN36 23 0 0.41 1 1 0 0 8 1 508 69 | 200716 1054 -24 -0.83 10.1402067 F4GOH IN78 20 0 0.14 1 1 16 1 41 1 810 70 | 200716 1054 -25 0.02 10.1402132 OE3KFB JN78 37 0 0.11 3 1 0 1 40 1 810 71 | 200716 1054 -19 -0.15 10.1402740 F1JSC JN03 37 0 0.49 1 1 0 0 10 1 430 72 | 200716 1056 -11 -0.10 10.1401591 G4GVZ IO81 37 0 0.71 1 1 0 0 0 1 657 73 | 200716 1056 -24 0.49 10.1402012 LA6BH JO28 33 0 0.24 1 1 0 0 30 17 -24 74 | 200716 1056 -29 -0.27 10.1402115 DL5RAZ JN68 13 0 0.18 1 1 16 1 40 1 810 75 | 200716 1058 -22 0.45 10.1401953 DL3NGN JN59 33 2 0.20 1 1 0 1 27 1 810 76 | 200716 1100 -20 0.15 10.1401567 JN59MO 33 0 0.39 1 1 0 0 12 5 376 77 | 200716 1100 -27 -0.15 10.1401854 G0OQK IO91 23 2 0.22 1 1 0 0 28 21 -3 78 | 200716 1100 -27 -0.19 10.1402115 DL5RAZ JN68 13 0 0.12 3 3 -16 1 37 1 810 79 | 200716 1100 -17 0.71 10.1402433 M0VSS IO91 23 0 0.56 1 1 0 0 6 1 495 80 | 200716 1100 -23 -0.74 10.1402636 IK1WVQ JN44 27 0 0.37 1 1 0 0 10 1 443 81 | 200716 1104 -3 -0.23 14.0970714 DM3FML JO60 37 0 0.78 1 1 0 0 0 1 732 82 | 200716 1104 -27 -0.40 14.0971017 DF6NN JO61 10 -1 0.14 1 1 56 1 40 1 810 83 | 200716 1104 -12 -0.66 14.0971179 MM1BTJ IO75 37 0 0.60 1 1 0 0 1 1 519 84 | 200716 1104 -23 -0.15 14.0971608 UR5KHL KO30 30 0 0.37 1 1 0 0 17 1 366 85 | 200716 1106 -28 -0.23 14.0971057 EA6GK JM19 20 -1 0.16 1 1 0 1 33 1 810 86 | 200716 1106 -25 -0.10 14.0971423 MM0RKT IO75 30 0 0.28 1 1 0 0 20 1 264 87 | 200716 1108 -6 -0.19 14.0970901 OE3KFB JN78 37 0 0.68 1 1 0 0 4 1 582 88 | 200716 1108 -18 -0.23 14.0970960 OH5XO KP41 27 0 0.40 1 1 0 0 8 1 453 89 | 200716 1108 -25 -0.10 14.0971012 DF6NN JO61 10 -2 0.22 2 1 0 1 34 1 810 90 | 200716 1108 -21 -0.19 14.0971205 LA3LJA JP53 27 0 0.30 1 1 0 0 17 1 281 91 | 200716 1108 -22 -0.15 14.0971284 MM/M0VIK 23 -2 0.25 2 1 0 1 38 1 810 92 | 200716 1108 -9 -0.19 14.0971289 DL4MFC JN58 33 0 0.59 1 1 0 0 4 1 531 93 | 200716 1108 -14 1.09 14.0971549 DK3DUA JO61 23 0 0.57 1 1 0 0 7 1 487 94 | 200716 1108 -21 -0.19 14.0971607 UR5KHL KO30 30 0 0.34 1 1 0 0 11 1 336 95 | 200716 1110 -28 -0.15 14.0970848 PA3ETC JO21 23 0 0.18 1 1 0 1 37 1 810 96 | 200716 1110 -23 0.02 14.0971140 JN33CV 37 0 0.31 1 1 0 0 22 1 101 97 | 200716 1110 -22 -0.15 14.0971259 IP90KE 23 -3 0.37 1 1 0 0 10 1 379 98 | 200716 1110 -9 0.11 14.0971728 GM4SFW IO77 33 0 0.76 1 1 0 0 0 1 697 99 | 200716 1112 -22 -0.23 14.0971047 EA6GK JM19 20 -1 0.33 1 1 0 0 11 1 374 100 | 200716 1112 -19 0.07 14.0971289 HA5IS JN97 37 0 0.44 1 1 0 0 6 1 505 101 | 200716 1112 -16 1.13 14.0971549 DK3DUA JO61 23 0 0.54 1 1 0 0 3 1 614 102 | 200716 1112 -20 -0.15 14.0971607 UR5KHL KO30 30 0 0.43 1 1 0 0 7 1 490 103 | 200716 1112 -29 -0.15 14.0971753 EA4DTE IN80 23 0 0.19 1 1 24 0 30 94 -60 104 | 200716 1114 -29 -0.40 14.0970144 EA5/G7NFK 30 0 0.15 3 3 24 0 34 403 -135 105 | 200716 1114 -8 -0.15 14.0971289 DL4MFC JN58 33 0 0.75 1 1 0 0 1 1 629 106 | 200716 1114 -25 -0.10 14.0971417 MM0RKT IO75 30 0 0.13 1 1 0 1 36 1 810 107 | 200716 1116 -15 -0.66 14.0970899 OE3KFB JN78 37 0 0.57 1 1 0 0 6 1 517 108 | 200716 1116 -20 -0.23 14.0970984 OH5XO KP41 27 0 0.27 1 1 0 0 21 1 267 109 | 200716 1116 -27 -0.74 14.0971011 DF6NN JO61 10 -2 0.18 2 1 32 1 40 1 810 110 | 200716 1116 -12 -0.74 14.0971179 MM1BTJ IO75 37 0 0.68 1 1 0 0 1 1 620 111 | 200716 1116 -22 -0.15 14.0971606 UR5KHL KO30 30 0 0.33 1 1 0 0 10 1 323 112 | 200716 1118 -26 -0.23 14.0971064 EA6GK JM19 20 -1 0.24 1 1 0 0 20 2 195 113 | 200716 1118 -18 -0.15 14.0971297 MM/M0VIK 23 -2 0.53 1 1 0 0 4 1 581 114 | 200716 1118 -15 1.09 14.0971549 DK3DUA JO61 23 0 0.61 1 1 0 0 0 1 619 115 | 200716 1120 -27 -0.57 14.0971009 DF6NN JO61 10 -1 0.15 1 1 -8 1 37 1 810 116 | 200716 1120 -20 -0.19 14.0971270 IP90KE 23 -3 0.34 2 1 0 0 30 33 -13 117 | 200716 1120 -6 -0.15 14.0971287 DL4MFC JN58 33 0 0.70 1 1 0 0 5 1 582 118 | 200716 1120 -21 2.24 14.0971469 OH3FR KP20 33 0 0.35 1 1 0 0 13 1 398 119 | 200716 1120 -15 1.13 14.0971550 DK3DUA JO61 23 0 0.58 1 1 0 0 4 1 462 120 | 200716 1120 -21 -0.19 14.0971607 UR5KHL KO30 30 0 0.35 1 1 0 0 12 2 323 121 | 200716 1122 -14 1.09 14.0971549 DK3DUA JO61 23 0 0.64 1 1 0 0 2 1 586 122 | 200716 1122 -12 0.07 14.0971729 GM4SFW IO77 33 0 0.64 1 1 0 0 3 1 591 123 | 200716 1124 -19 -0.19 14.0970986 OH5XO KP41 27 0 0.32 1 1 0 0 8 1 474 124 | 200716 1124 -23 -0.15 14.0971045 EA6GK JM19 20 -1 0.25 1 1 0 0 25 1 110 125 | 200716 1124 -14 -0.74 14.0971179 MM1BTJ IO75 37 0 0.47 1 1 0 0 8 1 476 126 | 200716 1124 -26 -1.21 14.0971185 EB1HHA IN73 17 -4 0.16 2 1 0 0 26 4 2 127 | 200716 1124 -26 1.52 14.0971289 HA5IS JN97 37 0 0.27 1 1 0 0 23 14 184 128 | 200716 1124 -24 -0.15 14.0971606 UR5KHL KO30 30 0 0.36 1 1 0 0 13 1 431 129 | 200716 1126 -26 -0.15 14.0970870 PA3ETC JO21 23 0 0.17 2 1 -8 1 32 1 810 130 | 200716 1126 1 -0.15 14.0971286 DL4MFC JN58 33 0 0.84 1 1 0 0 0 1 751 131 | 200716 1126 -19 1.18 14.0971549 DK3DUA JO61 23 0 0.44 1 1 0 0 9 1 464 132 | 200716 1128 -19 -0.57 14.0970899 OE3KFB JN78 37 0 0.50 1 1 0 0 6 1 530 133 | 200716 1128 -25 -0.32 14.0971007 DF6NN JO61 10 0 0.15 1 1 0 1 36 1 810 134 | 200716 1128 -23 -0.19 14.0971294 MM/M0VIK 23 -2 0.33 1 1 0 0 13 1 361 135 | 200716 1128 -17 1.13 14.0971549 DK3DUA JO61 23 0 0.52 1 1 0 0 4 1 541 136 | 200716 1128 -18 -0.19 14.0971605 UR5KHL KO30 30 0 0.48 1 1 0 0 7 1 504 137 | 200716 1130 -25 -0.15 14.0971053 EA6GK JM19 20 -1 0.17 1 1 0 1 39 1 810 138 | 200716 1130 -10 -0.19 14.0971181 IZ6QQT JN63 37 2 0.66 1 1 0 0 0 1 630 139 | 200716 1130 -24 -0.06 14.0971268 IP90KE 23 -4 0.26 1 1 0 0 21 1 218 140 | 200716 1132 -21 -0.19 14.0970987 OH5XO KP41 27 1 0.24 1 1 0 0 16 1 286 141 | 200716 1132 -29 -0.15 14.0971004 DF6NN JO61 10 0 0.20 2 1 0 1 36 1 810 142 | 200716 1132 -17 -0.74 14.0971179 MM1BTJ IO75 37 0 0.41 1 1 0 0 2 1 557 143 | 200716 1132 -4 -0.15 14.0971286 DL4MFC JN58 33 0 0.82 1 1 0 0 0 1 703 144 | 200716 1132 -15 1.13 14.0971549 DK3DUA JO61 23 0 0.59 1 1 0 0 2 1 592 145 | 200716 1132 -23 -0.15 14.0971604 UR5KHL KO30 30 0 0.30 1 1 0 0 10 1 430 146 | 200716 1134 -28 -0.06 14.0970857 PA3ETC JO21 23 0 0.18 3 2 -24 1 30 1 810 147 | 200716 1136 -24 -0.15 14.0971053 EA6GK JM19 20 -1 0.30 1 1 0 0 9 1 429 148 | 200716 1136 -23 0.19 14.0971288 HA5IS JN97 37 0 0.32 1 1 0 0 12 2 420 149 | 200716 1136 -27 0.41 14.0971426 IU1CYF JN35 23 0 0.20 1 1 0 1 37 1 810 150 | 200716 1136 -15 1.13 14.0971548 DK3DUA JO61 23 0 0.56 1 1 0 0 5 1 569 151 | 200716 1136 -17 -0.15 14.0971604 UR5KHL KO30 30 0 0.46 1 1 0 0 2 1 587 152 | 200716 1138 -2 -0.19 14.0971284 DL4MFC JN58 33 0 0.82 1 1 0 0 0 1 731 153 | 200716 1138 -20 1.13 14.0971548 DK3DUA JO61 23 0 0.40 1 1 0 0 13 1 357 154 | 200716 1140 -26 4.59 14.0970010 MW0ATK IO81 37 0 0.24 1 1 0 0 31 107 -17 155 | 200716 1140 -14 -0.06 14.0970899 OE3KFB JN78 37 1 0.46 1 1 0 0 12 1 415 156 | 200716 1140 -21 -0.23 14.0970997 OH5XO KP41 27 1 0.27 1 1 0 0 27 6 23 157 | 200716 1140 -19 -0.23 14.0971177 IZ6QQT JN63 37 2 0.47 1 1 0 0 5 1 612 158 | 200716 1140 -17 -0.19 14.0971265 DL1DUZ JO61 20 -1 0.44 1 1 0 0 22 1 183 159 | 200716 1140 -26 2.80 14.0971359 G4UGD IO83 37 0 0.19 1 1 0 0 32 383 -138 160 | 200716 1140 -21 -0.10 14.0971602 UR5KHL KO30 30 0 0.37 1 1 0 0 22 1 219 161 | 200716 1142 -10 -1.09 14.0970436 IW2DMO JN45 37 0 0.72 1 1 0 0 0 1 747 162 | 200716 1142 -24 -0.19 14.0970857 PA3ETC JO21 23 0 0.15 1 1 -8 1 31 1 810 163 | 200716 1142 -24 -0.15 14.0971053 EA6GK JM19 20 -1 0.30 1 1 0 0 12 1 390 164 | 200716 1142 -28 -0.10 14.0971422 MM0RKT IO75 30 0 0.15 2 1 0 1 29 1 810 165 | 200716 1142 -19 2.20 14.0971467 OH3FR KP20 33 0 0.40 1 1 0 0 7 1 412 166 | 200716 1142 -17 1.13 14.0971547 DK3DUA JO61 23 0 0.54 1 1 0 0 7 1 412 167 | 200716 1142 -29 -0.15 14.0971758 EA4DTE IN80 23 -2 0.14 1 1 0 1 35 1 810 168 | 200716 1144 -17 -0.83 14.0971179 MM1BTJ IO75 37 0 0.39 1 1 0 0 8 1 484 169 | 200716 1144 -1 -0.15 14.0971285 DL4MFC JN58 33 0 0.82 1 1 0 0 0 1 691 170 | 200716 1144 -22 -0.15 14.0971601 UR5KHL KO30 30 0 0.34 1 1 0 0 16 1 244 171 | 200716 1148 -25 -0.15 14.0971052 EA6GK JM19 20 0 0.16 1 1 0 0 29 25 -103 172 | 200716 1148 -27 -0.06 14.0971200 LA3LJA JP53 27 0 0.20 1 1 0 1 46 1 810 173 | 200716 1148 -27 -0.15 14.0971306 MM/M0VIK 23 -2 0.20 1 1 0 0 33 56 -92 174 | 200716 1148 -16 1.13 14.0971547 DK3DUA JO61 23 0 0.49 1 1 0 0 9 1 505 175 | 200716 1148 -19 -0.15 14.0971600 UR5KHL KO30 30 0 0.37 1 1 0 0 10 1 462 176 | 200716 1150 -21 0.62 14.0970637 DL5AB JN49 37 0 0.35 1 1 0 0 10 1 392 177 | 200716 1150 -29 -0.19 14.0970856 PA3ETC JO21 23 0 0.16 2 1 0 1 38 1 810 178 | 200716 1150 -22 -0.02 14.0970897 OE3KFB JN78 37 0 0.27 1 1 0 0 28 8 45 179 | 200716 1150 -15 -0.32 14.0971186 IZ6QQT JN63 37 1 0.48 1 1 0 0 3 1 574 180 | 200716 1150 -4 -0.15 14.0971283 DL4MFC JN58 33 0 0.76 1 1 0 0 0 1 716 181 | 200716 1152 -18 -0.79 14.0971177 MM1BTJ IO75 37 0 0.45 1 1 0 0 5 1 461 182 | 200716 1152 -22 -0.19 14.0971600 UR5KHL KO30 30 0 0.36 1 1 0 0 15 1 330 183 | 200716 1152 -28 -0.15 14.0971759 EA4DTE IN80 23 -1 0.19 1 1 0 1 37 1 810 184 | 200716 1154 -27 -0.15 14.0971051 EA6GK JM19 20 -1 0.21 1 1 -16 1 42 1 810 185 | 200716 1154 -29 0.11 14.0971287 HA5IS JN97 37 0 0.18 1 1 0 1 42 1 810 186 | 200716 1154 -20 1.13 14.0971547 DK3DUA JO61 23 0 0.44 1 1 0 0 5 1 537 -------------------------------------------------------------------------------- /dev/wspr-logs/wspr-df2jp.txt: -------------------------------------------------------------------------------- 1 | 200715 1006 10 -23 -0.3 7.040078 G6JVT IO90 23 0 1 0 2 | 200715 1006 4 -29 -0.1 7.040090 G8ORM IO93 30 0 50 0 3 | 200715 1006 16 -17 4.2 7.040127 M0WCZ IO92 30 0 1 0 4 | 200715 1008 4 -30 -0.3 7.040039 M5TXJ IO84 23 0 9880 -10 5 | 200715 1008 6 -25 -0.1 7.040092 M0XDC JO01 23 0 10 0 6 | 200715 1008 10 -23 -0.4 7.040178 M1DOX IO90 23 0 1 0 7 | 200715 1008 6 -26 -0.3 7.040194 M0GUC IO82 23 0 1 0 8 | 200715 1010 3 -27 -0.2 7.040126 G4VNM IO90 23 0 63 0 9 | 200715 1010 9 -24 -0.3 7.040179 G4NJJ JO02 23 0 7 0 10 | 200715 1020 15 -16 -0.5 7.040044 G0BZB IO94 20 -1 1 0 11 | 200715 1020 12 -19 -0.5 7.040126 OZ8PZ JO47 23 0 722 0 12 | 200715 1020 14 -17 -0.5 7.040165 UR5KHL KO30 30 0 1 0 13 | 200715 1046 24 -7 0.0 7.040033 DL1BGE JO43 23 -1 1 0 14 | 200715 1046 3 -29 -0.2 7.040076 IO92WH 33 0 1411 0 15 | 200715 1046 4 -29 0.0 7.040091 G8ORM IO93 30 0 6654 0 16 | 200715 1046 20 -12 -0.2 7.040121 DL4XJ JO42 30 0 1 0 17 | 200715 1046 10 -22 3.7 7.040134 M0UNI IO82 37 0 1 0 18 | 200715 1046 11 -21 0.0 7.040152 G7ICV JO01 27 -1 1 0 19 | 200715 1046 5 -27 -0.1 7.040162 DC7JZB JO62 37 0 1 0 20 | 200715 1046 5 -26 -0.2 7.040176 OZ7IT JO65 37 0 7 0 21 | 200715 1046 15 -17 -0.0 7.040192 DG7RJ JN58 37 0 1 0 22 | 200715 1048 8 -24 -0.2 7.040036 M0GUC IO82 23 0 1 0 23 | 200715 1048 4 -28 -0.3 7.040145 G8LIK IO93 23 0 14 0 24 | 200715 1048 12 -20 -0.4 7.040168 G0FTD JO01 30 0 1 0 25 | 200715 1050 13 -18 -0.3 7.040135 HB9HFR JN36 27 0 1 0 26 | 200715 1050 11 -21 -0.3 7.040178 G4NJJ JO02 23 0 1 0 27 | 200715 1052 17 -16 -0.3 7.040030 DL0PBS JO33 23 0 1 0 28 | 200715 1054 13 -18 -0.0 7.040055 2E0DSS IO82 33 0 1 0 29 | 200715 1054 10 -21 -0.3 7.040079 G6JVT IO90 23 0 1 0 30 | 200715 1054 6 -24 -0.1 7.040151 G0TKP IO83 23 0 1 0 31 | 200715 1054 18 -13 -0.1 7.040192 DG7RJ JN58 37 0 1 0 32 | 200715 1056 8 -24 0.0 7.040090 M0XDC JO01 23 0 1 0 33 | 200715 1056 10 -21 -0.2 7.040121 DL4XJ JO42 30 0 1 0 34 | 200715 1056 5 -25 -0.3 7.040145 G8LIK IO93 23 0 16 0 35 | 200715 1056 13 -20 -0.3 7.040176 OZ7IT JO65 37 0 1 0 36 | 200715 1058 8 -21 -0.2 7.040129 G8LDJ JO01 30 0 7575 19 37 | 200715 1058 13 -19 -0.3 7.040168 G0FTD JO01 30 0 1 0 38 | 200715 1058 13 -19 -0.0 7.040193 M0GUC IO82 23 0 1 0 39 | 200715 1100 6 -25 -0.2 7.040076 G1VWC IO92 33 0 1590 0 40 | 200715 1100 14 -17 -0.7 7.040129 G4JIX IO94 37 0 10 0 41 | 200715 1100 10 -22 -0.2 7.040178 G4NJJ JO02 23 0 1 0 42 | 200715 1102 3 -28 -0.0 7.040052 DL1BGE JO43 23 0 8309 6 43 | 200715 1102 5 -28 0.9 7.040060 DL2BBC JO32 23 0 5711 0 44 | 200715 1102 12 -18 -0.1 7.040135 HB9HFR JN36 27 0 1 0 45 | 200715 1104 22 -9 -0.3 7.040031 DL0PBS JO33 23 -1 1 0 46 | 200715 1104 12 -21 0.4 7.040062 G0AEN IO80 37 -1 1 0 47 | 200715 1104 7 -25 -0.3 7.040076 IO92WH 33 0 2 0 48 | 200715 1104 5 -25 -0.3 7.040152 G0TKP IO83 23 0 3 0 49 | 200715 1106 11 -22 -0.3 7.040079 G6JVT IO90 23 0 1 0 50 | 200715 1106 9 -21 -0.2 7.040107 PA3MRO JO22 37 0 12 0 51 | 200715 1108 12 -19 -0.4 7.040090 PA2PGU JO32 23 0 1 0 52 | 200715 1108 4 -26 0.5 7.040129 M0WCZ IO92 30 0 1629 0 53 | 200715 1108 4 -26 -0.1 7.040146 G8LIK IO93 23 0 162 0 54 | 200715 1108 8 -22 -0.1 7.040169 G0FTD JO01 30 0 1 0 55 | 200715 1108 9 -21 0.2 7.040191 M0GUC IO82 23 0 1 0 56 | 200715 1110 5 -26 -0.3 7.040076 G1VWC IO92 33 0 13 0 57 | 200715 1110 11 -22 -0.3 7.040178 G4NJJ JO02 23 0 1 0 58 | 200715 1112 13 -18 -0.3 7.040140 PA0ANH JO22 27 -1 1 0 59 | 200715 1114 13 -18 0.5 7.040062 G0AEN IO80 37 0 1 0 60 | 200715 1114 15 -16 -0.5 7.040104 PA2PGU JO32 23 0 1 0 61 | 200715 1114 4 -26 -0.1 7.040135 HB9HFR JN36 27 0 2558 -2 62 | 200715 1114 6 -24 -0.1 7.040152 G0TKP IO83 23 0 436 0 63 | 200715 1116 7 -25 -0.3 7.040031 DL0PBS JO33 23 0 2 0 64 | 200715 1116 8 -23 -0.1 7.040131 M7JDJ IO83 37 0 9929 20 65 | 200715 1118 13 -18 -0.1 7.040028 G8LXI IO70 40 0 1 0 66 | 200715 1118 9 -22 0.0 7.040146 DL1BGE JO43 23 -1 1 0 67 | 200715 1118 4 -28 -0.3 7.040177 OZ7IT JO65 37 0 3 0 68 | 200715 1120 12 -19 -0.4 7.040110 PA2PGU JO32 23 0 1 0 69 | 200715 1120 22 -8 -0.1 7.040122 DL4XJ JO42 30 0 1 0 70 | 200715 1120 17 -15 -0.5 7.040129 G4JIX IO94 37 0 1 0 71 | 200715 1120 3 -26 -0.1 7.040147 G8LIK IO93 23 0 438 5 72 | 200715 1120 12 -19 -0.2 7.040181 G4NJJ JO02 23 0 1 0 73 | 200715 1122 16 -16 -0.0 7.040056 2E0DSS IO82 33 0 1 0 74 | 200715 1122 10 -21 -0.4 7.040080 G6JVT IO90 23 0 30 0 75 | 200715 1122 9 -24 0.0 7.040123 HB9FXY JN36 23 0 1 0 76 | 200715 1122 2 -28 3.8 7.040132 2E0THH JO02 37 -1 4251 -8 77 | 200715 1122 14 -16 -0.3 7.040140 JO22LH 27 -1 1 0 78 | 200715 1124 19 -12 0.4 7.040063 G0AEN IO80 37 -1 1 0 79 | 200715 1124 8 -22 -0.3 7.040127 HB9JBP JN47 30 1 1588 0 80 | 200715 1124 7 -23 -0.1 7.040153 G0TKP IO83 23 0 1 0 81 | 200715 1126 28 -4 0.7 7.040049 M7ALU IO90 0 0 1 0 82 | 200715 1126 15 -17 -0.1 7.040085 DL1BGE JO43 23 -1 1 0 83 | 200715 1126 5 -26 -0.2 7.040107 PA3MRO JO22 37 0 2 0 84 | 200715 1126 9 -23 -0.2 7.040131 M7JDJ IO83 37 0 1 0 85 | 200715 1128 14 -18 -0.3 7.040032 DL0PBS JO33 23 0 1 0 86 | 200715 1128 6 -24 -0.5 7.040077 IO92WH 33 0 2 0 87 | 200715 1128 14 -18 0.0 7.040091 M0GUC IO82 23 0 1 0 88 | 200715 1128 2 -27 -0.3 7.040169 G0FTD JO01 30 0 5492 -19 89 | 200715 1130 2 -28 -0.3 7.040053 DK8JP JO31 30 0 8254 -44 90 | 200715 1130 3 -28 -0.1 7.040066 OZ1KVB JO44 27 0 10 0 91 | 200715 1130 11 -21 -0.2 7.040181 G4NJJ JO02 23 0 1 0 92 | 200715 1132 14 -17 -0.1 7.040131 M7JDJ IO83 37 0 1 0 93 | 200715 1132 8 -24 -0.2 7.040147 G8LIK IO93 23 0 8 0 94 | 200715 1132 3 -27 -0.3 7.040178 OZ7IT JO65 37 0 855 0 95 | 200715 1132 3 -28 0.2 7.040186 HB9FXY JN36 23 0 1972 0 96 | 200715 1134 2 -29 0.3 7.040047 G7ICV JO01 27 0 5674 0 97 | 200715 1134 15 -16 0.5 7.040063 G0AEN IO80 37 0 1 0 98 | 200715 1134 9 -23 -0.4 7.040077 G1VWC IO92 33 0 1 0 99 | 200715 1134 16 -15 0.0 7.040108 DL1BGE JO43 23 -1 1 0 100 | 200715 1134 9 -22 -0.0 7.040153 G0TKP IO83 23 -1 2 0 101 | 200715 1136 5 -26 -0.5 7.040147 G8LIK IO93 23 0 8951 2 102 | 200715 1138 14 -18 -0.2 7.040080 G6JVT IO90 23 0 2 0 103 | 200715 1138 12 -19 0.3 7.040094 M0GUC IO82 23 0 1 0 104 | 200715 1138 11 -20 -0.0 7.040137 HB9HFR JN36 27 -1 1 0 105 | 200715 1140 21 -10 -0.2 7.040029 G8LXI IO70 40 0 4 0 106 | 200715 1140 4 -27 -0.3 7.040066 OZ1KVB JO44 27 0 24 0 107 | 200715 1140 10 -22 -0.3 7.040146 G8LIK IO93 23 0 1 0 108 | 200715 1140 14 -19 -0.3 7.040181 G4NJJ JO02 23 0 1 0 109 | 200715 1142 17 -14 0.0 7.040133 DL1BGE JO43 23 0 72 0 110 | 200715 1142 10 -22 -0.4 7.040177 OZ7IT JO65 37 0 1 0 111 | 200715 1144 12 -18 0.9 7.040063 G0AEN IO80 37 0 1 0 112 | 200715 1144 7 -25 -0.1 7.040077 G1VWC IO92 33 0 2 0 113 | 200715 1144 10 -21 0.3 7.040128 G4VNM IO90 23 0 1 0 114 | 200715 1144 4 -27 -0.2 7.040136 PA2PGU JO32 23 0 2788 0 115 | 200715 1144 12 -20 0.3 7.040152 G0TKP IO83 23 0 1 0 116 | 200715 1146 25 -6 0.2 7.040021 M5KVK IO92 37 0 1 0 117 | 200715 1146 20 -11 0.2 7.040126 OZ2JBR JO65 37 0 1 0 118 | 200715 1146 16 -15 4.0 7.040136 M0UNI IO82 37 0 1 0 119 | 200715 1146 4 -27 0.1 7.040147 OZ8PZ JO47 23 0 1037 0 120 | 200715 1148 10 -22 -0.3 7.040077 IO92WH 33 0 1 0 121 | 200715 1148 12 -19 0.2 7.040095 M0GUC IO82 23 0 1 0 122 | 200715 1148 5 -25 0.0 7.040147 G8LIK IO93 23 0 63 0 -------------------------------------------------------------------------------- /src/FSKview.Tests/FSKview.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net6.0-windows 4 | false 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/FSKview.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: AssemblyTitle("FSKview.Tests")] 6 | [assembly: AssemblyDescription("")] 7 | [assembly: AssemblyConfiguration("")] 8 | [assembly: AssemblyCompany("")] 9 | [assembly: AssemblyProduct("FSKview.Tests")] 10 | [assembly: AssemblyCopyright("Copyright © 2020")] 11 | [assembly: AssemblyTrademark("")] 12 | [assembly: AssemblyCulture("")] 13 | 14 | [assembly: ComVisible(false)] 15 | 16 | [assembly: Guid("ac248652-1080-43cf-aa9d-3bd78dbeb421")] 17 | 18 | // [assembly: AssemblyVersion("1.0.*")] 19 | [assembly: AssemblyVersion("1.0.0.0")] 20 | [assembly: AssemblyFileVersion("1.0.0.0")] 21 | -------------------------------------------------------------------------------- /src/FSKview.Tests/WsprLogFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace FSKview.Tests 6 | { 7 | [TestClass] 8 | public class WsprLogFile 9 | { 10 | [TestMethod] 11 | public void Test_LogFormat_ReadAllLogs() 12 | { 13 | string logFolderPath = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "../../../../../dev/wspr-logs")); 14 | string[] logFilePaths = Directory.GetFiles(logFolderPath, "*.txt"); 15 | foreach (string logFilePath in logFilePaths) 16 | { 17 | var log = new FSKview.WsprLogFile(logFilePath); 18 | Console.WriteLine($"{Path.GetFileName(logFilePath)} has {log.spots.Count} valid spots"); 19 | Assert.IsTrue(log.spots.Count > 5); 20 | } 21 | } 22 | 23 | [TestMethod] 24 | public void Test_LogFormat_73() 25 | { 26 | string line = "200715 1006 10 -23 -0.3 7.040078 G6JVT IO90 23 0 1 0"; 27 | var spot = new WsprSpot(line); 28 | 29 | Assert.AreEqual(2020, spot.dt.Year); 30 | Assert.AreEqual(7, spot.dt.Month); 31 | Assert.AreEqual(15, spot.dt.Day); 32 | Assert.AreEqual(10, spot.dt.Hour); 33 | Assert.AreEqual(6, spot.dt.Minute); 34 | Assert.AreEqual(0, spot.dt.Second); 35 | Assert.AreEqual("2007151006", spot.timestamp); 36 | Assert.AreEqual(-23, spot.strength); 37 | Assert.AreEqual(7.040078, spot.frequencyMHz); 38 | Assert.AreEqual(7_040_078, spot.frequencyHz); 39 | Assert.AreEqual("G6JVT", spot.callsign); 40 | Assert.AreEqual("IO90", spot.grid); 41 | Assert.IsTrue(spot.isValid); 42 | } 43 | 44 | [TestMethod] 45 | public void Test_LogFormat_73b() 46 | { 47 | string line = "200712 1326 3 -27 0.6 14.097006 HB9FID JN47 37 0 306 0"; 48 | var spot = new WsprSpot(line); 49 | 50 | Assert.AreEqual(2020, spot.dt.Year); 51 | Assert.AreEqual(7, spot.dt.Month); 52 | Assert.AreEqual(12, spot.dt.Day); 53 | Assert.AreEqual(13, spot.dt.Hour); 54 | Assert.AreEqual(26, spot.dt.Minute); 55 | Assert.AreEqual(0, spot.dt.Second); 56 | Assert.AreEqual("2007121326", spot.timestamp); 57 | Assert.AreEqual(-27, spot.strength); 58 | Assert.AreEqual(14.097006, spot.frequencyMHz); 59 | Assert.AreEqual(14_097_006, spot.frequencyHz); 60 | Assert.AreEqual("HB9FID", spot.callsign); 61 | Assert.AreEqual("JN47", spot.grid); 62 | Assert.IsTrue(spot.isValid); 63 | } 64 | 65 | [TestMethod] 66 | public void Test_LogFormat_73c() 67 | { 68 | string line = "200712 1322 1 -28 -1.1 14.097110 JO22LH 27 -1 5495 -2"; 69 | var spot = new WsprSpot(line); 70 | 71 | Assert.AreEqual(2020, spot.dt.Year); 72 | Assert.AreEqual(7, spot.dt.Month); 73 | Assert.AreEqual(12, spot.dt.Day); 74 | Assert.AreEqual(13, spot.dt.Hour); 75 | Assert.AreEqual(22, spot.dt.Minute); 76 | Assert.AreEqual(0, spot.dt.Second); 77 | Assert.AreEqual("2007121322", spot.timestamp); 78 | Assert.AreEqual(-28, spot.strength); 79 | Assert.AreEqual(14.097110, spot.frequencyMHz); 80 | Assert.AreEqual(14_097_110, spot.frequencyHz); 81 | Assert.AreEqual("PA0ANH", spot.callsign); 82 | Assert.AreEqual("JO22LH", spot.grid); 83 | Assert.IsTrue(spot.isValid); 84 | } 85 | 86 | [TestMethod] 87 | public void Test_LogFormat_73d() 88 | { 89 | string line = "200712 1036 5 -27 -0.5 14.097014 <...> B000AA 63 0 2 0"; 90 | var spot = new WsprSpot(line); 91 | 92 | Assert.AreEqual(2020, spot.dt.Year); 93 | Assert.AreEqual(7, spot.dt.Month); 94 | Assert.AreEqual(12, spot.dt.Day); 95 | Assert.AreEqual(10, spot.dt.Hour); 96 | Assert.AreEqual(36, spot.dt.Minute); 97 | Assert.AreEqual(0, spot.dt.Second); 98 | Assert.AreEqual("2007121036", spot.timestamp); 99 | Assert.AreEqual(-27, spot.strength); 100 | Assert.AreEqual(14.097014, spot.frequencyMHz); 101 | Assert.AreEqual(14_097_014, spot.frequencyHz); 102 | Assert.IsNull(spot.callsign); 103 | Assert.AreEqual("B000AA", spot.grid); 104 | Assert.IsFalse(spot.isValid); 105 | } 106 | 107 | [TestMethod] 108 | public void Test_LogFormat_88() 109 | { 110 | string line = "200713 1908 4 -17 0.32 14.0970666 DL6NL JO50 27 0 1 0 1 527 0"; 111 | var spot = new WsprSpot(line); 112 | 113 | Assert.AreEqual(2020, spot.dt.Year); 114 | Assert.AreEqual(7, spot.dt.Month); 115 | Assert.AreEqual(13, spot.dt.Day); 116 | Assert.AreEqual(19, spot.dt.Hour); 117 | Assert.AreEqual(8, spot.dt.Minute); 118 | Assert.AreEqual(0, spot.dt.Second); 119 | Assert.AreEqual("2007131908", spot.timestamp); 120 | Assert.AreEqual(-17, spot.strength); 121 | Assert.AreEqual(14.0970666, spot.frequencyMHz); 122 | Assert.AreEqual(14_097_066.6, spot.frequencyHz); 123 | Assert.AreEqual("DL6NL", spot.callsign); 124 | Assert.AreEqual("JO50", spot.grid); 125 | Assert.IsTrue(spot.isValid); 126 | } 127 | 128 | [TestMethod] 129 | public void Test_LogFormat_96() 130 | { 131 | string line = "200603 1720 -27 -1.34 10.1401891 N8XEF EM99 37 3 0.13 1 1 0 1 38 1 810"; 132 | var spot = new WsprSpot(line); 133 | 134 | Assert.AreEqual(2020, spot.dt.Year); 135 | Assert.AreEqual(6, spot.dt.Month); 136 | Assert.AreEqual(3, spot.dt.Day); 137 | Assert.AreEqual(17, spot.dt.Hour); 138 | Assert.AreEqual(20, spot.dt.Minute); 139 | Assert.AreEqual(0, spot.dt.Second); 140 | Assert.AreEqual("2006031720", spot.timestamp); 141 | Assert.AreEqual(-27, spot.strength); 142 | Assert.AreEqual(10.1401891, spot.frequencyMHz); 143 | Assert.AreEqual(10_140_189.1, spot.frequencyHz); 144 | Assert.AreEqual("N8XEF", spot.callsign); 145 | Assert.AreEqual("EM99", spot.grid); 146 | Assert.IsTrue(spot.isValid); 147 | } 148 | 149 | [TestMethod] 150 | public void Test_LogFormat_FT() 151 | { 152 | string line = "191011_130213 14.080 Rx FT4 -16 0.2 2012 UA4CCH YO9NC -07"; 153 | var spot = new WsprSpot(line); 154 | 155 | Assert.AreEqual(2019, spot.dt.Year); 156 | Assert.AreEqual(10, spot.dt.Month); 157 | Assert.AreEqual(11, spot.dt.Day); 158 | Assert.AreEqual(13, spot.dt.Hour); 159 | Assert.AreEqual(2, spot.dt.Minute); 160 | Assert.AreEqual(13, spot.dt.Second); 161 | Assert.AreEqual("191011130213", spot.timestamp); 162 | Assert.AreEqual(-16, spot.strength); 163 | Assert.AreEqual(14.080 + 0.002012, spot.frequencyMHz); 164 | Assert.AreEqual(14_082_012, spot.frequencyHz); 165 | Assert.AreEqual("UA4CCH YO9NC -07", spot.callsign); 166 | Assert.IsTrue(spot.isValid); 167 | } 168 | 169 | [TestMethod] 170 | public void Test_LogFormat_garbage() 171 | { 172 | string line = "sdaf jldafj sdjfjas jfej alsjflk jes"; 173 | var spot = new WsprSpot(line); 174 | 175 | Assert.IsFalse(spot.isValid); 176 | } 177 | 178 | [TestMethod] 179 | public void Test_LogFormat_empty() 180 | { 181 | string line = ""; 182 | var spot = new WsprSpot(line); 183 | 184 | Assert.IsFalse(spot.isValid); 185 | } 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /src/FSKview.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/FSKview.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.31919.166 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FSKview", "FSKview\FSKview.csproj", "{4C287EDE-C5EB-4975-AC81-6E87907F6B2F}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FSKview.Tests", "FSKview.Tests\FSKview.Tests.csproj", "{C0268297-79D4-4F73-BE96-55CB4F29BB36}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {4C287EDE-C5EB-4975-AC81-6E87907F6B2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {4C287EDE-C5EB-4975-AC81-6E87907F6B2F}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {4C287EDE-C5EB-4975-AC81-6E87907F6B2F}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {4C287EDE-C5EB-4975-AC81-6E87907F6B2F}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {C0268297-79D4-4F73-BE96-55CB4F29BB36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {C0268297-79D4-4F73-BE96-55CB4F29BB36}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {C0268297-79D4-4F73-BE96-55CB4F29BB36}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {C0268297-79D4-4F73-BE96-55CB4F29BB36}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {2683882F-A64C-41E0-89FD-AE83214FAC6C} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /src/FSKview/AGC.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace FSKview 8 | { 9 | public static class AGC 10 | { 11 | private readonly static Random Rand = new Random(); 12 | 13 | /// 14 | /// Return a copy of the input with the noise floor subtracted from it. 15 | /// Noise floor is calculated as the mean of the quietest 20% of values. 16 | /// 17 | public static double[] Method1_SortedFloorMean(double[] input, int windowSizePx = 10, double percentile = .2, double power = 1) 18 | { 19 | double[] normalized = new double[input.Length]; 20 | 21 | double[] segment = new double[windowSizePx * 2 + 1]; 22 | int valuesInFloor = (int)(percentile * segment.Length); 23 | 24 | for (int i = windowSizePx; i < input.Length - windowSizePx; i++) 25 | { 26 | for (int j = 0; j < segment.Length; j++) 27 | segment[j] = input[i + j - windowSizePx]; 28 | 29 | Array.Sort(segment); 30 | 31 | double meanFloor = segment.Take(valuesInFloor).Sum() / valuesInFloor; 32 | normalized[i] = Math.Max(input[i] - meanFloor * power, 0); 33 | } 34 | 35 | return normalized; 36 | } 37 | 38 | /// 39 | /// Return a copy of the input with the noise floor subtracted from it. 40 | /// Noise floor is calculated as the mean of the quietest 20% of values. 41 | /// 42 | public static double[] Method2_QuicksortFloor(double[] input, int windowSizePx = 10, double percentile = .2, double power = 1) 43 | { 44 | double[] normalized = new double[input.Length]; 45 | 46 | double[] segment = new double[windowSizePx * 2 + 1]; 47 | int valuesInFloor = (int)(percentile * segment.Length); 48 | 49 | for (int i = windowSizePx; i < input.Length - windowSizePx; i++) 50 | { 51 | for (int j = 0; j < segment.Length; j++) 52 | segment[j] = input[i + j - windowSizePx]; 53 | 54 | Array.Sort(segment); 55 | 56 | double meanFloor = segment.Take(valuesInFloor).Sum() / valuesInFloor; 57 | normalized[i] = Math.Max(input[i] - meanFloor * power, 0); 58 | } 59 | 60 | return normalized; 61 | } 62 | 63 | /// 64 | /// Return the percentile of the given array 65 | /// 66 | /// 67 | /// number from 0 to 100 68 | /// 69 | private static double Percentile(double[] values, int percentile) => Quantile(values, percentile, 100); 70 | 71 | /// 72 | /// Return the Nth smallest value in the given array. 73 | /// 74 | private static double NthOrderStatistic(double[] values, int n) 75 | { 76 | if (n < 1 || n > values.Length) 77 | throw new ArgumentException("n must be a number from 1 to the length of the array"); 78 | 79 | double[] valuesCopy = new double[values.Length]; 80 | Array.Copy(values, valuesCopy, values.Length); 81 | return QuickSelect(valuesCopy, 0, values.Length - 1, n - 1); 82 | } 83 | 84 | /// 85 | /// Return the value of the Nth quantile. 86 | /// 87 | private static double Quantile(double[] values, int n, int quantileCount) 88 | { 89 | if (n == 0) 90 | return values.Min(); 91 | else if (n == quantileCount) 92 | return values.Max(); 93 | else 94 | return NthOrderStatistic(values, n * values.Length / quantileCount); 95 | } 96 | 97 | /// 98 | /// Return the kth smallest value from a range of the given array. 99 | /// WARNING: values will be mutated. 100 | /// 101 | /// 102 | /// inclusive lower bound 103 | /// inclusive upper bound 104 | /// number starting at 0 105 | /// 106 | private static double QuickSelect(double[] values, int leftIndex, int rightIndex, int k) 107 | { 108 | /* 109 | * QuickSelect (aka Hoare's Algorithm) is a selection algorithm 110 | * - Given an integer k it returns the kth smallest element in a sequence) with O(n) expected time. 111 | * - In the worst case it is O(n^2), i.e. when the chosen pivot is always the max or min at each call. 112 | * - The use of a random pivot virtually assures linear time performance. 113 | * - https://en.wikipedia.org/wiki/Quickselect 114 | */ 115 | 116 | if (leftIndex == rightIndex) 117 | return values[leftIndex]; 118 | 119 | if (k == 0) 120 | { 121 | double min = values[leftIndex]; 122 | for (int j = leftIndex; j <= rightIndex; j++) 123 | { 124 | if (values[j] < min) 125 | { 126 | min = values[j]; 127 | } 128 | } 129 | 130 | return min; 131 | } 132 | 133 | if (k == rightIndex - leftIndex) 134 | { 135 | double max = values[leftIndex]; 136 | for (int j = leftIndex; j <= rightIndex; j++) 137 | { 138 | if (values[j] > max) 139 | { 140 | max = values[j]; 141 | } 142 | } 143 | 144 | return max; 145 | } 146 | 147 | int partitionIndex = Partition(values, leftIndex, rightIndex); 148 | int pivotIndex = partitionIndex - leftIndex; 149 | 150 | if (k == pivotIndex) 151 | return values[partitionIndex]; 152 | else if (k < pivotIndex) 153 | return QuickSelect(values, leftIndex, partitionIndex - 1, k); 154 | else 155 | return QuickSelect(values, partitionIndex + 1, rightIndex, k - pivotIndex - 1); 156 | } 157 | 158 | /// 159 | /// Partition the array between the defined bounds according to elements above and below a randomly chosen pivot value 160 | /// 161 | /// 162 | /// 163 | /// 164 | /// index of the pivot used 165 | private static int Partition(double[] values, int leftIndex, int rightIndex) 166 | { 167 | // Moving the pivot to the end is far easier than handling it where it is 168 | // This also allows you to turn this into the non-randomized Partition 169 | int initialPivotIndex = Rand.Next(leftIndex, rightIndex + 1); 170 | double swap = values[initialPivotIndex]; 171 | values[initialPivotIndex] = values[rightIndex]; 172 | values[rightIndex] = swap; 173 | 174 | double pivotValue = values[rightIndex]; 175 | 176 | int pivotIndex = leftIndex - 1; 177 | for (int j = leftIndex; j < rightIndex; j++) 178 | { 179 | if (values[j] <= pivotValue) 180 | { 181 | pivotIndex++; 182 | double tmp1 = values[j]; 183 | values[j] = values[pivotIndex]; 184 | values[pivotIndex] = tmp1; 185 | } 186 | } 187 | 188 | pivotIndex++; 189 | double tmp2 = values[rightIndex]; 190 | values[rightIndex] = values[pivotIndex]; 191 | values[pivotIndex] = tmp2; 192 | 193 | return pivotIndex; 194 | } 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /src/FSKview/Annotate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics.Contracts; 4 | using System.Drawing; 5 | using System.Drawing.Imaging; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | #pragma warning disable CA1416 // Ignore System.Drawing platform compatibility 11 | 12 | namespace FSKview 13 | { 14 | static class Annotate 15 | { 16 | public static void Spectrogram( 17 | Spectrogram.Spectrogram spec, WsprBand band, List spots, 18 | Bitmap bmpSpectrogram, Bitmap bmpVericalScale, 19 | bool drawBandLines, bool drawVerticalLine, ProgramSettings settings) 20 | { 21 | using (Graphics gfx = Graphics.FromImage(bmpSpectrogram)) 22 | using (Bitmap bmpIndexed = spec.GetBitmapMax(settings.brightness, reduction: settings.verticalReduction, roll: settings.roll)) 23 | using (Pen bandEdgePen = new Pen(Color.White) { DashStyle = System.Drawing.Drawing2D.DashStyle.Dash }) 24 | using (Pen grabEdgePen = new Pen(Color.Yellow) { DashStyle = System.Drawing.Drawing2D.DashStyle.Dash }) 25 | using (Pen rollPen = new Pen(Color.White)) 26 | using (var font = new Font("consolas", 10, FontStyle.Bold)) 27 | using (var sfMiddleCenter = new StringFormat { LineAlignment = StringAlignment.Center, Alignment = StringAlignment.Center }) 28 | using (var sfUpperLeft = new StringFormat { LineAlignment = StringAlignment.Near, Alignment = StringAlignment.Near }) 29 | { 30 | // copy source bitmaps onto this display bitmap 31 | gfx.DrawImage(bmpIndexed, 0, 0); 32 | gfx.DrawImage(bmpVericalScale, spec.Width, 0); 33 | 34 | int wsprBandTopPx = spec.PixelY(band.upperFreq - band.dialFreq, settings.verticalReduction) + 1; 35 | int wsprBandBottomPx = spec.PixelY(band.lowerFreq - band.dialFreq, settings.verticalReduction) + 1; 36 | int qrssBandBottomPx = spec.PixelY(band.lowerFreq - band.dialFreq - 200, settings.verticalReduction) + 1; 37 | int grabTopPx = wsprBandTopPx - settings.grabSavePxAbove; 38 | int grabBotPx = qrssBandBottomPx + settings.grabSavePxBelow; 39 | 40 | if (drawBandLines) 41 | { 42 | gfx.DrawLine(bandEdgePen, 0, wsprBandTopPx, spec.Width, wsprBandTopPx); 43 | gfx.DrawLine(bandEdgePen, 0, wsprBandBottomPx, spec.Width, wsprBandBottomPx); 44 | gfx.DrawLine(bandEdgePen, 0, qrssBandBottomPx, spec.Width, qrssBandBottomPx); 45 | gfx.DrawLine(grabEdgePen, 0, grabTopPx - 1, spec.Width, grabTopPx - 1); 46 | gfx.DrawLine(grabEdgePen, 0, grabBotPx, spec.Width, grabBotPx); 47 | } 48 | 49 | if (settings.showTimeLines) 50 | { 51 | using Pen pen = new(Color.FromArgb(100, Color.White)); 52 | pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash; 53 | for (int i = 1; i < 10; i++) 54 | { 55 | int pxFromLeft = (int)(i * 60 / spec.SecPerPx); 56 | gfx.DrawLine(pen, pxFromLeft, 0, pxFromLeft, spec.Height); 57 | } 58 | } 59 | 60 | if (settings.roll && drawVerticalLine) 61 | gfx.DrawLine(rollPen, spec.NextColumnIndex, 0, spec.NextColumnIndex, spec.Height); 62 | 63 | if (settings.isWsprEnabled == false) 64 | return; 65 | 66 | // plot spots in a single segment (the 2m block within a 10m time frame) 67 | for (int segment = 0; segment < 5; segment++) 68 | { 69 | WsprSpot[] segmentSpots = spots 70 | .Where(x => x.segment == segment) // only this segment 71 | .Where(x => Math.Abs(x.frequencyHz - band.dialFreq) < 1e5) // only this band 72 | .OrderBy(x => x.strength).GroupBy(x => x.callsign).Select(x => x.Last()) // only strongest 73 | .OrderBy(x => x.frequencyHz).Reverse().ToArray(); // top to bottom 74 | 75 | int segmentX = spec.Width * segment / 5; 76 | if (settings.roll == false && segmentSpots.Length > 0) 77 | segmentX = (int)(spec.Width - segmentSpots[0].ageSec / spec.SecPerPx) + 10; 78 | 79 | for (int spotIndex = 0; spotIndex < segmentSpots.Length; spotIndex++) 80 | { 81 | WsprSpot spot = segmentSpots[spotIndex]; 82 | 83 | int r = 7; 84 | int y = spec.PixelY(spot.frequencyHz - band.dialFreq, settings.verticalReduction); 85 | 86 | // draw the marker 87 | if (spot.isWspr) 88 | { 89 | int xSpot = segmentX + r * 2 * (spotIndex % 8 + 1); 90 | 91 | // determine where to place the marker 92 | gfx.FillEllipse(Brushes.Black, xSpot - r, y - r, r * 2, r * 2); 93 | gfx.DrawString($"{spotIndex + 1}", font, Brushes.White, xSpot + 0.5f, y + 1, sfMiddleCenter); 94 | 95 | // draw the key label at the top of the band edge 96 | DrawStringWithShadow(gfx, $"{spotIndex + 1}: {spot.callsign} ({spot.strength} dB) ", 97 | segmentX, wsprBandTopPx - settings.grabSavePxAbove + 13 * spotIndex, 98 | font, sfUpperLeft, Brushes.White, Brushes.Black); 99 | } 100 | else 101 | { 102 | // draw the callsign exactly where the spot is on the spectrogram 103 | int xSpot = (int)(segmentX + (spot.dt.Minute % 2 * 60 + spot.dt.Second) / spec.SecPerPx); 104 | DrawStringWithShadow(gfx, spot.callsign, xSpot, y, font, sfUpperLeft, Brushes.White, Brushes.Black); 105 | } 106 | } 107 | } 108 | } 109 | } 110 | 111 | public static void Logo(Graphics gfx, string message, float x, float y) 112 | { 113 | using (var font = new Font(FontFamily.GenericMonospace, 10, FontStyle.Bold)) 114 | using (var sfLowerLeft = new StringFormat { LineAlignment = StringAlignment.Far, Alignment = StringAlignment.Near }) 115 | { 116 | DrawStringWithShadow(gfx, message, x, y, font, sfLowerLeft, Brushes.White, Brushes.Black); 117 | } 118 | } 119 | 120 | public static void TimeTicks(Graphics gfx, float height, double secPerPx, int tickLength = 3) 121 | { 122 | using (var font = new Font(FontFamily.GenericMonospace, 10, FontStyle.Bold)) 123 | using (var sfLowerLeft = new StringFormat { LineAlignment = StringAlignment.Far, Alignment = StringAlignment.Near }) 124 | { 125 | for (int i = 1; i < 10; i++) 126 | { 127 | int seconds = i * 60; 128 | int pxFromLeft = (int)(seconds / secPerPx); 129 | gfx.DrawLine(Pens.Black, pxFromLeft - 1, height, pxFromLeft - 1, height - tickLength); 130 | gfx.DrawLine(Pens.Black, pxFromLeft + 1, height, pxFromLeft + 1, height - tickLength); 131 | gfx.DrawLine(Pens.White, pxFromLeft, height, pxFromLeft, height - tickLength); 132 | } 133 | } 134 | } 135 | 136 | public static void DrawStringWithShadow(Graphics gfx, String str, float x, float y, 137 | Font font, StringFormat sf, Brush foreground, Brush background) 138 | { 139 | for (int dx = -1; dx < 2; dx++) 140 | for (int dy = -1; dy < 2; dy++) 141 | if (dx != 0 || dy != 0) 142 | gfx.DrawString(str, font, background, x + dx, y + dy, sf); 143 | 144 | gfx.DrawString(str, font, foreground, x, y, sf); 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/FSKview/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/FSKview/AudioControl.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace FSKview 2 | { 3 | partial class AudioControl 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.components = new System.ComponentModel.Container(); 32 | this.label1 = new System.Windows.Forms.Label(); 33 | this.comboBox1 = new System.Windows.Forms.ComboBox(); 34 | this.pictureBox2 = new System.Windows.Forms.PictureBox(); 35 | this.panel1 = new System.Windows.Forms.Panel(); 36 | this.timer1 = new System.Windows.Forms.Timer(this.components); 37 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit(); 38 | this.panel1.SuspendLayout(); 39 | this.SuspendLayout(); 40 | // 41 | // label1 42 | // 43 | this.label1.AutoSize = true; 44 | this.label1.Location = new System.Drawing.Point(0, 0); 45 | this.label1.Name = "label1"; 46 | this.label1.Size = new System.Drawing.Size(61, 13); 47 | this.label1.TabIndex = 3; 48 | this.label1.Text = "Audio Input"; 49 | // 50 | // comboBox1 51 | // 52 | this.comboBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 53 | | System.Windows.Forms.AnchorStyles.Right))); 54 | this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; 55 | this.comboBox1.FormattingEnabled = true; 56 | this.comboBox1.Location = new System.Drawing.Point(3, 16); 57 | this.comboBox1.Name = "comboBox1"; 58 | this.comboBox1.Size = new System.Drawing.Size(155, 21); 59 | this.comboBox1.TabIndex = 2; 60 | this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged); 61 | // 62 | // pictureBox2 63 | // 64 | this.pictureBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 65 | | System.Windows.Forms.AnchorStyles.Left))); 66 | this.pictureBox2.BackColor = System.Drawing.Color.DarkSeaGreen; 67 | this.pictureBox2.Location = new System.Drawing.Point(0, 0); 68 | this.pictureBox2.Name = "pictureBox2"; 69 | this.pictureBox2.Size = new System.Drawing.Size(64, 11); 70 | this.pictureBox2.TabIndex = 5; 71 | this.pictureBox2.TabStop = false; 72 | // 73 | // panel1 74 | // 75 | this.panel1.BackColor = System.Drawing.SystemColors.ControlLight; 76 | this.panel1.Controls.Add(this.pictureBox2); 77 | this.panel1.Location = new System.Drawing.Point(67, 2); 78 | this.panel1.Name = "panel1"; 79 | this.panel1.Size = new System.Drawing.Size(91, 11); 80 | this.panel1.TabIndex = 6; 81 | // 82 | // timer1 83 | // 84 | this.timer1.Enabled = true; 85 | this.timer1.Interval = 10; 86 | this.timer1.Tick += new System.EventHandler(this.timer1_Tick); 87 | // 88 | // AudioControl 89 | // 90 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 91 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 92 | this.Controls.Add(this.panel1); 93 | this.Controls.Add(this.label1); 94 | this.Controls.Add(this.comboBox1); 95 | this.Name = "AudioControl"; 96 | this.Size = new System.Drawing.Size(161, 41); 97 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).EndInit(); 98 | this.panel1.ResumeLayout(false); 99 | this.ResumeLayout(false); 100 | this.PerformLayout(); 101 | 102 | } 103 | 104 | #endregion 105 | 106 | private System.Windows.Forms.Label label1; 107 | private System.Windows.Forms.ComboBox comboBox1; 108 | private System.Windows.Forms.PictureBox pictureBox2; 109 | private System.Windows.Forms.Panel panel1; 110 | private System.Windows.Forms.Timer timer1; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/FSKview/AudioControl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using System.Security.Cryptography.X509Certificates; 11 | 12 | namespace FSKview 13 | { 14 | public partial class AudioControl : UserControl 15 | { 16 | public Listener listener; 17 | public event EventHandler InputDeviceChanged; 18 | 19 | [ 20 | Category("Audio"), 21 | Description("Audio device sample rate (Hz)") 22 | ] 23 | public int SampleRate { get; set; } = 6000; 24 | public int AudioDeviceIndex { get { return comboBox1.SelectedIndex; } } 25 | 26 | public AudioControl() 27 | { 28 | InitializeComponent(); 29 | 30 | if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) 31 | return; 32 | 33 | pictureBox2.Width = 0; 34 | 35 | comboBox1.Items.AddRange(Enumerable 36 | .Range(0, NAudio.Wave.WaveIn.DeviceCount) 37 | .Select(x => NAudio.Wave.WaveIn.GetCapabilities(x).ProductName) 38 | .ToArray()); 39 | 40 | if (comboBox1.Items.Count == 0) 41 | MessageBox.Show("No audio input devices were found.", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error); 42 | } 43 | 44 | public void SelectDevice(int deviceIndex) 45 | { 46 | if (deviceIndex > comboBox1.Items.Count - 1) 47 | deviceIndex = comboBox1.Items.Count - 1; 48 | if (deviceIndex < 0) 49 | deviceIndex = 0; 50 | comboBox1.SelectedIndex = deviceIndex; 51 | } 52 | 53 | private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) 54 | { 55 | listener?.Dispose(); 56 | listener = new Listener(comboBox1.SelectedIndex, SampleRate); 57 | InputDeviceChanged?.Invoke(this, e); 58 | } 59 | 60 | private void timer1_Tick(object sender, EventArgs e) 61 | { 62 | if (listener is null) 63 | return; 64 | int targetWidth = (int)(listener.AmplitudeFrac * panel1.Width); 65 | pictureBox2.Width = (targetWidth >= pictureBox2.Width) ? targetWidth : pictureBox2.Width - 1; 66 | pictureBox2.BackColor = (listener.AmplitudeFrac < .9) ? Color.LightSeaGreen : Color.Magenta; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/FSKview/AudioControl.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 17 122 | 123 | -------------------------------------------------------------------------------- /src/FSKview/FSKview.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net6.0-windows;net48 4 | WinExe 5 | false 6 | true 7 | latest 8 | fskview-icon.ico 9 | true 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/FSKview/FTP.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Net; 4 | 5 | #pragma warning disable SYSLIB0014 // Ignore obsolete WebClient 6 | 7 | namespace FSKview 8 | { 9 | public static class FTP 10 | { 11 | public static string Upload(string serverAddress, string remoteFolder, string username, string password, string localPath) 12 | { 13 | string prefix = serverAddress.StartsWith("ftp://", StringComparison.OrdinalIgnoreCase) ? "" : "ftp://"; 14 | string uploadFolder = $"{prefix}{serverAddress}/{remoteFolder}/"; 15 | 16 | try 17 | { 18 | using (var client = new WebClient()) 19 | { 20 | client.Credentials = new NetworkCredential(username, password); 21 | string uploadPath = uploadFolder + Path.GetFileName(localPath); 22 | client.UploadFile(uploadPath, WebRequestMethods.Ftp.UploadFile, localPath); 23 | return "upload successful"; 24 | } 25 | } 26 | catch (Exception ex) 27 | { 28 | return ex.ToString(); 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/FSKview/FormMain.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace FSKview 2 | { 3 | partial class FormMain 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.components = new System.ComponentModel.Container(); 32 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormMain)); 33 | this.nudBrightness = new System.Windows.Forms.NumericUpDown(); 34 | this.label1 = new System.Windows.Forms.Label(); 35 | this.cbColormap = new System.Windows.Forms.ComboBox(); 36 | this.label2 = new System.Windows.Forms.Label(); 37 | this.cbWindow = new System.Windows.Forms.ComboBox(); 38 | this.label3 = new System.Windows.Forms.Label(); 39 | this.cbDialFreq = new System.Windows.Forms.ComboBox(); 40 | this.label4 = new System.Windows.Forms.Label(); 41 | this.label5 = new System.Windows.Forms.Label(); 42 | this.lblTime = new System.Windows.Forms.Label(); 43 | this.btnConfigure = new System.Windows.Forms.Button(); 44 | this.cbWspr = new System.Windows.Forms.CheckBox(); 45 | this.panel1 = new System.Windows.Forms.Panel(); 46 | this.pictureBox1 = new System.Windows.Forms.PictureBox(); 47 | this.statusStrip1 = new System.Windows.Forms.StatusStrip(); 48 | this.pbTimeFrac = new System.Windows.Forms.ToolStripProgressBar(); 49 | this.lblStatusTime = new System.Windows.Forms.ToolStripStatusLabel(); 50 | this.lblStatus = new System.Windows.Forms.ToolStripStatusLabel(); 51 | this.lblVersion = new System.Windows.Forms.ToolStripStatusLabel(); 52 | this.timerUpdateSpectrogram = new System.Windows.Forms.Timer(this.components); 53 | this.cbSave = new System.Windows.Forms.CheckBox(); 54 | this.timerWsprUpdate = new System.Windows.Forms.Timer(this.components); 55 | this.cbBands = new System.Windows.Forms.CheckBox(); 56 | this.audioControl1 = new FSKview.AudioControl(); 57 | this.cbFTP = new System.Windows.Forms.CheckBox(); 58 | ((System.ComponentModel.ISupportInitialize)(this.nudBrightness)).BeginInit(); 59 | this.panel1.SuspendLayout(); 60 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); 61 | this.statusStrip1.SuspendLayout(); 62 | this.SuspendLayout(); 63 | // 64 | // nudBrightness 65 | // 66 | this.nudBrightness.DecimalPlaces = 1; 67 | this.nudBrightness.Increment = new decimal(new int[] { 68 | 1, 69 | 0, 70 | 0, 71 | 65536}); 72 | this.nudBrightness.Location = new System.Drawing.Point(716, 30); 73 | this.nudBrightness.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); 74 | this.nudBrightness.Name = "nudBrightness"; 75 | this.nudBrightness.Size = new System.Drawing.Size(62, 23); 76 | this.nudBrightness.TabIndex = 5; 77 | this.nudBrightness.Value = new decimal(new int[] { 78 | 2, 79 | 0, 80 | 0, 81 | 0}); 82 | this.nudBrightness.ValueChanged += new System.EventHandler(this.nudBrightness_ValueChanged); 83 | // 84 | // label1 85 | // 86 | this.label1.AutoSize = true; 87 | this.label1.Location = new System.Drawing.Point(713, 10); 88 | this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); 89 | this.label1.Name = "label1"; 90 | this.label1.Size = new System.Drawing.Size(62, 15); 91 | this.label1.TabIndex = 6; 92 | this.label1.Text = "Brightness"; 93 | // 94 | // cbColormap 95 | // 96 | this.cbColormap.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; 97 | this.cbColormap.FormattingEnabled = true; 98 | this.cbColormap.Location = new System.Drawing.Point(350, 29); 99 | this.cbColormap.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); 100 | this.cbColormap.Name = "cbColormap"; 101 | this.cbColormap.Size = new System.Drawing.Size(140, 23); 102 | this.cbColormap.TabIndex = 7; 103 | this.cbColormap.SelectedIndexChanged += new System.EventHandler(this.cbColormap_SelectedIndexChanged); 104 | // 105 | // label2 106 | // 107 | this.label2.AutoSize = true; 108 | this.label2.Location = new System.Drawing.Point(346, 10); 109 | this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); 110 | this.label2.Name = "label2"; 111 | this.label2.Size = new System.Drawing.Size(60, 15); 112 | this.label2.TabIndex = 8; 113 | this.label2.Text = "Colormap"; 114 | // 115 | // cbWindow 116 | // 117 | this.cbWindow.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; 118 | this.cbWindow.FormattingEnabled = true; 119 | this.cbWindow.Location = new System.Drawing.Point(202, 29); 120 | this.cbWindow.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); 121 | this.cbWindow.Name = "cbWindow"; 122 | this.cbWindow.Size = new System.Drawing.Size(140, 23); 123 | this.cbWindow.TabIndex = 9; 124 | this.cbWindow.SelectedIndexChanged += new System.EventHandler(this.cbWindow_SelectedIndexChanged); 125 | // 126 | // label3 127 | // 128 | this.label3.AutoSize = true; 129 | this.label3.Location = new System.Drawing.Point(198, 10); 130 | this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); 131 | this.label3.Name = "label3"; 132 | this.label3.Size = new System.Drawing.Size(51, 15); 133 | this.label3.TabIndex = 10; 134 | this.label3.Text = "Window"; 135 | // 136 | // cbDialFreq 137 | // 138 | this.cbDialFreq.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; 139 | this.cbDialFreq.FormattingEnabled = true; 140 | this.cbDialFreq.Location = new System.Drawing.Point(498, 29); 141 | this.cbDialFreq.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); 142 | this.cbDialFreq.Name = "cbDialFreq"; 143 | this.cbDialFreq.Size = new System.Drawing.Size(210, 23); 144 | this.cbDialFreq.TabIndex = 11; 145 | this.cbDialFreq.SelectedIndexChanged += new System.EventHandler(this.cbDialFreq_SelectedIndexChanged); 146 | // 147 | // label4 148 | // 149 | this.label4.AutoSize = true; 150 | this.label4.Location = new System.Drawing.Point(495, 10); 151 | this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); 152 | this.label4.Name = "label4"; 153 | this.label4.Size = new System.Drawing.Size(85, 15); 154 | this.label4.TabIndex = 12; 155 | this.label4.Text = "Dial Frequency"; 156 | // 157 | // label5 158 | // 159 | this.label5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 160 | this.label5.Font = new System.Drawing.Font("Segoe UI Semibold", 14.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point); 161 | this.label5.Location = new System.Drawing.Point(1049, 5); 162 | this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); 163 | this.label5.Name = "label5"; 164 | this.label5.Size = new System.Drawing.Size(117, 30); 165 | this.label5.TabIndex = 13; 166 | this.label5.Text = "FSKview"; 167 | this.label5.TextAlign = System.Drawing.ContentAlignment.BottomCenter; 168 | // 169 | // lblTime 170 | // 171 | this.lblTime.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 172 | this.lblTime.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); 173 | this.lblTime.ForeColor = System.Drawing.SystemColors.ControlDark; 174 | this.lblTime.Location = new System.Drawing.Point(1049, 35); 175 | this.lblTime.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); 176 | this.lblTime.Name = "lblTime"; 177 | this.lblTime.Size = new System.Drawing.Size(117, 30); 178 | this.lblTime.TabIndex = 14; 179 | this.lblTime.Text = "23:17:00 UTC"; 180 | this.lblTime.TextAlign = System.Drawing.ContentAlignment.TopCenter; 181 | // 182 | // btnConfigure 183 | // 184 | this.btnConfigure.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); 185 | this.btnConfigure.Location = new System.Drawing.Point(931, 16); 186 | this.btnConfigure.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); 187 | this.btnConfigure.Name = "btnConfigure"; 188 | this.btnConfigure.Size = new System.Drawing.Size(69, 28); 189 | this.btnConfigure.TabIndex = 15; 190 | this.btnConfigure.Text = "Settings"; 191 | this.btnConfigure.UseVisualStyleBackColor = true; 192 | this.btnConfigure.Click += new System.EventHandler(this.btnConfigure_Click); 193 | // 194 | // cbWspr 195 | // 196 | this.cbWspr.AutoSize = true; 197 | this.cbWspr.Checked = true; 198 | this.cbWspr.CheckState = System.Windows.Forms.CheckState.Checked; 199 | this.cbWspr.Location = new System.Drawing.Point(869, 7); 200 | this.cbWspr.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); 201 | this.cbWspr.Name = "cbWspr"; 202 | this.cbWspr.Size = new System.Drawing.Size(57, 19); 203 | this.cbWspr.TabIndex = 17; 204 | this.cbWspr.Text = "WSPR"; 205 | this.cbWspr.UseVisualStyleBackColor = true; 206 | this.cbWspr.CheckedChanged += new System.EventHandler(this.cbWspr_CheckedChanged); 207 | // 208 | // panel1 209 | // 210 | this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 211 | | System.Windows.Forms.AnchorStyles.Left) 212 | | System.Windows.Forms.AnchorStyles.Right))); 213 | this.panel1.AutoScroll = true; 214 | this.panel1.BackColor = System.Drawing.SystemColors.ControlDark; 215 | this.panel1.Controls.Add(this.pictureBox1); 216 | this.panel1.Location = new System.Drawing.Point(0, 61); 217 | this.panel1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); 218 | this.panel1.Name = "panel1"; 219 | this.panel1.Size = new System.Drawing.Size(1166, 477); 220 | this.panel1.TabIndex = 18; 221 | // 222 | // pictureBox1 223 | // 224 | this.pictureBox1.BackColor = System.Drawing.Color.Purple; 225 | this.pictureBox1.Location = new System.Drawing.Point(0, 0); 226 | this.pictureBox1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); 227 | this.pictureBox1.Name = "pictureBox1"; 228 | this.pictureBox1.Size = new System.Drawing.Size(735, 361); 229 | this.pictureBox1.TabIndex = 0; 230 | this.pictureBox1.TabStop = false; 231 | // 232 | // statusStrip1 233 | // 234 | this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 235 | this.pbTimeFrac, 236 | this.lblStatusTime, 237 | this.lblStatus, 238 | this.lblVersion}); 239 | this.statusStrip1.Location = new System.Drawing.Point(0, 539); 240 | this.statusStrip1.Name = "statusStrip1"; 241 | this.statusStrip1.Padding = new System.Windows.Forms.Padding(1, 0, 16, 0); 242 | this.statusStrip1.Size = new System.Drawing.Size(1166, 24); 243 | this.statusStrip1.TabIndex = 19; 244 | this.statusStrip1.Text = "statusStrip1"; 245 | // 246 | // pbTimeFrac 247 | // 248 | this.pbTimeFrac.Maximum = 600; 249 | this.pbTimeFrac.Name = "pbTimeFrac"; 250 | this.pbTimeFrac.Size = new System.Drawing.Size(117, 18); 251 | this.pbTimeFrac.Value = 123; 252 | // 253 | // lblStatusTime 254 | // 255 | this.lblStatusTime.Name = "lblStatusTime"; 256 | this.lblStatusTime.Size = new System.Drawing.Size(31, 19); 257 | this.lblStatusTime.Text = "time"; 258 | // 259 | // lblStatus 260 | // 261 | this.lblStatus.Name = "lblStatus"; 262 | this.lblStatus.Size = new System.Drawing.Size(954, 19); 263 | this.lblStatus.Spring = true; 264 | this.lblStatus.Text = "status"; 265 | // 266 | // lblVersion 267 | // 268 | this.lblVersion.Name = "lblVersion"; 269 | this.lblVersion.Size = new System.Drawing.Size(45, 19); 270 | this.lblVersion.Text = "version"; 271 | // 272 | // timerUpdateSpectrogram 273 | // 274 | this.timerUpdateSpectrogram.Enabled = true; 275 | this.timerUpdateSpectrogram.Interval = 1000; 276 | this.timerUpdateSpectrogram.Tick += new System.EventHandler(this.timerUpdateSpectrogram_Tick); 277 | // 278 | // cbSave 279 | // 280 | this.cbSave.AutoSize = true; 281 | this.cbSave.Checked = true; 282 | this.cbSave.CheckState = System.Windows.Forms.CheckState.Checked; 283 | this.cbSave.Location = new System.Drawing.Point(785, 31); 284 | this.cbSave.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); 285 | this.cbSave.Name = "cbSave"; 286 | this.cbSave.Size = new System.Drawing.Size(75, 19); 287 | this.cbSave.TabIndex = 21; 288 | this.cbSave.Text = "Autosave"; 289 | this.cbSave.UseVisualStyleBackColor = true; 290 | this.cbSave.CheckedChanged += new System.EventHandler(this.cbSave_CheckedChanged); 291 | // 292 | // timerWsprUpdate 293 | // 294 | this.timerWsprUpdate.Enabled = true; 295 | this.timerWsprUpdate.Interval = 500; 296 | this.timerWsprUpdate.Tick += new System.EventHandler(this.timerWsprUpdate_Tick); 297 | // 298 | // cbBands 299 | // 300 | this.cbBands.AutoSize = true; 301 | this.cbBands.Checked = true; 302 | this.cbBands.CheckState = System.Windows.Forms.CheckState.Checked; 303 | this.cbBands.Location = new System.Drawing.Point(785, 7); 304 | this.cbBands.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); 305 | this.cbBands.Name = "cbBands"; 306 | this.cbBands.Size = new System.Drawing.Size(58, 19); 307 | this.cbBands.TabIndex = 23; 308 | this.cbBands.Text = "Bands"; 309 | this.cbBands.UseVisualStyleBackColor = true; 310 | this.cbBands.CheckedChanged += new System.EventHandler(this.cbBands_CheckedChanged); 311 | // 312 | // audioControl1 313 | // 314 | this.audioControl1.Location = new System.Drawing.Point(10, 10); 315 | this.audioControl1.Margin = new System.Windows.Forms.Padding(0); 316 | this.audioControl1.Name = "audioControl1"; 317 | this.audioControl1.SampleRate = 6000; 318 | this.audioControl1.Size = new System.Drawing.Size(188, 47); 319 | this.audioControl1.TabIndex = 3; 320 | this.audioControl1.InputDeviceChanged += new System.EventHandler(this.audioControl1_InputDeviceChanged); 321 | // 322 | // cbFTP 323 | // 324 | this.cbFTP.AutoSize = true; 325 | this.cbFTP.Location = new System.Drawing.Point(869, 31); 326 | this.cbFTP.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); 327 | this.cbFTP.Name = "cbFTP"; 328 | this.cbFTP.Size = new System.Drawing.Size(45, 19); 329 | this.cbFTP.TabIndex = 24; 330 | this.cbFTP.Text = "FTP"; 331 | this.cbFTP.UseVisualStyleBackColor = true; 332 | this.cbFTP.CheckedChanged += new System.EventHandler(this.cbFTP_CheckedChanged); 333 | // 334 | // FormMain 335 | // 336 | this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); 337 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 338 | this.ClientSize = new System.Drawing.Size(1166, 563); 339 | this.Controls.Add(this.cbFTP); 340 | this.Controls.Add(this.cbSave); 341 | this.Controls.Add(this.cbBands); 342 | this.Controls.Add(this.statusStrip1); 343 | this.Controls.Add(this.panel1); 344 | this.Controls.Add(this.lblTime); 345 | this.Controls.Add(this.label5); 346 | this.Controls.Add(this.label4); 347 | this.Controls.Add(this.label3); 348 | this.Controls.Add(this.label2); 349 | this.Controls.Add(this.label1); 350 | this.Controls.Add(this.cbWspr); 351 | this.Controls.Add(this.btnConfigure); 352 | this.Controls.Add(this.cbDialFreq); 353 | this.Controls.Add(this.cbWindow); 354 | this.Controls.Add(this.cbColormap); 355 | this.Controls.Add(this.nudBrightness); 356 | this.Controls.Add(this.audioControl1); 357 | this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); 358 | this.Name = "FormMain"; 359 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 360 | this.Text = "FSKview"; 361 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormMain_FormClosing); 362 | this.Load += new System.EventHandler(this.FormMain_Load); 363 | ((System.ComponentModel.ISupportInitialize)(this.nudBrightness)).EndInit(); 364 | this.panel1.ResumeLayout(false); 365 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); 366 | this.statusStrip1.ResumeLayout(false); 367 | this.statusStrip1.PerformLayout(); 368 | this.ResumeLayout(false); 369 | this.PerformLayout(); 370 | 371 | } 372 | 373 | #endregion 374 | private AudioControl audioControl1; 375 | private System.Windows.Forms.NumericUpDown nudBrightness; 376 | private System.Windows.Forms.Label label1; 377 | private System.Windows.Forms.ComboBox cbColormap; 378 | private System.Windows.Forms.Label label2; 379 | private System.Windows.Forms.ComboBox cbWindow; 380 | private System.Windows.Forms.Label label3; 381 | private System.Windows.Forms.ComboBox cbDialFreq; 382 | private System.Windows.Forms.Label label4; 383 | private System.Windows.Forms.Label label5; 384 | private System.Windows.Forms.Label lblTime; 385 | private System.Windows.Forms.Button btnConfigure; 386 | private System.Windows.Forms.CheckBox cbWspr; 387 | private System.Windows.Forms.Panel panel1; 388 | private System.Windows.Forms.PictureBox pictureBox1; 389 | private System.Windows.Forms.StatusStrip statusStrip1; 390 | private System.Windows.Forms.ToolStripStatusLabel lblStatus; 391 | private System.Windows.Forms.Timer timerUpdateSpectrogram; 392 | private System.Windows.Forms.CheckBox cbSave; 393 | private System.Windows.Forms.Timer timerWsprUpdate; 394 | private System.Windows.Forms.CheckBox cbBands; 395 | private System.Windows.Forms.ToolStripStatusLabel lblVersion; 396 | private System.Windows.Forms.ToolStripProgressBar pbTimeFrac; 397 | private System.Windows.Forms.ToolStripStatusLabel lblStatusTime; 398 | private System.Windows.Forms.CheckBox cbFTP; 399 | } 400 | } 401 | 402 | -------------------------------------------------------------------------------- /src/FSKview/FormMain.cs: -------------------------------------------------------------------------------- 1 | using Spectrogram; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Data; 6 | using System.Diagnostics; 7 | using System.Drawing; 8 | using System.Drawing.Imaging; 9 | using System.IO; 10 | using System.Linq; 11 | using System.Reflection; 12 | using System.Text; 13 | using System.Threading.Tasks; 14 | using System.Windows.Forms; 15 | 16 | #pragma warning disable CA1416 // Ignore System.Drawing platform compatibility 17 | 18 | namespace FSKview 19 | { 20 | public partial class FormMain : Form 21 | { 22 | readonly ProgramSettings settings; 23 | readonly Version version = new(1, 3, 0); 24 | 25 | readonly Spectrogram.Colormap[] cmaps; 26 | WsprBand band; 27 | readonly List spots = new List(); 28 | readonly string appPath = Path.GetFullPath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)); 29 | 30 | readonly int verticalScaleWidth = 130; 31 | 32 | private string UtcTimeStamp { get { return $"{DateTime.UtcNow.Hour:D2}:{DateTime.UtcNow.Minute:D2}:{DateTime.UtcNow.Second:D2}"; } } 33 | private string UtcTimeStampNoSec { get { return $"{DateTime.UtcNow.Hour:D2}:{DateTime.UtcNow.Minute:D2}"; } } 34 | private string UtcDateStamp { get { return $"{DateTime.UtcNow.Year}-{DateTime.UtcNow.Month:D2}-{DateTime.UtcNow.Day:D2}"; } } 35 | 36 | public FormMain() 37 | { 38 | InitializeComponent(); 39 | 40 | if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) 41 | return; 42 | 43 | settings = File.Exists("settings.xml") ? ProgramSettings.Load("settings.xml") : new ProgramSettings(); 44 | lblVersion.Text = $"FSKview {version.Major}.{version.Minor}.{version.Build}"; 45 | 46 | // start in center of screen occupying 80% of its height 47 | Height = (int)(Screen.FromControl(this).Bounds.Height * .8); 48 | Location = new Point( 49 | x: Screen.FromControl(this).Bounds.Width / 2 - Width / 2, 50 | y: Screen.FromControl(this).Bounds.Height / 2 - Height / 2); 51 | 52 | // pre-populate listboxes 53 | cbWindow.Items.AddRange(FftSharp.Window.GetWindowNames()); 54 | cmaps = Spectrogram.Colormap.GetColormaps(); 55 | cbColormap.Items.AddRange(cmaps.Select(x => x.Name).ToArray()); 56 | cbDialFreq.Items.AddRange(WsprBands.GetBands().Select(x => $"{x.name}: {x.dialFreq:N0} Hz").ToArray()); 57 | 58 | // pre-select items based on saved settings 59 | audioControl1.SelectDevice(settings.audioDeviceIndex); 60 | cbWindow.SelectedIndex = cbWindow.Items.IndexOf(settings.window); 61 | cbColormap.SelectedIndex = cbColormap.Items.IndexOf(settings.colormap); 62 | cbDialFreq.SelectedIndex = settings.wsprBandIndex; 63 | cbWspr.Checked = settings.isWsprEnabled; 64 | cbFTP.Checked = settings.isFtpEnabled; 65 | nudBrightness.Value = (decimal)settings.brightness; 66 | 67 | // select on load 68 | ActiveControl = cbColormap; 69 | } 70 | 71 | private void FormMain_Load(object sender, EventArgs e) 72 | { 73 | ResetSpectrogram(); 74 | } 75 | 76 | private void FormMain_FormClosing(object sender, FormClosingEventArgs e) 77 | { 78 | audioControl1.listener.Dispose(); 79 | } 80 | 81 | private void audioControl1_InputDeviceChanged(object sender, EventArgs e) 82 | { 83 | settings.audioDeviceIndex = audioControl1.AudioDeviceIndex; 84 | settings.Save(); 85 | ResetSpectrogram(); 86 | } 87 | 88 | Spectrogram.Spectrogram spec; 89 | Bitmap bmpVericalScale; 90 | Bitmap bmpSpectrogram; 91 | 92 | private void ResetSpectrogram() 93 | { 94 | int sampleRate = audioControl1.SampleRate; 95 | int fftSize = 1 << 14; 96 | int samplesInTenMinutes = sampleRate * 60 * 10; 97 | int targetWidth = settings.targetWidth; 98 | int stepSize = samplesInTenMinutes / targetWidth; 99 | 100 | spec = new Spectrogram.Spectrogram(sampleRate, fftSize, stepSize, fixedWidth: targetWidth); 101 | spec.SetColormap(cmaps.Where(x => x.Name == settings.colormap).First()); 102 | 103 | // reset the spectrogram based on where we are in the 10 minute block 104 | ResetSpectrogramPosition(); 105 | 106 | // resize the image based on the spectrogram dimensions 107 | bmpSpectrogram = new Bitmap( 108 | width: spec.Width + verticalScaleWidth, 109 | height: spec.Height / settings.verticalReduction, 110 | format: PixelFormat.Format32bppPArgb); 111 | pictureBox1.Image = bmpSpectrogram; 112 | pictureBox1.Size = pictureBox1.Image.Size; 113 | Width = pictureBox1.Width + 33; 114 | UpdateVerticalScale(); 115 | 116 | Status($"Spectrogram reset"); 117 | } 118 | 119 | private void Status(string message) 120 | { 121 | lblStatus.Text = $"{UtcTimeStamp} UTC: {message}"; 122 | 123 | using (StreamWriter sw = File.AppendText("log.txt")) 124 | { 125 | sw.WriteLine($"{DateTime.UtcNow}: {message}"); 126 | } 127 | } 128 | 129 | private void UpdateVerticalScale() 130 | { 131 | if (spec != null && cbDialFreq.SelectedIndex >= 0) 132 | { 133 | bmpVericalScale = Ruler.GetVerticalScale(verticalScaleWidth, spec, band.dialFreq, settings.freqDisplayOffset, settings.verticalReduction); 134 | ScrollToUpperBandEdge(); 135 | } 136 | } 137 | 138 | private void ScrollToUpperBandEdge() 139 | { 140 | int wsprBandTopPx = spec.PixelY(band.upperFreq - band.dialFreq, settings.verticalReduction); 141 | panel1.AutoScrollPosition = new Point(0, wsprBandTopPx - settings.grabSavePxAbove + 1); 142 | } 143 | 144 | private void timerUpdateSpectrogram_Tick(object sender, EventArgs e) 145 | { 146 | if (spec is null) 147 | return; 148 | 149 | // capture new FFTs and note their indexes 150 | int fftsBefore = spec.FftsProcessed; 151 | spec.Add(audioControl1.listener.GetNewAudio()); 152 | int fftsAfter = spec.FftsProcessed; 153 | int newFftCount = fftsAfter - fftsBefore; 154 | int[] newFftIndexes = Enumerable.Range(spec.Width - newFftCount - 1, newFftCount).ToArray(); 155 | var ffts = spec.GetFFTs(); 156 | 157 | // optionally apply some sort of filter or AGC 158 | if (settings.agcMode == 1) 159 | { 160 | foreach (int fftIndex in newFftIndexes) 161 | { 162 | ffts[fftIndex] = AGC.Method1_SortedFloorMean(ffts[fftIndex], power: settings.agcPower); 163 | } 164 | } 165 | else if (settings.agcMode == 2) 166 | { 167 | foreach (int fftIndex in newFftIndexes) 168 | { 169 | ffts[fftIndex] = AGC.Method2_QuicksortFloor(ffts[fftIndex], power: settings.agcPower); 170 | } 171 | } 172 | 173 | // display the annotated spectrogram 174 | var spotsToShow = spots.Where(x => x.ageSec < (11 * 60)).ToList(); 175 | Annotate.Spectrogram(spec, band, spotsToShow, bmpSpectrogram, bmpVericalScale, cbBands.Checked, true, settings); 176 | pictureBox1.Refresh(); 177 | GC.Collect(); 178 | } 179 | 180 | private void cbWindow_SelectedIndexChanged(object sender, EventArgs e) 181 | { 182 | if (spec is null) 183 | return; 184 | 185 | settings.window = cbWindow.Text; 186 | settings.Save(); 187 | 188 | double[] window = FftSharp.Window.GetWindowByName(cbWindow.Text, spec.FftSize); 189 | spec.SetWindow(window); 190 | } 191 | 192 | private void cbColormap_SelectedIndexChanged(object sender, EventArgs e) 193 | { 194 | settings.colormap = cbColormap.Text; 195 | settings.Save(); 196 | 197 | spec?.SetColormap(cmaps[cbColormap.SelectedIndex]); 198 | } 199 | 200 | private void cbDialFreq_SelectedIndexChanged(object sender, EventArgs e) 201 | { 202 | band = WsprBands.GetBands()[cbDialFreq.SelectedIndex]; 203 | settings.wsprBandIndex = cbDialFreq.SelectedIndex; 204 | settings.Save(); 205 | 206 | UpdateVerticalScale(); 207 | } 208 | 209 | private void btnConfigure_Click(object sender, EventArgs e) 210 | { 211 | int oldTargetWidth = settings.targetWidth; 212 | int oldReduction = settings.verticalReduction; 213 | 214 | new FormSettings(settings).ShowDialog(); 215 | 216 | bool targetWidthChanged = (oldTargetWidth != settings.targetWidth); 217 | bool reductionChanged = (oldReduction != settings.verticalReduction); 218 | if (targetWidthChanged || reductionChanged) 219 | ResetSpectrogram(); 220 | 221 | UpdateVerticalScale(); 222 | ScrollToUpperBandEdge(); 223 | } 224 | 225 | DateTime wsprLogLastReadModifiedTime; 226 | private void LoadWsprSpots() 227 | { 228 | if (settings.wsprLogFilePath is null) 229 | return; 230 | 231 | if (!File.Exists(settings.wsprLogFilePath)) 232 | return; 233 | 234 | var lastModifiedTime = File.GetLastWriteTime(settings.wsprLogFilePath); 235 | if (lastModifiedTime == wsprLogLastReadModifiedTime) 236 | return; 237 | else 238 | wsprLogLastReadModifiedTime = lastModifiedTime; 239 | 240 | spots.Clear(); 241 | using (var stream = new FileStream(settings.wsprLogFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 242 | using (var streamReader = new StreamReader(stream)) 243 | { 244 | while (!streamReader.EndOfStream) 245 | { 246 | var spot = new WsprSpot(streamReader.ReadLine()); 247 | bool isRecent = spot.ageSec <= 30 * 60; // load spots within the last 15 min (apply a more tighter display rule later) 248 | if (spot.isValid && isRecent) 249 | { 250 | spots.Add(spot); 251 | } 252 | } 253 | } 254 | 255 | Status($"Loaded {spots.Count} WSPR spots"); 256 | } 257 | 258 | string stampLast; 259 | private void timerWsprUpdate_Tick(object sender, EventArgs e) 260 | { 261 | string stampNow = $"{DateTime.UtcNow.Hour}{DateTime.UtcNow.Minute}{DateTime.UtcNow.Second}"; 262 | if (stampNow == stampLast) 263 | return; 264 | 265 | stampLast = stampNow; 266 | int second = (DateTime.UtcNow.Minute % 10) * 60 + DateTime.UtcNow.Second; 267 | lblTime.Text = $"{UtcTimeStamp} UTC"; 268 | lblStatusTime.Text = $"{UtcTimeStamp} UTC (second {second}/600)"; 269 | pbTimeFrac.Value = second; 270 | LoadWsprSpots(); 271 | 272 | bool isTenMinute = DateTime.UtcNow.Minute % 10 == 0; 273 | bool isWsprHadTime = DateTime.UtcNow.Second == 2; 274 | if (isTenMinute && isWsprHadTime) 275 | { 276 | spec.RollReset(); 277 | if (cbSave.Checked && cbSave.Enabled) 278 | SaveGrab(uploadToo: cbFTP.Checked); 279 | } 280 | } 281 | 282 | private void cbSave_CheckedChanged(object sender, EventArgs e) 283 | { 284 | settings.saveGrabs = cbSave.Checked; 285 | settings.Save(); 286 | 287 | cbFTP.Enabled = cbSave.Checked; 288 | 289 | if (cbSave.Checked) 290 | { 291 | SaveGrab(); 292 | Process.Start("explorer.exe", $"\"{appPath}\""); 293 | } 294 | } 295 | 296 | private void SaveGrab(bool uploadToo = false) 297 | { 298 | int pxTop = spec.PixelY(band.upperFreq - band.dialFreq, settings.verticalReduction) - settings.grabSavePxAbove; 299 | int pxBot = spec.PixelY(band.lowerFreq - 200 - band.dialFreq, settings.verticalReduction) + settings.grabSavePxBelow; 300 | int height = pxBot - pxTop; 301 | int widthWithScale = spec.Width + verticalScaleWidth; 302 | 303 | using (Bitmap bmpFull = new Bitmap(widthWithScale, spec.Height, PixelFormat.Format32bppPArgb)) 304 | using (Bitmap bmpCropped = new Bitmap(widthWithScale, height, PixelFormat.Format32bppPArgb)) 305 | using (Graphics gfx = Graphics.FromImage(bmpCropped)) 306 | { 307 | // annotate a full-size spectrogram 308 | var spotsToShow = spots.Where(x => x.ageSec < (11 * 60)).ToList(); 309 | Annotate.Spectrogram(spec, band, spotsToShow, bmpFull, bmpVericalScale, false, false, settings); 310 | 311 | // draw the full-size spectrogram on the cropped Bitmap 312 | gfx.DrawImage(bmpFull, 0, -pxTop); 313 | 314 | // decorate the cropped bitmap 315 | string msg = $"FSKview {version.Major}.{version.Minor}.{version.Build}: " + 316 | $"{settings.stationInformation} {UtcDateStamp} {UtcTimeStampNoSec} UTC"; 317 | Annotate.Logo(gfx, msg, 3, height - 3); 318 | Annotate.TimeTicks(gfx, height, spec.SecPerPx); 319 | 320 | // ensure output folders exist 321 | string pathSaveWeb = $"{appPath}/grabs-web"; 322 | string pathSaveAll = $"{appPath}/grabs-all"; 323 | if (!Directory.Exists(pathSaveWeb)) 324 | Directory.CreateDirectory(pathSaveWeb); 325 | if (!Directory.Exists(pathSaveAll)) 326 | Directory.CreateDirectory(pathSaveAll); 327 | 328 | // save the cropped image for the web 329 | ImageFormat imgFmt = ImageFormat.Bmp; 330 | if (settings.grabFileName.EndsWith(".png", StringComparison.OrdinalIgnoreCase)) 331 | imgFmt = ImageFormat.Png; 332 | else if (settings.grabFileName.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase)) 333 | imgFmt = ImageFormat.Jpeg; 334 | else if (settings.grabFileName.EndsWith(".gif", StringComparison.OrdinalIgnoreCase)) 335 | imgFmt = ImageFormat.Gif; 336 | bmpCropped.Save($"{pathSaveWeb}/{settings.grabFileName}", imgFmt); 337 | 338 | // save the cropped bitmap for stitching 339 | string stitchFileName = $"{pathSaveAll}/{UtcDateStamp.Replace("-", "")}-{UtcTimeStamp.Replace(":", "")}.png"; 340 | if (settings.showScaleOnAllGrabs) 341 | { 342 | bmpCropped.Save(stitchFileName, ImageFormat.Png); 343 | } 344 | else 345 | { 346 | using (Bitmap bmpCropped2 = new Bitmap(spec.Width, height, PixelFormat.Format32bppPArgb)) 347 | using (Graphics gfx2 = Graphics.FromImage(bmpCropped2)) 348 | { 349 | gfx2.DrawImage(bmpCropped, 0, 0); 350 | bmpCropped2.Save(stitchFileName, ImageFormat.Png); 351 | } 352 | } 353 | 354 | Status($"Saved spectrogram as {settings.grabFileName}"); 355 | 356 | if (uploadToo) 357 | { 358 | Enabled = false; 359 | Status($"Performing FTP upload..."); 360 | Application.DoEvents(); 361 | string result = FTP.Upload(settings.ftpServerAddress, settings.ftpRemoteSubfolder, settings.ftpUsername, 362 | settings.DeObfuscate(settings.ftpObfuscatedPassword), $"{pathSaveWeb}/{settings.grabFileName}"); 363 | if (result.Contains("Not logged in")) 364 | result = "Incorrect username/password"; 365 | else if (result.Contains("File name not allowed")) 366 | result = "Invalid path (does the target folder exist?)"; 367 | else if (result == "upload successful") 368 | result = "FTP upload successful"; 369 | else 370 | result = "FTP ERROR (get full message in settings)\n" + result; 371 | Status(result); 372 | Enabled = true; 373 | } 374 | } 375 | } 376 | 377 | private void nudBrightness_ValueChanged(object sender, EventArgs e) 378 | { 379 | settings.brightness = (double)nudBrightness.Value; 380 | settings.Save(); 381 | } 382 | 383 | private void cbBands_CheckedChanged(object sender, EventArgs e) 384 | { 385 | settings.showBands = cbBands.Checked; 386 | settings.Save(); 387 | if (cbBands.Checked) 388 | ScrollToUpperBandEdge(); 389 | } 390 | 391 | private void cbWspr_CheckedChanged(object sender, EventArgs e) 392 | { 393 | settings.isWsprEnabled = cbWspr.Checked; 394 | settings.Save(); 395 | } 396 | 397 | private void ResetSpectrogramPosition() 398 | { 399 | if (settings.roll) 400 | { 401 | int secondsIntoTenMinute = (DateTime.UtcNow.Minute % 10) * 60 + DateTime.UtcNow.Second; 402 | double fracIntoTenMinute = secondsIntoTenMinute / 600.0; 403 | int nextIndex = (int)(fracIntoTenMinute * spec.Width); 404 | spec.RollReset(nextIndex); 405 | } 406 | else 407 | { 408 | spec.RollReset(spec.Width); 409 | } 410 | } 411 | 412 | private void cbRoll_CheckedChanged(object sender, EventArgs e) 413 | { 414 | ResetSpectrogramPosition(); 415 | } 416 | 417 | private void cbFTP_CheckedChanged(object sender, EventArgs e) 418 | { 419 | settings.isFtpEnabled = cbFTP.Checked; 420 | settings.Save(); 421 | } 422 | } 423 | } 424 | -------------------------------------------------------------------------------- /src/FSKview/FormSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Reflection; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using System.Windows.Forms; 12 | 13 | namespace FSKview 14 | { 15 | public partial class FormSettings : Form 16 | { 17 | readonly ProgramSettings settings; 18 | public FormSettings(ProgramSettings settings) 19 | { 20 | InitializeComponent(); 21 | this.settings = settings; 22 | 23 | tbServer.Text = settings.ftpServerAddress; 24 | tbRemotePath.Text = settings.ftpRemoteSubfolder; 25 | tbUsername.Text = settings.ftpUsername; 26 | tbPassword.Text = settings.DeObfuscate(settings.ftpObfuscatedPassword); 27 | tbWsprPath.Text = settings.wsprLogFilePath; 28 | nudTargetWidth.Value = settings.targetWidth; 29 | nudVerticalReduction.Value = settings.verticalReduction; 30 | nudFreqDisplayOffset.Value = settings.freqDisplayOffset; 31 | tbImageFileName.Text = settings.grabFileName; 32 | cbShowFreqScale.Checked = settings.showScaleOnAllGrabs; 33 | nudPxAbove.Value = settings.grabSavePxAbove; 34 | nudPxBelow.Value = settings.grabSavePxBelow; 35 | tbStationInfo.Text = settings.stationInformation; 36 | cbRoll.Checked = settings.roll; 37 | cbAgcMode.SelectedIndex = settings.agcMode; 38 | nudAgcPower.Value = (decimal)settings.agcPower; 39 | cbShowTimeLines.Checked = settings.showTimeLines; 40 | } 41 | 42 | private void btnSave_Click(object sender, EventArgs e) 43 | { 44 | settings.ftpServerAddress = tbServer.Text; 45 | settings.ftpRemoteSubfolder = tbRemotePath.Text; 46 | settings.ftpUsername = tbUsername.Text; 47 | settings.ftpObfuscatedPassword = settings.Obfuscate(tbPassword.Text); 48 | settings.wsprLogFilePath = tbWsprPath.Text; 49 | settings.targetWidth = (int)nudTargetWidth.Value; 50 | settings.verticalReduction = (int)nudVerticalReduction.Value; 51 | settings.freqDisplayOffset = (int)nudFreqDisplayOffset.Value; 52 | settings.grabFileName = tbImageFileName.Text; 53 | settings.showScaleOnAllGrabs = cbShowFreqScale.Checked; 54 | settings.grabSavePxAbove = (int)nudPxAbove.Value; 55 | settings.grabSavePxBelow = (int)nudPxBelow.Value; 56 | settings.stationInformation = tbStationInfo.Text; 57 | settings.roll = cbRoll.Checked; 58 | settings.agcMode = cbAgcMode.SelectedIndex; 59 | settings.agcPower = (double)nudAgcPower.Value; 60 | settings.showTimeLines = cbShowTimeLines.Checked; 61 | settings.Save(); 62 | Close(); 63 | } 64 | 65 | private void btnCancel_Click(object sender, EventArgs e) 66 | { 67 | Close(); 68 | } 69 | 70 | private void btnSetWsprPath_Click(object sender, EventArgs e) 71 | { 72 | OpenFileDialog diag = new OpenFileDialog(); 73 | diag.Filter = "WSPR Log Files (*.txt)|*.txt"; 74 | diag.FileName = "ALL_WSPR.TXT"; 75 | diag.Title = "Locate WSPR Log File"; 76 | if (diag.ShowDialog() == DialogResult.OK) 77 | { 78 | tbWsprPath.Text = diag.FileName; 79 | } 80 | } 81 | 82 | private void btnUploadNow_Click(object sender, EventArgs e) 83 | { 84 | string appPath = Path.GetFullPath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)); 85 | string localFilePath = $"{appPath}/grabs-web/{settings.grabFileName}"; 86 | 87 | if (File.Exists(localFilePath)) 88 | { 89 | Enabled = false; 90 | string result = FTP.Upload(tbServer.Text, tbRemotePath.Text, tbUsername.Text, tbPassword.Text, localFilePath); 91 | if (result.Contains("Not logged in")) 92 | MessageBox.Show("Incorrect username/password", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error); 93 | else if (result.Contains("File name not allowed")) 94 | MessageBox.Show("Invalid path (does the target folder exist?)", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error); 95 | else if (result == "upload successful") 96 | MessageBox.Show("FTP upload was successful", "SUCCESS", MessageBoxButtons.OK, MessageBoxIcon.Information); 97 | else 98 | MessageBox.Show(result, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error); 99 | Enabled = true; 100 | } 101 | else 102 | { 103 | MessageBox.Show($"latest grab file does not exist:\n{localFilePath}", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error); 104 | } 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/FSKview/Listener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace FSKview 9 | { 10 | /* The Listener handles incoming sound card buffers so you don't have to. 11 | * 12 | * The Listener class uses NAudio to connect to an audio device, continuously 13 | * handle incoming audio buffers, and add incoming audio values to a List. 14 | * The GetAudio() method returns (and removes) values from this incoming audio list. 15 | * 16 | */ 17 | public class Listener : IDisposable 18 | { 19 | public readonly int SampleRate; 20 | private readonly NAudio.Wave.WaveInEvent wvin; 21 | public double AmplitudeFrac { get; private set; } 22 | public int TotalSamples { get; private set; } 23 | public double TotalTimeSec { get { return (double)TotalSamples / SampleRate; } } 24 | private readonly List audio = new List(); 25 | public int SamplesInMemory { get { return audio.Count; } } 26 | readonly Thread t; 27 | 28 | public Listener(int deviceIndex, int sampleRate) 29 | { 30 | SampleRate = sampleRate; 31 | wvin = new NAudio.Wave.WaveInEvent 32 | { 33 | DeviceNumber = deviceIndex, 34 | WaveFormat = new NAudio.Wave.WaveFormat(sampleRate, bits: 16, channels: 1), 35 | BufferMilliseconds = 20 36 | }; 37 | wvin.DataAvailable += OnNewAudioData; 38 | wvin.StartRecording(); 39 | 40 | t = new Thread(AddBufferToAudioForever); 41 | t.Start(); 42 | } 43 | 44 | public void Dispose() 45 | { 46 | shuttingDown = true; 47 | wvin?.StopRecording(); 48 | wvin?.Dispose(); 49 | } 50 | 51 | private double[] buffer; 52 | private void OnNewAudioData(object sender, NAudio.Wave.WaveInEventArgs args) 53 | { 54 | int bytesPerSample = wvin.WaveFormat.BitsPerSample / 8; 55 | int newSampleCount = args.BytesRecorded / bytesPerSample; 56 | if (buffer is null) 57 | buffer = new double[newSampleCount]; 58 | 59 | double peak = 0; 60 | for (int i = 0; i < newSampleCount; i++) 61 | { 62 | buffer[i] = BitConverter.ToInt16(args.Buffer, i * bytesPerSample); 63 | peak = Math.Max(peak, buffer[i]); 64 | } 65 | AmplitudeFrac = peak / (1 << 15); 66 | TotalSamples += newSampleCount; 67 | } 68 | 69 | private bool shuttingDown = false; 70 | public void AddBufferToAudioForever() 71 | { 72 | int lastSampleAnalyzed = 0; 73 | while (shuttingDown == false) 74 | { 75 | if (lastSampleAnalyzed != TotalSamples) 76 | { 77 | lock (audio) 78 | { 79 | audio.AddRange(buffer); 80 | } 81 | lastSampleAnalyzed = TotalSamples; 82 | } 83 | Thread.Sleep(1); 84 | } 85 | } 86 | 87 | public double[] GetNewAudio() 88 | { 89 | lock (audio) 90 | { 91 | double[] values = new double[audio.Count]; 92 | for (int i = 0; i < values.Length; i++) 93 | values[i] = audio[i]; 94 | audio.RemoveRange(0, values.Length); 95 | return values; 96 | } 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/FSKview/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace FSKview 8 | { 9 | static class Program 10 | { 11 | /// 12 | /// The main entry point for the application. 13 | /// 14 | [STAThread] 15 | static void Main() 16 | { 17 | Application.EnableVisualStyles(); 18 | Application.SetCompatibleTextRenderingDefault(false); 19 | Application.Run(new FormMain()); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/FSKview/ProgramSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Text; 4 | using System.Windows.Forms; 5 | using System.Xml.Serialization; 6 | 7 | namespace FSKview 8 | { 9 | public class ProgramSettings 10 | { 11 | public string version; 12 | 13 | public int audioDeviceIndex = 0; 14 | public string window = "Cosine"; 15 | public string colormap = "Viridis"; 16 | public int dialFrequencyIndex = 5; 17 | public double brightness = 2.0; 18 | public bool isWsprEnabled = true; 19 | public string wsprLogFilePath = null; 20 | public int wsprBandIndex = 7; 21 | public bool showBands = true; 22 | public bool saveGrabs = true; 23 | public bool showScaleOnAllGrabs = false; 24 | public string grabFileName = "latest.png"; 25 | public bool roll = true; 26 | public bool showTimeLines = false; 27 | 28 | public int targetWidth = 1000; 29 | public int grabSavePxAbove = 120; 30 | public int grabSavePxBelow = 170; 31 | public int verticalReduction = 2; 32 | public int freqDisplayOffset = 0; 33 | public string stationInformation = "station information not set"; 34 | 35 | public string ftpServerAddress = "ftp://ftp.qsl.net"; 36 | public string ftpRemoteSubfolder = "/"; 37 | public string ftpUsername = "sampleUsername"; 38 | public string ftpObfuscatedPassword = "c2FtcGxlUGFzc3dvcmQ"; 39 | public bool isFtpEnabled = false; 40 | public int agcMode = 0; 41 | public double agcPower = 1; 42 | 43 | public ProgramSettings() 44 | { 45 | var version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; 46 | this.version = $"{version.Major}.{version.Minor}"; 47 | 48 | string predictedWsprFilePath = Path.GetFullPath(Application.LocalUserAppDataPath + "../../../../WSJT-X/ALL_WSPR.TXT"); 49 | wsprLogFilePath = File.Exists(predictedWsprFilePath) ? predictedWsprFilePath : null; 50 | } 51 | 52 | public static ProgramSettings Load(string filePath = "settings.xml") 53 | { 54 | var version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; 55 | string expectedVersion = $"{version.Major}.{version.Minor}"; 56 | 57 | XmlSerializer reader = new XmlSerializer(typeof(ProgramSettings)); 58 | using (StreamReader file = new StreamReader(filePath)) 59 | { 60 | ProgramSettings loadedConfig = (ProgramSettings)reader.Deserialize(file); 61 | if (loadedConfig.version == expectedVersion) 62 | return loadedConfig; 63 | else 64 | throw new InvalidOperationException("incompatible config file version"); 65 | } 66 | } 67 | 68 | public void Save(string filePath = "settings.xml") 69 | { 70 | XmlSerializer serializer = new XmlSerializer(typeof(ProgramSettings)); 71 | using (StreamWriter fileWriter = new StreamWriter(filePath)) 72 | { 73 | serializer.Serialize(fileWriter, this); 74 | } 75 | } 76 | 77 | public string GetXML() 78 | { 79 | using (StringWriter textWriter = new StringWriter()) 80 | { 81 | XmlSerializer xmlSerializer = new XmlSerializer(this.GetType()); 82 | xmlSerializer.Serialize(textWriter, this); 83 | return textWriter.ToString(); 84 | } 85 | } 86 | 87 | public string Obfuscate(string message) 88 | { 89 | return Convert.ToBase64String(Encoding.UTF8.GetBytes(message)).Trim('='); 90 | } 91 | 92 | public string DeObfuscate(string obfuscated) 93 | { 94 | while (obfuscated.Length % 4 != 0) 95 | obfuscated += "="; 96 | return Encoding.UTF8.GetString(Convert.FromBase64String(obfuscated)); 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/FSKview/Ruler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Drawing.Imaging; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | #pragma warning disable CA1416 // Ignore System.Drawing platform compatibility 10 | 11 | namespace FSKview 12 | { 13 | public static class Ruler 14 | { 15 | public static Bitmap GetVerticalScale(int width, Spectrogram.Spectrogram spec, int offsetFromZeroHz = 0, int offsetHz = 0, int reduction = 1) 16 | { 17 | int majorTickHz = 50; 18 | int majorTickLength = 4; 19 | int minorTickHz = 10; 20 | int minorTickLength = 1; 21 | 22 | Bitmap bmp = new Bitmap(width, spec.Height / reduction); 23 | 24 | using (var gfx = Graphics.FromImage(bmp)) 25 | using (var pen = new Pen(Color.Black)) 26 | using (var brush = new SolidBrush(Color.Black)) 27 | using (var font = new Font(FontFamily.GenericMonospace, 10)) 28 | using (var sf = new StringFormat() { LineAlignment = StringAlignment.Center }) 29 | { 30 | gfx.Clear(Color.White); 31 | 32 | List freqsMajor = new List(); 33 | for (double f = spec.FreqMin; f <= spec.FreqMax; f += majorTickHz) 34 | freqsMajor.Add(f); 35 | 36 | List freqsMinor = new List(); 37 | for (double f = spec.FreqMin; f <= spec.FreqMax; f += minorTickHz) 38 | freqsMinor.Add(f); 39 | 40 | // don't show first or last major tick 41 | if (freqsMajor.Count >= 2) 42 | { 43 | freqsMajor.RemoveAt(0); 44 | freqsMajor.RemoveAt(freqsMajor.Count - 1); 45 | } 46 | 47 | foreach (var freq in freqsMajor) 48 | { 49 | int y = spec.PixelY(freq + offsetHz) / reduction; 50 | gfx.DrawLine(pen, 0, y, majorTickLength, y); 51 | gfx.DrawString($"{freq + offsetFromZeroHz:N0} Hz", font, brush, majorTickLength, y, sf); 52 | } 53 | 54 | foreach (var freq in freqsMinor) 55 | { 56 | int y = spec.PixelY(freq + offsetHz) / reduction; 57 | gfx.DrawLine(pen, 0, y, minorTickLength, y); 58 | } 59 | } 60 | 61 | return bmp; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/FSKview/WsprBand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace FSKview 8 | { 9 | class WsprBand 10 | { 11 | public readonly string name; 12 | public readonly int dialFreq; 13 | public readonly int lowerFreq; 14 | public readonly int upperFreq; 15 | public WsprBand(string name, int dial) 16 | { 17 | this.name = name ?? $"?"; 18 | dialFreq = dial; 19 | lowerFreq = dial + 1400; 20 | upperFreq = dial + 1600; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/FSKview/WsprBands.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace FSKview 8 | { 9 | class WsprBands 10 | { 11 | public static WsprBand[] GetBands(bool ascending = true) 12 | { 13 | 14 | WsprBand[] bands = 15 | { 16 | new WsprBand("None", 0), 17 | 18 | // WSPR bands listed on http://wsprnet.org/ 19 | new WsprBand("WSPR 2200m", 0_136_000), 20 | new WsprBand("WSPR 630m", 0_474_200), 21 | new WsprBand("WSPR 160m", 1_836_600), 22 | new WsprBand("WSPR 80m", 3_568_600), 23 | new WsprBand("WSPR 60m", 5_287_200), 24 | new WsprBand("WSPR 40m", 7_038_600), 25 | new WsprBand("WSPR 30m", 10_138_700), 26 | new WsprBand("WSPR 20m", 14_095_600), 27 | new WsprBand("WSPR 17m", 18_104_600), 28 | new WsprBand("WSPR 15m", 21_094_600), 29 | new WsprBand("WSPR 12m", 24_924_600), 30 | new WsprBand("WSPR 10m", 28_124_600), 31 | new WsprBand("WSPR 6m", 50_293_000), 32 | new WsprBand("WSPR 2m", 144_488_500), 33 | 34 | /* 35 | new WsprBand("FT8 80m", 3_573_000), 36 | new WsprBand("FT8 40m", 7_074_000), 37 | new WsprBand("FT8 30m", 10_136_000), 38 | new WsprBand("FT8 20m", 14_074_000), 39 | new WsprBand("FT8 17m", 18_100_000), 40 | new WsprBand("FT8 15m", 21_074_000), 41 | new WsprBand("FT8 12m", 24_915_000), 42 | new WsprBand("FT8 10m", 28_074_000), 43 | new WsprBand("FT8 6m", 50_310_000), 44 | 45 | new WsprBand("FT4 80m", 3_575_000), 46 | new WsprBand("FT4 40m", 7_047_500), 47 | new WsprBand("FT4 30m", 10_140_000), 48 | new WsprBand("FT4 20m", 14_080_000), 49 | new WsprBand("FT4 17m", 18_104_000), 50 | new WsprBand("FT4 15m", 21_140_000), 51 | new WsprBand("FT4 12m", 24_919_000), 52 | new WsprBand("FT4 10m", 28_180_000), 53 | new WsprBand("FT4 6m", 50_318_000), 54 | 55 | new WsprBand("JS8 40m", 7_078_000), 56 | */ 57 | }; 58 | 59 | if (ascending == false) 60 | Array.Reverse(bands); 61 | 62 | return bands; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/FSKview/WsprLogFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace FSKview 9 | { 10 | public class WsprLogFile 11 | { 12 | public readonly string FilePath; 13 | public readonly List spots = new List(); 14 | 15 | public WsprLogFile(string logFilePath) 16 | { 17 | FilePath = Path.GetFullPath(logFilePath); 18 | if (!File.Exists(FilePath)) 19 | throw new ArgumentException($"file does not exist: {FilePath}"); 20 | Read(); 21 | } 22 | 23 | public void Read() 24 | { 25 | spots.Clear(); 26 | using (var stream = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 27 | using (var streamReader = new StreamReader(stream)) 28 | { 29 | while (!streamReader.EndOfStream) 30 | { 31 | var spot = new WsprSpot(streamReader.ReadLine()); 32 | if (spot.isValid) 33 | spots.Add(spot); 34 | } 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/FSKview/WsprSpot.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Globalization; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace FSKview 10 | { 11 | public class WsprSpot 12 | { 13 | public bool isValid { get; private set; } 14 | public DateTime dt { get; private set; } 15 | public string timestamp { get; private set; } 16 | public double strength { get; private set; } 17 | //public double deltaT { get; private set; } 18 | public double frequencyMHz { get; private set; } 19 | public double frequencyHz { get { return Math.Round(frequencyMHz * 1e6, 1); } } 20 | public string grid { get; private set; } 21 | //public double power { get; private set; } 22 | //public double drift { get; private set; } 23 | public string callsign { get; private set; } 24 | 25 | public bool isWspr { get; private set; } = true; 26 | 27 | public double ageSec { get { return (DateTime.UtcNow - dt).TotalSeconds; } } 28 | public int segment { get { return (dt.Minute % 10) / 2; } } 29 | 30 | public WsprSpot(string line) 31 | { 32 | // WSPR log files may be in multiple formats as described in: 33 | // https://github.com/swharden/FSKview/issues/26 34 | 35 | string[] parts = line.Split(' ').Where(x => x.Length > 0).ToArray(); 36 | 37 | if (line.Contains(" Rx FT") && parts.Length == 10) 38 | ParseFT(parts); 39 | else if (line.Length == 96 && parts.Length == 17) 40 | Parse96(parts); 41 | else if (line.Length == 88 && parts.Length == 15) 42 | Parse88(parts); 43 | else if (line.Length == 73 && parts.Length == 12) 44 | Parse73(parts); 45 | else 46 | Debug.WriteLine($"unsupported WSPR log line format"); 47 | 48 | 49 | /* 50 | * Callsigns enclosed in angle brackets are actually sent as 15-bit hash codes. 51 | * If such a code is received by another station before the full callsign has 52 | * been received, it will be displayed as <...> on the decoded text line. Once 53 | * the full callsign has been received, the decoder will thereafter recognize 54 | * the hash code and fill in the blanks. Two very different callsigns might have 55 | * the same hash code, but the 15-bit hashcode length ensures that in practice 56 | * such collisions will be rare. 57 | */ 58 | if (!string.IsNullOrWhiteSpace(callsign)) 59 | { 60 | callsign = callsign.Trim('<').Trim('>'); 61 | if (callsign == "...") 62 | callsign = null; 63 | } 64 | 65 | if (string.IsNullOrWhiteSpace(callsign)) 66 | isValid = false; 67 | } 68 | 69 | public override string ToString() 70 | { 71 | return (isValid) ? $"{callsign} ({strength} dB) from {grid} at {dt}" : "invalid"; 72 | } 73 | 74 | private void ParseFT(string[] parts) 75 | { 76 | // WSJT-X 2.2.2 77 | // 0 1 2 3 4 5 6 7 8 9 78 | // 191010_130200|14.080|Rx|FT4|-16|0.2|2012|UA4CCH|YO9NC|-07 79 | try 80 | { 81 | isWspr = false; 82 | 83 | int year = int.Parse(parts[0].Substring(0, 2)) + 2000; 84 | int month = int.Parse(parts[0].Substring(2, 2)); 85 | int day = int.Parse(parts[0].Substring(4, 2)); 86 | int hour = int.Parse(parts[0].Substring(7, 2)); 87 | int minute = int.Parse(parts[0].Substring(9, 2)); 88 | int second = int.Parse(parts[0].Substring(11, 2)); 89 | dt = new DateTime(year, month, day, hour, minute, second); 90 | timestamp = parts[0].Replace("_", ""); 91 | 92 | strength = int.Parse(parts[4]); 93 | frequencyMHz = double.Parse(parts[1], CultureInfo.InvariantCulture); 94 | frequencyMHz += double.Parse(parts[6], CultureInfo.InvariantCulture) / 1e6; 95 | callsign = string.Join(" ", parts.Skip(7)); 96 | 97 | isValid = true; 98 | } 99 | catch 100 | { 101 | isValid = false; 102 | } 103 | } 104 | 105 | private void Parse96(string[] parts) 106 | { 107 | // WSJT-X 2.2.2 108 | // 0 1 2 3 4 5 6 109 | // 200603|1720|-27|-1.34|10.1401891|N8XEF|EM99|37|3|0.13|1|1|0|1|38|1|810 110 | 111 | try 112 | { 113 | int year = int.Parse(parts[0].Substring(0, 2)) + 2000; 114 | int month = int.Parse(parts[0].Substring(2, 2)); 115 | int day = int.Parse(parts[0].Substring(4, 2)); 116 | int hour = int.Parse(parts[1].Substring(0, 2)); 117 | int minute = int.Parse(parts[1].Substring(2, 2)); 118 | int second = 0; 119 | dt = new DateTime(year, month, day, hour, minute, second); 120 | timestamp = parts[0]+parts[1]; 121 | 122 | strength = int.Parse(parts[2]); 123 | frequencyMHz = double.Parse(parts[4], CultureInfo.InvariantCulture); 124 | callsign = parts[5]; 125 | grid = parts[6]; 126 | 127 | isValid = true; 128 | } 129 | catch 130 | { 131 | isValid = false; 132 | } 133 | } 134 | 135 | private void Parse88(string[] parts) 136 | { 137 | // WSJT-X 2.1.2 138 | // 0 1 2 3 4 5 6 7 139 | // 200713|1908|4|-17|0.32|14.0970666|DL6NL|JO50|27|0|1|0|1|527|0 140 | 141 | try 142 | { 143 | int year = int.Parse(parts[0].Substring(0, 2)) + 2000; 144 | int month = int.Parse(parts[0].Substring(2, 2)); 145 | int day = int.Parse(parts[0].Substring(4, 2)); 146 | int hour = int.Parse(parts[1].Substring(0, 2)); 147 | int minute = int.Parse(parts[1].Substring(2, 2)); 148 | int second = 0; 149 | dt = new DateTime(year, month, day, hour, minute, second); 150 | timestamp = parts[0] + parts[1]; 151 | 152 | strength = int.Parse(parts[3]); 153 | frequencyMHz = double.Parse(parts[5], CultureInfo.InvariantCulture); 154 | callsign = parts[6]; 155 | grid = parts[7]; 156 | 157 | isValid = true; 158 | } 159 | catch 160 | { 161 | isValid = false; 162 | } 163 | } 164 | 165 | private void Parse73(string[] parts) 166 | { 167 | // WSPR classic 168 | // 0 1 2 3 4 5 6 7 169 | // 200715|1006|10|-23|-0.3|7.040078|G6JVT|IO90|23|0|1|0 170 | 171 | try 172 | { 173 | int year = int.Parse(parts[0].Substring(0, 2)) + 2000; 174 | int month = int.Parse(parts[0].Substring(2, 2)); 175 | int day = int.Parse(parts[0].Substring(4, 2)); 176 | int hour = int.Parse(parts[1].Substring(0, 2)); 177 | int minute = int.Parse(parts[1].Substring(2, 2)); 178 | int second = 0; 179 | dt = new DateTime(year, month, day, hour, minute, second); 180 | timestamp = parts[0] + parts[1]; 181 | 182 | strength = int.Parse(parts[3]); 183 | frequencyMHz = double.Parse(parts[5], CultureInfo.InvariantCulture); 184 | callsign = parts[6]; 185 | grid = parts[7]; 186 | 187 | isValid = true; 188 | } 189 | catch 190 | { 191 | isValid = false; 192 | } 193 | } 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /src/FSKview/fskview-icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swharden/FSKview/75e85a8a497ba8dd5c5ef8beea1bf170bfedc1af/src/FSKview/fskview-icon.ico -------------------------------------------------------------------------------- /src/FSKview/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | --------------------------------------------------------------------------------