Compare commits

...

291 Commits

Author SHA1 Message Date
Joe Taylor
2b9d65408d Bug fix: correct the misuse of variable 'ncand' in both q65 module and a common block. 2024-03-12 08:47:23 -04:00
Uwe Risse
c5a266b5e0 Update Catalan translation of the UI. Thanks to Xavi, EA3W. 2024-03-07 18:15:02 +01:00
Uwe Risse
de9dc8e3fb Minor changes to the Release Notes. 2024-03-07 17:22:40 +01:00
Uwe Risse
5e410a982b Further updates to the Spanish translation of the UI. Thanks to Cedrik, EA4AC. 2024-03-07 16:42:05 +01:00
Uwe Risse
2a9d0b6998 Update Spanish translation of the UI. 2024-03-07 11:17:16 +01:00
Uwe Risse
75f6b9b423 Fix a compilation error. 2024-03-07 01:14:11 +01:00
Uwe Risse
c7a93fca4a Code cleanup. 2024-03-04 10:50:17 +01:00
Uwe Risse
08785eff56 Update NEWS and Release Note for RC4. 2024-03-04 10:28:03 +01:00
Uwe Risse
40fbc208fd Code cleanup. 2024-03-04 10:27:14 +01:00
Uwe Risse
1ac2fc23c3 Remove unused code. 2024-03-04 10:14:54 +01:00
Uwe Risse
d4a5ea60e6 Preparations for RC4. 2024-03-04 10:00:03 +01:00
Uwe Risse
86fd50304f Remove unused code. 2024-03-04 09:58:32 +01:00
Uwe Risse
75b4e0e798 Remove unused code. 2024-03-04 09:45:59 +01:00
Joe Taylor
ee68285583 Revert "Bare-bones foxgen2 is now functional and parsing normal Fox messages."
This reverts commit b83c41c8deec1b09d56f504c0fd09e9b693d8184.
2024-03-01 16:40:16 -05:00
Joe Taylor
ae50058498 Revert "Fix two typos."
This reverts commit 72651037bdec5410272654699bbbf90edbc89f17.
2024-03-01 16:40:14 -05:00
Joe Taylor
587a16cd21 Revert "WIP on assembling SuperFox messages."
This reverts commit 4c0d34477d137ef57fa03def5cd5e1997717952e.
2024-03-01 16:40:12 -05:00
Joe Taylor
45151bda3b Revert "SuperFox messages are now properly assembled at uset level. Next, need to encode."
This reverts commit 34b97b53f82bd75a87fa1b302a325d3e71d494af.
2024-03-01 16:40:01 -05:00
Joe Taylor
34b97b53f8 SuperFox messages are now properly assembled at uset level. Next, need to encode. 2024-03-01 15:14:44 -05:00
Joe Taylor
4c0d34477d WIP on assembling SuperFox messages. 2024-03-01 13:22:33 -05:00
Joe Taylor
72651037bd Fix two typos. 2024-03-01 11:59:05 -05:00
Joe Taylor
b83c41c8de Bare-bones foxgen2 is now functional and parsing normal Fox messages. 2024-03-01 11:55:20 -05:00
Joe Taylor
ae61764af3 Starting to implement SuperFox capability in WSJT-X. 2024-03-01 10:48:41 -05:00
Joe Taylor
ae17011aa4 Alt+A to clear the Active Stations window in Q65 mode (for QMAP). 2024-02-28 13:58:23 -05:00
Uwe Risse
c228b6fe18 Disable double-clicking on combined messages also for the standard FT4 sub-bands. 2024-02-06 16:13:40 +01:00
Uwe Risse
ffe1d11e99 Don't fill DX Call box and Std Msgs when double-clicking on a combined message and we are on standard FT8 sub-bands. 2024-02-06 11:06:33 +01:00
Uwe Risse
3882953f51 Disable the popup message for now. 2024-02-05 17:01:03 +01:00
Uwe Risse
3611f07ad6 Enable Tx by double-clicking on a combined message on standard FT8 sub-bands is no longer permitted, as 10-bit hash collisions are too likely. 2024-02-05 16:50:22 +01:00
Steven Franke
98e48e00d3 Only hash the callsign of stations that we are hearing. 2024-02-05 08:52:57 -06:00
Uwe Risse
20c41cf45b Don't write <my_gridsquare> ADIF tag when myGrid is empty. 2024-02-03 15:44:02 +01:00
Joe Taylor
200168fd37 Reset QMAP's kHzRequested to 0 after the QSY is executed in WSJT-X. 2024-01-31 10:00:12 -05:00
Uwe Risse
b7efe4d26d Ensure that any message to MyCall is displayed in the Rx Frequency window when in FT8 Hound mode. 2024-01-30 17:50:12 +01:00
Joe Taylor
d67a406bf0 Merge branch 'develop' into qmap 2024-01-26 09:21:43 -05:00
Uwe Risse
41407dad9f Always display Q65 messages with own callsign in the right-hand window. 2024-01-26 10:34:30 +01:00
Joe Taylor
f59b5a48f7 CTRL+Click on QMAP's upper waterfall sends integer kHz dial freq request to WSJT-X. 2024-01-25 14:27:54 -05:00
Joe Taylor
c251764252 Display "T M R 73" only for JT4 and Q65 D and E. 2024-01-25 11:32:36 -05:00
Joe Taylor
2655e41dd6 Revert "Q65/JT65/JT4: Always display messages containing MyCall in the right window."
This reverts commit 226b17d0eaac79699b32ee1372dd767153cccedc.
2024-01-25 11:28:17 -05:00
Joe Taylor
d4e2c21053 Special case: yellow Tx message for Q65-60x should use hhmmss. 2024-01-25 11:14:55 -05:00
Joe Taylor
226b17d0ea Q65/JT65/JT4: Always display messages containing MyCall in the right window. 2024-01-25 10:57:15 -05:00
Joe Taylor
495170e7a1 Double-click on AS window to leave Tx Enable OFF. 2024-01-24 15:10:15 -05:00
Uwe Risse
90b7ff7da9 Deactivate Lookup for certain special operating activities, as 6-digit grids from CALL3.TXT may not be accepted. 2024-01-24 18:02:06 +01:00
Steven Franke
aac9de3e4c fastosd240_74.f90: Fix a couple of typos. No impact on WSJT-X decoding performance. 2024-01-23 09:47:19 -06:00
Steven Franke
e205bf0ca6 Changes to enable simulating (240,74) FST4W code with noncoherent 4FSK on AWGN or Rayleigh fading channels 2024-01-22 12:07:52 -06:00
Joe Taylor
b84742b1fc "Export .wav files" now working as intended in QMAP. 2024-01-22 11:11:53 -05:00
Joe Taylor
7be1c34ea0 Fix cablog so it can work with grid as exchange, e.g., for Jan VHF SS. 2024-01-22 11:09:45 -05:00
Joe Taylor
0705bd329e More work in progress toward "Export .wav file ..." in QMAP. 2024-01-22 07:12:40 -05:00
Joe Taylor
6474f7e1cf Merge branch 'qmap' of bitbucket.org:k1jt/wsjtx into qmap 2024-01-20 15:03:33 -05:00
Joe Taylor
adc0345ef3 Work in progress toward "Export .wav file". 2024-01-20 15:02:51 -05:00
Uwe Risse
69a19946df Remove an unnecessary space. 2024-01-20 18:50:26 +01:00
Joe Taylor
4ec84087c7 Revert "Suppress QMAP waterfall scrolling with all-zero data from qm file."
This reverts commit 05c33893076a33e118782f6c7d498fe82787cdcd.
2024-01-20 08:37:14 -05:00
Joe Taylor
05c3389307 Suppress QMAP waterfall scrolling with all-zero data from qm file. 2024-01-20 08:22:11 -05:00
Joe Taylor
9223ae3393 Cleanup in read_qm.f90. 2024-01-19 14:19:37 -05:00
Joe Taylor
e178df928e Skip redundant processing of candidates already decoded in same sequence. 2024-01-19 14:02:16 -05:00
Joe Taylor
8a2051e439 Decode cycles now start at t=19.5, 30.0, 49.5, and 58.5 s. 2024-01-19 13:04:24 -05:00
Joe Taylor
47c64f3675 Clean up commented code. 2024-01-19 12:11:30 -05:00
Joe Taylor
d155abe274 Remove a bunch of commented-out qDebug() statements. 2024-01-19 11:59:50 -05:00
Joe Taylor
9babd4616b Add a Q65-30x decode cycle at t=24s, ihsym=160. 2024-01-19 11:57:53 -05:00
Joe Taylor
e81cafa2c2 Remove unused variable in qmapa(). 2024-01-19 11:11:33 -05:00
Joe Taylor
55286b05a9 Zero the ss() array at start of sequence in symspec(). 2024-01-19 11:10:23 -05:00
Joe Taylor
b3d8750949 Increase width of "result" from 60 to 64, to accommodate longest messages. 2024-01-18 16:25:08 -05:00
Joe Taylor
3a5da4b2ac Deactivate a bunch of diagnostic wtites to console. 2024-01-18 10:19:30 -05:00
Joe Taylor
ae64b71498 Fix a typo. 2024-01-18 08:43:17 -05:00
Joe Taylor
74f07211c3 Restore normal behavior in read_qm(). 2024-01-17 12:41:43 -05:00
Joe Taylor
db3c7c4668 Full set of save_qm diagnostics for Roger and Uwe. 2024-01-17 10:52:39 -05:00
Joe Taylor
14b60aa146 Lighten the QMAP label background color for Q65-60D. 2024-01-17 09:08:38 -05:00
Joe Taylor
153c2e4212 Diagnostic work in progress on saving and reading QMAP files. 2024-01-17 07:13:05 -05:00
Joe Taylor
9044718e36 Better arrangement of timeout criteria for the QMAP decoder. 2024-01-16 13:50:38 -05:00
Joe Taylor
cc9c1c62c9 One more tweak: Do not call decoder at all, if nTx60>5. 2024-01-16 13:36:28 -05:00
Joe Taylor
8a899d000e Correct QMAP's dupe-checking behavior for manual decodes. 2024-01-16 11:46:36 -05:00
Joe Taylor
6e6caa0d82 Short decode cycles for 2nd half if we transmitted in 2nd half. 2024-01-15 19:49:10 -05:00
Joe Taylor
447127a49f Send filename and revision to q65c through a common block. 2024-01-15 19:24:26 -05:00
Joe Taylor
24bfc9f30d Correct a fvlaw in setting the decodeBusy flag. 2024-01-15 19:02:30 -05:00
Joe Taylor
9c45e510ff Be sure the saveFileName is static. 2024-01-15 18:34:01 -05:00
Joe Taylor
059096534b Cleanup. 2024-01-15 17:20:43 -05:00
Joe Taylor
2f46104140 Basically operational with save_qm called in the decoder thread. Needs testing! 2024-01-15 15:47:57 -05:00
Joe Taylor
4af9c58bb0 Send needed arguments to q65c(). 2024-01-15 13:45:00 -05:00
Joe Taylor
ae1cf334e2 Separate out the final call to timer(), using new "all_done()" function. 2024-01-15 13:22:45 -05:00
Joe Taylor
ff39abab58 WIP toward moving save_qm to the decoder thread. 2024-01-15 13:10:41 -05:00
Joe Taylor
f7e16671ab Status lab1 turns yellow when WSJT-X is transmitting. 2024-01-14 16:08:24 -05:00
Joe Taylor
8be743e0b8 Don't use future/watcher for reading raw data from disk. Better use of 30-second Rx sequences. 2024-01-13 15:28:35 -05:00
Joe Taylor
ae14fa13e9 Merge branch 'qmap' of bitbucket.org:k1jt/wsjtx into qmap 2024-01-13 13:32:21 -05:00
Joe Taylor
9c3cc3d685 Merge branch 'qmap' of bitbucket.org:k1jt/wsjtx into qmap 2024-01-13 09:51:01 -05:00
Joe Taylor
13a8efd533 One more removal: declaration of unused function. 2024-01-13 09:09:15 -05:00
Joe Taylor
80ed717aab Clean out the remains of writing .iq files. 2024-01-13 09:05:39 -05:00
Joe Taylor
8d17c7095c Disable saving .iq files, to see if Win7 then allows saving .qm files. 2024-01-12 10:34:41 -05:00
Joe Taylor
7a0a1736a7 Correct the logic for setting default bAlso30=true. 2024-01-11 13:59:32 -05:00
Joe Taylor
f93d846c22 Best (and simplest) performance is with FFTW npatience=0 and no threading. 2024-01-10 15:53:05 -05:00
Joe Taylor
42f322e461 Simplify ftninit. 2024-01-10 15:17:26 -05:00
Joe Taylor
f98009daab Use fftwf_ routines instead of sfftw_ routines. 2024-01-10 15:16:44 -05:00
Joe Taylor
c7e13191f1 Use the four2a in the WSJT-X lib directory. 2024-01-10 15:12:56 -05:00
Joe Taylor
2584b5ef3b Don't save and restore FFTW wisdom in QMAP. 2024-01-10 15:11:38 -05:00
Joe Taylor
6dc971d304 Add "Save decoded" to the QMAP Save menu. 2024-01-10 12:36:40 -05:00
Joe Taylor
fbfc157e79 Allocate and deallocate the id1 array in save_qm. 2024-01-10 12:00:44 -05:00
Joe Taylor
12042f6ae8 WIP: cleanup of things related to use of FFTW. More needed! 2024-01-08 18:55:00 -05:00
Joe Taylor
764fcaadcb Merge branch 'develop' into qmap 2024-01-08 08:58:34 -05:00
Joe Taylor
53db514d42 Enable decoding of MSK144 in jt9[.exe]. Thanks to Alex, VE3NEA! 2024-01-08 08:56:26 -05:00
Joe Taylor
e6fb080071 Change status label to "Saving files". 2024-01-06 12:19:44 -05:00
Joe Taylor
32c3cb7c4a Merge branch 'qmap' of bitbucket.org:k1jt/wsjtx into qmap 2024-01-06 11:37:19 -05:00
Joe Taylor
faae78e0e6 Enable click-to-decode for first half-minute. 2024-01-06 11:36:32 -05:00
Uwe Risse
bd4edcce49 Simplify color gradation. 2024-01-06 14:59:09 +01:00
Joe Taylor
07e82b0c40 Try to fix saving of ntx30[ab] in qm files. 2024-01-05 14:11:05 -05:00
Joe Taylor
d594d14a1e Tweak the Astro Window layout. 2024-01-05 13:17:51 -05:00
Joe Taylor
bb4564f734 Replace the required calculation of m_xavg, needed for pointing measurements. 2024-01-05 12:47:50 -05:00
Joe Taylor
9e0425ef40 Save and restore the "fac0" scaling value. 2024-01-05 07:01:55 -05:00
Joe Taylor
c733c0c123 Save SelfDop at start and end of Rx sequence in *.qm file header. 2024-01-04 16:51:02 -05:00
Joe Taylor
69f98d5c5c Q65-30x decoding turned on by default. 2024-01-04 16:06:42 -05:00
Joe Taylor
7f7a5322ed Clean up and complete(?) implementing save_qm and read_qm. 2024-01-04 16:03:44 -05:00
Joe Taylor
606506f578 Work in progress: Now able to read from *.qm files. 2024-01-04 10:52:36 -05:00
Joe Taylor
4a4225bb9c Working toward ability to write and read *.qm files. 2024-01-04 10:05:46 -05:00
Joe Taylor
b5bbf4a860 Working toward a new *.qm file type for QMAP. 2024-01-03 17:36:46 -05:00
Joe Taylor
986eaf5d40 Add fQSO back to azel.dat, for IK7EZN. 2024-01-03 16:17:57 -05:00
Joe Taylor
232c680a41 Remove unused code. 2024-01-03 15:31:33 -05:00
Joe Taylor
69f3186b13 General cleanup. Remove CFOM stuff. Fix logic for 30 s transmissions. Add ntx30x to .iq files. 2024-01-03 13:51:37 -05:00
Joe Taylor
05ed9c050d Another attempt at identifying 30 s Tx sequences from disk data. 2024-01-02 19:52:45 -05:00
Joe Taylor
a4e7b915de Maybe this is a better empirical test for ntx30[ab] in old disk data? 2024-01-02 16:04:03 -05:00
Joe Taylor
a7b6798c99 Bump the RC number to 4. 2024-01-02 09:55:12 -05:00
Joe Taylor
a7cef9fc89 Better format for Astro Data window. 2024-01-02 09:34:21 -05:00
Uwe Risse
0d46c8a66e Allow static RU exchanges only between 0001 and 7999. 2024-01-02 13:33:11 +01:00
Uwe Risse
2a4ab7e92f Display "Saving .iq files. 2024-01-02 12:06:35 +01:00
Uwe Risse
f3be4b47fa Add a color gradient for the Max Drift combo box. 2024-01-02 12:04:55 +01:00
Joe Taylor
fd0336f234 Optimize calling the QMAP decoder for different sub-sequence tasks. 2024-01-01 15:48:24 -05:00
Joe Taylor
7276e86e60 Delimit the times at which 60s and 30s decode attempts are made. 2024-01-01 13:56:39 -05:00
Joe Taylor
5cc82189e6 Clear up some cases where there's no need to call QMAP decoder. 2024-01-01 13:26:26 -05:00
Joe Taylor
ac0055b303 Remove more unused stuff. 2024-01-01 13:02:39 -05:00
Joe Taylor
0f417374c3 Remove more unused QMAP variables. 2024-01-01 12:51:15 -05:00
Joe Taylor
ce2a4d2fe7 Update the "Also Q65-30x" label appropriately when the 60s submode is changed. 2024-01-01 12:16:15 -05:00
Joe Taylor
40cba29e5f Removing more unused variables, etc., from QMAP. 2024-01-01 11:59:22 -05:00
Joe Taylor
f3308b7ee4 Remove unised variable m_fs96000. 2024-01-01 10:16:20 -05:00
Joe Taylor
2c2deab91a Remove references to unused variable m_idInt. 2024-01-01 10:10:40 -05:00
Joe Taylor
6cab8c3da9 Clean out some unused MAP65 variables. 2024-01-01 10:03:37 -05:00
Joe Taylor
76007c8031 Reconcile the datcom_ structure in soundin.cpp with that in commons.h. 2024-01-01 09:57:55 -05:00
Joe Taylor
673f74e67b QMAP work in progress: cleaning up the enabling of Q65-30x decodes. 2024-01-01 09:46:09 -05:00
Joe Taylor
1d21dff93f Increase the Fcal range to +/- 50000. 2024-01-01 07:31:04 -05:00
Joe Taylor
3ebf72076c Cancen RC nagging for K1JT and W2ZQ. 2023-12-31 15:17:56 -05:00
Joe Taylor
5bac396d60 Set signal meter to zero when transmitting. Remove some unused code. 2023-12-31 09:30:39 -05:00
Joe Taylor
efe8f090c2 Correct the bug in CallSandP2() that sets Rx freq incorrectly from ActiveStations window. 2023-12-31 09:05:31 -05:00
Uwe Risse
1f0ddb92c5 Make coloring of the Q65-30B lines compliant with Dark Style. 2023-12-28 23:51:09 +01:00
Joe Taylor
887bc433ec Some adjustments to details of QMAP <==> WSJT-X communication. 2023-12-28 16:41:22 -05:00
Joe Taylor
3546fd4ba2 Allow QMAP digital Gain settings in range +/- 50 dB. 2023-12-28 14:05:51 -05:00
Brian Moran
0eaf3360d8 remove incorrect check 2023-12-26 12:52:14 -08:00
Uwe Risse
115f850cd1 Align release date. 2023-12-24 16:11:52 +01:00
Uwe Risse
a4395c5d08 Finalize Release_Notes.txt and NEWS for the upcoming RC3 release. 2023-12-23 20:57:39 +01:00
Joe Taylor
e0078bf01e Merge branch 'develop' into qmap 2023-12-23 14:13:08 -05:00
Joe Taylor
e92d5ca1f5 Merge branch 'develop' of bitbucket.org:k1jt/wsjtx into develop 2023-12-23 14:00:12 -05:00
Joe Taylor
fcee51cea8 Update Section 1.7 of WSJT-X User Guide for v2.7.0. 2023-12-23 13:55:36 -05:00
Joe Taylor
f086aeb95a Correct a longstanding typo error in sun.f90. 2023-12-23 13:00:52 -05:00
Joe Taylor
c1253954f6 Minor editing of Release_Notes.txt for the upcoming RC3 release. 2023-12-23 10:13:17 -05:00
Joe Taylor
c8cbb481a0 Correct the expression of RC3 expiration date. 2023-12-23 09:24:23 -05:00
Uwe Risse
826fa8ae03 Draft text for the release notes. 2023-12-23 11:20:21 +01:00
Joe Taylor
d3e9f3fc5a Don't honor 'bSkip' if nagain.eq.1. 2023-12-22 19:37:54 -05:00
Joe Taylor
5bacc2d763 Click-to-decode should return ieediately after one success. 2023-12-22 15:50:17 -05:00
Joe Taylor
6b5db9fd0c Fix a problem with passing non-static variable to function in another thread. 2023-12-22 15:33:22 -05:00
Joe Taylor
08d9ebaf1a Some temporary commits, for testing. Includes some diagnostic prints! 2023-12-22 15:04:28 -05:00
Joe Taylor
6ec9466dc1 Remove a qDebug() call. 2023-12-21 11:22:55 -05:00
Joe Taylor
cdb7b02835 Don't call decoder if we transmitted Q65-30x in this 30 s segment. Also some CFOM diagnostics. 2023-12-21 11:04:23 -05:00
Joe Taylor
031f7fc1e6 Attempted fix so that Echo mode works with CFOM. 2023-12-21 10:05:01 -05:00
Joe Taylor
95daa2d791 Don't start another QMAP decode attempt if it's too late... 2023-12-21 09:15:19 -05:00
Joe Taylor
b13c7d8dca Make the QMAP checkbox for CFOM invisible by default. 2023-12-21 09:01:58 -05:00
Joe Taylor
171662ba50 Minor cleanup in cfom.f90. (But maybe dd is being altered, elsewhere, in symspec?) 2023-12-20 21:07:57 -05:00
Joe Taylor
4e935e01f3 Another try at getting yellow highlighting correct in Active Stations window. 2023-12-20 17:22:05 -05:00
Joe Taylor
9545c8eaa2 Many corrections for QMAP behavior regarding CFOM. 2023-12-20 12:18:05 -05:00
Uwe Risse
8f8f135e02 Update copyright notices. 2023-12-20 15:37:11 +01:00
Uwe Risse
50bd14937f Preparations for Release Candidate 3. 2023-12-20 15:26:06 +01:00
Joe Taylor
e42e995c59 Remove some obsolete MAP65 stuff. 2023-12-18 19:36:43 -05:00
Joe Taylor
2fb711401f Save and restore CFOM-adjusted data in *.iq files. 2023-12-18 16:34:44 -05:00
Joe Taylor
889531fda6 Add optional real-time CFOM to QMAP receiving. 2023-12-18 15:28:44 -05:00
Joe Taylor
e211bae779 Merge branch 'qmap' of bitbucket.org:k1jt/wsjtx into qmap 2023-12-18 13:55:35 -05:00
Joe Taylor
517ca61f5c Set background color of QMAP's MaxDrift control if its valus is > 0. 2023-12-18 13:54:22 -05:00
Joe Taylor
8be6d702d2 Several corrections in cfom_iq.f90. 2023-12-18 13:28:03 -05:00
Steven Franke
6f8c326717 ldpcsim174_91: Add the option to simulate the (174,91) code with noncoherent 8FSK on AWGN and block Rayleigh channels. 2023-12-18 10:23:12 -06:00
Uwe Risse
35a1d37012 Better stretching behavior of the program window (useful if users use App Scaling). 2023-12-18 16:19:11 +01:00
Joe Taylor
97fac57830 Add file cfom_iq.f90. 2023-12-17 17:19:23 -05:00
Joe Taylor
44bd5f9ac8 Change the "Dwell time" step size from 10 to 5. 2023-12-17 15:22:03 -05:00
Joe Taylor
363e301e31 Code cleanup. 2023-12-17 15:16:36 -05:00
Joe Taylor
84ec6bb457 Fix it so dupe-checking works when "Also Q65-30x" is not checked. 2023-12-17 15:09:31 -05:00
Joe Taylor
50519bc282 Send nhsym to qmapa, it might be used later. 2023-12-17 14:30:34 -05:00
Joe Taylor
1f78fe5f2c More info in QMAP status label lab4. 2023-12-17 14:07:41 -05:00
Joe Taylor
20c090e2bc QMAP decodes also at t=49.5 s. 2023-12-17 12:08:56 -05:00
Joe Taylor
2e715fa47d List ndecodes/ncand in QMAP status lab4. 2023-12-17 11:54:34 -05:00
Joe Taylor
d5a8ce97e3 Make sure diskDat() finished before starting another file. 2023-12-17 07:27:28 -05:00
Joe Taylor
bb5e8efd52 Remove an unused variable. 2023-12-17 06:19:59 -05:00
Joe Taylor
6afced7335 Minor code cleanup. 2023-12-16 11:59:11 -05:00
Joe Taylor
90f3c59ea0 Skip useless calls to QMAP's decode0(), depending on 30 s transmissions. 2023-12-16 11:48:06 -05:00
Uwe Risse
f42a1bb357 Create Save Directory if it does not yet exist. 2023-12-16 15:40:43 +01:00
Joe Taylor
9d5f3858d4 When requested, call the QMAP decoder also at t=30s. 2023-12-14 13:37:28 -05:00
Uwe Risse
1aeaec7a6d Change some default values. 2023-12-13 19:32:38 +01:00
Uwe Risse
186abfe99e Again, make the red background color consistent with the WSJT-X default value. 2023-12-13 18:51:06 +01:00
Uwe Risse
c45420b194 Make the red background colur consistent with the WSJT-X default value. 2023-12-13 18:36:16 +01:00
Uwe Risse
1b3f4315b1 More options for highlighting messages with myCall. 2023-12-13 16:32:57 +01:00
Joe Taylor
5e8deecdb4 Fix the logic about not scrolling the QMAP waterfall when transmitting. 2023-12-12 15:43:29 -05:00
Joe Taylor
7255a7c86a Merge branch 'qmap' of bitbucket.org:k1jt/wsjtx into qmap 2023-12-12 12:23:08 -05:00
Joe Taylor
1542b7f857 If myCall is in the message, highlight the line with red background. 2023-12-11 19:01:05 -05:00
Joe Taylor
9c7c837dc8 Yellow background for Q65-30x decodes in Active Stations window. 2023-12-11 16:07:43 -05:00
Uwe Risse
e040c926b9 Always attempt to decode when Continuous Waterfall is enabled. 2023-12-11 18:47:52 +01:00
Joe Taylor
11f8efd2a9 Suppress QMAP decoding only if WSJT-X transmitted too much in a Q65-60x submode. 2023-12-11 11:46:02 -05:00
Joe Taylor
e2ef2c7dbb Change beta-test expiration date to July 1, 2024. 2023-12-11 11:20:44 -05:00
Joe Taylor
c413ea2f14 Remove the 'QMAP deciding finished' stuff, it was a bad idea. 2023-12-11 10:51:50 -05:00
Joe Taylor
b0ea3a2eb5 Distinguish between m_nTx30 and m_nTx60. Add "QMAP decoding finished" so Active Stations will update. 2023-12-11 10:28:13 -05:00
Joe Taylor
717fd42ac1 Update the GUI label for Input device. 2023-12-11 09:03:01 -05:00
Uwe Risse
d9cab59537 Some more corrections and updates to the text. 2023-12-11 13:46:40 +01:00
Uwe Risse
61fc069443 Hamlib Git address updated. 2023-12-11 13:17:02 +01:00
Joe Taylor
2f1082e973 Try to correct the logic about not decoding if we transmitted too much. Not fully tested! 2023-12-09 15:20:59 -05:00
Joe Taylor
adc457214f Set correct Q65 submode (ABCDE) for a call selected from Active Stations window. 2023-12-09 14:53:28 -05:00
Joe Taylor
5d94775c7d Change nmode to nBaseSubmode, and don't allow for a JT65 mode. 2023-12-09 13:25:07 -05:00
Joe Taylor
91c0e43ef6 Don't re-define value of mode_q65; use mode_q65_tmp instead! 2023-12-08 16:48:17 -05:00
Joe Taylor
0cf01f1248 Correct a flaw in setting QMAP background colors. 2023-12-08 15:32:40 -05:00
Uwe Risse
f525f08365 Update CTY.DAT file. 2023-12-08 21:25:21 +01:00
Joe Taylor
6019101018 Highlight QMAP's Q65-30B decodes with yellow background. 2023-12-08 15:21:47 -05:00
Joe Taylor
115c4c4e30 Activate the Gain co0ntrol in QMAP's "File -> Settings -> I/O Devices". 2023-12-08 14:06:15 -05:00
Joe Taylor
ac1b5d03b2 Set TRperiod to 30 or 60 when in Q65 mode and a call is selected in AS Window. 2023-12-08 12:39:00 -05:00
Uwe Risse
6e9dc42881 Assign WAE entities to the correct DXCC when "Include extra WAE entities" is not selected. 2023-12-08 18:19:42 +01:00
Joe Taylor
e6fad89904 Remove a diagnostic write. 2023-12-08 12:13:00 -05:00
Joe Taylor
fe19a7263d Clean up the way UTC gets written to q65_decodes.txt and all_qmap.txt. 2023-12-08 12:06:20 -05:00
Joe Taylor
57aca5c222 Better checkbox labels in Active Stations window. 2023-12-07 14:38:49 -05:00
Joe Taylor
0d74918634 Most (probably not all) of the QMAP <-> WSJT-X interaction is now functional. 2023-12-07 14:29:27 -05:00
Joe Taylor
43019d0cb4 Transfer of QMAP decodes to ActiveStations basically working. Must add submode info. 2023-12-07 13:36:53 -05:00
Joe Taylor
7622915147 Add submode to display of decoded messages. 2023-12-07 13:00:21 -05:00
Joe Taylor
62eb8fa3e9 Merge branch 'qmap' of bitbucket.org:k1jt/wsjtx into qmap 2023-12-07 12:34:22 -05:00
Joe Taylor
8ae939b573 Save 60 s of data to *.iq files. Last 1.5 s may be zeroes. 2023-12-07 12:33:19 -05:00
Joe Taylor
0455cf23e6 Bring the MAP65's interface from q65b to map65_mmdec up to date. 2023-12-07 12:28:19 -05:00
Joe Taylor
7f660d62fa Reduce the search range back to +/- 10 Hz from detected sync freq. 2023-12-07 11:52:41 -05:00
Joe Taylor
bf861d9979 Resize arrays to enable processing up to full 60 seconds of data. 2023-12-07 11:43:25 -05:00
Joe Taylor
d62cdbaf2b Intermediate commit: work in progress. 2023-12-07 11:20:21 -05:00
Uwe Risse
ff2f2b00b9 Add an option for a continuous waterfall when WSJT-X is transmitting. 2023-12-07 11:27:26 +01:00
Joe Taylor
cb7395b504 QMAP now decodes both Q65-60C and Q65-30B in same 60-second Rx sequence. 2023-12-06 15:15:48 -05:00
Joe Taylor
93dba5e623 Work in progress on QMAP, for Q65-30x decoding. 2023-12-06 14:22:45 -05:00
Uwe Risse
05931313b3 Make some right-click mouse press events more intuitive and consistent. 2023-12-06 13:18:25 +01:00
Joe Taylor
7348bc323e Work in progress: Q65-30B candidate selection now basically working. 2023-12-05 15:11:57 -05:00
Joe Taylor
76e28298a3 Preparing for decoding of Q65-30x modes. Not there yet. 2023-12-04 15:13:47 -05:00
Joe Taylor
c6fb86067e Compute ss(i,j) at Q65-30x half-symbol steps. Functional now, but needs work... 2023-12-04 14:09:39 -05:00
Joe Taylor
711ea392ef Remove references to w2a, w2b. 2023-12-04 13:05:15 -05:00
Joe Taylor
456c5de125 Remove references to 95238; increase size of ss(322,NFFT) to ss(373,NFFT). 2023-12-04 13:01:12 -05:00
Joe Taylor
c02b977c94 Remove references to nfast in symspec.f90. 2023-12-04 12:49:17 -05:00
Joe Taylor
d8570e6817 Revert "Temporary code to save a Q65-30x *.wav file."
This reverts commit 60bcd6291d46a9f773e8bcd316a9aa153ed28e97.
2023-12-04 12:02:18 -05:00
Joe Taylor
74c6d9eb64 Merge branch 'develop' into qmap 2023-12-04 09:15:40 -05:00
Uwe Risse
0456b3af8c Don't insert individual contest name when in Fox mode. 2023-12-02 18:58:48 +01:00
Uwe Risse
bfd44f178a Improved behavior when Rig Split has been selected (patch by Mike). 2023-12-02 12:06:15 +01:00
Uwe Risse
4a9c4dac6f Each click on the FT8 button should exit hound mode. 2023-12-02 12:01:23 +01:00
Joe Taylor
f6989c3e6c Formatting updates for program CABLOG. 2023-12-01 09:35:53 -05:00
Joe Taylor
5e9b9ff2d4 Temporary commit (has diagnostic prints), starting on Q65-30 capability. 2023-12-01 08:46:40 -05:00
Joe Taylor
b986c7c81c Modify cablog to handle MAP65 log files wsjt.log as well as WSJT-X log files wsjtx.log. 2023-11-30 15:56:09 -05:00
Joe Taylor
330db0feb4 Merge branch 'develop' into qmap 2023-11-30 10:46:23 -05:00
Joe Taylor
933aa29451 Add utility program 'cablog' to convert wsjtx.log to Cabrillo format. 2023-11-28 13:43:16 -05:00
Uwe Risse
f394d77be7 Save and restore the state of the "Sh" checkbox by mode, and correctly restore state of the "Fast" checkbox. 2023-11-25 16:12:21 +01:00
Joe Taylor
5d3e927648 For Q65 mode, change "Ready only" to "CQ only" for the Active Stations window. 2023-11-21 14:15:31 -05:00
Joe Taylor
6546846f2c Merge branch 'develop' of bitbucket.org:k1jt/wsjtx into develop 2023-11-21 13:21:12 -05:00
Joe Taylor
05ae0ee9af Correct a bug in computing the value of Doppler spread for FST4. Thanks to N2BP! 2023-11-21 13:12:54 -05:00
Uwe Risse
6156cf0d7d Save and restore Submode, TRperiod and FTol parameters by mode, also for the JT9 Fast modes. 2023-11-20 16:38:02 +01:00
Joe Taylor
48ae40d781 Restore the previous code for saving JT9 submode parameters. 2023-11-16 09:32:38 -05:00
Joe Taylor
60bcd6291d Temporary code to save a Q65-30x *.wav file. 2023-11-14 10:55:56 -05:00
Uwe Risse
18b9dbf41b Display Hamlib version on Linux and macOS. 2023-10-30 16:04:25 +01:00
Uwe Risse
ce7a1c26fc Make code compliant with Qt6. 2023-10-29 13:39:05 +01:00
Uwe Risse
3fcb8d3deb Add some improvements to the Update Hamlib feature (display Hamlib version, etc.). 2023-10-29 12:48:26 +01:00
Uwe Risse
84069fe9e9 Set default download for the LotW file to http. 2023-10-26 11:22:04 +02:00
Uwe Risse
d4d47f8323 Correct a typo. 2023-10-25 08:28:42 +02:00
Uwe Risse
dece2e9fc5 Minor corrections to the Update Hamlib groupbox. 2023-10-23 21:06:50 +02:00
Uwe Risse
c5969b0434 Backup the libhamlib-4.dll file, so it is available after a program update. 2023-10-23 20:59:39 +02:00
Uwe Risse
d76790adc3 Add a new function "Update Hamlib (Windows only)". 2023-10-23 20:58:39 +02:00
k9an
b073fa0550 Make spot counter work for WSPR. 2023-10-21 09:56:41 -05:00
Joe Taylor
e8162970de Another tweak to protect against invalid argument in pctile(). 2023-10-18 08:01:47 -04:00
Joe Taylor
97ed4022a2 Check for invalid argument in pctile(). 2023-10-18 07:50:39 -04:00
Joe Taylor
893565f40d Remove a qDebug(). 2023-10-17 14:27:49 -04:00
Joe Taylor
9913111464 Merge branch 'develop' of bitbucket.org:k1jt/wsjtx into develop 2023-10-17 13:59:48 -04:00
Joe Taylor
ba453131eb Protect against wacky settings of nfa, nfb, in Q65 mode. 2023-10-17 13:59:08 -04:00
Uwe Risse
2e3c37d7b2 Uncheck other Pref settings only when a new Pref setting is added for that band and mode. 2023-10-17 10:23:08 +02:00
Uwe Risse
bf70fae0bf Don't uncheck the preferred frequency when adding a new frequency for that mode. 2023-10-16 20:29:33 +02:00
Joe Taylor
64f53f30ff Merge branch 'develop' of bitbucket.org:k1jt/wsjtx into develop 2023-10-16 12:23:57 -04:00
Joe Taylor
f75969ffb6 Remove some unused or irrelevant code. 2023-10-16 12:23:26 -04:00
Uwe Risse
8ecdebaeba Allow changing Tx frequency also for FT4 and FST4 when the VHF features are enabled. 2023-10-14 11:55:32 +02:00
Uwe Risse
a3a02a8996 Fix a compilation error on Mac M1 (patch by Alex, K6LOT). 2023-10-10 10:58:36 +02:00
Uwe Risse
06d1469c10 Prevent redundant network communication between WSJT-X and DX Lab Suite Commander. 2023-09-30 18:44:03 +02:00
Uwe Risse
ea8737e9f1 Remove RIG_TARGETABLE_PURE since it is no longer needed, and will not be supported anymore with new Hamlib versions. 2023-09-29 14:57:53 +02:00
Uwe Risse
c65ebb16d5 Add a tooltip. 2023-09-13 16:28:17 +02:00
Joe Taylor
b2a1c2d977 Use AlignCenter for Max Age and Max N controls in Active Stations window. 2023-09-11 10:30:04 -04:00
Uwe Risse
2ba2a580ff Improve auto stretching of the controls in the Active Stations window. 2023-09-11 11:43:31 +02:00
Joe Taylor
9a863d6590 Merge branch 'develop' of bitbucket.org:k1jt/wsjtx into develop 2023-08-31 14:32:21 -04:00
Joe Taylor
b04e1517a9 Must define 'offset' as a Fortran integer. Increase NJUNK by 1. 2023-08-31 14:29:20 -04:00
Uwe Risse
3b03c9c824 Fix a logging error in Q65_Pileup mode. 2023-08-29 17:03:20 +02:00
Joe Taylor
2d9bebddbe Correct a typo in User Guiide. 2023-08-29 08:43:59 -04:00
Uwe Risse
fea274ed57 QMAP: make offset adjustable. 2023-08-29 13:17:20 +02:00
Joe Taylor
e4dca8e241 Edits to User Guide concerning Echo mode. 2023-08-25 10:06:25 -04:00
Uwe Risse
cbcf0c0ecd Restore an accidentally deleted part 2023-08-24 16:53:38 +02:00
Uwe Risse
28d014e634 Allow averaging only when the VHF features are enabled, and make the program behavior more consistent and intuitive. 2023-08-24 16:10:19 +02:00
Uwe Risse
4f874b6507 Change the label texts to "Single Period Decodes" and "Average Decodes" only if averaging is enabled. 2023-08-23 18:26:10 +02:00
Uwe Risse
630f0c34c3 Do not adjust rx/tx for echo mode. 2023-08-04 16:02:03 +02:00
Uwe Risse
c2883532ed Prevent a possible memory leak, patch by Mike W9MDB. 2023-08-03 18:24:01 +02:00
Uwe Risse
ce2e94de26 For Q65, don't display decodes within 10 Hz of fQSO in the right window, but still display all messages for us. 2023-07-20 17:23:29 +02:00
Uwe Risse
88852bebe6 Revert "For Q65, don't display decodes within 10 Hz of fQSO in the right window, but still display all messages for us."
This reverts commit ec9682b57b9de25188411176660f228ce4c11602.
2023-07-20 16:52:44 +02:00
Uwe Risse
ec9682b57b For Q65, don't display decodes within 10 Hz of fQSO in the right window, but still display all messages for us. 2023-07-20 13:56:54 +02:00
Uwe Risse
68aae12588 Automatic detection of the version number for the splash screen. 2023-07-11 21:46:51 +02:00
Uwe Risse
99876a1916 Allow static 4-digit numbers as FT RU exchanges instead of serial numbers. This extends the usability of the FT RU protocol for other contest types. 2023-07-11 21:25:11 +02:00
Uwe Risse
54e46d90f2 Set version number to 2.7.0-rc3. 2023-07-11 21:16:55 +02:00
82 changed files with 5139 additions and 3392 deletions

View File

@ -71,7 +71,7 @@ message (STATUS "******************************************************")
include (set_build_type)
# RC 0 or omitted is a development build, GA is a General Availability release build
set_build_type (RC 2)
set_build_type (RC 4)
set (wsjtx_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}${BUILD_TYPE_REVISION}")
#
@ -161,7 +161,6 @@ endif ()
set (WSJT_PLUGIN_DESTINATION ${PLUGIN_DESTINATION} CACHE PATH "Path for plugins")
set (WSJT_QT_CONF_DESTINATION ${QT_CONF_DESTINATION} CACHE PATH "Path for the qt.conf file")
#
# Project sources
#
@ -363,6 +362,7 @@ set (wsjt_FSRCS
lib/bpdecode128_90.f90
lib/ft8/bpdecode174_91.f90
lib/baddata.f90
lib/cablog.f90
lib/calibrate.f90
lib/ccf2.f90
lib/ccf65.f90
@ -492,6 +492,7 @@ set (wsjt_FSRCS
lib/msk144sim.f90
lib/mskrtd.f90
lib/nuttal_window.f90
lib/decode_msk144.f90
lib/ft4/ft4sim.f90
lib/ft4/ft4sim_mult.f90
lib/ft4/ft4_downsample.f90
@ -1143,6 +1144,9 @@ target_link_libraries (jt65sim wsjt_fort wsjt_cxx)
add_executable (sumsim lib/sumsim.f90)
target_link_libraries (sumsim wsjt_fort wsjt_cxx)
add_executable (cablog lib/cablog.f90)
target_link_libraries (cablog)
add_executable (test_snr lib/test_snr.f90)
target_link_libraries (test_snr wsjt_fort)
@ -1599,7 +1603,7 @@ install (TARGETS jt9 wsprd fmtave fcal fmeasure
if(WSJT_BUILD_UTILS)
install (TARGETS ft8code jt65code jt9code jt4code msk144code
q65code fst4sim q65sim echosim hash22calc
q65code fst4sim q65sim echosim hash22calc cablog
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
)

View File

@ -173,7 +173,6 @@
#include <QJsonDocument>
#include <QJsonArray>
#include "pimpl_impl.hpp"
#include "Logger.hpp"
#include "qt_helpers.hpp"
@ -245,6 +244,9 @@ namespace
|X85|X86|X87|X88|X89|X90|X91
|X92|X93|X94|X95|X96|X97|X98
|X99
|[0][0][0][1-9] # 4-digit numbers
|[0][0-9][1-9][0-9] # between 0001
|[1-7][0-9][0-9][0-9] # and 7999
)
)", QRegularExpression::CaseInsensitiveOption | QRegularExpression::ExtendedPatternSyntaxOption};
@ -277,7 +279,6 @@ namespace
constexpr quint32 qrg_version_100 {100};
}
//
// Dialog to get a new Frequency item
//
@ -330,9 +331,9 @@ public:
connect (button_box, &QDialogButtonBox::accepted, this, &FrequencyDialog::accept);
connect (button_box, &QDialogButtonBox::rejected, this, &FrequencyDialog::reject);
connect(start_date_time_edit_, &QDateTimeEdit::dateTimeChanged, this, &FrequencyDialog::checkSaneDates);
connect(end_date_time_edit_, &QDateTimeEdit::dateTimeChanged, this, &FrequencyDialog::checkSaneDates);
connect(enable_dates_checkbox_, &QCheckBox::stateChanged, this, &FrequencyDialog::toggleValidity);
connect (start_date_time_edit_, &QDateTimeEdit::dateTimeChanged, this, &FrequencyDialog::checkSaneDates);
connect (end_date_time_edit_, &QDateTimeEdit::dateTimeChanged, this, &FrequencyDialog::checkSaneDates);
connect (enable_dates_checkbox_, &QCheckBox::stateChanged, this, &FrequencyDialog::toggleValidity);
toggleValidity();
}
@ -385,7 +386,6 @@ private:
QDateTimeEdit *start_date_time_edit_;
};
//
// Dialog to get a new Station item
//
@ -458,9 +458,6 @@ public:
}
};
// Internal implementation of the Configuration class.
class Configuration::impl final
: public QDialog
@ -580,6 +577,11 @@ private:
Q_SLOT void on_rescan_log_push_button_clicked (bool);
Q_SLOT void on_CTY_download_button_clicked (bool);
Q_SLOT void on_LotW_CSV_fetch_push_button_clicked (bool);
Q_SLOT void on_hamlib_download_button_clicked (bool);
Q_SLOT void on_revert_update_button_clicked (bool);
void error_during_hamlib_download (QString const& reason);
void after_hamlib_downloaded();
void display_file_information();
Q_SLOT void on_cbx2ToneSpacing_clicked(bool);
Q_SLOT void on_cbx4ToneSpacing_clicked(bool);
@ -684,6 +686,7 @@ private:
QString FD_exchange_;
QString RTTY_exchange_;
QString Contest_Name_;
QString hamlib_backed_up_;
qint32 id_interval_;
qint32 ntrials_;
@ -758,7 +761,6 @@ private:
#include "Configuration.moc"
// delegate to implementation class
Configuration::Configuration (QNetworkAccessManager * network_manager, QDir const& temp_directory,
QSettings * settings, LogBook * logbook, QWidget * parent)
@ -1570,6 +1572,7 @@ void Configuration::impl::read_settings ()
ui_->Field_Day_Exchange->setText(FD_exchange_);
ui_->RTTY_Exchange->setText(RTTY_exchange_);
ui_->Contest_Name->setText(Contest_Name_);
hamlib_backed_up_ = settings_->value ("HamlibBackedUp",QString {}).toString ();
if (next_font_.fromString (settings_->value ("Font", QGuiApplication::font ().toString ()).toString ())
&& next_font_ != font_)
@ -1746,6 +1749,18 @@ void Configuration::impl::read_settings ()
pwrBandTuneMemory_ = settings_->value("pwrBandTuneMemory",false).toBool ();
highlight_DXcall_ = settings_->value("highlight_DXcall",false).toBool ();
highlight_DXgrid_ = settings_->value("highlight_DXgrid",false).toBool ();
#ifdef WIN32
QTimer::singleShot (2500, [=] {display_file_information ();});
#else
ui_->hamlib_groupBox->setTitle("Hamlib Version");
ui_->rbHamlib64->setVisible(false);
ui_->rbHamlib32->setVisible(false);
ui_->hamlib_download_button->setVisible(false);
ui_->revert_update_button->setVisible(false);
ui_->backed_up_text->setVisible(false);
ui_->backed_up->setVisible(false);
QTimer::singleShot (2500, [=] {display_file_information ();});
#endif
}
void Configuration::impl::find_audio_devices ()
@ -2484,6 +2499,113 @@ void Configuration::impl::on_decoded_text_font_push_button_clicked ()
);
}
void Configuration::impl::on_hamlib_download_button_clicked (bool /*clicked*/)
{
#ifdef WIN32
extern char* hamlib_version2;
QString hamlib = QString(QLatin1String(hamlib_version2));
SettingsGroup g {settings_, "Configuration"};
settings_->setValue ("HamlibBackedUp", hamlib);
settings_->sync ();
QDir dataPath = QCoreApplication::applicationDirPath();
QFile f1 {dataPath.absolutePath() + "/" + "libhamlib-4_old.dll"};
QFile f2 {dataPath.absolutePath() + "/" + "libhamlib-4_new.dll"};
if (f1.exists()) f1.remove();
if (f2.exists()) f2.remove();
ui_->hamlib_download_button->setEnabled (false);
ui_->revert_update_button->setEnabled (false);
if (ui_->rbHamlib32->isChecked()) {
cty_download.configure(network_manager_,
"https://n0nb.users.sourceforge.net/dll32/libhamlib-4.dll",
dataPath.absoluteFilePath("libhamlib-4_new.dll"),
"Downloading latest libhamlib-4.dll");
} else {
cty_download.configure(network_manager_,
"https://n0nb.users.sourceforge.net/dll64/libhamlib-4.dll",
dataPath.absoluteFilePath("libhamlib-4_new.dll"),
"Downloading latest libhamlib-4.dll");
}
connect (&cty_download, &FileDownload::complete, this, &Configuration::impl::after_hamlib_downloaded, Qt::UniqueConnection);
connect (&cty_download, &FileDownload::error, this, &Configuration::impl::error_during_hamlib_download, Qt::UniqueConnection);
cty_download.start_download();
#else
MessageBox::warning_message (this, tr ("Hamlib update only available on Windows."));
#endif
}
void Configuration::impl::error_during_hamlib_download (QString const& reason)
{
QDir dataPath = QCoreApplication::applicationDirPath();
MessageBox::warning_message (this, tr ("Error Loading libhamlib-4.dll"), reason);
ui_->hamlib_download_button->setEnabled (true);
ui_->revert_update_button->setEnabled (true);
}
void Configuration::impl::after_hamlib_downloaded ()
{
QDir dataPath = QCoreApplication::applicationDirPath();
QFile::rename(dataPath.absolutePath() + "/" + "libhamlib-4.dll", dataPath.absolutePath() + "/" + "libhamlib-4_old.dll");
QTimer::singleShot (1000, [=] {
QFile::rename(dataPath.absolutePath() + "/" + "libhamlib-4_new.dll", dataPath.absolutePath() + "/" + "libhamlib-4.dll");
});
QTimer::singleShot (2000, [=] {
MessageBox::information_message (this, tr ("Hamlib Update successful \n\nNew Hamlib will be used after restart"));
ui_->revert_update_button->setEnabled (true);
ui_->hamlib_download_button->setEnabled (true);
});
}
void Configuration::impl::on_revert_update_button_clicked (bool /*clicked*/)
{
#ifdef WIN32
QDir dataPath = QCoreApplication::applicationDirPath();
QFile f {dataPath.absolutePath() + "/" + "libhamlib-4_old.dll"};
if (f.exists()) {
ui_->revert_update_button->setEnabled (false);
ui_->hamlib_download_button->setEnabled (false);
QFile::rename(dataPath.absolutePath() + "/" + "libhamlib-4.dll", dataPath.absolutePath() + "/" + "libhamlib-4_new.dll");
QTimer::singleShot (1000, [=] {
QFile::copy(dataPath.absolutePath() + "/" + "libhamlib-4_old.dll", dataPath.absolutePath() + "/" + "libhamlib-4.dll");
});
QTimer::singleShot (2000, [=] {
MessageBox::information_message (this, tr ("Hamlib successfully reverted \n\nReverted Hamlib will be used after restart"));
ui_->revert_update_button->setEnabled (true);
ui_->hamlib_download_button->setEnabled (true);
});
} else {
MessageBox::warning_message (this, tr ("No Hamlib update found that could be reverted"));
}
#else
MessageBox::warning_message (this, tr ("Hamlib update only available on Windows."));
#endif
}
void Configuration::impl::display_file_information ()
{
#ifdef WIN32
QDir dataPath = QCoreApplication::applicationDirPath();
extern char* hamlib_version2;
QString hamlib = QString(QLatin1String(hamlib_version2));
ui_->in_use->setText(hamlib);
QFileInfo fi2(dataPath.absolutePath() + "/" + "libhamlib-4_old.dll");
QString birthTime2 = fi2.birthTime().toString("yyyy-MM-dd hh:mm");
QFile f {dataPath.absolutePath() + "/" + "libhamlib-4_old.dll"};
if (f.exists()) {
if (hamlib_backed_up_=="") {
ui_->backed_up->setText(QString{"no hamlib data available, file saved %1"}.arg(birthTime2));
} else {
ui_->backed_up->setText(hamlib_backed_up_);
}
} else {
ui_->backed_up->setText("");
}
#else
extern char* hamlib_version2;
QString hamlib = QString(QLatin1String(hamlib_version2));
ui_->in_use->setText(hamlib);
#endif
}
void Configuration::impl::on_PTT_port_combo_box_activated (int /* index */)
{
set_rig_invariants ();

View File

@ -225,8 +225,7 @@ public:
// This method queries if a CAT and PTT connection is operational.
bool is_transceiver_online () const;
// Start the rig connection, safe and normal to call when rig is
// already open.
// Start the rig connection, safe and normal to call when rig is already open.
bool transceiver_online ();
// check if a real rig is configured

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>684</width>
<height>662</height>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
@ -529,6 +529,280 @@ quiet period when decoding is done.</string>
<string>Radio interface configuration settings.</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_3">
<item row="5" column="2">
<widget class="QGroupBox" name="mode_group_box">
<property name="toolTip">
<string>Modulation mode selected on radio.</string>
</property>
<property name="title">
<string>Mode</string>
</property>
<layout class="QGridLayout" name="gridLayout_10">
<item row="0" column="1">
<widget class="QRadioButton" name="mode_USB_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;USB is usually the correct modulation mode,&lt;/p&gt;&lt;p&gt;unless the radio has a special data or packet mode setting&lt;/p&gt;&lt;p&gt;for AFSK operation.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>US&amp;B</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">TX_mode_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="mode_none_radio_button">
<property name="toolTip">
<string>Don't allow the program to set the radio mode
(not recommended but use if the wrong mode
or bandwidth is selected).</string>
</property>
<property name="text">
<string>None</string>
</property>
<attribute name="buttonGroup">
<string notr="true">TX_mode_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="2">
<widget class="QRadioButton" name="mode_data_radio_button">
<property name="toolTip">
<string>If this is available then it is usually the correct mode for this program.</string>
</property>
<property name="text">
<string>Data/P&amp;kt</string>
</property>
<attribute name="buttonGroup">
<string notr="true">TX_mode_button_group</string>
</attribute>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="2">
<widget class="QGroupBox" name="TX_audio_source_group_box">
<property name="toolTip">
<string>Some radios can select the audio input using a CAT command,
this setting allows you to select which audio input will be used
(if it is available then generally the Rear/Data option is best).</string>
</property>
<property name="title">
<string>Transmit Audio Source</string>
</property>
<layout class="QGridLayout" name="gridLayout_7">
<item row="0" column="0">
<widget class="QRadioButton" name="TX_source_data_radio_button">
<property name="text">
<string>Rear&amp;/Data</string>
</property>
<attribute name="buttonGroup">
<string notr="true">TX_audio_source_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="TX_source_mic_radio_button">
<property name="text">
<string>&amp;Front/Mic</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">TX_audio_source_button_group</string>
</attribute>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="2">
<widget class="QGroupBox" name="PTT_method_group_box">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>How this program activates the PTT on your radio?</string>
</property>
<property name="title">
<string>PTT Method</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QRadioButton" name="PTT_VOX_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;No PTT activation, instead the radio's automatic VOX is used to key the transmitter.&lt;/p&gt;&lt;p&gt;Use this if you have no radio interface hardware.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>VO&amp;X</string>
</property>
<attribute name="buttonGroup">
<string notr="true">PTT_method_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="PTT_DTR_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use the RS-232 DTR control line to toggle your radio's PTT, requires hardware to interface the line.&lt;/p&gt;&lt;p&gt;Some commercial interface units also use this method.&lt;/p&gt;&lt;p&gt;The DTR control line of the CAT serial port may be used for this or a DTR control line on a different serial port may be used.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>&amp;DTR</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">PTT_method_button_group</string>
</attribute>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="PTT_CAT_radio_button">
<property name="toolTip">
<string>Some radios support PTT via CAT commands,
use this option if your radio supports it and you have no
other hardware interface for PTT.</string>
</property>
<property name="text">
<string>C&amp;AT</string>
</property>
<attribute name="buttonGroup">
<string notr="true">PTT_method_button_group</string>
</attribute>
</widget>
</item>
<item row="1" column="1">
<widget class="QRadioButton" name="PTT_RTS_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use the RS-232 RTS control line to toggle your radio's PTT, requires hardware to interface the line.&lt;/p&gt;&lt;p&gt;Some commercial interface units also use this method.&lt;/p&gt;&lt;p&gt;The RTS control line of the CAT serial port may be used for this or a RTS control line on a different serial port may be used. Note that this option is not available on the CAT serial port when hardware flow control is used.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>R&amp;TS</string>
</property>
<attribute name="buttonGroup">
<string notr="true">PTT_method_button_group</string>
</attribute>
</widget>
</item>
<item row="2" column="0" rowspan="2" colspan="2">
<layout class="QFormLayout" name="formLayout_4">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="PTT_port_label">
<property name="text">
<string>Port:</string>
</property>
<property name="buddy">
<cstring>PTT_port_combo_box</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="PTT_port_combo_box">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select the RS-232 serial port utilised for PTT control, this option is available when DTR or RTS is selected above as a transmit method.&lt;/p&gt;&lt;p&gt;This port can be the same one as the one used for CAT control.&lt;/p&gt;&lt;p&gt;For some interface types the special value CAT may be chosen, this is used for non-serial CAT interfaces that can control serial port control lines remotely (OmniRig for example).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="editable">
<bool>true</bool>
</property>
<property name="currentText">
<string/>
</property>
<property name="currentIndex">
<number>-1</number>
</property>
<property name="insertPolicy">
<enum>QComboBox::NoInsert</enum>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="8" column="2">
<widget class="QGroupBox" name="split_operation_group_box">
<property name="title">
<string>Split Operation</string>
</property>
<layout class="QGridLayout" name="gridLayout_12">
<item row="0" column="2">
<widget class="QRadioButton" name="split_emulate_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use only VFO A for split operation (the program temporarily changes the QRG of your rig during transmission).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Fake It</string>
</property>
<attribute name="buttonGroup">
<string notr="true">split_mode_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="split_rig_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use VFO A+B for split operation (works with many rigs, but requires the use of both VFOs).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Rig</string>
</property>
<attribute name="buttonGroup">
<string notr="true">split_mode_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="split_none_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Don't use split (not recommended).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>None</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">split_mode_button_group</string>
</attribute>
</widget>
</item>
</layout>
</widget>
</item>
<item row="11" column="2">
<spacer name="verticalSpacer_7">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" rowspan="11">
<widget class="QGroupBox" name="CAT_control_group_box">
<property name="sizePolicy">
@ -935,6 +1209,13 @@ a few, particularly some Kenwood rigs, require it).</string>
</layout>
</widget>
</item>
<item row="4" column="2">
<widget class="Line" name="line_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="Line" name="line_6">
<property name="orientation">
@ -942,236 +1223,6 @@ a few, particularly some Kenwood rigs, require it).</string>
</property>
</widget>
</item>
<item row="1" column="1" rowspan="12">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QGroupBox" name="PTT_method_group_box">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>How this program activates the PTT on your radio?</string>
</property>
<property name="title">
<string>PTT Method</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QRadioButton" name="PTT_VOX_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;No PTT activation, instead the radio's automatic VOX is used to key the transmitter.&lt;/p&gt;&lt;p&gt;Use this if you have no radio interface hardware.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>VO&amp;X</string>
</property>
<attribute name="buttonGroup">
<string notr="true">PTT_method_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="PTT_DTR_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use the RS-232 DTR control line to toggle your radio's PTT, requires hardware to interface the line.&lt;/p&gt;&lt;p&gt;Some commercial interface units also use this method.&lt;/p&gt;&lt;p&gt;The DTR control line of the CAT serial port may be used for this or a DTR control line on a different serial port may be used.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>&amp;DTR</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">PTT_method_button_group</string>
</attribute>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="PTT_CAT_radio_button">
<property name="toolTip">
<string>Some radios support PTT via CAT commands,
use this option if your radio supports it and you have no
other hardware interface for PTT.</string>
</property>
<property name="text">
<string>C&amp;AT</string>
</property>
<attribute name="buttonGroup">
<string notr="true">PTT_method_button_group</string>
</attribute>
</widget>
</item>
<item row="1" column="1">
<widget class="QRadioButton" name="PTT_RTS_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use the RS-232 RTS control line to toggle your radio's PTT, requires hardware to interface the line.&lt;/p&gt;&lt;p&gt;Some commercial interface units also use this method.&lt;/p&gt;&lt;p&gt;The RTS control line of the CAT serial port may be used for this or a RTS control line on a different serial port may be used. Note that this option is not available on the CAT serial port when hardware flow control is used.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>R&amp;TS</string>
</property>
<attribute name="buttonGroup">
<string notr="true">PTT_method_button_group</string>
</attribute>
</widget>
</item>
<item row="2" column="0" rowspan="2" colspan="2">
<layout class="QFormLayout" name="formLayout_4">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="PTT_port_label">
<property name="text">
<string>Port:</string>
</property>
<property name="buddy">
<cstring>PTT_port_combo_box</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="PTT_port_combo_box">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select the RS-232 serial port utilised for PTT control, this option is available when DTR or RTS is selected above as a transmit method.&lt;/p&gt;&lt;p&gt;This port can be the same one as the one used for CAT control.&lt;/p&gt;&lt;p&gt;For some interface types the special value CAT may be chosen, this is used for non-serial CAT interfaces that can control serial port control lines remotely (OmniRig for example).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="editable">
<bool>true</bool>
</property>
<property name="currentText">
<string/>
</property>
<property name="currentIndex">
<number>-1</number>
</property>
<property name="insertPolicy">
<enum>QComboBox::NoInsert</enum>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="5" column="2">
<widget class="QGroupBox" name="mode_group_box">
<property name="toolTip">
<string>Modulation mode selected on radio.</string>
</property>
<property name="title">
<string>Mode</string>
</property>
<layout class="QGridLayout" name="gridLayout_10">
<item row="0" column="1">
<widget class="QRadioButton" name="mode_USB_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;USB is usually the correct modulation mode,&lt;/p&gt;&lt;p&gt;unless the radio has a special data or packet mode setting&lt;/p&gt;&lt;p&gt;for AFSK operation.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>US&amp;B</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">TX_mode_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="mode_none_radio_button">
<property name="toolTip">
<string>Don't allow the program to set the radio mode
(not recommended but use if the wrong mode
or bandwidth is selected).</string>
</property>
<property name="text">
<string>None</string>
</property>
<attribute name="buttonGroup">
<string notr="true">TX_mode_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="2">
<widget class="QRadioButton" name="mode_data_radio_button">
<property name="toolTip">
<string>If this is available then it is usually the correct mode for this program.</string>
</property>
<property name="text">
<string>Data/P&amp;kt</string>
</property>
<attribute name="buttonGroup">
<string notr="true">TX_mode_button_group</string>
</attribute>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="2">
<widget class="QGroupBox" name="TX_audio_source_group_box">
<property name="toolTip">
<string>Some radios can select the audio input using a CAT command,
this setting allows you to select which audio input will be used
(if it is available then generally the Rear/Data option is best).</string>
</property>
<property name="title">
<string>Transmit Audio Source</string>
</property>
<layout class="QGridLayout" name="gridLayout_7">
<item row="0" column="0">
<widget class="QRadioButton" name="TX_source_data_radio_button">
<property name="text">
<string>Rear&amp;/Data</string>
</property>
<attribute name="buttonGroup">
<string notr="true">TX_audio_source_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="TX_source_mic_radio_button">
<property name="text">
<string>&amp;Front/Mic</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">TX_audio_source_button_group</string>
</attribute>
</widget>
</item>
</layout>
</widget>
</item>
<item row="9" column="2">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="2">
<widget class="Line" name="line_3">
<property name="orientation">
@ -1179,8 +1230,15 @@ this setting allows you to select which audio input will be used
</property>
</widget>
</item>
<item row="11" column="2">
<spacer name="verticalSpacer_7">
<item row="1" column="1" rowspan="13">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="13" column="0">
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
@ -1192,62 +1250,8 @@ this setting allows you to select which audio input will be used
</property>
</spacer>
</item>
<item row="0" column="0" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QLabel" name="rig_label">
<property name="text">
<string>Rig:</string>
</property>
<property name="buddy">
<cstring>rig_combo_box</cstring>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="rig_combo_box">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="CAT_poll_interval_label">
<property name="text">
<string>Poll Interval:</string>
</property>
<property name="buddy">
<cstring>CAT_poll_interval_spin_box</cstring>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="CAT_poll_interval_spin_box">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Interval to poll rig for status. Longer intervals will mean that changes to the rig will take longer to be detected.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="suffix">
<string> s</string>
</property>
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="2">
<widget class="Line" name="line_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="10" column="2">
<layout class="QHBoxLayout" name="horizontalLayout_11">
<layout class="QHBoxLayout" name="testCATPTT_Layout">
<item>
<widget class="QPushButton" name="test_CAT_push_button">
<property name="toolTip">
@ -1304,59 +1308,55 @@ radio interface behave as expected.</string>
</item>
</layout>
</item>
<item row="8" column="2">
<widget class="QGroupBox" name="split_operation_group_box">
<property name="title">
<string>Split Operation</string>
</property>
<layout class="QGridLayout" name="gridLayout_12">
<item row="0" column="2">
<widget class="QRadioButton" name="split_emulate_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use only VFO A for split operation (the program temporarily changes the QRG of your rig during transmission).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Fake It</string>
</property>
<attribute name="buttonGroup">
<string notr="true">split_mode_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="split_rig_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use VFO A+B for split operation (works with many rigs, but requires the use of both VFOs).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Rig</string>
</property>
<attribute name="buttonGroup">
<string notr="true">split_mode_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="split_none_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Don't use split (not recommended).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>None</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">split_mode_button_group</string>
</attribute>
</widget>
</item>
</layout>
</widget>
<item row="0" column="0" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QLabel" name="rig_label">
<property name="text">
<string>Rig:</string>
</property>
<property name="buddy">
<cstring>rig_combo_box</cstring>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="rig_combo_box">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="CAT_poll_interval_label">
<property name="text">
<string>Poll Interval:</string>
</property>
<property name="buddy">
<cstring>CAT_poll_interval_spin_box</cstring>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="CAT_poll_interval_spin_box">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Interval to poll rig for status. Longer intervals will mean that changes to the rig will take longer to be detected.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="suffix">
<string> s</string>
</property>
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="12" column="0">
<spacer name="verticalSpacer_5">
<item row="9" column="2">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
@ -1368,6 +1368,84 @@ radio interface behave as expected.</string>
</property>
</spacer>
</item>
<item row="12" column="0">
<widget class="QGroupBox" name="hamlib_groupBox">
<property name="title">
<string>Update Hamlib</string>
</property>
<layout class="QGridLayout" name="gridLayout_18">
<item row="0" column="0">
<widget class="QRadioButton" name="rbHamlib64">
<property name="text">
<string>64-bit</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="rbHamlib32">
<property name="text">
<string>32-bit</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="revert_update_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Revert the last Hamlib update. &lt;/p&gt;&lt;p&gt;Note: This function is only available on Windows.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Revert Update</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="hamlib_download_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Download the latest libhamlib-4.dll file from https://n0nb.users.sourceforge.net/. &lt;/p&gt;&lt;p&gt;Note: This function is only available on Windows.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Update Hamlib</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="4">
<layout class="QGridLayout" name="hamlib_version_gridLayout" columnstretch="0,1">
<item row="0" column="0">
<widget class="QLabel" name="in_use_text">
<property name="text">
<string>In use:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="backed_up_text">
<property name="text">
<string>Backed up:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="in_use">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="backed_up">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="audio_tab">
@ -2435,7 +2513,7 @@ Right click for insert and delete options.</string>
<string>URL</string>
</property>
<property name="text">
<string>https://lotw.arrl.org/lotw-user-activity.csv</string>
<string>http://lotw.arrl.org/lotw-user-activity.csv</string>
</property>
</widget>
</item>
@ -3420,13 +3498,13 @@ Right click for insert and delete options.</string>
</connection>
</connections>
<buttongroups>
<buttongroup name="split_mode_button_group"/>
<buttongroup name="CAT_data_bits_button_group"/>
<buttongroup name="PTT_method_button_group"/>
<buttongroup name="CAT_handshake_button_group"/>
<buttongroup name="split_mode_button_group"/>
<buttongroup name="TX_audio_source_button_group"/>
<buttongroup name="special_op_activity_button_group"/>
<buttongroup name="TX_mode_button_group"/>
<buttongroup name="special_op_activity_button_group"/>
<buttongroup name="CAT_data_bits_button_group"/>
<buttongroup name="CAT_stop_bits_button_group"/>
<buttongroup name="PTT_method_button_group"/>
</buttongroups>
</ui>

33
INSTALL
View File

@ -27,7 +27,7 @@ the Boost C++ libraries. For MS Windows see the section "Building
from Source on MS Windows" below. For Apple Mac see the section
"Building from Source on Apple Mac".
Qt v5, preferably v5.9 or later is required to build WSJT-X.
Qt v5, preferably v5.12 or later is required to build WSJT-X.
Qt v5 multimedia support, serial port, and Linguist is necessary as
well as the core Qt v5 components, normally installing the Qt
@ -50,15 +50,13 @@ normally you can choose not to install libusb-1.0-dev but if you have
a SoftRock USB or similar SDR that uses a custom USB interface then it
is required.
The Hamlib library is required. Currently WSJT-X needs to be built
using a forked version of the Hamlib git master. This fork contains
patches not yet accepted by the Hamlib development team which are
essential for correct operation of WSJT-X. To build the Hamlib fork
from sources something like the following recipe should suffice:
The Hamlib library is required. WSJT-X can be built with any version
of the Hamlib git master. To build Hamlib from sources something
like the following recipe should suffice:
$ mkdir ~/hamlib-prefix
$ cd ~/hamlib-prefix
$ git clone git://git.code.sf.net/u/bsomervi/hamlib src
$ git clone https://github.com/Hamlib/Hamlib src
$ cd src
$ git checkout integration
$ ./bootstrap
@ -113,13 +111,13 @@ Building from Source on MS Windows
Because building on MS Windows is quite complicated there is an
Software Development Kit available that provides all the prerequisite
libraries and tools for building WSJT-X. This SDK is called JT-SDK-QT
libraries and tools for building WSJT-X. This SDK is called HAMLIB SDK
which is documented here:
http://physics.princeton.edu/pulsar/K1JT/wsjtx-doc/dev-guide-main.html
https://sourceforge.net/projects/hamlib-sdk/
If you need to build Hamlib rather than use the Hamlib kit included in
the JT-SDK the following recipe should help. Reasons for building
the HAMLIB SDK the following recipe should help. Reasons for building
Hamlib from source might include picking up the very latest patches or
building a different branch that you wish to contribute to.
@ -143,7 +141,7 @@ In an MSYS shell:-
$ mkdir ~/hamib-prefix
$ cd ~/hamlib-prefix
$ git clone git://git.code.sf.net/u/bsomervi/hamlib src
$ git clone https://github.com/Hamlib/Hamlib src
$ cd src
$ git checkout integration
$ ./bootstrap
@ -178,10 +176,6 @@ Hamlib binary location as one of the paths in CMAKE_PREFIX_PATH.
Building from Source on Apple Mac
=================================
These instructions are adapted from my Evernote page at:
https://www.evernote.com/pub/bsomervi/wsjt-xmacbuilds
There are several ways to get the required GNU and other open source
tools and libraries installed, my preference is MacPorts because it is
easy to use and does everything we need.
@ -228,12 +222,11 @@ instructions are here:
Hamlib
------
First fetch hamlib from the repository, in this case my fork of Hamlib
3 until the official repository has all the fixes we need:
First fetch hamlib from the git master repository:
$ mkdir -p ~/hamlib-prefix/build
$ cd ~/hamlib-prefix
$ git clone git://git.code.sf.net/u/bsomervi/hamlib src
$ git clone https://github.com/Hamlib/Hamlib src
$ cd src
$ git checkout integration
$ ./bootstrap
@ -352,8 +345,8 @@ which installs the WSJT-X application bundle into ~/wsjtx-prefix
Updating and Rebuilding Hamlib
==============================
From time to time new fixes will be pushed to the Hamlib fork
repository integration branch. To pick them up type:
From time to time new fixes will be pushed to the Hamlib git
master repository. To pick them up type:
$ cd ~/hamlib-prefix/src
$ git pull

101
NEWS
View File

@ -9,7 +9,106 @@
\$$ \$$ \$$$$$$ \$$$$$$ \$$ \$$ \$$
Copyright 2001 - 2023 by Joe Taylor, K1JT, and the WSJT Development Team
Copyright 2001 - 2024 by Joe Taylor, K1JT, and the WSJT Development Team
Release: WSJT-X 2.7.0-rc4
March 11, 2024
-------------------------
WSJT-X 2.7.0 Release Candidate 4 brings some improvements for Fox-mode
operators, new features for companion program QMAP, and a number of
relatively minor enhancements and bug fixes.
QMAP enhancements -- of particular interest to EME operators:
- QMAP now decodes Q65 submodes with both 60-second and 30-second T/R
sequence lengths. Clicking on a resulting line in the WSJT-X Active
Stations window automatically sets dial frequency and working
submode as needed to call that station.
- QMAP operates in 60-second receive sequences, and its Q65 decoder
starts at t=19.5, 30.0, 49.5, and 58.5 s into the sequence. Most
decoded messages are displayed well before the end of the relevant
time slot.
- A new, more compact file format is now used for wideband data
files. A "Save decoded" option has been added to the Save menu.
- An option has been added to allow exporting a 3 kHz portion of a
wideband data file as a standard WSJT-X *.wav file.
- CTRL+click on QMAP's upper waterfall sends an integer kHz dial
frequency request to WSJT-X.
- With focus on the WSJT-X main window, hit Alt+A on the keyboard to
clear the Active Stations window.
- Many minor enhancements to the User Interface.
WSJT-X:
- Enable decoding of MSK144 from the jt9[.exe] executable.
- Several changes to reduce problems experienced when (contrary to
our recommendations) messages with short (10-bit) callsign hashes
are used in standard FT4/FT8 sub-bands.
Release: WSJT-X 2.7.0-rc3
January 1, 2024
-------------------------
WSJT-X 2.7.0 Release Candidate 3 brings some new features, as well as
numerous detail improvements and bug fixes, such as:
- Added a new "Update Hamlib" function. On Windows, it allows the user to
update Hamlib directly from the program. The previously used version is
backed up, so the user can easily revert a hamlib update.
- The Hamlib version in use is now displayed (also on Linux and macOS).
- The FT Roundup Messages protocol has been enhanced. It now allows also
the exchange of static 4-digit numbers instead of serial numbers. This
extends the usability of the FT RU protocol for other contest types.
- Improved direct switching between modes. Submode, as well as the status
of the "Sh" and "Fast" checkboxes are now saved and restored by mode.
- Some right-click events were made more intuitive and consistent.
- Right-clicking the Q65 button enables Q65 Pileup mode, a left-click
brings you back to the normal Q65 mode.
- Right-click the JT65 button to switch to JT9 mode.
- For Q65, all messages for us are now displayed in the right window.
- Message averaging is now allowed only when VHF features are
enabled, and label texts are changed to "Single Period Decodes" and
"Average Decodes" only if averaging is enabled.
- Some improvements to the Hamlib Transceiver code. Behavior is now
more stable when Rig Split has been selected.
- Prevented redundant network communication between WSJT-X and DX Lab
Suite Commander.
- Download of the LotW file now works without OpenSSL libraries.
- Made the spot counter work for WSPR.
- Prevented insertion of an individual contest name when in Fox mode.
- WAE entities are now assigned to the correct DXCC when "Include
extra WAE entities" is not selected.
- Added a utility program 'cablog' which can be used to convert the
wsjtx.log file to Cabrillo format for the ARRL EME contest.
- Minor improvements to the Active Stations window.
- The Rx/Tx frequency for Echo mode has been fixed at 1500 Hz.
- Some corrections and updates to the INSTALL instructions for Linux.
- Updated CTY.DAT file.
Release: WSJT-X 2.7.0-rc2
July 7, 2023

View File

@ -9,7 +9,106 @@
\$$ \$$ \$$$$$$ \$$$$$$ \$$ \$$ \$$
Copyright 2001 - 2023 by Joe Taylor, K1JT, and the WSJT Development Team
Copyright 2001 - 2024 by Joe Taylor, K1JT, and the WSJT Development Team
Release: WSJT-X 2.7.0-rc4
March 11, 2024
-------------------------
WSJT-X 2.7.0 Release Candidate 4 brings some improvements for Fox-mode
operators, new features for companion program QMAP, and a number of
relatively minor enhancements and bug fixes.
QMAP enhancements -- of particular interest to EME operators:
- QMAP now decodes Q65 submodes with both 60-second and 30-second T/R
sequence lengths. Clicking on a resulting line in the WSJT-X Active
Stations window automatically sets dial frequency and working
submode as needed to call that station.
- QMAP operates in 60-second receive sequences, and its Q65 decoder
starts at t=19.5, 30.0, 49.5, and 58.5 s into the sequence. Most
decoded messages are displayed well before the end of the relevant
time slot.
- A new, more compact file format is now used for wideband data
files. A "Save decoded" option has been added to the Save menu.
- An option has been added to allow exporting a 3 kHz portion of a
wideband data file as a standard WSJT-X *.wav file.
- CTRL+click on QMAP's upper waterfall sends an integer kHz dial
frequency request to WSJT-X.
- With focus on the WSJT-X main window, hit Alt+A on the keyboard to
clear the Active Stations window.
- Many minor enhancements to the User Interface.
WSJT-X:
- Enable decoding of MSK144 from the jt9[.exe] executable.
- Several changes to reduce problems experienced when (contrary to
our recommendations) messages with short (10-bit) callsign hashes
are used in standard FT4/FT8 sub-bands.
Release: WSJT-X 2.7.0-rc3
January 1, 2024
-------------------------
WSJT-X 2.7.0 Release Candidate 3 brings some new features, as well as
numerous detail improvements and bug fixes, such as:
- Added a new "Update Hamlib" function. On Windows, it allows the user to
update Hamlib directly from the program. The previously used version is
backed up, so the user can easily revert a hamlib update.
- The Hamlib version in use is now displayed (also on Linux and macOS).
- The FT Roundup Messages protocol has been enhanced. It now allows also
the exchange of static 4-digit numbers instead of serial numbers. This
extends the usability of the FT RU protocol for other contest types.
- Improved direct switching between modes. Submode, as well as the status
of the "Sh" and "Fast" checkboxes are now saved and restored by mode.
- Some right-click events were made more intuitive and consistent.
- Right-clicking the Q65 button enables Q65 Pileup mode, a left-click
brings you back to the normal Q65 mode.
- Right-click the JT65 button to switch to JT9 mode.
- For Q65, all messages for us are now displayed in the right window.
- Message averaging is now allowed only when VHF features are
enabled, and label texts are changed to "Single Period Decodes" and
"Average Decodes" only if averaging is enabled.
- Some improvements to the Hamlib Transceiver code. Behavior is now
more stable when Rig Split has been selected.
- Prevented redundant network communication between WSJT-X and DX Lab
Suite Commander.
- Download of the LotW file now works without OpenSSL libraries.
- Made the spot counter work for WSPR.
- Prevented insertion of an individual contest name when in Fox mode.
- WAE entities are now assigned to the correct DXCC when "Include
extra WAE entities" is not selected.
- Added a utility program 'cablog' which can be used to convert the
wsjtx.log file to Cabrillo format for the ARRL EME contest.
- Minor improvements to the Active Stations window.
- The Rx/Tx frequency for Echo mode has been fixed at 1500 Hz.
- Some corrections and updates to the INSTALL instructions for Linux.
- Updated CTY.DAT file.
Release: WSJT-X 2.7.0-rc2
July 7, 2023

View File

@ -206,15 +206,18 @@ void DXLabSuiteCommanderTransceiver::do_frequency (Frequency f, MODE m, bool /*n
{
CAT_TRACE (f << ' ' << state ());
auto f_string = frequency_to_string (f);
auto params = ("<xcvrfreq:%1>" + f_string).arg (f_string.size ());
simple_command (("<command:10>CmdSetFreq<parameters:%1>" + params).arg (params.size ()));
if (UNK != m)
if (UNK != m && m != get_mode ())
{
auto m_string = map_mode (m);
auto params = ("<xcvrfreq:%1>" + f_string + "<xcvrmode:%2>" + m_string + "<preservesplitanddual:1>Y").arg (f_string.size ()).arg (m_string.size ());
simple_command (("<command:14>CmdSetFreqMode<parameters:%1>" + params).arg (params.size ()));
update_mode (m);
}
else
{
auto params = ("<xcvrfreq:%1>" + f_string).arg (f_string.size ());
simple_command (("<command:10>CmdSetFreq<parameters:%1>" + params).arg (params.size ()));
}
update_rx_frequency (f);
}

View File

@ -760,7 +760,7 @@ int HamlibTransceiver::do_start ()
m_->reversed_ = RIG_VFO_B == v;
if (m_->mode_query_works_ && !(rig_get_caps_int (m_->model_, RIG_CAPS_TARGETABLE_VFO) & (RIG_TARGETABLE_MODE | RIG_TARGETABLE_PURE)))
if (m_->mode_query_works_ && !(rig_get_caps_int (m_->model_, RIG_CAPS_TARGETABLE_VFO) & RIG_TARGETABLE_MODE))
{
if (RIG_OK == rig_get_mode (m_->rig_.data (), RIG_VFO_CURR, &m, &w))
{
@ -911,9 +911,9 @@ void HamlibTransceiver::do_frequency (Frequency f, MODE m, bool no_ignore)
// to frequency such as the TS-2000 auto mode setting
CAT_TRACE ("rig_set_mode mode=" << rig_strrmode (new_mode));
m_->error_check (rig_set_mode (m_->rig_.data (), target_vfo, new_mode, RIG_PASSBAND_NOCHANGE), tr ("setting current VFO mode"));
// set mode on VFOB too if we are in split
if (state ().split()) rig_set_mode (m_->rig_.data (), RIG_VFO_B, new_mode, RIG_PASSBAND_NOCHANGE), tr ("setting VFOB mode");
}
// set mode on VFOB too if we are in split
if (state ().split()) rig_set_mode (m_->rig_.data (), RIG_VFO_B, new_mode, RIG_PASSBAND_NOCHANGE), tr ("setting VFOB mode");
update_mode (m);
}
}
@ -1147,7 +1147,7 @@ void HamlibTransceiver::do_poll ()
if ((WSJT_RIG_NONE_CAN_SPLIT || !m_->is_dummy_)
&& state ().split ()
&& (rig_get_caps_int (m_->model_, RIG_CAPS_TARGETABLE_VFO) & (RIG_TARGETABLE_FREQ | RIG_TARGETABLE_PURE))
&& (rig_get_caps_int (m_->model_, RIG_CAPS_TARGETABLE_VFO) & RIG_TARGETABLE_FREQ)
&& !m_->one_VFO_)
{
// only read "other" VFO if in split, this allows rigs like

3474
cty.dat

File diff suppressed because it is too large Load Diff

View File

@ -1,68 +1,60 @@
[[NEW_FEATURES]]
=== New in Version {VERSION_MAJOR}.{VERSION_MINOR}
- _WSJT-X 2.6_ implements new features supporting the ARRL
International Digital Contest and its distance based scoring. The
*Call 1st* checkbox has been replaced by a drop-down control offering
*CQ Max Dist* as an alternative. A new window labeled *Active
Stations* displays a list of received but unworked callsigns, sorted
in decreasing order of potential contest points. With option *CQ Max
Dist* selected, the program will select the reply to your CQ that
yields the most contest points. You can click on a line in the Active
Stations window to call that station.
_WSJT-X 2.7_ introduces a new program called *QMAP*, a new Special
Operating Activity *Q65 Pileup*, an option to *Update Hamlib* at the
click of a button, and a number of other enhancements and bug fixes.
- Decoding performance for FT8 and Q65 has been improved in a variety
of situations with available _a priori_ (AP) information.
- QMAP and Q65 Pileup mode are of particular interest to those engaged
in Earth-Moon-Earth (EME) communication, but other applications may
be found for them as well. QMAP is currently available for Windows
only; it is derived from MAP65, an older program used since 2007 for
EME. QMAP provides single-polarization receive-only capabilities for
any one of the 60-second submodes of Q65. It allows you to monitor
all traffic in a 90 kHz sub-band while conducting EME QSOs in the
usual way with _WSJT-X_. Q65 Pileup mode helps DX operators using
Q65 in pileup circumstances with many simultaneous callers and very
weak signals, such as those experienced by 6-meter EME DXpeditions.
Further details on QMAP and Q65 Pileup mode are available in a
Quick-Start guide posted here:
https://wsjt.sourceforge.io/Quick_Start_WSJT-X_2.7_QMAP.pdf
- *Echo* mode now offers a *Clear Avg* button and produces reliable
measurements of SNR even when Doppler spread is large. Its *Monitor*
function can be used to measure SNR for a received unmodulated carrier
such as a key-down test signal emitted by another station and
reflected from the Moon, and also to measure Sun, Moon, and ground
noise as aids for optimizing an EME station's performance.
- A button *Update Hamlib* now appears on the *Settings -> Radio* tab.
On Windows it allows the user to automatically download and install
the latest version of the rig-control features in Hamlib. The
previously used version is backed up, so you can easily revert the
procedure if necessary. Names and dates of the active and backup
versions are clearly displayed.
- New buttons on the main window allow quick changes between modes
FT4, FT8, MSK144, Q65, and JT65, and toggling FT8 Hound mode ON/OFF.
- Spotting to *PSK Reporter* has been made more efficient. Redundant
spots are omitted, and all posts are spread more widely in time. If
your station locator is changed, for example during portable
operations, your new locator will be sent automatically to PSK
Reporter.
- New convenience features allow Fox operators to react more quickly
to particular QSO situations. A two-column table in Tab 2 provides an
overview of the queue and of callsigns with QSOs in progress. Fox
operator can change the ordering of callsigns in the queue, allowing
reaction to changes in propagation. Fox now responds automatically
for another two cycles to stations whose report has not been received,
increasing the success rate for difficult QSOs.
- *Fox* mode now provides more convenient handling of the two callsign
queues, and Fox's Log window displays statistical data on recent QSO
rate. Multi-streamed messages transmitted by _MSHV_ are now handled
properly when _WSJT-X_ is in *Hound* mode.
- The Working frequency table now offers save/restore capability and
better handling of more than one frequency per mode-band
combination. You can set preferred frequencies, and WSJT-X will select
these when you change band or mode. You can label a tabled frequency
with a description, for example a DXpedition callsign, and set Start
and End date and time so the frequencies automatically appear and
disappear from the displayed options. You can load a publicly
available frequency table from a file, to easily make such DXpedition
data available to the program.
- The cty.dat file can now be updated by clicking a button on the
*Settings -> Colors* tab.
- Optional color highlighting is provided for specified DX Call and DX
Grid, and for messages containing RR73 or 73.
- The FT Roundup message protocol now allows the exchange of static
4-digit numbers in place of serial numbers. This extends the
usability of the FT RU protocol for other contest types.
- New options are provided for writing to file ALL.TXT. You can
request automatic starting of a new file every month or every year,
and you can disable writing altogether.
- Features for main-window switching between modes have been enhanced
so that submode and status of the *Sh* and *Fast* checkboxes are
saved and restored by mode. Right-click events were made more
intuitive and consistent. Right-clicking the Q65 button enables Q65
Pileup mode, and a left-click brings you back to the normal Q65
mode. Right-click on the JT65 button switches to JT9 mode.
- Settings for T/R period and Submode are remembered by mode when you
switch directly between modes: for example, MSK144-15, Q65-60A, or
FST4-120.
- Message averaging is now allowed only when *VHF features* are
enabled. Main window text box labels are changed to read "`Single
Period Decodes`" and "`Average Decodes`" when averaging is enabled.
- Tx and Rx audio frequencies are remembered and restored when you
return from a mode that sets a default frequency 1500 Hz (MSK144,
FST4W, Echo, WSPR, FreqCal), then switching back to FT4, FT8, Q65,
FST4, or JT65.
Further details on minor changes can be found in the Release Notes,
accessible from the _WSJT-X_ *Help* menu.
- Rig control is provided for some new radios, and bug fixes for
controlling others.
- New features in _MAP65_ (available for Windows only) include an aid
for measuring antenna pointing errors and an ability to read the file
wsjtx.log (kept by _WSJT-X_) to recognize EME contest dupes. In
addition, _MAP65_ now sends additional information to file azel.dat
and offers optional digital scaling of input I/Q data.

View File

@ -31,7 +31,7 @@ image::RadioTab.png[align="center",alt="Radio Tab"]
suitable.
* _CAT Control_: To have _WSJT-X_ control the radio directly rather
than though another program, make the following settings:
than through another program, make the following settings:
** Select the *Serial Port* or *Network Server* including the service
port number used to communicate with your radio.

View File

@ -26,7 +26,7 @@ on bands above 1.2 GHz.
To activate the VHF-and-up features:
- On the *Settings | General* tab check *Enable VHF/UHF/Microwave
- On the *Settings | General* tab check *Enable VHF and submode
features* and *Single decode*.
- For EME, check *Decode after EME delay* to allow for extra path
@ -291,14 +291,16 @@ communication.
For lunar echoes, _WSJT_ generates short fixed-frequency transmissions
that alternate with reception intervals at the appropriate
Doppler-shifted frequency. With *Split Operation* set to *Rig* or
*Fake It* on the *Settings | Radio* tab, check *Doppler tracking* and
*Own Echo* on the Astronomical Data window. Point your antenna at the
Moon and click *Enable Tx* on the main window to start a sequence of
echo measurements. Each cycle takes 6 seconds. If strong enough,
echoes will be visible in the waterfall. Their average spectrum will
be displayed in the Echo Graph window, and numerical parameters of the
measurements appear in the main window:
Doppler-shifted frequency. Be sure that *Enable VHF and submode
features* has been checked on the *Settings | General* tab. With
*Split Operation* set to *Rig* or *Fake It* on the *Settings | Radio*
tab, check *Doppler tracking* and *Own Echo* on the Astronomical Data
window. Point your antenna at the Moon and click *Enable Tx* on the
main window to start a sequence of echo measurements. Each cycle
takes 6 seconds. If strong enough, echoes will be visible in the
waterfall. Their average spectrum will be displayed in the Echo Graph
window, and numerical parameters of the measurements appear in the
main window:
image::Echo_1296.png[align="center",alt="Echo 144 MHz"]

View File

@ -474,13 +474,17 @@ subroutine unpack77(c77,nrx,msg,unpk77_success)
i=index(call_1,' ')
if(i.ge.4 .and. ipa.eq.1 .and. i3.eq.1) call_1(i:i+1)='/R'
if(i.ge.4 .and. ipa.eq.1 .and. i3.eq.2) call_1(i:i+1)='/P'
if(i.ge.4) call add_call_to_recent_calls(call_1)
if(i.ge.4) call add_call_to_recent_calls(call_1)
endif
if(index(call_2,'<').le.0) then
i=index(call_2,' ')
if(i.ge.4 .and. ipb.eq.1 .and. i3.eq.1) call_2(i:i+1)='/R'
if(i.ge.4 .and. ipb.eq.1 .and. i3.eq.2) call_2(i:i+1)='/P'
if(i.ge.4) call add_call_to_recent_calls(call_2)
if(i.ge.4) then
call add_call_to_recent_calls(call_2)
! only hash the "from" call
call save_hash_call(call_2,ndum10,ndum12,ndum22)
endif
endif
if(igrid4.le.MAXGRID4) then
call to_grid4(igrid4,grid4,unpkg4_success)
@ -560,6 +564,7 @@ subroutine unpack77(c77,nrx,msg,unpk77_success)
call_1=call_3
call_2=adjustl(c11)//' '
call add_call_to_recent_calls(call_2)
call save_hash_call(call_2,ndum10,ndum12,ndum22)
if(nrx.eq.1 .and. &
dxcall13_set .and. mycall13_set .and. &
call_2.eq.dxcall13 .and. &
@ -1540,7 +1545,7 @@ subroutine add_call_to_recent_calls(callsign)
endif
! Make sure that callsign is hashed
call save_hash_call(callsign,n10,n12,n22)
! call save_hash_call(callsign,n10,n12,n22) ! commented out - do this in the calling routine:
return
end subroutine add_call_to_recent_calls

142
lib/cablog.f90 Normal file
View File

@ -0,0 +1,142 @@
program cablog
character*100 line,infile,outfile
character cband*4,cmode*2,cdate*10,cutc*4,callsign*10,mycall*10
character csent*4,crcvd*4,dsent*4,drcvd*4,g1*4
character*3 cmo(12)
integer icomma(20)
logical map65
logical isgrid,gridx
data cmo/'Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep', &
'Oct','Nov','Dec'/
isgrid(g1)=g1(1:1).ge.'A' .and. g1(1:1).le.'R' .and. g1(2:2).ge.'A' .and. &
g1(2:2).le.'R' .and. g1(3:3).ge.'0' .and. g1(3:3).le.'9' .and. &
g1(4:4).ge.'0' .and. g1(4:4).le.'9' .and. g1(1:4).ne.'RR73'
nargs=iargc()
if(nargs.ne.4) then
print*,"Program cablog converts file 'wsjtx.log' written by WSJT-X"
print*,"(or wsjt.log written by MAP65) to a bare-bones Cabrillo"
print*,"log for the ARRL International EME Contest. You will"
print*,"certainly need to edit the header information, and you may"
print*,"edit the log elsewhere as required."
print*,' '
print*,'Usage: cablog <MyCall> <sent> <rcvd> <infile>'
print*,'Examples: cablog W2ZQ -15 -16 wsjtx.log'
print*,' cablog W2ZQ O O wsjt.log'
go to 999
endif
call getarg(1,mycall)
outfile=trim(mycall)//'.log'
call getarg(2,dsent)
gridx=isgrid(dsent)
call getarg(3,drcvd)
call getarg(4,infile)
open(10,file=trim(infile),status='old')
open(12,file=trim(outfile),status='unknown')
write(12,1000)
1000 format('START-OF-LOG: 3.0'/ &
'CONTEST: ARRL-EME'/ &
'CALLSIGN: '/ &
'CATEGORY-OPERATOR: '/ &
'CATEGORY-BAND: '/ &
'CATEGORY-MODE: '/ &
'EMAIL: '/ &
'OPERATORS: '/ &
'CATEGORY-POWER: HIGH'/ &
'CATEGORY-TRANSMITTER: ONE'/ &
'CATEGORY-STATION: FIXED'/ &
'CATEGORY-TIME: 24-HOURS'/ &
'CATEGORY-ASSISTED: ASSISTED'/ &
'LOCATION: SNJ'/ &
'CLAIMED-SCORE: '/ &
'CLUB: '/ &
'NAME: '/ &
'ADDRESS: '/ &
'ADDRESS: '/ &
'ADDRESS: '/ &
'CREATED-BY: cablog (C) K1JT')
n=0
map65=.false.
do nn=1,9999
read(10,'(a100)',end=900) line
if(len(trim(line)).eq.0) cycle
if(line(6:6).ge.'A' .and. line(6:6).le.'Z') map65=.true.
n=n+1
k=0
do j=1,100
if(line(j:j).eq.',') then
k=k+1
icomma(k)=j
endif
enddo
cmode='DG'
if(index(line,',CW,').gt.10) cmode='CW'
if(map65) then
do i=1,12
if(cmo(i).eq.line(6:8)) write(cdate(6:7),'(i2.2)') i
enddo
cdate(1:5)=line(1:5)
cdate(8:10)=line(9:11)
cutc=line(13:14)//line(16:17)
i0=index(line(19:),',')
callsign=line(19:17+i0)
cband='144 '
csent=dsent
crcvd=drcvd
else
cdate=line(1:10)
cutc=line(32:33)//line(35:36)
i0=index(line(41:),',')
callsign=line(41:39+i0)
read(line(icomma(6)+1:icomma(7)-1),*,err=10,end=10) freq
go to 20
10 print*,'***Error at line ',n
print*,trim(line)
20 if(freq.ge.50.0 .and. freq.le.54.0) cband='50 '
if(freq.ge.144.0 .and. freq.le.148.0) cband='144 '
if(freq.ge.28.0 .and. freq.le.29.0) cband='144 '
if(freq.ge.222.0 .and. freq.le.225.0) cband='222 '
if(freq.ge.420.0 .and. freq.le.450.0) cband='432 '
if(freq.ge.902.0 .and. freq.le.928.0) cband='902 '
if(freq.ge.1240.0 .and. freq.le.1300.0) cband='1.2G'
if(freq.ge.2300.0 .and. freq.le.2450.0) cband='2.3G'
if(freq.ge.3300.0 .and. freq.le.3500.0) cband='3.4G'
if(freq.ge.5650.0 .and. freq.le.5925.0) cband='5.7G'
if(freq.ge.10000.0 .and. freq.le.10500.0) cband='10G '
if(freq.ge.24000.0 .and. freq.le.24250.0) cband='24G '
if(icomma(8).eq.icomma(9)-1) then
csent=dsent
else
csent=line(icomma(8)+1:icomma(9)-1)
endif
if(icomma(9).eq.icomma(10)-1) then
crcvd=drcvd
else
crcvd=line(icomma(9)+1:icomma(10)-1)
endif
endif
if(gridx) then
csent=dsent
crcvd=line(icomma(5)+1:icomma(6)-1)
endif
write(12,1030) cband,cmode,cdate,cutc,mycall,csent,callsign,crcvd
1030 format('QSO: ',a4,1x,a2,1x,a10,1x,a4,1x,a6,1x,a4,4x,a10,1x,a4)
enddo
900 write(12,1900)
1900 format('END-OF-LOG:')
write(*,1910) n,trim(outfile)
1910 format('Processed',i5,' QSOs.'/'Output file: ',a)
999 end program cablog
!2023-10-28,00:17:00,2023-10-28,00:21:00,G7TZZ,IO92,1296.083100,Q65,-17,-17,,,,
!2023-Nov-30,20:31,W8WN,EM77,0,Q65A

57
lib/decode_msk144.f90 Normal file
View File

@ -0,0 +1,57 @@
subroutine decode_msk144(audio_samples, params, data_dir)
include 'jt9com.f90'
! constants
integer, parameter :: SAMPLING_RATE = 12000
integer, parameter :: BLOCK_SIZE = 7168
integer, parameter :: STEP_SIZE = BLOCK_SIZE / 2
integer, parameter :: CALL_LENGTH = 12
! aguments
integer*2 audio_samples(NMAX)
type(params_block) :: params
character(len = 500) :: data_dir
! parameters of mskrtd
integer*2 :: buffer(BLOCK_SIZE)
real :: tsec
logical :: bshmsg = .false. ! enables shorthand messages
logical :: btrain = .false. ! turns on training in MSK144 mode
real*8 :: pcoeffs(5) = (/ 0.0, 0.0, 0.0, 0.0, 0.0 /); ! phase equalization
logical :: bswl = .false.
character(len = 80) :: line
character(len = CALL_LENGTH) :: mycall
character(len = CALL_LENGTH) :: hiscall
! local variables
integer :: sample_count
integer :: position
integer :: message_count = 0
! decode in 0.3s blocks
sample_count = params%ntr * SAMPLING_RATE
mycall = transfer(params%mycall, mycall) ! string to char[]
hiscall = transfer(params%hiscall, hiscall)
do position = 1, sample_count - BLOCK_SIZE + 1, STEP_SIZE
buffer = audio_samples(position : position + BLOCK_SIZE - 1)
tsec = position / REAL(SAMPLING_RATE)
call mskrtd(buffer, params%nutc, tsec, params%ntol, params%nfqso, params%ndepth, &
mycall, hiscall, bshmsg, btrain, pcoeffs, bswl, data_dir, line)
if (line(1:1) .ne. char(0)) then
line = line(1:index(line, char(0))-1)
write(*, 1001) line
1001 format(a80)
message_count = message_count + 1;
end if
end do
if (.not. params%ndiskdat) then
write(*, 1002) 0, message_count, 0
1002 format('<DecodeFinished>', 2i4, i9)
end if
end subroutine decode_msk144

View File

@ -20,7 +20,7 @@ subroutine four2a(a,nfft,ndim,isign,iform)
! actual computations.
use fftw3
parameter (NPMAX=2100) !Max numberf of stored plans
parameter (NPMAX=2100) !Max number of stored plans
parameter (NSMALL=16385) !Max half complex size of "small" FFTs
complex a(nfft) !Array to be transformed
complex aa(NSMALL) !Local copy of "small" a()

View File

@ -171,15 +171,15 @@ subroutine fastosd240_74(llr,k,apmask,ndeep,message74,cw,nhardmin,dmin)
if( ndeep.eq. 1) then
nord=1
xlambda=0.0
nsyncmax=np
nsyndmax=np
elseif(ndeep.eq.2) then
nord=2
xlambda=0.0
nsyncmax=np
nsyndmax=np
elseif(ndeep.eq.3) then
nord=3
xlambda=4.0
nsyncmax=11
nsyndmax=11
elseif(ndeep.eq.4) then
nord=4
xlambda=3.4
@ -190,7 +190,6 @@ subroutine fastosd240_74(llr,k,apmask,ndeep,message74,cw,nhardmin,dmin)
s2=sum(absrx(k+1:N))
rho=s1/(s1+xlambda*s2)
rhodmin=rho*dmin
nerr64=-1
do iorder=1,nord
!beta=0.0
!if(iorder.ge.3) beta=0.4
@ -216,7 +215,6 @@ subroutine fastosd240_74(llr,k,apmask,ndeep,message74,cw,nhardmin,dmin)
cw=ce
nhardmin=sum(nxor)
nwhspmin=nwhsp
nerr64=sum(nxor(1:K))
endif
endif
! Get the next test error pattern, iflag will go negative
@ -224,7 +222,6 @@ subroutine fastosd240_74(llr,k,apmask,ndeep,message74,cw,nhardmin,dmin)
call nextpat74(mi,k,iorder,iflag)
enddo
enddo
998 continue
! Re-order the codeword to [message bits][parity bits] format.
cw(indices)=cw

View File

@ -4,33 +4,47 @@ program ldpcsim240_74
use packjt77
parameter(N=240, K=74, M=N-K)
parameter(N=240, NN=120)
character*8 arg
character*37 msg0
character*37 msg0,msgsent,msg
character*77 c77
character*24 c24
integer*1 msgbits(74)
integer*1 msgbits(101)
integer*1 apmask(240)
integer*1 cw(240)
integer*1 codeword(N),message74(74)
integer ncrc24
real rxdata(N),llr(N)
integer modtype, graymap(0:3)
integer*4 itone(120)
integer channeltype
integer lmax(1)
real rxdata(N)
real llr(240)
real bitmetrics(2*NN,4)
complex c1(4,8),c2(16,4),c4(256,2),cs(0:3,NN)
real s2(0:65535)
logical one(0:65535,0:15) ! 65536 8-symbol sequences, 16 bits
logical first
data first/.true./
data graymap/0,1,3,2/
nargs=iargc()
if(nargs.ne.5 .and. nargs.ne.6) then
print*,'Usage: ldpcsim niter ndeep #trials s K [msg]'
print*,'e.g. ldpcsim240_74 20 5 1000 0.85 64 "K9AN K1JT FN20"'
if(nargs.ne.7 .and. nargs.ne.8) then
print*,'Usage: ldpcsim maxosd norder #trials s Keff modtype channel '
print*,'e.g. ldpcsim240_74 2 4 1000 0.85 50 1 0'
print*,'s : if negative, then value is ignored and sigma is calculated from SNR.'
print*,'niter: is the number of BP iterations.'
print*,'ndeep: -1 is BP only, ndeep>=0 is OSD order'
print*,'K :is the number of message+CRC bits and must be in the range [50,74]'
print*,'maxosd<0: do bp only'
print*,'maxosd=0: do bp and then call osd once with channel llrs.'
print*,'maxosd>0: do bp and then call osc maxosd times with saved bp outputs.'
print*,'norder : osd decoding depth'
print*,'Keff : # of message bits, Keff must be in the range 50:74'
print*,'modtype : 0 coherent BPSK, 1 4FSK'
print*,'channel : 0 AWGN, 1 Rayleigh (4FSK only)'
print*,'WSPR-format message is optional'
return
endif
call getarg(1,arg)
read(arg,*) max_iterations
read(arg,*) maxosd
call getarg(2,arg)
read(arg,*) norder
call getarg(3,arg)
@ -39,17 +53,26 @@ program ldpcsim240_74
read(arg,*) s
call getarg(5,arg)
read(arg,*) Keff
msg0='K9AN K1JT FN20 '
if(nargs.eq.6) call getarg(6,msg0)
call getarg(6,arg)
read(arg,*) modtype
call getarg(7,arg)
read(arg,*) channeltype
call getarg(8,arg)
msg0='K9AN EN50 20 '
call pack77(msg0,i3,n3,c77)
rate=real(Keff)/real(N)
write(*,*) "code rate: ",rate
write(*,*) "niter : ",max_iterations
write(*,*) "maxosd : ",maxosd
write(*,*) "norder : ",norder
write(*,*) "s : ",s
write(*,*) "K : ",Keff
if(modtype.eq.0) write(*,*) "modtype : coherent BPSK"
if(modtype.eq.1) write(*,*) "modtype : noncoherent 4FSK"
if(channeltype.eq.0) write(*,*) "channel : AWGN"
if(channeltype.eq.1) write(*,*) "channel : Rayleigh"
msgbits=0
read(c77,'(50i1)') msgbits(1:50)
@ -59,49 +82,170 @@ program ldpcsim240_74
call get_crc24(msgbits,74,ncrc24)
write(c24,'(b24.24)') ncrc24
read(c24,'(24i1)') msgbits(51:74)
write(*,'(24i1)') msgbits(51:74)
write(*,'(24i1)') msgbits(51:74)
write(*,*) 'message with crc24'
write(*,'(74i1)') msgbits(1:74)
call encode240_74(msgbits,codeword)
call init_random_seed()
call sgran()
call encode240_74(msgbits(1:74),codeword)
do i=1,120
is=codeword(2*i)+2*codeword(2*i-1)
itone(i)=graymap(is)
enddo
write(*,*) 'codeword'
write(*,'(77i1,1x,24i1,1x,73i1)') codeword
write(*,*) "Eb/N0 Es/N0 ngood nundetected sigma symbol error rate"
do idb = 8,-3,-1
! call init_random_seed()
! call sgran()
one=.false.
do i=0,65535
do j=0,15
if(iand(i,2**j).ne.0) one(i,j)=.true.
enddo
enddo
write(*,*) "Eb/N0 Es/N0 ngood nundetected symbol error rate"
do idb = 24,-8,-1
db=idb/2.0-1.0
sigma=1/sqrt( 2*rate*(10**(db/10.0)) ) ! to make db represent Eb/No
sigma=1/sqrt( 2*rate*iq*(10**(db/10.0)) ) ! to make db represent Eb/No
! sigma=1/sqrt( 2*(10**(db/10.0)) ) ! db represents Es/No
ngood=0
nue=0
nberr=0
nsymerr=0
do itrial=1, ntrials
! Create a realization of a noisy received word
do i=1,N
rxdata(i) = 2.0*codeword(i)-1.0 + sigma*gran()
enddo
nerr=0
do i=1,N
if( rxdata(i)*(2*codeword(i)-1.0) .lt. 0 ) nerr=nerr+1
enddo
nberr=nberr+nerr
if(modtype.eq.0) then
iq = 1 ! bits per symbol
sigma=1/sqrt( 2*rate*iq*(10**(db/10.0)) ) ! to make db represent Eb/No
do i=1,N
rxdata(i) = 2.0*codeword(i)-1.0 + sigma*gran()
enddo
nerr=0
do i=1,N
if( rxdata(i)*(2*codeword(i)-1.0) .lt. 0 ) nerr=nerr+1
enddo
nberr=nberr+nerr
rxav=sum(rxdata)/N
rx2av=sum(rxdata*rxdata)/N
rxsig=sqrt(rx2av-rxav*rxav)
rxdata=rxdata/rxsig
if( s .lt. 0 ) then
ss=sigma
rxav=sum(rxdata)/N
rx2av=sum(rxdata*rxdata)/N
rxsig=sqrt(rx2av-rxav*rxav)
rxdata=rxdata/rxsig
if( s .lt. 0 ) then
ss=sigma
else
ss=s
endif
llr=2.0*rxdata/(ss*ss)
else
ss=s
! noncoherent MFSK
iq = 2 ! bits per symbol
sigma=1/sqrt( 2*rate*iq*(10**(db/10.0)) ) ! to make db represent Eb/No
A=1
do i=1,120
do j=0,3
if(j.eq.itone(i)) then
if(channeltype.eq.0) then
A=1.0
elseif(channeltype.eq.1) then
xI=gran()**2+gran()**2
A=sqrt(xI/2)
endif
cs(j,i)= A + sigma*gran() + cmplx(0,1)*sigma*gran()
elseif(j.ne.itone(i)) then
cs(j,i)= sigma*gran() + cmplx(0,1)*sigma*gran()
endif
enddo
lmax=maxloc(abs(cs(:,i)))
if(lmax(1)-1.ne.itone(i) ) nsymerr=nsymerr+1
enddo
do k=1,NN,8
do m=1,8 ! do 4 1-symbol correlations for each of 8 symbs
s2=0
do is=1,4
c1(is,m)=cs(graymap(is-1),k+m-1)
s2(is-1)=abs(c1(is,m))
enddo
ipt=(k-1)*2+2*(m-1)+1
do ib=0,1
bm=maxval(s2(0:3),one(0:3,1-ib)) - &
maxval(s2(0:3),.not.one(0:3,1-ib))
if(ipt+ib.gt.2*NN) cycle
bitmetrics(ipt+ib,1)=bm
enddo
enddo
do m=1,4 ! do 16 2-symbol correlations for each of 4 2-symbol groups
s2=0
do i=1,4
do j=1,4
is=(i-1)*4+j
c2(is,m)=c1(i,2*m-1)+c1(j,2*m)
s2(is-1)=abs(c2(is,m))**2
enddo
enddo
ipt=(k-1)*2+4*(m-1)+1
do ib=0,3
bm=maxval(s2(0:15),one(0:15,3-ib)) - &
maxval(s2(0:15),.not.one(0:15,3-ib))
if(ipt+ib.gt.2*NN) cycle
bitmetrics(ipt+ib,2)=bm
enddo
enddo
do m=1,2 ! do 256 4-symbol corrs for each of 2 4-symbol groups
s2=0
do i=1,16
do j=1,16
is=(i-1)*16+j
c4(is,m)=c2(i,2*m-1)+c2(j,2*m)
s2(is-1)=abs(c4(is,m))
enddo
enddo
ipt=(k-1)*2+8*(m-1)+1
do ib=0,7
bm=maxval(s2(0:255),one(0:255,7-ib)) - &
maxval(s2(0:255),.not.one(0:255,7-ib))
if(ipt+ib.gt.2*NN) cycle
bitmetrics(ipt+ib,3)=bm
enddo
enddo
s2=0 ! do 65536 8-symbol correlations for the entire group
do i=1,256
do j=1,256
is=(i-1)*256+j
s2(is-1)=abs(c4(i,1)+c4(j,2))
enddo
enddo
ipt=(k-1)*2+1
do ib=0,15
bm=maxval(s2(0:65535),one(0:65535,15-ib)) - &
maxval(s2(0:65535),.not.one(0:65535,15-ib))
if(ipt+ib.gt.2*NN) cycle
bitmetrics(ipt+ib,4)=bm
enddo
enddo
call normalizebmet(bitmetrics(:,1),2*NN)
call normalizebmet(bitmetrics(:,2),2*NN)
call normalizebmet(bitmetrics(:,3),2*NN)
call normalizebmet(bitmetrics(:,4),2*NN)
scalefac=2.83
bitmetrics=scalefac*bitmetrics
llr=bitmetrics(:,1)
endif
llr=2.0*rxdata/(ss*ss)
apmask=0
dmin=0.0
maxosd=2
call decode240_74(llr, Keff, maxosd, norder, apmask, message74, cw, ntype, nharderror, dmin)
if(nharderror.ge.0) then
n2err=0
@ -116,9 +260,10 @@ write(*,'(24i1)') msgbits(51:74)
endif
enddo
! snr2500=db+10*log10(200.0/116.0/2500.0)
esn0=db+10*log10(rate)
pberr=real(nberr)/(real(ntrials*N))
write(*,"(f4.1,4x,f5.1,1x,i8,1x,i8,8x,e10.3)") db,esn0,ngood,nue,pberr
esn0=db+10*log10(rate*iq)
pberr=real(nberr)/real(ntrials*N)
pserr=real(nsymerr)/real(ntrials*120)
write(*,"(f4.1,4x,f5.1,1x,i8,1x,i8,8x,e10.3)") db,esn0,ngood,nue,pserr
enddo

View File

@ -996,7 +996,7 @@ contains
do i=-ia,ia !Find freq range that has 50% of signal power
sum2=sum2 + ss(i)-avg
if(sum2.ge.0.25*sum1 .and. xi1.eq.-999.0) then
xi1=i - 1 + (sum2-0.25*sum1)/(sum2-sum2z)
xi1=i - 1 + (0.25*sum1-sum2)/(sum2-sum2z)
endif
if(sum2.ge.0.50*sum1 .and. xi2.eq.-999.0) then
xi2=i - 1 + (sum2-0.50*sum1)/(sum2-sum2z)

View File

@ -15,7 +15,7 @@ subroutine foxgen()
! common block.
parameter (NN=79,ND=58,NSPS=4*1920)
parameter (NWAVE=(160+2)*134400*4) !the biggest waveform we generate (FST4-1800 at 48kHz)
parameter (NWAVE=(160+2)*134400*4) ! the biggest waveform we generate (FST4-1800 at 48kHz)
parameter (NFFT=614400,NH=NFFT/2)
character*40 cmsg
character*37 msg,msgsent

View File

@ -2,38 +2,50 @@ program ldpcsim174_91
! End to end test of the (174,91)/crc14 encoder and decoder.
use packjt77
integer, parameter:: N=174, K=91, M=N-K
character*37 msg,msgsent,msgreceived
integer, parameter:: N=174, K=91, M=N-K, NN=58
character*37 msg,msgsent
character*77 c77
character*8 arg
character*6 grid
character*96 tmpchar
integer*1, allocatable :: codeword(:), decoded(:), message(:)
integer*1 msgbits(77)
integer*1 message77(77),message91(91)
integer*1 message91(91)
integer*1 apmask(N), cw(N)
integer lmax(1)
integer modtype, itone(79), itonecw(58), graymap(0:7)
integer nerrtot(0:N),nerrdec(0:N)
integer channeltype
logical unpk77_success
logical one(0:511,0:8)
real*8, allocatable :: rxdata(:)
real, allocatable :: llr(:)
real llr(174),llra(174),llrb(174),llrc(174),llrd(174)
real bmeta(174),bmetb(174),bmetc(174),bmetd(174)
complex cs(0:7,NN)
real s2(0:511)
data graymap/0,1,3,2,5,6,4,7/
nerrtot=0
nerrdec=0
!
nargs=iargc()
if(nargs.ne.6) then
print*,'Usage: ldpcsim niter ndepth #trials s Keff nbposd'
print*,'eg: ldpcsim 10 2 1000 0.84 91 1'
print*,'niter: max BP iterations'
print*,'ndepth: OSD order'
print*,'s: noise sigma; if negative value is ignored and sigma is calculated from SNR.'
print*,'nbposd=0, no coupling. nbposd>0, maxsuper=nbposd; nbposd<0, no OSD'
if(nargs.ne.7) then
print*,'Usage: ldpcsim maxosd norder #trials s Keff modtype channel'
print*,'eg: ldpcsim 10 2 1000 0.84 91 1 0'
print*,' maxosd<0: do bp only'
print*,' maxosd=0: do bp and then call osd once with channel llrs'
print*,' maxosd>1: do bp and then call osd maxosd times with saved bp outputs'
print*,' norder : osd decoding depth'
print*,' s : BPSK only, noise sigma, if s<0 value is ignored and sigma is calculated from SNR.'
print*,' Keff : Keff must be in the range [77,91]; Keff-77 is the # of bits to use as CRC.'
print*,' modtype : 0, coherent BPSK; 1 noncoherent 8FSK'
print*,' channel : 0, AWGN; 1, block Rayleigh (Rayleigh only works with 8FSK!)'
return
endif
call getarg(1,arg)
read(arg,*) max_iterations
read(arg,*) maxosd
call getarg(2,arg)
read(arg,*) ndepth
read(arg,*) norder
call getarg(3,arg)
read(arg,*) ntrials
call getarg(4,arg)
@ -41,16 +53,24 @@ program ldpcsim174_91
call getarg(5,arg)
read(arg,*) Keff
call getarg(6,arg)
read(arg,*) nbposd
read(arg,*) modtype
call getarg(7,arg)
read(arg,*) channeltype
! scale Eb/No for a (174,91) code
rate=real(K)/real(N)
write(*,*) "rate: ",rate
write(*,*) "niter= ",max_iterations," s= ",s
allocate ( codeword(N), decoded(K), message(K) )
allocate ( rxdata(N), llr(N) )
allocate ( rxdata(N) )
one=.false.
do i=0,511
do j=0,8
if(iand(i,2**j).ne.0) one(i,j)=.true.
enddo
enddo
msg="K9ABC K1ABC FN20"
i3=0
@ -65,47 +85,144 @@ program ldpcsim174_91
call init_random_seed()
iq=1
if(modtype.gt.0) then ! MFSK - get tones
i3=-1
n3=-1
call genft8(msg,i3,n3,msgsent,msgbits,itone)
write(*,*) 'message tones'
write(*,'(79(i1,1x))') itone
itonecw(1:29)=itone(8:36)
itonecw(30:58)=itone(44:72)
iq=3 ! bits per symbol
endif
call encode174_91(msgbits,codeword)
write(*,*) 'crc14'
write(*,'(14i1)') codeword(78:91)
write(*,*) 'codeword'
write(*,'(22(8i1,1x))') codeword
write(*,*) "Eb/N0 Es/N0 ngood nundetected sigma psymerr"
do idb = 10,-4,-1
write(*,*) 'Eb/N0 Es/N0 SNR2500 ngood nundetected sigma psymerr pbiterr'
do idb = 20,-4,-1
nsymerr=0
nbiterr=0
db=idb/2.0-1.0
sigma=1/sqrt( 2*rate*(10**(db/10.0)) )
sigma=1/sqrt( 2*rate*iq*(10**(db/10.0)) )
ngood=0
nue=0
nsumerr=0
do itrial=1, ntrials
! Create a realization of a noisy received word
do i=1,N
rxdata(i) = 2.0*codeword(i)-1.0 + sigma*gran()
enddo
nerr=0
do i=1,N
if( rxdata(i)*(2*codeword(i)-1.0) .lt. 0 ) nerr=nerr+1
enddo
if(nerr.ge.1) nerrtot(nerr)=nerrtot(nerr)+1
if(modtype.eq.0) then
do i=1,N
rxdata(i) = 2.0*codeword(i)-1.0 + sigma*gran()
enddo
nerr=0
do i=1,N
if( rxdata(i)*(2*codeword(i)-1.0) .lt. 0 ) nerr=nerr+1
enddo
if(nerr.ge.1) nerrtot(nerr)=nerrtot(nerr)+1
rxav=sum(rxdata)/N
rx2av=sum(rxdata*rxdata)/N
rxsig=sqrt(rx2av-rxav*rxav)
rxdata=rxdata/rxsig
if( s .lt. 0 ) then
ss=sigma
rxav=sum(rxdata)/N
rx2av=sum(rxdata*rxdata)/N
rxsig=sqrt(rx2av-rxav*rxav)
rxdata=rxdata/rxsig
if( s .lt. 0 ) then
ss=sigma
else
ss=s
endif
llr=2.0*rxdata/(ss*ss)
else
ss=s
! noncoherent MFSK
do i=1,58
do j=0,7
if(j.eq.itonecw(i)) then
if(channeltype.eq.0) then
A=1.0
elseif(channeltype.eq.1) then
xI=gran()**2 + gran()**2
A=sqrt(xI/2)
endif
cs(j,i)= A + sigma*gran() + cmplx(0,1)*sigma*gran()
elseif(j.ne.itonecw(i)) then
cs(j,i)= sigma*gran() + cmplx(0,1)*sigma*gran()
endif
enddo
lmax=maxloc(abs(cs(:,i)))
if(lmax(1)-1.ne.itonecw(i) ) nsymerr=nsymerr+1
enddo
do nsym=1,3
nt=2**(3*nsym)
do ks=1,58,nsym
amax=-1.0
do i=0,nt-1
i1=i/64
i2=iand(i,63)/8
i3=iand(i,7)
if(nsym.eq.1) then
s2(i)=abs(cs(graymap(i3),ks))
elseif(nsym.eq.2) then
s2(i)=abs(cs(graymap(i2),ks)+cs(graymap(i3),ks+1))
elseif(nsym.eq.3) then
if(ks.ne.58) then
s2(i)=abs(cs(graymap(i1),ks)+cs(graymap(i2),ks+1)+cs(graymap(i3),ks+2))
else
s2(i)=abs(cs(graymap(i1),ks))
endif
else
print*,"Error - nsym must be 1, 2, or 3."
endif
enddo
i32=1+(ks-1)*3
if(nsym.eq.1) ibmax=2
if(nsym.eq.2) ibmax=5
if(nsym.eq.3) ibmax=8
do ib=0,ibmax
bm=maxval(s2(0:nt-1),one(0:nt-1,ibmax-ib)) - &
maxval(s2(0:nt-1),.not.one(0:nt-1,ibmax-ib))
if(i32+ib .gt.174) cycle
if(nsym.eq.1) then
bmeta(i32+ib)=bm
den=max(maxval(s2(0:nt-1),one(0:nt-1,ibmax-ib)), &
maxval(s2(0:nt-1),.not.one(0:nt-1,ibmax-ib)))
if(den.gt.0.0) then
cm=bm/den
else ! erase it
cm=0.0
endif
bmetd(i32+ib)=cm
elseif(nsym.eq.2) then
bmetb(i32+ib)=bm
elseif(nsym.eq.3) then
bmetc(i32+ib)=bm
endif
enddo
enddo
enddo
call normalizebmet(bmeta,174)
call normalizebmet(bmetb,174)
call normalizebmet(bmetc,174)
call normalizebmet(bmetd,174)
scalefac=2.83
llra=scalefac*bmeta
llrb=scalefac*bmetb
llrc=scalefac*bmetc
llrd=scalefac*bmetd
llr=llrc
endif
llr=2.0*rxdata/(ss*ss)
do i=1, 174
if(llr(i)*(codeword(i)-0.5).lt.0) nbiterr=nbiterr+1
enddo
nap=0 ! number of AP bits
llr(1:nap)=5*(2.0*msgbits(1:nap)-1.0)
apmask=0
apmask(1:nap)=1
call decode174_91(llr,Keff,nbposd,ndepth,apmask,message91,cw,ntype,nharderrors,dmin)
call decode174_91(llr,Keff,maxosd,norder,apmask,message91,cw,ntype,nharderrors,dmin)
! If the decoder finds a valid codeword, nharderrors will be .ge. 0.
if( nharderrors.ge.0 ) then
nhw=count(cw.ne.codeword)
@ -119,9 +236,12 @@ program ldpcsim174_91
nsumerr=nsumerr+nerr
enddo
esn0=db+10.0*log10(rate)
pberr=real(nsumerr)/(real(ntrials*N))
write(*,"(f4.1,4x,f5.1,1x,i8,1x,i8,8x,f5.2,8x,e10.3)") db,esn0,ngood,nue,ss,pberr
esn0=db+10.0*log10(iq*rate) ! iq=3 bits per symbol for 8FSK
snr2500=esn0-10.0*log10(2500/6.25)
! pberr=real(nsumerr)/(real(ntrials*N))
psymerr=real(nsymerr)/(ntrials*174.0/iq)
pbiterr=real(nbiterr)/(ntrials*174.0)
write(*,"(f4.1,4x,f5.1,4x,f5.1,1x,i8,1x,i8,8x,f5.2,8x,e10.3,8x,e10.3)") db,esn0,snr2500,ngood,nue,ss,psymerr,pbiterr
enddo
@ -132,3 +252,18 @@ program ldpcsim174_91
close(23)
end program ldpcsim174_91
subroutine normalizebmet(bmet,n)
real bmet(n)
bmetav=sum(bmet)/real(n)
bmet2av=sum(bmet*bmet)/real(n)
var=bmet2av-bmetav*bmetav
if( var .gt. 0.0 ) then
bmetsig=sqrt(var)
else
bmetsig=sqrt(bmet2av)
endif
bmet=bmet/bmetsig
return
end subroutine normalizebmet

View File

@ -27,7 +27,7 @@ program jt9
logical :: read_files = .true., tx9 = .false., display_help = .false., &
bLowSidelobes = .false., nexp_decode_set = .false., &
have_ntol = .false.
type (option) :: long_options(32) = [ &
type (option) :: long_options(33) = [ &
option ('help', .false., 'h', 'Display this help message', ''), &
option ('shmem',.true.,'s','Use shared memory for sample data','KEY'), &
option ('tr-period', .true., 'p', 'Tx/Rx period, default SECONDS=60', &
@ -64,6 +64,7 @@ program jt9
option ('ft8', .false., '8', 'FT8 mode', ''), &
option ('jt9', .false., '9', 'JT9 mode', ''), &
option ('qra64', .false., 'q', 'QRA64 mode', ''), &
option ('msk144', .false., 'k', 'MSK144 mode', ''), &
option ('QSOprog', .true., 'Q', 'QSO progress (0-5), default PROGRESS=1',&
'QSOprogress'), &
option ('sub-mode', .true., 'b', 'Sub mode, default SUBMODE=A', 'A'), &
@ -91,7 +92,7 @@ program jt9
TRperiod=60.d0
do
call getopt('hs:e:a:b:r:m:p:d:f:F:w:t:9876543WYqTL:S:H:c:G:x:g:X:Q:', &
call getopt('hs:e:a:b:r:m:p:d:f:F:w:t:9876543WYqkTL:S:H:c:G:x:g:X:Q:', &
long_options,c,optarg,arglen,stat,offset,remain,.true.)
if (stat .ne. 0) then
exit
@ -129,7 +130,9 @@ program jt9
read (optarg(:arglen), *) fhigh
case ('q')
mode = 164
case ('Q')
case ('k')
mode = 144
case ('Q')
read (optarg(:arglen), *) nQSOProg
case ('3')
mode = 66
@ -352,7 +355,12 @@ program jt9
call multimode_decoder(shared_data%ss,id2a, &
shared_data%params,nfsample)
cycle
! MSK144
else if (mode .eq. 144) then
call decode_msk144(shared_data%id2, shared_data%params, data_dir)
endif
! Normal decoding pass
call multimode_decoder(shared_data%ss,shared_data%id2, &
shared_data%params,nfsample)

View File

@ -70,8 +70,15 @@ subroutine jt9a()
call multimode_decoder(shared_data%ss,id2a,local_params,12000)
local_params%nzhsym=50
endif
! Normal decoding pass
call multimode_decoder(shared_data%ss,shared_data%id2,local_params,12000)
if(local_params%nmode .eq. 144) then
! MSK144
call decode_msk144(shared_data%id2, shared_data%params, data_dir)
else
! Normal decoding pass
call multimode_decoder(shared_data%ss,shared_data%id2,local_params,12000)
endif
call timer('decoder ',1)

View File

@ -1,5 +1,5 @@
subroutine map65_mmdec(nutc,id2,nqd,nsubmode,nfa,nfb,nfqso,ntol,newdat, &
nagain,max_drift,ndepth,mycall,hiscall,hisgrid)
subroutine map65_mmdec(nutc,id2,nqd,ntrperiod, nsubmode,nfa,nfb,nfqso, &
ntol,newdat,nagain,max_drift,ndepth,mycall,hiscall,hisgrid)
use prog_args
use timer_module, only: timer
@ -39,7 +39,7 @@ subroutine map65_mmdec(nutc,id2,nqd,nsubmode,nfa,nfb,nfqso,ntol,newdat, &
lagain=(nagain.ne.0)
bVHF=.true.
emedelay=2.5
ntrperiod=60
! ntrperiod=60
call timer('dec_q65 ',0)
call my_q65%decode(q65_decoded,id2,nqd,nutc,ntrperiod,nsubmode,nfqso, &

View File

@ -3,6 +3,10 @@ subroutine pctile(x,npts,npct,xpct)
real x(npts)
real,allocatable :: tmp(:)
if(npts.lt.0 .or. npct.lt.0 .or. npct.gt.100) then
xpct=1.0
go to 900
endif
allocate(tmp(npts))
tmp=x
@ -11,6 +15,7 @@ subroutine pctile(x,npts,npct,xpct)
if(j.lt.1) j=1
if(j.gt.npts) j=npts
xpct=tmp(j)
deallocate(tmp)
return
900 return
end subroutine pctile

View File

@ -17,7 +17,6 @@ module q65
integer navg(0:1)
logical lnewdat
real candidates(20,3) !snr, xdt, and f0 of top candidates
real, allocatable :: s1raw(:,:) !Symbol spectra, 1/8-symbol steps
real, allocatable :: s1(:,:) !Symbol spectra w/suppressed peaks
real, allocatable :: s1w(:,:) !Symbol spectra w/suppressed peaks (W3SZ)
real, allocatable,save :: s1a(:,:,:) !Cumulative symbol spectra
@ -106,8 +105,6 @@ subroutine q65_dec0(iavg,iwave,ntrperiod,nfqso,ntol,lclearave, &
allocate(s3(-64:LL-65,63))
allocate(ccf1(-ia2:ia2))
if(LL.ne.LL0 .or. iz.ne.iz0 .or. jz.ne.jz0 .or. lclearave) then
if(allocated(s1raw)) deallocate(s1raw)
allocate(s1raw(iz,jz))
if(allocated(s1)) deallocate(s1)
allocate(s1(iz,jz))
if(allocated(s1a)) deallocate(s1a)
@ -146,19 +143,6 @@ subroutine q65_dec0(iavg,iwave,ntrperiod,nfqso,ntol,lclearave, &
endif
i0=nint(nfqso/df) !Target QSO frequency
ii1=max(1,i0-64)
ii2=i0-65+LL
call pctile(s1(ii1:ii2,1:jz),ii2-ii1+1*jz,45,base)
! s1=s1/base
s1raw=s1
! Apply fast AGC to the symbol spectra
! s1max=20.0 !Empirical choice
! do j=1,jz !### Maybe wrong way? ###
! smax=maxval(s1(ii1:ii2,j))
! if(smax.gt.s1max) s1(ii1:ii2,j)=s1(ii1:ii2,j)*s1max/smax
! enddo
dat4=0
if(ncw.gt.0 .and. iavg.le.1) then
! Try list decoding via "Deep Likelihood".
@ -506,12 +490,12 @@ subroutine q65_ccf_22(s1,iz,jz,nfqso,ntol,iavg,ipk,jpk, &
ia=max(nint(100/df),nint((nfqso-ntol)/df))
ib=min(nint(4900/df),nint((nfqso+ntol)/df))
endif
if(ia.ge.ib) ia=ib-ntol/df !Protect against wacky settings
do i=ia,ib
s1avg(i)=sum(s1(i,1:jz))
enddo
call pctile(s1avg(ia:ib),ib-ia+1,40,base0)
ccfbest=0.
ibest=0
lagpk=0
@ -788,7 +772,7 @@ subroutine q65_snr(dat4,dtdec,f0dec,mode_q65,snr2)
if(j.ge.1 .and. j.le.jz0) then
do i=1,iz0
ii=i+mode_q65*itone(k)
if(ii.ge.1 .and. ii.le.iz0) spec(i)=spec(i) + s1raw(ii,j)
if(ii.ge.1 .and. ii.le.iz0) spec(i)=spec(i) + s1(ii,j)
enddo
endif
enddo

View File

@ -50,7 +50,7 @@ subroutine sun(y,m,DD,UT,lon,lat,RA,Dec,LST,Az,El,mjd,day)
MM = mod(356.0470d0 + 0.9856002585d0 * d + 360000.d0,360.d0)
Ls = mod(w+MM+720.0,360.0)
EE = MM + e*rad*sin(MM/rad) * (1.0 + e*cos(M/rad))
EE = MM + e*rad*sin(MM/rad) * (1.0 + e*cos(MM/rad))
EE = EE - (EE - e*rad*sin(EE/rad)-MM) / (1.0 - e*cos(EE/rad))
xv = cos(EE/rad) - e

View File

@ -146,6 +146,7 @@ unsigned long readwavfile(char *ptr_to_infile, int ntrmin, float *idat, float *q
nr=fread(buf2,2,npoints,fp); //Read raw data
fclose(fp);
if( nr == 0 ) {
free(buf2);
fprintf(stderr, "No data in file '%s'\n", ptr_to_infile);
return 1;
}

View File

@ -446,8 +446,8 @@ auto AD1CCty::lookup (QString const& call) const -> Record
if (p != m_->prefixes_.end ())
{
impl::entity_by_id::iterator e = m_->lookup_entity (call, *p);
if ((m_->configuration_->include_WAE_entities () || !e->WAE_only_)
&& (!p->exact_ || call.size () == search_prefix.size ()))
// always lookup WAE entities, we substitute them later in displaytext.cpp if "Include extra WAE entites" is not selected
if (!p->exact_ || call.size () == search_prefix.size ())
{
return m_->fixup (*p, *e);
}

View File

@ -101,7 +101,7 @@ QByteArray LogBook::QSOToADIF (QString const& hisCall, QString const& hisGrid, Q
t += " <band:" + QString::number(band.size()) + ">" + band;
t += " <freq:" + QString::number(strDialFreq.size()) + ">" + strDialFreq;
t += " <station_callsign:" + QString::number(myCall.size()) + ">" + myCall;
t += " <my_gridsquare:" + QString::number(myGrid.size()) + ">" + myGrid;
if(myGrid!="") t += " <my_gridsquare:" + QString::number(myGrid.size()) + ">" + myGrid;
if(txPower!="") t += " <tx_pwr:" + QString::number(txPower.size()) + ">" + txPower;
if(comments!="") t += " <comment:" + QString::number(comments.size()) + ">" + comments;
if(name!="") t += " <name:" + QString::number(name.size()) + ">" + name;

View File

@ -140,7 +140,7 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
ndpth=3
! NB: Frequency of ipk is now shifted to 1000 Hz.
call map65_mmdec(nutc,iwave,nqd,nsubmode,nfa,nfb,1000,ntol, &
call map65_mmdec(nutc,iwave,nqd,60,nsubmode,nfa,nfb,1000,ntol, &
newdat,nagain,max_drift,ndepth,mycall,hiscall0,hisgrid)
MHz=fcenter

View File

@ -659,7 +659,7 @@ QModelIndex FrequencyList_v2_101::impl::add (Item f)
endInsertRows ();
// if we added one that had a preferred frequency, unprefer everything else
unprefer_all_but(f, row, {Qt::DisplayRole, Qt::CheckStateRole});
if (f.preferred_) unprefer_all_but(f, row, {Qt::DisplayRole, Qt::CheckStateRole});
return index (row, 0);
}
@ -1335,8 +1335,10 @@ FrequencyList_v2_101::FrequencyItems FrequencyList_v2_101::from_json_file(QFile
{
throw ReadFileException{tr ("No Frequencies were found")};
}
int valid_entry_count [[maybe_unused]] = 0;
int skipped_entry_count [[maybe_unused]] = 0;
#ifdef DUMP_ENTRY_COUNTS
int valid_entry_count = 0;
int skipped_entry_count = 0;
#endif
for (auto const &item: arr)
{
QString mode_s, region_s;
@ -1359,13 +1361,21 @@ FrequencyList_v2_101::FrequencyItems FrequencyList_v2_101::from_json_file(QFile
freq.isSane())
{
list.push_back(freq);
#ifdef DUMP_ENTRY_COUNTS
valid_entry_count++;
} else
#endif
} else {
#ifdef DUMP_ENTRY_COUNTS
skipped_entry_count++;
#endif
}
}
//MessageBox::information_message(this, tr("Loaded Frequencies from %1").arg(file_name),
// tr("Entries Valid/Skipped %1").arg(QString::number(valid_entry_count) + "/" +
// QString::number(skipped_entry_count)));
#ifdef DUMP_ENTRY_COUNTS
MessageBox::information_message(this, tr("Loaded Frequencies from %1").arg(file_name),
tr("Entries Valid/Skipped %1").arg(QString::number(valid_entry_count) + "/" +
QString::number(skipped_entry_count)));
#endif
return list;
}
// write JSON format to a file

View File

@ -13,7 +13,7 @@ CAboutDlg::CAboutDlg(QWidget *parent) :
"QMAP is a wideband receiver for the Q65 protocol, intnded<br />"
"primarily for amateur radio EME communication. It works <br />"
"in close cooperation with WSJT-X, versions 2.7 and later. <br /><br />"
"Copyright 2001-2023 by Joe Taylor, K1JT. Additional <br />"
"Copyright 2001-2024 by Joe Taylor, K1JT. Additional <br />"
"acknowledgments are contained in the source code.");
}

View File

@ -20,7 +20,7 @@
</sizepolicy>
</property>
<property name="windowTitle">
<string>About MAP65</string>
<string>About QMAP</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>

View File

@ -44,10 +44,8 @@ Astro::~Astro()
delete ui;
}
void Astro::astroUpdate(QDateTime t, QString mygrid, QString hisgrid,
int fQSO, int nsetftx, int ntxFreq, QString azelDir, double xavg)
void Astro::astroUpdate(QDateTime t, QString mygrid, QString azelDir, double xavg)
{
static int ntxFreq0=-99;
char cc[300];
double azsun,elsun,azmoon,elmoon,azmoondx,elmoondx;
double ramoon,decmoon,dgrd,poloffset,xnr;
@ -63,32 +61,29 @@ void Astro::astroUpdate(QDateTime t, QString mygrid, QString hisgrid,
int isec=sec;
double uth=nhr + nmin/60.0 + sec/3600.0;
int nfreq=(int)datcom_.fcenter;
// if(nfreq<10 or nfreq > 50000) nfreq=144;
astrosub_(&nyear, &month, &nday, &uth, &nfreq, mygrid.toLatin1(),
hisgrid.toLatin1(), &azsun, &elsun, &azmoon, &elmoon,
mygrid.toLatin1(), &azsun, &elsun, &azmoon, &elmoon,
&azmoondx, &elmoondx, &ntsky, &ndop, &ndop00,&ramoon, &decmoon,
&dgrd, &poloffset, &xnr, 6, 6);
datcom_.ndop00=ndop00; //Send self Doppler to decoder, via datcom
// qDebug() << "aa" << isec << datcom_.fcenter << nfreq << ndop00;
m_ndop00=ndop00;
snprintf(cc, sizeof(cc),
"Az: %6.1f\n"
"El: %6.1f\n"
"MyDop: %6d\n"
"DxAz: %6.1f\n"
"DxEl: %6.1f\n"
"DxDop: %6d\n"
"Dec: %6.1f\n"
"SunAz: %6.1f\n"
"SunEl: %6.1f\n"
"Freq: %6d\n"
"Tsky: %6d\n"
"MNR: %6.1f\n"
"Dgrd: %6.1f",
azmoon,elmoon,ndop00,azmoondx,elmoondx,ndop,decmoon,azsun,elsun,
"Az: %6.1f\n"
"El: %6.1f\n"
"SelfDop:%6d\n"
"MoonDec:%6.1f\n"
"SunAz: %6.1f\n"
"SunEl: %6.1f\n"
"Freq: %6d\n"
"Tsky: %6d\n"
"MNR: %6.1f\n"
"Dgrd: %6.1f",
azmoon,elmoon,ndop00,decmoon,azsun,elsun,
nfreq,ntsky,xnr,dgrd);
ui->astroTextBrowser->setText(" "+ date + "\nUTC: " + utc + "\n" + cc);
ui->astroTextBrowser->setText(" "+ date + "\nUTC: " + utc + "\n" + cc);
double azOffset=0.0;
double elOffset=0.0;
@ -154,7 +149,6 @@ void Astro::astroUpdate(QDateTime t, QString mygrid, QString hisgrid,
// Write pointing data to azel.dat
QString fname=azelDir+"/azel.dat";
// qDebug() << "aa" << fname << isec << bPointing << azOffset << elOffset;
QFile f(fname);
if(!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
if(azelDir==m_AzElDir0) return;
@ -164,22 +158,18 @@ void Astro::astroUpdate(QDateTime t, QString mygrid, QString hisgrid,
mb.exec();
return;
}
int ndiff=0;
if(ntxFreq != ntxFreq0) ndiff=1;
ntxFreq0=ntxFreq;
QTextStream out(&f);
snprintf(cc,sizeof(cc),"%2.2d:%2.2d:%2.2d,%5.1f,%5.1f,Moon\n"
"%2.2d:%2.2d:%2.2d,%5.1f,%5.1f,Sun\n"
"%2.2d:%2.2d:%2.2d,%5.1f,%5.1f,Source\n"
"%4d,%6d,%6d,Doppler\n"
"%3d,%1d,fQSO\n"
"%3d,%1d,fQSO2\n",
"%3d,%1d,fQSO\n",
nhr,nmin,isec,azmoon,elmoon,
nhr,nmin,isec,azsun+azOffset,elsun+elOffset,
nhr,nmin,isec,0.0,0.0,
nfreq,ndop,ndop00,
fQSO,nsetftx,
ntxFreq,ndiff);
datcom_.mousefqso,0);
out << cc;
f.close();
}
@ -199,3 +189,7 @@ void Astro::on_cbOnOff_clicked(bool checked)
if(checked) ui->cbAutoCycle->setChecked(false);
}
int Astro::getSelfDop()
{
return m_ndop00;
}

View File

@ -14,9 +14,10 @@ class Astro : public QWidget
public:
explicit Astro (QString const& settings_filename, QWidget *parent = 0);
void astroUpdate(QDateTime t, QString mygrid, QString hisgrid,
int fQSO, int nsetftx, int ntxFreq, QString azelDir, double xavg);
void astroUpdate(QDateTime t, QString mygrid, QString azelDir, double xavg);
void setFontSize(int n);
int getSelfDop();
~Astro ();
private slots:
@ -27,6 +28,8 @@ private:
Ui::Astro *ui;
QString m_settings_filename;
QString m_AzElDir0;
qint32 m_ndop00=0;
};
#endif

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>441</width>
<height>483</height>
<width>431</width>
<height>393</height>
</rect>
</property>
<property name="windowTitle">
@ -19,7 +19,7 @@
<x>269</x>
<y>19</y>
<width>151</width>
<height>431</height>
<height>361</height>
</rect>
</property>
<property name="title">
@ -29,7 +29,7 @@
<property name="geometry">
<rect>
<x>10</x>
<y>100</y>
<y>70</y>
<width>30</width>
<height>17</height>
</rect>
@ -42,7 +42,7 @@
<property name="geometry">
<rect>
<x>60</x>
<y>100</y>
<y>70</y>
<width>40</width>
<height>17</height>
</rect>
@ -58,7 +58,7 @@
<property name="geometry">
<rect>
<x>110</x>
<y>100</y>
<y>70</y>
<width>30</width>
<height>17</height>
</rect>
@ -71,7 +71,7 @@
<property name="geometry">
<rect>
<x>60</x>
<y>150</y>
<y>120</y>
<width>30</width>
<height>17</height>
</rect>
@ -84,7 +84,7 @@
<property name="geometry">
<rect>
<x>60</x>
<y>50</y>
<y>20</y>
<width>30</width>
<height>17</height>
</rect>
@ -97,7 +97,7 @@
<property name="geometry">
<rect>
<x>10</x>
<y>230</y>
<y>180</y>
<width>130</width>
<height>22</height>
</rect>
@ -131,7 +131,7 @@
<property name="geometry">
<rect>
<x>30</x>
<y>330</y>
<y>260</y>
<width>91</width>
<height>17</height>
</rect>
@ -144,7 +144,7 @@
<property name="geometry">
<rect>
<x>30</x>
<y>380</y>
<y>300</y>
<width>70</width>
<height>17</height>
</rect>
@ -157,7 +157,7 @@
<property name="geometry">
<rect>
<x>10</x>
<y>280</y>
<y>220</y>
<width>130</width>
<height>22</height>
</rect>
@ -172,28 +172,46 @@
<string>Dwell </string>
</property>
<property name="minimum">
<number>10</number>
<number>15</number>
</property>
<property name="maximum">
<number>300</number>
</property>
<property name="singleStep">
<number>10</number>
<number>5</number>
</property>
</widget>
</widget>
<widget class="QWidget" name="">
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>10</y>
<width>258</width>
<height>471</height>
<height>371</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextBrowser" name="astroTextBrowser">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>325</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<family>Courier New</family>
@ -207,7 +225,7 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer_2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@ -227,7 +245,7 @@
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@ -241,6 +259,22 @@
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>

View File

@ -7,7 +7,7 @@ extern "C" {
extern struct { //This is "common/datcom/..." in Fortran
float d4[2*5760000]; //Raw I/Q data from Linrad
float ss[322*NFFT]; //Half-symbol spectra at 0,45,90,135 deg pol
float ss[400*NFFT]; //Half-symbol spectra at 0,45,90,135 deg pol
float savg[NFFT]; //Avg spectra at 0,45,90,135 deg pol
double fcenter; //Center freq from Linrad (MHz)
int nutc; //UTC as integer, HHMM
@ -17,23 +17,24 @@ extern struct { //This is "common/datcom/..." in Fortran
int nagain; //1 ==> decode only at fQSO +/- Tol
int ndepth; //How much hinted decoding to do?
int ndiskdat; //1 ==> data read from *.iq file
int neme; //Hinted decoding tries only for EME calls
int ntx60; //Number of seconds transmitted in Q65-60x
int newdat; //1 ==> new data, must do long FFT
int nfa; //Low decode limit (kHz)
int nfb; //High decode limit (kHz)
int nfcal; //Frequency correction, for calibration (Hz)
int nfshift; //Shift of displayed center freq (kHz)
int mcall3; //1 ==> CALL3.TXT has been modified
int ntimeout; //Max for timeouts in Messages and BandMap
int ntx30a; //Number of seconds transmitted in first half minute , Q65-30x
int ntx30b; //Number of seconds transmitted in second half minute, Q65-30x
int ntol; //+/- decoding range around fQSO (Hz)
int nxant; //1 ==> add 45 deg to measured pol angle
int junk_1;
int n60; //nsecs%60
int junk4; //
int nfsample; //Input sample rate
int nxpol; //1 if using xpol antennas, 0 otherwise
int nmode; //nmode = 10*m_modeQ65 + m_modeJT65
int ndop00; //EME Self Doppler
int nsave; //Number of s3(64,63) spectra saved
int ndop58; //EME Self Doppler at t=58
int nBaseSubmode; //Base submode for Q65-60x (aka m_modeQ65)
int ndop00; //EME Self Doppler at t=0
int nsave; //0=None, 1=SaveDecoded, 2=SaveAll
int max_drift; //Maximum Q65 drift: units symbol_rate/TxT
int offset; //Offset in Hz
int nhsym; //Number of available JT65 half-symbols
char mycall[12];
char mygrid[6];
@ -42,11 +43,12 @@ extern struct { //This is "common/datcom/..." in Fortran
char datetime[20];
int junk1; //Used to test extent of copy to shared memory
int junk2;
bool bAlso30; //Process for 30-second submode as well as 60-second
} datcom_;
extern struct { //This is "common/datcom/..." in Fortran
float d4[2*5760000]; //Raw I/Q data from Linrad
float ss[322*NFFT]; //Half-symbol spectra at 0,45,90,135 deg pol
float ss[400*NFFT]; //Half-symbol spectra at 0,45,90,135 deg pol
float savg[NFFT]; //Avg spectra at 0,45,90,135 deg pol
double fcenter; //Center freq from Linrad (MHz)
int nutc; //UTC as integer, HHMM
@ -56,23 +58,24 @@ extern struct { //This is "common/datcom/..." in Fortran
int nagain; //1 ==> decode only at fQSO +/- Tol
int ndepth; //How much hinted decoding to do?
int ndiskdat; //1 ==> data read from *.iq file
int neme; //Hinted decoding tries only for EME calls
int ntx60; //Number of seconds transmitted in Q65-60x
int newdat; //1 ==> new data, must do long FFT
int nfa; //Low decode limit (kHz)
int nfb; //High decode limit (kHz)
int nfcal; //Frequency correction, for calibration (Hz)
int nfshift; //Shift of displayed center freq (kHz)
int mcall3; //1 ==> CALL3.TXT has been modified
int ntimeout; //Max for timeouts in Messages and BandMap
int ntx30a; //Number of seconds transmitted in first half minute , Q65-30x
int ntx30b; //Number of seconds transmitted in second half minute, Q65-30x
int ntol; //+/- decoding range around fQSO (Hz)
int nxant; //1 ==> add 45 deg to measured pol angle
int junk_1;
int n60; //nsecs%60
int junk4; //
int nfsample; //Input sample rate
int nxpol; //1 if using xpol antennas, 0 otherwise
int nmode; //nmode = 10*m_modeQ65 + m_modeJT65
int ndop00; //EME Self Doppler
int nsave; //Number of s3(64,63) spectra saved
int ndop58; //EME Self Doppler at t=58
int nBaseSubmode; //Base submode for Q65-60x (aka m_modeQ65)
int ndop00; //EME Self Doppler at t=0
int nsave; //0=None, 1=SaveDecoded, 2=SaveAll
int max_drift; //Maximum Q65 drift: units symbol_rate/TxT
int offset; //Offset in Hz
int nhsym; //Number of available JT65 half-symbols
char mycall[12];
char mygrid[6];
@ -81,6 +84,7 @@ extern struct { //This is "common/datcom/..." in Fortran
char datetime[20];
int junk1; //Used to test extent of copy to shared memory
int junk2;
bool bAlso30; //Process for 30-second submode as well as 60-second
} datcom2_;
extern struct {
@ -88,10 +92,16 @@ extern struct {
int ncand; //between QMAP and WSJT-X
int nQDecoderDone; //1 for real-time decodes, 2 for data from disk
int nWDecoderBusy; //Set to 1 when WSJT-X decoder is busy
int nWTransmitting; //Set to 1 when WSJT-X is transmitting
char result[50][60]; //Staging area for QMAP decodes
int nWTransmitting; //Set to TRperiod when WSJT-X is transmitting
int kHzRequested; //Integer kHz dial frequency request to WSJT-X
char result[50][64]; //Staging area for QMAP decodes
} decodes_;
extern struct {
char revision[22];
char saveFileName[120];
} savecom_;
}
#endif // COMMONS_H

View File

@ -20,6 +20,8 @@ void DevSetup::initDlg()
ui.myCallEntry->setText(m_myCall);
ui.myGridEntry->setText(m_myGrid);
ui.astroFont->setValue(m_astroFont);
ui.myCallColor->addItems({"","red","green","cyan"});
ui.myCallColor->setCurrentIndex(m_myCallColor);
ui.saveDirEntry->setText(m_saveDir);
ui.azelDirEntry->setText(m_azelDir);
ui.fCalSpinBox->setValue(m_fCal);
@ -38,6 +40,7 @@ void DevSetup::accept()
m_myCall=ui.myCallEntry->text();
m_myGrid=ui.myGridEntry->text();
m_astroFont=ui.astroFont->value();
m_myCallColor=ui.myCallColor->currentIndex();
m_saveDir=ui.saveDirEntry->text();
m_azelDir=ui.azelDirEntry->text();
m_fCal=ui.fCalSpinBox->value();

View File

@ -12,10 +12,6 @@ public:
~DevSetup();
void initDlg();
qint32 m_idInt;
qint32 m_pttPort;
qint32 m_timeout;
qint32 m_dPhi;
qint32 m_fCal;
qint32 m_udpPort;
qint32 m_astroFont;
@ -25,14 +21,14 @@ public:
double m_TxOffset;
bool m_network;
bool m_fs96000;
bool m_restartSoundIn;
int m_myCallColor;
QString m_myCall;
QString m_myGrid;
QString m_saveDir;
QString m_azelDir;
QString m_editorCommand;
public slots:
void accept();

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>400</width>
<height>250</height>
<height>268</height>
</rect>
</property>
<property name="windowTitle">
@ -63,6 +63,13 @@
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Highlight My Call:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
@ -106,6 +113,9 @@
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="myCallColor"/>
</item>
</layout>
</item>
<item>
@ -175,10 +185,10 @@
<item>
<widget class="QSpinBox" name="fCalSpinBox">
<property name="minimum">
<number>-20000</number>
<number>-50000</number>
</property>
<property name="maximum">
<number>20000</number>
<number>50000</number>
</property>
</widget>
</item>
@ -287,7 +297,7 @@
</sizepolicy>
</property>
<property name="title">
<string>Input from Linrad</string>
<string>Input from Linrad or SDR Console</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
@ -312,7 +322,7 @@
<number>-50</number>
</property>
<property name="maximum">
<number>10</number>
<number>50</number>
</property>
<property name="singleStep">
<number>1</number>

View File

@ -6,10 +6,10 @@
extern qint16 id[2*60*96000];
void getfile(QString fname, bool xpol, int dbDgrd)
void getfile(QString fname, int dbDgrd)
{
int npts=2*56*96000;
if(xpol) npts=2*npts;
// int npts=2*56*96000;
int npts=2*60*96000;
// Degrade S/N by dbDgrd dB -- for tests only!!
float dgrd=0.0;
@ -23,31 +23,32 @@ void getfile(QString fname, bool xpol, int dbDgrd)
if(fp != NULL) {
auto n = fread(&datcom_.fcenter,sizeof(datcom_.fcenter),1,fp);
// qDebug() << "aa0" << sizeof(datcom_.fcenter) << n << datcom_.fcenter;
n = fread(id,2,npts,fp);
Q_UNUSED (n);
n=fread(id,2,npts,fp);
n=fread(&datcom_.ntx30a,4,1,fp);
n=fread(&datcom_.ntx30b,4,1,fp);
if(n==0) {
datcom_.ntx30a=0;
datcom_.ntx30b=0;
}
int j=0;
if(dbDgrd<0) {
for(int i=0; i<npts; i+=2) {
datcom_.d4[j++]=fac*((float)id[i] + dgrd*gran());
datcom_.d4[j++]=fac*((float)id[i+1] + dgrd*gran());
// if(!xpol) j+=2; //Skip over d4(3,x) and d4(4,x)
}
} else {
for(int i=0; i<npts; i+=2) {
datcom_.d4[j++]=(float)id[i];
datcom_.d4[j++]=(float)id[i+1];
// if(!xpol) j+=2; //Skip over d4(3,x) and d4(4,x)
}
}
fclose(fp);
datcom_.ndiskdat=1;
int nfreq=(int)datcom_.fcenter;
if(nfreq!=144 and nfreq != 432 and nfreq != 1296) datcom_.fcenter=1296.080;
int i0=fname.indexOf(".tf2");
if(i0<0) i0=fname.indexOf(".iq");
if(nfreq!=144 and nfreq != 432 and nfreq != 1296) datcom_.fcenter=1296.090;
int i0=fname.indexOf(".iq");
datcom_.nutc=0;
if(i0>0) {
datcom_.nutc=100*fname.mid(i0-4,2).toInt() + fname.mid(i0-2,2).toInt();
@ -55,11 +56,9 @@ void getfile(QString fname, bool xpol, int dbDgrd)
}
}
void savetf2(QString fname, bool xpol)
void save_iq(QString fname)
{
int npts=2*56*96000;
if(xpol) npts=2*npts;
int npts=2*60*96000;
qint16* buf=(qint16*)malloc(2*npts);
char name[80];
strcpy(name,fname.toLocal8Bit());
@ -69,11 +68,11 @@ void savetf2(QString fname, bool xpol)
fwrite(&datcom_.fcenter,sizeof(datcom_.fcenter),1,fp);
int j=0;
for(int i=0; i<npts; i+=2) {
buf[i]=(qint16)datcom_.d4[j++];
buf[i+1]=(qint16)datcom_.d4[j++];
// if(!xpol) j+=2; //Skip over d4(3,x) and d4(4,x)
buf[i]=(qint16)qRound(datcom_.d4[j++]);
buf[i+1]=(qint16)qRound(datcom_.d4[j++]);
}
fwrite(buf,2,npts,fp);
fwrite(&datcom_.ntx30a,4,2,fp); //Write ntx30a and ntx30b to disk
fclose(fp);
}
free(buf);

View File

@ -5,8 +5,8 @@
#include <QDebug>
#include "commons.h"
void getfile(QString fname, bool xpol, int dbDgrd);
void savetf2(QString fname, bool xpol);
void getfile(QString fname, int dbDgrd);
void save_iq(QString fname);
float gran();
#endif // GETFILE_H

View File

@ -5,14 +5,14 @@ set (libq65_FSRCS
astro.f90
astro0.f90
astrosub.f90
chkstat.f90
dcoord.f90
decode0.f90
dot.f90
fchisq0.f90
filbig.f90
four2a.f90
fftbig.f90
ftninit.f90
ftnquit.f90
# ftnquit.f90
geocentric.f90
getcand2.f90
grid2deg.f90
@ -24,12 +24,15 @@ set (libq65_FSRCS
q65c.f90
q65_sync.f90
qmapa.f90
read_qm.f90
recvpkt.f90
save_qm.f90
sun.f90
symspec.f90
timf2.f90
tm2.f90
toxyz.f90
zaptx.f90
f77_wisdom.f
)

40
qmap/libqmap/cfom.f90 Normal file
View File

@ -0,0 +1,40 @@
subroutine cfom(dd,k0,k,ndop0)
parameter(NMAX=60*96000)
real dd(2,NMAX)
complex*16 w,wstep
complex*8 c
real*8 twopi,dphi
logical first
data first/.true./
save twopi,w,first
if(first) then
twopi=8.d0*atan(1.d0)
w=1.d0
first=.false.
endif
dop0=0.5*ndop0
dphi=dop0*twopi/96000.0
wstep=cmplx(cos(dphi),sin(dphi))
do j=k0+1,k
c=w*cmplx(dd(1,j),dd(2,j))
dd(1,j)=real(c)
dd(2,j)=aimag(c)
w=w*wstep
enddo
return
end subroutine cfom
subroutine zaptx(dd,k0,k)
parameter(NMAX=60*96000)
real dd(2,NMAX)
dd(1:2,k0+1:k)=0.
return
end subroutine zaptx

48
qmap/libqmap/cfom_iq.f90 Normal file
View File

@ -0,0 +1,48 @@
program cfom_iq
parameter(NMAX=60*96000)
integer*2 id2(2,NMAX)
complex*16 c,w,wstep
real*8 fcenter,uth8,twopi,dphi
character*6 mygrid
twopi=8.d0*atan(1.d0)
open(10,file='231028_0131.iq',status='old',access='stream')
open(12,file='231028_0131.cfom',status='unknown',access='stream')
mygrid='FN20OG'
nyear=2023
month=10
nday=28
uth8=01 + 31.d0/60
nfreq=1296
call astrosub00(nyear,month,nday,uth8,nfreq,mygrid,ndop0)
call astrosub00(nyear,month,nday,uth8+1.d0/60.d0,nfreq,mygrid,ndop1)
print*,ndop0,ndop1
read(10) fcenter,id2(1:2,1:56*96000)
id2(1:2,56*96000+1:NMAX)=0
dop0=0.5*ndop0
dop1=0.5*ndop1
j=0
w=1.0
do isec=1,60
dop=dop0 + (isec-0.5)*(dop1-dop0)/60.
dphi=dop*twopi/96000.0
wstep=cmplx(cos(dphi),sin(dphi))
do n=1,96000
j=j+1
x=id2(1,j)
y=id2(2,j)
w=w*wstep
c=100.d0*w*cmplx(x,y)
id2(1,j)=0.01d0*real(c)
id2(2,j)=0.01d0*aimag(c)
enddo
enddo
write(12) fcenter,id2
end program cfom_iq

28
qmap/libqmap/chkstat.f90 Normal file
View File

@ -0,0 +1,28 @@
subroutine chkstat(dd,nhsym,pdb)
real dd(2,5760000)
real pdb(4)
integer ia(4),ib(4)
logical*1 btx0,btx1
btx0=.false.
btx1=.false.
ia(1)=23*96000+1
ib(1)=24*96000
ia(2)=27*96000+1
ib(2)=28*96000
ia(3)=53*96000+1
ib(3)=54*96000
ia(4)=57*96000+1
ib(4)=58*96000
do j=1,4
sq=0.
do i=ia(j),ib(j)
sq=sq + dd(1,i)*dd(1,i) + dd(2,i)*dd(2,i)
enddo
pdb(j)=db(1.0 + sq/(2.0*96000.0))
enddo
return
end subroutine chkstat

View File

@ -3,24 +3,26 @@ subroutine decode0(dd,ss,savg)
use timer_module, only: timer
parameter (NSMAX=60*96000)
real*4 dd(2,NSMAX),ss(322,NFFT),savg(NFFT)
real*4 dd(2,NSMAX),ss(400,NFFT),savg(NFFT)
real*8 fcenter
integer offset
integer hist(0:32768)
logical*1 bAlso30
character mycall*12,hiscall*12,mygrid*6,hisgrid*6,datetime*20
character mycall0*12,hiscall0*12,hisgrid0*6
character*60 result
common/decodes/ndecodes,ncand,nQDecoderDone,nWDecoderBusy, &
nWTransmitting,result(50)
common/npar/fcenter,nutc,fselected,mousedf,mousefqso,nagain, &
ndepth,ndiskdat,neme,newdat,nfa,nfb,nfcal,nfshift, &
mcall3,nkeep,ntol,nxant,nrxlog,nfsample,nxpol,nmode, &
ndop00,nsave,max_drift,nhsym,mycall,mygrid,hiscall,hisgrid,datetime
data neme0/-99/
character*64 result
common/decodes/ndecodes,ncand2,nQDecoderDone,nWDecoderBusy, &
nWTransmitting,kHzRequested,result(50)
common/npar/fcenter,nutc,fselected,mousedf,mousefqso,nagain, &
ndepth,ndiskdat,ntx60,newdat,nfa,nfb,nfcal,nfshift, &
ntx30a,ntx30b,ntol,n60,nCFOM,nfsample,ndop58,nmode, &
ndop00,nsave,max_drift,offset,nhsym,mycall,mygrid, &
hiscall,hisgrid,datetime,junk1,junk2,bAlso30
save
nQDecoderDone=0
if(newdat.ne.0) then
nz=96000*nhsym/5.3833
nz=96000*nhsym*0.15
hist=0
do i=1,nz
j1=min(abs(dd(1,i)),32768.0)
@ -39,13 +41,12 @@ subroutine decode0(dd,ss,savg)
mycall0=mycall
hiscall0=hiscall
hisgrid0=hisgrid
neme0=neme
call timer('qmapa ',0)
call qmapa(dd,ss,savg,newdat,nutc,fcenter,ntol,nfa,nfb, &
mousedf,mousefqso,nagain,nfshift,max_drift, &
nfcal,mycall,hiscall,hisgrid,nfsample,nmode,ndepth, &
datetime,ndop00,fselected)
call qmapa(dd,ss,savg,newdat,nutc,fcenter,ntol,nfa,nfb, &
mousedf,mousefqso,nagain,ntx30a,ntx30b,nfshift,max_drift,offset, &
nfcal,mycall,hiscall,hisgrid,nfsample,nmode,ndepth, &
datetime,ndop00,fselected,bAlso30,nhsym,NCFOM)
call timer('qmapa ',1)
return

56
qmap/libqmap/fftbig.f90 Normal file
View File

@ -0,0 +1,56 @@
subroutine fftbig(dd,nmax)
! Do the full length FFT of complex data stored in array dd(2,nmax).
use, intrinsic :: iso_c_binding
use FFTW3
use timer_module, only: timer
parameter (MAXFFT1=5376000)
real*4 dd(2,nmax) !Input data
complex ca(MAXFFT1) !FFT of input
real*8 df
type(C_PTR) :: plan1 !Pointer to FFTW plan
logical first
common/cacb/ca
equivalence (rfilt,cfilt)
data first/.true./,npatience/0/
save
if(nmax.lt.0) go to 900
nfft1=MAXFFT1
if(first) then
nflags=FFTW_ESTIMATE
if(npatience.eq.1) nflags=FFTW_ESTIMATE_PATIENT
if(npatience.eq.2) nflags=FFTW_MEASURE
if(npatience.eq.3) nflags=FFTW_PATIENT
if(npatience.eq.4) nflags=FFTW_EXHAUSTIVE
! Plan the big FFT just once
call timer('FFTplan ',0)
plan1=fftwf_plan_dft_1d(nfft1,ca,ca,+1,nflags)
call timer('FFTplan ',1)
df=96000.d0/nfft1
first=.false.
endif
nz=min(nmax,nfft1)
do i=1,nz
ca(i)=cmplx(dd(1,i),dd(2,i))
enddo
if(nmax.lt.nfft1) then
do i=nmax+1,nfft1
ca(i)=0.
enddo
endif
call timer('FFTbig ',0)
call fftwf_execute_dft(plan1,ca,ca)
call timer('FFTbig ',1)
go to 999
900 call fftwf_destroy_plan(plan1)
999 return
end subroutine fftbig

View File

@ -1,123 +0,0 @@
subroutine filbig(dd,nmax,f0,newdat,nfsample,c4a,n4)
! Filter and downsample complex data stored in array dd(2,nmax).
! Output is downsampled from 96000 Hz to 1375.125 Hz.
use timer_module, only: timer
parameter (MAXFFT1=5376000,MAXFFT2=77175)
real*4 dd(2,nmax) !Input data
complex ca(MAXFFT1) !FFT of input
complex c4a(MAXFFT2) !Output data
real*8 df
real halfpulse(8) !Impulse response of filter (one sided)
complex cfilt(MAXFFT2) !Filter (complex; imag = 0)
real rfilt(MAXFFT2) !Filter (real)
integer*8 plan1,plan2,plan3,plan4,plan5
logical first
include 'fftw3.f'
common/cacb/ca
equivalence (rfilt,cfilt)
data first/.true./,npatience/1/
data halfpulse/114.97547150,36.57879257,-20.93789101, &
5.89886379,1.59355187,-2.49138308,0.60910773,-0.04248129/
save
if(nmax.lt.0) go to 900
nfft1=MAXFFT1
nfft2=MAXFFT2
if(nfsample.eq.95238) then
nfft1=5120000
nfft2=74088
endif
if(first) then
nflags=FFTW_ESTIMATE
if(npatience.eq.1) nflags=FFTW_ESTIMATE_PATIENT
if(npatience.eq.2) nflags=FFTW_MEASURE
if(npatience.eq.3) nflags=FFTW_PATIENT
if(npatience.eq.4) nflags=FFTW_EXHAUSTIVE
! Plan the FFTs just once
call timer('FFTplans ',0)
call sfftw_plan_dft_1d(plan1,nfft1,ca,ca,FFTW_BACKWARD,nflags)
call sfftw_plan_dft_1d(plan3,nfft2,c4a,c4a,FFTW_FORWARD,nflags)
call sfftw_plan_dft_1d(plan5,nfft2,cfilt,cfilt,FFTW_BACKWARD,nflags)
call timer('FFTplans ',1)
! Convert impulse response to filter function
do i=1,nfft2
cfilt(i)=0.
enddo
fac=0.00625/nfft1
cfilt(1)=fac*halfpulse(1)
do i=2,8
cfilt(i)=fac*halfpulse(i)
cfilt(nfft2+2-i)=fac*halfpulse(i)
enddo
call sfftw_execute(plan5)
base=cfilt(nfft2/2+1)
do i=1,nfft2
rfilt(i)=real(cfilt(i))-base
enddo
df=96000.d0/nfft1
if(nfsample.eq.95238) df=95238.1d0/nfft1
first=.false.
endif
! When new data comes along, we need to compute a new "big FFT"
! If we just have a new f0, continue with the existing ca.
if(newdat.ne.0 .or. sum(abs(ca)).eq.0.0) then !### Test on ca should be unnecessary?
nz=min(nmax,nfft1)
do i=1,nz
ca(i)=cmplx(dd(1,i),dd(2,i))
enddo
if(nmax.lt.nfft1) then
do i=nmax+1,nfft1
ca(i)=0.
enddo
endif
call timer('FFTbig ',0)
call sfftw_execute(plan1)
call timer('FFTbig ',1)
!### newdat=0
endif
! NB: f0 is the frequency at which we want our filter centered.
! i0 is the bin number in ca closest to f0.
i0=nint(f0/df) + 1
nh=nfft2/2
do i=1,nh !Copy data into c4a
j=i0+i-1 !and apply the filter function
if(j.ge.1 .and. j.le.nfft1) then
c4a(i)=rfilt(i)*ca(j)
else
c4a(i)=0.
endif
enddo
do i=nh+1,nfft2
j=i0+i-1-nfft2
if(j.lt.1) j=j+nfft1
c4a(i)=rfilt(i)*ca(j)
enddo
! Do the short reverse transform, to go back to time domain.
call timer('FFTsmall',0)
call sfftw_execute(plan3)
call timer('FFTsmall',1)
n4=min(nmax/64,nfft2)
go to 999
900 call sfftw_destroy_plan(plan1)
call sfftw_destroy_plan(plan2)
call sfftw_destroy_plan(plan3)
call sfftw_destroy_plan(plan4)
call sfftw_destroy_plan(plan5)
999 return
end subroutine filbig

View File

@ -1,115 +0,0 @@
subroutine four2a(a,nfft,ndim,isign,iform)
! IFORM = 1, 0 or -1, as data is
! complex, real, or the first half of a complex array. Transform
! values are returned in array DATA. They are complex, real, or
! the first half of a complex array, as IFORM = 1, -1 or 0.
! The transform of a real array (IFORM = 0) dimensioned N(1) by N(2)
! by ... will be returned in the same array, now considered to
! be complex of dimensions N(1)/2+1 by N(2) by .... Note that if
! IFORM = 0 or -1, N(1) must be even, and enough room must be
! reserved. The missing values may be obtained by complex conjugation.
! The reverse transformation of a half complex array dimensioned
! N(1)/2+1 by N(2) by ..., is accomplished by setting IFORM
! to -1. In the N array, N(1) must be the true N(1), not N(1)/2+1.
! The transform will be real and returned to the input array.
! This version of four2a makes calls to the FFTW library to do the
! actual computations.
use fftw3
parameter (NPMAX=2100) !Max numberf of stored plans
parameter (NSMALL=16384) !Max size of "small" FFTs
complex a(nfft+1) !Array to be transformed
complex aa(NSMALL) !Local copy of "small" a()
integer nn(NPMAX),ns(NPMAX),nf(NPMAX) !Params of stored plans
integer*8 nl(NPMAX),nloc !More params of plans
integer*8 plan(NPMAX) !Pointers to stored plans
logical found_plan
data nplan/0/ !Number of stored plans
common/patience/npatience,nthreads !Patience and threads for FFTW plans
save plan,nplan,nn,ns,nf,nl
if(nfft.lt.0) go to 999
nloc=loc(a)
found_plan = .false.
!$omp critical(four2a_setup)
do i=1,nplan
if(nfft.eq.nn(i) .and. isign.eq.ns(i) .and. &
iform.eq.nf(i) .and. nloc.eq.nl(i)) then
found_plan = .true.
exit
end if
enddo
if(i.ge.NPMAX) stop 'Too many FFTW plans requested.'
if (.not. found_plan) then
nplan=nplan+1
i=nplan
nn(i)=nfft
ns(i)=isign
nf(i)=iform
nl(i)=nloc
! Planning: FFTW_ESTIMATE, FFTW_ESTIMATE_PATIENT, FFTW_MEASURE,
! FFTW_PATIENT, FFTW_EXHAUSTIVE
nflags=FFTW_ESTIMATE
if(npatience.eq.1) nflags=FFTW_ESTIMATE_PATIENT
if(npatience.eq.2) nflags=FFTW_MEASURE
if(npatience.eq.3) nflags=FFTW_PATIENT
if(npatience.eq.4) nflags=FFTW_EXHAUSTIVE
if(nfft.le.NSMALL) then
jz=nfft
if(iform.eq.0) jz=nfft/2
aa(1:jz)=a(1:jz)
endif
!$omp critical(fftw) ! serialize non thread-safe FFTW3 calls
if(isign.eq.-1 .and. iform.eq.1) then
call sfftw_plan_dft_1d(plan(i),nfft,a,a,FFTW_FORWARD,nflags)
else if(isign.eq.1 .and. iform.eq.1) then
call sfftw_plan_dft_1d(plan(i),nfft,a,a,FFTW_BACKWARD,nflags)
else if(isign.eq.-1 .and. iform.eq.0) then
call sfftw_plan_dft_r2c_1d(plan(i),nfft,a,a,nflags)
else if(isign.eq.1 .and. iform.eq.-1) then
call sfftw_plan_dft_c2r_1d(plan(i),nfft,a,a,nflags)
else
stop 'Unsupported request in four2a'
endif
!$omp end critical(fftw)
if(nfft.le.NSMALL) then
jz=nfft
if(iform.eq.0) jz=nfft/2
a(1:jz)=aa(1:jz)
endif
end if
!$omp end critical(four2a_setup)
call sfftw_execute(plan(i))
return
999 continue
!$omp critical(four2a)
do i=1,nplan
! The test is only to silence a compiler warning:
if(ndim.ne.-999) then
!$omp critical(fftw) ! serialize non thread-safe FFTW3 calls
call sfftw_destroy_plan(plan(i))
!$omp end critical(fftw)
end if
enddo
nplan=0
!$omp end critical(four2a)
return
end subroutine four2a

View File

@ -3,10 +3,8 @@ subroutine ftninit
use timer_impl, only: init_timer !,fini_timer, limtrace
use, intrinsic :: iso_c_binding, only: C_NULL_CHAR
use FFTW3
! character*(*) appd
character*1 appd
character addpfx*8
character wisfile*256
common/pfxcom/addpfx
lu=8
@ -17,17 +15,6 @@ subroutine ftninit
open(12,file=appd//'/all_qmap.txt',status='unknown',position='append')
open(17,file=appd//'/red.dat',status='unknown')
open(19,file=appd//'/livecq.txt',status='unknown')
open(71,file=appd//'/fort.71',status='unknown')
open(72,file=appd//'/fort.72',status='unknown')
open(73,file=appd//'/fort.73',status='unknown')
! Import FFTW wisdom, if available:
iret=fftwf_init_threads() !Initialize FFTW threading
! Default to 1 thread, but use nthreads for the big ones
call fftwf_plan_with_nthreads(1)
! Import FFTW wisdom, if available
wisfile=trim(appd)//'/m65_wisdom.dat'// C_NULL_CHAR
iret=fftwf_import_wisdom_from_filename(wisfile)
return
end subroutine ftninit

View File

@ -2,7 +2,7 @@ subroutine ftnquit
! Destroy the FFTW plans
call four2a(a,-1,1,1,1)
call filbig(id,-1,f0,newdat,nfsample,c4a,n4)
call fftbig(id,-1)
return
end subroutine ftnquit

View File

@ -1,4 +1,5 @@
subroutine getcand2(ss,savg0,nts_q65,nagain,ntol,f0_selected,cand,ncand)
subroutine getcand2(ss,savg0,nts_q65,nagain,nhsym,ntx30a,ntx30b, &
ntol,f0_selected,bAlso30,cand,ncand2)
! Get candidates for Q65 decodes, based on presence of sync tone.
@ -6,15 +7,18 @@ subroutine getcand2(ss,savg0,nts_q65,nagain,ntol,f0_selected,cand,ncand)
real :: snr !Relative S/N of sync detection
real :: f !Freq of sync tone, 0 to 96000 Hz
real :: xdt !DT of matching sync pattern, -1.0 to +4.0 s
integer :: ntrperiod !60 for Q65-60x, 30 for Q65-30x
integer :: iseq !0 for first half-minute, 1 for second half
end type candidate
parameter (NFFT=32768) !FFTs done in symspec()
parameter (MAX_CANDIDATES=50)
type(candidate) :: cand(MAX_CANDIDATES)
real ss(322,NFFT) !Symbol spectra
real ss(400,NFFT) !Symbol spectra
real savg0(NFFT),savg(NFFT) !Average spectra over whole Rx sequence
integer ipk1(1) !Peak index of local portion of spectrum
logical sync_ok !True if sync pattern is present
logical*1 bAlso30
data nseg/16/,npct/40/
savg=savg0 !Save the original spectrum
@ -35,7 +39,7 @@ subroutine getcand2(ss,savg0,nts_q65,nagain,ntol,f0_selected,cand,ncand)
nguard=5 !Guard range in bins
i1=1
i2=NFFT-nbw-nguard
if(nagain.eq.1) then
if(nagain.ge.1) then
i1=nint((1000.0*f0_selected-ntol)/df)
i2=nint((1000.0*f0_selected+ntol)/df)
endif
@ -48,20 +52,65 @@ subroutine getcand2(ss,savg0,nts_q65,nagain,ntol,f0_selected,cand,ncand)
i0=ipk1(1) + i - 1 !Index of local peak in savg()
fpk=0.001*i0*df !Frequency of peak (kHz)
! Check to see if sync tone is present.
call q65_sync(ss,i0,nts_q65,sync_ok,snr_sync,xdt)
if(.not.sync_ok) cycle
ntrperiod=60
iseq=0
if(nhsym.ge.200) then
call q65_sync(ss,i0,nts_q65,ntrperiod,iseq,sync_ok,snr_sync,xdt)
if(sync_ok) then
! Sync tone is present, we have a candidate for decoding
j=j+1
cand(j)%f=fpk
cand(j)%xdt=xdt
cand(j)%snr=snr_sync
ia=max(1,min(i,i0-nguard))
ib=min(i0+nbw+nguard,32768)
savg(ia:ib)=0.
if(j.ge.MAX_CANDIDATES) exit
j=j+1
cand(j)%f=fpk
cand(j)%xdt=xdt
cand(j)%snr=snr_sync
cand(j)%ntrperiod=ntrperiod
cand(j)%iseq=iseq
ia=max(1,min(i,i0-nguard))
ib=min(i0+nbw+nguard,32768)
savg(ia:ib)=0.
if(j.ge.MAX_CANDIDATES) exit
endif
endif
if(.not.bAlso30) cycle
ntrperiod=30
if(nhsym.le.200 .and. ntx30a.le.5) then
call q65_sync(ss,i0,nts_q65,ntrperiod,iseq,sync_ok,snr_sync,xdt)
if(sync_ok) then
! Sync tone is present, we have a candidate for decoding
j=j+1
cand(j)%f=fpk
cand(j)%xdt=xdt
cand(j)%snr=snr_sync
cand(j)%ntrperiod=ntrperiod
cand(j)%iseq=iseq
ia=max(1,min(i,i0-nguard))
ib=min(i0+nbw+nguard,32768)
savg(ia:ib)=0.
if(j.ge.MAX_CANDIDATES) exit
endif
endif
iseq=1
if(nhsym.ge.330 .and. ntx30b.le.5) then
call q65_sync(ss,i0,nts_q65,ntrperiod,iseq,sync_ok,snr_sync,xdt)
if(sync_ok) then
! Sync tone is present, we have a candidate for decoding
j=j+1
cand(j)%f=fpk
cand(j)%xdt=xdt
cand(j)%snr=snr_sync
cand(j)%ntrperiod=ntrperiod
cand(j)%iseq=iseq
ia=max(1,min(i,i0-nguard))
ib=min(i0+nbw+nguard,32768)
savg(ia:ib)=0.
if(j.ge.MAX_CANDIDATES) exit
endif
endif
enddo
ncand=j !Total number of candidates found
ncand2=j !Total number of candidates found
return
end subroutine getcand2

View File

@ -1 +1 @@
parameter(NJUNK=40)
parameter(NJUNK=42)

View File

@ -1,38 +1,42 @@
subroutine q65_sync(ss,i0,nts_q65,sync_ok,snr,xdt)
subroutine q65_sync(ss,i0,nts_q65,ntrperiod,iseq,sync_ok,snr,xdt)
! Test for presence of Q65 sync tone
parameter (NFFT=32768)
parameter (LAGMAX=33)
real ss(322,NFFT) !Symbol spectra
real ss(400,NFFT) !Symbol spectra
real ccf(0:LAGMAX) !The WSJT "blue curve", peak at DT
logical sync_ok
logical first
integer isync(22),ipk(1)
integer isync0(22),isync(22),ipk(1)
! Q65 sync symbols
data isync/1,9,12,13,15,22,23,26,27,33,35,38,46,50,55,60,62,66,69,74,76,85/
data first/.true./
save first,isync
data isync0/1,9,12,13,15,22,23,26,27,33,35,38,46,50,55,60,62,66,69,74,76,85/
tstep=2048.0/11025.0 !0.185760 s: 0.5*tsym_jt65, 0.3096*tsym_q65
if(first) then
fac=0.6/tstep !3.230
do i=1,22 !Expand the Q65 sync stride
isync(i)=nint((isync(i)-1)*fac) + 1
enddo
first=.false.
endif
sync_ok=.false.
! if(ntrperiod.ne.60) return
tstep=0.15 !0.5*tsym_Q65-30x, 0.25*tsys_Q65-60x
nfac=4
if(ntrperiod.eq.30) nfac=2
do i=1,22 !Expand sync stride for Q65-60x
isync(i)=nfac*(isync0(i)-1) + 1
enddo
m=nts_q65/2
if(ntrperiod.eq.30) m=nts_q65/4
i1=max(1,i0-m)
i2=min(NFFT,i0+m)
ccf=0.
do lag=0,LAGMAX !Search over range of DT
do j=1,22 !Test for Q65 sync
k=isync(j) + lag
ccf(lag)=ccf(lag) + sum(ss(k,i1:i2)) + sum(ss(k+1,i1:i2)) &
+ sum(ss(k+2,i1:i2))
k=isync(j) + lag + iseq*200
if(k.ge.400) cycle
if(ntrperiod.eq.60) then
ccf(lag)=ccf(lag) + sum(ss(k,i1:i2)) + sum(ss(k+1,i1:i2)) &
+ sum(ss(k+2,i1:i2)) + sum(ss(k+3,i1:i2))
else
ccf(lag)=ccf(lag) + sum(ss(k,i1:i2)) + sum(ss(k+1,i1:i2))
endif
! Q: Should we use weighted sums, perhaps a Lorentzian peak?
enddo
enddo
@ -40,16 +44,20 @@ subroutine q65_sync(ss,i0,nts_q65,sync_ok,snr,xdt)
ipk=maxloc(ccf)
lagbest=ipk(1)-1
xdt=lagbest*tstep - 1.0
if(ntrperiod.eq.30) xd=xdt+0.6 !Why ???
xsum=0.
sq=0.
nsum=0
fpk=0.001*i0*96000.0/32768.0 + 32.0
do i=0,lagmax !Compute ave and rms of "blue curve"
if(abs(i-lagbest).gt.2) then
xsum=xsum+ccf(i)
sq=sq+ccf(i)**2
nsum=nsum+1
endif
! write(40,3040) i,i*tstep-1.0,ccf(i),fpk
!3040 format(i5,3f8.2)
enddo
ave=xsum/nsum
rms=sqrt(sq/nsum - ave*ave)

View File

@ -1,6 +1,7 @@
subroutine q65b(nutc,nqd,fcenter,nfcal,nfsample,ikhz,mousedf,ntol, &
mycall0,hiscall0,hisgrid,mode_q65,f0,fqso,nkhz_center, newdat,nagain, &
max_drift,ndepth,datetime,ndop00,idec)
ntrperiod,iseq,mycall0,hiscall0,hisgrid,mode_q65,f0,fqso,nkhz_center, &
newdat,nagain,bClickDecode,max_drift,offset,ndepth,datetime,nCFOM, &
ndop00,nhsym,idec)
! This routine provides an interface between QMAP and the Q65 decoder
! in WSJT-X. All arguments are input data obtained from the QMAP GUI.
@ -8,27 +9,34 @@ subroutine q65b(nutc,nqd,fcenter,nfcal,nfsample,ikhz,mousedf,ntol, &
! in common/cacb. Decoded messages are sent back to the GUI.
use q65_decode
use wavhdr
use timer_module, only: timer
parameter (MAXFFT1=5376000) !56*96000
parameter (MAXFFT2=336000) !56*6000 (downsampled by 1/16)
parameter (NMAX=60*12000)
parameter (RAD=57.2957795)
type(hdr) h
integer*2 iwave(60*12000)
integer offset
complex ca(MAXFFT1) !FFT of raw I/Q data from Linrad
complex cx(0:MAXFFT2-1),cz(0:MAXFFT2)
real*8 fcenter,freq0,freq1
logical*1 bClickDecode
character*12 mycall0,hiscall0
character*12 mycall,hiscall
character*6 hisgrid
character*4 grid4
character*60 result
character*20 datetime
common/decodes/ndecodes,ncand,nQDecoderDone,nWDecoderBusy, &
nWTransmitting,result(50)
character*3 csubmode
character*17 fname
character*64 result,ctmp
character*20 datetime,datetime1
common/decodes/ndecodes,ncand2,nQDecoderDone,nWDecoderBusy, &
nWTransmitting,kHzRequested,result(50)
common/cacb/ca
data ifile/0/
save
if(mycall0(1:1).ne.' ') mycall=mycall0
if(hiscall0(1:1).ne.' ') hiscall=hiscall0
if(hisgrid(1:4).ne.' ') grid4=hisgrid(1:4)
@ -36,26 +44,18 @@ subroutine q65b(nutc,nqd,fcenter,nfcal,nfsample,ikhz,mousedf,ntol, &
! Find best frequency from sync_dat, the "orange sync curve".
df3=96000.0/32768.0
ipk=(1000.0*f0-1.0)/df3
if(nagain.ge.2) ipk = nint(1000.0*(fqso-nkhz_center+48.0)/df3)
nfft1=MAXFFT1
nfft2=MAXFFT2
df=96000.0/NFFT1
if(nfsample.eq.95238) then
nfft1=5120000
nfft2=322560
df=96000.0/nfft1
endif
nh=nfft2/2
f_mouse=1000.0*(fqso+48.0) + mousedf
k0=nint((ipk*df3-1000.0)/df)
if(nagain.eq.1) k0=nint((f_mouse-1000.0)/df)
if(k0.lt.nh .or. k0.gt.MAXFFT1-nfft2+1) go to 900
fac=1.0/nfft2
cx(0:nfft2-1)=ca(k0:k0+nfft2-1)
cx=fac*cx
cx(0:nfft2-1)=fac*ca(k0:k0+nfft2-1)
! Here cx is frequency-domain data around the selected
! QSO frequency, taken from the full-length FFT computed in filbig().
! QSO frequency, taken from the full-length FFT computed in fftbig().
! Values for fsample, nfft1, nfft2, df, and the downsampled data rate
! are as follows:
@ -88,19 +88,65 @@ subroutine q65b(nutc,nqd,fcenter,nfcal,nfsample,ikhz,mousedf,ntol, &
nsubmode=mode_q65-1
nfa=990 !Tight limits around ipk for the wideband decode
nfb=1010
if(nagain.eq.1) then !For nagain=1, use limits of +/- ntol
if(nagain.ge.1) then !For nagain>=1, use limits of +/- ntol
nfa=max(100,1000-ntol)
nfb=min(2500,1000+ntol)
endif
nsnr0=-99 !Default snr for no decode
if(iseq.eq.1) iwave(1:360000)=iwave(360001:720000)
csubmode(1:2)='60'
csubmode(3:3)=char(ichar('A')+nsubmode)
nhhmmss=100*nutc
nutc1=nutc
datetime(12:13)='00'
datetime1=datetime
if(ntrperiod.eq.30) then
csubmode(1:2)='30'
nhhmmss=100*nutc + iseq*30
nutc1=nhhmmss
if(iseq.eq.1) datetime1(12:13)='30'
endif
if(nagain.ge.2) then
ifile=ifile+1
write(fname,1000) ifile
1000 format('000000_',i6.6,'.wav')
open(27,file=fname,status='unknown',access='stream')
if(nagain.eq.2) then
h=default_header(12000,60*12000)
ia=1
ib=60*12000
else if(nagain.eq.3) then
h=default_header(12000,30*12000)
ia=1
ib=30*12000
else
h=default_header(12000,30*12000)
ia=30*12000 + 1
ib=60*12000
endif
write(27) h,iwave(ia:ib)
close(27)
go to 900
endif
! NB: Frequency of ipk is now shifted to 1000 Hz.
call map65_mmdec(nutc,iwave,nqd,nsubmode,nfa,nfb,1000,ntol, &
newdat,nagain,max_drift,ndepth,mycall,hiscall,hisgrid)
MHz=fcenter
nagain2=0
call map65_mmdec(nutc1,iwave,nqd,ntrperiod,nsubmode,nfa,nfb,1000,ntol, &
newdat,nagain2,max_drift,ndepth,mycall,hiscall,hisgrid)
MHz=fcenter
freq0=MHz + 0.001d0*ikhz
if(nsnr0.gt.-99) then
do i=1,ndecodes !Check for dupes
i1=index(result(i)(42:),trim(msg0))
! If this is a dupe, don't save it again:
if(i1.gt.0 .and. (.not.bClickDecode .or. nhsym.eq.390)) go to 800
enddo
nq65df=nint(1000*(0.001*k0*df+nkhz_center-48.0+1.000-1.27046-ikhz))-nfcal
nq65df=nq65df + nfreq0 - 1000
ikhz1=ikhz
@ -109,15 +155,16 @@ subroutine q65b(nutc,nqd,fcenter,nfcal,nfsample,ikhz,mousedf,ntol, &
if(ndf.lt.-500) ikhz1=ikhz + (nq65df-500)/1000
ndf=nq65df - 1000*(ikhz1-ikhz)
freq1=freq0 + 0.001d0*(ikhz1-ikhz)
ndecodes=ndecodes+1
frx=0.001*k0*df+nkhz_center-48.0+1.0 - 0.001*nfcal
fsked=frx - 0.001*ndop00/2.0 - 1.5
write(result(ndecodes),1120) nutc,frx,fsked,xdt0,nsnr0,trim(msg0)
1120 format(i4.4,f9.3,f7.1,f7.2,i5,2x,a)
write(12,1130) datetime,trim(result(ndecodes)(5:))
1130 format(a11,1x,a)
fsked=frx - 0.001*ndop00/2.0 - 0.001*offset
ctmp=csubmode//' '//trim(msg0)
ndecodes=min(ndecodes+1,50)
write(result(ndecodes),1120) nhhmmss,frx,fsked,xdt0,nsnr0,trim(ctmp)
1120 format(i6.6,f9.3,f7.1,f7.2,i5,2x,a)
write(12,1130) datetime1,trim(result(ndecodes)(7:))
1130 format(a13,1x,a)
result(ndecodes)=trim(result(ndecodes))//char(0)
idec=0
800 idec=0
endif
900 flush(12)

View File

@ -1,4 +1,4 @@
subroutine q65c(itimer)
subroutine q65c
use timer_module, only: timer
use timer_impl, only: fini_timer !, limtrace
@ -10,42 +10,96 @@ subroutine q65c(itimer)
parameter (NFFT=32768)
include 'njunk.f90'
real*8 fcenter
real*4 pdb(4)
integer nparams0(NJUNK+3),nparams(NJUNK+3)
! integer values(8)
logical first
logical*1 bAlso30
character*120 fname
character*22 revision
character*12 mycall,hiscall
character*6 mygrid,hisgrid
character*20 datetime
common/datcom2/dd(2,5760000),ss(322,NFFT),savg(NFFT),nparams0
character*64 result
common/decodes/ndecodes,ncand2,nQDecoderDone,nWDecoderBusy, &
nWTransmitting,kHzRequested,result(50)
common/datcom2/dd(2,5760000),ss(400,NFFT),savg(NFFT),nparams0
common/savecom/revision,fname
!### REMEMBER that /npar/ is not updated until nparams=nparams0 is executed. ###
common/npar/fcenter,nutc,fselected,mousedf,mousefqso,nagain, &
ndepth,ndiskdat,neme,newdat,nfcal,nfshift, &
mcall3,nkeep,ntol,nxant,nrxlog,nfsample,nxpol,nmode, &
ndop00,nsave,max_nhsym,mycall,mygrid,hiscall,hisgrid, &
datetime,junk1,junk2
ndepth,ndiskdat,ntx60,newdat,nn1,nn2,nfcal,nfshift, &
ntx30a,ntx30b,ntol,n60,nCFOM,nfsample,ndop58,nmode, &
ndop00,nsave,nn3,nn4,nhsym,mycall,mygrid,hiscall,hisgrid, &
datetime,junk1,junk2,bAlso30
equivalence (nparams,fcenter)
data first/.true./
save first
nparams=nparams0 !Copy parameters into common/npar/
if(itimer.ne.0) then
call timer('decode0 ',101)
call fini_timer
return
endif
datetime(18:20)=':00'
datetime(12:)='00 '
npatience=1
newdat=1 !Always on ??
! write(*,3001) 'aa',newdat,nagain,nfa,nfb,ntol,fselected
!3001 format(a2,5i6,f10.3)
! write(*,3001) 'bb',newdat,nagain,nfa,nfb,ntol,fselected
if(ndiskdat.eq.1) then
call chkstat(dd,nhsym,pdb)
if((abs(pdb(1)-pdb(2)).gt.3.0 .and. pdb(1).gt.1.0) .or. &
pdb(1).lt.1.0) ntx30a=20 !Tx 1st half
if((abs(pdb(3)-pdb(4)).gt.3.0 .and. pdb(3).gt.1.0) .or. &
pdb(3).lt.1.0) ntx30b=20 !Tx 2nd half
if(pdb(4).lt.0.04) then
ntx30a=0 !Older 56s files have no Tx
ntx30b=0 !Older 56s files have no Tx
endif
endif
if(ntx30a.gt.5) then
dd(1:2,1:30*96000)=0.
ss(1:200,1:NFFT)=0.
do i=1,NFFT
savg(i)=sum(ss(201:400,i))
enddo
endif
if(ntx30b.gt.5) then
dd(1:2,30*96000+1:60*96000)=0.
ss(201:400,1:NFFT)=0.
do i=1,NFFT
savg(i)=sum(ss(1:200,i))
enddo
endif
if(nhsym.gt.200 .and. ntx30b.gt.5) go to 10
call timer('decode0 ',0)
call decode0(dd,ss,savg)
call timer('decode0 ',1)
10 continue
! call date_and_time(VALUES=values)
! n60b=values(7)
! nd=n60b-n60
! if(nd.lt.0) nd=nd+60
! write(*,3002) nutc,nagain,nhsym,n60,n60b,nd,ntx30a,ntx30b,ndecodes, &
! nsave,revision
!3002 format('A',i5.4,i3,i5,7i4,1x,a22)
! flush(6)
if(ndiskdat.eq.0) then
if(nhsym.eq.390 .and. &
(nsave.eq.2 .or. (nsave.eq.1 .and. ndecodes.ge.1))) then
call save_qm(fname,revision,mycall,mygrid,dd,ntx30a,ntx30b,fcenter, &
nutc,ndop00,ndop58)
endif
endif
return
end subroutine q65c
subroutine all_done
use timer_module, only: timer
use timer_impl, only: fini_timer
call timer('decode0 ',101)
call fini_timer
return
end subroutine all_done

View File

@ -1,6 +1,7 @@
subroutine qmapa(dd,ss,savg,newdat,nutc,fcenter,ntol,nfa,nfb, &
mousedf,mousefqso,nagain,nfshift,max_drift,nfcal,mycall, &
hiscall,hisgrid,nfsample,nmode,ndepth,datetime,ndop00,fselected)
mousedf,mousefqso,nagain,ntx30a,ntx30b,nfshift,max_drift,offset, &
nfcal,mycall,hiscall,hisgrid,nfsample,nBaseSubmode,ndepth, &
datetime,ndop00,fselected,bAlso30,nhsym,nCFOM)
! Processes timf2 data received from Linrad to find and decode Q65 signals.
@ -10,64 +11,109 @@ subroutine qmapa(dd,ss,savg,newdat,nutc,fcenter,ntol,nfa,nfb, &
real :: snr !Relative S/N of sync detection
real :: f !Freq of sync tone, 0 to 96000 Hz
real :: xdt !DT of matching sync pattern, -1.0 to +4.0 s
integer :: ntrperiod !60 for Q65-60x, 30 for Q65-30x
integer :: iseq !0 for first half-minute, 1 for second half
end type candidate
type good_decode
real :: f !Freq of sync tone, 0 to 96000 Hz
integer :: ntrperiod !60 for Q65-60x, 30 for Q65-30x
integer :: iseq !0 for first half-minute, 1 for second half
end type good_decode
parameter (NFFT=32768) !Size of FFTs done in symspec()
parameter (MAX_CANDIDATES=50)
parameter (MAXMSG=1000) !Size of decoded message list
parameter (NSMAX=60*96000)
complex cx(NSMAX/64) !Data at 1378.125 samples/s
real dd(2,NSMAX) !I/Q data from Linrad
real ss(322,NFFT) !Symbol spectra
real ss(400,NFFT) !Symbol spectra
real savg(NFFT) !Average spectrum
real*8 fcenter !Center RF frequency, MHz
real*8 fcenter !Center RF frequency, MHz
logical*1 bAlso30,bClickDecode
character mycall*12,hiscall*12,hisgrid*6
type(candidate) :: cand(MAX_CANDIDATES)
character*60 result
type(good_decode) found(MAX_CANDIDATES)
character*64 result
character*20 datetime
common/decodes/ndecodes,ncand,nQDecoderDone,nWDecoderBusy, &
nWTransmitting,result(50)
common/decodes/ndecodes,ncand2,nQDecoderDone,nWDecoderBusy, &
nWTransmitting,kHzRequested,result(50)
save
tsec0=sec_midn()
if(nagain.eq.1) ndepth=3 !Use full depth for click-to-decode
if(nagain.ge.1) ndepth=3 !Use full depth for click-to-decode
nkhz_center=nint(1000.0*(fcenter-int(fcenter)))
mfa=nfa-nkhz_center+48
mfb=nfb-nkhz_center+48
mode_q65=nmode/10
mode_q65=nBaseSubmode
nts_q65=2**(mode_q65-1) !Q65 tone separation factor
f0_selected=fselected - nkhz_center + 48.0
call timer('get_cand',0)
! Get a list of decoding candidates
call getcand2(ss,savg,nts_q65,nagain,ntol,f0_selected,cand,ncand)
call timer('get_cand',1)
if(nagain.le.1) then
call timer('get_cand',0)
! Get a list of decoding candidates
call getcand2(ss,savg,nts_q65,nagain,nhsym,ntx30a,ntx30b,ntol, &
f0_selected,bAlso30,cand,ncand2)
call timer('get_cand',1)
endif
nwrite_q65=0
df=96000.0/NFFT !df = 96000/NFFT = 2.930 Hz
if(nfsample.eq.95238) df=95238.1/NFFT
ftol=0.010 !Frequency tolerance (kHz)
foffset=0.001*(1270 + nfcal) !Offset from sync tone, plus CAL
fqso=mousefqso + foffset - 0.5*(nfa+nfb) + nfshift !fqso at baseband (khz)
nqd=0
nagain2=0
bClickDecode=(nagain.ge.1)
call timer('filbig ',0)
call filbig(dd,NSMAX,f0,newdat,nfsample,cx,n5) !Do the full-length FFT
call timer('filbig ',1)
call timer('fftbig ',0)
call fftbig(dd,NSMAX) !Do the full-length FFT
call timer('fftbig ',1)
do icand=1,ncand !Attempt to decode each candidate
if(nagain.ge.2) then
ncand2=1
fqso=fselected
endif
do icand=1,ncand2 !Attempt to decode each candidate
tsec=sec_midn() - tsec0
if(ndiskdat.eq.0) then
! No more realtime decode attempts if it's nearly too late, already
if(nhsym.eq.130 .and. tsec.gt.6.0) exit
if(nhsym.eq.200 .and. tsec.gt.10.0) exit
if(nhsym.eq.330 .and. tsec.gt.6.0) exit
if(nhsym.eq.390 .and. tsec.gt.16.0) exit
endif
f0=cand(icand)%f
freq=cand(icand)%f+nkhz_center-48.0-1.27046
ntrperiod=cand(icand)%ntrperiod
iseq=cand(icand)%iseq
if(nagain.eq.0) then
! Skip this candidate if we already decoded it.
do j=1,ndecodes
if(abs(f0-found(j)%f).lt.0.005 .and. &
ntrperiod.eq.found(j)%ntrperiod .and. &
iseq.eq.found(j)%iseq) go to 10
enddo
endif
mode_q65_tmp=mode_q65
if(ntrperiod.eq.30) mode_q65_tmp=max(1,mode_q65-1)
freq=f0+nkhz_center-48.0-1.27046
ikhz=nint(freq)
idec=-1
call timer('q65b ',0)
call q65b(nutc,nqd,fcenter,nfcal,nfsample,ikhz,mousedf,ntol, &
mycall,hiscall,hisgrid,mode_q65,f0,fqso,nkhz_center,newdat, &
nagain2,max_drift,ndepth,datetime,ndop00,idec)
call q65b(nutc,nqd,fcenter,nfcal,nfsample,ikhz,mousedf,ntol, &
ntrperiod,iseq,mycall,hiscall,hisgrid,mode_q65_tmp,f0,fqso, &
nkhz_center,newdat,nagain,bClickDecode,max_drift,offset, &
ndepth,datetime,nCFOM,ndop00,nhsym,idec)
call timer('q65b ',1)
tsec=sec_midn() - tsec0
if(tsec.gt.30.0) exit !Don't start another decode attempt after t=30 s.
if(bClickDecode .and. idec.ge.0) exit
if(idec.ge.0) then
! Save some details on good decodes, to avoid duplicated effort
found(ndecodes)%f=f0
found(ndecodes)%ntrperiod=ntrperiod
found(ndecodes)%iseq=iseq
end if
10 continue
enddo ! icand
return

44
qmap/libqmap/read_qm.f90 Normal file
View File

@ -0,0 +1,44 @@
subroutine read_qm(fname,iret)
include 'njunk.f90'
parameter(NMAX=60*96000,NFFT=32768)
character*(*) fname
character prog_id*24,mycall*12,mygrid*6
real*8 fcenter
integer nxtra(15) !For possible future additions
integer*1 id1(2,NMAX)
common/datcom/dd(2,5760000),ss(400,NFFT),savg(NFFT), &
fcenter,nutc,fselected,mousedf,mousefqso,nagain, &
ndepth,ndiskdat,ntx60,newdat,nn1,nn2,nfcal,nfshift, &
ntx30a,ntx30b !...
open(28,file=trim(fname),status='old',access='stream',err=900)
read(28,end=910) prog_id,mycall,mygrid,fcenter,nutc,ntx30a, &
ntx30b,ndop00,ndop58,ia,ib,fac0,nxtra
iret=3
if(ib.eq.NMAX/2) iret=1
if(ia.eq.NMAX/2+1) iret=2
fac=1.0
if(fac0.gt.0.0) fac=1.0/fac0
id1=0
read(28,end=910) id1(1:2,ia:ib)
dd=0.
dd(1:2,ia:ib)=fac*id1(1:2,ia:ib) !Boost back to previous level
go to 999
900 iret=-1; go to 999
910 iret=-2
999 close(28)
! sq1=0.
! sq2=0.
! NH=NMAX/2
! do i=1,NMAX
! if(i.le.NH) sq1=sq1 + dd(1,i)*dd(1,i) + dd(2,i)*dd(2,i)
! if(i.gt.NH) sq2=sq2 + dd(1,i)*dd(1,i) + dd(2,i)*dd(2,i)
! enddo
! print*,'B',sqrt(sq1/NMAX),sqrt(sq2/NMAX)
return
end subroutine read_qm

View File

@ -1,4 +1,4 @@
subroutine recvpkt(nsam,nblock2,userx_no,k,buf4,buf8)
subroutine recvpkt(nsam,nblock2,userx_no,k,buf4,buf8,ndb)
! Reformat timf2 data from Linrad and stuff data into r*4 array dd().
@ -11,11 +11,12 @@ subroutine recvpkt(nsam,nblock2,userx_no,k,buf4,buf8)
integer*2 jd(4),kd(2),nblock2
real*4 yd(2)
real*8 fcenter
common/datcom/dd(2,5760000),ss(322,NFFT),savg(NFFT),fcenter,nutc, &
common/datcom/dd(2,5760000),ss(400,NFFT),savg(NFFT),fcenter,nutc, &
junk(NJUNK)
equivalence (kd,d4)
equivalence (jd,d8,yd)
gain=10.0**(0.05*ndb)
if(nblock2.eq.-9999) nblock2=-9998 !Silence a compiler warning
if(nsam.eq.-1) then
! Move data from the UDP packet buffer into array dd().
@ -23,15 +24,15 @@ subroutine recvpkt(nsam,nblock2,userx_no,k,buf4,buf8)
do i=1,174 !One RF channel, r*4 data
k=k+1
d8=buf8(i)
dd(1,k)=yd(1)
dd(2,k)=yd(2)
dd(1,k)=yd(1)*gain
dd(2,k)=yd(2)*gain
enddo
else if(userx_no.eq.1) then
do i=1,348 !One RF channel, i*2 data
k=k+1
d4=buf4(i)
dd(1,k)=kd(1)
dd(2,k)=kd(2)
dd(1,k)=kd(1)*gain
dd(2,k)=kd(2)*gain
enddo
endif
else
@ -39,12 +40,12 @@ subroutine recvpkt(nsam,nblock2,userx_no,k,buf4,buf8)
do i=1,nsam !One RF channel, r*4 data
k=k+1
d4=buf4(i)
dd(1,k)=kd(1)
dd(2,k)=kd(2)
dd(1,k)=kd(1)*gain
dd(2,k)=kd(2)*gain
k=k+1
dd(1,k)=kd(1)
dd(2,k)=kd(2)
dd(1,k)=kd(1)*gain
dd(2,k)=kd(2)*gain
enddo
endif
endif

63
qmap/libqmap/save_qm.f90 Normal file
View File

@ -0,0 +1,63 @@
subroutine save_qm(fname,revision,mycall,mygrid,dd,ntx30a,ntx30b,fcenter, &
nutc,ndop00,ndop58)
parameter(NMAX=60*96000)
character*120 fname
character*22 revision
character*12 mycall
character*6 mygrid
real*4 dd(2,NMAX)
real*8 fcenter
integer nxtra(15) !For possible future additions
integer*1,allocatable :: id1(:,:)
ia=1
ib=NMAX
if(ntx30a.gt.5) ia=NMAX/2+1
if(ntx30b.gt.5) ib=NMAX/2
sq=0.
do i=ia,ib
x=dd(1,i)
y=dd(2,i)
sq=sq + x*x + y*y
enddo
nsum=2*(ib-ia+1)
rms=sqrt(sq/nsum)
nbad=0
dmax=0.
fac0=10.0/rms
allocate(id1(1:2,1:NMAX))
do i=ia,ib
x=fac0*dd(1,i)
y=fac0*dd(2,i)
ax=abs(x)
ay=abs(y)
dmax=max(dmax,ax,ay)
if(ax.gt.127.0) then
x=0.
nbad=nbad+1
endif
if(ay.gt.127.0) then
y=0.
nbad=nbad+1
endif
id1(1,i)=nint(x)
id1(2,i)=nint(y)
enddo
if(ia.gt.30*96000) id1(1:2,1:ia-1)=0
if(ib.eq.30*96000) id1(1:2,ib+1:60*96000)=0
open(29,file=trim(fname),status='unknown',access='stream')
nxtra=0
write(29) revision//' ',mycall,mygrid,fcenter,nutc,ntx30a,ntx30b, &
ndop00,ndop58,ia,ib,fac0,nxtra !Write header to disk
write(29) id1(1:2,ia:ib) !Write 8-bit data to disk
close(29)
deallocate(id1)
return
end subroutine save_qm

View File

@ -8,7 +8,7 @@ subroutine symspec(k,ndiskdat,nb,nbslider,nfsample, &
! pxdb power in x channel (0-60 dB)
! ssz5a polarized spectrum, for waterfall display
! nkhz integer kHz portion of center frequency, e.g., 125 for 144.125
! ihsym index number of this half-symbol (1-322)
! ihsym index number of this half-symbol (1-400)
! nzap number of samples zero'ed by noise blanker
include 'njunk.f90'
@ -16,9 +16,9 @@ subroutine symspec(k,ndiskdat,nb,nbslider,nfsample, &
parameter (NFFT=32768) !Length of FFTs
real*8 ts,hsym
real*8 fcenter
common/datcom/dd(2,5760000),ss(322,NFFT),savg(NFFT),fcenter,nutc, &
common/datcom/dd(2,5760000),ss(400,NFFT),savg(NFFT),fcenter,nutc, &
junk(NJUNK)
real*4 ssz5a(NFFT),w(NFFT),w2a(NFFT),w2b(NFFT)
real*4 ssz5a(NFFT),w(NFFT)
complex cx(NFFT)
complex cx00(NFFT)
complex cx0(0:1023),cx1(0:1023)
@ -26,31 +26,24 @@ subroutine symspec(k,ndiskdat,nb,nbslider,nfsample, &
data rms/999.0/,k0/99999999/,nadjx/0/,nadjy/0/
save
nfast=1
hsym=0.15d0*96000.d0 !Samples per Q65-30x half-symbol
npts=2*hsym !Full Q65-30x symbol
if(k.gt.5751000) go to 999
if(k.lt.NFFT) then
if(k.lt.npts) then
ihsym=0
go to 999 !Wait for enough samples to start
endif
if(k0.eq.99999999) then
pi=4.0*atan(1.0)
w2a=0.
w2b=0.
do i=1,NFFT
w(i)=(sin(i*pi/NFFT))**2 !Window for nfast=1
if(i.lt.17833) w2a(i)=(sin(i*pi/17832.925))**2 !Window a for nfast=2
j=i-8916
if(j.gt.0 .and. j.lt.17833) w2b(i)=(sin(j*pi/17832.925))**2 ! b
enddo
w2a=sqrt(2.0)*w2a
w2b=sqrt(2.0)*w2b
! pi=4.0*atan(1.0)
! do i=1,NFFT
! w(i)=(sin(i*pi/NFFT))**2 !Window
! enddo
w=0.7 !Flat window
endif
hsym=2048.d0*96000.d0/11025.d0 !Samples per JT65 half-symbol
if(nfsample.eq.95238) hsym=2048.d0*95238.1d0/11025.d0
if(k.lt.k0) then
ts=1.d0 - hsym
ss=0.
savg=0.
ihsym=0
k1=0
@ -85,12 +78,9 @@ subroutine symspec(k,ndiskdat,nb,nbslider,nfsample, &
k1=k1+kstep
enddo
npts=NFFT !Samples used in each half-symbol FFT
ts=ts+hsym
ja=ts !Index of first sample
jb=ja+npts-1 !Last sample
i=0
fac=0.0002
do j=ja,jb !Copy data into cx
@ -99,11 +89,12 @@ subroutine symspec(k,ndiskdat,nb,nbslider,nfsample, &
i=i+1
cx(i)=fac*cmplx(x1,x2)
enddo
cx(npts+1:)=0.
if(nzap/178.lt.50 .and. (ndiskdat.eq.0 .or. ihsym.lt.280)) then
nsum=nblks*kstep - nzap
if(nsum.le.0) nsum=1
rmsx=sqrt(0.5*px/nsum)
rmsx=sqrt(px/nsum)
rms=rmsx
endif
pxdb=0.
@ -112,31 +103,21 @@ subroutine symspec(k,ndiskdat,nb,nbslider,nfsample, &
cx00=cx
do mm=1,nfast
ihsym=ihsym+1
if(nfast.eq.1) then
cx=w*cx00 !Apply window for 2nd forward FFT
else
if(mm.eq.1) then
cx=w2a*cx00
else
cx=w2b*cx00
endif
endif
call four2a(cx,NFFT,1,1,1) !Second forward FFT (X)
n=min(322,ihsym)
do i=1,NFFT
sx=real(cx(i))**2 + aimag(cx(i))**2
ss(n,i)=sx ! Pol = 0
savg(i)=savg(i) + sx
ssz5a(i)=sx
enddo
ihsym=ihsym+1
cx=w*cx00 !Apply window for 2nd forward FFT
call four2a(cx,NFFT,1,1,1) !Second forward FFT (X)
n=min(400,ihsym)
do i=1,NFFT
sx=real(cx(i))**2 + aimag(cx(i))**2
ss(n,i)=sx ! Pol = 0
savg(i)=savg(i) + sx
ssz5a(i)=sx
enddo
nkhz=nint(1000.d0*(fcenter-int(fcenter)))
if(fcenter.eq.0.d0) nkhz=125
! write(*,3001) hsym,ts,ja,jb,ihsym
!3001 format(2f12.3,3i10)
999 return
end subroutine symspec

9
qmap/libqmap/zaptx.f90 Normal file
View File

@ -0,0 +1,9 @@
subroutine zaptx(dd,k0,k)
parameter(NMAX=60*96000)
real dd(2,NMAX)
dd(1:2,k0+1:k)=0.
return
end subroutine zaptx

View File

@ -16,6 +16,7 @@ extern "C" {
void _gfortran_set_args(int argc, char *argv[]);
void _gfortran_set_convert(int conv);
void ftninit_(void);
void fftbig_(float dd[], int* nfft);
}
int main(int argc, char *argv[])
@ -29,7 +30,7 @@ int main(int argc, char *argv[])
// Override programs executable basename as application name.
a.setApplicationName ("QMAP");
a.setApplicationVersion ("0.2");
a.setApplicationVersion ("0.4");
// switch off as we share an Info.plist file with WSJT-X
a.setAttribute (Qt::AA_DontUseNativeMenuBar);
MainWindow w;
@ -45,9 +46,9 @@ int main(int argc, char *argv[])
int iform {1};
// free FFT plan resources
four2a_ (nullptr, &nfft, &ndim, &isign, &iform, 0);
fftbig_(nullptr, &nfft);
}
fftwf_forget_wisdom ();
fftwf_cleanup ();
return result;
}

View File

@ -60,8 +60,9 @@ MainWindow::MainWindow(QWidget *parent) :
ui->actionQ65E->setActionGroup(modeGroup2);
QActionGroup* saveGroup = new QActionGroup(this);
ui->actionSave_all->setActionGroup(saveGroup);
ui->actionNone->setActionGroup(saveGroup);
ui->actionSave_all->setActionGroup(saveGroup);
ui->actionSave_decoded->setActionGroup(saveGroup);
setWindowTitle (program_title ());
@ -71,27 +72,25 @@ MainWindow::MainWindow(QWidget *parent) :
createStatusBar();
connect(m_gui_timer, &QTimer::timeout, this, &MainWindow::guiUpdate);
m_waterfallAvg = 1;
m_network = true;
m_waterfallAvg=1;
m_network=true;
m_restart=false;
m_myCall="K1JT";
m_myGrid="FN20qi";
m_myCallColor=0;
m_saveDir="";
m_azelDir="";
m_loopall=false;
m_startAnother=false;
m_saveAll=false;
m_onlyEME=false;
m_saveDecoded=false;
m_sec0=-1;
m_hsym0=-1;
m_palette="CuteSDR";
m_nutc0=9999;
m_kb8rq=false;
m_NB=false;
m_mode="Q65";
m_fs96000=true;
m_udpPort=50004;
m_nsave=0;
m_modeQ65=0;
m_TRperiod=60;
@ -110,8 +109,7 @@ MainWindow::MainWindow(QWidget *parent) :
memset(ipc_wsjtx,0,memSize); //Zero all of shared memory
mem_qmap.unlock();
fftwf_import_wisdom_from_filename (QDir {m_appDir}.absoluteFilePath ("qmap_wisdom.dat").toLocal8Bit ());
// fftwf_import_wisdom_from_filename (QDir {m_appDir}.absoluteFilePath ("qmap_wisdom.dat").toLocal8Bit ());
readSettings(); //Restore user's setup params
m_pbdecoding_style1="QPushButton{background-color: cyan; \
@ -134,14 +132,6 @@ MainWindow::MainWindow(QWidget *parent) :
if(m_modeQ65==4) on_actionQ65D_triggered();
if(m_modeQ65==5) on_actionQ65E_triggered();
future1 = new QFuture<void>;
watcher1 = new QFutureWatcher<void>;
connect(watcher1, SIGNAL(finished()),this,SLOT(diskDat()));
future2 = new QFuture<void>;
watcher2 = new QFutureWatcher<void>;
connect(watcher2, SIGNAL(finished()),this,SLOT(diskWriteFinished()));
connect(&watcher3, SIGNAL(finished()),this,SLOT(decoderFinished()));
// Assign input device and start input thread
@ -159,6 +149,8 @@ MainWindow::MainWindow(QWidget *parent) :
m_wide_graph_window->setTol(m_tol);
m_wide_graph_window->setFcal(m_fCal);
m_wide_graph_window->setFsample(96000);
QString rev{"QMAP v" + QCoreApplication::applicationVersion() + " " + revision()};
m_revision=rev;
// Create "m_worked", a dictionary of all calls in wsjt.log
QFile f("wsjt.log");
@ -194,14 +186,12 @@ MainWindow::MainWindow(QWidget *parent) :
MainWindow::~MainWindow()
{
writeSettings();
int itimer=1;
q65c_(&itimer);
all_done_();
if (soundInThread.isRunning()) {
soundInThread.quit();
soundInThread.wait(3000);
}
fftwf_export_wisdom_to_filename (QDir {m_appDir}.absoluteFilePath ("qmap_wisdom.dat").toLocal8Bit ());
delete ui;
}
@ -218,15 +208,13 @@ void MainWindow::writeSettings()
SettingsGroup g {&settings, "Common"};
settings.setValue("MyCall",m_myCall);
settings.setValue("MyGrid",m_myGrid);
settings.setValue("IDint",m_idInt);
settings.setValue("AstroFont",m_astroFont);
settings.setValue("MyCallColor",m_myCallColor);
settings.setValue("SaveDir",m_saveDir);
settings.setValue("AzElDir",m_azelDir);
settings.setValue("Timeout",m_timeout);
settings.setValue("Fcal",m_fCal);
settings.setValue("Fadd",m_fAdd);
settings.setValue("NetworkInput", m_network);
settings.setValue("FSam96000", m_fs96000);
settings.setValue("paInDevice",m_paInDevice);
settings.setValue("Scale_dB",m_dB);
settings.setValue("UDPport",m_udpPort);
@ -238,15 +226,13 @@ void MainWindow::writeSettings()
settings.setValue("nModeQ65",m_modeQ65);
settings.setValue("SaveNone",ui->actionNone->isChecked());
settings.setValue("SaveAll",ui->actionSave_all->isChecked());
settings.setValue("NEME",m_onlyEME);
settings.setValue("KB8RQ",m_kb8rq);
settings.setValue("SaveDecoded",ui->actionSave_decoded->isChecked());
settings.setValue("ContinuousWaterfall",ui->continuous_waterfall->isChecked());
settings.setValue("NB",m_NB);
settings.setValue("NBslider",m_NBslider);
settings.setValue("GainX",(double)m_gainx);
settings.setValue("GainY",(double)m_gainy);
settings.setValue("PhaseX",(double)m_phasex);
settings.setValue("PhaseY",(double)m_phasey);
settings.setValue("MaxDrift",ui->sbMaxDrift->value());
settings.setValue("Offset",ui->sbOffset->value());
settings.setValue("Also30",m_bAlso30);
}
//---------------------------------------------------------- readSettings()
@ -262,16 +248,14 @@ void MainWindow::readSettings()
SettingsGroup g {&settings, "Common"};
m_myCall=settings.value("MyCall","").toString();
m_myGrid=settings.value("MyGrid","").toString();
m_idInt=settings.value("IDint",0).toInt();
m_astroFont=settings.value("AstroFont",20).toInt();
m_astroFont=settings.value("AstroFont",18).toInt();
m_myCallColor=settings.value("MyCallColor",1).toInt();
m_saveDir=settings.value("SaveDir",m_appDir + "/save").toString();
m_azelDir=settings.value("AzElDir",m_appDir).toString();
m_timeout=settings.value("Timeout",20).toInt();
m_fCal=settings.value("Fcal",0).toInt();
m_fAdd=settings.value("FAdd",0).toDouble();
soundInThread.setFadd(m_fAdd);
m_network = settings.value("NetworkInput",true).toBool();
m_fs96000 = settings.value("FSam96000",true).toBool();
m_dB = settings.value("Scale_dB",0).toInt();
m_udpPort = settings.value("UDPport",50004).toInt();
soundInThread.setScale(m_dB);
@ -281,7 +265,7 @@ void MainWindow::readSettings()
ui->actionLinrad->setChecked(settings.value(
"PaletteLinrad",false).toBool());
m_modeQ65=settings.value("nModeQ65",2).toInt();
m_modeQ65=settings.value("nModeQ65",3).toInt();
if(m_modeQ65==1) ui->actionQ65A->setChecked(true);
if(m_modeQ65==2) ui->actionQ65B->setChecked(true);
if(m_modeQ65==3) ui->actionQ65C->setChecked(true);
@ -290,20 +274,29 @@ void MainWindow::readSettings()
ui->actionNone->setChecked(settings.value("SaveNone",true).toBool());
ui->actionSave_all->setChecked(settings.value("SaveAll",false).toBool());
ui->actionSave_decoded->setChecked(settings.value("SaveDecoded",false).toBool());
ui->continuous_waterfall->setChecked(settings.value("ContinuousWaterfall",false).toBool());
m_saveAll=ui->actionSave_all->isChecked();
m_onlyEME=settings.value("NEME",false).toBool();
ui->actionOnly_EME_calls->setChecked(m_onlyEME);
m_kb8rq=settings.value("KB8RQ",false).toBool();
m_saveDecoded=ui->actionSave_decoded->isChecked();
if(m_saveAll) {
lab5->setStyleSheet("QLabel{background-color: #ffff00}");
lab5->setText("Save all");
} else if(m_saveDecoded) {
lab5->setStyleSheet("QLabel{background-color: #ffff00}");
lab5->setText("Save decoded");
} else {
lab5->setStyleSheet("");
lab5->setText("");
}
m_NB=settings.value("NB",false).toBool();
ui->NBcheckBox->setChecked(m_NB);
ui->sbMaxDrift->setValue(settings.value("MaxDrift",0).toInt());
ui->sbOffset->setValue(settings.value("Offset",1500).toInt());
m_NBslider=settings.value("NBslider",40).toInt();
ui->NBslider->setValue(m_NBslider);
m_gainx=settings.value("GainX",1.0).toFloat();
m_gainy=settings.value("GainY",1.0).toFloat();
m_phasex=settings.value("PhaseX",0.0).toFloat();
m_phasey=settings.value("PhaseY",0.0).toFloat();
m_bAlso30=settings.value("Also30",true).toBool();
ui->actionAlso_Q65_30x->setChecked(m_bAlso30);
on_actionAlso_Q65_30x_toggled(m_bAlso30);
if(!ui->actionLinrad->isChecked() && !ui->actionCuteSDR->isChecked() &&
!ui->actionAFMHot->isChecked() && !ui->actionBlue->isChecked()) {
on_actionLinrad_triggered();
@ -317,6 +310,7 @@ void MainWindow::dataSink(int k)
static float s[NFFT],splot[NFFT];
static int n=0;
static int ihsym=0;
static int ihsym0=0;
static int nzap=0;
static int ntrz=0;
static int nkhz;
@ -325,6 +319,7 @@ void MainWindow::dataSink(int k)
static int nsum=0;
static int ndiskdat;
static int nb;
static int k0=0;
static float px=0.0;
static uchar lstrong[1024];
static float slimit;
@ -341,7 +336,10 @@ void MainWindow::dataSink(int k)
nb=0;
if(m_NB) nb=1;
nfsample=96000;
if(!m_fs96000) nfsample=95238;
if(m_bWTransmitting) zaptx_(datcom_.d4, &k0, &k);
k0=k;
symspec_(&k, &ndiskdat, &nb, &m_NBslider, &nfsample,
&px, s, &nkhz, &ihsym, &nzap, &slimit, lstrong);
@ -357,6 +355,7 @@ void MainWindow::dataSink(int k)
}
nsec0=nsec;
if(m_bWTransmitting) px=0.0;
QString t;
m_pctZap=nzap/178.3;
@ -366,9 +365,9 @@ void MainWindow::dataSink(int k)
.arg (m_pctZap, 5, 'f', 1)
);
xSignalMeter->setValue(px); // Update the signal meters
xSignalMeter->setValue(px); // Update the signal meter
//Suppress scrolling if WSJT-X is transmitting
if((m_monitoring and ipc_wsjtx[4] != 1) or m_diskData) {
if((m_monitoring and (!m_bWTransmitting or ui->continuous_waterfall->isChecked())) or m_diskData) {
m_wide_graph_window->dataSink2(s,nkhz,ihsym,m_diskData,lstrong);
}
@ -399,26 +398,26 @@ void MainWindow::dataSink(int k)
n=0;
}
bool bCallDecoder=false;
if(ihsym < m_hsymStop) m_decode_called=false;
if(ihsym==m_hsymStop and !m_decode_called) bCallDecoder=true; //Decode at t=58.5 s
if(ihsym==130) bCallDecoder=true;
if(m_bAlso30 and (ihsym==200)) bCallDecoder=true;
if(ihsym==330) bCallDecoder=true;
if(ihsym==ihsym0) bCallDecoder=false;
if(ihsym >= m_hsymStop and !m_decode_called) { //Decode at t=56 s (for Q65 and data from disk)
m_decode_called=true;
datcom_.newdat=1;
ihsym0=ihsym;
if(bCallDecoder) {
if(ihsym==m_hsymStop) m_decode_called=true;
datcom_.nagain=0;
datcom_.nhsym=ihsym;
QDateTime t = QDateTime::currentDateTimeUtc();
m_dateTime=t.toString("yymmdd_hhmm");
decode(); //Start the decoder
if(m_saveAll and !m_diskData and m_nTransmitted<10) {
QString fname=m_saveDir + "/" + t.date().toString("yyMMdd") + "_" +
t.time().toString("hhmm");
fname += ".iq";
*future2 = QtConcurrent::run(savetf2, fname, false);
watcher2->setFuture(*future2);
decode(); //Prepare to start the decoder
if(ihsym==m_hsymStop) {
m_nTx30a=0;
m_nTx30b=0;
m_nTx60=0;
}
m_nTransmitted=0;
}
soundInThread.m_dataSinkBusy=false;
}
@ -433,33 +432,29 @@ void MainWindow::on_actionSettings_triggered()
DevSetup dlg(this);
dlg.m_myCall=m_myCall;
dlg.m_myGrid=m_myGrid;
dlg.m_idInt=m_idInt;
dlg.m_astroFont=m_astroFont;
dlg.m_myCallColor=m_myCallColor;
dlg.m_saveDir=m_saveDir;
dlg.m_azelDir=m_azelDir;
dlg.m_timeout=m_timeout;
dlg.m_fCal=m_fCal;
dlg.m_fAdd=m_fAdd;
dlg.m_network=m_network;
dlg.m_fs96000=m_fs96000;
dlg.m_udpPort=m_udpPort;
dlg.m_dB=m_dB;
dlg.initDlg();
if(dlg.exec() == QDialog::Accepted) {
m_myCall=dlg.m_myCall;
m_myGrid=dlg.m_myGrid;
m_idInt=dlg.m_idInt;
m_astroFont=dlg.m_astroFont;
m_myCallColor=dlg.m_myCallColor;
if(m_astro_window && m_astro_window->isVisible()) m_astro_window->setFontSize(m_astroFont);
ui->actionFind_Delta_Phi->setEnabled(false);
m_saveDir=dlg.m_saveDir;
m_azelDir=dlg.m_azelDir;
m_timeout=dlg.m_timeout;
m_fCal=dlg.m_fCal;
m_fAdd=dlg.m_fAdd;
soundInThread.setFadd(m_fAdd);
m_wide_graph_window->setFcal(m_fCal);
m_fs96000=dlg.m_fs96000;
m_network=dlg.m_network;
m_udpPort=dlg.m_udpPort;
m_dB=dlg.m_dB;
@ -595,9 +590,16 @@ void MainWindow::createStatusBar() //createStatusBar
lab4 = new QLabel("");
lab4->setAlignment(Qt::AlignHCenter);
lab4->setMinimumSize(QSize(50,10));
lab4->setMinimumSize(QSize(80,10));
lab4->setFrameStyle(QFrame::Panel | QFrame::Sunken);
statusBar()->addWidget(lab4);
lab5 = new QLabel("");
lab5->setAlignment(Qt::AlignHCenter);
lab5->setMinimumSize(QSize(100,10));
lab5->setFrameStyle(QFrame::Panel | QFrame::Sunken);
lab5->setStyleSheet("");
statusBar()->addWidget(lab5);
}
void MainWindow::on_tolSpinBox_valueChanged(int i) //tolSpinBox
@ -644,11 +646,11 @@ void MainWindow::on_actionOpen_triggered() //Open File
soundInThread.setMonitoring(m_monitoring);
QString fname;
fname=QFileDialog::getOpenFileName(this, "Open File", m_path,
"MAP65/QMAP Files (*.iq)");
"MAP65/QMAP Files (*.iq *.qm)");
if(fname != "") {
m_path=fname;
int i;
i=fname.indexOf(".iq") - 11;
i=qMax(fname.indexOf(".iq") - 11, fname.indexOf(".qm") - 11);
if(i>=0) {
lab1->setStyleSheet("QLabel{background-color: #66ff66}");
lab1->setText(" " + fname.mid(i,15) + " ");
@ -656,9 +658,13 @@ void MainWindow::on_actionOpen_triggered() //Open File
if(m_monitoring) on_monitorButton_clicked();
m_diskData=true;
int dbDgrd=0;
if(m_myCall=="K1JT" and m_idInt<0) dbDgrd=m_idInt;
*future1 = QtConcurrent::run(getfile, fname, false, dbDgrd);
watcher1->setFuture(*future1);
int iret=4;
if(m_path.indexOf(".iq")>0) {
getfile(fname, dbDgrd);
} else {
read_qm_(fname.toLatin1(), &iret, fname.length());
}
if(iret > 0) diskDat(iret);
}
}
@ -667,7 +673,11 @@ void MainWindow::on_actionOpen_next_in_directory_triggered() //Open Next
int i,len;
QFileInfo fi(m_path);
QStringList list;
list= fi.dir().entryList().filter(".iq");
if(m_path.indexOf(".iq")>0) {
list= fi.dir().entryList().filter(".iq");
} else {
list= fi.dir().entryList().filter(".qm");
}
for (i = 0; i < list.size()-1; ++i) {
if(i==list.size()-2) m_loopall=false;
len=list.at(i).length();
@ -676,16 +686,20 @@ void MainWindow::on_actionOpen_next_in_directory_triggered() //Open Next
QString fname=m_path.replace(n-len,len,list.at(i+1));
m_path=fname;
int i;
i=fname.indexOf(".iq") - 11;
i=qMax(fname.indexOf(".iq") - 11, fname.indexOf(".qm") - 11);
if(i>=0) {
lab1->setStyleSheet("QLabel{background-color: #66ff66}");
lab1->setText(" " + fname.mid(i,len) + " ");
}
m_diskData=true;
int dbDgrd=0;
if(m_myCall=="K1JT" and m_idInt<0) dbDgrd=m_idInt;
*future1 = QtConcurrent::run(getfile, fname, false, dbDgrd);
watcher1->setFuture(*future1);
int iret=4;
if(m_path.indexOf(".iq")>0) {
getfile(fname, dbDgrd);
} else {
read_qm_(fname.toLatin1(), &iret, fname.length());
}
if(iret > 0) diskDat(iret);
return;
}
}
@ -697,41 +711,54 @@ void MainWindow::on_actionDecode_remaining_files_in_directory_triggered()
on_actionOpen_next_in_directory_triggered();
}
void MainWindow::diskDat() //diskDat()
void MainWindow::diskDat(int iret) //diskDat()
{
int ia=0;
int ib=400;
if(iret==1) ib=202;
m_bDiskDatBusy=true;
double hsym;
//These may be redundant??
m_diskData=true;
datcom_.newdat=1;
hsym=2048.0*96000.0/11025.0; //Samples per JT65 half-symbol
for(int i=0; i<304; i++) { // Do the half-symbol FFTs
int k = i*hsym + 2048.5;
m_nTx30a=datcom_.ntx30a;
m_nTx30b=datcom_.ntx30b;
hsym=0.15*96000.0; //Samples per Q65-30x half-symbol or Q65-60x quarter-symbol
for(int i=ia; i<ib; i++) { // Do the half-symbol FFTs
int k = i*hsym + 0.5;
if(k > 60*96000) break;
dataSink(k);
qApp->processEvents(); // Allow the waterfall to update
while(m_decoderBusy) {
qApp->processEvents(); // Wait for an early decode to finish
}
}
m_bDiskDatBusy=false;
}
void MainWindow::diskWriteFinished() //diskWriteFinished
{
// qDebug() << "diskWriteFinished";
}
void MainWindow::decoderFinished() //diskWriteFinished
void MainWindow::decoderFinished()
{
m_startAnother=m_loopall;
ui->DecodeButton->setStyleSheet("");
decodeBusy(false);
decodes_.nQDecoderDone=1;
decodes_.kHzRequested=0;
if(m_diskData) decodes_.nQDecoderDone=2;
mem_qmap.lock();
decodes_.nWDecoderBusy=ipc_wsjtx[3]; //Prevent overwriting values
decodes_.nWTransmitting=ipc_wsjtx[4]; //written here by WSJT-X
m_bWTransmitting=decodes_.nWTransmitting>0;
memcpy((char*)ipc_wsjtx, &decodes_, sizeof(decodes_)); //Send decodes and flags to WSJT-X
mem_qmap.unlock();
QString t1;
t1=t1.asprintf(" %d ",decodes_.ndecodes);
t1=t1.asprintf(" %.1f s %d/%d ", 0.15*datcom2_.nhsym, decodes_.ndecodes, decodes_.ncand);
lab4->setText(t1);
QDateTime now=QDateTime::currentDateTimeUtc();
decodeBusy(false);
if(m_bDecodeAgain) {
datcom_.nhsym=390;
datcom_.nagain=1;
m_bDecodeAgain=false;
decode();
}
}
void MainWindow::on_actionDelete_all_iq_files_in_SaveDir_triggered()
@ -739,7 +766,7 @@ void MainWindow::on_actionDelete_all_iq_files_in_SaveDir_triggered()
int i;
QString fname;
int ret = QMessageBox::warning(this, "Confirm Delete",
"Are you sure you want to delete all *.iq files in\n" +
"Are you sure you want to delete all *.iq and *.qm files in\n" +
QDir::toNativeSeparators(m_saveDir) + " ?",
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
if(ret==QMessageBox::Yes) {
@ -750,6 +777,8 @@ void MainWindow::on_actionDelete_all_iq_files_in_SaveDir_triggered()
fname=*f;
i=(fname.indexOf(".iq"));
if(i==11) dir.remove(fname);
i=(fname.indexOf(".qm"));
if(i==11) dir.remove(fname);
}
}
}
@ -757,13 +786,25 @@ void MainWindow::on_actionDelete_all_iq_files_in_SaveDir_triggered()
void MainWindow::on_actionNone_triggered() //Save None
{
m_saveAll=false;
m_saveDecoded=false;
lab5->setStyleSheet("");
lab5->setText("");
}
// ### Implement "Save Last" here? ###
void MainWindow::on_actionSave_decoded_triggered()
{
m_saveDecoded=true;
m_saveAll=false;
lab5->setStyleSheet("QLabel{background-color: #ffff00}");
lab5->setText("Save decoded");
}
void MainWindow::on_actionSave_all_triggered() //Save All
void MainWindow::on_actionSave_all_triggered()
{
m_saveAll=true;
m_saveDecoded=false;
lab5->setStyleSheet("QLabel{background-color: #ffff00}");
lab5->setText("Save all");
}
void MainWindow::on_DecodeButton_clicked() //Decode request
@ -771,12 +812,23 @@ void MainWindow::on_DecodeButton_clicked() //Decode request
if(!m_decoderBusy) {
datcom_.newdat=0;
datcom_.nagain=1;
if(m_bAlso30 and m_nTx30a<5) {
datcom_.nhsym=200; //Decode the first half-minute
if(m_nTx30b<5) m_bDecodeAgain=true; //Queue up decoding of the seciond half minute
}
decode();
}
}
void MainWindow::freezeDecode(int n) //freezeDecode()
{
if(n==3) {
decodes_.kHzRequested=m_wide_graph_window->QSOfreq();
mem_qmap.lock();
ipc_wsjtx[5]=decodes_.kHzRequested;
mem_qmap.unlock();
return;
}
if(n==2) {
ui->tolSpinBox->setValue(5);
datcom_.ntol=m_tol;
@ -789,17 +841,17 @@ void MainWindow::freezeDecode(int n) //freezeDecode()
if(!m_decoderBusy) {
datcom_.nagain=1;
datcom_.newdat=0;
decode();
on_DecodeButton_clicked();
}
}
void MainWindow::decode() //decode()
{
//Don't attempt to decode if decoder is already busy, or if we transmitted for 10 s or more.
if(m_decoderBusy or m_nTransmitted>10) return;
if(m_decoderBusy) {
return; //Don't attempt decode if decoder already busy
}
decodeBusy(true);
QString fname=" ";
ui->DecodeButton->setStyleSheet(m_pbdecoding_style1);
if(datcom_.nagain==0 && (!m_diskData)) {
qint64 ms = QDateTime::currentMSecsSinceEpoch() % 86400000;
int imin=ms/60000;
@ -814,24 +866,11 @@ void MainWindow::decode() //decode()
datcom_.ndiskdat=0;
if(m_diskData) {
datcom_.ndiskdat=1;
int i0=m_path.indexOf(".iq");
int i0=qMax(m_path.indexOf(".iq"),m_path.indexOf(".qm"));
if(i0>0) {
// Compute self Doppler using the filename for Date and Time
int nyear=m_path.mid(i0-11,2).toInt()+2000;
int month=m_path.mid(i0-9,2).toInt();
int nday=m_path.mid(i0-7,2).toInt();
int nhr=m_path.mid(i0-4,2).toInt();
int nmin=m_path.mid(i0-2,2).toInt();
double uth=nhr + nmin/60.0;
int nfreq=(int)datcom_.fcenter;
int ndop00;
astrosub00_(&nyear, &month, &nday, &uth, &nfreq, m_myGrid.toLatin1(),&ndop00,6);
datcom_.ndop00=ndop00; //Send self Doppler to decoder, via datcom
fname=m_path.mid(i0-11,11);
}
}
datcom_.neme=0;
if(ui->actionOnly_EME_calls->isChecked()) datcom_.neme=1;
int ispan=int(m_wide_graph_window->fSpan());
if(ispan%2 == 1) ispan++;
@ -844,19 +883,12 @@ void MainWindow::decode() //decode()
datcom_.nfb=nfb;
datcom_.nfcal=m_fCal;
datcom_.nfshift=nfshift;
datcom_.mcall3=0;
if(m_call3Modified) datcom_.mcall3=1;
datcom_.ntimeout=m_timeout;
datcom_.ntol=m_tol;
datcom_.nxant=0;
m_nutc0=datcom_.nutc;
datcom_.junk_1=0;
datcom_.nfsample=96000;
if(!m_fs96000) datcom_.nfsample=95238;
datcom_.nxpol=0;
datcom_.nmode=10*m_modeQ65;
datcom_.nsave=m_nsave;
datcom_.nBaseSubmode=m_modeQ65;
datcom_.max_drift=ui->sbMaxDrift->value();
datcom_.offset=ui->sbOffset->value();
datcom_.ndepth=1;
if(datcom_.nagain==1) datcom_.ndepth=3;
@ -870,24 +902,64 @@ void MainWindow::decode() //decode()
} else {
memcpy(datcom_.datetime, m_dateTime.toLatin1(), 11);
}
datcom_.junk1=1234; //Cecck for these values in m65
datcom_.ntx30a=m_nTx30a;
datcom_.ntx30b=m_nTx30b;
datcom_.ntx60=m_nTx60;
datcom_.nsave=0;
if(m_saveDecoded) datcom_.nsave=1;
if(m_saveAll) datcom_.nsave=2;
datcom_.n60=m_n60;
datcom_.junk1=1234; //Check for these values in m65
datcom_.junk2=5678;
datcom_.bAlso30=m_bAlso30;
datcom_.ndop00=m_dop00;
datcom_.ndop58=m_dop58;
char *to = (char*) datcom2_.d4;
char *from = (char*) datcom_.d4;
memcpy(to, from, sizeof(datcom_));
datcom_.nagain=0;
datcom_.ndiskdat=0;
m_call3Modified=false;
memcpy(to, from, sizeof(datcom_)); //Copy the full datcom_ common block into datcom2_
decodes_.ndecodes=0;
datcom_.ndiskdat=0;
if((!m_bAlso30 and (datcom2_.nhsym==330)) or (m_bAlso30 and (datcom2_.nhsym==130))) {
decodes_.ndecodes=0; //Start the decode cycle with a clean slate
m_fetched=0;
}
decodes_.ncand=0;
decodes_.nQDecoderDone=0;
m_fetched=0;
int itimer=0;
m_decoder_start_time=QDateTime::currentDateTimeUtc();
watcher3.setFuture(QtConcurrent::run (std::bind (q65c_, &itimer)));
m_saveFileName="NoSave";
if(!m_diskData) {
QDateTime t = QDateTime::currentDateTimeUtc();
m_dateTime=t.toString("yyMMdd_hhmm");
QDir dir(m_saveDir);
if (!dir.exists()) dir.mkpath(".");
m_saveFileName=m_saveDir + "/" + m_dateTime + ".qm";
}
bool bSkipDecode=false;
//No need to call decoder for first half, if we transmitted in the first half:
if((datcom2_.nhsym<=200) and (m_nTx30a>5)) bSkipDecode=true;
//No need to call decoder at 330, if we transmitted in 2nd half:
if((datcom2_.nhsym==330) and (m_nTx30b>5)) bSkipDecode=true;
//No need to call decoder at all, if we transmitted in a 60 s submode.
if(m_nTx60>5) bSkipDecode=true;
if(bSkipDecode) {
decodeBusy(false);
return;
}
int len1=m_saveFileName.length();
int len2=m_revision.length();
memcpy(savecom_.revision, m_revision.toLatin1(), len2);
memcpy(savecom_.saveFileName, m_saveFileName.toLatin1(),len1);
ui->actionExport_wav_file_at_fQSO->setEnabled(m_diskData);
watcher3.setFuture(QtConcurrent::run (q65c_));
decodeBusy(true);
}
@ -895,6 +967,7 @@ void MainWindow::on_EraseButton_clicked()
{
ui->decodedTextBrowser->clear();
lab4->clear();
m_nline=0;
}
@ -902,6 +975,8 @@ void MainWindow::decodeBusy(bool b) //decodeBusy()
{
m_decoderBusy=b;
ui->DecodeButton->setEnabled(!b);
if(!b) ui->DecodeButton->setStyleSheet("");
if(b) ui->DecodeButton->setStyleSheet(m_pbdecoding_style1);
ui->actionOpen->setEnabled(!b);
ui->actionOpen_next_in_directory->setEnabled(!b);
ui->actionDecode_remaining_files_in_directory->setEnabled(!b);
@ -923,7 +998,7 @@ void MainWindow::guiUpdate()
m_wide_graph_window->updateFreqLabel();
if(m_startAnother) {
if(m_startAnother and !m_bDiskDatBusy) {
m_startAnother=false;
on_actionOpen_next_in_directory_triggered();
}
@ -934,30 +1009,59 @@ void MainWindow::guiUpdate()
QString t=QString::fromLatin1(decodes_.result[m_fetched]);
if(m_UTC0!="" and m_UTC0!=t.left(4)) {
t1="-";
ui->decodedTextBrowser->append(t1.repeated(56));
ui->decodedTextBrowser->append(t1.repeated(60));
m_nline++;
QTextCursor cursor(ui->decodedTextBrowser->document()->findBlockByLineNumber(m_nline-1));
QTextBlockFormat f = cursor.blockFormat();
f.setBackground(QBrush(Qt::white));
cursor.setBlockFormat(f);
}
m_UTC0=t.left(4);
ui->decodedTextBrowser->append(t.trimmed());
t=t.trimmed();
ui->decodedTextBrowser->append(t);
m_fetched++;
m_nline++;
QTextCursor cursor(ui->decodedTextBrowser->document()->findBlockByLineNumber(m_nline-1));
QTextBlockFormat f = cursor.blockFormat();
f.setBackground(QBrush(Qt::white));
if(t.mid(36,2)=="30") f.setBackground(QBrush(Qt::yellow));
if(t.indexOf(m_myCall)>10 and m_myCallColor==1) f.setBackground(QColor(255,102,102));
if(t.indexOf(m_myCall)>10 and m_myCallColor==2) f.setBackground(QBrush(Qt::green));
if(t.indexOf(m_myCall)>10 and m_myCallColor==3) f.setBackground(QBrush(Qt::cyan));
cursor.setBlockFormat(f);
}
}
t1="";
t1=t1.asprintf("%.3f",datcom_.fcenter);
ui->labFreq->setText(t1);
if(nsec != m_sec0) { //Once per second
// qDebug() << "AAA" << nsec << m_fAdd;
static int n60z=99;
int n60=nsec%60;
m_n60=nsec%60;
// See if WSJT-X is transmitting
int itest[5];
mem_qmap.lock();
memcpy(&itest, (char*)ipc_wsjtx, 20);
mem_qmap.unlock();
if(itest[4]==1) m_nTransmitted++;
// qDebug() << "AAA" << n60 << itest[0] << itest[1] << itest[2] << itest[3] << itest[4]
// << m_nTransmitted;
if(n60<n60z) m_nTransmitted=0;
n60z=n60;
if(itest[4]>0) {
m_WSJTX_TRperiod=itest[4];
m_bWTransmitting=true;
if(m_WSJTX_TRperiod==30 and m_n60<30) m_nTx30a++;
if(m_WSJTX_TRperiod==30 and m_n60>=30) m_nTx30b++;
if(m_WSJTX_TRperiod==60) m_nTx60++;
} else {
m_bWTransmitting=false;
}
if((m_n60<n60z) and !m_diskData) {
m_nTx30a=0;
m_nTx30b=0;
m_nTx60=0;
}
n60z=m_n60;
if(m_pctZap>30.0) {
lab2->setStyleSheet("QLabel{background-color: #ff0000}");
@ -965,8 +1069,7 @@ void MainWindow::guiUpdate()
lab2->setStyleSheet("");
}
if(m_monitoring) {
if(m_monitoring and !m_bWTransmitting) {
lab1->setStyleSheet("QLabel{background-color: #00ff00}");
m_nrx=soundInThread.nrx();
khsym=soundInThread.mhsym();
@ -985,26 +1088,30 @@ void MainWindow::guiUpdate()
lab1->setStyleSheet("QLabel{background-color: #ffc0cb}");
}
lab1->setText("Receiving " + t);
} else if (!m_diskData) {
} else if(m_bWTransmitting) {
lab1->setStyleSheet("QLabel{background-color: #ffff00}"); //Yellow
lab1->setText("WSJT-X Transmitting");
} else if(!m_diskData) {
lab1->setStyleSheet("");
lab1->setText("");
}
datcom_.mousefqso=m_wide_graph_window->QSOfreq();
QDateTime t = QDateTime::currentDateTimeUtc();
int fQSO=m_wide_graph_window->QSOfreq();
m_astro_window->astroUpdate(t, m_myGrid, m_hisGrid, fQSO, m_setftx,
m_txFreq, m_azelDir, m_xavg);
m_setftx=0;
m_astro_window->astroUpdate(t, m_myGrid, m_azelDir, m_xavg);
QString utc = t.date().toString(" yyyy MMM dd \n") + t.time().toString();
ui->labUTC->setText(utc);
m_hsym0=khsym;
m_sec0=nsec;
if(m_n60==0) m_dop00=datcom_.ndop00;
if(m_n60==58) m_dop58=datcom_.ndop00;
}
}
void MainWindow::on_actionQ65A_triggered()
{
m_modeQ65=1;
ui->actionAlso_Q65_30x->setText("Also Q65-30A");
lab3->setStyleSheet("QLabel{background-color: #ffb266}");
lab3->setText("Q65-60A");
}
@ -1012,6 +1119,7 @@ void MainWindow::on_actionQ65A_triggered()
void MainWindow::on_actionQ65B_triggered()
{
m_modeQ65=2;
ui->actionAlso_Q65_30x->setText("Also Q65-30A");
lab3->setStyleSheet("QLabel{background-color: #b2ff66}");
lab3->setText("Q65-60B");
}
@ -1019,6 +1127,7 @@ void MainWindow::on_actionQ65B_triggered()
void MainWindow::on_actionQ65C_triggered()
{
m_modeQ65=3;
ui->actionAlso_Q65_30x->setText("Also Q65-30B");
lab3->setStyleSheet("QLabel{background-color: #66ffff}");
lab3->setText("Q65-60C");
}
@ -1026,13 +1135,15 @@ void MainWindow::on_actionQ65C_triggered()
void MainWindow::on_actionQ65D_triggered()
{
m_modeQ65=4;
lab3->setStyleSheet("QLabel{background-color: #b266ff}");
ui->actionAlso_Q65_30x->setText("Also Q65-30C");
lab3->setStyleSheet("QLabel{background-color: #d9b3ff}");
lab3->setText("Q65-60D");
}
void MainWindow::on_actionQ65E_triggered()
{
m_modeQ65=5;
ui->actionAlso_Q65_30x->setText("Also Q65-30D");
lab3->setStyleSheet("QLabel{background-color: #ff66ff}");
lab3->setText("Q65-60E");
}
@ -1069,3 +1180,35 @@ void MainWindow::on_actionQuick_Start_Guide_to_WSJT_X_2_7_and_QMAP_triggered()
QDesktopServices::openUrl (QUrl {"https://wsjt.sourceforge.io/Quick_Start_WSJT-X_2.7_QMAP.pdf"});
}
void MainWindow::on_actionAlso_Q65_30x_toggled(bool b)
{
m_bAlso30=b;
}
void MainWindow::on_sbMaxDrift_valueChanged(int n)
{
if(n==0) ui->sbMaxDrift->setStyleSheet("");
if(n==5) ui->sbMaxDrift->setStyleSheet("QSpinBox { background-color: #ffff82; }");
if(n>=10) ui->sbMaxDrift->setStyleSheet("QSpinBox { background-color: #ffff00; }");
}
void MainWindow::on_actionExport_wav_file_at_fQSO_triggered()
{
datcom_.newdat=0;
datcom_.nagain=2;
decode();
}
void MainWindow::on_actionExport_wav_file_at_fQSO_30a_triggered()
{
datcom_.newdat=0;
datcom_.nagain=3;
decode();
}
void MainWindow::on_actionExport_wav_file_at_fQSO_30b_triggered()
{
datcom_.newdat=0;
datcom_.nagain=4;
decode();}

View File

@ -39,8 +39,7 @@ public slots:
void showSoundInError(const QString& errorMsg);
void showStatusMessage(const QString& statusMsg);
void dataSink(int k);
void diskDat();
void diskWriteFinished();
void diskDat(int iret);
void decoderFinished();
void freezeDecode(int n);
void guiUpdate();
@ -82,6 +81,14 @@ private slots:
void on_actionQ65E_triggered();
void on_actionQuick_Start_Guide_to_Q65_triggered();
void on_actionQuick_Start_Guide_to_WSJT_X_2_7_and_QMAP_triggered();
void on_actionAlso_Q65_30x_toggled(bool b);
void on_sbMaxDrift_valueChanged(int arg1);
void on_actionSave_decoded_triggered();
void on_actionExport_wav_file_at_fQSO_triggered();
void on_actionExport_wav_file_at_fQSO_30a_triggered();
void on_actionExport_wav_file_at_fQSO_30b_triggered();
private:
Ui::MainWindow *ui;
@ -90,16 +97,11 @@ private:
QScopedPointer<Astro> m_astro_window;
QScopedPointer<WideGraph> m_wide_graph_window;
QPointer<QTimer> m_gui_timer;
qint32 m_idInt;
qint32 m_waterfallAvg;
qint32 m_DF;
qint32 m_tol;
qint32 m_QSOfreq0;
qint32 m_astroFont;
qint32 m_timeout;
qint32 m_fCal;
qint32 m_txFreq;
qint32 m_setftx;
qint32 m_sec0;
qint32 m_nutc0;
qint32 m_nrx;
@ -107,15 +109,20 @@ private:
qint32 m_paInDevice;
qint32 m_udpPort;
qint32 m_NBslider;
qint32 m_nsum;
qint32 m_nsave;
qint32 m_TRperiod;
qint32 m_modeQ65;
qint32 m_dB;
qint32 m_fetched=0;
qint32 m_hsymStop=302;
qint32 m_nTransmitted=0;
qint32 m_hsymStop=390; //390*0.15 = 58.5 s
qint32 m_nTx30a=0;
qint32 m_nTx30b=0;
qint32 m_nTx60=0;
qint32 m_nDoubleClicked=0;
qint32 m_nline=0;
qint32 m_WSJTX_TRperiod=0;
qint32 m_dop00=0;
qint32 m_dop58=0;
qint32 m_n60;
double m_fAdd;
double m_xavg;
@ -125,21 +132,20 @@ private:
bool m_loopall;
bool m_decoderBusy=false;
bool m_restart;
bool m_call3Modified;
bool m_startAnother;
bool m_saveAll;
bool m_onlyEME;
bool m_kb8rq;
bool m_saveDecoded;
bool m_NB;
bool m_fs96000;
bool m_decode_called=false;
bool m_bAlso30=true;
bool m_bDiskDatBusy=false;
bool m_bWTransmitting=false;
bool m_bDecodeAgain=false;
float m_gainx;
float m_gainy;
float m_phasex;
float m_phasey;
float m_pctZap;
int m_myCallColor;
QRect m_wideGraphGeom;
QLabel* lab1; // labels in status bar
@ -152,15 +158,8 @@ private:
QMessageBox msgBox0;
QFuture<void>* future1;
QFuture<void>* future2;
QFutureWatcher<void>* watcher1;
QFutureWatcher<void>* watcher2;
QFutureWatcher<void> watcher3; //For decoder
QDateTime m_decoder_start_time;
QString m_path;
QString m_pbdecoding_style1;
QString m_pbmonitor_style;
@ -175,13 +174,12 @@ private:
QString m_dateTime;
QString m_mode;
QString m_UTC0="";
QString m_revision;
QString m_saveFileName;
QDateTime m_dateTimeSeqStart; //Nominal start time of Rx sequence about to be decoded
QHash<QString,bool> m_worked;
SignalMeter *xSignalMeter;
SignalMeter *ySignalMeter;
SoundInThread soundInThread; //Instantiate the audio threads
//---------------------------------------------------- private functions
@ -194,7 +192,7 @@ private:
};
extern void getfile(QString fname, bool xpol, int idInt);
extern void savetf2(QString fname, bool xpol);
extern void save_iq(QString fname);
extern int killbyname(const char* progName);
extern "C" {
@ -206,7 +204,18 @@ extern "C" {
void astrosub00_ (int* nyear, int* month, int* nday, double* uth, int* nfreq,
const char* mygrid, int* ndop00, int len1);
void q65c_(int* itimer);
void q65c_();
void all_done_();
void zaptx_(float d4[], int* k0, int* k);
void save_qm_(const char* fname, const char* prog_id, const char* mycall, const char* mygrid,
float d4[], int* ntx30a, int* ntx30b, double* fcenter, int* nutc,
int* dop00, int* dop58, int len1, int len2, int len3, int len4);
void read_qm_(const char* fname, int* iret, int len);
}
#endif // MAINWINDOW_H

View File

@ -24,8 +24,8 @@
</property>
<property name="maximumSize">
<size>
<width>640</width>
<height>1080</height>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="windowTitle">
@ -40,8 +40,8 @@
<layout class="QFormLayout" name="formLayout">
<item row="1" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="3" colspan="2">
<widget class="QPushButton" name="EraseButton">
<item row="0" column="5">
<widget class="QPushButton" name="DecodeButton">
<property name="minimumSize">
<size>
<width>50</width>
@ -49,26 +49,7 @@
</size>
</property>
<property name="text">
<string>&amp;Erase</string>
</property>
</widget>
</item>
<item row="1" column="4" colspan="2">
<widget class="QSpinBox" name="sbMaxDrift">
<property name="toolTip">
<string>Maximum drift rate in units of symbol rate per transmissiion.</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="prefix">
<string>Max Drift </string>
</property>
<property name="maximum">
<number>50</number>
</property>
<property name="singleStep">
<number>5</number>
<string>&amp;Decode</string>
</property>
</widget>
</item>
@ -96,95 +77,34 @@
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QPushButton" name="DecodeButton">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
<item row="3" column="4" colspan="2">
<widget class="QSlider" name="NBslider">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Decode</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QCheckBox" name="NBcheckBox">
<property name="text">
<string>NB</string>
</property>
</widget>
</item>
<item row="1" column="1" rowspan="2">
<widget class="QLabel" name="labUTC">
<property name="minimumSize">
<size>
<width>140</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>165</width>
<height>60</height>
</size>
</property>
<property name="font">
<font>
<pointsize>16</pointsize>
</font>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="text">
<string> 2023 Feb 02
01:23:45 </string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="3">
<widget class="QFrame" name="xMeterFrame">
<property name="minimumSize">
<size>
<width>50</width>
<height>150</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="monitorButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>&amp;Monitor</string>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>40</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
@ -274,33 +194,141 @@
</layout>
</item>
<item row="2" column="4" colspan="2">
<widget class="QSlider" name="NBslider">
<property name="enabled">
<bool>false</bool>
<widget class="QSpinBox" name="sbOffset">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select offset announced by calling station, or use commonly used value for the band in use. Manually set WSJT-X TX and RX offset to same value.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="suffix">
<string> Hz</string>
</property>
<property name="prefix">
<string>Offset </string>
</property>
<property name="minimum">
<number>500</number>
</property>
<property name="maximum">
<number>2000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
<property name="value">
<number>1500</number>
</property>
</widget>
</item>
<item row="0" column="3" colspan="2">
<widget class="QPushButton" name="EraseButton">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>&amp;Erase</string>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="4">
<widget class="QFrame" name="xMeterFrame">
<property name="minimumSize">
<size>
<width>50</width>
<height>150</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
<item row="1" column="1" rowspan="3">
<widget class="QLabel" name="labUTC">
<property name="minimumSize">
<size>
<width>140</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>165</width>
<height>60</height>
</size>
</property>
<property name="font">
<font>
<pointsize>16</pointsize>
</font>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="text">
<string> 2023 Feb 02
01:23:45 </string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="monitorButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="minimum">
<number>0</number>
<property name="text">
<string>&amp;Monitor</string>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QCheckBox" name="NBcheckBox">
<property name="text">
<string>NB</string>
</property>
</widget>
</item>
<item row="1" column="4" colspan="2">
<widget class="QSpinBox" name="sbMaxDrift">
<property name="toolTip">
<string>Maximum drift rate in units of symbol rate per transmission.</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="prefix">
<string>Max Drift </string>
</property>
<property name="maximum">
<number>100</number>
<number>50</number>
</property>
<property name="value">
<number>40</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
<property name="singleStep">
<number>5</number>
</property>
</widget>
</item>
@ -309,7 +337,7 @@
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
@ -322,31 +350,31 @@
</property>
<property name="maximumSize">
<size>
<width>620</width>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="title">
<string> UTC Frx Fsked DT dB Message</string>
<string> UTC Frx Fsked DT dB Q65- Message</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0" colspan="2">
<widget class="DisplayText" name="decodedTextBrowser">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Expanding">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>500</width>
<height>100</height>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>610</width>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
@ -370,9 +398,8 @@
</property>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;meta charset=&quot;utf-8&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
hr { height: 1px; border-width: 0; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Courier New'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
@ -394,7 +421,7 @@ hr { height: 1px; border-width: 0; }
<x>0</x>
<y>0</y>
<width>640</width>
<height>22</height>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
@ -407,6 +434,9 @@ hr { height: 1px; border-width: 0; }
<addaction name="separator"/>
<addaction name="actionDelete_all_iq_files_in_SaveDir"/>
<addaction name="separator"/>
<addaction name="actionExport_wav_file_at_fQSO"/>
<addaction name="actionExport_wav_file_at_fQSO_30a"/>
<addaction name="actionExport_wav_file_at_fQSO_30b"/>
<addaction name="actionSettings"/>
<addaction name="separator"/>
<addaction name="actionExit"/>
@ -426,12 +456,15 @@ hr { height: 1px; border-width: 0; }
<addaction name="actionWide_Waterfall"/>
<addaction name="separator"/>
<addaction name="menuWaterfall_palette"/>
<addaction name="separator"/>
<addaction name="continuous_waterfall"/>
</widget>
<widget class="QMenu" name="menuSave">
<property name="title">
<string>Save</string>
</property>
<addaction name="actionNone"/>
<addaction name="actionSave_decoded"/>
<addaction name="actionSave_all"/>
</widget>
<widget class="QMenu" name="menuHelp">
@ -453,6 +486,8 @@ hr { height: 1px; border-width: 0; }
<addaction name="actionQ65C"/>
<addaction name="actionQ65D"/>
<addaction name="actionQ65E"/>
<addaction name="separator"/>
<addaction name="actionAlso_Q65_30x"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuView"/>
@ -476,7 +511,7 @@ hr { height: 1px; border-width: 0; }
</action>
<action name="actionAbout">
<property name="text">
<string> About QMAP</string>
<string>About QMAP</string>
</property>
<property name="shortcut">
<string>Ctrl+F1</string>
@ -528,7 +563,7 @@ hr { height: 1px; border-width: 0; }
</action>
<action name="actionDelete_all_iq_files_in_SaveDir">
<property name="text">
<string>Delete all *.iq files in SaveDir</string>
<string>Delete all *.iq and *.qm files in SaveDir</string>
</property>
</action>
<action name="actionErase_Band_Map_and_Messages">
@ -730,7 +765,7 @@ hr { height: 1px; border-width: 0; }
<bool>true</bool>
</property>
<property name="text">
<string>Q65A</string>
<string>Q65-60A</string>
</property>
</action>
<action name="actionQ65B">
@ -738,7 +773,7 @@ hr { height: 1px; border-width: 0; }
<bool>true</bool>
</property>
<property name="text">
<string>Q65B</string>
<string>Q65-60B</string>
</property>
</action>
<action name="actionQ65C">
@ -749,7 +784,7 @@ hr { height: 1px; border-width: 0; }
<bool>true</bool>
</property>
<property name="text">
<string>Q65C</string>
<string>Q65-60C</string>
</property>
</action>
<action name="actionQ65D">
@ -757,7 +792,7 @@ hr { height: 1px; border-width: 0; }
<bool>true</bool>
</property>
<property name="text">
<string>Q65D</string>
<string>Q65-60D</string>
</property>
</action>
<action name="actionQ65E">
@ -765,7 +800,7 @@ hr { height: 1px; border-width: 0; }
<bool>true</bool>
</property>
<property name="text">
<string>Q65E</string>
<string>Q65-60E</string>
</property>
</action>
<action name="actionQSG_Q65">
@ -773,16 +808,6 @@ hr { height: 1px; border-width: 0; }
<string>Quick-Start Guide to Q65</string>
</property>
</action>
<action name="actionQSG_MAP65_v3">
<property name="text">
<string>Quick-Start Guide to WSJT-X 2.5.0 and MAP65 3.0</string>
</property>
</action>
<action name="actionQ65_Sensitivity_in_MAP65_3_0">
<property name="text">
<string>Q65 Sensitivity in MAP65 3.0</string>
</property>
</action>
<action name="actionRelease_Notes">
<property name="text">
<string>Release Notes</string>
@ -806,6 +831,48 @@ hr { height: 1px; border-width: 0; }
<string>Quick-Start Guide to Q65</string>
</property>
</action>
<action name="continuous_waterfall">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Continuous Waterfall</string>
</property>
</action>
<action name="actionAlso_Q65_30x">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Also Q65-30x</string>
</property>
</action>
<action name="actionSave_decoded">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Save decoded</string>
</property>
</action>
<action name="actionExport_wav_file_at_fQSO">
<property name="text">
<string>Export .wav file at fQSO (60 s)</string>
</property>
</action>
<action name="actionExport_wav_file_at_fQSO_30b">
<property name="text">
<string>Export .wav file at fQSO (30 s, second part)</string>
</property>
</action>
<action name="actionExport_wav_file_at_fQSO_30a">
<property name="text">
<string>Export .wav file at fQSO (30 s, first part)</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
@ -824,8 +891,8 @@ hr { height: 1px; border-width: 0; }
<slot>update()</slot>
<hints>
<hint type="sourcelabel">
<x>269</x>
<y>255</y>
<x>287</x>
<y>281</y>
</hint>
<hint type="destinationlabel">
<x>126</x>

View File

@ -602,6 +602,7 @@ void CPlotter::mousePressEvent(QMouseEvent *event) //mousePressEvent
if(y < h+30) { // Wideband waterfall
if(button==1) {
setFQSO(x,false);
if(event->modifiers() & Qt::ControlModifier) emit freezeDecode1(3);
}
if(button==2 and !m_bLockTxRx) {
if(x<0) x=0; // x is pixel number

View File

@ -15,37 +15,43 @@ extern "C"
struct
{
double d8[60*96000]; //This is "common/datcom/..." in fortran
float ss[322*NFFT];
float savg[NFFT];
double fcenter;
int nutc;
float ss[400*NFFT];
float savg[NFFT]; //Avg spectra at 0,45,90,135 deg pol
double fcenter; //Center freq from Linrad (MHz)
int nutc; //UTC as integer, HHMM
float fselected; //Selected frequency for nagain decodes
int mousedf; //User-selected DF
int mousefqso; //User-selected QSO freq (kHz)
int nagain; //1 ==> decode only at fQSO +/- Tol
int ndepth; //How much hinted decoding to do?
int ndiskdat; //1 ==> data read from *.tf2 or *.iq file
int neme; //Hinted decoding tries only for EME calls
int ndiskdat; //1 ==> data read from *.iq file
int ntx60; //Number of seconds transmitted in Q65-60x
int newdat; //1 ==> new data, must do long FFT
int nfa; //Low decode limit (kHz)
int nfb; //High decode limit (kHz)
int nfcal; //Frequency correction, for calibration (Hz)
int nfshift; //Shift of displayed center freq (kHz)
int mcall3; //1 ==> CALL3.TXT has been modified
int ntimeout; //Max for timeouts in Messages and BandMap
int ntx30a; //Number of seconds transmitted in first half minute , Q65-30x
int ntx30b; //Number of seconds transmitted in second half minute, Q65-30x
int ntol; //+/- decoding range around fQSO (Hz)
int nxant; //1 ==> add 45 deg to measured pol angle
int junk_1; //Flags to control log files
int junk5; //
int junk4; //
int nfsample; //Input sample rate
int nxpol; //1 if using xpol antennas, 0 otherwise
int mode65; //JT65 sub-mode: A=1, B=2, C=4
int nfast; //1No longer used
int junk3; //
int nBaseSubmode; //Base submode for Q65-60x (aka m_modeQ65)
int ndop00; //EME Self Doppler
int nsave; //Number of s3(64,63) spectra saved
int max_drift; //Maximum Q65 drift: units symbol_rate/TxT
int offset; //Offset in Hz
int nhsym; //Number of available JT65 half-symbols
char mycall[12];
char mygrid[6];
char hiscall[12];
char hisgrid[6];
char datetime[20];
int junk1; //Used to test extent of copy to shared memory
int junk2;
bool bAlso30; //Process for 30-second submode as well as 60-second
} datcom_;
}
@ -208,12 +214,10 @@ void SoundInThread::inputUDP()
// If buffer will not overflow, move data into datcom_
if ((k+iz) <= 60*96000) {
int nsam=-1;
recvpkt_(&nsam, &b.iblk, &b.nrx, &k, b.d8, b.d8);
recvpkt_(&nsam, &b.iblk, &b.nrx, &k, b.d8, b.d8, &m_dB);
datcom_.fcenter=b.cfreq + m_fAdd;
// qDebug() << "bb" << b.cfreq << m_fAdd << datcom_.fcenter;
}
m_hsym=(k-2048)*11025.0/(2048.0*m_rate);
m_hsym=(k-2048)/14400; //14400 = 0.15 * 96000
if(m_hsym != nhsym0) {
if(!m_dataSinkBusy) {
m_dataSinkBusy=true;

View File

@ -67,7 +67,8 @@ private:
};
extern "C" {
void recvpkt_(int* nsam, quint16* iblk, qint8* nrx, int* k, double s1[], double s2[]);
void recvpkt_(int* nsam, quint16* iblk, qint8* nrx, int* k,
double s1[], double s2[], int* ndb);
}
#endif // SOUNDIN_H

View File

@ -318,7 +318,7 @@
<message>
<location filename="../widgets/colorhighlighting.ui" line="150"/>
<source>New Call</source>
<translation>Nou Indicatiu</translation>
<translation>Indicatiu nou</translation>
</message>
<message>
<location filename="../widgets/colorhighlighting.ui" line="157"/>
@ -2238,12 +2238,12 @@ Error(%2): %3</translation>
<message>
<location filename="../widgets/mainwindow.ui" line="1683"/>
<source>Maximum drift rate in units of symbol rate per transmission.</source>
<translation type="unfinished"></translation>
<translation>Taxa de deriva màxima en unitats de taxa de símbols per transmissió.</translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="1686"/>
<source>Max Drift </source>
<translation type="unfinished"></translation>
<translation>Deriva màxima </translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="2604"/>
@ -3658,7 +3658,7 @@ La llista es pot mantenir a la configuració (F2).</translation>
<message>
<location filename="../widgets/mainwindow.ui" line="3429"/>
<source>Quick-Start Guide to WSJT-X 2.5.0 and MAP65 3.0</source>
<translation type="unfinished"></translation>
<translation>Guia d&apos;inici ràpid de WSJT-X 2.5.0 i MAP65 3.0</translation>
</message>
<message>
<location filename="../widgets/mainwindow.cpp" line="258"/>
@ -3685,7 +3685,7 @@ La llista es pot mantenir a la configuració (F2).</translation>
<message>
<location filename="../widgets/mainwindow.cpp" line="523"/>
<source>Scanned ADIF log, %1 worked-before records created. CTY: %2</source>
<translation>Log ADIF escanejat, %1 funcionava abans de la creació de registres</translation>
<translation>Log ADIF escanejat, %1 funcionava abans de la creació de registres. CTY: %2</translation>
</message>
<message>
<location filename="../widgets/mainwindow.cpp" line="631"/>

View File

@ -2480,17 +2480,17 @@ Error(%2): %3</translation>
<message>
<location filename="../widgets/mainwindow.ui" line="1683"/>
<source>Maximum drift rate in units of symbol rate per transmission.</source>
<translation type="unfinished"></translation>
<translation>Tasa de deriva máxima en unidades de tasa de símbolos por transmisión.</translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="1686"/>
<source>Max Drift </source>
<translation type="unfinished"></translation>
<translation>Máxima deriva </translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="3416"/>
<source>Quick-Start Guide to Q65</source>
<translation>Guía de inicio rápido de Q65</translation>
<translation>Guía de inicio rápido de Q65 (inglés)</translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="3424"/>
@ -2500,7 +2500,7 @@ Error(%2): %3</translation>
<message>
<location filename="../widgets/mainwindow.ui" line="3429"/>
<source>Quick-Start Guide to WSJT-X 2.5.0 and MAP65 3.0</source>
<translation type="unfinished"></translation>
<translation>Guía de inicio rápido para WSJT-X 2.5.0 y MAP65 3.0 (inglés)</translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="1588"/>
@ -2703,7 +2703,7 @@ Amarillo cuando esta muy bajo.</translation>
<message>
<location filename="../widgets/mainwindow.ui" line="876"/>
<source>&amp;Lookup</source>
<translation>Buscar</translation>
<translation>Buscar (&amp;L)</translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="988"/>
@ -3044,7 +3044,7 @@ No está disponible para los titulares de indicativo no estándar.</translatorco
<location filename="../widgets/mainwindow.ui" line="1215"/>
<source>Best S+P</source>
<translatorcomment>El mejor S+P </translatorcomment>
<translation>Mejor S+P (&amp;B)</translation>
<translation>Mejor S+P</translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="1225"/>
@ -3181,7 +3181,8 @@ Cuando no está marcado, puede verse los resultados de la calibración.</transla
Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</source>
<translatorcomment>Enviar este mensaje en el siguiente intervalo de transmisión.
Haz doble clic para alternar el uso del mensaje TX1 para iniciar un QSO con una estación (no está permitido para titulares de indicativos compuestos de tipo 1).</translatorcomment>
<translation>Enviar este mensaje en el siguiente intervalo de TX. Doble clic para alternar el uso del mensaje TX1 para iniciar un QSO con una estación (no está permitido para titulares de indicativos compuestos de tipo 1).</translation>
<translation>Enviar este mensaje en el siguiente intervalo de TX.
Doble clic para alternar el uso del mensaje TX1 para iniciar un QSO con una estación (no está permitido para titulares de indicativos compuestos de tipo 1).</translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="1826"/>
@ -3246,7 +3247,8 @@ Haz doble clic para alternar el uso del mensaje TX1 para iniciar un QSO con una
<location filename="../widgets/mainwindow.ui" line="2035"/>
<source>Send this message in next Tx interval
Double-click to reset to the standard 73 message</source>
<translation>Enviar este mensaje en el siguiente intervalo de TX. Doble clic para restablecer el mensaje 73 estándar.</translation>
<translation>Enviar este mensaje en el siguiente intervalo de TX.
Doble clic para restablecer el mensaje 73 estándar.</translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="2045"/>
@ -3300,7 +3302,9 @@ RR73 messages should only be used when you are reasonably confident that no mess
<translatorcomment>Cambia a este mensaje de TX AHORA.
Haz doble clic para alternar entre los mensajes RRR y RR73 en TX4 (no está permitido para titulares de indicativos compuestos de tipo 2).
Los mensajes RR73 solo deben usarse cuando esté razonablemente seguro de que no se requerirán repeticiones de mensajes.</translatorcomment>
<translation>Cambiar a este mensaje de TX AHORA. Doble clic para alternar entre los mensajes RRR y RR73 en TX4 (no está permitido para titulares de indicativos compuestos de tipo 2). Los mensajes RR73 solo deben usarse cuando esté razonablemente seguro de que no se requerirán repeticiones de mensajes.</translation>
<translation>Cambiar a este mensaje de TX AHORA.
Doble clic para alternar entre los mensajes RRR y RR73 en TX4 (no está permitido para titulares de indicativos compuestos de tipo 2).
Los mensajes RR73 solo deben usarse cuando esté razonablemente seguro de que no se requerirán repeticiones de mensajes.</translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="1951"/>
@ -3397,7 +3401,7 @@ predefinida. La lista se puede modificar en &quot;Ajustes&quot; (F2).</translati
<message>
<location filename="../widgets/mainwindow.ui" line="3358"/>
<source>Quick-Start Guide to FST4 and FST4W</source>
<translation>Guía de inicio rápido a FST4 y FST4W</translation>
<translation>Guía de inicio rápido a FST4 y FST4W (inglés)</translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="3384"/>
@ -4239,7 +4243,7 @@ predefinida. La lista se puede modificar en &quot;Ajustes&quot; (F2).</translati
<location filename="../widgets/mainwindow.cpp" line="523"/>
<source>Scanned ADIF log, %1 worked-before records created. CTY: %2</source>
<translatorcomment>Log ADIF escaneado, %1 funcionaba antes de la creación de registros</translatorcomment>
<translation>Log ADIF escaneado, %1 registros trabajados B4 creados</translation>
<translation>Log ADIF escaneado, %1 registros trabajados B4 creados. CTY: %2</translation>
</message>
<message>
<location filename="../widgets/mainwindow.cpp" line="631"/>
@ -4912,7 +4916,7 @@ ya está en CALL3.TXT, ¿desea reemplazarlo?</translation>
<location filename="../widgets/mainwindow.cpp" line="8593"/>
<source>Confirm Reset</source>
<translatorcomment>Confirmar reinicio</translatorcomment>
<translation>Confirmar restablecer</translation>
<translation>Confirmar borrado</translation>
</message>
<message>
<location filename="../widgets/mainwindow.cpp" line="6841"/>
@ -5354,7 +5358,7 @@ Error(%2): %3</translation>
<message>
<location filename="../SampleDownloader.cpp" line="112"/>
<source>Base URL for samples:</source>
<translation>Enlace para muestras:</translation>
<translation>Enlace de las muestras:</translation>
</message>
<message>
<location filename="../SampleDownloader.cpp" line="113"/>
@ -5483,7 +5487,7 @@ Error(%2): %3</translation>
<message>
<location filename="../Audio/soundout.cpp" line="95"/>
<source>No audio output device configured.</source>
<translation>No hay dispositivo de salida de audio configurado</translation>
<translation>No hay dispositivo de salida de audio configurado.</translation>
</message>
<message>
<location filename="../Audio/soundout.cpp" line="184"/>
@ -5974,7 +5978,7 @@ Error(%2): %3</translation>
<location filename="../Configuration.ui" line="237"/>
<source>Font...</source>
<translatorcomment>Letra...</translatorcomment>
<translation>Tipo de letra para la aplicación</translation>
<translation>Tipo de letra para la aplicación..</translation>
</message>
<message>
<location filename="../Configuration.ui" line="244"/>
@ -6220,7 +6224,7 @@ período de silencio cuando se ha realizado la decodificación.</translation>
<message>
<location filename="../Configuration.ui" line="628"/>
<source>4800</source>
<translation></translation>
<translation>4800</translation>
</message>
<message>
<location filename="../Configuration.ui" line="633"/>
@ -6832,7 +6836,7 @@ Haz clic derecho para acciones específicas del artículo.
Clic, Mayúsculas+Clic y, CTRL+Clic para seleccionar elementos.</translatorcomment>
<translation>Arrastre y suelte elementos para reorganizar el orden
Clic derecho para acciones específicas del elemento.
Clic, Mayús+Clic y CTRL+Clic para seleccionar elementos.</translation>
Clic, Mayús+Clic y CTRL+Clic para seleccionar elementos</translation>
</message>
<message>
<location filename="../Configuration.ui" line="1709"/>
@ -7559,7 +7563,7 @@ Clic derecho para insertar y eliminar opciones.</translation>
<location filename="../Configuration.ui" line="2970"/>
<source>Waterfall spectra</source>
<translatorcomment>Espectros de la cascada</translatorcomment>
<translation>Espectro de la cascada (waterfall)</translation>
<translation>Cascada (Waterfall)</translation>
</message>
<message>
<location filename="../Configuration.ui" line="2976"/>

View File

@ -21,7 +21,7 @@ CAboutDlg::CAboutDlg(QWidget *parent) :
"WSJT-X implements a number of digital modes designed for <br />"
"weak-signal Amateur Radio communication. <br /><br />"
"&copy; 2001-2023 by Joe Taylor, K1JT, Bill Somerville, G4WJS, <br />"
"&copy; 2001-2024 by Joe Taylor, K1JT, Bill Somerville, G4WJS, <br />"
"Steve Franke, K9AN, Nico Palermo, IV3NWV, <br />"
"Uwe Risse, DG2YCB, and Brian Moran, N9ADG <br /><br />"
"We gratefully acknowledge contributions from AC6SL, AE4JY,<br />"

View File

@ -47,7 +47,7 @@ void ActiveStations::read_settings ()
ui->sbMaxRecent->setValue(settings_->value("MaxRecent",10).toInt());
ui->sbMaxAge->setValue(settings_->value("MaxAge",10).toInt());
ui->cbReadyOnly->setChecked(settings_->value("ReadyOnly",false).toBool());
ui->cbWantedOnly->setChecked(settings_->value("WantedOnly",false).toBool());
ui->cbWantedOnly->setChecked(settings_->value("# WantedOnly",false).toBool());
}
void ActiveStations::write_settings ()
@ -64,9 +64,11 @@ void ActiveStations::displayRecentStations(QString mode, QString const& t)
{
if(mode!=m_mode) {
m_mode=mode;
ui->cbReadyOnly->setText(" Ready only");
if(m_mode=="Q65") {
ui->header_label2->setText(" N Frx Fsked S/N Call Grid Tx Age");
ui->header_label2->setText(" N Frx Fsked S/N Q65 Call Grid Tx Age");
ui->label->setText("QSOs:");
ui->cbReadyOnly->setText("* CQ only");
} else if(m_mode=="Q65-pileup") {
ui->header_label2->setText(" N Freq Call Grid El Age(h)");
} else {
@ -90,6 +92,32 @@ void ActiveStations::displayRecentStations(QString mode, QString const& t)
bool bClickOK=m_clickOK;
m_clickOK=false;
ui->RecentStationsPlainTextEdit->setPlainText(t);
//White background for Q65-60x decodes, yellow for Q65-30x:
int i0=0;
int i1=0;
int npos=0;
int nlines=t.count("\n");
QTextCursor cursor=ui->RecentStationsPlainTextEdit->textCursor();
QTextCharFormat fmt;
for(int i=0; i<nlines; i++) {
i1=t.indexOf("\n",i0);
npos=t.indexOf(QRegularExpression(" 30[ABCD] "), i0);
if(npos>0) {
cursor.setPosition(npos);
cursor.select(QTextCursor::LineUnderCursor);
fmt.setBackground(QBrush(Qt::yellow));
fmt.setForeground(QBrush(Qt::black));
} else {
cursor.setPosition(i0+10);
cursor.select(QTextCursor::LineUnderCursor);
fmt.clearForeground();
fmt.clearBackground();
}
cursor.setCharFormat(fmt);
i0=i1+1;
}
m_clickOK=bClickOK;
}

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>395</width>
<height>339</height>
<width>400</width>
<height>340</height>
</rect>
</property>
<property name="windowTitle">
@ -17,32 +17,30 @@
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="2">
<widget class="QSpinBox" name="sbMaxRecent">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<layout class="QGridLayout" name="gridLayout_2" columnstretch="1,0,1,0,0,1">
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Band Changes:</string>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="QLineEdit" name="score">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Set maximum number of displayed lines.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Total score accumulated since most recent reset of Cabrillo log.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="prefix">
<string>Max N </string>
<property name="text">
<string>0</string>
</property>
<property name="maximum">
<number>50</number>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="value">
<number>10</number>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
@ -50,7 +48,7 @@
<widget class="QLineEdit" name="rate">
<property name="maximumSize">
<size>
<width>80</width>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
@ -78,30 +76,24 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Band Changes:</string>
<item row="0" column="1">
<widget class="QCheckBox" name="cbWantedOnly">
<property name="visible">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
<property name="text">
<string># Wanted only</string>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="QLineEdit" name="score">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Total score accumulated since most recent reset of Cabrillo log.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<item row="1" column="4">
<widget class="QLabel" name="label_2">
<property name="text">
<string>0</string>
<string>Score:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="4">
@ -124,19 +116,22 @@
</property>
<property name="minimumSize">
<size>
<width>80</width>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Set maximum elapsed number of T/R sequences.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="prefix">
<string>Max Age </string>
</property>
@ -151,13 +146,34 @@
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Score:</string>
<item row="0" column="2">
<widget class="QSpinBox" name="sbMaxRecent">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Set maximum number of displayed lines.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
<set>Qt::AlignCenter</set>
</property>
<property name="prefix">
<string>Max N </string>
</property>
<property name="maximum">
<number>50</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
@ -177,16 +193,6 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="cbWantedOnly">
<property name="visible">
<bool>false</bool>
</property>
<property name="text">
<string>Wanted only</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">

View File

@ -387,6 +387,17 @@ QString DisplayText::appendWorkedB4 (QString message, QString call, QString cons
countryName.replace ("European", "EU");
countryName.replace ("African", "AF");
// assign WAE entities to the correct DXCC when "Include extra WAE entities" is not selected
if (!(m_config->include_WAE_entities())) {
countryName.replace ("Bear Is.", "Svalbard");
countryName.replace ("Shetland Is.", "Scotland");
countryName.replace ("AF Italy", "Italy");
countryName.replace ("Sicily", "Italy");
countryName.replace ("Vienna Intl Ctr", "Austria");
countryName.replace ("AF Turkey", "Turkey");
countryName.replace ("EU Turkey", "Turkey");
}
extra += countryName;
}
}
@ -520,7 +531,8 @@ void DisplayText::displayTransmittedText(QString text, QString modeTx, qint32 tx
QString t2;
t2 = t2.asprintf("%4d",txFreq);
QString t;
if(bFastMode or modeTx=="FT8" or modeTx=="FT4" or (TRperiod<60)) {
if(bFastMode or modeTx=="FT8" or modeTx=="FT4" or (TRperiod<60) or
(modeTx=="Q65" and TRperiod==60)) {
t = QDateTime::currentDateTimeUtc().toString("hhmmss") + \
" Tx " + t2 + t1 + text;
} else if(modeTx.mid(0,6)=="FT8fox") {

View File

@ -213,6 +213,7 @@ QVector<QColor> g_ColorTbl;
using SpecOp = Configuration::SpecialOperatingActivity;
bool blocked = false;
bool m_displayBand = false;
bool no_a7_decodes = false;
bool keep_frequency = false;
@ -224,7 +225,8 @@ struct {
int nQDecoderDone; //QMAP decoder is finished (0 or 1)
int nWDecoderBusy; //WSJT-X decoder is busy (0 or 1)
int nWTransmitting; //WSJT-X is transmitting (0 or 1)
char result[50][60]; //Decodes as character*60 arrays
int kHzRequested; //Integer kHz dial frequency requested from QMAP
char result[50][64]; //Decodes as character*64 arrays
} qmapcom;
int* ipc_qmap;
@ -1084,18 +1086,35 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
QString jpleph = m_config.data_dir().absoluteFilePath("JPLEPH");
jpl_setup_(const_cast<char *>(jpleph.toLocal8Bit().constData()),256);
#ifdef WIN32
// backup libhamlib-4.dll file, so it is still available after the next program update
QDir dataPath = QCoreApplication::applicationDirPath();
QFile f {dataPath.absolutePath() + "/" + "libhamlib-4_old.dll"};
if (!f.exists()) {
QFile::copy(dataPath.absolutePath() + "/" + "libhamlib-4.dll", dataPath.absolutePath() + "/" + "libhamlib-4_old.dll");
QTimer::singleShot (5000, [=] { //wait until hamlib has been started
extern char* hamlib_version2;
QString hamlib = QString(QLatin1String(hamlib_version2));
m_settings->beginGroup("Configuration");
m_settings->setValue ("HamlibBackedUp", hamlib);
m_settings->endGroup();
});
}
#endif
// this must be the last statement of constructor
if (!m_valid) throw std::runtime_error {"Fatal initialization exception"};
}
void MainWindow::not_GA_warning_message ()
{
if(m_config.my_callsign()=="K1JT" or m_config.my_callsign()=="W2ZQ") return;
MessageBox::critical_message (this,
"This is a pre-release version of WSJT-X 2.7.0-rc2 made\n"
"This is a pre-release version of WSJT-X " + version (false) + " made\n"
"available for testing purposes. By design it will\n"
"be nonfunctional after Jan 15, 2024.");
"be nonfunctional after October 30, 2024.");
auto now = QDateTime::currentDateTimeUtc ();
if (now >= QDateTime {{2024, 01, 15}, {23, 59, 59, 999}, Qt::UTC}) {
if (now >= QDateTime {{2024, 10, 30}, {23, 59, 59, 999}, Qt::UTC}) {
Q_EMIT finished ();
}
}
@ -1206,6 +1225,16 @@ void MainWindow::writeSettings()
m_settings->setValue ("SerialNumber",ui->sbSerialNumber->value ());
m_settings->endGroup();
// do this in the General group because we save the parameters from various places
if(m_mode=="JT9") {
m_settings->setValue("SubMode",ui->sbSubmode->value());
m_settings->setValue("TRPeriod", ui->sbTR->value());
}
if(m_mode=="MSK144") m_settings->setValue("ShMsgs_MSK144",m_bShMsgs);
if(m_mode=="Q65") m_settings->setValue("ShMsgs_Q65",m_bShMsgs);
if(m_mode=="JT65") m_settings->setValue("ShMsgs_JT65",m_bShMsgs);
if(m_mode=="JT4") m_settings->setValue("ShMsgs_JT4",m_bShMsgs);
m_settings->beginGroup("Common");
m_settings->setValue("Mode",m_mode);
m_settings->setValue("SaveNone",ui->actionNone->isChecked());
@ -1219,13 +1248,12 @@ void MainWindow::writeSettings()
m_settings->setValue("FST4W_FTol",ui->sbFST4W_FTol->value());
m_settings->setValue("FST4_FLow",ui->sbF_Low->value());
m_settings->setValue("FST4_FHigh",ui->sbF_High->value());
// m_settings->setValue("SubMode",ui->sbSubmode->value());
m_settings->setValue("DTtol",m_DTtol);
m_settings->setValue("Ftol", ui->sbFtol->value ());
m_settings->setValue("MinSync",m_minSync);
m_settings->setValue ("AutoSeq", ui->cbAutoSeq->isChecked ());
m_settings->setValue ("RxAll", ui->cbRxAll->isChecked ());
m_settings->setValue("ShMsgs",m_bShMsgs);
// m_settings->setValue("ShMsgs",m_bShMsgs);
m_settings->setValue("SWL",ui->cbSWL->isChecked());
m_settings->setValue ("DialFreq", QVariant::fromValue(m_lastMonitoredFrequency));
m_settings->setValue("OutAttenuation", ui->outAttenuation->value ());
@ -1241,7 +1269,6 @@ void MainWindow::writeSettings()
m_settings->setValue("UploadSpots",m_uploadWSPRSpots);
m_settings->setValue("NoOwnCall",ui->cbNoOwnCall->isChecked());
m_settings->setValue ("BandHopping", ui->band_hopping_group_box->isChecked ());
// m_settings->setValue ("TRPeriod", ui->sbTR->value ());
m_settings->setValue ("MaxDrift", ui->sbMaxDrift->value());
m_settings->setValue ("TRPeriod_FST4W", ui->sbTR_FST4W->value ());
m_settings->setValue("FastMode",m_bFastMode);
@ -1309,16 +1336,58 @@ void MainWindow::readSettings()
ui->sbSerialNumber->setValue (m_settings->value ("SerialNumber", 1).toInt ());
m_settings->endGroup();
m_settings->beginGroup("Common");
m_mode=m_settings->value("Mode","FT8").toString();
m_settings->endGroup();
// do this outside of settings group because it uses groups internally
ui->actionAstronomical_data->setChecked (displayAstro);
// do this in the General group because we save the parameters from various places
if(m_mode=="JT9") {
blocked=true;
m_nSubMode=m_settings->value("SubMode",0).toInt();
ui->sbSubmode->setValue(m_nSubMode);
ui->sbFtol->setValue (m_settings->value("Ftol_JT9", 50).toInt());
ui->sbTR->setValue (m_settings->value ("TRPeriod", 15).toInt());
QTimer::singleShot (50, [=] {blocked = false;});
}
if (m_mode=="Q65") {
m_nSubMode=m_settings->value("SubMode_Q65",0).toInt();
ui->sbSubmode->setValue(m_nSubMode_Q65);
ui->sbFtol->setValue (m_settings->value("Ftol_Q65", 50).toInt());
ui->sbTR->setValue (m_settings->value ("TRPeriod_Q65", 30).toInt());
}
if (m_mode=="JT65") {
m_nSubMode=m_settings->value("SubMode_JT65",0).toInt();
ui->sbSubmode->setValue(m_nSubMode_JT65);
ui->sbFtol->setValue (m_settings->value("Ftol_JT65", 50).toInt());
}
if (m_mode=="JT4") {
m_nSubMode=m_settings->value("SubMode_JT4",0).toInt();
ui->sbSubmode->setValue(m_nSubMode_JT4);
ui->sbFtol->setValue (m_settings->value("Ftol_JT4", 50).toInt());
ui->sbTR->setValue (m_settings->value ("TRPeriod_FST4", 60).toInt());
}
if (m_mode=="MSK144") {
ui->sbFtol->setValue (m_settings->value("Ftol_MSK144",50).toInt());
if (!(m_currentBand=="6m" or m_currentBand=="4m" or m_currentBand=="2m")) ui->sbTR->setValue (m_settings->value ("TRPeriod_MSK144", 30).toInt());
if (m_currentBand=="6m" or m_currentBand=="4m") ui->sbTR->setValue (m_settings->value ("TRPeriod_MSK144_6m", 15).toInt());
if (m_currentBand=="2m") ui->sbTR->setValue (m_settings->value ("TRPeriod_MSK144_2m", 30).toInt());
}
if (m_mode=="MSK144") m_bShMsgs=m_settings->value("ShMsgs_MSK144",false).toBool();
if (m_mode=="Q65") m_bShMsgs=m_settings->value("ShMsgs_Q65",false).toBool();
if (m_mode=="JT65") m_bShMsgs=m_settings->value("ShMsgs_JT65",false).toBool();
if (m_mode=="JT4") m_bShMsgs=m_settings->value("ShMsgs_JT4",false).toBool();
m_settings->beginGroup("Common");
ui->labDXped->setText(m_settings->value("labDXpedText",QString {}).toString ());
ui->actionDon_t_split_ALL_TXT->setChecked(m_settings->value("actionDontSplitALLTXT", true).toBool());
ui->actionSplit_ALL_TXT_yearly->setChecked(m_settings->value("splitAllTxtYearly", false).toBool());
ui->actionSplit_ALL_TXT_monthly->setChecked(m_settings->value("splitAllTxtMonthly", false).toBool());
ui->actionDisable_writing_of_ALL_TXT->setChecked(m_settings->value("disableWritingOfAllTxt", false).toBool());
m_mode=m_settings->value("Mode","FT8").toString();
// m_mode=m_settings->value("Mode","FT8").toString();
ui->actionNone->setChecked(m_settings->value("SaveNone",true).toBool());
ui->actionSave_decoded->setChecked(m_settings->value("SaveDecoded",false).toBool());
ui->actionSave_all->setChecked(m_settings->value("SaveAll",false).toBool());
@ -1328,28 +1397,16 @@ void MainWindow::readSettings()
ui->sbFST4W_RxFreq->setValue(m_settings->value("FST4W_RxFreq",1500).toInt());
ui->sbF_Low->setValue(m_settings->value("FST4_FLow",600).toInt());
ui->sbF_High->setValue(m_settings->value("FST4_FHigh",1400).toInt());
// m_nSubMode=m_settings->value("SubMode",0).toInt();
if (m_mode=="Q65") m_nSubMode=m_settings->value("SubMode_Q65",0).toInt();
if (m_mode=="JT65") m_nSubMode=m_settings->value("SubMode_JT65",0).toInt();
if (m_mode=="JT4") m_nSubMode=m_settings->value("SubMode_JT4",0).toInt();
// ui->sbSubmode->setValue(m_nSubMode);
if (m_mode=="Q65") ui->sbSubmode->setValue(m_nSubMode_Q65);
if (m_mode=="JT65") ui->sbSubmode->setValue(m_nSubMode_JT65);
if (m_mode=="JT4") ui->sbSubmode->setValue(m_nSubMode_JT4);
ui->sbFtol->setValue (m_settings->value("Ftol", 50).toInt());
ui->sbFST4W_FTol->setValue(m_settings->value("FST4W_FTol",100).toInt());
m_minSync=m_settings->value("MinSync",0).toInt();
ui->syncSpinBox->setValue(m_minSync);
ui->cbAutoSeq->setChecked (m_settings->value ("AutoSeq", false).toBool());
ui->cbRxAll->setChecked (m_settings->value ("RxAll", false).toBool());
m_bShMsgs=m_settings->value("ShMsgs",false).toBool();
// m_bShMsgs=m_settings->value("ShMsgs",false).toBool();
m_bSWL=m_settings->value("SWL",false).toBool();
m_bFast9=m_settings->value("Fast9",false).toBool();
m_bFastMode=m_settings->value("FastMode",false).toBool();
// ui->sbTR->setValue (m_settings->value ("TRPeriod", 15).toInt());
if (m_mode=="Q65") ui->sbTR->setValue (m_settings->value ("TRPeriod_Q65", 30).toInt());
if (m_mode=="MSK144") ui->sbTR->setValue (m_settings->value ("TRPeriod_MSK144", 15).toInt());
if (m_mode=="FST4") ui->sbTR->setValue (m_settings->value ("TRPeriod_FST4", 60).toInt());
ui->sbMaxDrift->setValue (m_settings->value ("MaxDrift",0).toInt());
ui->sbTR_FST4W->setValue (m_settings->value ("TRPeriod_FST4W", 15).toInt());
m_lastMonitoredFrequency = m_settings->value ("DialFreq",
@ -1677,6 +1734,7 @@ void MainWindow::dataSink(qint64 frames)
float width=m_fSpread;
echocom_.nclearave=m_nclearave;
int nDop=m_fAudioShift;
if(m_astroWidget->DopplerMethod()==2) nDop=0; //Using CFOM
int nDopTotal=m_fDop;
int navg=ui->sbEchoAvg->value();
if(m_diskData) {
@ -2193,6 +2251,13 @@ void MainWindow::keyPressEvent (QKeyEvent * e)
bool bAltF1F6=m_config.alternate_bindings();
switch(e->key())
{
case Qt::Key_A:
if(m_mode=="Q65" && e->modifiers() & Qt::AltModifier) {
m_EMECall.clear();
qmapcom.ndecodes=0;
readWidebandDecodes();
}
return;
case Qt::Key_B:
if(m_mode=="FT4" && e->modifiers() & Qt::AltModifier) {
on_pbBestSP_clicked();
@ -2491,16 +2556,37 @@ void MainWindow::statusChanged()
.arg (f.fileName ()).arg (f.errorString ()));
}
on_dxGridEntry_textChanged(m_hisGrid);
if(m_specOp!=SpecOp::HOUND) {
ui->txb2->setEnabled(true);
ui->txrb2->setEnabled(true);
ui->txb4->setEnabled(true);
ui->txrb4->setEnabled(true);
ui->txb5->setEnabled(true);
ui->txrb5->setEnabled(true);
ui->txb6->setEnabled(true);
ui->txrb6->setEnabled(true);
ui->houndButton->setChecked(false);
if (m_specOp!=SpecOp::HOUND) {
ui->txb2->setEnabled(true);
ui->txrb2->setEnabled(true);
ui->txb4->setEnabled(true);
ui->txrb4->setEnabled(true);
ui->txb5->setEnabled(true);
ui->txrb5->setEnabled(true);
ui->txb6->setEnabled(true);
ui->txrb6->setEnabled(true);
ui->houndButton->setChecked(false);
}
if (m_config.enable_VHF_features() && (m_mode=="JT4" or m_mode=="Q65" or m_mode=="JT65")) {
ui->actionInclude_averaging->setVisible(true);
ui->actionAuto_Clear_Avg->setVisible(true);
} else {
ui->actionInclude_averaging->setVisible(false);
ui->actionAuto_Clear_Avg->setVisible(false);
}
if (m_mode=="JT4" or m_mode=="Q65" or m_mode=="JT65") {
if (ui->actionInclude_averaging->isVisible() && ui->actionInclude_averaging->isChecked()) {
ui->lh_decodes_title_label->setText(tr ("Single-Period Decodes"));
ui->rh_decodes_title_label->setText(tr ("Average Decodes"));
} else {
if (m_config.enable_VHF_features()) {
ui->lh_decodes_title_label->setText(tr ("Band Activity"));
ui->rh_decodes_title_label->setText(tr ("Decodes containing My Call"));
} else {
ui->lh_decodes_title_label->setText(tr ("Band Activity"));
ui->rh_decodes_title_label->setText(tr ("Rx Frequency"));
}
}
}
}
@ -2803,7 +2889,7 @@ void MainWindow::on_actionCopyright_Notice_triggered()
"\"The algorithms, source code, look-and-feel of WSJT-X and related "
"programs, and protocol specifications for the modes FSK441, FST4, FT8, "
"JT4, JT6M, JT9, JT65, JTMS, QRA64, Q65, MSK144 are Copyright (C) "
"2001-2023 by one or more of the following authors: Joseph Taylor, "
"2001-2024 by one or more of the following authors: Joseph Taylor, "
"K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, "
"IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; "
"Philip Karn, KA9Q; Uwe Risse, DG2YCB; Brian Moran, N9ADG; "
@ -3180,6 +3266,7 @@ void MainWindow::on_actionKeyboard_shortcuts_triggered()
<tr><td><b>Ctrl+Shift+F12 </b></td><td>Move dial frequency up 1000 Hz</td></tr>
<tr><td><b>Alt+1-6 </b></td><td>Set now transmission to this number on Tab 1</td></tr>
<tr><td><b>Ctl+1-6 </b></td><td>Set next transmission to this number on Tab 1</td></tr>
<tr><td><b>Alt+A </b></td><td>Clear Active Stations for QMAP</td></tr>
<tr><td><b>Alt+B </b></td><td>Toggle "Best S+P" status</td></tr>
<tr><td><b>Alt+C </b></td><td>Toggle "Call 1st" checkbox</td></tr>
<tr><td><b>Alt+D </b></td><td>Decode again at QSO frequency</td></tr>
@ -3226,7 +3313,7 @@ void MainWindow::on_actionSpecial_mouse_commands_triggered()
<td><b>Click</b> to set Rx frequency.<br/>
<b>Shift-click</b> to set Tx frequency.<br/>
<b>Ctrl-click</b> or <b>Right-click</b> to set Rx and Tx frequencies.<br/>
<b>Double-click</b> to also decode at Rx frequency.<br/>
<b>Double-click</b> to also decode at Rx frequency.
</td>
</tr>
<tr>
@ -3237,7 +3324,7 @@ void MainWindow::on_actionSpecial_mouse_commands_triggered()
messages.<br/>
If <b>Hold Tx Freq</b> is checked or first callsign in message<br/>
is your own call, Tx frequency is not changed unless <br/>
<b>Ctrl</b> is held down.<br/>
<b>Ctrl</b> is held down.
</td>
</tr>
<tr>
@ -3246,6 +3333,18 @@ void MainWindow::on_actionSpecial_mouse_commands_triggered()
<b>Double-click</b> to erase QSO and Band Activity windows.
</td>
</tr>
<tr>
<td align="right">Q65 Button:</td>
<td><b>Click</b> to switch to Q65 Mode.<br/>
<b>Right-click</b> to switch to Q65 Pileup Mode.
</td>
</tr>
<tr>
<td align="right">JT65 Button:</td>
<td><b>Click</b> to switch to JT65 Mode.<br/>
<b>Right-click</b> to switch to JT9 Mode.
</td>
</tr>
</table>)"), font});
}
m_mouseCmnds->showNormal ();
@ -3830,9 +3929,9 @@ void MainWindow::callSandP2(int n)
int nMHz=m_freqNominal/1000000;
m_freqNominal=(nMHz*1000 + kHz)* 1000;
}
m_deCall=w[3];
m_deGrid=w[4];
m_txFirst=(w[5]=="0");
m_deCall=w[4];
m_deGrid=w[5];
m_txFirst=(w[6]=="0");
// ui->TxFreqSpinBox->setValue(1500);
} else {
m_deCall=w[0];
@ -3840,6 +3939,18 @@ void MainWindow::callSandP2(int n)
ui->RxFreqSpinBox->setValue(w[4].toInt());
m_txFirst = (w[5]=="0");
}
if(w[3].left(2)=="30") {
ui->sbTR->setValue(30);
} else {
ui->sbTR->setValue(60);
}
if(w[3].right(1)=="A") ui->sbSubmode->setValue(0);
if(w[3].right(1)=="B") ui->sbSubmode->setValue(1);
if(w[3].right(1)=="C") ui->sbSubmode->setValue(2);
if(w[3].right(1)=="D") ui->sbSubmode->setValue(3);
if(w[3].right(1)=="E") ui->sbSubmode->setValue(4);
m_bDoubleClicked=true; //### needed?
ui->dxCallEntry->setText(m_deCall);
ui->dxGridEntry->setText(m_deGrid);
@ -3851,7 +3962,14 @@ void MainWindow::callSandP2(int n)
}
setTxMsg(1);
ui->txFirstCheckBox->setChecked(m_txFirst);
if (!ui->autoButton->isChecked()) ui->autoButton->click(); // Enable Tx
static qint64 ms0=0;
qint64 ms=QDateTime::currentMSecsSinceEpoch();
if(ui->autoButton->isChecked()) {
if((ms-ms0)<=500) ui->autoButton->click(); // Disable Tx on double click
} else if((ms-ms0)>500) {
ui->autoButton->click(); // Enable Tx on single click
}
ms0=ms;
if(m_transmitting) m_restart=true;
}
@ -4154,7 +4272,9 @@ void MainWindow::readFromStdout() //readFromStdout
if((abs(audioFreq - m_wideGraph->rxFreq()) <= 10) and
!m_config.enable_VHF_features()) bDisplayRight=true;
}
if(m_mode=="Q65" and !bAvgMsg) bDisplayRight=false;
if(m_mode=="Q65" and !bAvgMsg and !decodedtext.string().contains(m_baseCall)) bDisplayRight=false;
if((m_mode=="JT4" or m_mode=="Q65" or m_mode=="JT65") and decodedtext.string().contains(m_baseCall) && ui->actionInclude_averaging->isVisible() && !ui->actionInclude_averaging->isChecked()) bDisplayRight=true;
if(m_mode=="FT8" and SpecOp::HOUND==m_specOp && decodedtext0.string().replace("<","").replace(">","").contains(" " + m_baseCall + " ")) bDisplayRight=true;
if (bDisplayRight) {
// This msg is within 10 hertz of our tuned frequency, or a JT4 or JT65 avg,
@ -4980,19 +5100,24 @@ void MainWindow::guiUpdate()
if(m_decoderBusy) n=1;
ipc_qmap[3]=n;
n=0;
if(m_transmitting) n=1;
if(m_transmitting) n=m_TRperiod;
ipc_qmap[4]=n;
if(ipc_qmap[0] > 0) { //ndecodes
memcpy(&qmapcom, (char*)ipc_qmap, sizeof(qmapcom)); //Fetch the new decode(s)
readWidebandDecodes();
}
if(ipc_qmap[5]>0) {
// qDebug() << "aa" << m_freqNominal << ipc_qmap[5];
setRig((m_freqNominal/1000000)*1000000 + 1000*ipc_qmap[5]);
ipc_qmap[5]=0;
// qDebug() << "bb" << m_freqNominal << ipc_qmap[5];
}
mem_qmap.unlock();
}
//Once per second (onesec)
if(nsec != m_sec0) {
// qDebug() << "AAA" << nsec%60 << int(m_specOp);
// qDebug() << "AAA" << nsec%60 << ipc_qmap[5];
if(m_mode=="FST4") chk_FST4_freq_range();
m_currentBand=m_config.bands()->find(m_freqNominal);
if( SpecOp::HOUND == m_specOp ) {
@ -5398,7 +5523,24 @@ void MainWindow::doubleClickOnCall(Qt::KeyboardModifiers modifiers)
} else {
cursor=ui->decodedTextBrowser2->textCursor();
}
DecodedText message {cursor.block().text().trimmed().left(61).remove("TU; ")};
if(message.string().contains(";") && message.string().contains("<")) {
QVector<qint32> Freq = {1840000,3573000,7074000,10136000,14074000,18100000,21074000,24915000,28074000,50313000,70154000,3575000,7047500,10140000,14080000,18104000,21140000,24919000,28180000,50318000};
for(int i=0; i<Freq.length()-1; i++) {
int kHzdiff=m_freqNominal - Freq[i];
if(qAbs(kHzdiff) < 3000 ) {
m_bTxTime=false;
if (m_auto) auto_tx_mode (false);
if (m_tune) stop_tuning();
// auto const& msg2 = tr("Double-clicking on combined messages\n"
// "not allowed on the standard FT8 sub-bands.");
// QTimer::singleShot (0, [=] { // don't block guiUpdate
// MessageBox::warning_message (this, tr ("Potential hash collision"), msg2);
// });
return;
}
}
}
if(modifiers==(Qt::ShiftModifier + Qt::ControlModifier + Qt::AltModifier)) {
//### What was the purpose of this ??? ###
cursor.setPosition(0);
@ -5413,7 +5555,6 @@ void MainWindow::doubleClickOnCall(Qt::KeyboardModifiers modifiers)
}
return;
}
DecodedText message {cursor.block().text().trimmed().left(61).remove("TU; ")};
m_bDoubleClicked = true;
processMessage (message, modifiers);
}
@ -5517,7 +5658,7 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
QString firstcall = message.call();
if(firstcall.length()>=4 and firstcall.mid(0,3)=="CQ ") firstcall="CQ";
if(!m_bFastMode and (!m_config.enable_VHF_features() or m_mode=="FT8")) {
if(!m_bFastMode and (!m_config.enable_VHF_features() or m_mode=="FT8" or m_mode=="FT4" or m_mode=="FST4")) {
// Don't change Tx freq if in a fast mode, or VHF features enabled; also not if a
// station is calling me, unless CTRL or SHIFT is held down.
if ((Radio::is_callsign (firstcall)
@ -5973,7 +6114,7 @@ void MainWindow::genCQMsg ()
( tlist.at(1)==my_callsign or
tlist.at(2)==my_callsign ) and
stdCall(my_callsign)) {
if(m_config.Individual_Contest_Name()) {
if(m_config.Individual_Contest_Name() && SpecOp::FOX != m_specOp) {
m_cqStr = m_config.Contest_Name();
} else {
if(SpecOp::NA_VHF == m_specOp) m_cqStr="TEST";
@ -6102,6 +6243,9 @@ void MainWindow::genStdMsgs(QString rpt, bool unconditional)
t1 = t1.asprintf("%4.4d",ui->sbSerialNumber->value());
sent=rst + t1;
}
if(t1.contains(QRegularExpression {"\\d\\d\\d\\d"})) {
t1 = m_config.RTTY_Exchange();
}
}
if(SpecOp::EU_VHF==m_specOp) {
QString a;
@ -6290,7 +6434,7 @@ void MainWindow::lookup()
{
QString hisCall {ui->dxCallEntry->text()};
QString hisgrid0 {ui->dxGridEntry->text()};
if (!hisCall.size ()) return;
if (!hisCall.size () or (!(m_specOp==SpecOp::NONE or m_specOp==SpecOp::HOUND or m_specOp==SpecOp::Q65_PILEUP))) return;
QFile f {m_config.writeable_data_dir ().absoluteFilePath ("CALL3.TXT")};
if (f.open (QIODevice::ReadOnly | QIODevice::Text))
{
@ -6520,18 +6664,14 @@ void MainWindow::on_RoundRobin_currentTextChanged(QString text)
void MainWindow::mousePressEvent(QMouseEvent *event)
{
if(ui->q65Button->hasFocus() && (event->button() & Qt::RightButton)) {
m_specOp=m_config.special_op_id();
if (m_specOp==SpecOp::Q65_PILEUP) {
m_config.setSpecial_None();
ui->tx1->setEnabled(true);
ui->txb1->setEnabled(true);
} else {
m_config.setSpecial_Q65_Pileup();
}
if(ui->q65Button->hasFocus() && (event->button() & Qt::RightButton)) { // switch to Q65_Pileup mode
m_config.setSpecial_Q65_Pileup();
m_specOp=m_config.special_op_id();
on_actionQ65_triggered();
}
if(ui->jt65Button->hasFocus() && (event->button() & Qt::RightButton)) { // switch to JT9 mode
on_actionJT9_triggered();
}
}
void MainWindow::on_dxCallEntry_textChanged (QString const& call)
@ -6651,6 +6791,10 @@ void MainWindow::on_logQSOButton_clicked() //Log QSO button
m_xSent=m_config.my_grid().left(4);
m_xRcvd=m_hisGrid;
break;
case SpecOp::Q65_PILEUP:
m_xSent=m_config.my_grid().left(4);
m_xRcvd=m_hisGrid;
break;
default: break;
}
@ -6840,6 +6984,10 @@ void MainWindow::on_actionFST4_triggered()
on_sbSubmode_valueChanged(ui->sbSubmode->value());
});
m_mode="FST4";
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
ui->actionFST4->setChecked(true);
m_bFast9=false;
m_bFastMode=false;
@ -6882,6 +7030,10 @@ void MainWindow::on_actionFST4_triggered()
void MainWindow::on_actionFST4W_triggered()
{
m_mode="FST4W";
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
ui->actionFST4W->setChecked(true);
m_bFast9=false;
m_bFastMode=false;
@ -6917,6 +7069,10 @@ void MainWindow::on_actionFT4_triggered()
on_sbSubmode_valueChanged(ui->sbSubmode->value());
});
m_mode="FT4";
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
m_TRperiod=7.5;
bool bVHF=m_config.enable_VHF_features();
m_bFast9=false;
@ -7083,6 +7239,10 @@ void MainWindow::on_actionJT4_triggered()
ui->RxFreqSpinBox->setValue(m_settings->value("RxFreq_old",1500).toInt());
});
m_mode="JT4";
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
bool bVHF=m_config.enable_VHF_features();
WSPR_config(false);
switch_mode (Modes::JT4);
@ -7103,15 +7263,16 @@ void MainWindow::on_actionJT4_triggered()
m_bFast9=false;
setup_status_bar (bVHF);
ui->sbSubmode->setMaximum(6);
ui->lh_decodes_title_label->setText(tr ("Single-Period Decodes"));
ui->rh_decodes_title_label->setText(tr ("Average Decodes"));
ui->lh_decodes_headings_label->setText("UTC dB DT Freq " + tr ("Message"));
ui->rh_decodes_headings_label->setText("UTC dB DT Freq " + tr ("Message"));
if(bVHF) {
// ui->sbSubmode->setValue(m_nSubMode);
QTimer::singleShot (50, [=] {m_nSubMode=m_settings->value("SubMode_JT4",0).toInt();});
QTimer::singleShot (75, [=] {ui->sbSubmode->setValue(m_settings->value("SubMode_JT4",0).toInt());});
QTimer::singleShot (100, [=] {on_sbSubmode_valueChanged(m_nSubMode);});
// restore last used parameters
ui->sbFtol->setValue (m_settings->value ("Ftol_JT4", 50).toInt());
m_nSubMode=m_settings->value("SubMode_JT4",0).toInt();
ui->sbSubmode->setValue(m_settings->value("SubMode_JT4",0).toInt());
QTimer::singleShot (50, [=] {on_sbSubmode_valueChanged(ui->sbSubmode->value());});
m_bShMsgs=m_settings->value("ShMsgs_JT4",false).toBool();
ui->cbShMsgs->setChecked(m_bShMsgs);
} else {
ui->sbSubmode->setValue(0);
}
@ -7128,8 +7289,25 @@ void MainWindow::on_actionJT4_triggered()
void MainWindow::on_actionJT9_triggered()
{
m_mode="JT9";
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
bool bVHF=m_config.enable_VHF_features();
m_bFast9=ui->cbFast9->isChecked();
// restore last used parameters
if(bVHF && m_mode!="JT65" && !blocked) {
ui->sbSubmode->setMaximum(7);
m_bFast9=m_settings->value("JT9_Fast",false).toBool();
ui->cbFast9->setChecked(m_bFast9 or m_bFastMode);
ui->sbFtol->setValue (m_settings->value ("Ftol_JT9", 50).toInt());
m_nSubMode=m_settings->value("SubMode",0).toInt();
ui->sbSubmode->setValue(m_nSubMode);
QTimer::singleShot (50, [=] {
on_sbTR_valueChanged (ui->sbTR->value());
on_sbSubmode_valueChanged(ui->sbSubmode->value());
});
}
// m_bFast9=ui->cbFast9->isChecked();
m_bFastMode=m_bFast9;
WSPR_config(false);
switch_mode (Modes::JT9);
@ -7152,6 +7330,7 @@ void MainWindow::on_actionJT9_triggered()
ui->sbSubmode->setMaximum(7);
if(m_bFast9) {
ui->sbTR->values ({5, 10, 15, 30});
if(bVHF && m_mode!="JT65" && !blocked) ui->sbTR->setValue (m_settings->value ("TRPeriod", 15).toInt()); // restore last used TRperiod
on_sbTR_valueChanged (ui->sbTR->value());
m_wideGraph->hide();
m_fastGraph->showNormal();
@ -7191,6 +7370,10 @@ void MainWindow::on_actionJT65_triggered()
ui->RxFreqSpinBox->setValue(m_settings->value("RxFreq_old",1500).toInt());
});
on_actionJT9_triggered();
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
m_mode="JT65";
bool bVHF=m_config.enable_VHF_features();
WSPR_config(false);
@ -7216,12 +7399,13 @@ void MainWindow::on_actionJT65_triggered()
m_bFast9=false;
ui->sbSubmode->setMaximum(2);
if(bVHF) {
// ui->sbSubmode->setValue(m_nSubMode);
QTimer::singleShot (50, [=] {m_nSubMode=m_settings->value("SubMode_JT65",0).toInt();});
QTimer::singleShot (75, [=] {ui->sbSubmode->setValue(m_settings->value("SubMode_JT65",0).toInt());});
QTimer::singleShot (100, [=] {on_sbSubmode_valueChanged(m_nSubMode);});
ui->lh_decodes_title_label->setText(tr ("Single-Period Decodes"));
ui->rh_decodes_title_label->setText(tr ("Average Decodes"));
// restore last used parameters
ui->sbFtol->setValue (m_settings->value ("Ftol_JT65", 50).toInt());
m_nSubMode=m_settings->value("SubMode_JT65",0).toInt();
ui->sbSubmode->setValue(m_settings->value("SubMode_JT65",0).toInt());
QTimer::singleShot (50, [=] {on_sbSubmode_valueChanged(ui->sbSubmode->value());});
m_bShMsgs=m_settings->value("ShMsgs_JT65",false).toBool();
ui->cbShMsgs->setChecked(m_bShMsgs);
} else {
ui->sbSubmode->setValue(0);
ui->lh_decodes_title_label->setText(tr ("Band Activity"));
@ -7248,6 +7432,10 @@ void MainWindow::on_actionQ65_triggered()
ui->RxFreqSpinBox->setValue(m_settings->value("RxFreq_old",1500).toInt());
});
m_mode="Q65";
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
ui->actionQ65->setChecked(true);
switch_mode(Modes::Q65);
ui->cbAutoSeq->setChecked(true);
@ -7261,12 +7449,17 @@ void MainWindow::on_actionQ65_triggered()
Q_EMIT FFTSize(m_FFTSize);
m_hsymStop=49;
ui->sbTR->values ({15, 30, 60, 120, 300});
ui->sbTR->setValue (m_settings->value ("TRPeriod_Q65", 30).toInt()); // remember sbTR settings by mode
QTimer::singleShot (50, [=] {on_sbTR_valueChanged (ui->sbTR->value());});
// ui->sbSubmode->setValue(m_nSubMode);
QTimer::singleShot (50, [=] {m_nSubMode=m_settings->value("SubMode_Q65",0).toInt();});
QTimer::singleShot (75, [=] {ui->sbSubmode->setValue(m_settings->value("SubMode_Q65",0).toInt());});
QTimer::singleShot (100, [=] {on_sbSubmode_valueChanged(m_nSubMode);});
// restore last used parameters
ui->sbTR->setValue (m_settings->value ("TRPeriod_Q65", 30).toInt());
ui->sbFtol->setValue (m_settings->value ("Ftol_Q65", 50).toInt());
m_nSubMode=m_settings->value("SubMode_Q65",0).toInt();
ui->sbSubmode->setValue(m_settings->value("SubMode_Q65",0).toInt());
QTimer::singleShot (50, [=] {
on_sbTR_valueChanged (ui->sbTR->value());
on_sbSubmode_valueChanged(ui->sbSubmode->value());
});
m_bShMsgs=m_settings->value("ShMsgs_Q65",false).toBool();
ui->cbShMsgs->setChecked(m_bShMsgs);
QString fname {QDir::toNativeSeparators(m_config.temp_dir().absoluteFilePath ("red.dat"))};
m_wideGraph->setRedFile(fname);
m_wideGraph->setMode(m_mode);
@ -7277,8 +7470,6 @@ void MainWindow::on_actionQ65_triggered()
switch_mode (Modes::Q65);
// 01234567890123456789012345678901234567
displayWidgets(nWidgets("11111101011011010011100000010000000011"));
ui->lh_decodes_title_label->setText(tr ("Single-Period Decodes"));
ui->rh_decodes_title_label->setText(tr ("Average Decodes"));
ui->lh_decodes_headings_label->setText("UTC dB DT Freq " + tr ("Message"));
ui->rh_decodes_headings_label->setText("UTC dB DT Freq " + tr ("Message"));
@ -7330,6 +7521,10 @@ void MainWindow::on_actionMSK144_triggered()
return;
}
m_mode="MSK144";
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
ui->actionMSK144->setChecked(true);
switch_mode (Modes::MSK144);
m_nsps=6;
@ -7343,11 +7538,10 @@ void MainWindow::on_actionMSK144_triggered()
m_bFastMode=true;
m_bFast9=false;
ui->sbTR->values ({5, 10, 15, 30});
ui->sbTR->setValue (m_settings->value ("TRPeriod_MSK144", 15).toInt()); // remember sbTR settings by mode
QTimer::singleShot (50, [=] {
on_sbTR_valueChanged (ui->sbTR->value());
on_sbSubmode_valueChanged(ui->sbSubmode->value());
});
ui->sbTR->setValue (m_settings->value ("TRPeriod_MSK144", 15).toInt()); // restore last used TRperiod
QTimer::singleShot (50, [=] {on_sbTR_valueChanged (ui->sbTR->value());});
m_bShMsgs=m_settings->value("ShMsgs_MSK144",false).toBool();
ui->cbShMsgs->setChecked(m_bShMsgs);
m_wideGraph->hide();
m_fastGraph->showNormal();
ui->TxFreqSpinBox->setValue(1500);
@ -7388,6 +7582,10 @@ void MainWindow::on_actionMSK144_triggered()
void MainWindow::on_actionWSPR_triggered()
{
m_mode="WSPR";
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
WSPR_config(true);
switch_mode (Modes::WSPR);
m_TRperiod=120.0;
@ -7424,6 +7622,10 @@ void MainWindow::on_actionEcho_triggered()
if(nd==3) ui->actionDeepestDecode->setChecked (true);
m_mode="Echo";
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
ui->actionEcho->setChecked(true);
m_TRperiod=3.0;
m_modulator->setTRPeriod(m_TRperiod); // TODO - not thread safe
@ -7458,6 +7660,10 @@ void MainWindow::on_actionFreqCal_triggered()
{
on_actionJT9_triggered();
m_mode="FreqCal";
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
ui->actionFreqCal->setChecked(true);
switch_mode(Modes::FreqCal);
m_wideGraph->setMode(m_mode);
@ -7652,6 +7858,7 @@ void MainWindow::on_actionDeepestDecode_toggled (bool checked)
void MainWindow::on_actionInclude_averaging_toggled (bool checked)
{
m_ndepth ^= (-checked ^ m_ndepth) & 0x00000010;
statusChanged();
}
void MainWindow::on_actionInclude_correlation_toggled (bool checked)
@ -8008,6 +8215,7 @@ void MainWindow::setXIT(int n, Frequency base)
void MainWindow::setFreq4(int rxFreq, int txFreq)
{
if (m_mode=="ECHO") return; // we do not adjust rx/tx for echo mode -- always 1500Hz
if (ui->RxFreqSpinBox->isEnabled ()) ui->RxFreqSpinBox->setValue(rxFreq);
if(m_mode=="WSPR" or m_mode=="FST4W") {
ui->WSPRfreqSpinBox->setValue(txFreq);
@ -8449,6 +8657,14 @@ void MainWindow::on_sbFtol_valueChanged(int value)
{
m_wideGraph->setTol (value);
statusUpdate ();
// save last used parameters
QTimer::singleShot (200, [=] {
if (m_mode=="Q65") m_settings->setValue ("Ftol_Q65", ui->sbFtol->value());
if (m_mode=="MSK144") m_settings->setValue ("Ftol_MSK144", ui->sbFtol->value());
if (m_mode=="JT65") m_settings->setValue ("Ftol_JT65", ui->sbFtol->value ());
if (m_mode=="JT4") m_settings->setValue ("Ftol_JT4", ui->sbFtol->value());
if (m_mode=="JT9") m_settings->setValue ("Ftol_JT9", ui->sbFtol->value ());
});
}
void::MainWindow::VHF_features_enabled(bool b)
@ -8510,19 +8726,25 @@ void MainWindow::on_sbTR_valueChanged(int value)
m_wideGraph->setPeriod (value, m_nsps);
progressBar.setMaximum (value);
}
if (m_mode=="Q65") {
QTimer::singleShot (200, [=] {m_settings->setValue ("TRPeriod_Q65", ui->sbTR->value ());});
}
if (m_mode=="MSK144") {
QTimer::singleShot (200, [=] {m_settings->setValue ("TRPeriod_MSK144", ui->sbTR->value ());});
}
if (m_mode=="FST4") {
chk_FST4_freq_range();
QTimer::singleShot (200, [=] {m_settings->setValue ("TRPeriod_FST4", ui->sbTR->value ());});
}
// if(m_transmitting) on_stopTxButton_clicked(); //### Is this needed or desirable? ###
if (m_mode=="FST4") chk_FST4_freq_range();
on_sbSubmode_valueChanged(ui->sbSubmode->value());
statusUpdate ();
// save last used parameters
QTimer::singleShot (200, [=] {
if (m_mode=="Q65") m_settings->setValue ("TRPeriod_Q65", ui->sbTR->value ());
if (m_mode=="MSK144" && (!(m_currentBand=="6m" or m_currentBand=="4m" or m_currentBand=="2m"))) {
m_settings->setValue ("TRPeriod_MSK144", ui->sbTR->value ());
}
if (m_mode=="MSK144" && (m_currentBand=="6m" or m_currentBand=="4m")) {
m_settings->setValue ("TRPeriod_MSK144_6m", ui->sbTR->value ());
}
if (m_mode=="MSK144" && m_currentBand=="2m") {
m_settings->setValue ("TRPeriod_MSK144_2m", ui->sbTR->value ());
}
if (m_mode=="FST4") m_settings->setValue ("TRPeriod_FST4", ui->sbTR->value ());
if (m_mode=="JT9") m_settings->setValue ("TRPeriod", ui->sbTR->value ());
});
}
void MainWindow::on_sbTR_FST4W_valueChanged(int value)
@ -8569,17 +8791,21 @@ void MainWindow::on_sbSubmode_valueChanged(int n)
ui->sbTR->setVisible(false);
m_TRperiod=60.0;
} else {
ui->cbFast9->setEnabled(true);
if(!blocked) ui->cbFast9->setEnabled(true);
}
ui->sbTR->setVisible(m_bFast9);
if(m_bFast9) ui->TxFreqSpinBox->setValue(700);
}
if(m_transmitting and m_bFast9 and m_nSubMode>=4) transmit (99.0);
if (m_mode !="Q65") ui->TxFreqSpinBox->setStyleSheet("");
if (m_mode=="Q65") {QTimer::singleShot (200, [=] {m_settings->setValue("SubMode_Q65",ui->sbSubmode->value());});}
if (m_mode=="JT65") {QTimer::singleShot (200, [=] {m_settings->setValue("SubMode_JT65",ui->sbSubmode->value());});}
if (m_mode=="JT4") {QTimer::singleShot (200, [=] {m_settings->setValue("SubMode_JT4",ui->sbSubmode->value());});}
statusUpdate ();
// save last used parameters
QTimer::singleShot (200, [=] {
if (m_mode=="Q65") m_settings->setValue("SubMode_Q65",ui->sbSubmode->value());
if (m_mode=="JT65") m_settings->setValue("SubMode_JT65",ui->sbSubmode->value());
if (m_mode=="JT4") m_settings->setValue("SubMode_JT4",ui->sbSubmode->value());
if (m_mode=="JT9") m_settings->setValue("SubMode",ui->sbSubmode->value());
});
}
void MainWindow::on_cbFast9_clicked(bool b)
@ -8587,7 +8813,12 @@ void MainWindow::on_cbFast9_clicked(bool b)
if(m_mode=="JT9") {
m_bFast9=b;
// ui->cbAutoSeq->setVisible(b);
blocked=true; // needed to prevent a loop
on_actionJT9_triggered();
QTimer::singleShot (50, [=] {blocked = false;}); // needed to prevent a loop
QTimer::singleShot (200, [=] {
if(m_mode=="JT9") m_settings->setValue("JT9_Fast",m_bFast9);
});
}
if(b) {
@ -8619,6 +8850,12 @@ void MainWindow::on_cbShMsgs_toggled(bool b)
if(ntx==4) ui->txrb4->setChecked(true);
if(ntx==5) ui->txrb5->setChecked(true);
if(ntx==6) ui->txrb6->setChecked(true);
QTimer::singleShot (200, [=] {
if(m_mode=="MSK144") m_settings->setValue("ShMsgs_MSK144",m_bShMsgs);
if(m_mode=="Q65") m_settings->setValue("ShMsgs_Q65",m_bShMsgs);
if(m_mode=="JT65") m_settings->setValue("ShMsgs_JT65",m_bShMsgs);
if(m_mode=="JT4") m_settings->setValue("ShMsgs_JT4",m_bShMsgs);
});
}
void MainWindow::on_cbSWL_toggled(bool b)
@ -8823,6 +9060,7 @@ void MainWindow::p1ReadFromStdout() //p1readFromStdout
}
killFileTimer.start (45*1000); //Kill in 45s (for slow modes)
}
ndecodes_label.setText(QString::number(m_nWSPRdecodes));
m_nWSPRdecodes=0;
ui->DecodeButton->setChecked (false);
if(m_uploadWSPRSpots && m_config.is_transceiver_online()) { // need working rig control
@ -9440,28 +9678,35 @@ void MainWindow::readWidebandDecodes()
if(m_ActiveStationsWidget==NULL) return;
int nhr=0;
int nmin=0;
int nsec=0;
int nsnr=0;
while(m_fetched < qmapcom.ndecodes) {
// Recover and parse each decoded line.
QString line=QString::fromLatin1(qmapcom.result[m_fetched]);
m_fetched++;
nhr=line.mid(0,2).toInt();
nmin=line.mid(2,2).toInt();
double frx=line.mid(4,9).toDouble();
double fsked=line.mid(13,7).toDouble();
QString msg=line.mid(34,-1);
nsec=line.mid(4,2).toInt();
double frx=line.mid(6,9).toDouble();
double fsked=line.mid(16,7).toDouble();
QString submode=line.mid(36,3);
QString msg=line.mid(41,-1);
int i1=msg.indexOf(" ");
int i2=i1 +1 + msg.mid(i1+1,-1).indexOf(" ");
QString dxcall=msg.mid(i1+1,i2-i1-1);
if(stdCall(dxcall)) {
QString w3=msg.mid(i2+1,-1);
nsnr=line.mid(29,3).toInt();
nsnr=line.mid(31,3).toInt();
m_EMECall[dxcall].frx=frx;
m_EMECall[dxcall].fsked=fsked;
m_EMECall[dxcall].nsnr=nsnr;
m_EMECall[dxcall].t=60*nhr + nmin;
m_EMECall[dxcall].t=3600*nhr + 60*nmin + nsec;
m_EMECall[dxcall].submode=submode;
//### Make sure WSJT-X is set to a Q65 submode consistent with the executing QMAP.
if(w3.contains(grid_regexp)) m_EMECall[dxcall].grid4=w3;
bool bCQ=line.contains(" CQ ");
m_EMECall[dxcall].ready2call=(bCQ or line.contains(" 73") or line.contains(" RR73"));
// m_EMECall[dxcall].ready2call=(bCQ or line.contains(" 73") or line.contains(" RR73"));
m_EMECall[dxcall].ready2call=(bCQ);
Frequency frequency = (m_freqNominal/1000000) * 1000000 + int(fsked*1000.0);
bool bFromDisk=qmapcom.nQDecoderDone==2;
if(!bFromDisk and (m_EMECall[dxcall].grid4.contains(grid_regexp) or bCQ)) {
@ -9497,8 +9742,11 @@ void MainWindow::readWidebandDecodes()
if(m_ActiveStationsWidget->readyOnly() and !i->ready2call) bSkip=true;
if(!bSkip) {
int snr=i->nsnr;
int odd=1 - (i->t)%2;
int age=60*nhr + nmin - (i->t);
QString submode=i->submode;
int odd=0;
if(submode.left(2)=="30" and (i->t%60)==0) odd=1;
if(submode.left(2)=="60" and (i->t%120)==0) odd=1;
int age=(3600*nhr + 60*nmin + nsec - (i->t))/60;
char c2[3]={32,32,0};
if(age<0) age += 1440;
if(age<=maxAge) {
@ -9506,7 +9754,8 @@ void MainWindow::readWidebandDecodes()
dxgrid4=(i->grid4+"... ").left(4);
if(!m_EMEworked[dxcall.trimmed()]) c2[0]=35; //# for not in log
if(i->ready2call) c2[1]=42; //* for ready to call
t1=t1.asprintf("%7.3f %5.1f %+03d %8s %4s %3d %3d %2s\n",i->frx,i->fsked,snr,dxcall.toLatin1().constData(),
t1=t1.asprintf("%7.3f %5.1f %+03d %3s %8s %4s %3d %3d %2s\n",i->frx,i->fsked,snr,
submode.toLatin1().constData(),dxcall.toLatin1().constData(),
dxgrid4.toLatin1().constData(),odd,age,c2);
f[k]=i->fsked;
list.append(t1);
@ -9963,10 +10212,7 @@ list1Done:
if(list2.size()==m_Nslots) {
break;
}
if(m_foxQSO.count()>=5*3 /* could have 5 slots * 3 states ([0-2],4,5) */) {
break;
}
}
list2Done:
@ -10475,7 +10721,7 @@ void MainWindow::remote_configure (QString const& mode, quint32 frequency_tolera
{
if (mode.size ())
{
set_mode (mode);
if (mode != m_mode) set_mode (mode);
}
auto is_FST4W = "FST4W" == m_mode;
if (frequency_tolerance != quint32_max && (ui->sbFtol->isVisible () || is_FST4W))
@ -10596,45 +10842,33 @@ void MainWindow::on_houndButton_clicked (bool checked)
void MainWindow::on_ft8Button_clicked()
{
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
on_actionFT8_triggered();
if (m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
on_actionFT8_triggered();
}
void MainWindow::on_ft4Button_clicked()
{
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
on_actionFT4_triggered();
on_actionFT4_triggered();
}
void MainWindow::on_msk144Button_clicked()
{
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
on_actionMSK144_triggered();
on_actionMSK144_triggered();
}
void MainWindow::on_q65Button_clicked()
{
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
on_actionQ65_triggered();
if (m_specOp==SpecOp::Q65_PILEUP) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
on_actionQ65_triggered();
}
void MainWindow::on_jt65Button_clicked()
{
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
on_actionJT65_triggered();
on_actionJT65_triggered();
}

View File

@ -719,6 +719,7 @@ private:
qint32 t;
bool worked;
bool ready2call;
QString submode;
};
QMap<QString,EMECall> m_EMECall;

View File

@ -3017,7 +3017,7 @@ QLabel[oob=&quot;true&quot;] {
<enum>Qt::StrongFocus</enum>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Switch to Q65 mode. Right-click to toggle Q65 Pileup mode On/Off.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Switch to Q65 mode.&lt;br&gt; Right-click to switch to Q65 Pileup mode.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Q65</string>
@ -3038,8 +3038,11 @@ QLabel[oob=&quot;true&quot;] {
<height>16777215</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="toolTip">
<string>Switch to JT65 mode</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Switch to JT65 mode. &lt;br&gt;Right-click to switch to JT9 mode.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>JT65</string>

View File

@ -263,7 +263,7 @@ void CPlotter::draw(float swide[], bool bScroll, bool bRed)
painter1.drawText (5, painter1.fontMetrics ().ascent (), t);
}
if(m_mode=="JT4" or (m_mode=="Q65" and m_nSubMode>=2)) {
if(m_mode=="JT4" or (m_mode=="Q65" and m_nSubMode>=3)) {
DrawOverlay();
QPen pen3(Qt::yellow); //Mark freqs of JT4/Q65 single-tone msgs
painter2D.setPen(pen3);