├── .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 | [](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 | 
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 |
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 | 
21 |
22 | #### Viridis
23 | 
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 |
--------------------------------------------------------------------------------