[hamradio-commits] [wsjtx] 01/02: Imported Upstream version 1.1.r3496
Iain R. Learmonth
irl at moszumanska.debian.org
Sun Oct 18 15:02:18 UTC 2015
This is an automated email from the git hooks/post-receive script.
irl pushed a commit to branch master
in repository wsjtx.
commit dcdaca79e76b8b9863b33ad3e9d7a20c18ee02a4
Author: Iain R. Learmonth <irl at debian.org>
Date: Sun Oct 18 15:59:59 2015 +0100
Imported Upstream version 1.1.r3496
---
LICENSE_WHEATLEY.TXT | 30 +
PSKReporter.h | 127 +++
QtSupport.iss | 10 +
about.cpp | 23 +
about.h | 24 +
about.ui | 40 +
afmhot.dat | 257 +++++
blue.dat | 256 +++++
commons.h | 35 +
devsetup.cpp | 595 ++++++++++
devsetup.h | 120 ++
devsetup.ui | 2599 ++++++++++++++++++++++++++++++++++++++++++
displaytext.cpp | 16 +
displaytext.h | 22 +
ffft.f | 69 ++
fftw3.f | 64 ++
getdev.cpp | 259 +++++
getfile.cpp | 199 ++++
getfile.h | 18 +
in.dat | 16 +
jt9.txt | 65 ++
killbyname.cpp | 284 +++++
lib/Makefile.MinGW | 117 ++
lib/Makefile.linux | 104 ++
lib/afc65b.f90 | 59 +
lib/afc9.f90 | 58 +
lib/analytic.f90 | 25 +
lib/azdist.f90 | 107 ++
lib/bpskmetrics.dat | 256 +++++
lib/ccf2.f90 | 45 +
lib/ccf65.f90 | 117 ++
lib/char.h | 57 +
lib/chkhist.f90 | 21 +
lib/chkmsg.f90 | 31 +
lib/chkss2.f90 | 24 +
lib/constants.f90 | 5 +
lib/conv232.f90 | 38 +
lib/cutil.c | 93 ++
lib/db.f90 | 5 +
lib/decode65a.f90 | 95 ++
lib/decode65b.f90 | 36 +
lib/decode9.f90 | 85 ++
lib/decode_rs.c | 263 +++++
lib/decoder.f90 | 173 +++
lib/deep24.f90 | 182 +++
lib/deg2grid.f90 | 30 +
lib/demod64a.f90 | 73 ++
lib/downsam9.f90 | 66 ++
lib/encode232.f90 | 33 +
lib/encode4.f90 | 20 +
lib/encode_rs.c | 52 +
lib/entail.f90 | 30 +
lib/extract.F90 | 103 ++
lib/extract4.f90 | 61 +
lib/f77_wisdom.f90 | 45 +
lib/fano232.f90 | 140 +++
lib/fchisq.f90 | 41 +
lib/fchisq65.f90 | 68 ++
lib/fftw3.f90 | 64 ++
lib/fil3.f90 | 159 +++
lib/fil61.f90 | 64 ++
lib/fil6521.f90 | 44 +
lib/filbig.f90 | 127 +++
lib/fillcom.f90 | 25 +
lib/flat1.f90 | 30 +
lib/flat2.f90 | 18 +
lib/flat65.f90 | 25 +
lib/four2a.f90 | 90 ++
lib/gen24.f90 | 86 ++
lib/gen65.f90 | 65 ++
lib/genjt9.f90 | 58 +
lib/genmet.f90 | 88 ++
lib/geodist.f90 | 96 ++
lib/getlags.f90 | 27 +
lib/getmet24.f90 | 52 +
lib/getpfx1.f90 | 97 ++
lib/getpfx2.f90 | 24 +
lib/gran.c | 28 +
lib/graycode.f90 | 9 +
lib/graycode65.f90 | 9 +
lib/grid2deg.f90 | 38 +
lib/grid2k.f90 | 12 +
lib/grid2n.f90 | 10 +
lib/igray.c | 18 +
lib/indexx.f90 | 19 +
lib/init_rs.c | 126 +++
lib/int.h | 57 +
lib/interleave24.f90 | 43 +
lib/interleave63.f90 | 25 +
lib/interleave8.f90 | 17 +
lib/interleave9.f90 | 39 +
lib/ipcomm.cpp | 50 +
lib/jt65.f90 | 68 ++
lib/jt65a.f90 | 85 ++
lib/jt9.f90 | 111 ++
lib/jt9a.f90 | 72 ++
lib/jt9b.f90 | 12 +
lib/jt9c.f90 | 21 +
lib/jt9code.f90 | 29 +
lib/jt9sim.f90 | 166 +++
lib/jt9sync.f90 | 18 +
lib/k2grid.f90 | 12 +
lib/libhamlib.dll.a | Bin 0 -> 177492 bytes
lib/met8.21 | 256 +++++
lib/morse.f90 | 86 ++
lib/move.f90 | 7 +
lib/msgs.txt | 60 +
lib/n2grid.f90 | 14 +
lib/nchar.f90 | 23 +
lib/noisegen.f90 | 13 +
lib/packbits.f90 | 21 +
lib/packcall.f90 | 79 ++
lib/packdxcc.f90 | 64 ++
lib/packgrid.f90 | 76 ++
lib/packmsg.f90 | 113 ++
lib/packtext.f90 | 47 +
lib/pctile.f90 | 22 +
lib/peakdt9.f90 | 54 +
lib/peakup.f90 | 8 +
lib/pfx.f90 | 50 +
lib/pfxdump.f90 | 13 +
lib/ps24.f90 | 27 +
lib/ptt.c | 50 +
lib/rig_control.c | 99 ++
lib/rs.h | 35 +
lib/s3avg.f90 | 60 +
lib/sec_midn.f90 | 11 +
lib/setup65.f90 | 96 ++
lib/sleep.h | 32 +
lib/sleep_msec.f90 | 4 +
lib/slope.f90 | 40 +
lib/smo121.f90 | 13 +
lib/softsym.f90 | 50 +
lib/sort.f90 | 4 +
lib/ss.bat | 1 +
lib/ssort.f90 | 264 +++++
lib/stdmsg.f90 | 12 +
lib/symspec.f90 | 113 ++
lib/symspec2.f90 | 88 ++
lib/symspec65.f90 | 47 +
lib/sync24.f90 | 179 +++
lib/sync9.f90 | 101 ++
lib/tab.c | 36 +
lib/timer.f90 | 112 ++
lib/timeval.h | 74 ++
lib/tstrig.c | 26 +
lib/tstrig.h | 50 +
lib/twkfreq.f90 | 28 +
lib/twkfreq65.f90 | 25 +
lib/unpackbits.f90 | 22 +
lib/unpackcall.f90 | 142 +++
lib/unpackgrid.f90 | 45 +
lib/unpackmsg.f90 | 107 ++
lib/unpacktext.f90 | 35 +
lib/vit216.c | 219 ++++
lib/wrapkarn.c | 70 ++
lib/wsjt24.f90 | 181 +++
lib/wsjt24d.f90 | 43 +
lib/xcor24.f90 | 94 ++
lib/zplot9.f90 | 31 +
logqso.cpp | 174 +++
logqso.h | 53 +
logqso.ui | 759 +++++++++++++
main.cpp | 60 +
mainwindow.cpp | 3052 ++++++++++++++++++++++++++++++++++++++++++++++++++
mainwindow.h | 392 +++++++
mainwindow.ui | 2925 +++++++++++++++++++++++++++++++++++++++++++++++
meterwidget.cpp | 51 +
meterwidget.h | 30 +
mouse_commands.txt | 18 +
paInputDevice.c | 56 +
pa_get_device_info.c | 172 +++
plotter.cpp | 565 ++++++++++
plotter.h | 139 +++
psk_reporter.cpp | 104 ++
psk_reporter.h | 41 +
rigclass.cpp | 324 ++++++
rigclass.h | 98 ++
shortcuts.txt | 26 +
signalmeter.cpp | 53 +
signalmeter.h | 32 +
sleep.h | 16 +
soundin.cpp | 208 ++++
soundin.h | 50 +
soundout.cpp | 270 +++++
soundout.h | 53 +
ss.bat | 1 +
sss.bat | 1 +
widegraph.cpp | 314 ++++++
widegraph.h | 89 ++
widegraph.ui | 398 +++++++
wsjt.ico | Bin 0 -> 1078 bytes
wsjtx.iss | 23 +
wsjtx.pro | 81 ++
wsjtx.rc | 1 +
wsjtx_changelog.txt | 791 +++++++++++++
wsjtx_opti.iss | 23 +
197 files changed, 25334 insertions(+)
diff --git a/LICENSE_WHEATLEY.TXT b/LICENSE_WHEATLEY.TXT
new file mode 100644
index 0000000..8b0ce24
--- /dev/null
+++ b/LICENSE_WHEATLEY.TXT
@@ -0,0 +1,30 @@
++ + + This Software is released under the "Simplified BSD License" + + +
+Copyright 2010 Moe Wheatley. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+THIS SOFTWARE IS PROVIDED BY Moe Wheatley ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL Moe Wheatley OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The views and conclusions contained in the software and documentation
+are those of the authors and should not be interpreted as representing
+official policies, either expressed or implied, of Moe Wheatley.
diff --git a/PSKReporter.h b/PSKReporter.h
new file mode 100644
index 0000000..a6c52c4
--- /dev/null
+++ b/PSKReporter.h
@@ -0,0 +1,127 @@
+#pragma once
+
+// Main header file for the external interface to the PSK Reporter API
+// For documentation see http://psk.gladstonefamily.net/PSKReporterAPI.pdf
+
+/*
+
+Copyright (c) 2008 Philip Gladstone
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+ */
+
+
+#ifdef _DLL_OPTION_PSKREPORTER_EXPORT
+#define DllImportExport __declspec ( dllexport )
+#else
+#define DllImportExport __declspec ( dllimport )
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define REPORTER_SOURCE_MASK 0x07
+#define REPORTER_SOURCE_AUTOMATIC 0x01
+#define REPORTER_SOURCE_LOG 0x02
+#define REPORTER_SOURCE_MANUAL 0x03
+#define REPORTER_SOURCE_TENTATIVE 0x40
+#define REPORTER_SOURCE_TEST 0x80
+
+typedef struct {
+ wchar_t hostname[256];
+ wchar_t port[32];
+ bool connected;
+ unsigned int callsigns_sent;
+ unsigned int callsigns_buffered;
+ unsigned int callsigns_discarded;
+ unsigned int last_send_time;
+ unsigned int next_send_time;
+ wchar_t last_callsign_queued[24];
+ unsigned int bytes_sent;
+ unsigned int bytes_sent_total;
+ unsigned int packets_sent;
+ unsigned int packets_sent_total;
+} REPORTER_STATISTICS;
+
+
+
+
+unsigned long DllImportExport __cdecl ReporterInitialize(
+ const wchar_t *hostname,
+ const wchar_t *port
+);
+
+unsigned long DllImportExport __cdecl ReporterSeenCallsign(
+ const wchar_t *remoteInformation,
+ const wchar_t *localInformation,
+ unsigned long flags
+);
+
+unsigned long DllImportExport __cdecl ReporterTickle(
+);
+
+unsigned long DllImportExport __cdecl ReporterGetInformation(
+ wchar_t *buffer,
+ unsigned long maxlen
+);
+
+unsigned long DllImportExport __cdecl ReporterGetStatistics(
+ REPORTER_STATISTICS *buffer,
+ unsigned long maxlen
+);
+
+unsigned long DllImportExport __cdecl ReporterUninitialize(
+);
+
+
+unsigned long DllImportExport __stdcall ReporterInitializeSTD(
+ const char *hostname,
+ const char *port
+);
+
+unsigned long DllImportExport __stdcall ReporterSeenCallsignSTD(
+ const char *remoteInformation,
+ const char *localInformation,
+ unsigned long flags
+);
+
+unsigned long DllImportExport __stdcall ReporterTickleSTD(
+);
+
+unsigned long DllImportExport __stdcall ReporterGetInformationSTD(
+ char *buffer,
+ unsigned long maxlen
+);
+
+unsigned long DllImportExport __stdcall ReporterGetStatisticsSTD(
+ REPORTER_STATISTICS *buffer,
+ unsigned long maxlen
+);
+
+unsigned long DllImportExport __stdcall ReporterUninitializeSTD(
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+
diff --git a/QtSupport.iss b/QtSupport.iss
new file mode 100644
index 0000000..a7144c2
--- /dev/null
+++ b/QtSupport.iss
@@ -0,0 +1,10 @@
+[Setup]
+AppName="QtSupport for MAP65"
+AppVerName=QtSupport
+DefaultDirName=C:\MAP65
+
+[Files]
+Source: "c:\Users\joe\map65\QtSupport\*.dll"; DestDir: "{app}"; Flags: onlyifdoesntexist
+
+
+
diff --git a/about.cpp b/about.cpp
new file mode 100644
index 0000000..5cab294
--- /dev/null
+++ b/about.cpp
@@ -0,0 +1,23 @@
+#include "about.h"
+#include "ui_about.h"
+
+CAboutDlg::CAboutDlg(QWidget *parent, QString Revision) :
+ QDialog(parent),
+ m_Revision(Revision),
+ ui(new Ui::CAboutDlg)
+{
+ ui->setupUi(this);
+ ui->labelTxt->clear();
+ m_Str = "<html><h2>" + m_Revision + "</h2>\n\n";
+ m_Str += "WSJT-X implements experimental mode JT9 for <br>";
+ m_Str += "Amateur Radio communication at HF, MF, and LF. <br><br>";
+ m_Str += "Copyright 2001-2013 by Joe Taylor, K1JT. Additional <br>";
+ m_Str += "contributions from AC6SL, AE4JY, G4KLA, K3WYC, PY2SDR, <br>";
+ m_Str += "and VK4BDJ.<br>";
+ ui->labelTxt->setText(m_Str);
+}
+
+CAboutDlg::~CAboutDlg()
+{
+ delete ui;
+}
diff --git a/about.h b/about.h
new file mode 100644
index 0000000..ca45d19
--- /dev/null
+++ b/about.h
@@ -0,0 +1,24 @@
+#ifndef ABOUTDLG_H
+#define ABOUTDLG_H
+
+#include <QDialog>
+
+namespace Ui {
+ class CAboutDlg;
+}
+
+class CAboutDlg : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit CAboutDlg(QWidget *parent=0, QString Revision="");
+ ~CAboutDlg();
+
+private:
+ QString m_Revision;
+ Ui::CAboutDlg *ui;
+ QString m_Str;
+};
+
+#endif // ABOUTDLG_H
diff --git a/about.ui b/about.ui
new file mode 100644
index 0000000..3a86259
--- /dev/null
+++ b/about.ui
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CAboutDlg</class>
+ <widget class="QDialog" name="CAboutDlg">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>374</width>
+ <height>164</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>About WSJT-X</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="labelTxt">
+ <property name="text">
+ <string/>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/afmhot.dat b/afmhot.dat
new file mode 100644
index 0000000..8b312a1
--- /dev/null
+++ b/afmhot.dat
@@ -0,0 +1,257 @@
+ 0 0.0000 0.0000 0.0000
+ 1 0.0000 0.0000 0.0000
+ 2 0.0078 0.0000 0.0000
+ 3 0.0157 0.0000 0.0000
+ 4 0.0235 0.0000 0.0000
+ 5 0.0314 0.0000 0.0000
+ 6 0.0392 0.0000 0.0000
+ 7 0.0471 0.0000 0.0000
+ 8 0.0549 0.0000 0.0000
+ 9 0.0627 0.0000 0.0000
+ 10 0.0706 0.0000 0.0000
+ 11 0.0784 0.0000 0.0000
+ 12 0.0863 0.0000 0.0000
+ 13 0.0941 0.0000 0.0000
+ 14 0.1020 0.0000 0.0000
+ 15 0.1098 0.0000 0.0000
+ 16 0.1176 0.0000 0.0000
+ 17 0.1255 0.0000 0.0000
+ 18 0.1333 0.0000 0.0000
+ 19 0.1412 0.0000 0.0000
+ 20 0.1490 0.0000 0.0000
+ 21 0.1569 0.0000 0.0000
+ 22 0.1647 0.0000 0.0000
+ 23 0.1725 0.0000 0.0000
+ 24 0.1804 0.0000 0.0000
+ 25 0.1882 0.0000 0.0000
+ 26 0.1961 0.0000 0.0000
+ 27 0.2039 0.0000 0.0000
+ 28 0.2118 0.0000 0.0000
+ 29 0.2196 0.0000 0.0000
+ 30 0.2275 0.0000 0.0000
+ 31 0.2353 0.0000 0.0000
+ 32 0.2431 0.0000 0.0000
+ 33 0.2510 0.0000 0.0000
+ 34 0.2588 0.0000 0.0000
+ 35 0.2667 0.0000 0.0000
+ 36 0.2745 0.0000 0.0000
+ 37 0.2824 0.0000 0.0000
+ 38 0.2902 0.0000 0.0000
+ 39 0.2980 0.0000 0.0000
+ 40 0.3059 0.0000 0.0000
+ 41 0.3137 0.0000 0.0000
+ 42 0.3216 0.0000 0.0000
+ 43 0.3294 0.0000 0.0000
+ 44 0.3373 0.0000 0.0000
+ 45 0.3451 0.0000 0.0000
+ 46 0.3529 0.0000 0.0000
+ 47 0.3608 0.0000 0.0000
+ 48 0.3686 0.0000 0.0000
+ 49 0.3765 0.0000 0.0000
+ 50 0.3843 0.0000 0.0000
+ 51 0.3922 0.0000 0.0000
+ 52 0.4000 0.0000 0.0000
+ 53 0.4078 0.0000 0.0000
+ 54 0.4157 0.0000 0.0000
+ 55 0.4235 0.0000 0.0000
+ 56 0.4314 0.0000 0.0000
+ 57 0.4392 0.0000 0.0000
+ 58 0.4471 0.0000 0.0000
+ 59 0.4549 0.0000 0.0000
+ 60 0.4627 0.0000 0.0000
+ 61 0.4706 0.0000 0.0000
+ 62 0.4784 0.0000 0.0000
+ 63 0.4863 0.0000 0.0000
+ 64 0.4941 0.0000 0.0000
+ 65 0.5020 0.0000 0.0000
+ 66 0.5098 0.0098 0.0000
+ 67 0.5176 0.0176 0.0000
+ 68 0.5255 0.0255 0.0000
+ 69 0.5333 0.0333 0.0000
+ 70 0.5412 0.0412 0.0000
+ 71 0.5490 0.0490 0.0000
+ 72 0.5569 0.0569 0.0000
+ 73 0.5647 0.0647 0.0000
+ 74 0.5725 0.0725 0.0000
+ 75 0.5804 0.0804 0.0000
+ 76 0.5882 0.0882 0.0000
+ 77 0.5961 0.0961 0.0000
+ 78 0.6039 0.1039 0.0000
+ 79 0.6118 0.1118 0.0000
+ 80 0.6196 0.1196 0.0000
+ 81 0.6275 0.1275 0.0000
+ 82 0.6353 0.1353 0.0000
+ 83 0.6431 0.1431 0.0000
+ 84 0.6510 0.1510 0.0000
+ 85 0.6588 0.1588 0.0000
+ 86 0.6667 0.1667 0.0000
+ 87 0.6745 0.1745 0.0000
+ 88 0.6824 0.1824 0.0000
+ 89 0.6902 0.1902 0.0000
+ 90 0.6980 0.1980 0.0000
+ 91 0.7059 0.2059 0.0000
+ 92 0.7137 0.2137 0.0000
+ 93 0.7216 0.2216 0.0000
+ 94 0.7294 0.2294 0.0000
+ 95 0.7373 0.2373 0.0000
+ 96 0.7451 0.2451 0.0000
+ 97 0.7529 0.2529 0.0000
+ 98 0.7608 0.2608 0.0000
+ 99 0.7686 0.2686 0.0000
+ 100 0.7765 0.2765 0.0000
+ 101 0.7843 0.2843 0.0000
+ 102 0.7922 0.2922 0.0000
+ 103 0.8000 0.3000 0.0000
+ 104 0.8078 0.3078 0.0000
+ 105 0.8157 0.3157 0.0000
+ 106 0.8235 0.3235 0.0000
+ 107 0.8314 0.3314 0.0000
+ 108 0.8392 0.3392 0.0000
+ 109 0.8471 0.3471 0.0000
+ 110 0.8549 0.3549 0.0000
+ 111 0.8627 0.3627 0.0000
+ 112 0.8706 0.3706 0.0000
+ 113 0.8784 0.3784 0.0000
+ 114 0.8863 0.3863 0.0000
+ 115 0.8941 0.3941 0.0000
+ 116 0.9020 0.4020 0.0000
+ 117 0.9098 0.4098 0.0000
+ 118 0.9176 0.4176 0.0000
+ 119 0.9255 0.4255 0.0000
+ 120 0.9333 0.4333 0.0000
+ 121 0.9412 0.4412 0.0000
+ 122 0.9490 0.4490 0.0000
+ 123 0.9569 0.4569 0.0000
+ 124 0.9647 0.4647 0.0000
+ 125 0.9725 0.4725 0.0000
+ 126 0.9804 0.4804 0.0000
+ 127 0.9882 0.4882 0.0000
+ 128 0.9961 0.4961 0.0000
+ 129 1.0000 0.5039 0.0000
+ 130 1.0000 0.5118 0.0118
+ 131 1.0000 0.5196 0.0196
+ 132 1.0000 0.5275 0.0275
+ 133 1.0000 0.5353 0.0353
+ 134 1.0000 0.5431 0.0431
+ 135 1.0000 0.5510 0.0510
+ 136 1.0000 0.5588 0.0588
+ 137 1.0000 0.5667 0.0667
+ 138 1.0000 0.5745 0.0745
+ 139 1.0000 0.5824 0.0824
+ 140 1.0000 0.5902 0.0902
+ 141 1.0000 0.5980 0.0980
+ 142 1.0000 0.6059 0.1059
+ 143 1.0000 0.6137 0.1137
+ 144 1.0000 0.6216 0.1216
+ 145 1.0000 0.6294 0.1294
+ 146 1.0000 0.6373 0.1373
+ 147 1.0000 0.6451 0.1451
+ 148 1.0000 0.6529 0.1529
+ 149 1.0000 0.6608 0.1608
+ 150 1.0000 0.6686 0.1686
+ 151 1.0000 0.6765 0.1765
+ 152 1.0000 0.6843 0.1843
+ 153 1.0000 0.6922 0.1922
+ 154 1.0000 0.7000 0.2000
+ 155 1.0000 0.7078 0.2078
+ 156 1.0000 0.7157 0.2157
+ 157 1.0000 0.7235 0.2235
+ 158 1.0000 0.7314 0.2314
+ 159 1.0000 0.7392 0.2392
+ 160 1.0000 0.7471 0.2471
+ 161 1.0000 0.7549 0.2549
+ 162 1.0000 0.7627 0.2627
+ 163 1.0000 0.7706 0.2706
+ 164 1.0000 0.7784 0.2784
+ 165 1.0000 0.7863 0.2863
+ 166 1.0000 0.7941 0.2941
+ 167 1.0000 0.8020 0.3020
+ 168 1.0000 0.8098 0.3098
+ 169 1.0000 0.8176 0.3176
+ 170 1.0000 0.8255 0.3255
+ 171 1.0000 0.8333 0.3333
+ 172 1.0000 0.8412 0.3412
+ 173 1.0000 0.8490 0.3490
+ 174 1.0000 0.8569 0.3569
+ 175 1.0000 0.8647 0.3647
+ 176 1.0000 0.8725 0.3725
+ 177 1.0000 0.8804 0.3804
+ 178 1.0000 0.8882 0.3882
+ 179 1.0000 0.8961 0.3961
+ 180 1.0000 0.9039 0.4039
+ 181 1.0000 0.9118 0.4118
+ 182 1.0000 0.9196 0.4196
+ 183 1.0000 0.9275 0.4275
+ 184 1.0000 0.9353 0.4353
+ 185 1.0000 0.9431 0.4431
+ 186 1.0000 0.9510 0.4510
+ 187 1.0000 0.9588 0.4588
+ 188 1.0000 0.9667 0.4667
+ 189 1.0000 0.9745 0.4745
+ 190 1.0000 0.9824 0.4824
+ 191 1.0000 0.9902 0.4902
+ 192 1.0000 0.9980 0.4980
+ 193 1.0000 1.0000 0.5059
+ 194 1.0000 1.0000 0.5137
+ 195 1.0000 1.0000 0.5216
+ 196 1.0000 1.0000 0.5294
+ 197 1.0000 1.0000 0.5373
+ 198 1.0000 1.0000 0.5451
+ 199 1.0000 1.0000 0.5529
+ 200 1.0000 1.0000 0.5608
+ 201 1.0000 1.0000 0.5686
+ 202 1.0000 1.0000 0.5765
+ 203 1.0000 1.0000 0.5843
+ 204 1.0000 1.0000 0.5922
+ 205 1.0000 1.0000 0.6000
+ 206 1.0000 1.0000 0.6078
+ 207 1.0000 1.0000 0.6157
+ 208 1.0000 1.0000 0.6235
+ 209 1.0000 1.0000 0.6314
+ 210 1.0000 1.0000 0.6392
+ 211 1.0000 1.0000 0.6471
+ 212 1.0000 1.0000 0.6549
+ 213 1.0000 1.0000 0.6627
+ 214 1.0000 1.0000 0.6706
+ 215 1.0000 1.0000 0.6784
+ 216 1.0000 1.0000 0.6863
+ 217 1.0000 1.0000 0.6941
+ 218 1.0000 1.0000 0.7020
+ 219 1.0000 1.0000 0.7098
+ 220 1.0000 1.0000 0.7176
+ 221 1.0000 1.0000 0.7255
+ 222 1.0000 1.0000 0.7333
+ 223 1.0000 1.0000 0.7412
+ 224 1.0000 1.0000 0.7490
+ 225 1.0000 1.0000 0.7569
+ 226 1.0000 1.0000 0.7647
+ 227 1.0000 1.0000 0.7725
+ 228 1.0000 1.0000 0.7804
+ 229 1.0000 1.0000 0.7882
+ 230 1.0000 1.0000 0.7961
+ 231 1.0000 1.0000 0.8039
+ 232 1.0000 1.0000 0.8118
+ 233 1.0000 1.0000 0.8196
+ 234 1.0000 1.0000 0.8275
+ 235 1.0000 1.0000 0.8353
+ 236 1.0000 1.0000 0.8431
+ 237 1.0000 1.0000 0.8510
+ 238 1.0000 1.0000 0.8588
+ 239 1.0000 1.0000 0.8667
+ 240 1.0000 1.0000 0.8745
+ 241 1.0000 1.0000 0.8824
+ 242 1.0000 1.0000 0.8902
+ 243 1.0000 1.0000 0.8980
+ 244 1.0000 1.0000 0.9059
+ 245 1.0000 1.0000 0.9137
+ 246 1.0000 1.0000 0.9216
+ 247 1.0000 1.0000 0.9294
+ 248 1.0000 1.0000 0.9373
+ 249 1.0000 1.0000 0.9451
+ 250 1.0000 1.0000 0.9529
+ 251 1.0000 1.0000 0.9608
+ 252 1.0000 1.0000 0.9686
+ 253 1.0000 1.0000 0.9765
+ 254 1.0 0.0 0.0
+ 255 1.0 1.0 0.0
+ 256 0.0 1.000 0.0
diff --git a/blue.dat b/blue.dat
new file mode 100644
index 0000000..d9fc886
--- /dev/null
+++ b/blue.dat
@@ -0,0 +1,256 @@
+ 0 0.0000 0.0000 0.0000
+ 1 0.0902 0.0902 0.2558
+ 2 0.1176 0.1176 0.2694
+ 3 0.1412 0.1412 0.2820
+ 4 0.1569 0.1569 0.2938
+ 5 0.1725 0.1725 0.3049
+ 6 0.1843 0.1843 0.3154
+ 7 0.1961 0.1961 0.3254
+ 8 0.2039 0.2039 0.3349
+ 9 0.2157 0.2157 0.3440
+ 10 0.2235 0.2235 0.3528
+ 11 0.2314 0.2314 0.3612
+ 12 0.2392 0.2392 0.3693
+ 13 0.2471 0.2471 0.3772
+ 14 0.2549 0.2549 0.3848
+ 15 0.2588 0.2588 0.3921
+ 16 0.2667 0.2667 0.3992
+ 17 0.2706 0.2706 0.4061
+ 18 0.2784 0.2784 0.4129
+ 19 0.2824 0.2824 0.4194
+ 20 0.2902 0.2902 0.4258
+ 21 0.2941 0.2941 0.4319
+ 22 0.2980 0.2980 0.4380
+ 23 0.3059 0.3059 0.4439
+ 24 0.3098 0.3098 0.4496
+ 25 0.3137 0.3137 0.4553
+ 26 0.3176 0.3176 0.4608
+ 27 0.3216 0.3216 0.4661
+ 28 0.3294 0.3294 0.4714
+ 29 0.3333 0.3333 0.4765
+ 30 0.3373 0.3373 0.4815
+ 31 0.3412 0.3412 0.4865
+ 32 0.3451 0.3451 0.4913
+ 33 0.3490 0.3490 0.4960
+ 34 0.3529 0.3529 0.5006
+ 35 0.3569 0.3569 0.5052
+ 36 0.3608 0.3608 0.5096
+ 37 0.3647 0.3647 0.5140
+ 38 0.3686 0.3686 0.5183
+ 39 0.3725 0.3725 0.5225
+ 40 0.3765 0.3765 0.5266
+ 41 0.3804 0.3804 0.5306
+ 42 0.3843 0.3843 0.5346
+ 43 0.3843 0.3843 0.5385
+ 44 0.3882 0.3882 0.5423
+ 45 0.3922 0.3922 0.5460
+ 46 0.3961 0.3961 0.5497
+ 47 0.4000 0.4000 0.5533
+ 48 0.4039 0.4039 0.5569
+ 49 0.4078 0.4078 0.5603
+ 50 0.4118 0.4118 0.5638
+ 51 0.4118 0.4118 0.5671
+ 52 0.4157 0.4157 0.5704
+ 53 0.4196 0.4196 0.5736
+ 54 0.4235 0.4235 0.5768
+ 55 0.4275 0.4275 0.5799
+ 56 0.4314 0.4314 0.5829
+ 57 0.4314 0.4314 0.5859
+ 58 0.4353 0.4353 0.5889
+ 59 0.4392 0.4392 0.5917
+ 60 0.4431 0.4431 0.5946
+ 61 0.4471 0.4471 0.5973
+ 62 0.4471 0.4471 0.6001
+ 63 0.4510 0.4510 0.6027
+ 64 0.4549 0.4549 0.6053
+ 65 0.4588 0.4588 0.6079
+ 66 0.4627 0.4627 0.6104
+ 67 0.4627 0.4627 0.6129
+ 68 0.4667 0.4667 0.6153
+ 69 0.4706 0.4706 0.6176
+ 70 0.4745 0.4745 0.6199
+ 71 0.4745 0.4745 0.6222
+ 72 0.4784 0.4784 0.6244
+ 73 0.4824 0.4824 0.6266
+ 74 0.4863 0.4863 0.6287
+ 75 0.4863 0.4863 0.6308
+ 76 0.4902 0.4902 0.6328
+ 77 0.4941 0.4941 0.6348
+ 78 0.4980 0.4980 0.6367
+ 79 0.5020 0.5020 0.6386
+ 80 0.5020 0.5020 0.6404
+ 81 0.5059 0.5059 0.6422
+ 82 0.5098 0.5098 0.6440
+ 83 0.5098 0.5098 0.6457
+ 84 0.5137 0.5137 0.6474
+ 85 0.5176 0.5176 0.6490
+ 86 0.5216 0.5216 0.6506
+ 87 0.5216 0.5216 0.6521
+ 88 0.5255 0.5255 0.6536
+ 89 0.5294 0.5294 0.6551
+ 90 0.5333 0.5333 0.6565
+ 91 0.5333 0.5333 0.6578
+ 92 0.5373 0.5373 0.6591
+ 93 0.5412 0.5412 0.6604
+ 94 0.5451 0.5451 0.6617
+ 95 0.5451 0.5451 0.6629
+ 96 0.5490 0.5490 0.6640
+ 97 0.5529 0.5529 0.6651
+ 98 0.5569 0.5569 0.6662
+ 99 0.5569 0.5569 0.6672
+ 100 0.5608 0.5608 0.6682
+ 101 0.5647 0.5647 0.6692
+ 102 0.5647 0.5647 0.6701
+ 103 0.5686 0.5686 0.6710
+ 104 0.5725 0.5725 0.6718
+ 105 0.5765 0.5765 0.6726
+ 106 0.5765 0.5765 0.6733
+ 107 0.5804 0.5804 0.6740
+ 108 0.5843 0.5843 0.6747
+ 109 0.5843 0.5843 0.6753
+ 110 0.5882 0.5882 0.6759
+ 111 0.5922 0.5922 0.6765
+ 112 0.5961 0.5961 0.6770
+ 113 0.5961 0.5961 0.6774
+ 114 0.6000 0.6000 0.6779
+ 115 0.6039 0.6039 0.6783
+ 116 0.6039 0.6039 0.6786
+ 117 0.6078 0.6078 0.6789
+ 118 0.6118 0.6118 0.6792
+ 119 0.6157 0.6157 0.6794
+ 120 0.6157 0.6157 0.6796
+ 121 0.6196 0.6196 0.6798
+ 122 0.6235 0.6235 0.6799
+ 123 0.6235 0.6235 0.6800
+ 124 0.6275 0.6275 0.6800
+ 125 0.6314 0.6314 0.6800
+ 126 0.6353 0.6353 0.6799
+ 127 0.6353 0.6353 0.6799
+ 128 0.6392 0.6392 0.6797
+ 129 0.6431 0.6431 0.6796
+ 130 0.6431 0.6431 0.6794
+ 131 0.6471 0.6471 0.6791
+ 132 0.6510 0.6510 0.6789
+ 133 0.6549 0.6549 0.6785
+ 134 0.6549 0.6549 0.6782
+ 135 0.6588 0.6588 0.6778
+ 136 0.6627 0.6627 0.6773
+ 137 0.6627 0.6627 0.6769
+ 138 0.6667 0.6667 0.6763
+ 139 0.6706 0.6706 0.6758
+ 140 0.6745 0.6745 0.6752
+ 141 0.6745 0.6745 0.6746
+ 142 0.6784 0.6784 0.6739
+ 143 0.6824 0.6824 0.6732
+ 144 0.6824 0.6824 0.6724
+ 145 0.6863 0.6863 0.6716
+ 146 0.6902 0.6902 0.6708
+ 147 0.6941 0.6941 0.6699
+ 148 0.6941 0.6941 0.6690
+ 149 0.6980 0.6980 0.6680
+ 150 0.7020 0.7020 0.6670
+ 151 0.7020 0.7020 0.6660
+ 152 0.7059 0.7059 0.6649
+ 153 0.7098 0.7098 0.6638
+ 154 0.7098 0.7098 0.6626
+ 155 0.7137 0.7137 0.6614
+ 156 0.7176 0.7176 0.6601
+ 157 0.7216 0.7216 0.6589
+ 158 0.7216 0.7216 0.6575
+ 159 0.7255 0.7255 0.6561
+ 160 0.7294 0.7294 0.6547
+ 161 0.7294 0.7294 0.6533
+ 162 0.7333 0.7333 0.6518
+ 163 0.7373 0.7373 0.6502
+ 164 0.7412 0.7412 0.6486
+ 165 0.7412 0.7412 0.6470
+ 166 0.7451 0.7451 0.6453
+ 167 0.7490 0.7490 0.6436
+ 168 0.7490 0.7490 0.6418
+ 169 0.7529 0.7529 0.6400
+ 170 0.7569 0.7569 0.6382
+ 171 0.7608 0.7608 0.6363
+ 172 0.7608 0.7608 0.6343
+ 173 0.7647 0.7647 0.6324
+ 174 0.7686 0.7686 0.6303
+ 175 0.7686 0.7686 0.6282
+ 176 0.7725 0.7725 0.6261
+ 177 0.7765 0.7765 0.6239
+ 178 0.7804 0.7804 0.6217
+ 179 0.7804 0.7804 0.6194
+ 180 0.7843 0.7843 0.6171
+ 181 0.7882 0.7882 0.6147
+ 182 0.7882 0.7882 0.6123
+ 183 0.7922 0.7922 0.6098
+ 184 0.7961 0.7961 0.6073
+ 185 0.8000 0.8000 0.6047
+ 186 0.8000 0.8000 0.6021
+ 187 0.8039 0.8039 0.5994
+ 188 0.8078 0.8078 0.5967
+ 189 0.8078 0.8078 0.5939
+ 190 0.8118 0.8118 0.5911
+ 191 0.8157 0.8157 0.5882
+ 192 0.8196 0.8196 0.5853
+ 193 0.8196 0.8196 0.5823
+ 194 0.8235 0.8235 0.5792
+ 195 0.8275 0.8275 0.5761
+ 196 0.8275 0.8275 0.5729
+ 197 0.8314 0.8314 0.5697
+ 198 0.8353 0.8353 0.5664
+ 199 0.8392 0.8392 0.5630
+ 200 0.8392 0.8392 0.5596
+ 201 0.8431 0.8431 0.5561
+ 202 0.8471 0.8471 0.5525
+ 203 0.8471 0.8471 0.5489
+ 204 0.8510 0.8510 0.5452
+ 205 0.8549 0.8549 0.5414
+ 206 0.8588 0.8588 0.5376
+ 207 0.8588 0.8588 0.5337
+ 208 0.8627 0.8627 0.5297
+ 209 0.8667 0.8667 0.5257
+ 210 0.8667 0.8667 0.5215
+ 211 0.8706 0.8706 0.5173
+ 212 0.8745 0.8745 0.5130
+ 213 0.8784 0.8784 0.5086
+ 214 0.8784 0.8784 0.5042
+ 215 0.8824 0.8824 0.4996
+ 216 0.8863 0.8863 0.4950
+ 217 0.8863 0.8863 0.4902
+ 218 0.8902 0.8902 0.4854
+ 219 0.8941 0.8941 0.4804
+ 220 0.8980 0.8980 0.4754
+ 221 0.8980 0.8980 0.4702
+ 222 0.9020 0.9020 0.4649
+ 223 0.9059 0.9059 0.4595
+ 224 0.9098 0.9098 0.4540
+ 225 0.9098 0.9098 0.4484
+ 226 0.9137 0.9137 0.4426
+ 227 0.9176 0.9176 0.4366
+ 228 0.9176 0.9176 0.4306
+ 229 0.9216 0.9216 0.4243
+ 230 0.9255 0.9255 0.4179
+ 231 0.9294 0.9294 0.4114
+ 232 0.9294 0.9294 0.4046
+ 233 0.9333 0.9333 0.3977
+ 234 0.9373 0.9373 0.3905
+ 235 0.9373 0.9373 0.3831
+ 236 0.9412 0.9412 0.3754
+ 237 0.9451 0.9451 0.3675
+ 238 0.9490 0.9490 0.3594
+ 239 0.9490 0.9490 0.3509
+ 240 0.9529 0.9529 0.3420
+ 241 0.9569 0.9569 0.3328
+ 242 0.9608 0.9608 0.3232
+ 243 0.9608 0.9608 0.3131
+ 244 0.9647 0.9647 0.3024
+ 245 0.9686 0.9686 0.2912
+ 246 0.9686 0.9686 0.2792
+ 247 0.9725 0.9725 0.2664
+ 248 0.9765 0.9765 0.2526
+ 249 0.9804 0.9804 0.2375
+ 250 0.9804 0.9804 0.2208
+ 251 0.9843 0.9843 0.2020
+ 252 0.9882 0.9882 0.1800
+ 253 1.0 0.0 0.0
+ 254 1.0 1.0 0.0
+ 255 0.0 1.000 0.0
diff --git a/commons.h b/commons.h
new file mode 100644
index 0000000..e521841
--- /dev/null
+++ b/commons.h
@@ -0,0 +1,35 @@
+#ifndef COMMONS_H
+#define COMMONS_H
+
+//#define NSMAX 1365
+#define NSMAX 6827
+#define NTMAX 120
+
+extern "C" {
+
+extern struct {
+ float ss[184*NSMAX]; //This is "common/jt9com/..." in fortran
+ float savg[NSMAX];
+ short int d2[NTMAX*12000];
+ int nutc; //UTC as integer, HHMM
+ int ndiskdat; //1 ==> data read from *.wav file
+ int ntrperiod; //TR period (seconds)
+ int nfqso; //User-selected QSO freq (kHz)
+ int newdat; //1 ==> new data, must do long FFT
+ int npts8; //npts for c0() array
+ int nfa; //Low decode limit (Hz)
+ int nfb; //High decode limit (Hz)
+ int ntol; //+/- decoding range around fQSO (Hz)
+ int kin;
+ int nzhsym;
+ int nsave;
+ int nagain;
+ int ndepth;
+ int ntxmode;
+ int nmode;
+ char datetime[20];
+} jt9com_;
+
+}
+
+#endif // COMMONS_H
diff --git a/devsetup.cpp b/devsetup.cpp
new file mode 100644
index 0000000..018a188
--- /dev/null
+++ b/devsetup.cpp
@@ -0,0 +1,595 @@
+#include "devsetup.h"
+#include <QDebug>
+#include <QSettings>
+#include <portaudio.h>
+
+#define MAXDEVICES 100
+
+extern double dFreq[16];
+qint32 g2_iptt;
+qint32 g2_COMportOpen;
+
+//----------------------------------------------------------- DevSetup()
+DevSetup::DevSetup(QWidget *parent) : QDialog(parent)
+{
+ ui.setupUi(this); //setup the dialog form
+ m_restartSoundIn=false;
+ m_restartSoundOut=false;
+ m_firstCall=true;
+ g2_iptt=0;
+ m_test=0;
+ m_bRigOpen=false;
+ g2_COMportOpen=0;
+}
+
+DevSetup::~DevSetup()
+{
+}
+
+void DevSetup::initDlg()
+{
+ QString m_appDir = QApplication::applicationDirPath();
+ QString inifile = m_appDir + "/wsjtx.ini";
+ QSettings settings(inifile, QSettings::IniFormat);
+ settings.beginGroup("Common");
+ QString catPortDriver = settings.value("CATdriver","None").toString();
+ settings.endGroup();
+
+ int k,id;
+ int numDevices=Pa_GetDeviceCount();
+
+ const PaDeviceInfo *pdi;
+ int nchin;
+ int nchout;
+ char pa_device_name[128];
+ char pa_device_hostapi[128];
+
+ k=0;
+ for(id=0; id<numDevices; id++ ) {
+ pdi=Pa_GetDeviceInfo(id);
+ nchin=pdi->maxInputChannels;
+ if(nchin>0) {
+ m_inDevList[k]=id;
+ if (id == m_paInDevice)
+ m_nDevIn = k;
+ k++;
+ sprintf((char*)(pa_device_name),"%s",pdi->name);
+ sprintf((char*)(pa_device_hostapi),"%s",
+ Pa_GetHostApiInfo(pdi->hostApi)->name);
+
+#ifdef WIN32
+ char *p,*p1;
+ char p2[50];
+ p1=(char*)"";
+ p=strstr(pa_device_hostapi,"MME");
+ if(p!=NULL) p1=(char*)"MME";
+ p=strstr(pa_device_hostapi,"Direct");
+ if(p!=NULL) p1=(char*)"DirectX";
+ p=strstr(pa_device_hostapi,"WASAPI");
+ if(p!=NULL) p1=(char*)"WASAPI";
+ p=strstr(pa_device_hostapi,"ASIO");
+ if(p!=NULL) p1=(char*)"ASIO";
+ p=strstr(pa_device_hostapi,"WDM-KS");
+ if(p!=NULL) p1=(char*)"WDM-KS";
+
+ sprintf(p2,"%2d %d %-8s %-39s",id,nchin,p1,pa_device_name);
+ QString t(p2);
+#else
+ QString t;
+ t.sprintf("%2d %d %-8s %-39s",id,nchin,
+ Pa_GetHostApiInfo(pdi->hostApi)->name,pdi->name);
+#endif
+ ui.comboBoxSndIn->addItem(t);
+ }
+ }
+
+ k=0;
+ for(id=0; id<numDevices; id++ ) {
+ pdi=Pa_GetDeviceInfo(id);
+ nchout=pdi->maxOutputChannels;
+ if(nchout>0) {
+ m_outDevList[k]=id;
+ if (id == m_paOutDevice)
+ m_nDevOut = k;
+ k++;
+ sprintf((char*)(pa_device_name),"%s",pdi->name);
+ sprintf((char*)(pa_device_hostapi),"%s",
+ Pa_GetHostApiInfo(pdi->hostApi)->name);
+
+#ifdef WIN32
+ char *p,*p1;
+ char p2[50];
+ p1=(char*)"";
+ p=strstr(pa_device_hostapi,"MME");
+ if(p!=NULL) p1=(char*)"MME";
+ p=strstr(pa_device_hostapi,"Direct");
+ if(p!=NULL) p1=(char*)"DirectX";
+ p=strstr(pa_device_hostapi,"WASAPI");
+ if(p!=NULL) p1=(char*)"WASAPI";
+ p=strstr(pa_device_hostapi,"ASIO");
+ if(p!=NULL) p1=(char*)"ASIO";
+ p=strstr(pa_device_hostapi,"WDM-KS");
+ if(p!=NULL) p1=(char*)"WDM-KS";
+ sprintf(p2,"%2d %d %-8s %-39s",id,nchout,p1,pa_device_name);
+ QString t(p2);
+#else
+ QString t;
+ t.sprintf("%2d %d %-8s %-39s",id,nchout,
+ Pa_GetHostApiInfo(pdi->hostApi)->name,pdi->name);
+#endif
+ ui.comboBoxSndOut->addItem(t);
+ }
+ }
+
+ connect(&p4, SIGNAL(readyReadStandardOutput()),
+ this, SLOT(p4ReadFromStdout()));
+ connect(&p4, SIGNAL(readyReadStandardError()),
+ this, SLOT(p4ReadFromStderr()));
+ connect(&p4, SIGNAL(error(QProcess::ProcessError)),
+ this, SLOT(p4Error()));
+ p4.start("rigctl -l");
+ p4.waitForFinished(1000);
+ ui.rigComboBox->addItem(" 9998 Commander");
+ ui.rigComboBox->addItem(" 9999 Ham Radio Deluxe");
+
+ QPalette pal(ui.myCallEntry->palette());
+ if(m_myCall=="") {
+ pal.setColor(QPalette::Base,"#ffccff");
+ } else {
+ pal.setColor(QPalette::Base,Qt::white);
+ }
+ ui.myCallEntry->setPalette(pal);
+ ui.myGridEntry->setPalette(pal);
+ ui.myCallEntry->setText(m_myCall);
+ ui.myGridEntry->setText(m_myGrid);
+ ui.pskReporterAntenna->setText(m_pskAntenna);
+
+ ui.idIntSpinBox->setValue(m_idInt);
+ ui.pttMethodComboBox->setCurrentIndex(m_pttMethodIndex);
+ ui.saveDirEntry->setText(m_saveDir);
+ ui.comboBoxSndIn->setCurrentIndex(m_nDevIn);
+ ui.comboBoxSndOut->setCurrentIndex(m_nDevOut);
+ ui.cbID73->setChecked(m_After73);
+ ui.cbPSKReporter->setChecked(m_pskReporter);
+ ui.cbSplit->setChecked(m_bSplit and m_catEnabled);
+ ui.cbXIT->setChecked(m_bXIT);
+ ui.cbXIT->setVisible(false);
+
+ enableWidgets();
+
+ ui.rigComboBox->setCurrentIndex(m_rigIndex);
+ ui.catPortComboBox->setCurrentIndex(m_catPortIndex);
+ ui.serialRateComboBox->setCurrentIndex(m_serialRateIndex);
+ ui.dataBitsComboBox->setCurrentIndex(m_dataBitsIndex);
+ ui.stopBitsComboBox->setCurrentIndex(m_stopBitsIndex);
+ ui.handshakeComboBox->setCurrentIndex(m_handshakeIndex);
+ ui.rbData->setChecked(m_pttData);
+ ui.pollSpinBox->setValue(m_poll);
+
+ // PY2SDR -- Per OS serial port names
+ m_tmp=m_pttPort;
+ ui.pttComboBox->clear();
+ ui.catPortComboBox->clear();
+ ui.pttComboBox->addItem("None");
+ ui.catPortComboBox->addItem("None");
+#ifdef WIN32
+ for ( int i = 1; i < 100; i++ ) {
+ ui.pttComboBox->addItem("COM" + QString::number(i));
+ ui.catPortComboBox->addItem("COM" + QString::number(i));
+ }
+ ui.pttComboBox->addItem("USB");
+ ui.catPortComboBox->addItem("USB");
+#else
+ ui.catPortComboBox->addItem("/dev/ttyS0");
+ ui.catPortComboBox->addItem("/dev/ttyS1");
+ ui.catPortComboBox->addItem("/dev/ttyS2");
+ ui.catPortComboBox->addItem("/dev/ttyS3");
+ ui.catPortComboBox->addItem("/dev/ttyS4");
+ ui.catPortComboBox->addItem("/dev/ttyS5");
+ ui.catPortComboBox->addItem("/dev/ttyS6");
+ ui.catPortComboBox->addItem("/dev/ttyS7");
+ ui.catPortComboBox->addItem("/dev/ttyUSB0");
+ ui.catPortComboBox->addItem("/dev/ttyUSB1");
+ ui.catPortComboBox->addItem("/dev/ttyUSB2");
+ ui.catPortComboBox->addItem("/dev/ttyUSB3");
+ ui.catPortComboBox->addItem(catPortDriver);
+
+ ui.pttComboBox->addItem("/dev/ttyS0");
+ ui.pttComboBox->addItem("/dev/ttyS1");
+ ui.pttComboBox->addItem("/dev/ttyS2");
+ ui.pttComboBox->addItem("/dev/ttyS3");
+ ui.pttComboBox->addItem("/dev/ttyS4");
+ ui.pttComboBox->addItem("/dev/ttyS5");
+ ui.pttComboBox->addItem("/dev/ttyS6");
+ ui.pttComboBox->addItem("/dev/ttyS7");
+ ui.pttComboBox->addItem("/dev/ttyUSB0");
+ ui.pttComboBox->addItem("/dev/ttyUSB1");
+ ui.pttComboBox->addItem("/dev/ttyUSB2");
+ ui.pttComboBox->addItem("/dev/ttyUSB3");
+#endif
+ ui.pttComboBox->setCurrentIndex(m_tmp);
+ ui.catPortComboBox->setCurrentIndex(m_catPortIndex);
+
+ int n=m_macro.length();
+ if(n>=1) ui.macro1->setText(m_macro[0].toUpper());
+ if(n>=2) ui.macro2->setText(m_macro[1].toUpper());
+ if(n>=3) ui.macro3->setText(m_macro[2].toUpper());
+ if(n>=4) ui.macro4->setText(m_macro[3].toUpper());
+ if(n>=5) ui.macro5->setText(m_macro[4].toUpper());
+ if(n>=6) ui.macro6->setText(m_macro[5].toUpper());
+ if(n>=7) ui.macro7->setText(m_macro[6].toUpper());
+ if(n>=8) ui.macro8->setText(m_macro[7].toUpper());
+ if(n>=8) ui.macro9->setText(m_macro[8].toUpper());
+ if(n>=10) ui.macro10->setText(m_macro[9].toUpper());
+
+ ui.f1->setText(m_dFreq[0]);
+ ui.f2->setText(m_dFreq[1]);
+ ui.f3->setText(m_dFreq[2]);
+ ui.f4->setText(m_dFreq[3]);
+ ui.f5->setText(m_dFreq[4]);
+ ui.f6->setText(m_dFreq[5]);
+ ui.f7->setText(m_dFreq[6]);
+ ui.f8->setText(m_dFreq[7]);
+ ui.f9->setText(m_dFreq[8]);
+ ui.f10->setText(m_dFreq[9]);
+ ui.f11->setText(m_dFreq[10]);
+ ui.f12->setText(m_dFreq[11]);
+ ui.f13->setText(m_dFreq[12]);
+ ui.f14->setText(m_dFreq[13]);
+ ui.f15->setText(m_dFreq[14]);
+ ui.f16->setText(m_dFreq[15]);
+}
+
+//------------------------------------------------------- accept()
+void DevSetup::accept()
+{
+ // Called when OK button is clicked.
+ // Check to see whether SoundInThread must be restarted,
+ // and save user parameters.
+
+ if(m_nDevIn!=ui.comboBoxSndIn->currentIndex() or
+ m_paInDevice!=m_inDevList[m_nDevIn]) m_restartSoundIn=true;
+
+ if(m_nDevOut!=ui.comboBoxSndOut->currentIndex() or
+ m_paOutDevice!=m_outDevList[m_nDevOut]) m_restartSoundOut=true;
+
+ m_myCall=ui.myCallEntry->text();
+ m_myGrid=ui.myGridEntry->text();
+ m_pskAntenna=ui.pskReporterAntenna->text();
+ m_idInt=ui.idIntSpinBox->value();
+ m_pttMethodIndex=ui.pttMethodComboBox->currentIndex();
+ m_pttPort=ui.pttComboBox->currentIndex();
+ m_saveDir=ui.saveDirEntry->text();
+ m_nDevIn=ui.comboBoxSndIn->currentIndex();
+ m_paInDevice=m_inDevList[m_nDevIn];
+ m_nDevOut=ui.comboBoxSndOut->currentIndex();
+ m_paOutDevice=m_outDevList[m_nDevOut];
+
+ m_macro.clear();
+ m_macro.append(ui.macro1->text());
+ m_macro.append(ui.macro2->text());
+ m_macro.append(ui.macro3->text());
+ m_macro.append(ui.macro4->text());
+ m_macro.append(ui.macro5->text());
+ m_macro.append(ui.macro6->text());
+ m_macro.append(ui.macro7->text());
+ m_macro.append(ui.macro8->text());
+ m_macro.append(ui.macro9->text());
+ m_macro.append(ui.macro10->text());
+
+ m_dFreq.clear();
+ m_dFreq.append(ui.f1->text());
+ m_dFreq.append(ui.f2->text());
+ m_dFreq.append(ui.f3->text());
+ m_dFreq.append(ui.f4->text());
+ m_dFreq.append(ui.f5->text());
+ m_dFreq.append(ui.f6->text());
+ m_dFreq.append(ui.f7->text());
+ m_dFreq.append(ui.f8->text());
+ m_dFreq.append(ui.f9->text());
+ m_dFreq.append(ui.f10->text());
+ m_dFreq.append(ui.f11->text());
+ m_dFreq.append(ui.f12->text());
+ m_dFreq.append(ui.f13->text());
+ m_dFreq.append(ui.f14->text());
+ m_dFreq.append(ui.f15->text());
+ m_dFreq.append(ui.f16->text());
+
+ if(m_bRigOpen) {
+ rig->close();
+ if(m_rig<9900) delete rig;
+ m_bRigOpen=false;
+ }
+
+ QDialog::accept();
+}
+
+//------------------------------------------------------- reject()
+void DevSetup::reject()
+{
+ if(m_bRigOpen) rig->close();
+ QDialog::reject();
+}
+
+void DevSetup::p4ReadFromStdout() //p4readFromStdout
+{
+ while(p4.canReadLine()) {
+ QString t(p4.readLine());
+ QString t1,t2,t3;
+ if(t.mid(0,6)!=" Rig #") {
+ t1=t.mid(0,6);
+ t2=t.mid(8,22).trimmed();
+ t3=t.mid(31,23).trimmed();
+ t=t1 + " " + t2 + " " + t3;
+ ui.rigComboBox->addItem(t);
+ }
+ }
+}
+
+void DevSetup::p4ReadFromStderr() //p4readFromStderr
+{
+ QByteArray t=p4.readAllStandardError();
+ if(t.length()>0) {
+ msgBox(t);
+ }
+}
+
+void DevSetup::p4Error() //p4rror
+{
+ msgBox("Error running 'rigctl -l'.");
+}
+
+void DevSetup::msgBox(QString t) //msgBox
+{
+ msgBox0.setText(t);
+ msgBox0.exec();
+}
+
+void DevSetup::on_myCallEntry_editingFinished()
+{
+ QString t=ui.myCallEntry->text();
+ ui.myCallEntry->setText(t.toUpper());
+}
+
+void DevSetup::on_myGridEntry_editingFinished()
+{
+ QString t=ui.myGridEntry->text();
+ t=t.mid(0,4).toUpper()+t.mid(4,2).toLower();
+ ui.myGridEntry->setText(t);
+}
+
+void DevSetup::on_cbPSKReporter_clicked(bool b)
+{
+ m_pskReporter=b;
+ ui.label_8->setEnabled(m_pskReporter);
+ ui.pskReporterAntenna->setEnabled(m_pskReporter);
+}
+
+void DevSetup::on_pttMethodComboBox_activated(int index)
+{
+ m_pttMethodIndex=index;
+ enableWidgets();
+}
+
+void DevSetup::on_catPortComboBox_activated(int index)
+{
+ m_catPortIndex=index;
+ m_catPort=ui.catPortComboBox->itemText(index);
+}
+
+void DevSetup::on_cbEnableCAT_toggled(bool b)
+{
+ m_catEnabled=b;
+ enableWidgets();
+ ui.cbSplit->setChecked(m_bSplit and m_catEnabled);
+}
+
+void DevSetup::on_serialRateComboBox_activated(int index)
+{
+ m_serialRateIndex=index;
+ m_serialRate=ui.serialRateComboBox->itemText(index).toInt();
+}
+
+void DevSetup::on_handshakeComboBox_activated(int index)
+{
+ m_handshakeIndex=index;
+ m_handshake=ui.handshakeComboBox->itemText(index);
+}
+
+void DevSetup::on_dataBitsComboBox_activated(int index)
+{
+ m_dataBitsIndex=index;
+ m_dataBits=ui.dataBitsComboBox->itemText(index).toInt();
+}
+
+void DevSetup::on_stopBitsComboBox_activated(int index)
+{
+ m_stopBitsIndex=index;
+ m_stopBits=ui.stopBitsComboBox->itemText(index).toInt();
+}
+
+void DevSetup::on_rigComboBox_activated(int index)
+{
+ m_rigIndex=index;
+ QString t=ui.rigComboBox->itemText(index);
+ m_rig=t.mid(0,7).toInt();
+ enableWidgets();
+}
+
+void DevSetup::on_cbID73_toggled(bool checked)
+{
+ m_After73=checked;
+}
+
+void DevSetup::on_testCATButton_clicked()
+{
+ openRig();
+ if(!m_catEnabled) return;
+ QString t;
+ double fMHz=rig->getFreq(RIG_VFO_CURR)/1000000.0;
+ if(fMHz>0.0) {
+ t.sprintf("Rig control appears to be working.\nDial Frequency: %.6f MHz",
+ fMHz);
+ } else {
+ t.sprintf("Rig control error %d\nFailed to read frequency.",
+ int(1000000.0*fMHz));
+ if(m_poll>0) {
+ m_catEnabled=false;
+ ui.cbEnableCAT->setChecked(false);
+ }
+ }
+ msgBox(t);
+}
+
+void DevSetup::openRig()
+{
+ QString t;
+ int ret;
+
+ if(!m_catEnabled) return;
+ if(m_bRigOpen) {
+ rig->close();
+ if(m_rig<9900) delete rig;
+ m_bRigOpen=false;
+ }
+
+ rig = new Rig();
+
+ if(m_rig<9900) {
+ if (!rig->init(m_rig)) {
+ msgBox("Rig init failure");
+ m_catEnabled=false;
+ return;
+ }
+ QString sCATport=m_catPort;
+#ifdef WIN32
+ sCATport="\\\\.\\" + m_catPort; //Allow COM ports above 9
+#endif
+ rig->setConf("rig_pathname", sCATport.toLatin1().data());
+ char buf[80];
+ sprintf(buf,"%d",m_serialRate);
+ rig->setConf("serial_speed",buf);
+ sprintf(buf,"%d",m_dataBits);
+ rig->setConf("data_bits",buf);
+ sprintf(buf,"%d",m_stopBits);
+ rig->setConf("stop_bits",buf);
+ rig->setConf("serial_handshake",m_handshake.toLatin1().data());
+ if(m_bDTRoff) {
+ rig->setConf("rts_state","OFF");
+ rig->setConf("dtr_state","OFF");
+ }
+ }
+
+ ret=rig->open(m_rig);
+ if(ret==RIG_OK) {
+ m_bRigOpen=true;
+ } else {
+ t="Open rig failed";
+ msgBox(t);
+ m_catEnabled=false;
+ ui.cbEnableCAT->setChecked(false);
+ return;
+ }
+}
+
+void DevSetup::on_testPTTButton_clicked()
+{
+ m_test=1-m_test;
+ if(m_pttMethodIndex==1 or m_pttMethodIndex==2) {
+ ptt(m_pttPort,m_test,&g2_iptt,&g2_COMportOpen);
+ }
+ if(m_pttMethodIndex==0 and !m_bRigOpen) {
+// on_testCATButton_clicked();
+ openRig();
+ }
+ if(m_pttMethodIndex==0 and m_bRigOpen) {
+ if(m_test==0) rig->setPTT(RIG_PTT_OFF, RIG_VFO_CURR);
+ if(m_test==1) {
+ if(m_pttData) rig->setPTT(RIG_PTT_ON_DATA, RIG_VFO_CURR);
+ if(!m_pttData) rig->setPTT(RIG_PTT_ON_MIC, RIG_VFO_CURR);
+ }
+ }
+}
+
+void DevSetup::on_cbDTRoff_toggled(bool checked)
+{
+ m_bDTRoff=checked;
+}
+
+void DevSetup::on_rbData_toggled(bool checked)
+{
+ m_pttData=checked;
+}
+
+void DevSetup::on_pollSpinBox_valueChanged(int n)
+{
+ m_poll=n;
+}
+
+void DevSetup::on_pttComboBox_currentIndexChanged(int index)
+{
+ m_pttPort=index;
+ enableWidgets();
+}
+
+void DevSetup::on_pttMethodComboBox_currentIndexChanged(int index)
+{
+ m_pttMethodIndex=index;
+ bool b=m_pttMethodIndex==1 or m_pttMethodIndex==2;
+ ui.pttComboBox->setEnabled(b);
+}
+
+void DevSetup::enableWidgets()
+{
+ ui.label_8->setEnabled(m_pskReporter);
+ ui.pskReporterAntenna->setEnabled(m_pskReporter);
+
+ ui.cbEnableCAT->setChecked(m_catEnabled);
+ ui.cbDTRoff->setChecked(m_bDTRoff);
+ ui.rigComboBox->setEnabled(m_catEnabled);
+ ui.testCATButton->setEnabled(m_catEnabled);
+ ui.label_4->setEnabled(m_catEnabled);
+ ui.label_47->setEnabled(m_catEnabled);
+ ui.cbSplit->setEnabled(m_catEnabled);
+ if(m_rig==9999) { //No Split Tx with HRD
+ ui.cbSplit->setChecked(false);
+ ui.cbSplit->setEnabled(false);
+ }
+ ui.cbXIT->setEnabled(m_catEnabled);
+
+ bool bSerial=m_catEnabled and (m_rig<9900);
+ ui.catPortComboBox->setEnabled(bSerial);
+ ui.serialRateComboBox->setEnabled(bSerial);
+ ui.dataBitsComboBox->setEnabled(bSerial);
+ ui.stopBitsComboBox->setEnabled(bSerial);
+ ui.handshakeComboBox->setEnabled(bSerial);
+ ui.cbDTRoff->setEnabled(bSerial);
+ ui.rbData->setEnabled(bSerial);
+ ui.rbMic->setEnabled(bSerial);
+ ui.label_21->setEnabled(bSerial);
+ ui.label_22->setEnabled(bSerial);
+ ui.label_23->setEnabled(bSerial);
+ ui.label_24->setEnabled(bSerial);
+ ui.label_25->setEnabled(bSerial);
+
+ ui.pollSpinBox->setEnabled(m_catEnabled);
+ bool b1=(m_pttMethodIndex==1 or m_pttMethodIndex==2);
+ ui.pttComboBox->setEnabled(b1);
+ b1=b1 and (m_pttPort!=0);
+ bool b2 = (m_catEnabled and m_pttMethodIndex==1 and m_rig<9900) or
+ (m_catEnabled and m_pttMethodIndex==2 and m_rig<9900);
+ bool b3 = (m_catEnabled and m_pttMethodIndex==0);
+ ui.testPTTButton->setEnabled(b1 or b2 or b3); //Include PTT via HRD or Commander
+}
+
+void DevSetup::on_cbSplit_toggled(bool checked)
+{
+ m_bSplit=checked;
+ if(m_bSplit and m_bXIT) ui.cbXIT->setChecked(false);
+}
+
+void DevSetup::on_cbXIT_toggled(bool checked)
+{
+ m_bXIT=checked;
+ if(m_bSplit and m_bXIT) ui.cbSplit->setChecked(false);
+}
diff --git a/devsetup.h b/devsetup.h
new file mode 100644
index 0000000..f483470
--- /dev/null
+++ b/devsetup.h
@@ -0,0 +1,120 @@
+#ifndef DEVSETUP_H
+#define DEVSETUP_H
+
+#include <QDialog>
+#include <QProcess>
+#include <QMessageBox>
+#include "ui_devsetup.h"
+#include "rigclass.h"
+
+class DevSetup : public QDialog
+{
+ Q_OBJECT
+public:
+ DevSetup(QWidget *parent=0);
+ ~DevSetup();
+
+ void initDlg();
+
+ qint32 m_idInt;
+ qint32 m_pttMethodIndex;
+ qint32 m_pttPort;
+ qint32 m_nDevIn;
+ qint32 m_nDevOut;
+ qint32 m_inDevList[100];
+ qint32 m_outDevList[100];
+ qint32 m_paInDevice;
+ qint32 m_paOutDevice;
+ qint32 m_catPortIndex;
+ qint32 m_rig;
+ qint32 m_rigIndex;
+ qint32 m_serialRate;
+ qint32 m_serialRateIndex;
+ qint32 m_dataBits;
+ qint32 m_dataBitsIndex;
+ qint32 m_stopBits;
+ qint32 m_stopBitsIndex;
+ qint32 m_handshakeIndex;
+ qint32 m_test;
+ qint32 m_poll;
+ qint32 m_tmp;
+
+ bool m_restartSoundIn;
+ bool m_restartSoundOut;
+ bool m_pskReporter;
+ bool m_firstCall;
+ bool m_catEnabled;
+ bool m_After73;
+ bool m_bRigOpen;
+ bool m_bDTRoff;
+ bool m_pttData;
+ bool m_bSplit;
+ bool m_bXIT;
+
+ QString m_myCall;
+ QString m_myGrid;
+ QString m_saveDir;
+ QString m_azelDir;
+ QString m_catPort;
+ QString m_handshake;
+ QString m_pskAntenna;
+
+ QStringList m_macro;
+ QStringList m_dFreq;
+
+ QProcess p4;
+ QMessageBox msgBox0;
+
+public slots:
+ void accept();
+ void reject();
+ void p4ReadFromStdout();
+ void p4ReadFromStderr();
+ void p4Error();
+
+private slots:
+ void on_myCallEntry_editingFinished();
+ void on_myGridEntry_editingFinished();
+ void on_cbPSKReporter_clicked(bool checked);
+ void on_pttMethodComboBox_activated(int index);
+ void on_catPortComboBox_activated(int index);
+ void on_cbEnableCAT_toggled(bool checked);
+ void on_serialRateComboBox_activated(int index);
+ void on_handshakeComboBox_activated(int index);
+ void on_dataBitsComboBox_activated(int index);
+ void on_stopBitsComboBox_activated(int index);
+ void on_rigComboBox_activated(int index);
+ void on_cbID73_toggled(bool checked);
+ void on_testCATButton_clicked();
+ void on_testPTTButton_clicked();
+ void on_cbDTRoff_toggled(bool checked);
+ void on_rbData_toggled(bool checked);
+ void on_pollSpinBox_valueChanged(int n);
+ void on_pttComboBox_currentIndexChanged(int index);
+ void on_pttMethodComboBox_currentIndexChanged(int index);
+
+ void on_cbSplit_toggled(bool checked);
+
+ void on_cbXIT_toggled(bool checked);
+
+private:
+ Rig* rig;
+ void msgBox(QString t);
+ void enableWidgets();
+ void openRig();
+ Ui::DialogSndCard ui;
+};
+
+extern int ptt(int nport, int ntx, int* iptt, int* nopen);
+
+#ifdef WIN32
+extern "C" {
+ bool HRDInterfaceConnect(const wchar_t *host, const ushort);
+ void HRDInterfaceDisconnect();
+ bool HRDInterfaceIsConnected();
+ wchar_t* HRDInterfaceSendMessage(const wchar_t *msg);
+ void HRDInterfaceFreeString(const wchar_t *lstring);
+}
+#endif
+
+#endif // DEVSETUP_H
diff --git a/devsetup.ui b/devsetup.ui
new file mode 100644
index 0000000..b1a31cd
--- /dev/null
+++ b/devsetup.ui
@@ -0,0 +1,2599 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DialogSndCard</class>
+ <widget class="QDialog" name="DialogSndCard">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>569</width>
+ <height>493</height>
+ </rect>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>569</width>
+ <height>493</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>Configuration</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QTabWidget" name="ioTabWidget">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>Station</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_5">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>80</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>My Call:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="myCallEntry">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Station callsign</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_8"/>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>80</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>My Grid:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="myGridEntry">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>60</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Maidenhead locator</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLabel" name="label_5">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>80</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>PTT method:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="pttMethodComboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Select method for T/R switching</string>
+ </property>
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>CAT</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>DTR</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>RTS</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>VOX</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_9">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>80</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>PTT Port:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="pttComboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>100</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Select port for hardware T/R switching</string>
+ </property>
+ <item>
+ <property name="text">
+ <string>None</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_6">
+ <item>
+ <widget class="QCheckBox" name="cbPSKReporter">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>146</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>146</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Send spots to PSK Reporter web site</string>
+ </property>
+ <property name="text">
+ <string>Enable PSK Reporter</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_7">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbID73">
+ <property name="toolTip">
+ <string>Send CW ID after a message with 73 or free text</string>
+ </property>
+ <property name="text">
+ <string>CW ID after 73</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>CW ID Interval (min):</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="idIntSpinBox">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>60</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Select CW ID interval (0 for none)</string>
+ </property>
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_12">
+ <item>
+ <widget class="QLabel" name="label_8">
+ <property name="text">
+ <string>Antenna for PSK Reporter:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="pskReporterAntenna"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>13</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_7">
+ <item>
+ <widget class="QCheckBox" name="cbEnableCAT">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>110</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>100</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Enable computer control of transceiver</string>
+ </property>
+ <property name="text">
+ <string>Enable CAT</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_4">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Rig:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="rigComboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Select radio type</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_1">
+ <item>
+ <widget class="QLabel" name="label_21">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>110</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>100</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>CAT port:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="catPortComboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Select port for CAT control</string>
+ </property>
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>None</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbDTRoff">
+ <property name="text">
+ <string>RTS/DTR OFF</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_14">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_24">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>60</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>60</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Data bits:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="dataBitsComboBox">
+ <property name="sizePolicy">
+ <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>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>7</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>8</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_9">
+ <item>
+ <widget class="QLabel" name="label_22">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>110</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>100</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Serial rate:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="serialRateComboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>1200</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>4800</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>9600</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>19200</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>38400</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>57600</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_13">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="rbData">
+ <property name="toolTip">
+ <string>Use special Tx command for "data"</string>
+ </property>
+ <property name="text">
+ <string>Data</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="rbMic">
+ <property name="toolTip">
+ <string>Use normal Tx command</string>
+ </property>
+ <property name="text">
+ <string>Mic</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_25">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>60</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>60</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Stop bits:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="stopBitsComboBox">
+ <property name="sizePolicy">
+ <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>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>2</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_10">
+ <item>
+ <widget class="QLabel" name="label_23">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>110</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>100</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Handshake:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="handshakeComboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="currentIndex">
+ <number>2</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>None</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>XonXoff</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Hardware</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_16">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbSplit">
+ <property name="text">
+ <string>Split Tx</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_6">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_11">
+ <item>
+ <widget class="QPushButton" name="testCATButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>110</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>100</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Check to see if CAT control is working</string>
+ </property>
+ <property name="text">
+ <string>Test CAT Control</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="testPTTButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Test to see if T/R switching is working</string>
+ </property>
+ <property name="text">
+ <string>Test PTT</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_17">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbXIT">
+ <property name="text">
+ <string>XIT</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_12">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_47">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>60</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Polling interval (s):</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="pollSpinBox">
+ <property name="minimumSize">
+ <size>
+ <width>50</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Select interval for reading dial frequency</string>
+ </property>
+ <property name="maximum">
+ <number>60</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_1">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>13</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_13">
+ <item>
+ <spacer name="horizontalSpacer_15">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>96</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_26">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Dev Ch API Name</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_6">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QLabel" name="label_6">
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Audio In:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="comboBoxSndIn">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip">
+ <string>Select audio input device and driver API</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="QLabel" name="label_7">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Audio Out:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="comboBoxSndOut">
+ <property name="toolTip">
+ <string>select audio output device and driver API</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="label_10">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Save Directory:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="saveDirEntry">
+ <property name="toolTip">
+ <string>Directory for saved audio files</string>
+ </property>
+ <property name="text">
+ <string>C:\Users\joe\wsjt\map65\save</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_2">
+ <attribute name="title">
+ <string>Tx Macros</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <spacer name="verticalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="6" column="1">
+ <widget class="QLabel" name="label_17">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>7</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="2">
+ <widget class="QLineEdit" name="macro6">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>200</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLineEdit" name="macro1">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>200</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLabel" name="label_13">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>3</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QLineEdit" name="macro3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>200</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>10W DPL 73 GL</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QLabel" name="label_15">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>5</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="1">
+ <widget class="QLabel" name="label_18">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>8</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="1">
+ <widget class="QLabel" name="label_19">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>9</string>
+ </property>
+ </widget>
+ </item>
+ <item row="9" column="1">
+ <widget class="QLabel" name="label_20">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>10</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QLabel" name="label_16">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>6</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLabel" name="label_14">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>4</string>
+ </property>
+ </widget>
+ </item>
+ <item row="9" column="2">
+ <widget class="QLineEdit" name="macro10">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>200</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="2">
+ <widget class="QLineEdit" name="macro5">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>200</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="2">
+ <widget class="QLineEdit" name="macro4">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>200</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLineEdit" name="macro2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>200</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>5W DPL 73 GL</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="2">
+ <widget class="QLineEdit" name="macro9">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>200</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="3">
+ <spacer name="horizontalSpacer_8">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="label_11">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>1</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="2">
+ <widget class="QLineEdit" name="macro7">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>200</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="label_12">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>2</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="2">
+ <widget class="QLineEdit" name="macro8">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>200</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_3">
+ <attribute name="title">
+ <string>Default Frequencies</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <item>
+ <spacer name="verticalSpacer_6">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="5" column="4">
+ <widget class="QLabel" name="label_39">
+ <property name="text">
+ <string>6 m</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="5">
+ <widget class="QLineEdit" name="f13">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>27</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>50.293</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="label_43">
+ <property name="text">
+ <string>Band</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="label_44">
+ <property name="text">
+ <string>Freq (MHz)</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="5">
+ <widget class="QLineEdit" name="f11">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>27</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>24.9246</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QLabel" name="label_30">
+ <property name="text">
+ <string>80 m</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="4">
+ <widget class="QLabel" name="label_36">
+ <property name="text">
+ <string>15 m</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="5">
+ <widget class="QLineEdit" name="f10">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>27</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>21.078</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="4">
+ <widget class="QLabel" name="label_38">
+ <property name="text">
+ <string>10 m</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="label_27">
+ <property name="text">
+ <string>2200 m</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="4">
+ <widget class="QLabel" name="label_37">
+ <property name="text">
+ <string>12 m</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="5">
+ <widget class="QLineEdit" name="f12">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>27</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>28.078</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="5">
+ <widget class="QLineEdit" name="f14">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>27</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>70.091</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QLabel" name="label_31">
+ <property name="text">
+ <string>60 m</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="QLabel" name="label_32">
+ <property name="text">
+ <string>40 m</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="4">
+ <widget class="QLabel" name="label_40">
+ <property name="text">
+ <string>4 m</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="4">
+ <widget class="QLabel" name="label_35">
+ <property name="text">
+ <string>17 m</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="4">
+ <widget class="QLabel" name="label_45">
+ <property name="text">
+ <string>Band</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="5">
+ <widget class="QLabel" name="label_46">
+ <property name="text">
+ <string>Freq (MHz)</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="1">
+ <widget class="QLabel" name="label_33">
+ <property name="text">
+ <string>30 m</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="5">
+ <widget class="QLineEdit" name="f16">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>27</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>432.178</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLabel" name="label_29">
+ <property name="text">
+ <string>160 m</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLabel" name="label_28">
+ <property name="text">
+ <string>630 m</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="1">
+ <widget class="QLabel" name="label_34">
+ <property name="text">
+ <string>20 m</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="4">
+ <widget class="QLabel" name="label_42">
+ <property name="text">
+ <string>Other</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="5">
+ <widget class="QLineEdit" name="f9">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>27</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>18.1046</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QLineEdit" name="f2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>27</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>0.4742</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="4">
+ <widget class="QLabel" name="label_41">
+ <property name="text">
+ <string>2 m</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="5">
+ <widget class="QLineEdit" name="f15">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>27</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>144.489</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLineEdit" name="f1">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>27</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>0.136</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="2">
+ <widget class="QLineEdit" name="f3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>27</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>1.838</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="2">
+ <widget class="QLineEdit" name="f5">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>27</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>5.2872</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="2">
+ <widget class="QLineEdit" name="f4">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>27</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>3.578</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="3">
+ <spacer name="horizontalSpacer_9">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="7" column="2">
+ <widget class="QLineEdit" name="f7">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>27</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>10.130</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="2">
+ <widget class="QLineEdit" name="f6">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>27</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>7.078</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="2">
+ <widget class="QLineEdit" name="f8">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>27</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>14.078</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <spacer name="horizontalSpacer_10">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="4" column="6">
+ <spacer name="horizontalSpacer_11">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="maximumSize">
+ <size>
+ <width>469</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>myCallEntry</tabstop>
+ <tabstop>myGridEntry</tabstop>
+ <tabstop>pttMethodComboBox</tabstop>
+ <tabstop>pttComboBox</tabstop>
+ <tabstop>cbPSKReporter</tabstop>
+ <tabstop>cbID73</tabstop>
+ <tabstop>idIntSpinBox</tabstop>
+ <tabstop>pskReporterAntenna</tabstop>
+ <tabstop>cbEnableCAT</tabstop>
+ <tabstop>rigComboBox</tabstop>
+ <tabstop>catPortComboBox</tabstop>
+ <tabstop>dataBitsComboBox</tabstop>
+ <tabstop>serialRateComboBox</tabstop>
+ <tabstop>stopBitsComboBox</tabstop>
+ <tabstop>handshakeComboBox</tabstop>
+ <tabstop>testCATButton</tabstop>
+ <tabstop>testPTTButton</tabstop>
+ <tabstop>pollSpinBox</tabstop>
+ <tabstop>comboBoxSndIn</tabstop>
+ <tabstop>comboBoxSndOut</tabstop>
+ <tabstop>saveDirEntry</tabstop>
+ <tabstop>macro1</tabstop>
+ <tabstop>macro2</tabstop>
+ <tabstop>macro3</tabstop>
+ <tabstop>macro4</tabstop>
+ <tabstop>macro5</tabstop>
+ <tabstop>macro6</tabstop>
+ <tabstop>macro7</tabstop>
+ <tabstop>macro8</tabstop>
+ <tabstop>macro9</tabstop>
+ <tabstop>macro10</tabstop>
+ <tabstop>f1</tabstop>
+ <tabstop>f2</tabstop>
+ <tabstop>f3</tabstop>
+ <tabstop>f4</tabstop>
+ <tabstop>f5</tabstop>
+ <tabstop>f6</tabstop>
+ <tabstop>f7</tabstop>
+ <tabstop>f8</tabstop>
+ <tabstop>f9</tabstop>
+ <tabstop>f10</tabstop>
+ <tabstop>f11</tabstop>
+ <tabstop>f12</tabstop>
+ <tabstop>f13</tabstop>
+ <tabstop>f14</tabstop>
+ <tabstop>f15</tabstop>
+ <tabstop>f16</tabstop>
+ <tabstop>buttonBox</tabstop>
+ <tabstop>ioTabWidget</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>DialogSndCard</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>DialogSndCard</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/displaytext.cpp b/displaytext.cpp
new file mode 100644
index 0000000..0b8181e
--- /dev/null
+++ b/displaytext.cpp
@@ -0,0 +1,16 @@
+#include "displaytext.h"
+#include <QDebug>
+#include <QMouseEvent>
+
+DisplayText::DisplayText(QWidget *parent) :
+ QTextBrowser(parent)
+{
+}
+
+void DisplayText::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ bool ctrl = (e->modifiers() & Qt::ControlModifier);
+ bool shift = (e->modifiers() & Qt::ShiftModifier);
+ emit(selectCallsign(shift,ctrl));
+ QTextBrowser::mouseDoubleClickEvent(e);
+}
diff --git a/displaytext.h b/displaytext.h
new file mode 100644
index 0000000..c07f00e
--- /dev/null
+++ b/displaytext.h
@@ -0,0 +1,22 @@
+#ifndef DISPLAYTEXT_H
+#define DISPLAYTEXT_H
+
+#include <QTextBrowser>
+
+class DisplayText : public QTextBrowser
+{
+ Q_OBJECT
+public:
+ explicit DisplayText(QWidget *parent = 0);
+
+signals:
+ void selectCallsign(bool shift, bool ctrl);
+
+public slots:
+
+protected:
+ void mouseDoubleClickEvent(QMouseEvent *e);
+
+};
+
+#endif // DISPLAYTEXT_H
diff --git a/ffft.f b/ffft.f
new file mode 100644
index 0000000..9c3c091
--- /dev/null
+++ b/ffft.f
@@ -0,0 +1,69 @@
+ subroutine ffft(d,npts,isign,ireal)
+
+C Fourier transform of length npts=2**k, performed in place.
+C Input data in array d, treated as complex if ireal=0, and as real if ireal=1.
+C In either case the transform values are returned in array d, treated as
+C complex. The DC term is d(1), and d(npts/2+1) is the term at the Nyquist
+C frequency. The basic algorithm is the same as Norm Brenner's FOUR1, and
+C uses radix-2 transforms.
+
+C J. H. Taylor, Princeton University.
+
+ complex d(npts),t,w,wstep,tt,uu
+ data pi/3.14159265359/
+
+C Shuffle the data to bit-reversed order.
+
+ imax=npts/(ireal+1)
+ irev=1
+ do 5 i=1,imax
+ if(i.ge.irev) go to 2
+ t=d(i)
+ d(i)=d(irev)
+ d(irev)=t
+2 mmax=imax/2
+3 if(irev.le.mmax) go to 5
+ irev=irev-mmax
+ mmax=mmax/2
+ if(mmax.ge.1) go to 3
+5 irev=irev+mmax
+
+C The radix-2 transform begins here.
+
+ api=isign*pi/2.
+ mmax=1
+6 istep=2*mmax
+ wstep=cmplx(-2.*sin(api/mmax)**2,sin(2.*api/mmax))
+ w=1.
+ do 9 m=1,mmax
+
+C This in the inner-most loop -- optimization here is important!
+ do 8 i=m,imax,istep
+ t=w*d(i+mmax)
+ d(i+mmax)=d(i)-t
+8 d(i)=d(i)+t
+
+9 w=w*(1.+wstep)
+ mmax=istep
+ if(mmax.lt.imax) go to 6
+
+ if(ireal.eq.0) return
+
+C Now complete the last stage of a doubled-up real transform.
+
+ jmax=imax/2 + 1
+ wstep=cmplx(-2.*sin(isign*pi/npts)**2,sin(isign*pi/imax))
+ w=1.0
+ d(imax+1)=d(1)
+
+ do 10 j=1,jmax
+ uu=cmplx(real(d(j))+real(d(2+imax-j)),aimag(d(j)) -
+ + aimag(d(2+imax-j)))
+ tt=w*cmplx(aimag(d(j))+aimag(d(2+imax-j)),-real(d(j)) +
+ + real(d(2+imax-j)))
+ d(j)=uu+tt
+ d(2+imax-j)=conjg(uu-tt)
+10 w=w*(1.+wstep)
+
+ return
+ end
diff --git a/fftw3.f b/fftw3.f
new file mode 100644
index 0000000..3410184
--- /dev/null
+++ b/fftw3.f
@@ -0,0 +1,64 @@
+ INTEGER FFTW_R2HC
+ PARAMETER (FFTW_R2HC=0)
+ INTEGER FFTW_HC2R
+ PARAMETER (FFTW_HC2R=1)
+ INTEGER FFTW_DHT
+ PARAMETER (FFTW_DHT=2)
+ INTEGER FFTW_REDFT00
+ PARAMETER (FFTW_REDFT00=3)
+ INTEGER FFTW_REDFT01
+ PARAMETER (FFTW_REDFT01=4)
+ INTEGER FFTW_REDFT10
+ PARAMETER (FFTW_REDFT10=5)
+ INTEGER FFTW_REDFT11
+ PARAMETER (FFTW_REDFT11=6)
+ INTEGER FFTW_RODFT00
+ PARAMETER (FFTW_RODFT00=7)
+ INTEGER FFTW_RODFT01
+ PARAMETER (FFTW_RODFT01=8)
+ INTEGER FFTW_RODFT10
+ PARAMETER (FFTW_RODFT10=9)
+ INTEGER FFTW_RODFT11
+ PARAMETER (FFTW_RODFT11=10)
+ INTEGER FFTW_FORWARD
+ PARAMETER (FFTW_FORWARD=-1)
+ INTEGER FFTW_BACKWARD
+ PARAMETER (FFTW_BACKWARD=+1)
+ INTEGER FFTW_MEASURE
+ PARAMETER (FFTW_MEASURE=0)
+ INTEGER FFTW_DESTROY_INPUT
+ PARAMETER (FFTW_DESTROY_INPUT=1)
+ INTEGER FFTW_UNALIGNED
+ PARAMETER (FFTW_UNALIGNED=2)
+ INTEGER FFTW_CONSERVE_MEMORY
+ PARAMETER (FFTW_CONSERVE_MEMORY=4)
+ INTEGER FFTW_EXHAUSTIVE
+ PARAMETER (FFTW_EXHAUSTIVE=8)
+ INTEGER FFTW_PRESERVE_INPUT
+ PARAMETER (FFTW_PRESERVE_INPUT=16)
+ INTEGER FFTW_PATIENT
+ PARAMETER (FFTW_PATIENT=32)
+ INTEGER FFTW_ESTIMATE
+ PARAMETER (FFTW_ESTIMATE=64)
+ INTEGER FFTW_ESTIMATE_PATIENT
+ PARAMETER (FFTW_ESTIMATE_PATIENT=128)
+ INTEGER FFTW_BELIEVE_PCOST
+ PARAMETER (FFTW_BELIEVE_PCOST=256)
+ INTEGER FFTW_DFT_R2HC_ICKY
+ PARAMETER (FFTW_DFT_R2HC_ICKY=512)
+ INTEGER FFTW_NONTHREADED_ICKY
+ PARAMETER (FFTW_NONTHREADED_ICKY=1024)
+ INTEGER FFTW_NO_BUFFERING
+ PARAMETER (FFTW_NO_BUFFERING=2048)
+ INTEGER FFTW_NO_INDIRECT_OP
+ PARAMETER (FFTW_NO_INDIRECT_OP=4096)
+ INTEGER FFTW_ALLOW_LARGE_GENERIC
+ PARAMETER (FFTW_ALLOW_LARGE_GENERIC=8192)
+ INTEGER FFTW_NO_RANK_SPLITS
+ PARAMETER (FFTW_NO_RANK_SPLITS=16384)
+ INTEGER FFTW_NO_VRANK_SPLITS
+ PARAMETER (FFTW_NO_VRANK_SPLITS=32768)
+ INTEGER FFTW_NO_VRECURSE
+ PARAMETER (FFTW_NO_VRECURSE=65536)
+ INTEGER FFTW_NO_SIMD
+ PARAMETER (FFTW_NO_SIMD=131072)
diff --git a/getdev.cpp b/getdev.cpp
new file mode 100644
index 0000000..751c87f
--- /dev/null
+++ b/getdev.cpp
@@ -0,0 +1,259 @@
+#include <stdio.h>
+#define MAXDEVICES 100
+#include <string.h>
+#include <portaudio.h>
+#include <QDebug>
+
+//------------------------------------------------------- pa_get_device_info
+int pa_get_device_info (int n,
+ void *pa_device_name,
+ void *pa_device_hostapi,
+ double *pa_device_max_speed,
+ double *pa_device_min_speed,
+ int *pa_device_max_bytes,
+ int *pa_device_min_bytes,
+ int *pa_device_max_channels,
+ int *pa_device_min_channels )
+{
+
+ (void) n ;
+ (void) pa_device_name;
+ (void) pa_device_hostapi;
+ (void) pa_device_max_speed;
+ (void) pa_device_min_speed;
+ (void) pa_device_max_bytes;
+ (void) pa_device_min_bytes;
+ (void) pa_device_max_channels;
+ (void) pa_device_min_channels;
+ const PaDeviceInfo *deviceInfo;
+ PaError pa_err;
+ PaStreamParameters inputParameters;
+ int i,j, speed_warning;
+ int minBytes, maxBytes;
+ double maxStandardSampleRate;
+ double minStandardSampleRate;
+ int minInputChannels;
+ int maxInputChannels;
+
+// negative terminated list
+ static double standardSampleRates[] = {8000.0, 9600.0,
+ 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0,
+ 44100.0, 48000.0, 88200.0, 96000.0, 192000.0, -1};
+// *******************************************************
+
+
+ *pa_device_max_speed=0;
+ *pa_device_min_speed=0;
+ *pa_device_max_bytes=0;
+ *pa_device_min_bytes=0;
+ *pa_device_max_channels=0;
+ *pa_device_min_channels=0;
+ minInputChannels=0;
+ if(n >= Pa_GetDeviceCount() ) return -1;
+ deviceInfo = Pa_GetDeviceInfo(n);
+ if (deviceInfo->maxInputChannels==0) return -1;
+ sprintf((char*)(pa_device_name),"%s",deviceInfo->name);
+ sprintf((char*)(pa_device_hostapi),"%s",
+ Pa_GetHostApiInfo( deviceInfo->hostApi )->name);
+ speed_warning=0;
+
+// bypass bug in Juli@ ASIO driver:
+// this driver hangs after a Pa_IsFormatSupported call
+ i = strncmp(deviceInfo->name, "ASIO 2.0 - ESI Juli@", 19);
+ if (i == 0) {
+ minStandardSampleRate=44100;
+ maxStandardSampleRate=192000;
+ minBytes=1;
+ maxBytes=4;
+ maxInputChannels= deviceInfo->maxInputChannels;
+ minInputChannels= 1;
+ goto end_pa_get_device_info;
+ }
+
+// Investigate device capabilities.
+// Check min and max samplerates with 16 bit data.
+ maxStandardSampleRate=0;
+ minStandardSampleRate=0;
+ inputParameters.device = n;
+ inputParameters.channelCount = deviceInfo->maxInputChannels;
+ inputParameters.sampleFormat = paInt16;
+ inputParameters.suggestedLatency = 0;
+ inputParameters.hostApiSpecificStreamInfo = NULL;
+
+// ************************************************************************
+//filter for portaudio Windows hostapi's with non experts.
+//only allow ASIO or WASAPI or WDM-KS
+ i = strncmp(Pa_GetHostApiInfo(deviceInfo->hostApi)->name, "ASIO", 4);
+ if (i==0 ) goto end_filter_hostapi;
+ i = strncmp(Pa_GetHostApiInfo(deviceInfo->hostApi)->name,
+ "Windows WASAPI", 14);
+ if (i==0 ) goto end_filter_hostapi;
+ i = strncmp(Pa_GetHostApiInfo(deviceInfo->hostApi)->name,
+ "Windows WDM-KS", 14);
+ if (i==0 ) goto end_filter_hostapi;
+ speed_warning=1;
+end_filter_hostapi:;
+
+// ************************************************************************
+ i=0;
+ while(standardSampleRates[i] > 0 && minStandardSampleRate==0) {
+ pa_err=Pa_IsFormatSupported(&inputParameters, NULL,
+ standardSampleRates[i] );
+ if(pa_err == paDeviceUnavailable) return -1;
+ if(pa_err == paInvalidDevice) return -1;
+ if(pa_err == paFormatIsSupported ) {
+ minStandardSampleRate=standardSampleRates[i];
+ }
+ i++;
+ }
+ if(minStandardSampleRate == 0) return -1;
+ j=i;
+ while(standardSampleRates[i] > 0 ) i++;
+ i--;
+
+ while(i >= j && maxStandardSampleRate==0) {
+ pa_err=Pa_IsFormatSupported(&inputParameters, NULL,
+ standardSampleRates[i] );
+ if(pa_err == paDeviceUnavailable) return -1;
+ if(pa_err == paInvalidDevice) return -1;
+ if( pa_err == paFormatIsSupported ) {
+ maxStandardSampleRate=standardSampleRates[i];
+ }
+ i--;
+ }
+
+// check if min SampleRate = max SampleRate
+ if(maxStandardSampleRate==0 && (minStandardSampleRate != 0)) {
+ maxStandardSampleRate= minStandardSampleRate;
+ }
+
+// check min and max bytes
+ minBytes=2;
+ maxBytes=2;
+ inputParameters.sampleFormat = paUInt8;
+ pa_err=Pa_IsFormatSupported(&inputParameters, NULL,
+ maxStandardSampleRate );
+ if( pa_err == paFormatIsSupported ) {
+ minBytes=1;
+ }
+ inputParameters.sampleFormat = paInt32;
+ pa_err=Pa_IsFormatSupported(&inputParameters, NULL,
+ maxStandardSampleRate );
+ if( pa_err == paFormatIsSupported ) {
+ maxBytes=4;
+ }
+
+// check min channel count
+ maxInputChannels= deviceInfo->maxInputChannels;
+ inputParameters.channelCount = 1;
+ inputParameters.sampleFormat = paInt16;
+ pa_err=paFormatIsSupported+32000;
+ while(pa_err != paFormatIsSupported &&
+ ( inputParameters.channelCount < (maxInputChannels+1)) ) {
+ pa_err=Pa_IsFormatSupported(&inputParameters, NULL,
+ maxStandardSampleRate );
+ inputParameters.channelCount++;
+ }
+ if( pa_err == paFormatIsSupported ) {
+ minInputChannels=inputParameters.channelCount-1;
+ } else {
+ return -1;
+ }
+
+end_pa_get_device_info:;
+
+ *pa_device_max_speed=maxStandardSampleRate;
+ *pa_device_min_speed=minStandardSampleRate;
+ *pa_device_max_bytes=maxBytes;
+ *pa_device_min_bytes=minBytes;
+ *pa_device_max_channels= maxInputChannels;
+ *pa_device_min_channels= minInputChannels;
+
+ return speed_warning;
+}
+
+
+void paInputDevice(int id, char* hostAPI_DeviceName, int* minChan,
+ int* maxChan, int* minSpeed, int* maxSpeed)
+{
+ int i;
+ char pa_device_name[128];
+ char pa_device_hostapi[128];
+ double pa_device_max_speed;
+ double pa_device_min_speed;
+ int pa_device_max_bytes;
+ int pa_device_min_bytes;
+ int pa_device_max_channels;
+ int pa_device_min_channels;
+ char p2[50];
+ char *p,*p1;
+ static int iret, valid_dev_cnt;
+
+ iret=pa_get_device_info (id,
+ &pa_device_name,
+ &pa_device_hostapi,
+ &pa_device_max_speed,
+ &pa_device_min_speed,
+ &pa_device_max_bytes,
+ &pa_device_min_bytes,
+ &pa_device_max_channels,
+ &pa_device_min_channels);
+
+ if (iret >= 0 ) {
+ valid_dev_cnt++;
+
+ p1=(char*)"";
+ p=strstr(pa_device_hostapi,"MME");
+ if(p!=NULL) p1=(char*)"MME";
+ p=strstr(pa_device_hostapi,"Direct");
+ if(p!=NULL) p1=(char*)"DirectX";
+ p=strstr(pa_device_hostapi,"WASAPI");
+ if(p!=NULL) p1=(char*)"WASAPI";
+ p=strstr(pa_device_hostapi,"ASIO");
+ if(p!=NULL) p1=(char*)"ASIO";
+ p=strstr(pa_device_hostapi,"WDM-KS");
+ if(p!=NULL) p1=(char*)"WDM-KS";
+
+ sprintf(p2,"%-8s %-39s",p1,pa_device_name);
+ for(i=0; i<50; i++) {
+ hostAPI_DeviceName[i]=p2[i];
+ if(p2[i]==0) break;
+ }
+ *minChan=pa_device_min_channels;
+ *maxChan=pa_device_max_channels;
+ *minSpeed=(int)pa_device_min_speed;
+ *maxSpeed=(int)pa_device_max_speed;
+ } else {
+ for(i=0; i<50; i++) {
+ hostAPI_DeviceName[i]=0;
+ }
+ *minChan=0;
+ *maxChan=0;
+ *minSpeed=0;
+ *maxSpeed=0;
+ }
+}
+
+void getDev(int* numDevices0, char hostAPI_DeviceName[][50],
+ int minChan[], int maxChan[],
+ int minSpeed[], int maxSpeed[])
+{
+ int i,id,numDevices;
+ int minch,maxch,minsp,maxsp;
+ char apidev[256];
+
+ numDevices=Pa_GetDeviceCount();
+ *numDevices0=numDevices;
+
+ for(id=0; id<numDevices; id++) {
+ paInputDevice(id,apidev,&minch,&maxch,&minsp,&maxsp);
+ for(i=0; i<50; i++) {
+ hostAPI_DeviceName[id][i]=apidev[i];
+ }
+ hostAPI_DeviceName[id][49]=0;
+ minChan[id]=minch;
+ maxChan[id]=maxch;
+ minSpeed[id]=minsp;
+ maxSpeed[id]=maxsp;
+ }
+}
diff --git a/getfile.cpp b/getfile.cpp
new file mode 100644
index 0000000..ecc7bbb
--- /dev/null
+++ b/getfile.cpp
@@ -0,0 +1,199 @@
+#include "getfile.h"
+#include <QDir>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef WIN32
+#include <windows.h>
+#else
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <err.h>
+#endif
+
+void getfile(QString fname, int ntrperiod)
+{
+
+ char name[80];
+ strcpy(name,fname.toLatin1());
+ FILE* fp=fopen(name,"rb");
+
+ int i0=fname.indexOf(".wav");
+ jt9com_.nutc=0;
+ if(i0>0) jt9com_.nutc=100*fname.mid(i0-4,2).toInt() +
+ fname.mid(i0-2,2).toInt();
+ int npts=ntrperiod*12000;
+ memset(jt9com_.d2,0,2*npts);
+
+ if(fp != NULL) {
+// Read (and ignore) a 44-byte WAV header; then read data
+ int n=fread(jt9com_.d2,1,44,fp);
+ n=fread(jt9com_.d2,2,npts,fp);
+ fclose(fp);
+ jt9com_.newdat=1;
+ if(n==-99999) jt9com_.newdat=2; //Silence compiler warning
+ }
+}
+
+void savewav(QString fname, int ntrperiod)
+{
+ struct {
+ char ariff[4]; //ChunkID: "RIFF"
+ int nchunk; //ChunkSize: 36+SubChunk2Size
+ char awave[4]; //Format: "WAVE"
+ char afmt[4]; //Subchunk1ID: "fmt "
+ int lenfmt; //Subchunk1Size: 16
+ short int nfmt2; //AudioFormat: 1
+ short int nchan2; //NumChannels: 1
+ int nsamrate; //SampleRate: 12000
+ int nbytesec; //ByteRate: SampleRate*NumChannels*BitsPerSample/8
+ short int nbytesam2; //BlockAlign: NumChannels*BitsPerSample/8
+ short int nbitsam2; //BitsPerSample: 16
+ char adata[4]; //Subchunk2ID: "data"
+ int ndata; //Subchunk2Size: numSamples*NumChannels*BitsPerSample/8
+ } hdr;
+
+ int npts=ntrperiod*12000;
+// qint16* buf=(qint16*)malloc(2*npts);
+ char name[80];
+ strcpy(name,fname.toLatin1());
+ FILE* fp=fopen(name,"wb");
+
+ if(fp != NULL) {
+// Write a WAV header
+ hdr.ariff[0]='R';
+ hdr.ariff[1]='I';
+ hdr.ariff[2]='F';
+ hdr.ariff[3]='F';
+ hdr.nchunk=36 + 2*npts;
+ hdr.awave[0]='W';
+ hdr.awave[1]='A';
+ hdr.awave[2]='V';
+ hdr.awave[3]='E';
+ hdr.afmt[0]='f';
+ hdr.afmt[1]='m';
+ hdr.afmt[2]='t';
+ hdr.afmt[3]=' ';
+ hdr.lenfmt=16;
+ hdr.nfmt2=1;
+ hdr.nchan2=1;
+ hdr.nsamrate=12000;
+ hdr.nbytesec=2*12000;
+ hdr.nbytesam2=2;
+ hdr.nbitsam2=16;
+ hdr.adata[0]='d';
+ hdr.adata[1]='a';
+ hdr.adata[2]='t';
+ hdr.adata[3]='a';
+ hdr.ndata=2*npts;
+
+ fwrite(&hdr,sizeof(hdr),1,fp);
+// memcpy(jt9com_.d2,buf,2*npts);
+// fwrite(buf,2,npts,fp);
+ fwrite(jt9com_.d2,2,npts,fp);
+ fclose(fp);
+ }
+// free(buf);
+}
+
+//#define MAX_RANDOM 0x7fffffff
+
+/* Generate gaussian random float with mean=0 and std_dev=1 */
+float gran()
+{
+ float fac,rsq,v1,v2;
+ static float gset;
+ static int iset;
+
+ if(iset){
+ /* Already got one */
+ iset = 0;
+ return gset;
+ }
+ /* Generate two evenly distributed numbers between -1 and +1
+ * that are inside the unit circle
+ */
+ do {
+ v1 = 2.0 * (float)rand() / RAND_MAX - 1;
+ v2 = 2.0 * (float)rand() / RAND_MAX - 1;
+ rsq = v1*v1 + v2*v2;
+ } while(rsq >= 1.0 || rsq == 0.0);
+ fac = sqrt(-2.0*log(rsq)/rsq);
+ gset = v1*fac;
+ iset++;
+ return v2*fac;
+}
+
+int ptt(int nport, int ntx, int* iptt, int* nopen)
+{
+#ifdef WIN32
+ static HANDLE hFile;
+ char s[10];
+ int i3=1,i4=1,i5=1,i6=1,i9=1,i00=1; //Defs to silence compiler warning
+
+ if(nport==0) {
+ *iptt=ntx;
+ return 0;
+ }
+
+ if(ntx && (!(*nopen))) {
+ sprintf(s,"\\\\.\\COM%d",nport);
+ hFile=CreateFile(TEXT(s),GENERIC_WRITE,0,NULL,OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,NULL);
+ if(hFile==INVALID_HANDLE_VALUE) {
+ QString t;
+ t.sprintf("Cannot open COM port %d for PTT\n",nport);
+ return 1;
+ }
+ *nopen=1;
+ }
+
+ if(ntx && *nopen) {
+ i3=EscapeCommFunction(hFile,SETRTS);
+ i5=EscapeCommFunction(hFile,SETDTR);
+ *iptt=1;
+ }
+
+ else {
+ i4=EscapeCommFunction(hFile,CLRRTS);
+ i6=EscapeCommFunction(hFile,CLRDTR);
+ i9=EscapeCommFunction(hFile,CLRBREAK);
+ i00=CloseHandle(hFile);
+ *iptt=0;
+ *nopen=0;
+ }
+ if((i3+i4+i5+i6+i9+i00)==-999) return 1; //Silence compiler warning
+ return 0;
+#else
+ int control=TIOCM_RTS | TIOCM_DTR;
+// int control = TIOCM_RTS;
+ static int fd;
+
+ if(*nopen==0) {
+ fd=open("/dev/ttyUSB0",O_RDWR | O_NONBLOCK);
+ if(fd<0) {
+ return -1;
+ }
+ *nopen=1;
+ }
+
+ if(ntx) {
+ ioctl(fd, TIOCMBIS, &control);
+ *iptt=1;
+ *nopen=1;
+ } else {
+ ioctl(fd, TIOCMBIC, &control);
+ close(fd);
+ *iptt=0;
+ *nopen=0;
+ }
+ return 0;
+#endif
+ if((nport+ntx+(*iptt)==-99999)) *nopen=0; //Silence compiler warning
+ return 0;
+}
diff --git a/getfile.h b/getfile.h
new file mode 100644
index 0000000..2e255d1
--- /dev/null
+++ b/getfile.h
@@ -0,0 +1,18 @@
+#ifndef GETFILE_H
+#define GETFILE_H
+#include <QString>
+#include <QFile>
+#include <QDebug>
+#include "commons.h"
+
+void getfile(QString fname, int ntrperiod);
+float gran();
+//int ptt(int* nport, int* ntx, int* iptt);
+int ptt(int nport, int ntx, int* iptt, int* nopen);
+
+extern "C" {
+int ptt_(int nport, int ntx, int* iptt, int* nopen);
+}
+
+
+#endif // GETFILE_H
diff --git a/in.dat b/in.dat
new file mode 100644
index 0000000..5294129
--- /dev/null
+++ b/in.dat
@@ -0,0 +1,16 @@
+ 35 36 22 8 31 11 14 55 20 36 55 13 24 15 56 38 16 28 61 58
+ 15 26 45 8 41 53 37 57 59 60 29 29 41 46 44 35 52 61 24 26
+ 16 20 53 35 2 6 9 27 47 28 57 6 15 9 16 10 56 9 63 46
+ 9 15 3
+ 74 61 44 233 29 245 254 64 119 64 250 111 38 145 53 29 140 194 119 99
+ 55 86 48 110 142 95 48 120 61 66 252 252 245 88 62 41 124 249 246 68
+ 250 249 65 64 140 142 88 190 237 90 240 52 79 216 55 31 112 135 66 44
+ 99 57 68
+ 54 61 26 5 13 60 3 56 30 58 57 4 16 43 28 43 6 61 13 19
+ 56 8 4 9 45 32 9 7 14 52 4 38 40 27 3 26 51 54 40 29
+ 36 63 34 43 3 48 36 49 46 30 8 20 40 59 29 28 17 11 8 19
+ 11 63 5
+ 38 25 35 8 28 0 0 60 60 25 0 31 28 52 14 24 9 30 18 54
+ 49 55 48 15 27 54 26 22 30 27 1 1 4 31 35 29 23 2 2 27
+ 0 1 25 32 21 84 28 19 5 60 2 27 15 9 39 23 42 12 29 17
+ 16 50 49
diff --git a/jt9.txt b/jt9.txt
new file mode 100644
index 0000000..ddbd86b
--- /dev/null
+++ b/jt9.txt
@@ -0,0 +1,65 @@
+JT9 is a mode designed for amateur QSOs at MF and LF. The mode uses
+the same 72-bit structured messages as JT65. Error control coding
+(ECC) uses a strong convolutional code with constraint length K=32,
+rate r=1/2, and a zero tail, leading to an encoded message length of
+(72+31)*2 = 206 information-carrying bits. Modulation is 9-FSK: 8
+tones for data, one for synchronization. Sixteen symbol intervals are
+used for synchronization, so a transmission requires a total of 207/3
++ 16 = 85 channel symbols. Symbol durations tsym are approximately
+(TRperiod-8)/85, where TRperiod is the T/R sequence length in seconds.
+Exact symbol lengths are chosen so that nsps, the number of samples
+per symbol (at 12000 samples per second) is a number with no prime
+factor greater than 7. This choice makes for efficient FFTs. Tone
+spacing of the 9-FSK modulation is df=1/tsym=12000/nsps, equal to the
+keying rate. The total occupied bandwidth is 9*df. The generated
+signal has continuous phase, and there are no key clicks.
+
+Parameters of five JT9 sub-modes are summarized in the following
+table, along with S/N thresholds measured by simulation on an AWGN
+channel. Numbers following "JT9-" in the sub-mode names specify the
+T/R sequence length in minutes.
+
+--------------------------------------------------------------------------
+Mode nsps nsps2 df tsym BW S/N* Tdec Tfree Factors
+ 12000 1500 (Hz) (s) (Hz) (dB) (s) (s) of nsps nfft3
+--------------------------------------------------------------------------
+JT9-1 6912 864 1.736 0.58 15.6 -26.9 52.5 7.5 2^8 3^3 2048
+JT9-2 15360 1920 0.781 1.28 7.0 -30.2 112.3 7.7 2^10 3 5 2048
+JT9-5 40960 5120 0.293 3.41 2.6 -34.4 293.6 6.4 2^13 5 6144
+JT9-10 82944 10368 0.145 6.91 1.3 -37.5 591.0 9.0 2^10 3^4 12288
+JT9-30 252000 31500 0.048 21.00 0.4 -42.3 1788.5 11.5 2^5 3^2 5^3 7 32768
+--------------------------------------------------------------------------
+* Noise power measured in a 2500 Hz bandwidth.
+NB: nfft3 might be doubled and used with a sin^2 window.
+
+Transmitting
+------------
+1. Source encode the structured message to 72 bits
+2. Apply convolutional ECC (K=32, r=1/2) to yield (72+31)*2 = 206 bits
+3. Interleave to scramble the bit order
+4. Assemble 3-bit groups to make (206+1)/3 = 69 symbols
+5. Gray-code the symbol values
+6. Insert 16 sync symbols ==> 69+16=85 channel symbols, values 0-8
+
+
+Receiving
+---------
+1. Apply noise blanking with the timf2 method
+2. Filter to 1000 Hz bandwidth and downsample (1/8) to 1500 Hz, saving
+ complex data to array c0(2,700,000).
+3. Compute spectra at half-symbol steps. Use for waterfall display
+ s(22000) and save in ss(184,22000) and savg(22000) for detecting
+ sync vectors.
+4. At time Tdec, find sync vectors in ss(); get approx DF or list of DFs
+5. Do full-length FFT, NFFT1=96*nsps2, zero-padded as required.
+6. For each candidate signal, do inverse FFT of length 1536 (or 3072?).
+ This yields 16 complex samples per symbol; sync tone should be
+ close to zero frequency.
+7. Use afc65b method to get improved values of DF, DT.
+8. Tweak freq and time offset to 0.
+9. Compute 8-bin spectra of 69 data symbols: ssym(0:7,69). Re-order the
+ bins to remove Gray code.
+10. Compute soft symbols for 206 bits (bit 207 is always 0).
+11. Remove interleaving
+12. Pack bits into bytes, send to Fano decoder
+13. If Fano succeeds, remove source encoding and display user message.
diff --git a/killbyname.cpp b/killbyname.cpp
new file mode 100644
index 0000000..240ad5a
--- /dev/null
+++ b/killbyname.cpp
@@ -0,0 +1,284 @@
+#include <windows.h>
+#include <tlhelp32.h>
+#include <iostream>
+
+int killbyname(const char *szToTerminate)
+// Created: 6/23/2000 (Ravi Kochhar)
+// Last modified: 3/10/2002 (RK)
+// Please report any problems or bugs to kochhar at physiology.wisc.edu
+// The latest version of this routine can be found at:
+// http://www.neurophys.wisc.edu/ravi/software/killproc/
+// Terminate the process "szToTerminate" if it is currently running
+// This works for Win/95/98/ME and also Win/NT/2000/XP
+// The process name is case-insensitive, i.e. "notepad.exe" and "NOTEPAD.EXE"
+// will both work (for szToTerminate)
+// Return codes are as follows:
+// 0 = Process was successfully terminated
+// 602 = Unable to terminate process for some other reason
+// 603 = Process was not currently running
+// 604 = No permission to terminate process
+// 605 = Unable to load PSAPI.DLL
+// 606 = Unable to identify system type
+// 607 = Unsupported OS
+// 632 = Invalid process name
+// 700 = Unable to get procedure address from PSAPI.DLL
+// 701 = Unable to get process list, EnumProcesses failed
+// 702 = Unable to load KERNEL32.DLL
+// 703 = Unable to get procedure address from KERNEL32.DLL
+// 704 = CreateToolhelp32Snapshot failed
+
+{
+ BOOL bResult,bResultm;
+ DWORD aiPID[1000],iCb=1000,iNumProc; //,iV2000=0;
+ DWORD iCbneeded,i,iFound=0;
+ char szName[MAX_PATH],szToTermUpper[MAX_PATH];
+ HANDLE hProc,hSnapShot,hSnapShotm;
+ OSVERSIONINFO osvi;
+ HINSTANCE hInstLib;
+// int iLen,iLenP,indx;
+ int iLenP,indx;
+ HMODULE hMod;
+ PROCESSENTRY32 procentry;
+ MODULEENTRY32 modentry;
+
+ // Transfer Process name into "szToTermUpper" and convert to upper case
+ iLenP=strlen(szToTerminate);
+ if(iLenP<1 || iLenP>MAX_PATH) return 632;
+ for(indx=0;indx<iLenP;indx++)
+ szToTermUpper[indx]=toupper(szToTerminate[indx]);
+ szToTermUpper[iLenP]=0;
+
+ // PSAPI Function Pointers.
+ BOOL (WINAPI *lpfEnumProcesses)( DWORD *, DWORD cb, DWORD * );
+ BOOL (WINAPI *lpfEnumProcessModules)( HANDLE, HMODULE *,
+ DWORD, LPDWORD );
+ DWORD (WINAPI *lpfGetModuleBaseName)( HANDLE, HMODULE,
+ LPTSTR, DWORD );
+
+ // ToolHelp Function Pointers.
+ HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD,DWORD) ;
+ BOOL (WINAPI *lpfProcess32First)(HANDLE,LPPROCESSENTRY32) ;
+ BOOL (WINAPI *lpfProcess32Next)(HANDLE,LPPROCESSENTRY32) ;
+ BOOL (WINAPI *lpfModule32First)(HANDLE,LPMODULEENTRY32) ;
+ BOOL (WINAPI *lpfModule32Next)(HANDLE,LPMODULEENTRY32) ;
+
+ // First check what version of Windows we're in
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ bResult=GetVersionEx(&osvi);
+ if(!bResult) return 606; // Unable to identify system version
+
+ // At Present we only support Win/NT/2000/XP or Win/9x/ME
+ // Seems to work OK in Win7
+ if((osvi.dwPlatformId != VER_PLATFORM_WIN32_NT) &&
+ (osvi.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)) return 607;
+
+ if(osvi.dwPlatformId==VER_PLATFORM_WIN32_NT)
+ {
+ // Win/NT or 2000 or XP
+
+ // Load library and get the procedures explicitly. We do
+ // this so that we don't have to worry about modules using
+ // this code failing to load under Windows 9x, because
+ // it can't resolve references to the PSAPI.DLL.
+ hInstLib = LoadLibraryA("PSAPI.DLL");
+ if(hInstLib == NULL) return 605;
+
+ // Get procedure addresses.
+ lpfEnumProcesses = (BOOL(WINAPI *)(DWORD *,DWORD,DWORD*))
+ GetProcAddress( hInstLib, "EnumProcesses" ) ;
+ lpfEnumProcessModules = (BOOL(WINAPI *)(HANDLE, HMODULE *,
+ DWORD, LPDWORD)) GetProcAddress( hInstLib, "EnumProcessModules" ) ;
+ lpfGetModuleBaseName =(DWORD (WINAPI *)(HANDLE, HMODULE, LPTSTR,
+ DWORD )) GetProcAddress( hInstLib, "GetModuleBaseNameA" ) ;
+
+ if(lpfEnumProcesses == NULL || lpfEnumProcessModules == NULL ||
+ lpfGetModuleBaseName == NULL) {
+ FreeLibrary(hInstLib);
+ return 700;
+ }
+
+ bResult=lpfEnumProcesses(aiPID,iCb,&iCbneeded);
+ if(!bResult) {
+ // Unable to get process list, EnumProcesses failed
+ FreeLibrary(hInstLib);
+ return 701;
+ }
+
+ // How many processes are there?
+ iNumProc=iCbneeded/sizeof(DWORD);
+
+ // Get and match the name of each process
+ for(i=0;i<iNumProc;i++) {
+ // Get the (module) name for this process
+ strcpy(szName,"Unknown");
+ // First, get a handle to the process
+ hProc=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE,
+ aiPID[i]);
+ // Now, get the process name
+ if(hProc) {
+ if(lpfEnumProcessModules(hProc,&hMod,sizeof(hMod),&iCbneeded) ) {
+// iLen=lpfGetModuleBaseName(hProc,hMod,szName,MAX_PATH);
+ lpfGetModuleBaseName(hProc,hMod,szName,MAX_PATH);
+ }
+ }
+ CloseHandle(hProc);
+ // We will match regardless of lower or upper case
+ if(strcmp(_strupr(szName),szToTermUpper)==0) {
+ // Process found, now terminate it
+ iFound=1;
+ // First open for termination
+ hProc=OpenProcess(PROCESS_TERMINATE,FALSE,aiPID[i]);
+ if(hProc) {
+ if(TerminateProcess(hProc,0)) {
+ // process terminated
+ CloseHandle(hProc);
+ FreeLibrary(hInstLib);
+ return 0;
+ } else {
+ // Unable to terminate process
+ CloseHandle(hProc);
+ FreeLibrary(hInstLib);
+ return 602;
+ }
+ } else {
+ // Unable to open process for termination
+ FreeLibrary(hInstLib);
+ return 604;
+ }
+ }
+ }
+ }
+
+ if(osvi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)
+ {
+ // Win/95 or 98 or ME
+
+ hInstLib = LoadLibraryA("Kernel32.DLL");
+ if( hInstLib == NULL )
+ return 702;
+
+ // Get procedure addresses.
+ // We are linking to these functions of Kernel32
+ // explicitly, because otherwise a module using
+ // this code would fail to load under Windows NT,
+ // which does not have the Toolhelp32
+ // functions in the Kernel 32.
+ lpfCreateToolhelp32Snapshot=
+ (HANDLE(WINAPI *)(DWORD,DWORD))
+ GetProcAddress( hInstLib,
+ "CreateToolhelp32Snapshot" ) ;
+ lpfProcess32First=
+ (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
+ GetProcAddress( hInstLib, "Process32First" ) ;
+ lpfProcess32Next=
+ (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
+ GetProcAddress( hInstLib, "Process32Next" ) ;
+ lpfModule32First=
+ (BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32))
+ GetProcAddress( hInstLib, "Module32First" ) ;
+ lpfModule32Next=
+ (BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32))
+ GetProcAddress( hInstLib, "Module32Next" ) ;
+ if( lpfProcess32Next == NULL ||
+ lpfProcess32First == NULL ||
+ lpfModule32Next == NULL ||
+ lpfModule32First == NULL ||
+ lpfCreateToolhelp32Snapshot == NULL )
+ {
+ FreeLibrary(hInstLib);
+ return 703;
+ }
+
+ // The Process32.. and Module32.. routines return names in all uppercase
+
+ // Get a handle to a Toolhelp snapshot of all the systems processes.
+
+ hSnapShot = lpfCreateToolhelp32Snapshot(
+ TH32CS_SNAPPROCESS, 0 ) ;
+ if( hSnapShot == INVALID_HANDLE_VALUE )
+ {
+ FreeLibrary(hInstLib);
+ return 704;
+ }
+
+ // Get the first process' information.
+ procentry.dwSize = sizeof(PROCESSENTRY32);
+ bResult=lpfProcess32First(hSnapShot,&procentry);
+
+ // While there are processes, keep looping and checking.
+ while(bResult)
+ {
+ // Get a handle to a Toolhelp snapshot of this process.
+ hSnapShotm = lpfCreateToolhelp32Snapshot(
+ TH32CS_SNAPMODULE, procentry.th32ProcessID) ;
+ if( hSnapShotm == INVALID_HANDLE_VALUE )
+ {
+ CloseHandle(hSnapShot);
+ FreeLibrary(hInstLib);
+ return 704;
+ }
+ // Get the module list for this process
+ modentry.dwSize=sizeof(MODULEENTRY32);
+ bResultm=lpfModule32First(hSnapShotm,&modentry);
+
+ // While there are modules, keep looping and checking
+ while(bResultm)
+ {
+ if(strcmp(modentry.szModule,szToTermUpper)==0)
+ {
+ // Process found, now terminate it
+ iFound=1;
+ // First open for termination
+ hProc=OpenProcess(PROCESS_TERMINATE,FALSE,procentry.th32ProcessID);
+ if(hProc)
+ {
+ if(TerminateProcess(hProc,0))
+ {
+ // process terminated
+ CloseHandle(hSnapShotm);
+ CloseHandle(hSnapShot);
+ CloseHandle(hProc);
+ FreeLibrary(hInstLib);
+ return 0;
+ }
+ else
+ {
+ // Unable to terminate process
+ CloseHandle(hSnapShotm);
+ CloseHandle(hSnapShot);
+ CloseHandle(hProc);
+ FreeLibrary(hInstLib);
+ return 602;
+ }
+ }
+ else
+ {
+ // Unable to open process for termination
+ CloseHandle(hSnapShotm);
+ CloseHandle(hSnapShot);
+ FreeLibrary(hInstLib);
+ return 604;
+ }
+ }
+ else
+ { // Look for next modules for this process
+ modentry.dwSize=sizeof(MODULEENTRY32);
+ bResultm=lpfModule32Next(hSnapShotm,&modentry);
+ }
+ }
+
+ //Keep looking
+ CloseHandle(hSnapShotm);
+ procentry.dwSize = sizeof(PROCESSENTRY32);
+ bResult = lpfProcess32Next(hSnapShot,&procentry);
+ }
+ CloseHandle(hSnapShot);
+ }
+ if(iFound==0)
+ {
+ FreeLibrary(hInstLib);
+ return 603;
+ }
+ FreeLibrary(hInstLib);
+ return 0;
+}
diff --git a/lib/Makefile.MinGW b/lib/Makefile.MinGW
new file mode 100644
index 0000000..e09924b
--- /dev/null
+++ b/lib/Makefile.MinGW
@@ -0,0 +1,117 @@
+# Makefile for MinGW on Windows
+# Windows re-direct:
+# C> make > junk1 2>&1
+
+CC = gcc
+FC = g95
+
+FFLAGS = -O2 -fbounds-check -Wall -Wno-precision-loss -fno-second-underscore
+CFLAGS = -I. -fbounds-check -mno-stack-arg-probe
+
+# Default rules
+%.o: %.c
+ ${CC} ${CFLAGS} -c $<
+%.o: %.f
+ ${FC} ${FFLAGS} -c $<
+%.o: %.F
+ ${FC} ${FFLAGS} -c $<
+%.o: %.f90
+ ${FC} ${FFLAGS} -c $<
+%.o: %.F90
+ ${FC} ${FFLAGS} -c $<
+
+all: libjt9.a jt9sim.exe jt9.exe jt9code.exe jt65.exe
+
+OBJS1 = pctile.o graycode.o sort.o ssort.o \
+ unpackmsg.o igray.o unpackcall.o unpackgrid.o \
+ grid2k.o unpacktext.o getpfx2.o packmsg.o deg2grid.o \
+ packtext.o getpfx1.o packcall.o k2grid.o packgrid.o \
+ nchar.o four2a.o grid2deg.o pfxdump.o f77_wisdom.o \
+ symspec.o analytic.o db.o genjt9.o \
+ packbits.o unpackbits.o encode232.o interleave9.o \
+ entail.o fano232.o gran.o sync9.o decode9.o \
+ fil3.o decoder.o grid2n.o n2grid.o timer.o \
+ softsym.o getlags.o afc9.o fchisq.o twkfreq.o downsam9.o \
+ peakdt9.o symspec2.o stdmsg.o morse.o azdist.o geodist.o \
+ fillcom.o chkss2.o zplot9.o flat2.o \
+ jt65a.o symspec65.o flat65.o ccf65.o decode65a.o \
+ filbig.o fil6521.o afc65b.o decode65b.o setup65.o \
+ extract.o fchisq65.o demod64a.o chkhist.o interleave63.o ccf2.o \
+ move.o indexx.o graycode65.o twkfreq65.o smo121.o \
+ wrapkarn.o init_rs.o encode_rs.o decode_rs.o gen65.o
+
+libjt9.a: $(OBJS1)
+ ar cr libjt9.a $(OBJS1)
+ ranlib libjt9.a
+
+OBJS2 = jt9.o jt9a.o jt9b.o jt9c.o ipcomm.o sec_midn.o cutil.o
+LIBS2 = -L'c:/QtSDK/Desktop/Qt/4.7.4/mingw/lib' -lQtCore4
+jt9.exe: $(OBJS2) libjt9.a
+ g++ -o jt9.exe $(OBJS2) $(LIBS2) libjt9.a ../libfftw3f_win.a \
+ c:/MinGW/lib/libf95.a
+ cp jt9.exe ../../wsjtx_install
+
+OBJS3 = jt9sim.o
+jt9sim.exe: $(OBJS3) libjt9.a
+ $(FC) -o jt9sim.exe $(OBJS3) libjt9.a
+
+OBJS4 = jt9code.o
+jt9code.exe: $(OBJS4) libjt9.a
+ $(FC) -o jt9code.exe $(OBJS4) libjt9.a
+
+OBJS5 = jt65.o
+jt65.exe: $(OBJS5) libjt9.a
+ $(FC) -o jt65.exe $(OBJS5) libjt9.a ../libfftw3f_win.a
+
+INCPATH = -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include/QtCore' \
+ -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include' \
+ -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include/ActiveQt' \
+ -I'release' -I'.' -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/mkspecs/win32-g++'
+
+sync9.o: sync9.f90 jt9sync.f90
+ $(FC) $(FFLAGS) -c sync9.f90
+
+spec9.o: spec9.f90 jt9sync.f90
+ $(FC) $(FFLAGS) -c spec9.f90
+
+peakdt9.o: peakdt9.f90 jt9sync.f90
+ $(FC) $(FFLAGS) -c peakdt9.f90
+
+jt9sim.o: jt9sim.f90 jt9sync.f90
+ $(FC) $(FFLAGS) -c jt9sim.f90
+
+genjt9.o: genjt9.f90 jt9sync.f90
+ $(FC) $(FFLAGS) -c genjt9.f90
+
+redsync.o: redsync.f90 jt9sync.f90
+ $(FC) $(FFLAGS) -c redsync.f90
+
+unpackmsg.o: unpackmsg.f90
+ $(FC) -c -O0 -fbounds-check -Wall -Wno-precision-loss unpackmsg.f90
+
+ipcomm.o: ipcomm.cpp
+ g++ -c $(INCPATH) ipcomm.cpp
+
+sec_midn.o: sec_midn.f90
+ $(FC) -c -fno-second-underscore sec_midn.f90
+
+#rig_control.o: rig_control.c
+# $(CC) -c -Wall -I..\..\..\hamlib-1.2.15.3\include rig_control.c
+
+tstrig.o: tstrig.c
+ $(CC) -c -Wall -I..\..\..\hamlib-1.2.15.3\include tstrig.c
+
+init_rs.o: init_rs.c
+ $(CC) -c -DBIGSYM=1 -o init_rs.o init_rs.c
+
+encode_rs.o: encode_rs.c
+ $(CC) -c -DBIGSYM=1 -o encode_rs.o encode_rs.c
+
+decode_rs.o: decode_rs.c
+ $(CC) -c -DBIGSYM=1 -o decode_rs.o decode_rs.c
+
+
+.PHONY : clean
+
+clean:
+ rm -f *.o libjt9.a wsjtx.exe jt9sim.exe jt9.exe jt65.exe
diff --git a/lib/Makefile.linux b/lib/Makefile.linux
new file mode 100644
index 0000000..19e6096
--- /dev/null
+++ b/lib/Makefile.linux
@@ -0,0 +1,104 @@
+CC = gcc
+FC = gfortran
+
+FFLAGS = -O2 -fbounds-check -Wall -Wno-conversion -fno-second-underscore
+CFLAGS = -I. -fbounds-check -mno-stack-arg-probe
+
+# Default rules
+%.o: %.c
+ ${CC} ${CFLAGS} -c $<
+%.o: %.f
+ ${FC} ${FFLAGS} -c $<
+%.o: %.F
+ ${FC} ${FFLAGS} -c $<
+%.o: %.f90
+ ${FC} ${FFLAGS} -c $<
+%.o: %.F90
+ ${FC} ${FFLAGS} -c $<
+
+all: libjt9.a jt9sim jt9 jt9code
+
+OBJS1 = pctile.o graycode.o sort.o ssort.o \
+ unpackmsg.o igray.o unpackcall.o unpackgrid.o \
+ grid2k.o unpacktext.o getpfx2.o packmsg.o deg2grid.o \
+ packtext.o getpfx1.o packcall.o k2grid.o packgrid.o \
+ nchar.o four2a.o grid2deg.o pfxdump.o f77_wisdom.o \
+ symspec.o analytic.o db.o genjt9.o \
+ packbits.o unpackbits.o encode232.o interleave9.o \
+ entail.o fano232.o gran.o sync9.o decode9.o \
+ fil3.o decoder.o grid2n.o n2grid.o timer.o \
+ softsym.o peakdt9.o getlags.o afc9.o fchisq.o \
+ twkfreq.o downsam9.o symspec2.o ipcomm.o sleep_msec.o \
+ stdmsg.o sec_midn.o cutil.o azdist.o geodist.o morse.o \
+ fillcom.o chkss2.o zplot9.o flat2.o \
+ jt65a.o symspec65.o flat65.o ccf65.o decode65a.o \
+ filbig.o fil6521.o afc65b.o decode65b.o setup65.o \
+ extract.o fchisq65.o demod64a.o chkhist.o interleave63.o ccf2.o \
+ move.o indexx.o graycode65.o twkfreq65.o smo121.o \
+ wrapkarn.o init_rs.o encode_rs.o decode_rs.o gen65.o
+
+libjt9.a: $(OBJS1)
+ ar cr libjt9.a $(OBJS1)
+ ranlib libjt9.a
+
+OBJS2 = jt9.o jt9a.o jt9b.o jt9c.o
+
+jt9: $(OBJS2) libjt9.a
+ g++ -o jt9 $(OBJS2) libjt9.a -lfftw3f -lgfortran -lQtCore
+ cp jt9 ../../wsjtx_install
+
+OBJS3 = jt9sim.o
+jt9sim: $(OBJS3) libjt9.a
+ $(FC) -o jt9sim $(OBJS3) libjt9.a
+
+OBJS4 = jt9code.o
+jt9code: $(OBJS4) libjt9.a
+ $(FC) -o jt9code $(OBJS4) libjt9.a
+
+#INCPATH = -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include/QtCore' \
+# -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include' \
+# -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include/ActiveQt' \
+# -I'release' -I'.' -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/mkspecs/win32-g++'
+
+INCPATH = -I'/usr/include/qt4' -I'/usr/include/qt4/QtCore'
+
+#jt9.o: jt9.f90
+# $(FC) -O0 -c jt9.f90
+
+sync9.o: sync9.f90 jt9sync.f90
+ $(FC) $(FFLAGS) -c sync9.f90
+
+peakdf9.o: peakdf9.f90 jt9sync.f90
+ $(FC) $(FFLAGS) -c peakdf9.f90
+
+peakdt9.o: peakdt9.f90 jt9sync.f90
+ $(FC) $(FFLAGS) -c peakdt9.f90
+
+jt9sim.o: jt9sim.f90 jt9sync.f90
+ $(FC) $(FFLAGS) -c jt9sim.f90
+
+genjt9.o: genjt9.f90 jt9sync.f90
+ $(FC) $(FFLAGS) -c genjt9.f90
+
+redsync.o: redsync.f90 jt9sync.f90
+ $(FC) $(FFLAGS) -c redsync.f90
+
+ipcomm.o: ipcomm.cpp
+ g++ -c $(INCPATH) ipcomm.cpp
+
+sec_midn.o: sec_midn.f90
+ $(FC) -c -fno-second-underscore sec_midn.f90
+
+init_rs.o: init_rs.c
+ $(CC) -c -DBIGSYM=1 -o init_rs.o init_rs.c
+
+encode_rs.o: encode_rs.c
+ $(CC) -c -DBIGSYM=1 -o encode_rs.o encode_rs.c
+
+decode_rs.o: decode_rs.c
+ $(CC) -c -DBIGSYM=1 -o decode_rs.o decode_rs.c
+
+.PHONY : clean
+
+clean:
+ rm -f *.o libjt9.a wsjtx jt9sim jt9 jt9code
diff --git a/lib/afc65b.f90 b/lib/afc65b.f90
new file mode 100644
index 0000000..f78f275
--- /dev/null
+++ b/lib/afc65b.f90
@@ -0,0 +1,59 @@
+subroutine afc65b(cx,npts,fsample,nflip,a,ccfbest,dtbest)
+
+! Find delta f, f1, f2 ==> a(1:3)
+
+ complex cx(npts)
+ real a(5),deltaa(5)
+
+ a(1)=0.
+ a(2)=0.
+ a(3)=0.
+ a(4)=0.
+ deltaa(1)=2.0
+ deltaa(2)=2.0
+ deltaa(3)=2.0
+ deltaa(4)=0.05
+ nterms=3 !Maybe 2 is enough?
+
+! Start the iteration
+ chisqr=0.
+ chisqr0=1.e6
+ do iter=1,3 !One iteration is enough?
+ do j=1,nterms
+ chisq1=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax)
+ fn=0.
+ delta=deltaa(j)
+10 a(j)=a(j)+delta
+ chisq2=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax)
+ if(chisq2.eq.chisq1) go to 10
+ if(chisq2.gt.chisq1) then
+ delta=-delta !Reverse direction
+ a(j)=a(j)+delta
+ tmp=chisq1
+ chisq1=chisq2
+ chisq2=tmp
+ endif
+20 fn=fn+1.0
+ a(j)=a(j)+delta
+ chisq3=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax)
+ if(chisq3.lt.chisq2) then
+ chisq1=chisq2
+ chisq2=chisq3
+ go to 20
+ endif
+
+! Find minimum of parabola defined by last three points
+ delta=delta*(1./(1.+(chisq1-chisq2)/(chisq3-chisq2))+0.5)
+ a(j)=a(j)-delta
+ deltaa(j)=deltaa(j)*fn/3.
+ enddo
+ chisqr=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax)
+ if(chisqr/chisqr0.gt.0.9999) go to 30
+ chisqr0=chisqr
+ enddo
+
+30 ccfbest=ccfmax * (1378.125/fsample)**2
+ dtbest=dtmax
+
+ return
+end subroutine afc65b
diff --git a/lib/afc9.f90 b/lib/afc9.f90
new file mode 100644
index 0000000..1fbcf2f
--- /dev/null
+++ b/lib/afc9.f90
@@ -0,0 +1,58 @@
+subroutine afc9(c3,npts,fsample,a,syncpk)
+
+ complex c3(0:npts-1)
+ real a(3),deltaa(3)
+
+ a(1)=0. !f0
+ a(2)=0. !f1
+ a(3)=0. !f2
+ deltaa(1)=0.2
+ deltaa(2)=0.01
+ deltaa(3)=0.01
+ nterms=3
+
+! Start the iteration
+ chisqr=0.
+ chisqr0=1.e6
+ do iter=1,4 !One iteration is enough?
+ do j=1,nterms
+ chisq1=fchisq(c3,npts,fsample,a)
+ fn=0.
+ delta=deltaa(j)
+10 a(j)=a(j)+delta
+ chisq2=fchisq(c3,npts,fsample,a)
+ if(chisq2.eq.chisq1) go to 10
+ if(chisq2.gt.chisq1) then
+ delta=-delta !Reverse direction
+ a(j)=a(j)+delta
+ tmp=chisq1
+ chisq1=chisq2
+ chisq2=tmp
+ endif
+20 fn=fn+1.0
+ a(j)=a(j)+delta
+ chisq3=fchisq(c3,npts,fsample,a)
+ if(chisq3.lt.chisq2) then
+ chisq1=chisq2
+ chisq2=chisq3
+ go to 20
+ endif
+
+! Find minimum of parabola defined by last three points
+ delta=delta*(1./(1.+(chisq1-chisq2)/(chisq3-chisq2))+0.5)
+ a(j)=a(j)-delta
+ deltaa(j)=deltaa(j)*fn/3.
+! write(*,4000) iter,j,a,deltaa,-chisq2
+!4000 format(i1,i2,6f10.4,f9.3)
+ enddo
+ chisqr=fchisq(c3,npts,fsample,a)
+ if(chisqr/chisqr0.gt.0.9999) exit
+ chisqr0=chisqr
+ enddo
+
+ syncpk=-chisqr
+! write(*,4001) a,deltaa,-chisq2
+!4001 format(3x,6f10.4,f9.3)
+
+ return
+end subroutine afc9
diff --git a/lib/analytic.f90 b/lib/analytic.f90
new file mode 100644
index 0000000..33d5fc7
--- /dev/null
+++ b/lib/analytic.f90
@@ -0,0 +1,25 @@
+subroutine analytic(d,npts,nfft,s,c)
+
+! Convert real data to analytic signal
+
+ parameter (NFFTMAX=128*1024)
+ real d(npts)
+ real s(npts)
+ complex c(NFFTMAX)
+
+ nh=nfft/2
+ fac=2.0/nfft
+ c(1:npts)=fac*d(1:npts)
+ c(npts+1:nfft)=0.
+ call four2a(c,nfft,1,-1,1) !Forward c2c FFT
+
+ do i=1,nh
+ s(i)=real(c(i))**2 + aimag(c(i))**2
+ enddo
+
+ c(1)=0.5*c(1)
+ c(nh+2:nfft)=0.
+ call four2a(c,nfft,1,1,1) !Inverse c2c FFT
+
+ return
+end subroutine analytic
diff --git a/lib/azdist.f90 b/lib/azdist.f90
new file mode 100644
index 0000000..528801f
--- /dev/null
+++ b/lib/azdist.f90
@@ -0,0 +1,107 @@
+subroutine azdist(MyGrid,HisGrid,utch,nAz,nEl,nDmiles,nDkm,nHotAz,nHotABetter)
+
+ character*6 MyGrid,HisGrid,mygrid0,hisgrid0
+ real*8 utch,utch0
+ logical HotABetter,IamEast
+ real eltab(22),daztab(22)
+ data eltab/18.,15.,13.,11.,9.,8.,7.,6.,5.3,4.7,4.,3.3,2.7, &
+ 2.,1.5,1.,0.8,0.6,0.4,0.2,0.0,0.0/
+ data daztab/21.,18.,16.,15.,14.,13.,12.,11.,10.7,10.3,10., &
+ 10.,10.,10.,10.,10.,10.,9.,9.,9.,8.,8./
+ data mygrid0/" "/,hisgrid0/" "/,utch0/-999.d0/
+ save
+
+ if(MyGrid.eq.HisGrid) then
+ naz=0
+ nel=0
+ ndmiles=0
+ ndkm=0
+ nhotaz=0
+ nhotabetter=1
+ go to 999
+ endif
+
+ if(mygrid.eq.mygrid0 .and. hisgrid.eq.hisgrid0 .and. &
+ abs(utch-utch0).lt.0.1666667d0) go to 900
+ utch0=utch
+ mygrid0=mygrid
+ hisgrid0=hisgrid
+ utchours=utch
+
+ if(MyGrid(5:5).eq.' ') MyGrid(5:5)='m'
+ if(MyGrid(6:6).eq.' ') MyGrid(6:6)='m'
+ if(HisGrid(5:5).eq.' ') HisGrid(5:5)='m'
+ if(HisGrid(6:6).eq.' ') HisGrid(6:6)='m'
+
+ if(MyGrid.eq.HisGrid) then
+ Az=0.
+ Dmiles=0.
+ Dkm=0.0
+ El=0.
+ HotA=0.
+ HotB=0.
+ HotABetter=.true.
+ go to 900
+ endif
+
+ call grid2deg(MyGrid,dlong1,dlat1)
+ call grid2deg(HisGrid,dlong2,dlat2)
+ call geodist(dlat1,dlong1,dlat2,dlong2,Az,Baz,Dkm)
+
+ ndkm=Dkm/100
+ j=ndkm-4
+ if(j.lt.1) j=1
+ if(j.gt.21)j=21
+ if(Dkm.lt.500.0) then
+ El=18.0
+ else
+ u=(Dkm-100.0*ndkm)/100.0
+ El=(1.0-u)*eltab(j) + u*eltab(j+1)
+ endif
+
+ daz=daztab(j) + u * (daztab(j+1)-daztab(j))
+ Dmiles=Dkm/1.609344
+
+ tmid=mod(UTChours-0.5*(dlong1+dlong2)/15.0+48.0,24.0)
+ IamEast=.false.
+ if(dlong1.lt.dlong2) IamEast=.true.
+ if(dlong1.eq.dlong2 .and. dlat1.gt.dlat2) IamEast=.false.
+ azEast=baz
+ if(IamEast) azEast=az
+ if((azEast.ge.45.0 .and. azEast.lt.135.0) .or. &
+ (azEast.ge.225.0 .and. azEast.lt.315.0)) then
+! The path will be taken as "east-west".
+ HotABetter=.true.
+ if(abs(tmid-6.0).lt.6.0) HotABetter=.false.
+ if((dlat1+dlat2)/2.0 .lt. 0.0) HotABetter=.not.HotABetter
+ else
+! The path will be taken as "north-south".
+ HotABetter=.false.
+ if(abs(tmid-12.0).lt.6.0) HotABetter=.true.
+ endif
+ if(IamEast) then
+ HotA = Az - daz
+ HotB = Az + daz
+ else
+ HotA = Az + daz
+ HotB = Az - daz
+ endif
+ if(HotA.lt.0.0) HotA=HotA+360.0
+ if(HotA.gt.360.0) HotA=HotA-360.0
+ if(HotB.lt.0.0) HotB=HotB+360.0
+ if(HotB.gt.360.0) HotB=HotB-360.0
+
+900 continue
+ naz=nint(Az)
+ nel=nint(el)
+ nDmiles=nint(Dmiles)
+ nDkm=nint(Dkm)
+ nHotAz=nint(HotB)
+ nHotABetter=0
+ if(HotABetter) then
+ nHotAz=nint(HotA)
+ nHotABetter=1
+ endif
+
+999 return
+end subroutine azdist
diff --git a/lib/bpskmetrics.dat b/lib/bpskmetrics.dat
new file mode 100644
index 0000000..4073e57
--- /dev/null
+++ b/lib/bpskmetrics.dat
@@ -0,0 +1,256 @@
+ -12.8 1.000 -9.966 1.000000 0.000000
+ -12.7 1.000 -9.966 1.000000 0.000000
+ -12.6 1.000 -9.966 1.000000 0.000000
+ -12.5 1.000 -9.966 1.000000 0.000000
+ -12.4 1.000 -9.966 1.000000 0.000000
+ -12.3 1.000 -9.966 1.000000 0.000000
+ -12.2 1.000 -9.966 1.000000 0.000000
+ -12.1 1.000 -9.966 1.000000 0.000000
+ -12.0 1.000 -9.966 1.000000 0.000000
+ -11.9 1.000 -9.966 1.000000 0.000000
+ -11.8 1.000 -9.966 1.000000 0.000000
+ -11.7 1.000 -9.966 1.000000 0.000000
+ -11.6 1.000 -9.966 1.000000 0.000000
+ -11.5 1.000 -9.966 1.000000 0.000000
+ -11.4 1.000 -9.966 1.000000 0.000000
+ -11.3 1.000 -9.966 1.000000 0.000000
+ -11.2 1.000 -9.966 1.000000 0.000000
+ -11.1 1.000 -9.966 1.000000 0.000000
+ -11.0 1.000 -9.966 1.000000 0.000000
+ -10.9 1.000 -9.966 1.000000 0.000000
+ -10.8 1.000 -9.966 1.000000 0.000000
+ -10.7 1.000 -9.966 1.000000 0.000000
+ -10.6 1.000 -9.966 1.000000 0.000000
+ -10.5 1.000 -9.966 1.000000 0.000000
+ -10.4 1.000 -9.966 1.000000 0.000000
+ -10.3 1.000 -9.966 1.000000 0.000000
+ -10.2 1.000 -9.966 1.000000 0.000000
+ -10.1 1.000 -9.966 1.000000 0.000000
+ -10.0 1.000 -9.966 1.000000 0.000000
+ -9.9 1.000 -9.966 1.000000 0.000000
+ -9.8 1.000 -9.966 1.000000 0.000000
+ -9.7 1.000 -9.966 1.000000 0.000000
+ -9.6 1.000 -9.966 1.000000 0.000000
+ -9.5 1.000 -9.966 1.000000 0.000000
+ -9.4 1.000 -9.966 1.000000 0.000000
+ -9.3 1.000 -9.966 1.000000 0.000000
+ -9.2 1.000 -9.966 1.000000 0.000000
+ -9.1 1.000 -9.966 1.000000 0.000000
+ -9.0 1.000 -9.966 1.000000 0.000000
+ -8.9 1.000 -9.966 1.000000 0.000000
+ -8.8 1.000 -9.966 1.000000 0.000000
+ -8.7 1.000 -9.966 1.000000 0.000000
+ -8.6 1.000 -9.966 1.000000 0.000000
+ -8.5 1.000 -9.966 1.000000 0.000000
+ -8.4 1.000 -9.966 1.000000 0.000000
+ -8.3 1.000 -9.966 1.000000 0.000000
+ -8.2 1.000 -9.966 1.000000 0.000000
+ -8.1 1.000 -9.966 1.000000 0.000000
+ -8.0 1.000 -9.966 1.000000 0.000000
+ -7.9 1.000 -9.966 1.000000 0.000000
+ -7.8 1.000 -9.966 1.000000 0.000000
+ -7.7 1.000 -9.966 1.000000 0.000000
+ -7.6 1.000 -9.966 1.000000 0.000000
+ -7.5 1.000 -9.966 1.000000 0.000000
+ -7.4 1.000 -9.966 1.000000 0.000000
+ -7.3 1.000 -9.966 1.000000 0.000000
+ -7.2 1.000 -9.966 1.000000 0.000000
+ -7.1 1.000 -9.966 1.000000 0.000000
+ -7.0 1.000 -9.966 1.000000 0.000000
+ -6.9 1.000 -9.966 1.000000 0.000000
+ -6.8 1.000 -9.966 1.000000 0.000000
+ -6.7 1.000 -9.966 1.000000 0.000000
+ -6.6 1.000 -9.966 1.000000 0.000000
+ -6.5 1.000 -9.966 1.000000 0.000000
+ -6.4 1.000 -9.966 1.000000 0.000000
+ -6.3 1.000 -9.966 1.000000 0.000000
+ -6.2 1.000 -9.966 1.000000 0.000000
+ -6.1 1.000 -9.966 1.000000 0.000000
+ -6.0 1.000 -9.966 1.000000 0.000000
+ -5.9 1.000 -9.966 1.000000 0.000000
+ -5.8 1.000 -9.966 1.000000 0.000000
+ -5.7 1.000 -9.966 1.000000 0.000000
+ -5.6 1.000 -9.966 1.000000 0.000000
+ -5.5 1.000 -9.966 1.000000 0.000000
+ -5.4 1.000 -9.966 1.000000 0.000000
+ -5.3 1.000 -9.966 1.000000 0.000000
+ -5.2 1.000 -9.966 1.000000 0.000000
+ -5.1 1.000 -9.966 1.000000 0.000000
+ -5.0 1.000 -9.966 1.000000 0.000000
+ -4.9 1.000 -9.966 1.000000 0.000000
+ -4.8 1.000 -9.966 1.000000 0.000000
+ -4.7 1.000 -9.966 1.000000 0.000000
+ -4.6 1.000 -9.966 1.000000 0.000000
+ -4.5 1.000 -9.966 1.000000 0.000000
+ -4.4 1.000 -9.966 1.000000 0.000000
+ -4.3 1.000 -9.966 1.000000 0.000000
+ -4.2 1.000 -9.966 1.000000 0.000000
+ -4.1 1.000 -9.966 1.000000 0.000000
+ -4.0 1.000 -9.966 1.000000 0.000000
+ -3.9 1.000 -9.966 1.000000 0.000000
+ -3.8 1.000 -9.966 1.000000 0.000000
+ -3.7 1.000 -9.966 1.000000 0.000000
+ -3.6 1.000 -9.966 1.000000 0.000000
+ -3.5 1.000 -9.966 1.000000 0.000000
+ -3.4 1.000 -9.966 1.000000 0.000000
+ -3.3 1.000 -9.966 1.000000 0.000000
+ -3.2 1.000 -9.966 1.000000 0.000000
+ -3.1 1.000 -9.966 1.000000 0.000000
+ -3.0 1.000 -9.966 1.000000 0.000000
+ -2.9 1.000 -9.966 1.000000 0.000000
+ -2.8 1.000 -9.966 0.999955 0.000045
+ -2.7 1.000 -9.966 0.999968 0.000032
+ -2.6 1.000 -9.966 0.999909 0.000091
+ -2.5 1.000 -9.966 0.999983 0.000017
+ -2.4 1.000 -9.966 0.999937 0.000063
+ -2.3 1.000 -9.966 0.999914 0.000086
+ -2.2 1.000 -9.966 0.999813 0.000187
+ -2.1 1.000 -9.966 0.999775 0.000225
+ -2.0 1.000 -9.966 0.999671 0.000329
+ -1.9 0.999 -9.966 0.999531 0.000469
+ -1.8 0.999 -9.308 0.999211 0.000789
+ -1.7 0.998 -8.893 0.998948 0.001052
+ -1.6 0.998 -8.191 0.998290 0.001710
+ -1.5 0.996 -7.655 0.997519 0.002481
+ -1.4 0.994 -7.037 0.996192 0.003808
+ -1.3 0.992 -6.513 0.994525 0.005475
+ -1.2 0.988 -5.931 0.991804 0.008196
+ -1.1 0.982 -5.359 0.987816 0.012184
+ -1.0 0.974 -4.789 0.981916 0.018084
+ -0.9 0.961 -4.217 0.973110 0.026890
+ -0.8 0.942 -3.672 0.960785 0.039215
+ -0.7 0.915 -3.123 0.942613 0.057387
+ -0.6 0.874 -2.582 0.916477 0.083523
+ -0.5 0.816 -2.062 0.880296 0.119704
+ -0.4 0.734 -1.573 0.831905 0.168095
+ -0.3 0.619 -1.109 0.768168 0.231832
+ -0.2 0.465 -0.690 0.690103 0.309897
+ -0.1 0.260 -0.317 0.598759 0.401241
+ 0.0 0.000 0.000 0.500000 0.500000
+ 0.1 -0.317 0.260 0.401241 0.598759
+ 0.2 -0.690 0.465 0.309897 0.690103
+ 0.3 -1.109 0.619 0.231832 0.768168
+ 0.4 -1.573 0.734 0.168095 0.831905
+ 0.5 -2.062 0.816 0.119704 0.880296
+ 0.6 -2.582 0.874 0.083523 0.916477
+ 0.7 -3.123 0.915 0.057387 0.942613
+ 0.8 -3.672 0.942 0.039215 0.960785
+ 0.9 -4.217 0.961 0.026890 0.973110
+ 1.0 -4.789 0.974 0.018084 0.981916
+ 1.1 -5.359 0.982 0.012184 0.987816
+ 1.2 -5.931 0.988 0.008196 0.991804
+ 1.3 -6.513 0.992 0.005475 0.994525
+ 1.4 -7.037 0.994 0.003808 0.996192
+ 1.5 -7.655 0.996 0.002481 0.997519
+ 1.6 -8.191 0.998 0.001710 0.998290
+ 1.7 -8.893 0.998 0.001052 0.998948
+ 1.8 -9.308 0.999 0.000789 0.999211
+ 1.9 -9.966 0.999 0.000469 0.999531
+ 2.0 -9.966 1.000 0.000329 0.999671
+ 2.1 -9.966 1.000 0.000225 0.999775
+ 2.2 -9.966 1.000 0.000187 0.999813
+ 2.3 -9.966 1.000 0.000086 0.999914
+ 2.4 -9.966 1.000 0.000063 0.999937
+ 2.5 -9.966 1.000 0.000017 0.999983
+ 2.6 -9.966 1.000 0.000091 0.999909
+ 2.7 -9.966 1.000 0.000032 0.999968
+ 2.8 -9.966 1.000 0.000045 0.999955
+ 2.9 -9.966 1.000 0.000000 1.000000
+ 3.0 -9.966 1.000 0.000000 1.000000
+ 3.1 -9.966 1.000 0.000000 1.000000
+ 3.2 -9.966 1.000 0.000000 1.000000
+ 3.3 -9.966 1.000 0.000000 1.000000
+ 3.4 -9.966 1.000 0.000000 1.000000
+ 3.5 -9.966 1.000 0.000000 1.000000
+ 3.6 -9.966 1.000 0.000000 1.000000
+ 3.7 -9.966 1.000 0.000000 1.000000
+ 3.8 -9.966 1.000 0.000000 1.000000
+ 3.9 -9.966 1.000 0.000000 1.000000
+ 4.0 -9.966 1.000 0.000000 1.000000
+ 4.1 -9.966 1.000 0.000000 1.000000
+ 4.2 -9.966 1.000 0.000000 1.000000
+ 4.3 -9.966 1.000 0.000000 1.000000
+ 4.4 -9.966 1.000 0.000000 1.000000
+ 4.5 -9.966 1.000 0.000000 1.000000
+ 4.6 -9.966 1.000 0.000000 1.000000
+ 4.7 -9.966 1.000 0.000000 1.000000
+ 4.8 -9.966 1.000 0.000000 1.000000
+ 4.9 -9.966 1.000 0.000000 1.000000
+ 5.0 -9.966 1.000 0.000000 1.000000
+ 5.1 -9.966 1.000 0.000000 1.000000
+ 5.2 -9.966 1.000 0.000000 1.000000
+ 5.3 -9.966 1.000 0.000000 1.000000
+ 5.4 -9.966 1.000 0.000000 1.000000
+ 5.5 -9.966 1.000 0.000000 1.000000
+ 5.6 -9.966 1.000 0.000000 1.000000
+ 5.7 -9.966 1.000 0.000000 1.000000
+ 5.8 -9.966 1.000 0.000000 1.000000
+ 5.9 -9.966 1.000 0.000000 1.000000
+ 6.0 -9.966 1.000 0.000000 1.000000
+ 6.1 -9.966 1.000 0.000000 1.000000
+ 6.2 -9.966 1.000 0.000000 1.000000
+ 6.3 -9.966 1.000 0.000000 1.000000
+ 6.4 -9.966 1.000 0.000000 1.000000
+ 6.5 -9.966 1.000 0.000000 1.000000
+ 6.6 -9.966 1.000 0.000000 1.000000
+ 6.7 -9.966 1.000 0.000000 1.000000
+ 6.8 -9.966 1.000 0.000000 1.000000
+ 6.9 -9.966 1.000 0.000000 1.000000
+ 7.0 -9.966 1.000 0.000000 1.000000
+ 7.1 -9.966 1.000 0.000000 1.000000
+ 7.2 -9.966 1.000 0.000000 1.000000
+ 7.3 -9.966 1.000 0.000000 1.000000
+ 7.4 -9.966 1.000 0.000000 1.000000
+ 7.5 -9.966 1.000 0.000000 1.000000
+ 7.6 -9.966 1.000 0.000000 1.000000
+ 7.7 -9.966 1.000 0.000000 1.000000
+ 7.8 -9.966 1.000 0.000000 1.000000
+ 7.9 -9.966 1.000 0.000000 1.000000
+ 8.0 -9.966 1.000 0.000000 1.000000
+ 8.1 -9.966 1.000 0.000000 1.000000
+ 8.2 -9.966 1.000 0.000000 1.000000
+ 8.3 -9.966 1.000 0.000000 1.000000
+ 8.4 -9.966 1.000 0.000000 1.000000
+ 8.5 -9.966 1.000 0.000000 1.000000
+ 8.6 -9.966 1.000 0.000000 1.000000
+ 8.7 -9.966 1.000 0.000000 1.000000
+ 8.8 -9.966 1.000 0.000000 1.000000
+ 8.9 -9.966 1.000 0.000000 1.000000
+ 9.0 -9.966 1.000 0.000000 1.000000
+ 9.1 -9.966 1.000 0.000000 1.000000
+ 9.2 -9.966 1.000 0.000000 1.000000
+ 9.3 -9.966 1.000 0.000000 1.000000
+ 9.4 -9.966 1.000 0.000000 1.000000
+ 9.5 -9.966 1.000 0.000000 1.000000
+ 9.6 -9.966 1.000 0.000000 1.000000
+ 9.7 -9.966 1.000 0.000000 1.000000
+ 9.8 -9.966 1.000 0.000000 1.000000
+ 9.9 -9.966 1.000 0.000000 1.000000
+ 10.0 -9.966 1.000 0.000000 1.000000
+ 10.1 -9.966 1.000 0.000000 1.000000
+ 10.2 -9.966 1.000 0.000000 1.000000
+ 10.3 -9.966 1.000 0.000000 1.000000
+ 10.4 -9.966 1.000 0.000000 1.000000
+ 10.5 -9.966 1.000 0.000000 1.000000
+ 10.6 -9.966 1.000 0.000000 1.000000
+ 10.7 -9.966 1.000 0.000000 1.000000
+ 10.8 -9.966 1.000 0.000000 1.000000
+ 10.9 -9.966 1.000 0.000000 1.000000
+ 11.0 -9.966 1.000 0.000000 1.000000
+ 11.1 -9.966 1.000 0.000000 1.000000
+ 11.2 -9.966 1.000 0.000000 1.000000
+ 11.3 -9.966 1.000 0.000000 1.000000
+ 11.4 -9.966 1.000 0.000000 1.000000
+ 11.5 -9.966 1.000 0.000000 1.000000
+ 11.6 -9.966 1.000 0.000000 1.000000
+ 11.7 -9.966 1.000 0.000000 1.000000
+ 11.8 -9.966 1.000 0.000000 1.000000
+ 11.9 -9.966 1.000 0.000000 1.000000
+ 12.0 -9.966 1.000 0.000000 1.000000
+ 12.1 -9.966 1.000 0.000000 1.000000
+ 12.2 -9.966 1.000 0.000000 1.000000
+ 12.3 -9.966 1.000 0.000000 1.000000
+ 12.4 -9.966 1.000 0.000000 1.000000
+ 12.5 -9.966 1.000 0.000000 1.000000
+ 12.6 -9.966 1.000 0.000000 1.000000
+ 12.7 -9.966 1.000 0.000000 1.000000
diff --git a/lib/ccf2.f90 b/lib/ccf2.f90
new file mode 100644
index 0000000..4e74a52
--- /dev/null
+++ b/lib/ccf2.f90
@@ -0,0 +1,45 @@
+subroutine ccf2(ss,nz,nflip,ccfbest,lagpk)
+
+ parameter (LAGMAX=60)
+! parameter (LAGMAX=200)
+ real ss(nz)
+ real ccf(-LAGMAX:LAGMAX)
+ integer npr(126)
+
+! The JT65 pseudo-random sync pattern:
+ data npr/ &
+ 1,0,0,1,1,0,0,0,1,1,1,1,1,1,0,1,0,1,0,0, &
+ 0,1,0,1,1,0,0,1,0,0,0,1,1,1,0,0,1,1,1,1, &
+ 0,1,1,0,1,1,1,1,0,0,0,1,1,0,1,0,1,0,1,1, &
+ 0,0,1,1,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,1, &
+ 1,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,0,1, &
+ 0,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,0,0,1,1, &
+ 1,1,1,1,1,1/
+ save
+
+ ccfbest=0.
+ lag1=-LAGMAX
+ lag2=LAGMAX
+ do lag=lag1,lag2
+ s0=0.
+ s1=0.
+ do i=1,126
+ j=2*(8*i + 43) + lag
+ if(j.ge.1 .and. j.le.nz-8) then
+ x=ss(j)+ss(j+8) !Add two half-symbol contributions
+ if(npr(i).eq.0) then
+ s0=s0 + x
+ else
+ s1=s1 + x
+ endif
+ endif
+ enddo
+ ccf(lag)=nflip*(s1-s0)
+ if(ccf(lag).gt.ccfbest) then
+ ccfbest=ccf(lag)
+ lagpk=lag
+ endif
+ enddo
+
+ return
+end subroutine ccf2
diff --git a/lib/ccf65.f90 b/lib/ccf65.f90
new file mode 100644
index 0000000..9e667df
--- /dev/null
+++ b/lib/ccf65.f90
@@ -0,0 +1,117 @@
+subroutine ccf65(ss,nhsym,ssmax,sync1,dt1,flipk,syncshort,snr2,dt2)
+
+ parameter (NFFT=512,NH=NFFT/2)
+ real ss(322) !Input: half-symbol normalized powers
+ real s(NFFT) !CCF = ss*pr
+ complex cs(0:NH) !Complex FT of s
+ real s2(NFFT) !CCF = ss*pr2
+ complex cs2(0:NH) !Complex FT of s2
+ real pr(NFFT) !JT65 pseudo-random sync pattern
+ complex cpr(0:NH) !Complex FT of pr
+ real pr2(NFFT) !JT65 shorthand pattern
+ complex cpr2(0:NH) !Complex FT of pr2
+ real tmp1(322)
+ real ccf(-11:54)
+ logical first
+ integer npr(126)
+ data first/.true./
+ equivalence (s,cs),(pr,cpr),(s2,cs2),(pr2,cpr2)
+ save
+
+! The JT65 pseudo-random sync pattern:
+ data npr/ &
+ 1,0,0,1,1,0,0,0,1,1,1,1,1,1,0,1,0,1,0,0, &
+ 0,1,0,1,1,0,0,1,0,0,0,1,1,1,0,0,1,1,1,1, &
+ 0,1,1,0,1,1,1,1,0,0,0,1,1,0,1,0,1,0,1,1, &
+ 0,0,1,1,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,1, &
+ 1,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,0,1, &
+ 0,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,0,0,1,1, &
+ 1,1,1,1,1,1/
+
+ if(first) then
+! Initialize pr, pr2; compute cpr, cpr2.
+ fac=1.0/NFFT
+ do i=1,NFFT
+ pr(i)=0.
+ pr2(i)=0.
+ k=2*mod((i-1)/8,2)-1
+ if(i.le.NH) pr2(i)=fac*k
+ enddo
+ do i=1,126
+ j=2*i
+ pr(j)=fac*(2*npr(i)-1)
+! Not sure why, but it works significantly better without the following line:
+! pr(j-1)=pr(j)
+ enddo
+ call four2a(cpr,NFFT,1,-1,0)
+ call four2a(cpr2,NFFT,1,-1,0)
+ first=.false.
+ endif
+
+! Look for JT65 sync pattern and shorthand square-wave pattern.
+ ccfbest=0.
+ ccfbest2=0.
+ do i=1,nhsym-1
+ s(i)=min(ssmax,ss(i)+ss(i+1))
+! s(i)=ss(i)+ss(i+1)
+ enddo
+
+ call pctile(s,nhsym-1,50,base)
+ s(1:nhsym-1)=s(1:nhsym-1)-base
+ s(nhsym:NFFT)=0.
+ call four2a(cs,NFFT,1,-1,0) !Real-to-complex FFT
+ do i=0,NH
+! cs2(i)=cs(i)*conjg(cpr2(i)) !Mult by complex FFT of pr2
+ cs(i)=cs(i)*conjg(cpr(i)) !Mult by complex FFT of pr
+ enddo
+ call four2a(cs,NFFT,1,1,-1) !Complex-to-real inv-FFT
+! call four2a(cs2,NFFT,1,1,-1) !Complex-to-real inv-FFT
+
+ do lag=-11,54 !Check for best JT65 sync
+ j=lag
+ if(j.lt.1) j=j+NFFT
+ ccf(lag)=s(j)
+! if(abs(ccf(lag)).gt.ccfbest) then
+ if(ccf(lag).gt.ccfbest) then !No inverted sync for use at HF
+! ccfbest=abs(ccf(lag))
+ ccfbest=ccf(lag)
+ lagpk=lag
+ flipk=1.0
+! if(ccf(lag).lt.0.0) flipk=-1.0
+ endif
+ enddo
+
+! do lag=-11,54 !Check for best shorthand
+! ccf2=s2(lag+28)
+! if(ccf2.gt.ccfbest2) then
+! ccfbest2=ccf2
+! lagpk2=lag
+! endif
+! enddo
+
+! Find rms level on baseline of "ccfblue", for normalization.
+ sum=0.
+ do lag=-11,54
+ if(abs(lag-lagpk).gt.1) sum=sum + ccf(lag)
+ enddo
+ base=sum/50.0
+ sq=0.
+ do lag=-11,54
+ if(abs(lag-lagpk).gt.1) sq=sq + (ccf(lag)-base)**2
+ enddo
+ rms=sqrt(sq/49.0)
+ sync1=ccfbest/rms - 4.0
+ dt1=lagpk*(2048.0/11025.0) - 2.5
+
+! Find base level for normalizing snr2.
+ do i=1,nhsym
+ tmp1(i)=ss(i)
+ enddo
+ call pctile(tmp1,nhsym,40,base)
+ snr2=0.398107*ccfbest2/base !### empirical
+ syncshort=0.5*ccfbest2/rms - 4.0 !### better normalizer than rms?
+! dt2=(2.5 + lagpk2*(2048.0/11025.0))
+ dt2=0.
+
+ return
+end subroutine ccf65
diff --git a/lib/char.h b/lib/char.h
new file mode 100644
index 0000000..cc477ec
--- /dev/null
+++ b/lib/char.h
@@ -0,0 +1,57 @@
+/* Include file to configure the RS codec for character symbols
+ *
+ * Copyright 2002, Phil Karn, KA9Q
+ * May be used under the terms of the GNU General Public License (GPL)
+ */
+#define DTYPE unsigned char
+
+/* Reed-Solomon codec control block */
+struct rs {
+ int mm; /* Bits per symbol */
+ int nn; /* Symbols per block (= (1<<mm)-1) */
+ DTYPE *alpha_to; /* log lookup table */
+ DTYPE *index_of; /* Antilog lookup table */
+ DTYPE *genpoly; /* Generator polynomial */
+ int nroots; /* Number of generator roots = number of parity symbols */
+ int fcr; /* First consecutive root, index form */
+ int prim; /* Primitive element, index form */
+ int iprim; /* prim-th root of 1, index form */
+ int pad; /* Padding bytes in shortened block */
+};
+
+static inline int modnn(struct rs *rs,int x){
+ while (x >= rs->nn) {
+ x -= rs->nn;
+ x = (x >> rs->mm) + (x & rs->nn);
+ }
+ return x;
+}
+#define MODNN(x) modnn(rs,x)
+
+#define MM (rs->mm)
+#define NN (rs->nn)
+#define ALPHA_TO (rs->alpha_to)
+#define INDEX_OF (rs->index_of)
+#define GENPOLY (rs->genpoly)
+#define NROOTS (rs->nroots)
+#define FCR (rs->fcr)
+#define PRIM (rs->prim)
+#define IPRIM (rs->iprim)
+#define PAD (rs->pad)
+#define A0 (NN)
+
+#define ENCODE_RS encode_rs_char
+#define DECODE_RS decode_rs_char
+#define INIT_RS init_rs_char
+#define FREE_RS free_rs_char
+
+void ENCODE_RS(void *p,DTYPE *data,DTYPE *parity);
+int DECODE_RS(void *p,DTYPE *data,int *eras_pos,int no_eras);
+void *INIT_RS(int symsize,int gfpoly,int fcr,
+ int prim,int nroots,int pad);
+void FREE_RS(void *p);
+
+
+
+
+
diff --git a/lib/chkhist.f90 b/lib/chkhist.f90
new file mode 100644
index 0000000..6aa4a80
--- /dev/null
+++ b/lib/chkhist.f90
@@ -0,0 +1,21 @@
+subroutine chkhist(mrsym,nmax,ipk)
+
+ integer mrsym(63)
+ integer hist(0:63)
+
+ hist=0
+ do j=1,63
+ i=mrsym(j)
+ hist(i)=hist(i)+1
+ enddo
+
+ nmax=0
+ do i=0,63
+ if(hist(i).gt.nmax) then
+ nmax=hist(i)
+ ipk=i+1
+ endif
+ enddo
+
+ return
+end subroutine chkhist
diff --git a/lib/chkmsg.f90 b/lib/chkmsg.f90
new file mode 100644
index 0000000..ade13bc
--- /dev/null
+++ b/lib/chkmsg.f90
@@ -0,0 +1,31 @@
+subroutine chkmsg(message,cok,nspecial,flip)
+
+ character message*22,cok*3
+
+ nspecial=0
+ flip=1.0
+ cok=" "
+
+ do i=22,1,-1
+ if(message(i:i).ne.' ') go to 10
+ enddo
+ i=22
+
+10 if(i.ge.11) then
+ if((message(i-3:i).eq.' OOO') .or. (message(20:22).eq.' OO')) then
+ cok='OOO'
+ flip=-1.0
+ if(message(20:22).eq.' OO') then
+ message=message(1:19)
+ else
+ message=message(1:i-4)
+ endif
+ endif
+ endif
+
+ if(message(1:2).eq.'RO') nspecial=2
+ if(message(1:3).eq.'RRR') nspecial=3
+ if(message(1:2).eq.'73') nspecial=4
+
+ return
+end subroutine chkmsg
diff --git a/lib/chkss2.f90 b/lib/chkss2.f90
new file mode 100644
index 0000000..12b2a2e
--- /dev/null
+++ b/lib/chkss2.f90
@@ -0,0 +1,24 @@
+subroutine chkss2(ss2,freq,drift,schk)
+
+ real ss2(0:8,85)
+ real s(0:8,85)
+ real s1(0:5)
+ include 'jt9sync.f90'
+
+ ave=sum(ss2)/(9*85)
+ if(freq+drift.eq.-999999.0) ave=0. !To silence compiler warning
+ s=ss2/ave-1.0
+
+! call zplot9(s,freq,drift)
+ s1=0.
+ do lag=0,5
+ do i=1,16
+ j=ii(i)+lag
+ if(j.le.85) s1(lag)=s1(lag) + s(0,j)
+ enddo
+ enddo
+ schk=s1(0)/16.0
+
+ return
+end subroutine chkss2
+
diff --git a/lib/constants.f90 b/lib/constants.f90
new file mode 100644
index 0000000..2acf6bb
--- /dev/null
+++ b/lib/constants.f90
@@ -0,0 +1,5 @@
+ parameter (NTMAX=120)
+ parameter (NMAX=NTMAX*12000) !Total sample intervals per 30 minutes
+ parameter (NDMAX=NTMAX*1500) !Sample intervals at 1500 Hz rate
+ parameter (NSMAX=6827) !Max length of saved spectra
+ parameter (MAXFFT3=16384)
diff --git a/lib/conv232.f90 b/lib/conv232.f90
new file mode 100644
index 0000000..3a347e1
--- /dev/null
+++ b/lib/conv232.f90
@@ -0,0 +1,38 @@
+! Layland-Lushbaugh polynomials for a K=32, r=1/2 convolutional code,
+! and 8-bit parity lookup table.
+
+ data npoly1/-221228207/,npoly2/-463389625/
+ integer*1 partab(0:255)
+ data partab/ &
+ 0, 1, 1, 0, 1, 0, 0, 1, &
+ 1, 0, 0, 1, 0, 1, 1, 0, &
+ 1, 0, 0, 1, 0, 1, 1, 0, &
+ 0, 1, 1, 0, 1, 0, 0, 1, &
+ 1, 0, 0, 1, 0, 1, 1, 0, &
+ 0, 1, 1, 0, 1, 0, 0, 1, &
+ 0, 1, 1, 0, 1, 0, 0, 1, &
+ 1, 0, 0, 1, 0, 1, 1, 0, &
+ 1, 0, 0, 1, 0, 1, 1, 0, &
+ 0, 1, 1, 0, 1, 0, 0, 1, &
+ 0, 1, 1, 0, 1, 0, 0, 1, &
+ 1, 0, 0, 1, 0, 1, 1, 0, &
+ 0, 1, 1, 0, 1, 0, 0, 1, &
+ 1, 0, 0, 1, 0, 1, 1, 0, &
+ 1, 0, 0, 1, 0, 1, 1, 0, &
+ 0, 1, 1, 0, 1, 0, 0, 1, &
+ 1, 0, 0, 1, 0, 1, 1, 0, &
+ 0, 1, 1, 0, 1, 0, 0, 1, &
+ 0, 1, 1, 0, 1, 0, 0, 1, &
+ 1, 0, 0, 1, 0, 1, 1, 0, &
+ 0, 1, 1, 0, 1, 0, 0, 1, &
+ 1, 0, 0, 1, 0, 1, 1, 0, &
+ 1, 0, 0, 1, 0, 1, 1, 0, &
+ 0, 1, 1, 0, 1, 0, 0, 1, &
+ 0, 1, 1, 0, 1, 0, 0, 1, &
+ 1, 0, 0, 1, 0, 1, 1, 0, &
+ 1, 0, 0, 1, 0, 1, 1, 0, &
+ 0, 1, 1, 0, 1, 0, 0, 1, &
+ 1, 0, 0, 1, 0, 1, 1, 0, &
+ 0, 1, 1, 0, 1, 0, 0, 1, &
+ 0, 1, 1, 0, 1, 0, 0, 1, &
+ 1, 0, 0, 1, 0, 1, 1, 0/
diff --git a/lib/cutil.c b/lib/cutil.c
new file mode 100644
index 0000000..69a526b
--- /dev/null
+++ b/lib/cutil.c
@@ -0,0 +1,93 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+// #include <sys/times.h>
+// #include <time.h>
+// #include <sys/time.h>
+#include "sleep.h"
+#include "timeval.h"
+
+/* FORTRAN: fd = close(filedes) */
+int close_(int *filedes)
+{
+return(close(*filedes));
+}
+/* FORTRAN: fd = open(filnam,mode) */
+int open_(char filnam[], int *mode)
+{
+ return(open(filnam,*mode));
+}
+/* FORTRAN: fd = creat(filnam,mode) */
+int creat_(char filnam[],int *mode)
+{
+ return(creat(filnam,*mode));
+}
+/* FORTRAN: nread = read(fd,buf,n) */
+int read_(int *fd, char buf[], int *n)
+{
+ return(read(*fd,buf,*n));
+}
+/* FORTRAN: nwrt = write(fd,buf,n) */
+int write_(int *fd, char buf[], int *n)
+{
+ return(write(*fd,buf,*n));
+}
+/* FORTRAN: ns = lseek(fd,offset,origin) */
+int lseek_(int *fd,int *offset, int *origin)
+{
+ return(lseek(*fd,*offset,*origin));
+}
+/* times(2) */
+//int times_(struct tms *buf)
+//{
+// return (times(buf));
+//}
+/* ioperm(2) */
+//ioperm_(from,num,turn_on)
+//unsigned long *from,*num,*turn_on;
+//{
+// return (ioperm(*from,*num,*turn_on));
+// return (i386_get_ioperm(*from,*num,*turn_on));
+//}
+
+/* usleep(3) */
+void usleep_(unsigned long *microsec)
+{
+ usleep(*microsec);
+}
+
+/* returns random numbers between 0 and 32767 to FORTRAN program */
+int iran_(int *arg)
+{
+ return (rand());
+}
+
+int exit_(int *n)
+{
+ printf("\n\n");
+ exit(*n);
+}
+
+/*
+struct tm *
+gmtime_r_(const time_t *clock, struct tm *result)
+{
+ gmtime_r(clock, result);
+}
+*/
+
+time_t time_(void)
+{
+ return time(0);
+}
+
+/* hrtime() */
+double hrtime_(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv,NULL);
+ return(tv.tv_sec+1.e-6*tv.tv_usec);
+}
diff --git a/lib/db.f90 b/lib/db.f90
new file mode 100644
index 0000000..aa58f43
--- /dev/null
+++ b/lib/db.f90
@@ -0,0 +1,5 @@
+real function db(x)
+ db=-99.0
+ if(x.gt.1.259e-10) db=10.0*log10(x)
+ return
+end function db
diff --git a/lib/decode65a.f90 b/lib/decode65a.f90
new file mode 100644
index 0000000..ea61d35
--- /dev/null
+++ b/lib/decode65a.f90
@@ -0,0 +1,95 @@
+subroutine decode65a(dd,npts,newdat,f0,nflip,mode65,sync2,a,dt, &
+ nbmkv,nhist,decoded)
+
+! Apply AFC corrections to a candidate JT65 signal, then decode it.
+
+ parameter (NMAX=60*12000) !Samples per 60 s
+ real*4 dd(NMAX) !92 MB: raw data from Linrad timf2
+ complex cx(NMAX/8) !Data at 1378.125 samples/s
+ complex c5x(NMAX/32) !Data at 344.53125 Hz
+ complex c5a(512)
+ real s2(66,126)
+ real a(5)
+ logical first
+ character decoded*22
+ data first/.true./,jjjmin/1000/,jjjmax/-1000/
+ data nhz0/-9999999/
+ save
+
+! Mix sync tone to baseband, low-pass filter, downsample to 1378.125 Hz
+ dt00=dt
+ call timer('filbig ',0)
+ call filbig(dd,npts,f0,newdat,cx,n5,sq0)
+ call timer('filbig ',1)
+
+! NB: cx has sample rate 12000*77125/672000 = 1378.125 Hz
+
+! Find best DF, f1, f2, and DT. Start by downsampling to 344.53125 Hz
+ call timer('fil6521 ',0)
+! Add some zeros at start of c5 arrays -- empirical fix for negative DT's
+ nadd=1089
+ c5x(:nadd)=0.
+ call fil6521(cx,n5,c5x(nadd+1),n6)
+ n6=n6+nadd
+ call timer('fil6521 ',1)
+
+ fsample=1378.125/4.
+ a(5)=dt00
+ i0=nint((a(5)+0.5)*fsample) - 2 + nadd
+ if(i0.lt.1) then
+! write(23,*) 'i0 too small in decode1a:',i0,f0,a(5),fsample,nadd
+! flush(23)
+ i0=1
+ endif
+ nz=n6+1-i0
+
+! We're looking only at sync tone here... so why not downsample by another
+! factor of 1/8, say? Should be a significant execution speed-up.
+ call timer('afc65b ',0)
+! Best fit for DF, f1, and f2
+ call afc65b(c5x(i0),nz,fsample,nflip,a,ccfbest,dtbest)
+ call timer('afc65b ',1)
+
+ sync2=3.7e-4*ccfbest/sq0 !Constant is empirical
+
+! Apply AFC corrections to the time-domain signal
+! Now we are back to using the 1378.125 Hz sample rate, enough to
+! accommodate the full JT65C bandwidth.
+
+ call timer('twkfreq ',0)
+ call twkfreq65(cx,n5,a)
+ call timer('twkfreq ',1)
+
+! Compute spectrum for each half symbol.
+! Adding or subtracting a small number (e.g., 5) to j may make it decode.\
+! NB: might want to try computing full-symbol spectra (nfft=512, even for
+! submodes B and C).
+
+ nsym=126
+ nfft=512
+ j=(dt00+dtbest+2.685)*1378.125
+ if(j.lt.0) j=0
+
+ call timer('sh_ffts ',0)
+ do k=1,nsym
+ do i=1,nfft
+ j=j+1
+ c5a(i)=cx(j)
+ enddo
+ call four2a(c5a,nfft,1,1,1)
+ do i=1,66
+ jj=i
+ if(mode65.eq.2) jj=2*i-1
+ if(mode65.eq.4) jj=4*i-3
+ s2(i,k)=real(c5a(jj))**2 + aimag(c5a(jj))**2
+ enddo
+ enddo
+ call timer('sh_ffts ',1)
+
+ call timer('dec65b ',0)
+ call decode65b(s2,nflip,mode65,nbmkv,nhist,decoded)
+ dt=dt00 + dtbest + 1.7
+ call timer('dec65b ',1)
+
+ return
+end subroutine decode65a
diff --git a/lib/decode65b.f90 b/lib/decode65b.f90
new file mode 100644
index 0000000..729a218
--- /dev/null
+++ b/lib/decode65b.f90
@@ -0,0 +1,36 @@
+subroutine decode65b(s2,nflip,mode65,nbmkv,nhist,decoded)
+
+ real s2(66,126)
+ real s3(64,63)
+ logical first,ltext
+ character decoded*22
+ common/prcom/pr(126),mdat(126),mref(126,2),mdat2(126),mref2(126,2)
+ data first/.true./
+ save
+
+ if(first) call setup65
+ first=.false.
+
+ do j=1,63
+ k=mdat(j) !Points to data symbol
+ if(nflip.lt.0) k=mdat2(j)
+ do i=1,64
+ s3(i,j)=s2(i+2,k)
+ enddo
+ k=mdat2(j) !Points to data symbol
+ if(nflip.lt.0) k=mdat(j)
+ enddo
+
+ nadd=mode65
+ call extract(s3,nadd,ncount,nhist,decoded,ltext,nbmkv) !Extract the message
+! Suppress "birdie messages" and other garbage decodes:
+ if(decoded(1:7).eq.'000AAA ') ncount=-1
+ if(decoded(1:7).eq.'0L6MWK ') ncount=-1
+ if(nflip.lt.0 .and. ltext) ncount=-1
+ if(ncount.lt.0) then
+ nbmkv=0
+ decoded=' '
+ endif
+
+ return
+end subroutine decode65b
diff --git a/lib/decode9.f90 b/lib/decode9.f90
new file mode 100644
index 0000000..06809eb
--- /dev/null
+++ b/lib/decode9.f90
@@ -0,0 +1,85 @@
+subroutine decode9(i1SoftSymbols,limit,nlim,msg)
+
+! Decoder for JT9
+! Input: i1SoftSymbols(207) - Single-bit soft symbols
+! Output: msg - decoded message (blank if erasure)
+
+ character*22 msg
+ integer*4 i4DecodedBytes(9)
+ integer*4 i4Decoded6BitWords(12)
+ integer*1 i1DecodedBytes(13) !72 bits and zero tail as 8-bit bytes
+ integer*1 i1SoftSymbols(207)
+ integer*1 i1DecodedBits(72)
+
+ real*4 xx0(0:255)
+
+ logical first
+ integer*4 mettab(0:255,0:1)
+ data first/.true./
+ data xx0/ & !Metric table
+ 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, &
+ 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, &
+ 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, &
+ 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, &
+ 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, &
+ 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, &
+ 0.988, 1.000, 0.991, 0.993, 1.000, 0.995, 1.000, 0.991, &
+ 1.000, 0.991, 0.992, 0.991, 0.990, 0.990, 0.992, 0.996, &
+ 0.990, 0.994, 0.993, 0.991, 0.992, 0.989, 0.991, 0.987, &
+ 0.985, 0.989, 0.984, 0.983, 0.979, 0.977, 0.971, 0.975, &
+ 0.974, 0.970, 0.970, 0.970, 0.967, 0.962, 0.960, 0.957, &
+ 0.956, 0.953, 0.942, 0.946, 0.937, 0.933, 0.929, 0.920, &
+ 0.917, 0.911, 0.903, 0.895, 0.884, 0.877, 0.869, 0.858, &
+ 0.846, 0.834, 0.821, 0.806, 0.790, 0.775, 0.755, 0.737, &
+ 0.713, 0.691, 0.667, 0.640, 0.612, 0.581, 0.548, 0.510, &
+ 0.472, 0.425, 0.378, 0.328, 0.274, 0.212, 0.146, 0.075, &
+ 0.000,-0.079,-0.163,-0.249,-0.338,-0.425,-0.514,-0.606, &
+ -0.706,-0.796,-0.895,-0.987,-1.084,-1.181,-1.280,-1.376, &
+ -1.473,-1.587,-1.678,-1.790,-1.882,-1.992,-2.096,-2.201, &
+ -2.301,-2.411,-2.531,-2.608,-2.690,-2.829,-2.939,-3.058, &
+ -3.164,-3.212,-3.377,-3.463,-3.550,-3.768,-3.677,-3.975, &
+ -4.062,-4.098,-4.186,-4.261,-4.472,-4.621,-4.623,-4.608, &
+ -4.822,-4.870,-4.652,-4.954,-5.108,-5.377,-5.544,-5.995, &
+ -5.632,-5.826,-6.304,-6.002,-6.559,-6.369,-6.658,-7.016, &
+ -6.184,-7.332,-6.534,-6.152,-6.113,-6.288,-6.426,-6.313, &
+ -9.966,-6.371,-9.966,-7.055,-9.966,-6.629,-6.313,-9.966, &
+ -5.858,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966, &
+ -9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966, &
+ -9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966, &
+ -9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966, &
+ -9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966, &
+ -9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966/
+ save
+
+ if(first) then
+! Get the metric table
+ bias=0.5
+ scale=10
+ do i=0,255
+ mettab(i,0)=nint(scale*(xx0(i)-bias))
+ if(i.ge.1) mettab(256-i,1)=mettab(i,0)
+ enddo
+ first=.false.
+ endif
+
+ msg=' '
+ nbits=72
+ ndelta=17
+ call fano232(i1SoftSymbols,nbits+31,mettab,ndelta,limit,i1DecodedBytes, &
+ ncycles,metric,ierr)
+
+ nlim=ncycles/(nbits+31)
+ if(ncycles.lt.(nbits*limit)) then
+ nbytes=(nbits+7)/8
+ do i=1,nbytes
+ n=i1DecodedBytes(i)
+ i4DecodedBytes(i)=iand(n,255)
+ enddo
+ call unpackbits(i4DecodedBytes,nbytes,8,i1DecodedBits)
+ call packbits(i1DecodedBits,12,6,i4Decoded6BitWords)
+ call unpackmsg(i4Decoded6BitWords,msg) !Unpack decoded msg
+ if(index(msg,'000AAA ').gt.0) msg=' '
+ endif
+
+ return
+end subroutine decode9
diff --git a/lib/decode_rs.c b/lib/decode_rs.c
new file mode 100644
index 0000000..ac85edd
--- /dev/null
+++ b/lib/decode_rs.c
@@ -0,0 +1,263 @@
+/* Reed-Solomon decoder
+ * Copyright 2002 Phil Karn, KA9Q
+ * May be used under the terms of the GNU General Public License (GPL)
+ */
+
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+#include <string.h>
+
+//#define NULL ((void *)0)
+#define min(a,b) ((a) < (b) ? (a) : (b))
+
+#ifdef FIXED
+#include "fixed.h"
+#elif defined(BIGSYM)
+#include "int.h"
+#else
+#include "char.h"
+#endif
+
+int DECODE_RS(
+#ifdef FIXED
+DTYPE *data, int *eras_pos, int no_eras,int pad){
+#else
+void *p,DTYPE *data, int *eras_pos, int no_eras){
+ struct rs *rs = (struct rs *)p;
+#endif
+ int deg_lambda, el, deg_omega;
+ int i, j, r,k;
+ DTYPE u,q,tmp,num1,num2,den,discr_r;
+ DTYPE lambda[NROOTS+1], s[NROOTS]; /* Err+Eras Locator poly
+ * and syndrome poly */
+ DTYPE b[NROOTS+1], t[NROOTS+1], omega[NROOTS+1];
+ DTYPE root[NROOTS], reg[NROOTS+1], loc[NROOTS];
+ int syn_error, count;
+
+#ifdef FIXED
+ /* Check pad parameter for validity */
+ if(pad < 0 || pad >= NN)
+ return -1;
+#endif
+
+ /* form the syndromes; i.e., evaluate data(x) at roots of g(x) */
+ for(i=0;i<NROOTS;i++)
+ s[i] = data[0];
+
+ for(j=1;j<NN-PAD;j++){
+ for(i=0;i<NROOTS;i++){
+ if(s[i] == 0){
+ s[i] = data[j];
+ } else {
+ s[i] = data[j] ^ ALPHA_TO[MODNN(INDEX_OF[s[i]] + (FCR+i)*PRIM)];
+ }
+ }
+ }
+
+ /* Convert syndromes to index form, checking for nonzero condition */
+ syn_error = 0;
+ for(i=0;i<NROOTS;i++){
+ syn_error |= s[i];
+ s[i] = INDEX_OF[s[i]];
+ }
+
+ if (!syn_error) {
+ /* if syndrome is zero, data[] is a codeword and there are no
+ * errors to correct. So return data[] unmodified
+ */
+ count = 0;
+ goto finish;
+ }
+ memset(&lambda[1],0,NROOTS*sizeof(lambda[0]));
+ lambda[0] = 1;
+
+ if (no_eras > 0) {
+ /* Init lambda to be the erasure locator polynomial */
+ lambda[1] = ALPHA_TO[MODNN(PRIM*(NN-1-eras_pos[0]))];
+ for (i = 1; i < no_eras; i++) {
+ u = MODNN(PRIM*(NN-1-eras_pos[i]));
+ for (j = i+1; j > 0; j--) {
+ tmp = INDEX_OF[lambda[j - 1]];
+ if(tmp != A0)
+ lambda[j] ^= ALPHA_TO[MODNN(u + tmp)];
+ }
+ }
+
+#if DEBUG >= 1
+ /* Test code that verifies the erasure locator polynomial just constructed
+ Needed only for decoder debugging. */
+
+ /* find roots of the erasure location polynomial */
+ for(i=1;i<=no_eras;i++)
+ reg[i] = INDEX_OF[lambda[i]];
+
+ count = 0;
+ for (i = 1,k=IPRIM-1; i <= NN; i++,k = MODNN(k+IPRIM)) {
+ q = 1;
+ for (j = 1; j <= no_eras; j++)
+ if (reg[j] != A0) {
+ reg[j] = MODNN(reg[j] + j);
+ q ^= ALPHA_TO[reg[j]];
+ }
+ if (q != 0)
+ continue;
+ /* store root and error location number indices */
+ root[count] = i;
+ loc[count] = k;
+ count++;
+ }
+ if (count != no_eras) {
+ printf("count = %d no_eras = %d\n lambda(x) is WRONG\n",count,no_eras);
+ count = -1;
+ goto finish;
+ }
+#if DEBUG >= 2
+ printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n");
+ for (i = 0; i < count; i++)
+ printf("%d ", loc[i]);
+ printf("\n");
+#endif
+#endif
+ }
+ for(i=0;i<NROOTS+1;i++)
+ // printf("%d %d %d\n",i,lambda[i],INDEX_OF[lambda[i]]);
+ b[i] = INDEX_OF[lambda[i]];
+
+ /*
+ * Begin Berlekamp-Massey algorithm to determine error+erasure
+ * locator polynomial
+ */
+ r = no_eras;
+ el = no_eras;
+ while (++r <= NROOTS) { /* r is the step number */
+ /* Compute discrepancy at the r-th step in poly-form */
+ discr_r = 0;
+ for (i = 0; i < r; i++){
+ if ((lambda[i] != 0) && (s[r-i-1] != A0)) {
+ discr_r ^= ALPHA_TO[MODNN(INDEX_OF[lambda[i]] + s[r-i-1])];
+ }
+ }
+ discr_r = INDEX_OF[discr_r]; /* Index form */
+ if (discr_r == A0) {
+ /* 2 lines below: B(x) <-- x*B(x) */
+ memmove(&b[1],b,NROOTS*sizeof(b[0]));
+ b[0] = A0;
+ } else {
+ /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */
+ t[0] = lambda[0];
+ for (i = 0 ; i < NROOTS; i++) {
+ if(b[i] != A0)
+ t[i+1] = lambda[i+1] ^ ALPHA_TO[MODNN(discr_r + b[i])];
+ else
+ t[i+1] = lambda[i+1];
+ }
+ if (2 * el <= r + no_eras - 1) {
+ el = r + no_eras - el;
+ /*
+ * 2 lines below: B(x) <-- inv(discr_r) *
+ * lambda(x)
+ */
+ for (i = 0; i <= NROOTS; i++)
+ b[i] = (lambda[i] == 0) ? A0 : MODNN(INDEX_OF[lambda[i]] - discr_r + NN);
+ } else {
+ /* 2 lines below: B(x) <-- x*B(x) */
+ memmove(&b[1],b,NROOTS*sizeof(b[0]));
+ b[0] = A0;
+ }
+ memcpy(lambda,t,(NROOTS+1)*sizeof(t[0]));
+ }
+ }
+
+ /* Convert lambda to index form and compute deg(lambda(x)) */
+ deg_lambda = 0;
+ for(i=0;i<NROOTS+1;i++){
+ lambda[i] = INDEX_OF[lambda[i]];
+ if(lambda[i] != A0)
+ deg_lambda = i;
+ }
+ /* Find roots of the error+erasure locator polynomial by Chien search */
+ memcpy(®[1],&lambda[1],NROOTS*sizeof(reg[0]));
+ count = 0; /* Number of roots of lambda(x) */
+ for (i = 1,k=IPRIM-1; i <= NN; i++,k = MODNN(k+IPRIM)) {
+ q = 1; /* lambda[0] is always 0 */
+ for (j = deg_lambda; j > 0; j--){
+ if (reg[j] != A0) {
+ reg[j] = MODNN(reg[j] + j);
+ q ^= ALPHA_TO[reg[j]];
+ }
+ }
+ if (q != 0)
+ continue; /* Not a root */
+ /* store root (index-form) and error location number */
+#if DEBUG>=2
+ printf("count %d root %d loc %d\n",count,i,k);
+#endif
+ root[count] = i;
+ loc[count] = k;
+ /* If we've already found max possible roots,
+ * abort the search to save time
+ */
+ if(++count == deg_lambda)
+ break;
+ }
+ if (deg_lambda != count) {
+ /*
+ * deg(lambda) unequal to number of roots => uncorrectable
+ * error detected
+ */
+ count = -1;
+ goto finish;
+ }
+ /*
+ * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
+ * x**NROOTS). in index form. Also find deg(omega).
+ */
+ deg_omega = deg_lambda-1;
+ for (i = 0; i <= deg_omega;i++){
+ tmp = 0;
+ for(j=i;j >= 0; j--){
+ if ((s[i - j] != A0) && (lambda[j] != A0))
+ tmp ^= ALPHA_TO[MODNN(s[i - j] + lambda[j])];
+ }
+ omega[i] = INDEX_OF[tmp];
+ }
+
+ /*
+ * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
+ * inv(X(l))**(FCR-1) and den = lambda_pr(inv(X(l))) all in poly-form
+ */
+ for (j = count-1; j >=0; j--) {
+ num1 = 0;
+ for (i = deg_omega; i >= 0; i--) {
+ if (omega[i] != A0)
+ num1 ^= ALPHA_TO[MODNN(omega[i] + i * root[j])];
+ }
+ num2 = ALPHA_TO[MODNN(root[j] * (FCR - 1) + NN)];
+ den = 0;
+
+ /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */
+ for (i = min(deg_lambda,NROOTS-1) & ~1; i >= 0; i -=2) {
+ if(lambda[i+1] != A0)
+ den ^= ALPHA_TO[MODNN(lambda[i+1] + i * root[j])];
+ }
+#if DEBUG >= 1
+ if (den == 0) {
+ printf("\n ERROR: denominator = 0\n");
+ count = -1;
+ goto finish;
+ }
+#endif
+ /* Apply error to data */
+ if (num1 != 0 && loc[j] >= PAD) {
+ data[loc[j]-PAD] ^= ALPHA_TO[MODNN(INDEX_OF[num1] + INDEX_OF[num2] + NN - INDEX_OF[den])];
+ }
+ }
+ finish:
+ if(eras_pos != NULL){
+ for(i=0;i<count;i++)
+ eras_pos[i] = loc[i];
+ }
+ return count;
+}
diff --git a/lib/decoder.f90 b/lib/decoder.f90
new file mode 100644
index 0000000..83e63a2
--- /dev/null
+++ b/lib/decoder.f90
@@ -0,0 +1,173 @@
+subroutine decoder(ss,id2)
+
+! Decoder for JT9.
+
+ include 'constants.f90'
+ real ss(184,NSMAX)
+ character*22 msg
+ character*20 datetime
+ real*4 ccfred(NSMAX)
+ real*4 red2(NSMAX)
+ logical ccfok(NSMAX)
+ logical done(NSMAX)
+ logical done65
+ integer*2 id2(NTMAX*12000)
+ real*4 dd(NTMAX*12000)
+ integer*1 i1SoftSymbols(207)
+ common/npar/nutc,ndiskdat,ntrperiod,nfqso,newdat,npts8,nfa,nfb,ntol, &
+ kin,nzhsym,nsave,nagain,ndepth,ntxmode,nmode,datetime
+ common/tracer/limtrace,lu
+ save
+
+ call system_clock(iclock0,iclock_rate,iclock_max) !###
+ nfreqs0=0
+ nfreqs1=0
+ ndecodes0=0
+ ndecodes1=0
+
+ open(13,file='decoded.txt',status='unknown')
+ open(22,file='kvasd.dat',access='direct',recl=1024,status='unknown')
+
+ npts65=52*12000
+ ntol65=20
+ done65=.false.
+ if(nmode.ge.65 .and. ntxmode.eq.65) then
+ if(newdat.ne.0) dd(1:npts65)=id2(1:npts65)
+ call jt65a(dd,npts65,newdat,nutc,nfa,nfqso,ntol65,nagain,ndecoded)
+ done65=.true.
+ endif
+
+ if(nmode.eq.65) go to 800
+
+ nsynced=0
+ ndecoded=0
+ nsps=0
+
+ nsps=6912 !Params for JT9-1
+ df3=1500.0/2048.0
+
+ tstep=0.5*nsps/12000.0 !Half-symbol step (seconds)
+ done=.false.
+
+ nf0=0
+ ia=max(1,nint((nfa-nf0)/df3))
+ ib=min(NSMAX,nint((nfb-nf0)/df3))
+ lag1=-(2.5/tstep + 0.9999)
+ lag2=5.0/tstep + 0.9999
+ if(newdat.ne.0) then
+ call timer('sync9 ',0)
+ call sync9(ss,nzhsym,lag1,lag2,ia,ib,ccfred,red2,ipk)
+ call timer('sync9 ',1)
+ endif
+
+ nsps8=nsps/8
+ df8=1500.0/nsps8
+ dblim=db(864.0/nsps8) - 26.2
+
+ do nqd=1,0,-1
+ limit=1000
+ ccflim=4.0
+ red2lim=1.6
+ schklim=2.2
+ if(ndepth.eq.2) then
+ limit=10000
+ ccflim=3.5
+ endif
+ if(ndepth.ge.3 .or. nqd.eq.1) then
+ limit=100000
+ ccflim=2.5
+ endif
+ ccfok=.false.
+
+ if(nqd.eq.1) then
+ nfa1=nfqso-ntol
+ nfb1=nfqso+ntol
+ ia=max(1,nint((nfa1-nf0)/df3))
+ ib=min(NSMAX,nint((nfb1-nf0)/df3))
+ ccfok(ia:ib)=(ccfred(ia:ib).gt.(ccflim-2.0)) .and. &
+ (red2(ia:ib).gt.(red2lim-1.0))
+ ia1=ia
+ ib1=ib
+ else
+ nfa1=nfa
+ nfb1=nfb
+ ia=max(1,nint((nfa1-nf0)/df3))
+ ib=min(NSMAX,nint((nfb1-nf0)/df3))
+ do i=ia,ib
+ ccfok(i)=ccfred(i).gt.ccflim .and. red2(i).gt.red2lim
+ enddo
+ ccfok(ia1:ib1)=.false.
+ endif
+
+ fgood=0.
+ do i=ia,ib
+ if(done(i) .or. (.not.ccfok(i))) cycle
+ f=(i-1)*df3
+ if(nqd.eq.1 .or. &
+ (ccfred(i).ge.ccflim .and. abs(f-fgood).gt.10.0*df8)) then
+
+ if(nqd.eq.0) nfreqs0=nfreqs0+1
+ if(nqd.eq.1) nfreqs1=nfreqs1+1
+
+ call timer('softsym ',0)
+ fpk=nf0 + df3*(i-1)
+
+ call softsym(id2,npts8,nsps8,newdat,fpk,syncpk,snrdb,xdt, &
+ freq,drift,schk,i1SoftSymbols)
+ call timer('softsym ',1)
+
+! write(71,3001) nqd,i,f,fpk,ccfred(i),red2(i),schk
+!3001 format(2i6,2f8.1,3f6.1)
+! call flush(71)
+
+ if(schk.lt.schklim) cycle
+
+ call timer('decode9 ',0)
+ call decode9(i1SoftSymbols,limit,nlim,msg)
+ call timer('decode9 ',1)
+
+ sync=(syncpk+1)/4.0
+ if(sync.lt.0.0 .or. snrdb.lt.dblim-2.0) sync=0.0
+ nsync=sync
+ if(nsync.gt.10) nsync=10
+ nsnr=nint(snrdb)
+ ndrift=nint(drift/df3)
+
+ if(msg.ne.' ') then
+ if(nqd.eq.0) ndecodes0=ndecodes0+1
+ if(nqd.eq.1) ndecodes1=ndecodes1+1
+
+ write(*,1000) nutc,nsnr,xdt,nint(freq),msg
+1000 format(i4.4,i4,f5.1,i5,1x,'@',1x,a22)
+ write(13,1002) nutc,nsync,nsnr,xdt,freq,ndrift,msg
+1002 format(i4.4,i4,i5,f6.1,f8.0,i4,3x,a22,' JT9')
+
+ iaa=max(1,i-1)
+ ibb=min(NSMAX,i+22)
+ fgood=f
+ nsynced=1
+ ndecoded=1
+ ccfok(iaa:ibb)=.false.
+ done(iaa:ibb)=.true.
+ call flush(6)
+ endif
+ endif
+ enddo
+ call flush(6)
+ if(nagain.ne.0) exit
+ enddo
+
+ if(nmode.ge.65 .and. (.not.done65)) then
+ if(newdat.ne.0) dd(1:npts65)=id2(1:npts65)
+ call jt65a(dd,npts65,newdat,nutc,nfa,nfqso,ntol65,nagain,ndecoded)
+ endif
+
+!### JT65 is not yet producing info for nsynced, ndecoded.
+800 write(*,1010) nsynced,ndecoded
+1010 format('<DecodeFinished>',2i4)
+ call flush(6)
+ close(13)
+ close(22)
+
+ return
+end subroutine decoder
diff --git a/lib/deep24.f90 b/lib/deep24.f90
new file mode 100644
index 0000000..70a69ae
--- /dev/null
+++ b/lib/deep24.f90
@@ -0,0 +1,182 @@
+subroutine deep24(sym,neme,flip,mycall,hiscall,hisgrid,decoded,qual)
+
+! Have barely begun converting this from JT65 to JT4
+
+ parameter (MAXCALLS=7000,MAXRPT=63)
+ real*4 sym(206)
+ character callsign*12,grid*4,message*22,hisgrid*6,c*1,ceme*3
+ character*12 mycall,hiscall
+ character mycall0*12,hiscall0*12,hisgrid0*6
+ character*22 decoded
+ character*22 testmsg(2*MAXCALLS + 2 + MAXRPT)
+ character*15 callgrid(MAXCALLS)
+ character*180 line
+ character*4 rpt(MAXRPT)
+ integer ncode(206)
+ real*4 code(206,2*MAXCALLS + 2 + MAXRPT)
+ real pp(2*MAXCALLS + 2 + MAXRPT)
+! common/c3com/ mcall3a
+
+ data neme0/-99/
+ data rpt/'-01','-02','-03','-04','-05', &
+ '-06','-07','-08','-09','-10', &
+ '-11','-12','-13','-14','-15', &
+ '-16','-17','-18','-19','-20', &
+ '-21','-22','-23','-24','-25', &
+ '-26','-27','-28','-29','-30', &
+ 'R-01','R-02','R-03','R-04','R-05', &
+ 'R-06','R-07','R-08','R-09','R-10', &
+ 'R-11','R-12','R-13','R-14','R-15', &
+ 'R-16','R-17','R-18','R-19','R-20', &
+ 'R-21','R-22','R-23','R-24','R-25', &
+ 'R-26','R-27','R-28','R-29','R-30', &
+ 'RO','RRR','73'/
+ save
+
+ if(mycall.eq.mycall0 .and. hiscall.eq.hiscall0 .and. &
+ hisgrid.eq.hisgrid0 .and. mcall3a.eq.0 .and. neme.eq.neme0) go to 30
+
+ mcall3a=0
+ rewind 23
+ k=0
+ icall=0
+ do n=1,MAXCALLS
+ if(n.eq.1) then
+ callsign=hiscall
+ do i=4,12
+ if(ichar(callsign(i:i)).eq.0) callsign(i:i)=' '
+ enddo
+ grid=hisgrid(1:4)
+ if(ichar(grid(3:3)).eq.0) grid(3:3)=' '
+ if(ichar(grid(4:4)).eq.0) grid(4:4)=' '
+ else
+ read(23,1002,end=20) line
+1002 format (A80)
+ if(line(1:4).eq.'ZZZZ') go to 20
+ if(line(1:2).eq.'//') go to 10
+ i1=index(line,',')
+ if(i1.lt.4) go to 10
+ i2=index(line(i1+1:),',')
+ if(i2.lt.5) go to 10
+ i2=i2+i1
+ i3=index(line(i2+1:),',')
+ if(i3.lt.1) i3=index(line(i2+1:),' ')
+ i3=i2+i3
+ callsign=line(1:i1-1)
+ grid=line(i1+1:i2-1)
+ ceme=line(i2+1:i3-1)
+ if(neme.eq.1 .and. ceme.ne.'EME') go to 10
+ endif
+
+ icall=icall+1
+ j1=index(mycall,' ') - 1
+ if(j1.le.-1) j1=12
+ if(j1.lt.3) j1=6
+ j2=index(callsign,' ') - 1
+ if(j2.le.-1) j2=12
+ if(j2.lt.3) j2=6
+ j3=index(mycall,'/') ! j3>0 means compound mycall
+ j4=index(callsign,'/') ! j4>0 means compound hiscall
+ callgrid(icall)=callsign(1:j2)
+
+ mz=1
+! Allow MyCall + HisCall + rpt (?)
+ if(n.eq.1 .and. j3.lt.1 .and. j4.lt.1 .and. &
+ flip.gt.0.0 .and. callsign(1:6).ne.' ') mz=MAXRPT+1
+ do m=1,mz
+ if(m.gt.1) grid=rpt(m-1)
+ if(j3.lt.1 .and.j4.lt.1) callgrid(icall)=callsign(1:j2)//' '//grid
+ message=mycall(1:j1)//' '//callgrid(icall)
+ k=k+1
+ testmsg(k)=message
+ call encode4(message,ncode)
+ code(1:206,k)=2*ncode(1:206)-1
+ if(n.ge.2) then
+! Insert CQ message
+ if(j4.lt.1) callgrid(icall)=callsign(1:j2)//' '//grid
+ message='CQ '//callgrid(icall)
+ k=k+1
+ testmsg(k)=message
+ call encode4(message,ncode)
+ code(1:206,k)=2*ncode(1:206)-1
+ endif
+ enddo
+10 continue
+ enddo
+
+20 continue
+ ntot=k
+ neme0=neme
+
+30 mycall0=mycall
+ hiscall0=hiscall
+ hisgrid0=hisgrid
+
+ sq=0.
+ do j=1,206
+ sq=sq + sym(j)**2
+ enddo
+ rms=sqrt(sq/206.0)
+ sym=sym/rms
+
+ p1=-1.e30
+ p2=-1.e30
+ do k=1,ntot
+ pp(k)=0.
+! Test all messages if flip=+1; skip the CQ messages if flip=-1.
+ if(flip.gt.0.0 .or. testmsg(k)(1:3).ne.'CQ ') then
+ p=0.
+ do j=1,206
+ i=code(j,k)+1
+ p=p + code(j,k)*sym(j)
+ enddo
+ pp(k)=p
+ if(p.gt.p1) then
+ p1=p
+ ip1=k
+ endif
+ endif
+ enddo
+
+ do i=1,ntot
+ if(pp(i).gt.p2 .and. pp(i).ne.p1) p2=pp(i)
+ enddo
+
+! ### DO NOT REMOVE ###
+! rewind 77
+! write(77,*) p1,p2
+! ### Works OK without it (in both Windows and Linux) if compiled
+! ### without optimization. However, in Windows this is a colossal
+! ### pain because of the way F2PY wants to run the compile step.
+
+
+ bias=1.1*p2
+! if(mode65.eq.1) bias=max(1.12*p2,0.335)
+! if(mode65.eq.2) bias=max(1.08*p2,0.405)
+! if(mode65.ge.4) bias=max(1.04*p2,0.505)
+
+ if(p2.eq.p1 .and. p1.ne.-1.e30) stop 'Error in deep24'
+ qual=10.0*(p1-bias)
+
+ decoded=' '
+ c=' '
+
+ if(qual.gt.1.0) then
+ if(qual.lt.6.0) c='?'
+ decoded=testmsg(ip1)
+ else
+ qual=0.
+ endif
+ decoded(22:22)=c
+
+! Make sure everything is upper case.
+ do i=1,22
+ if(decoded(i:i).ge.'a' .and. decoded(i:i).le.'z') &
+ decoded(i:i)=char(ichar(decoded(i:i))-32)
+ enddo
+
+! write(*,3010) p1,p2,p1-p2,p1/p2,qual,decoded
+!3010 format('DS:',5f9.1,2x,a22)
+
+ return
+end subroutine deep24
diff --git a/lib/deg2grid.f90 b/lib/deg2grid.f90
new file mode 100644
index 0000000..4fdc2af
--- /dev/null
+++ b/lib/deg2grid.f90
@@ -0,0 +1,30 @@
+subroutine deg2grid(dlong0,dlat,grid)
+
+ real dlong !West longitude (deg)
+ real dlat !Latitude (deg)
+ character grid*6
+
+ dlong=dlong0
+ if(dlong.lt.-180.0) dlong=dlong+360.0
+ if(dlong.gt.180.0) dlong=dlong-360.0
+
+! Convert to units of 5 min of longitude, working east from 180 deg.
+ nlong=int(60.0*(180.0-dlong)/5.0)
+ n1=nlong/240 !20-degree field
+ n2=(nlong-240*n1)/24 !2 degree square
+ n3=nlong-240*n1-24*n2 !5 minute subsquare
+ grid(1:1)=char(ichar('A')+n1)
+ grid(3:3)=char(ichar('0')+n2)
+ grid(5:5)=char(ichar('a')+n3)
+
+! Convert to units of 2.5 min of latitude, working north from -90 deg.
+ nlat=int(60.0*(dlat+90)/2.5)
+ n1=nlat/240 !10-degree field
+ n2=(nlat-240*n1)/24 !1 degree square
+ n3=nlat-240*n1-24*n2 !2.5 minuts subsquare
+ grid(2:2)=char(ichar('A')+n1)
+ grid(4:4)=char(ichar('0')+n2)
+ grid(6:6)=char(ichar('a')+n3)
+
+ return
+end subroutine deg2grid
diff --git a/lib/demod64a.f90 b/lib/demod64a.f90
new file mode 100644
index 0000000..9d1a379
--- /dev/null
+++ b/lib/demod64a.f90
@@ -0,0 +1,73 @@
+subroutine demod64a(s3,nadd,mrsym,mrprob,mr2sym,mr2prob,ntest,nlow)
+
+! Demodulate the 64-bin spectra for each of 63 symbols in a frame.
+
+! Parameters
+! nadd number of spectra already summed
+! mrsym most reliable symbol value
+! mr2sym second most likely symbol value
+! mrprob probability that mrsym was the transmitted value
+! mr2prob probability that mr2sym was the transmitted value
+
+ implicit real*8 (a-h,o-z)
+ real*4 s3(64,63)
+ real*8 fs(64)
+ integer mrsym(63),mrprob(63),mr2sym(63),mr2prob(63)
+! common/mrscom/ mrs(63),mrs2(63)
+
+ if(nadd.eq.-999) return
+ afac=1.1 * float(nadd)**0.64
+ scale=255.999
+
+! Compute average spectral value
+ sum=0.
+ do j=1,63
+ do i=1,64
+ sum=sum+s3(i,j)
+ enddo
+ enddo
+ ave=sum/(64.*63.)
+ i1=1 !Silence warning
+ i2=1
+
+! Compute probabilities for most reliable symbol values
+ do j=1,63
+ s1=-1.e30
+ fsum=0.
+ do i=1,64
+ x=min(afac*s3(i,j)/ave,50.d0)
+ fs(i)=exp(x)
+ fsum=fsum+fs(i)
+ if(s3(i,j).gt.s1) then
+ s1=s3(i,j)
+ i1=i !Most reliable
+ endif
+ enddo
+
+ s2=-1.e30
+ do i=1,64
+ if(i.ne.i1 .and. s3(i,j).gt.s2) then
+ s2=s3(i,j)
+ i2=i !Second most reliable
+ endif
+ enddo
+ p1=fs(i1)/fsum !Normalized probabilities
+ p2=fs(i2)/fsum
+ mrsym(j)=i1-1
+ mr2sym(j)=i2-1
+ mrprob(j)=scale*p1
+ mr2prob(j)=scale*p2
+! mrs(j)=i1
+! mrs2(j)=i2
+ enddo
+
+ sum=0.
+ nlow=0
+ do j=1,63
+ sum=sum+mrprob(j)
+ if(mrprob(j).le.5) nlow=nlow+1
+ enddo
+ ntest=sum/63
+
+ return
+end subroutine demod64a
diff --git a/lib/downsam9.f90 b/lib/downsam9.f90
new file mode 100644
index 0000000..851d497
--- /dev/null
+++ b/lib/downsam9.f90
@@ -0,0 +1,66 @@
+subroutine downsam9(id2,npts8,nsps8,newdat,nspsd,fpk,c2,nz2)
+
+!Downsample from id2() into C2() so as to yield nspsd samples per symbol,
+!mixing from fpk down to zero frequency.
+
+ include 'constants.f90'
+ parameter (NMAX1=1024*1920)
+ integer*2 id2(0:8*npts8-1)
+ real*4 x1(0:NMAX1-1)
+ complex c1(0:NMAX1/2)
+ complex c2(0:4096-1)
+ real s(5000)
+ equivalence (c1,x1)
+ save
+
+ nfft1=1024*nsps8 !Forward FFT length
+ df1=12000.0/nfft1
+ npts=8*npts8
+
+ if(newdat.eq.1) then
+ fac=6.963e-6 !Why this weird constant?
+ do i=0,npts-1
+ x1(i)=fac*id2(i)
+ enddo
+ x1(npts:nfft1-1)=0. !Zero the rest of x1
+ call timer('fft_forw',0)
+ call four2a(c1,nfft1,1,-1,0) !Forward FFT, r2c
+ call timer('fft_forw',1)
+
+ nadd=1.0/df1
+ s=0.
+ do i=1,5000
+ j=(i-1)/df1
+ do n=1,nadd
+ j=j+1
+ s(i)=s(i)+real(c1(j))**2 + aimag(c1(j))**2
+ enddo
+ enddo
+ endif
+
+ ndown=8*nsps8/nspsd !Downsample factor
+ nfft2=nfft1/ndown !Backward FFT length
+ nh2=nfft2/2
+ nf=nint(fpk)
+ i0=fpk/df1
+
+ nw=100
+ ia=max(1,nf-nw)
+ ib=min(5000,nf+nw)
+ call timer('pctile_1',0)
+ call pctile(s(ia),ib-ia+1,40,avenoise)
+ call timer('pctile_1',1)
+
+ fac=sqrt(1.0/avenoise)
+ do i=0,nfft2-1
+ j=i0+i
+ if(i.gt.nh2) j=j-nfft2
+ c2(i)=fac*c1(j)
+ enddo
+ call timer('fft_back',0)
+ call four2a(c2,nfft2,1,1,1) !FFT back to time domain
+ call timer('fft_back',1)
+ nz2=8*npts8/ndown
+
+ return
+end subroutine downsam9
diff --git a/lib/encode232.f90 b/lib/encode232.f90
new file mode 100644
index 0000000..bc904b4
--- /dev/null
+++ b/lib/encode232.f90
@@ -0,0 +1,33 @@
+subroutine encode232(dat,nsym,symbol)
+
+! Convolutional encoder for a K=32, r=1/2 code.
+
+ integer*1 dat(13) !User data, packed 8 bits per byte
+ integer*1 symbol(500) !Channel symbols, one bit per byte
+ integer*1 i1
+ include 'conv232.f90'
+
+ nstate=0
+ k=0
+ do j=1,nsym
+ do i=7,0,-1
+ i1=dat(j)
+ i4=i1
+ if (i4.lt.0) i4=i4+256
+ nstate=ior(ishft(nstate,1),iand(ishft(i4,-i),1))
+ n=iand(nstate,npoly1)
+ n=ieor(n,ishft(n,-16))
+ k=k+1
+ symbol(k)=partab(iand(ieor(n,ishft(n,-8)),255))
+ n=iand(nstate,npoly2)
+ n=ieor(n,ishft(n,-16))
+ k=k+1
+ symbol(k)=partab(iand(ieor(n,ishft(n,-8)),255))
+ if(k.ge.nsym) go to 100
+ enddo
+ enddo
+
+100 continue
+
+ return
+end subroutine encode232
diff --git a/lib/encode4.f90 b/lib/encode4.f90
new file mode 100644
index 0000000..64b9dfc
--- /dev/null
+++ b/lib/encode4.f90
@@ -0,0 +1,20 @@
+subroutine encode4(message,ncode)
+
+ parameter (MAXCALLS=7000,MAXRPT=63)
+ integer ncode(206)
+ character*22 message !Message to be generated
+ character*3 cok !' ' or 'OOO'
+ integer dgen(13)
+ integer*1 data0(13),symbol(216)
+ logical text
+
+ call chkmsg(message,cok,nspecial,flip)
+ call packmsg(message,dgen,text) !Pack 72-bit message into 12 six-bit symbols
+ call entail(dgen,data0)
+ call encode232(data0,206,symbol) !Convolutional encoding
+ call interleave24(symbol,1) !Apply JT4 interleaving
+ do i=1,206
+ ncode(i)=symbol(i)
+ enddo
+
+end subroutine encode4
diff --git a/lib/encode_rs.c b/lib/encode_rs.c
new file mode 100644
index 0000000..911bc36
--- /dev/null
+++ b/lib/encode_rs.c
@@ -0,0 +1,52 @@
+/* Reed-Solomon encoder
+ * Copyright 2002, Phil Karn, KA9Q
+ * May be used under the terms of the GNU General Public License (GPL)
+ */
+#include <string.h>
+
+#ifdef FIXED
+#include "fixed.h"
+#elif defined(BIGSYM)
+#include "int.h"
+#else
+#include "char.h"
+#endif
+
+void ENCODE_RS(
+#ifdef FIXED
+DTYPE *data, DTYPE *bb,int pad){
+#else
+void *p,DTYPE *data, DTYPE *bb){
+ struct rs *rs = (struct rs *)p;
+#endif
+ int i, j;
+ DTYPE feedback;
+
+#ifdef FIXED
+ /* Check pad parameter for validity */
+ if(pad < 0 || pad >= NN)
+ return;
+#endif
+
+ memset(bb,0,NROOTS*sizeof(DTYPE));
+
+ for(i=0;i<NN-NROOTS-PAD;i++){
+ feedback = INDEX_OF[data[i] ^ bb[0]];
+ if(feedback != A0){ /* feedback term is non-zero */
+#ifdef UNNORMALIZED
+ /* This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
+ * always be for the polynomials constructed by init_rs()
+ */
+ feedback = MODNN(NN - GENPOLY[NROOTS] + feedback);
+#endif
+ for(j=1;j<NROOTS;j++)
+ bb[j] ^= ALPHA_TO[MODNN(feedback + GENPOLY[NROOTS-j])];
+ }
+ /* Shift */
+ memmove(&bb[0],&bb[1],sizeof(DTYPE)*(NROOTS-1));
+ if(feedback != A0)
+ bb[NROOTS-1] = ALPHA_TO[MODNN(feedback + GENPOLY[0])];
+ else
+ bb[NROOTS-1] = 0;
+ }
+}
diff --git a/lib/entail.f90 b/lib/entail.f90
new file mode 100644
index 0000000..1228a75
--- /dev/null
+++ b/lib/entail.f90
@@ -0,0 +1,30 @@
+subroutine entail(dgen,data0)
+
+! Move 72-bit packed data from 6-bit to 8-bit symbols and add a zero tail.
+ integer dgen(13)
+ integer*1 data0(13)
+
+ i4=0
+ k=0
+ m=0
+ do i=1,12
+ n=dgen(i)
+ do j=1,6
+ k=k+1
+ i4=i4+i4+iand(1,ishft(n,j-6))
+ i4=iand(i4,255)
+ if(k.eq.8) then
+ m=m+1
+ if(i4.gt.127) i4=i4-256
+ data0(m)=i4
+ k=0
+ endif
+ enddo
+ enddo
+ do m=10,13
+ data0(m)=0
+ enddo
+
+ return
+end subroutine entail
+
diff --git a/lib/extract.F90 b/lib/extract.F90
new file mode 100644
index 0000000..2b580f6
--- /dev/null
+++ b/lib/extract.F90
@@ -0,0 +1,103 @@
+subroutine extract(s3,nadd,ncount,nhist,decoded,ltext,nbmkv)
+
+ real s3(64,63)
+ character decoded*22
+ integer era(51),dat4(12),indx(64)
+ integer mrsym(63),mr2sym(63),mrprob(63),mr2prob(63)
+ logical nokv,ltext
+ data nokv/.false./,nsec1/0/
+ save
+
+ nbmkv=0
+ nfail=0
+1 continue
+ call demod64a(s3,nadd,mrsym,mrprob,mr2sym,mr2prob,ntest,nlow)
+ if(ntest.lt.50 .or. nlow.gt.20) then
+ ncount=-999 !Flag bad data
+ go to 900
+ endif
+ call chkhist(mrsym,nhist,ipk)
+
+ if(nhist.ge.20) then
+ nfail=nfail+1
+ call pctile(s3,4032,50,base) ! ### or, use ave from demod64a
+ do j=1,63
+ s3(ipk,j)=base
+ enddo
+ if(nfail.gt.30) then
+ decoded=' '
+ ncount=-1
+ go to 900
+ endif
+ go to 1
+ endif
+
+ call graycode65(mrsym,63,-1)
+ call interleave63(mrsym,-1)
+ call interleave63(mrprob,-1)
+
+! Decode using Berlekamp-Massey algorithm
+ nemax=30 !Max BM erasures
+ call indexx(63,mrprob,indx)
+ do i=1,nemax
+ j=indx(i)
+ if(mrprob(j).gt.120) then
+ ne2=i-1
+ go to 2
+ endif
+ era(i)=j-1
+ enddo
+ ne2=nemax
+2 decoded=' '
+ do nerase=0,ne2,2
+ call rs_decode(mrsym,era,nerase,dat4,ncount)
+ if(ncount.ge.0) then
+ call unpackmsg(dat4,decoded)
+ if(iand(dat4(10),8).ne.0) ltext=.true.
+ nbmkv=1
+ go to 900
+ endif
+ enddo
+
+! Berlekamp-Massey algorithm failed, try Koetter-Vardy
+
+ if(nokv) go to 900
+
+ maxe=8 !Max KV errors in 12 most reliable symbols
+! xlambda=12.0
+ xlambda=7.99
+ call graycode65(mr2sym,63,-1)
+ call interleave63(mr2sym,-1)
+ call interleave63(mr2prob,-1)
+
+ nsec1=nsec1+1
+ write(22,rec=1) nsec1,xlambda,maxe,200,mrsym,mrprob,mr2sym,mr2prob
+ call flush(22)
+ call timer('kvasd ',0)
+#ifdef UNIX
+ iret=system('./kvasd -q > dev_null')
+#else
+ iret=system('kvasd -q > dev_null')
+#endif
+ call timer('kvasd ',1)
+ if(iret.ne.0) then
+ if(.not.nokv) write(*,1000)
+1000 format('Error in KV decoder, or no KV decoder present.')
+ nokv=.true.
+ go to 900
+ endif
+
+ read(22,rec=2,err=900) nsec2,ncount,dat4
+ j=nsec2 !Silence compiler warning
+ decoded=' '
+ ltext=.false.
+ if(ncount.ge.0) then
+ call unpackmsg(dat4,decoded) !Unpack the user message
+ if(iand(dat4(10),8).ne.0) ltext=.true.
+ nbmkv=2
+ endif
+
+900 continue
+
+ return
+end subroutine extract
diff --git a/lib/extract4.f90 b/lib/extract4.f90
new file mode 100644
index 0000000..0622946
--- /dev/null
+++ b/lib/extract4.f90
@@ -0,0 +1,61 @@
+subroutine extract4(sym,nadd,ncount,decoded)
+
+ real sym(207)
+ character decoded*22, submode*1
+ character*72 c72
+ integer*1 symbol(207)
+ integer*1 data1(13) !Decoded data (8-bit bytes)
+ integer data4a(9) !Decoded data (8-bit bytes)
+ integer data4(12) !Decoded data (6-bit bytes)
+ integer mettab(0:255,0:1) !Metric table
+ logical first
+ data first/.true./
+ save first,mettab
+
+ if(first) then
+ call getmet24(mode,mettab)
+ first=.false.
+ endif
+
+ do j=1,207
+ r=sym(j) + 128.
+ if(r.gt.255.0) r=255.0
+ if(r.lt.0.0) r=0.0
+ i4=nint(r)
+ if(i4.gt.127) i4=i4-256
+ symbol(j)=i4
+ enddo
+
+ nbits=72+31
+ ndelta=50
+ limit=100000
+ ncycles=0
+ ncount=-1
+ decoded=' '
+ submode=' '
+
+ call interleave24(symbol(2),-1) !Remove the interleaving
+ call fano232(symbol(2),nbits,mettab,ndelta,limit,data1,ncycles,metric,ncount)
+ nlim=ncycles/nbits
+
+ if(ncount.ge.0) then
+ do i=1,9
+ i4=data1(i)
+ if(i4.lt.0) i4=i4+256
+ data4a(i)=i4
+ enddo
+ write(c72,1100) (data4a(i),i=1,9)
+1100 format(9b8.8)
+ read(c72,1102) data4
+1102 format(12b6)
+
+ call unpackmsg(data4,decoded)
+ submode=char(ichar('A')+ich-1)
+ if(decoded(1:6).eq.'000AAA') then
+ decoded='***WRONG MODE?***'
+ ncount=-1
+ endif
+ endif
+
+ return
+end subroutine extract4
diff --git a/lib/f77_wisdom.f90 b/lib/f77_wisdom.f90
new file mode 100644
index 0000000..39bdff8
--- /dev/null
+++ b/lib/f77_wisdom.f90
@@ -0,0 +1,45 @@
+subroutine write_char(c, iunit)
+ character c
+ integer iunit
+ write(iunit,1000) c
+1000 format(a,$)
+end subroutine write_char
+
+subroutine export_wisdom_to_file(iunit)
+ integer iunit
+ external write_char
+! call dfftw_export_wisdom(write_char, iunit)
+ call sfftw_export_wisdom(write_char, iunit)
+end subroutine export_wisdom_to_file
+
+subroutine read_char(ic, iunit)
+ integer ic
+ integer iunit
+ character*256 buf
+ save buf
+ integer ibuf
+ data ibuf/257/
+ save ibuf
+ if (ibuf .lt. 257) then
+ ic = ichar(buf(ibuf:ibuf))
+ ibuf = ibuf + 1
+ return
+ endif
+ read(iunit,1000,end=10) buf
+1000 format(a256)
+ ic = ichar(buf(1:1))
+ ibuf = 2
+ return
+10 ic = -1
+ ibuf = 257
+ rewind iunit
+ return
+end subroutine read_char
+
+subroutine import_wisdom_from_file(isuccess, iunit)
+ integer isuccess
+ integer iunit
+ external read_char
+! call dfftw_import_wisdom(isuccess, read_char, iunit)
+ call sfftw_import_wisdom(isuccess, read_char, iunit)
+end subroutine import_wisdom_from_file
diff --git a/lib/fano232.f90 b/lib/fano232.f90
new file mode 100644
index 0000000..1e12950
--- /dev/null
+++ b/lib/fano232.f90
@@ -0,0 +1,140 @@
+subroutine fano232(symbol,nbits,mettab,ndelta,maxcycles,dat, &
+ ncycles,metric,ierr)
+
+! Sequential decoder for K=32, r=1/2 convolutional code using
+! the Fano algorithm. Translated from C routine for same purpose
+! written by Phil Karn, KA9Q.
+
+ parameter (MAXBITS=103)
+ parameter (MAXBYTES=(MAXBITS+7)/8)
+ integer*1 symbol(0:2*MAXBITS-1) !Soft symbols (as unsigned i*1)
+ integer*1 dat(MAXBYTES) !Decoded user data, 8 bits per byte
+ integer mettab(0:255,0:1) !Metric table
+
+! These were the "node" structure in Karn's C code:
+ integer nstate(0:MAXBITS-1) !Encoder state of next node
+ integer gamma(0:MAXBITS-1) !Cumulative metric to this node
+ integer metrics(0:3,0:MAXBITS-1) !Metrics indexed by all possible Tx syms
+ integer tm(0:1,0:MAXBITS-1) !Sorted metrics for current hypotheses
+ integer ii(0:MAXBITS-1) !Current branch being tested
+
+ logical noback
+ include 'conv232.f90' !Polynomials defined here
+
+ ntail=nbits-31
+
+! Compute all possible branch metrics for each symbol pair.
+! This is the only place we actually look at the raw input symbols
+ i4a=0
+ i4b=0
+ do np=0,nbits-1
+ j=2*np
+ i4a=symbol(j)
+ i4b=symbol(j+1)
+ if (i4a.lt.0) i4a=i4a+256
+ if (i4b.lt.0) i4b=i4b+256
+ metrics(0,np) = mettab(i4a,0) + mettab(i4b,0)
+ metrics(1,np) = mettab(i4a,0) + mettab(i4b,1)
+ metrics(2,np) = mettab(i4a,1) + mettab(i4b,0)
+ metrics(3,np) = mettab(i4a,1) + mettab(i4b,1)
+ enddo
+
+ np=0
+ nstate(np)=0
+
+ n=iand(nstate(np),npoly1) !Compute and sort branch metrics
+ n=ieor(n,ishft(n,-16)) !from the root node
+ lsym=partab(iand(ieor(n,ishft(n,-8)),255))
+ n=iand(nstate(np),npoly2)
+ n=ieor(n,ishft(n,-16))
+ lsym=lsym+lsym+partab(iand(ieor(n,ishft(n,-8)),255))
+ m0=metrics(lsym,np)
+ m1=metrics(ieor(3,lsym),np)
+ if(m0.gt.m1) then
+ tm(0,np)=m0 !0-branch has better metric
+ tm(1,np)=m1
+ else
+ tm(0,np)=m1 !1-branch is better
+ tm(1,np)=m0
+ nstate(np)=nstate(np) + 1 !Set low bit
+ endif
+
+ ii(np)=0 !Start with best branch
+ gamma(np)=0
+ nt=0
+
+ do i=1,nbits*maxcycles !Start the Fano decoder
+ ngamma=gamma(np) + tm(ii(np),np) !Look forward
+ if(ngamma.ge.nt) then
+! Node is acceptable. If first time visiting this node, tighten threshold:
+ if(gamma(np).lt.(nt+ndelta)) nt=nt + ndelta * ((ngamma-nt)/ndelta)
+ gamma(np+1)=ngamma !Move forward
+ nstate(np+1)=ishft(nstate(np),1)
+ np=np+1
+ if(np.eq.nbits-1) go to 100 !We're done!
+
+ n=iand(nstate(np),npoly1)
+ n=ieor(n,ishft(n,-16))
+ lsym=partab(iand(ieor(n,ishft(n,-8)),255))
+ n=iand(nstate(np),npoly2)
+ n=ieor(n,ishft(n,-16))
+ lsym=lsym+lsym+partab(iand(ieor(n,ishft(n,-8)),255))
+
+ if(np.ge.ntail) then
+ tm(0,np)=metrics(lsym,np) !We're in the tail, now all zeros
+ else
+ m0=metrics(lsym,np)
+ m1=metrics(ieor(3,lsym),np)
+ if(m0.gt.m1) then
+ tm(0,np)=m0 !0-branch has better metric
+ tm(1,np)=m1
+ else
+ tm(0,np)=m1 !1-branch is better
+ tm(1,np)=m0
+ nstate(np)=nstate(np) + 1 !Set low bit
+ endif
+ endif
+ ii(np)=0 !Start with best branch
+ else
+ do while(.true.)
+ noback=.false. !Threshold violated, can't go forward
+ if(np.eq.0) noback=.true.
+ if(np.gt.0) then
+ if(gamma(np-1).lt.nt) noback=.true.
+ endif
+
+ if(noback) then !Can't back up, either
+ nt=nt-ndelta !Relax threshold and look forward again
+ if(ii(np).ne.0) then
+ ii(np)=0
+ nstate(np)=ieor(nstate(np),1)
+ endif
+ exit
+ endif
+
+ np=np-1 !Back up
+ if(np.lt.ntail .and. ii(np).ne.1) then
+ ii(np)=ii(np)+1 !Search the next best branch
+ nstate(np)=ieor(nstate(np),1)
+ exit
+ endif
+ enddo
+ endif
+ enddo
+ i=nbits*maxcycles
+
+100 metric=gamma(np) !Final path metric
+ nbytes=(nbits+7)/8 !Copy decoded data to user's buffer
+ np=7
+ do j=1,nbytes-1
+ i4a=nstate(np)
+ dat(j)=i4a
+ np=np+8
+ enddo
+ dat(nbytes)=0
+ ncycles=i+1
+ ierr=0
+ if(i.ge.maxcycles*nbits) ierr=-1
+
+ return
+end subroutine fano232
diff --git a/lib/fchisq.f90 b/lib/fchisq.f90
new file mode 100644
index 0000000..1dece10
--- /dev/null
+++ b/lib/fchisq.f90
@@ -0,0 +1,41 @@
+real function fchisq(c3,npts,fsample,a)
+
+ parameter (NMAX=85*16)
+ complex c3(npts)
+ complex c4(NMAX)
+ real a(3)
+ complex z
+ data a1,a2,a3/99.,99.,99./
+ include 'jt9sync.f90'
+ save
+
+ if(a(1).ne.a1 .or. a(2).ne.a2 .or. a(3).ne.a3) then
+ a1=a(1)
+ a2=a(2)
+ a3=a(3)
+ call twkfreq(c3,c4,npts,fsample,a)
+ endif
+
+! Get sync power.
+ nspsd=16
+ sum1=0.
+ sum0=0.
+ k=-1
+ do i=1,85
+ z=0.
+ do j=1,nspsd
+ k=k+1
+ z=z+c4(k+1)
+ enddo
+ pp=real(z)**2 + aimag(z)**2
+ if(isync(i).eq.1) then
+ sum1=sum1+pp
+ else
+ sum0=sum0+pp
+ endif
+ enddo
+ sync=(sum1/16.0)/(sum0/69.0) - 1.0
+ fchisq=-sync
+
+ return
+end function fchisq
diff --git a/lib/fchisq65.f90 b/lib/fchisq65.f90
new file mode 100644
index 0000000..b91444e
--- /dev/null
+++ b/lib/fchisq65.f90
@@ -0,0 +1,68 @@
+real function fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax)
+
+ parameter (NMAX=60*12000) !Samples per 60 s
+ complex cx(npts)
+ real a(5)
+ complex w,wstep,z
+ real ss(3000)
+ complex csx(0:NMAX/8)
+ data twopi/6.283185307/a1,a2,a3/99.,99.,99./
+ save
+
+ call timer('fchisq65',0)
+ baud=11025.0/4096.0
+ nsps=nint(fsample/baud) !Samples per symbol
+ nsph=nsps/2 !Samples per half-symbol
+ ndiv=16 !Output ss() steps per symbol
+ nout=ndiv*npts/nsps
+ dtstep=1.0/(ndiv*baud) !Time per output step
+
+ if(a(1).ne.a1 .or. a(2).ne.a2 .or. a(3).ne.a3) then
+ a1=a(1)
+ a2=a(2)
+ a3=a(3)
+
+! Mix and integrate the complex signal
+ csx(0)=0.
+ w=1.0
+ x0=0.5*(npts+1)
+ s=2.0/npts
+ do i=1,npts
+ x=s*(i-x0)
+ if(mod(i,100).eq.1) then
+ p2=1.5*x*x - 0.5
+ dphi=(a(1) + x*a(2) + p2*a(3)) * (twopi/fsample)
+ wstep=cmplx(cos(dphi),sin(dphi))
+ endif
+ w=w*wstep
+ csx(i)=csx(i-1) + w*cx(i)
+ enddo
+ endif
+
+! Compute 1/2-symbol powers at 1/16-symbol steps.
+ fac=1.e-4
+
+ do i=1,nout
+ j=i*nsps/ndiv
+ k=j-nsph
+ ss(i)=0.
+ if(k.ge.1) then
+ z=csx(j)-csx(k)
+ ss(i)=fac*(real(z)**2 + aimag(z)**2)
+ endif
+ enddo
+
+ ccfmax=0.
+ call timer('ccf2 ',0)
+ call ccf2(ss,nout,nflip,ccf,lagpk)
+ call timer('ccf2 ',1)
+ if(ccf.gt.ccfmax) then
+ ccfmax=ccf
+ dtmax=lagpk*dtstep
+ endif
+ fchisq65=-ccfmax
+
+ call timer('fchisq65',1)
+
+ return
+end function fchisq65
diff --git a/lib/fftw3.f90 b/lib/fftw3.f90
new file mode 100644
index 0000000..440ccc2
--- /dev/null
+++ b/lib/fftw3.f90
@@ -0,0 +1,64 @@
+ INTEGER FFTW_R2HC
+ PARAMETER (FFTW_R2HC=0)
+ INTEGER FFTW_HC2R
+ PARAMETER (FFTW_HC2R=1)
+ INTEGER FFTW_DHT
+ PARAMETER (FFTW_DHT=2)
+ INTEGER FFTW_REDFT00
+ PARAMETER (FFTW_REDFT00=3)
+ INTEGER FFTW_REDFT01
+ PARAMETER (FFTW_REDFT01=4)
+ INTEGER FFTW_REDFT10
+ PARAMETER (FFTW_REDFT10=5)
+ INTEGER FFTW_REDFT11
+ PARAMETER (FFTW_REDFT11=6)
+ INTEGER FFTW_RODFT00
+ PARAMETER (FFTW_RODFT00=7)
+ INTEGER FFTW_RODFT01
+ PARAMETER (FFTW_RODFT01=8)
+ INTEGER FFTW_RODFT10
+ PARAMETER (FFTW_RODFT10=9)
+ INTEGER FFTW_RODFT11
+ PARAMETER (FFTW_RODFT11=10)
+ INTEGER FFTW_FORWARD
+ PARAMETER (FFTW_FORWARD=-1)
+ INTEGER FFTW_BACKWARD
+ PARAMETER (FFTW_BACKWARD=+1)
+ INTEGER FFTW_MEASURE
+ PARAMETER (FFTW_MEASURE=0)
+ INTEGER FFTW_DESTROY_INPUT
+ PARAMETER (FFTW_DESTROY_INPUT=1)
+ INTEGER FFTW_UNALIGNED
+ PARAMETER (FFTW_UNALIGNED=2)
+ INTEGER FFTW_CONSERVE_MEMORY
+ PARAMETER (FFTW_CONSERVE_MEMORY=4)
+ INTEGER FFTW_EXHAUSTIVE
+ PARAMETER (FFTW_EXHAUSTIVE=8)
+ INTEGER FFTW_PRESERVE_INPUT
+ PARAMETER (FFTW_PRESERVE_INPUT=16)
+ INTEGER FFTW_PATIENT
+ PARAMETER (FFTW_PATIENT=32)
+ INTEGER FFTW_ESTIMATE
+ PARAMETER (FFTW_ESTIMATE=64)
+ INTEGER FFTW_ESTIMATE_PATIENT
+ PARAMETER (FFTW_ESTIMATE_PATIENT=128)
+ INTEGER FFTW_BELIEVE_PCOST
+ PARAMETER (FFTW_BELIEVE_PCOST=256)
+ INTEGER FFTW_DFT_R2HC_ICKY
+ PARAMETER (FFTW_DFT_R2HC_ICKY=512)
+ INTEGER FFTW_NONTHREADED_ICKY
+ PARAMETER (FFTW_NONTHREADED_ICKY=1024)
+ INTEGER FFTW_NO_BUFFERING
+ PARAMETER (FFTW_NO_BUFFERING=2048)
+ INTEGER FFTW_NO_INDIRECT_OP
+ PARAMETER (FFTW_NO_INDIRECT_OP=4096)
+ INTEGER FFTW_ALLOW_LARGE_GENERIC
+ PARAMETER (FFTW_ALLOW_LARGE_GENERIC=8192)
+ INTEGER FFTW_NO_RANK_SPLITS
+ PARAMETER (FFTW_NO_RANK_SPLITS=16384)
+ INTEGER FFTW_NO_VRANK_SPLITS
+ PARAMETER (FFTW_NO_VRANK_SPLITS=32768)
+ INTEGER FFTW_NO_VRECURSE
+ PARAMETER (FFTW_NO_VRECURSE=65536)
+ INTEGER FFTW_NO_SIMD
+ PARAMETER (FFTW_NO_SIMD=131072)
diff --git a/lib/fil3.f90 b/lib/fil3.f90
new file mode 100644
index 0000000..0d66061
--- /dev/null
+++ b/lib/fil3.f90
@@ -0,0 +1,159 @@
+subroutine fil3(x1,n1,c2,n2)
+
+! FIR real-to-complex filter designed using ScopeFIR
+!
+!-----------------------------------------------
+! fsample (Hz) 12000 Input sample rate
+! Ntaps 113 Number of filter taps
+! fc (Hz) 500 Cutoff frequency
+! fstop (Hz) 750 Lower limit of stopband
+! Ripple (dB) 0.2 Ripple in passband
+! Stop Atten (dB) 50 Stopband attenuation
+! fmix (HZ) 1500 Mixing frequency
+! fout (Hz) 1500 Output sample rate
+
+! Resulting passband is 1000 - 2000 Hz
+
+! Suggest calling with n1 = 8*n2 + 105, where n2 is the desired number
+! of 1500 Hz output samples.
+
+ parameter (NTAPS=113)
+ parameter (NH=NTAPS/2)
+ parameter (NDOWN=8) !Downsample ratio = 1/8
+ real x1(n1)
+ complex z
+ complex c2(n1/NDOWN)
+
+! Filter coefficients:
+ complex ca(-NH:NH)
+ data ca/ &
+ (-0.001818142144, 0.000000000000), &
+ (-0.000664066641,-0.000664066640), &
+ (-0.000000000000,-0.001044063550), &
+ ( 0.000737290018,-0.000737290010), &
+ ( 0.000908957610,-0.000000000000), &
+ ( 0.000444156615, 0.000444156610), &
+ (-0.000000000000, 0.000202701460), &
+ ( 0.000244876473,-0.000244876470), &
+ ( 0.000978154552, 0.000000000000), &
+ ( 0.001155650277, 0.001155650270), &
+ ( 0.000000000000, 0.002243121590), &
+ (-0.001927618608, 0.001927618600), &
+ (-0.003006201675, 0.000000000000), &
+ (-0.002134087852,-0.002134087850), &
+ ( 0.000000000000,-0.002717699570), &
+ ( 0.001478946738,-0.001478946730), &
+ ( 0.001162489032, 0.000000000000), &
+ (-0.000005589545,-0.000005589540), &
+ (-0.000000000000,-0.001321554800), &
+ ( 0.001873767954,-0.001873767950), &
+ ( 0.003843608784,-0.000000000000), &
+ ( 0.003356874940, 0.003356874940), &
+ (-0.000000000000, 0.005218967040), &
+ (-0.003640348011, 0.003640348010), &
+ (-0.004470167307, 0.000000000000), &
+ (-0.002247131477,-0.002247131470), &
+ (-0.000000000000,-0.001335998900), &
+ (-0.000647656208, 0.000647656200), &
+ (-0.003386100636, 0.000000000000), &
+ (-0.004114456189,-0.004114456180), &
+ ( 0.000000000000,-0.007939147960), &
+ ( 0.006692816134,-0.006692816130), &
+ ( 0.010145641899, 0.000000000000), &
+ ( 0.006920770724, 0.006920770720), &
+ ( 0.000000000000, 0.008285915750), &
+ (-0.003992321524, 0.003992321520), &
+ (-0.001995842303, 0.000000000000), &
+ ( 0.001704388774, 0.001704388770), &
+ (-0.000000000000, 0.007202515550), &
+ (-0.008426458377, 0.008426458370), &
+ (-0.016028350845, 0.000000000000), &
+ (-0.013430355885,-0.013430355880), &
+ (-0.000000000000,-0.020297455950), &
+ ( 0.013791263729,-0.013791263720), &
+ ( 0.016298136197,-0.000000000000), &
+ ( 0.007443596155, 0.007443596150), &
+ (-0.000000000000, 0.002223837360), &
+ ( 0.005924356866,-0.005924356860), &
+ ( 0.020854478160, 0.000000000000), &
+ ( 0.024471928130, 0.024471928130), &
+ ( 0.000000000000, 0.048909701460), &
+ (-0.044508219241, 0.044508219240), &
+ (-0.075874892030, 0.000000000000), &
+ (-0.061450241075,-0.061450241070), &
+ ( 0.000000000000,-0.095332017640), &
+ ( 0.071148679982,-0.071148679980), &
+ ( 0.102420526192, 0.000000000000), &
+ ( 0.071148679982, 0.071148679980), &
+ ( 0.000000000000, 0.095332017640), &
+ (-0.061450241075, 0.061450241070), &
+ (-0.075874892030, 0.000000000000), &
+ (-0.044508219241,-0.044508219240), &
+ ( 0.000000000000,-0.048909701460), &
+ ( 0.024471928130,-0.024471928130), &
+ ( 0.020854478160, 0.000000000000), &
+ ( 0.005924356866, 0.005924356860), &
+ (-0.000000000000,-0.002223837360), &
+ ( 0.007443596155,-0.007443596150), &
+ ( 0.016298136197,-0.000000000000), &
+ ( 0.013791263729, 0.013791263720), &
+ (-0.000000000000, 0.020297455950), &
+ (-0.013430355885, 0.013430355880), &
+ (-0.016028350845, 0.000000000000), &
+ (-0.008426458377,-0.008426458370), &
+ (-0.000000000000,-0.007202515550), &
+ ( 0.001704388774,-0.001704388770), &
+ (-0.001995842303, 0.000000000000), &
+ (-0.003992321524,-0.003992321520), &
+ ( 0.000000000000,-0.008285915750), &
+ ( 0.006920770724,-0.006920770720), &
+ ( 0.010145641899, 0.000000000000), &
+ ( 0.006692816134, 0.006692816130), &
+ ( 0.000000000000, 0.007939147960), &
+ (-0.004114456189, 0.004114456180), &
+ (-0.003386100636, 0.000000000000), &
+ (-0.000647656208,-0.000647656200), &
+ (-0.000000000000, 0.001335998900), &
+ (-0.002247131477, 0.002247131470), &
+ (-0.004470167307, 0.000000000000), &
+ (-0.003640348011,-0.003640348010), &
+ (-0.000000000000,-0.005218967040), &
+ ( 0.003356874940,-0.003356874940), &
+ ( 0.003843608784,-0.000000000000), &
+ ( 0.001873767954, 0.001873767950), &
+ (-0.000000000000, 0.001321554800), &
+ (-0.000005589545, 0.000005589540), &
+ ( 0.001162489032, 0.000000000000), &
+ ( 0.001478946738, 0.001478946730), &
+ ( 0.000000000000, 0.002717699570), &
+ (-0.002134087852, 0.002134087850), &
+ (-0.003006201675, 0.000000000000), &
+ (-0.001927618608,-0.001927618600), &
+ ( 0.000000000000,-0.002243121590), &
+ ( 0.001155650277,-0.001155650270), &
+ ( 0.000978154552, 0.000000000000), &
+ ( 0.000244876473, 0.000244876470), &
+ (-0.000000000000,-0.000202701460), &
+ ( 0.000444156615,-0.000444156610), &
+ ( 0.000908957610,-0.000000000000), &
+ ( 0.000737290018, 0.000737290010), &
+ (-0.000000000000, 0.001044063550), &
+ (-0.000664066641, 0.000664066640), &
+ (-0.001818142144, 0.000000000000)/
+ save ca
+
+ n2=(n1-NTAPS+NDOWN)/NDOWN
+ k0=NH-NDOWN+1
+
+! Loop over all output samples
+ do i=1,n2
+ z=0.
+ k=k0 + NDOWN*i
+ do j=-NH,NH
+ z=z + x1(j+k)*ca(j)
+ enddo
+ c2(i)=z
+ enddo
+
+ return
+end subroutine fil3
diff --git a/lib/fil61.f90 b/lib/fil61.f90
new file mode 100644
index 0000000..faf62a3
--- /dev/null
+++ b/lib/fil61.f90
@@ -0,0 +1,64 @@
+12000 61 250 750 0.2 50, mix at 1500
+
+
+-0.000000000000 0.001944450121
+-0.000668730681 0.000668730681
+-0.000974850191 -0.000000000000
+-0.000581679123 -0.000581679123
+ 0.000000000000 -0.000439648787
+-0.000148911451 0.000148911451
+-0.001140891736 -0.000000000000
+-0.001653102965 -0.001653102965
+ 0.000000000000 -0.003749915818
+ 0.003740834397 -0.003740834397
+ 0.006834087490 0.000000000000
+ 0.005812808655 0.005812808655
+-0.000000000000 0.009262713933
+-0.006900370427 0.006900370427
+-0.009503248519 -0.000000000000
+-0.005874581677 -0.005874581677
+ 0.000000000000 -0.006017530719
+ 0.001785268072 -0.001785268072
+-0.002214736448 -0.000000000000
+-0.005777038427 -0.005777038427
+ 0.000000000000 -0.015228682747
+ 0.016402831440 -0.016402831440
+ 0.031806920774 0.000000000000
+ 0.028800401613 0.028800401613
+-0.000000000000 0.049589395998
+-0.041000303659 0.041000303659
+-0.065514139214 -0.000000000000
+-0.050781544715 -0.050781544715
+ 0.000000000000 -0.076562341482
+ 0.056225821996 -0.056225821996
+ 0.080516569816 0.000000000000
+ 0.056225821996 0.056225821996
+-0.000000000000 0.076562341482
+-0.050781544715 0.050781544715
+-0.065514139214 -0.000000000000
+-0.041000303659 -0.041000303659
+ 0.000000000000 -0.049589395998
+ 0.028800401613 -0.028800401613
+ 0.031806920774 0.000000000000
+ 0.016402831440 0.016402831440
+-0.000000000000 0.015228682747
+-0.005777038427 0.005777038427
+-0.002214736448 -0.000000000000
+ 0.001785268072 0.001785268072
+-0.000000000000 0.006017530719
+-0.005874581677 0.005874581677
+-0.009503248519 -0.000000000000
+-0.006900370427 -0.006900370427
+ 0.000000000000 -0.009262713933
+ 0.005812808655 -0.005812808655
+ 0.006834087490 0.000000000000
+ 0.003740834397 0.003740834397
+-0.000000000000 0.003749915818
+-0.001653102965 0.001653102965
+-0.001140891736 -0.000000000000
+-0.000148911451 -0.000148911451
+-0.000000000000 0.000439648787
+-0.000581679123 0.000581679123
+-0.000974850191 -0.000000000000
+-0.000668730681 -0.000668730681
+ 0.000000000000 -0.001944450121
diff --git a/lib/fil6521.f90 b/lib/fil6521.f90
new file mode 100644
index 0000000..6e78e63
--- /dev/null
+++ b/lib/fil6521.f90
@@ -0,0 +1,44 @@
+subroutine fil6521(c1,n1,c2,n2)
+
+! FIR lowpass filter designed using ScopeFIR
+
+! Pass #1 Pass #2
+! -----------------------------------------------
+! fsample (Hz) 1378.125 Input sample rate
+! Ntaps 21 Number of filter taps
+! fc (Hz) 40 Cutoff frequency
+! fstop (Hz) 172.266 Lower limit of stopband
+! Ripple (dB) 0.1 Ripple in passband
+! Stop Atten (dB) 38 Stopband attenuation
+! fout (Hz) 344.531 Output sample rate
+
+ parameter (NTAPS=21)
+ parameter (NH=NTAPS/2)
+ parameter (NDOWN=4) !Downsample ratio = 1/4
+ complex c1(n1)
+ complex c2(n1/NDOWN)
+
+! Filter coefficients:
+ real a(-NH:NH)
+ data a/ &
+ -0.011958606980,-0.013888627387,-0.015601306443,-0.010602249570, &
+ 0.003804023436, 0.028320058273, 0.060903935217, 0.096841904411, &
+ 0.129639871228, 0.152644580853, 0.160917511283, 0.152644580853, &
+ 0.129639871228, 0.096841904411, 0.060903935217, 0.028320058273, &
+ 0.003804023436,-0.010602249570,-0.015601306443,-0.013888627387, &
+ -0.011958606980/
+
+ n2=(n1-NTAPS+NDOWN)/NDOWN
+ k0=NH-NDOWN+1
+
+! Loop over all output samples
+ do i=1,n2
+ c2(i)=0.
+ k=k0 + NDOWN*i
+ do j=-NH,NH
+ c2(i)=c2(i) + c1(j+k)*a(j)
+ enddo
+ enddo
+
+ return
+end subroutine fil6521
diff --git a/lib/filbig.f90 b/lib/filbig.f90
new file mode 100644
index 0000000..cb59b2f
--- /dev/null
+++ b/lib/filbig.f90
@@ -0,0 +1,127 @@
+subroutine filbig(dd,npts,f0,newdat,c4a,n4,sq0)
+
+! Filter and downsample the real data in array dd(npts), sampled at 12000 Hz.
+! Output is complex, sampled at 1378.125 Hz.
+
+ parameter (NSZ=3413)
+ parameter (NFFT1=672000,NFFT2=77175)
+ parameter (NZ2=1000)
+ real*4 dd(npts) !Input data
+ complex ca(NFFT1) !FFT of input
+ complex c4a(NFFT2) !Output data
+ real*4 s(NZ2)
+ real*8 df
+ real halfpulse(8) !Impulse response of filter (one sided)
+ complex cfilt(NFFT2) !Filter (complex; imag = 0)
+ real rfilt(NFFT2) !Filter (real)
+ integer*8 plan1,plan2,plan3
+ logical first
+ include 'fftw3.f90'
+ equivalence (rfilt,cfilt)
+ data first/.true./,npatience/0/
+ data halfpulse/114.97547150,36.57879257,-20.93789101, &
+ 5.89886379,1.59355187,-2.49138308,0.60910773,-0.04248129/
+ common/refspec/dfref,ref(NSZ)
+ save
+
+ if(npts.lt.0) go to 900 !Clean up at end of program
+
+ 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(plan2,nfft2,c4a,c4a,FFTW_FORWARD,nflags)
+ call sfftw_plan_dft_1d(plan3,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 timer('FFTfilt ',0)
+ call sfftw_execute(plan3)
+ call timer('FFTfilt ',1)
+
+ base=cfilt(nfft2/2+1)
+ do i=1,nfft2
+ rfilt(i)=real(cfilt(i))-base
+ enddo
+
+ df=12000.d0/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 data in ca.
+
+ if(newdat.ne.0) then
+ nz=min(npts,nfft1)
+ ca(1:nz)=dd(1:nz)
+ ca(nz+1:)=0. !### Should change this to r2c FFT ###
+ call timer('FFTbig ',0)
+ call sfftw_execute(plan1)
+ call timer('FFTbig ',1)
+
+ do i=1,NFFT1/2 !Flatten the spectrum
+ j=nint(i*df/dfref)
+ if(j.lt.1) j=1
+ if(j.gt.NSZ) j=NSZ
+ fac=sqrt(min(30.0,1.0/ref(j)))
+ ca(i)=fac * ca(i)
+ enddo
+ 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 and apply
+ j=i0+i-1 !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 !nfft1 was nfft2
+ c4a(i)=rfilt(i)*ca(j)
+ enddo
+
+ nadd=nfft2/NZ2
+ i=0
+ do j=1,NZ2
+ s(j)=0.
+ do n=1,nadd
+ i=i+1
+ s(j)=s(j) + real(c4a(i))**2 + aimag(c4a(i))**2
+ enddo
+ enddo
+ call pctile(s,NZ2,30,sq0)
+
+! Do the short reverse transform, to go back to time domain.
+ call timer('FFTsmall',0)
+ call sfftw_execute(plan2)
+ call timer('FFTsmall',1)
+ n4=min(npts/8,nfft2)
+ return
+
+900 call sfftw_destroy_plan(plan1)
+ call sfftw_destroy_plan(plan2)
+ call sfftw_destroy_plan(plan3)
+
+ return
+end subroutine filbig
diff --git a/lib/fillcom.f90 b/lib/fillcom.f90
new file mode 100644
index 0000000..03fbb2c
--- /dev/null
+++ b/lib/fillcom.f90
@@ -0,0 +1,25 @@
+subroutine fillcom(nutc0,ndepth0,nrxfreq)
+ character*20 datetime
+ common/npar/nutc,ndiskdat,ntrperiod,nfqso,newdat,npts8,nfa,nfb,ntol, &
+ kin,nzhsym,nsave,nagain,ndepth,ntxmode,nmode,datetime
+ save
+
+ nutc=nutc0
+ ndiskdat=1
+ ntrperiod=60
+ nfqso=nrxfreq
+ newdat=1
+ npts8=74736
+ nfa=2700
+ nfb=4007
+ ntol=3
+ kin=1024
+ nzhsym=173
+ nsave=0
+ ndepth=ndepth0
+ ntxmode=9
+ nmode=9+65
+ datetime="2013-Apr-16 15:13"
+
+ return
+end subroutine fillcom
diff --git a/lib/flat1.f90 b/lib/flat1.f90
new file mode 100644
index 0000000..526ab9b
--- /dev/null
+++ b/lib/flat1.f90
@@ -0,0 +1,30 @@
+subroutine flat1(psavg,s2,nh,nsteps,nhmax,nsmax)
+
+ real psavg(nh)
+ real s2(nhmax,nsmax)
+ real x(8192),tmp(33)
+
+ nsmo=33
+ ia=nsmo/2 + 1
+ ib=nh - nsmo/2 - 1
+ do i=ia,ib
+ call pctile(psavg(i-nsmo/2),nsmo,50,x(i))
+ enddo
+ do i=1,ia-1
+ x(i)=x(ia)
+ enddo
+ do i=ib+1,nh
+ x(i)=x(ib)
+ enddo
+
+ do i=1,nh
+ psavg(i)=psavg(i)/x(i)
+ do j=1,nsteps
+ s2(i,j)=s2(i,j)/x(i)
+ enddo
+ enddo
+
+ return
+end subroutine flat1
+
+
diff --git a/lib/flat2.f90 b/lib/flat2.f90
new file mode 100644
index 0000000..cebd989
--- /dev/null
+++ b/lib/flat2.f90
@@ -0,0 +1,18 @@
+subroutine flat2(s,nz,ref)
+
+ parameter (NSMAX=6827)
+ real s(NSMAX)
+ real ref(NSMAX)
+
+ nsmo=10
+ ia=nsmo+1
+ ib=nz-nsmo-1
+ do i=ia,ib
+ call pctile(s(i-nsmo),2*nsmo+1,5,ref(i))
+ enddo
+
+ ref(:ia-1)=ref(ia)
+ ref(ib+1:)=ref(ib)
+
+ return
+end subroutine flat2
diff --git a/lib/flat65.f90 b/lib/flat65.f90
new file mode 100644
index 0000000..7aa106c
--- /dev/null
+++ b/lib/flat65.f90
@@ -0,0 +1,25 @@
+subroutine flat65(ss,nhsym,maxhsym,nsz,ref)
+
+ real stmp(nsz)
+ real ss(maxhsym,nsz)
+ real ref(nsz)
+
+ npct=28 !Somewhat arbitrary
+ do i=1,nsz
+ call pctile(ss(1,i),nhsym,npct,stmp(i))
+ enddo
+
+ nsmo=33
+ ia=nsmo/2 + 1
+ ib=nsz - nsmo/2 - 1
+ do i=ia,ib
+ call pctile(stmp(i-nsmo/2),nsmo,npct,ref(i))
+ enddo
+ ref(:ia-1)=ref(ia)
+ ref(ib+1:)=ref(ib)
+ ref=4.0*ref
+
+ return
+end subroutine flat65
+
+
diff --git a/lib/four2a.f90 b/lib/four2a.f90
new file mode 100644
index 0000000..c095629
--- /dev/null
+++ b/lib/four2a.f90
@@ -0,0 +1,90 @@
+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.
+
+ parameter (NPMAX=100)
+ parameter (NSMALL=16384)
+ complex a(nfft)
+ complex aa(NSMALL)
+ integer nn(NPMAX),ns(NPMAX),nf(NPMAX)
+ integer*8 plan(NPMAX),nl(NPMAX),nloc
+ data nplan/0/,npatience/1/
+! data nplan/0/,npatience/0/
+ include 'fftw3.f90'
+ save plan,nplan,nn,ns,nf,nl
+
+ if(nfft.lt.0) go to 999
+
+ nloc=loc(a)
+ do i=1,nplan
+ if(nfft.eq.nn(i) .and. isign.eq.ns(i) .and. &
+ iform.eq.nf(i) .and. nloc.eq.nl(i)) go to 10
+ enddo
+ if(nplan.ge.NPMAX) stop 'Too many FFTW plans requested.'
+ 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
+ do j=1,jz
+ aa(j)=a(j)
+ enddo
+ endif
+ 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
+ i=nplan
+ if(nfft.le.NSMALL) then
+ jz=nfft
+ if(iform.eq.0) jz=nfft/2
+ do j=1,jz
+ a(j)=aa(j)
+ enddo
+ endif
+
+10 continue
+ call sfftw_execute(plan(i))
+ return
+
+999 do i=1,nplan
+! The test is only to silence a compiler warning:
+ if(ndim.ne.-999) call sfftw_destroy_plan(plan(i))
+ enddo
+
+ return
+end subroutine four2a
diff --git a/lib/gen24.f90 b/lib/gen24.f90
new file mode 100644
index 0000000..e2aaa77
--- /dev/null
+++ b/lib/gen24.f90
@@ -0,0 +1,86 @@
+subroutine gen24(message,mode4,samfac,ntxdf,iwave,nwave,sendingsh,msgsent,nmsg)
+
+! Encode a JT4 message into a wavefile.
+
+ parameter (NMAX=60*11025) !Max length of wave file
+ character*22 message !Message to be generated
+ character*22 msgsent !Message as it will be received
+ character*3 cok !' ' or 'OOO'
+ real*8 t,dt,phi,f,f0,dfgen,dphi,pi,twopi,samfac,tsymbol
+ integer*2 iwave(NMAX) !Generated wave file
+ integer sendingsh
+ integer dgen(13)
+ integer*1 data0(13),symbol(216)
+ logical first
+ include 'prcom2.f'
+ data first/.true./
+ save
+
+ nsym=207 !Symbols per transmission
+ if(first) then
+ do i=1,nsym
+ pr2(i)=2*npr2(i)-1
+ enddo
+ pi=4.d0*atan(1.d0)
+ twopi=2.d0*pi
+ first=.false.
+ endif
+
+ call chkmsg(message,cok,nspecial,flip)
+ call packmsg(message,dgen) !Pack 72-bit message into 12 six-bit symbols
+ call entail(dgen,data0)
+ call unpackmsg(dgen,msgsent)
+
+ nbytes=(72+31+7)/8
+ call encode(data0,nbytes,symbol(2)) !Convolutional encoding
+ symbol(1)=0 !Reference phase
+ sendingsh=0
+ if(iand(dgen(10),8).ne.0) sendingsh=-1 !Plain text flag
+ call interleave24(symbol(2),1) !Apply JT4 interleaving
+
+! Set up necessary constants
+ tsymbol=2520.d0/11025.d0
+ dt=1.d0/(samfac*11025.d0)
+ f0=118*11025.d0/1024 + ntxdf
+ dfgen=11025.d0/2520 !4.375 Hz
+ t=0.d0
+ phi=0.d0
+ j0=0
+ ndata=(nsym*11025.d0*samfac*tsymbol)/2
+ ndata=2*ndata
+ do i=1,ndata
+ t=t+dt
+ j=int(t/tsymbol) + 1 !Symbol number, 1-207
+ if(j.ne.j0) then
+ f=f0 + (npr2(j)+2*symbol(j)-1.5) * dfgen * mode4
+ if(flip.lt.0.0) f=f0+((1-npr2(j))+2*symbol(j)-1.5)*dfgen*mode4
+ dphi=twopi*dt*f
+ j0=j
+ endif
+ phi=phi+dphi
+ iwave(i)=32767.0*sin(phi)
+ enddo
+
+ do j=1,5512 !Put another 0.5 sec of silence at end
+ i=i+1
+ iwave(i)=0
+ enddo
+ nwave=i
+
+ if(flip.lt.0.0) then
+ do i=22,1,-1
+ if(msgsent(i:i).ne.' ') goto 10
+ enddo
+10 msgsent=msgsent(1:i)//' OOO'
+ endif
+ do i=22,1,-1
+ if(msgsent(i:i).ne.' ') goto 20
+ enddo
+20 nmsg=i
+
+! write(*,3002) (symbol(i),i=1,207)
+! 3002 format(70i1)
+
+ return
+end subroutine gen24
+
diff --git a/lib/gen65.f90 b/lib/gen65.f90
new file mode 100644
index 0000000..8580238
--- /dev/null
+++ b/lib/gen65.f90
@@ -0,0 +1,65 @@
+subroutine gen65(msg0,ichk,msgsent,itone,itext)
+
+! Encodes a JT65 message to yieild itone(1:126)
+! Temporarily, does not implement EME shorthands
+
+ character*22 msg0
+ character*22 message !Message to be generated
+ character*22 msgsent !Message as it will be received
+ integer itone(126)
+! character*3 cok !' ' or 'OOO'
+ integer dgen(13)
+ integer sent(63)
+ logical text
+ integer nprc(126)
+ data nprc/1,0,0,1,1,0,0,0,1,1,1,1,1,1,0,1,0,1,0,0, &
+ 0,1,0,1,1,0,0,1,0,0,0,1,1,1,0,0,1,1,1,1, &
+ 0,1,1,0,1,1,1,1,0,0,0,1,1,0,1,0,1,0,1,1, &
+ 0,0,1,1,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,1, &
+ 1,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,0,1, &
+ 0,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,0,0,1,1, &
+ 1,1,1,1,1,1/
+ save
+
+ message=msg0
+ do i=1,22
+ if(ichar(message(i:i)).eq.0) then
+ message(i:)=' '
+ exit
+ endif
+ enddo
+
+ do i=1,22 !Strip leading blanks
+ if(message(1:1).ne.' ') exit
+ message=message(i+1:)
+ enddo
+
+ nspecial=0
+! call chkmsg(message,cok,nspecial,flip)
+ if(nspecial.eq.0) then
+ call packmsg(message,dgen,text) !Pack message into 72 bits
+ itext=0
+ if(text) itext=1
+ call unpackmsg(dgen,msgsent) !Unpack to get message sent
+ if(ichk.ne.0) go to 999 !Return if checking only
+
+ call rs_encode(dgen,sent) !Apply Reed-Solomon code
+ call interleave63(sent,1) !Apply interleaving
+ call graycode65(sent,63,1) !Apply Gray code
+ nsym=126 !Symbols per transmission
+ else
+ nsym=32
+ endif
+
+ k=0
+ do j=1,nsym
+ if(nprc(j).eq.0) then
+ k=k+1
+ itone(j)=sent(k)+2
+ else
+ itone(j)=0
+ endif
+ enddo
+
+999 return
+end subroutine gen65
diff --git a/lib/genjt9.f90 b/lib/genjt9.f90
new file mode 100644
index 0000000..90427e1
--- /dev/null
+++ b/lib/genjt9.f90
@@ -0,0 +1,58 @@
+subroutine genjt9(msg0,ichk,msgsent,i4tone,itext)
+
+! Encodes a JT9 message and returns msgsent, the message as it will
+! be decoded, and an integer array i4tone(85) of 9-FSK tone values
+! in the range 0-8.
+
+ character*22 msg0
+ character*22 message !Message to be generated
+ character*22 msgsent !Message as it will be received
+ integer*4 i4Msg6BitWords(13) !72-bit message as 6-bit words
+ integer*1 i1Msg8BitBytes(13) !72 bits and zero tail as 8-bit bytes
+ integer*1 i1EncodedBits(207) !Encoded information-carrying bits
+ integer*1 i1ScrambledBits(207) !Encoded bits after interleaving
+ integer*4 i4DataSymbols(69) !Data symbols (values 0-7)
+ integer*4 i4GrayCodedSymbols(69) !Gray-coded symbols (values 0-7)
+ integer*4 i4tone(85) !Tone #s, data and sync (values 0-8)
+ logical text
+ include 'jt9sync.f90'
+ save
+
+ message=msg0
+ do i=1,22
+ if(ichar(message(i:i)).eq.0) then
+ message(i:)=' '
+ exit
+ endif
+ enddo
+
+ do i=1,22 !Strip leading blanks
+ if(message(1:1).ne.' ') exit
+ message=message(i+1:)
+ enddo
+
+ call packmsg(message,i4Msg6BitWords,text) !Pack message into 12 6-bit bytes
+ itext=0
+ if(text) itext=1
+ call unpackmsg(i4Msg6BitWords,msgsent) !Unpack to get msgsent
+ if(ichk.ne.0) go to 999
+ call entail(i4Msg6BitWords,i1Msg8BitBytes) !Add tail, convert to 8-bit bytes
+ nsym2=206
+ call encode232(i1Msg8BitBytes,nsym2,i1EncodedBits) !Encode K=32, r=1/2
+ call interleave9(i1EncodedBits,1,i1ScrambledBits) !Interleave the bits
+ call packbits(i1ScrambledBits,nsym2,3,i4DataSymbols) !Pack 3-bits into words
+ call graycode(i4DataSymbols,69,1,i4GrayCodedSymbols) !Apply Gray code
+
+! Insert sync symbols at ntone=0 and add 1 to the data-tone numbers.
+ j=0
+ do i=1,85
+ if(isync(i).eq.1) then
+ i4tone(i)=0
+ else
+ j=j+1
+ i4tone(i)=i4GrayCodedSymbols(j)+1
+ endif
+ enddo
+
+999 return
+end subroutine genjt9
diff --git a/lib/genmet.f90 b/lib/genmet.f90
new file mode 100644
index 0000000..0682bf8
--- /dev/null
+++ b/lib/genmet.f90
@@ -0,0 +1,88 @@
+program genmet
+
+! Generate metric table for M-FSK modulation.
+
+ character*12 arg
+ real*4 r(0:255)
+ integer hist(2,-128:128)
+ data hist/514*0/,idum/-1/
+
+ lim(x)=min(127,max(-128,nint(scale*x)))
+
+ nargs=iargc()
+ if(nargs.ne.5) then
+ print*,'Usage: genmet ncoh nadd m0 snr iters'
+ go to 999
+ endif
+ call getarg(1,arg)
+ read(arg,*) ncoh
+ call getarg(2,arg)
+ read(arg,*) nadd
+ call getarg(3,arg)
+ read(arg,*) m0
+ call getarg(4,arg)
+ read(arg,*) snr
+ call getarg(5,arg)
+ read(arg,*) iters
+
+ ntones=2**m0
+ xm0=m0
+ scale=5.0
+ fac=sqrt(1.0/nadd)
+ s=sqrt(10.0**(0.1*snr))
+ hist=0
+ nerr=0
+
+ do iter=1,iters
+ do i=0,ntones-1
+ r(i)=0.
+ do n=1,nadd
+ x1=0.707*gran()
+ y1=0.707*gran()
+ if(i.eq.0) x1=x1+s
+ if(ncoh.eq.0) r(i)=r(i) + x1*x1 + y1*y1
+ if(ncoh.ne.0) r(i)=r(i) + x1
+ enddo
+ r(i)=fac*r(i)
+ enddo
+ do m=0,m0-1
+ n=2**m
+ r1=0.
+ r2=0.
+ do i=0,ntones-1
+ if(iand(i,n).ne.0) r1=max(r1,r(i))
+ if(iand(i,n).eq.0) r2=max(r2,r(i))
+ enddo
+ don=r2-r1
+ doff=r1-r2
+ if(don.lt.0.0) nerr=nerr+1
+ j1=lim(doff)
+ hist(1,j1)=hist(1,j1)+1
+ j2=lim(don)
+ hist(2,j2)=hist(2,j2)+1
+ enddo
+ enddo
+
+ do i=-128,127
+ write(13,1010) i/scale,hist(1,i)/(xm0*iters),hist(2,i)/(xm0*iters)
+1010 format(f8.3,2f12.9)
+ enddo
+
+ ber=nerr/(xm0*iters)
+ write(*,1020) nadd,m0,snr,ber
+1020 format('nadd:',i3,' m0:',i2,' snr: 'f5.1,' BER:',f8.3)
+
+ xln2=log(2.0)
+ do i=-128,127
+ p1=hist(2,i)/(xm0*iters)
+ p0=hist(1,i)/(xm0*iters)
+ if(p0+p1.eq.0.0 .and. i.lt.0) p0=1.e-6
+ if(p0+p1.eq.0.0 .and. i.gt.0) p1=1.e-6
+ xlhd0=log(max(0.001,2.0*p0/(p0+p1)))/xln2
+ xlhd1=log(max(0.001,2.0*p1/(p0+p1)))/xln2
+ write(14,1012) i/scale,xlhd0,xlhd1,p0/(p0+p1),p1/(p0+p1)
+1012 format(f7.1,2f8.3,2f9.6)
+ enddo
+
+999 end program genmet
+
diff --git a/lib/geodist.f90 b/lib/geodist.f90
new file mode 100644
index 0000000..2ca7553
--- /dev/null
+++ b/lib/geodist.f90
@@ -0,0 +1,96 @@
+subroutine geodist(Eplat,Eplon,Stlat,Stlon,Az,Baz,Dist)
+ implicit none
+ real eplat, eplon, stlat, stlon, az, baz, dist
+
+! JHT: In actual fact, I use the first two arguments for "My Location",
+! the second two for "His location"; West longitude is positive.
+
+! Taken directly from:
+! Thomas, P.D., 1970, Spheroidal geodesics, reference systems,
+! & local geometry, U.S. Naval Oceanographi!Office SP-138,
+! 165 pp.
+! assumes North Latitude and East Longitude are positive
+
+! EpLat, EpLon = End point Lat/Long
+! Stlat, Stlon = Start point lat/long
+! Az, BAz = direct & reverse azimuith
+! Dist = Dist (km); Deg = central angle, discarded
+
+ real BOA, F, P1R, P2R, L1R, L2R, DLR, T1R, T2R, TM, &
+ DTM, STM, CTM, SDTM,CDTM, KL, KK, SDLMR, L, &
+ CD, DL, SD, T, U, V, D, X, E, Y, A, FF64, TDLPM, &
+ HAPBR, HAMBR, A1M2, A2M1
+
+ real AL,BL,D2R,Pi2
+
+ data AL/6378206.4/ ! Clarke 1866 ellipsoid
+ data BL/6356583.8/
+! real pi /3.14159265359/
+ data D2R/0.01745329251994/ ! degrees to radians conversion factor
+ data Pi2/6.28318530718/
+
+ BOA = BL/AL
+ F = 1.0 - BOA
+! Convert st/end pts to radians
+ P1R = Eplat * D2R
+ P2R = Stlat * D2R
+ L1R = Eplon * D2R
+ L2R = StLon * D2R
+ DLR = L2R - L1R ! DLR = Delta Long in Rads
+ T1R = ATan(BOA * Tan(P1R))
+ T2R = ATan(BOA * Tan(P2R))
+ TM = (T1R + T2R) / 2.0
+ DTM = (T2R - T1R) / 2.0
+ STM = Sin(TM)
+ CTM = Cos(TM)
+ SDTM = Sin(DTM)
+ CDTM = Cos(DTM)
+ KL = STM * CDTM
+ KK = SDTM * CTM
+ SDLMR = Sin(DLR/2.0)
+ L = SDTM * SDTM + SDLMR * SDLMR * (CDTM * CDTM - STM * STM)
+ CD = 1.0 - 2.0 * L
+ DL = ACos(CD)
+ SD = Sin(DL)
+ T = DL/SD
+ U = 2.0 * KL * KL / (1.0 - L)
+ V = 2.0 * KK * KK / L
+ D = 4.0 * T * T
+ X = U + V
+ E = -2.0 * CD
+ Y = U - V
+ A = -D * E
+ FF64 = F * F / 64.0
+ Dist = AL*SD*(T -(F/4.0)*(T*X-Y)+FF64*(X*(A+(T-(A+E) &
+ /2.0)*X)+Y*(-2.0*D+E*Y)+D*X*Y))/1000.0
+ TDLPM = Tan((DLR+(-((E*(4.0-X)+2.0*Y)*((F/2.0)*T+FF64* &
+ (32.0*T+(A-20.0*T)*X-2.0*(D+2.0)*Y))/4.0)*Tan(DLR)))/2.0)
+ HAPBR = ATan2(SDTM,(CTM*TDLPM))
+ HAMBR = Atan2(CDTM,(STM*TDLPM))
+ A1M2 = Pi2 + HAMBR - HAPBR
+ A2M1 = Pi2 - HAMBR - HAPBR
+
+1 If ((A1M2 .ge. 0.0) .AND. (A1M2 .lt. Pi2)) GOTO 5
+ If (A1M2 .lt. Pi2) GOTO 4
+ A1M2 = A1M2 - Pi2
+ GOTO 1
+4 A1M2 = A1M2 + Pi2
+ GOTO 1
+
+! All of this gens the proper az, baz (forward and back azimuth)
+
+5 If ((A2M1 .ge. 0.0) .AND. (A2M1 .lt. Pi2)) GOTO 9
+ If (A2M1 .lt. Pi2) GOTO 8
+ A2M1 = A2M1 - Pi2
+ GOTO 5
+8 A2M1 = A2M1 + Pi2
+ GOTO 5
+
+9 Az = A1M2 / D2R
+ BAZ = A2M1 / D2R
+
+!Fix the mirrored coords here.
+
+ az = 360.0 - az
+ baz = 360.0 - baz
+end subroutine geodist
diff --git a/lib/getlags.f90 b/lib/getlags.f90
new file mode 100644
index 0000000..0d1f5d6
--- /dev/null
+++ b/lib/getlags.f90
@@ -0,0 +1,27 @@
+subroutine getlags(nsps8,lag0,lag1,lag2)
+ if(nsps8.eq.864) then
+ lag1=39
+ lag2=291
+ lag0=123
+ else if(nsps8.eq.1920) then
+ lag1=70
+ lag2=184
+ lag0=108
+ else if(nsps8.eq.5120) then
+ lag1=84
+ lag2=129
+ lag0=99
+ else if(nsps8.eq.10368) then
+ lag1=91
+ lag2=112
+ lag0=98
+ else if(nsps8.eq.31500) then
+ lag1=93
+ lag2=102
+ lag0=96
+ else
+ stop 'Error in getlags'
+ endif
+
+ return
+end subroutine getlags
diff --git a/lib/getmet24.f90 b/lib/getmet24.f90
new file mode 100644
index 0000000..f35a90a
--- /dev/null
+++ b/lib/getmet24.f90
@@ -0,0 +1,52 @@
+subroutine getmet24(mode,mettab)
+
+! Return appropriate metric table for soft-decision convolutional decoder.
+
+! Metric table (RxSymbol,TxSymbol)
+ integer mettab(0:255,0:1)
+ real*4 xx0(0:255)
+ data xx0/ &
+ 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, &
+ 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, &
+ 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, &
+ 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, &
+ 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, &
+ 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, &
+ 0.988, 1.000, 0.991, 0.993, 1.000, 0.995, 1.000, 0.991, &
+ 1.000, 0.991, 0.992, 0.991, 0.990, 0.990, 0.992, 0.996, &
+ 0.990, 0.994, 0.993, 0.991, 0.992, 0.989, 0.991, 0.987, &
+ 0.985, 0.989, 0.984, 0.983, 0.979, 0.977, 0.971, 0.975, &
+ 0.974, 0.970, 0.970, 0.970, 0.967, 0.962, 0.960, 0.957, &
+ 0.956, 0.953, 0.942, 0.946, 0.937, 0.933, 0.929, 0.920, &
+ 0.917, 0.911, 0.903, 0.895, 0.884, 0.877, 0.869, 0.858, &
+ 0.846, 0.834, 0.821, 0.806, 0.790, 0.775, 0.755, 0.737, &
+ 0.713, 0.691, 0.667, 0.640, 0.612, 0.581, 0.548, 0.510, &
+ 0.472, 0.425, 0.378, 0.328, 0.274, 0.212, 0.146, 0.075, &
+ 0.000,-0.079,-0.163,-0.249,-0.338,-0.425,-0.514,-0.606, &
+ -0.706,-0.796,-0.895,-0.987,-1.084,-1.181,-1.280,-1.376, &
+ -1.473,-1.587,-1.678,-1.790,-1.882,-1.992,-2.096,-2.201, &
+ -2.301,-2.411,-2.531,-2.608,-2.690,-2.829,-2.939,-3.058, &
+ -3.164,-3.212,-3.377,-3.463,-3.550,-3.768,-3.677,-3.975, &
+ -4.062,-4.098,-4.186,-4.261,-4.472,-4.621,-4.623,-4.608, &
+ -4.822,-4.870,-4.652,-4.954,-5.108,-5.377,-5.544,-5.995, &
+ -5.632,-5.826,-6.304,-6.002,-6.559,-6.369,-6.658,-7.016, &
+ -6.184,-7.332,-6.534,-6.152,-6.113,-6.288,-6.426,-6.313, &
+ -9.966,-6.371,-9.966,-7.055,-9.966,-6.629,-6.313,-9.966, &
+ -5.858,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966, &
+ -9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966, &
+ -9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966, &
+ -9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966, &
+ -9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966, &
+ -9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966,-9.966/
+ save
+
+ bias=0.5
+ scale=10.0
+ do i=0,255
+ mettab(i,0)=nint(scale*(xx0(i)-bias))
+ if(i.ge.1) mettab(256-i,1)=mettab(i,0)
+ enddo
+
+ return
+end subroutine getmet24
+
diff --git a/lib/getpfx1.f90 b/lib/getpfx1.f90
new file mode 100644
index 0000000..4d4e7aa
--- /dev/null
+++ b/lib/getpfx1.f90
@@ -0,0 +1,97 @@
+subroutine getpfx1(callsign,k,nv2)
+
+ character*12 callsign0,callsign,lof,rof
+ character*8 c
+ character addpfx*8,tpfx*4,tsfx*3
+ logical ispfx,issfx,invalid
+ common/pfxcom/addpfx
+ include 'pfx.f90'
+
+ callsign0=callsign
+ nv2=0
+ iz=index(callsign,' ') - 1
+ if(iz.lt.0) iz=12
+ islash=index(callsign(1:iz),'/')
+ k=0
+ if(k.eq.0) go to 10 !### Always use JT65v2 ###
+ c=' '
+ if(islash.gt.0 .and. islash.le.(iz-4)) then
+! Add-on prefix
+ c=callsign(1:islash-1)
+ callsign=callsign(islash+1:iz)
+ do i=1,NZ
+ if(pfx(i)(1:4).eq.c) then
+ k=i
+ go to 10
+ endif
+ enddo
+ if(addpfx.eq.c) then
+ k=449
+ go to 10
+ endif
+
+ else if(islash.eq.(iz-1)) then
+! Add-on suffix
+ c=callsign(islash+1:iz)
+ callsign=callsign(1:islash-1)
+ do i=1,NZ2
+ if(sfx(i).eq.c(1:1)) then
+ k=400+i
+ go to 10
+ endif
+ enddo
+ endif
+
+10 if(islash.ne.0 .and.k.eq.0) then
+! Original JT65 would force this compound callsign to be treated as
+! plain text. In JT65v2, we will encode the prefix or suffix into nc1.
+! The task here is to compute the proper value of k.
+ lof=callsign0(:islash-1)
+ rof=callsign0(islash+1:)
+ llof=len_trim(lof)
+ lrof=len_trim(rof)
+ ispfx=(llof.gt.0 .and. llof.le.4)
+ issfx=(lrof.gt.0 .and. lrof.le.3)
+ invalid=.not.(ispfx.or.issfx)
+ if(ispfx.and.issfx) then
+ if(llof.lt.3) issfx=.false.
+ if(lrof.lt.3) ispfx=.false.
+ if(ispfx.and.issfx) then
+ i=ichar(callsign0(islash-1:islash-1))
+ if(i.ge.ichar('0') .and. i.le.ichar('9')) then
+ issfx=.false.
+ else
+ ispfx=.false.
+ endif
+ endif
+ endif
+
+ if(invalid) then
+ k=-1
+ else
+ if(ispfx) then
+ tpfx=lof(1:4)
+ k=nchar(tpfx(1:1))
+ k=37*k + nchar(tpfx(2:2))
+ k=37*k + nchar(tpfx(3:3))
+ k=37*k + nchar(tpfx(4:4))
+ nv2=1
+ i=index(callsign0,'/')
+ callsign=callsign0(:i-1)
+ callsign=callsign0(i+1:)
+ endif
+ if(issfx) then
+ tsfx=rof(1:3)
+ k=nchar(tsfx(1:1))
+ k=37*k + nchar(tsfx(2:2))
+ k=37*k + nchar(tsfx(3:3))
+ nv2=2
+ i=index(callsign0,'/')
+ callsign=callsign0(:i-1)
+ endif
+ endif
+ endif
+
+ return
+end subroutine getpfx1
+
diff --git a/lib/getpfx2.f90 b/lib/getpfx2.f90
new file mode 100644
index 0000000..d747e7f
--- /dev/null
+++ b/lib/getpfx2.f90
@@ -0,0 +1,24 @@
+subroutine getpfx2(k0,callsign)
+
+ character callsign*12
+ include 'pfx.f90'
+ character addpfx*8
+ common/pfxcom/addpfx
+
+ k=k0
+ if(k.gt.450) k=k-450
+ if(k.ge.1 .and. k.le.NZ) then
+ iz=index(pfx(k),' ') - 1
+ callsign=pfx(k)(1:iz)//'/'//callsign
+ else if(k.ge.401 .and. k.le.400+NZ2) then
+ iz=index(callsign,' ') - 1
+ callsign=callsign(1:iz)//'/'//sfx(k-400)
+ else if(k.eq.449) then
+ iz=index(addpfx,' ') - 1
+ if(iz.lt.1) iz=8
+ callsign=addpfx(1:iz)//'/'//callsign
+ endif
+
+ return
+end subroutine getpfx2
+
diff --git a/lib/gran.c b/lib/gran.c
new file mode 100644
index 0000000..ceeb6da
--- /dev/null
+++ b/lib/gran.c
@@ -0,0 +1,28 @@
+#include <stdlib.h>
+#include <math.h>
+
+/* Generate gaussian random float with mean=0 and std_dev=1 */
+float gran_()
+{
+ float fac,rsq,v1,v2;
+ static float gset;
+ static int iset;
+
+ if(iset){
+ /* Already got one */
+ iset = 0;
+ return gset;
+ }
+ /* Generate two evenly distributed numbers between -1 and +1
+ * that are inside the unit circle
+ */
+ do {
+ v1 = 2.0 * (float)rand() / RAND_MAX - 1;
+ v2 = 2.0 * (float)rand() / RAND_MAX - 1;
+ rsq = v1*v1 + v2*v2;
+ } while(rsq >= 1.0 || rsq == 0.0);
+ fac = sqrt(-2.0*log(rsq)/rsq);
+ gset = v1*fac;
+ iset++;
+ return v2*fac;
+}
diff --git a/lib/graycode.f90 b/lib/graycode.f90
new file mode 100644
index 0000000..21c1f90
--- /dev/null
+++ b/lib/graycode.f90
@@ -0,0 +1,9 @@
+subroutine graycode(ia,n,idir,ib)
+
+ integer ia(n),ib(n)
+ do i=1,n
+ ib(i)=igray(ia(i),idir)
+ enddo
+
+ return
+end subroutine graycode
diff --git a/lib/graycode65.f90 b/lib/graycode65.f90
new file mode 100644
index 0000000..3ee9a42
--- /dev/null
+++ b/lib/graycode65.f90
@@ -0,0 +1,9 @@
+subroutine graycode65(dat,n,idir)
+
+ integer dat(n)
+ do i=1,n
+ dat(i)=igray(dat(i),idir)
+ enddo
+
+ return
+end subroutine graycode65
diff --git a/lib/grid2deg.f90 b/lib/grid2deg.f90
new file mode 100644
index 0000000..843fc84
--- /dev/null
+++ b/lib/grid2deg.f90
@@ -0,0 +1,38 @@
+subroutine grid2deg(grid0,dlong,dlat)
+
+! Converts Maidenhead grid locator to degrees of West longitude
+! and North latitude.
+
+ character*6 grid0,grid
+ character*1 g1,g2,g3,g4,g5,g6
+
+ grid=grid0
+ i=ichar(grid(5:5))
+ if(grid(5:5).eq.' ' .or. i.le.64 .or. i.ge.128) grid(5:6)='mm'
+
+ if(grid(1:1).ge.'a' .and. grid(1:1).le.'z') grid(1:1)= &
+ char(ichar(grid(1:1))+ichar('A')-ichar('a'))
+ if(grid(2:2).ge.'a' .and. grid(2:2).le.'z') grid(2:2)= &
+ char(ichar(grid(2:2))+ichar('A')-ichar('a'))
+ if(grid(5:5).ge.'A' .and. grid(5:5).le.'Z') grid(5:5)= &
+ char(ichar(grid(5:5))-ichar('A')+ichar('a'))
+ if(grid(6:6).ge.'A' .and. grid(6:6).le.'Z') grid(6:6)= &
+ char(ichar(grid(6:6))-ichar('A')+ichar('a'))
+
+ g1=grid(1:1)
+ g2=grid(2:2)
+ g3=grid(3:3)
+ g4=grid(4:4)
+ g5=grid(5:5)
+ g6=grid(6:6)
+
+ nlong = 180 - 20*(ichar(g1)-ichar('A'))
+ n20d = 2*(ichar(g3)-ichar('0'))
+ xminlong = 5*(ichar(g5)-ichar('a')+0.5)
+ dlong = nlong - n20d - xminlong/60.0
+ nlat = -90+10*(ichar(g2)-ichar('A')) + ichar(g4)-ichar('0')
+ xminlat = 2.5*(ichar(g6)-ichar('a')+0.5)
+ dlat = nlat + xminlat/60.0
+
+ return
+end subroutine grid2deg
diff --git a/lib/grid2k.f90 b/lib/grid2k.f90
new file mode 100644
index 0000000..f68b140
--- /dev/null
+++ b/lib/grid2k.f90
@@ -0,0 +1,12 @@
+subroutine grid2k(grid,k)
+
+ character*6 grid
+
+ call grid2deg(grid,xlong,xlat)
+ nlong=nint(xlong)
+ nlat=nint(xlat)
+ k=0
+ if(nlat.ge.85) k=5*(nlong+179)/2 + nlat-84
+
+ return
+end subroutine grid2k
diff --git a/lib/grid2n.f90 b/lib/grid2n.f90
new file mode 100644
index 0000000..d02d786
--- /dev/null
+++ b/lib/grid2n.f90
@@ -0,0 +1,10 @@
+subroutine grid2n(grid,n)
+ character*4 grid
+
+ i1=ichar(grid(1:1))-ichar('A')
+ i2=ichar(grid(3:3))-ichar('0')
+ i=10*i1 + i2
+ n=-i - 31
+
+ return
+end subroutine grid2n
diff --git a/lib/igray.c b/lib/igray.c
new file mode 100644
index 0000000..4646898
--- /dev/null
+++ b/lib/igray.c
@@ -0,0 +1,18 @@
+int igray_(int *n0, int *idir)
+{
+ int n;
+ unsigned long sh;
+ unsigned long nn;
+ n=*n0;
+
+ if(*idir>0) return (n ^ (n >> 1));
+
+ sh = 1;
+ nn = (n >> sh);
+ while (nn > 0) {
+ n ^= nn;
+ sh <<= 1;
+ nn = (n >> sh);
+ }
+ return (n);
+}
diff --git a/lib/indexx.f90 b/lib/indexx.f90
new file mode 100644
index 0000000..57c1ec0
--- /dev/null
+++ b/lib/indexx.f90
@@ -0,0 +1,19 @@
+subroutine indexx(n,arr,indx)
+
+ parameter (NMAX=3000)
+ integer indx(n)
+ real arr(n)
+ real brr(NMAX)
+ if(n.gt.NMAX) then
+ print*,'n=',n,' too big in indexx.'
+ stop
+ endif
+ do i=1,n
+ brr(i)=arr(i)
+ indx(i)=i
+ enddo
+ call ssort(brr,indx,n,2)
+
+ return
+end subroutine indexx
+
diff --git a/lib/init_rs.c b/lib/init_rs.c
new file mode 100644
index 0000000..eb27119
--- /dev/null
+++ b/lib/init_rs.c
@@ -0,0 +1,126 @@
+/* Initialize a RS codec
+ *
+ * Copyright 2002 Phil Karn, KA9Q
+ * May be used under the terms of the GNU General Public License (GPL)
+ */
+#include <stdlib.h>
+
+#ifdef CCSDS
+#include "ccsds.h"
+#elif defined(BIGSYM)
+#include "int.h"
+#else
+#include "char.h"
+#endif
+
+//#define NULL ((void *)0)
+
+void FREE_RS(void *p){
+ struct rs *rs = (struct rs *)p;
+
+ free(rs->alpha_to);
+ free(rs->index_of);
+ free(rs->genpoly);
+ free(rs);
+}
+
+/* Initialize a Reed-Solomon codec
+ * symsize = symbol size, bits (1-8)
+ * gfpoly = Field generator polynomial coefficients
+ * fcr = first root of RS code generator polynomial, index form
+ * prim = primitive element to generate polynomial roots
+ * nroots = RS code generator polynomial degree (number of roots)
+ * pad = padding bytes at front of shortened block
+ */
+void *INIT_RS(int symsize,int gfpoly,int fcr,int prim,
+ int nroots,int pad){
+ struct rs *rs;
+ int i, j, sr,root,iprim;
+
+ /* Check parameter ranges */
+ if(symsize < 0 || symsize > 8*sizeof(DTYPE))
+ return NULL; /* Need version with ints rather than chars */
+
+ if(fcr < 0 || fcr >= (1<<symsize))
+ return NULL;
+ if(prim <= 0 || prim >= (1<<symsize))
+ return NULL;
+ if(nroots < 0 || nroots >= (1<<symsize))
+ return NULL; /* Can't have more roots than symbol values! */
+ if(pad < 0 || pad >= ((1<<symsize) -1 - nroots))
+ return NULL; /* Too much padding */
+
+ rs = (struct rs *)calloc(1,sizeof(struct rs));
+ rs->mm = symsize;
+ rs->nn = (1<<symsize)-1;
+ rs->pad = pad;
+
+ rs->alpha_to = (DTYPE *)malloc(sizeof(DTYPE)*(rs->nn+1));
+ if(rs->alpha_to == NULL){
+ free(rs);
+ return NULL;
+ }
+ rs->index_of = (DTYPE *)malloc(sizeof(DTYPE)*(rs->nn+1));
+ if(rs->index_of == NULL){
+ free(rs->alpha_to);
+ free(rs);
+ return NULL;
+ }
+
+ /* Generate Galois field lookup tables */
+ rs->index_of[0] = A0; /* log(zero) = -inf */
+ rs->alpha_to[A0] = 0; /* alpha**-inf = 0 */
+ sr = 1;
+ for(i=0;i<rs->nn;i++){
+ rs->index_of[sr] = i;
+ rs->alpha_to[i] = sr;
+ sr <<= 1;
+ if(sr & (1<<symsize))
+ sr ^= gfpoly;
+ sr &= rs->nn;
+ }
+ if(sr != 1){
+ /* field generator polynomial is not primitive! */
+ free(rs->alpha_to);
+ free(rs->index_of);
+ free(rs);
+ return NULL;
+ }
+
+ /* Form RS code generator polynomial from its roots */
+ rs->genpoly = (DTYPE *)malloc(sizeof(DTYPE)*(nroots+1));
+ if(rs->genpoly == NULL){
+ free(rs->alpha_to);
+ free(rs->index_of);
+ free(rs);
+ return NULL;
+ }
+ rs->fcr = fcr;
+ rs->prim = prim;
+ rs->nroots = nroots;
+
+ /* Find prim-th root of 1, used in decoding */
+ for(iprim=1;(iprim % prim) != 0;iprim += rs->nn)
+ ;
+ rs->iprim = iprim / prim;
+
+ rs->genpoly[0] = 1;
+ for (i = 0,root=fcr*prim; i < nroots; i++,root += prim) {
+ rs->genpoly[i+1] = 1;
+
+ /* Multiply rs->genpoly[] by @**(root + x) */
+ for (j = i; j > 0; j--){
+ if (rs->genpoly[j] != 0)
+ rs->genpoly[j] = rs->genpoly[j-1] ^ rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[j]] + root)];
+ else
+ rs->genpoly[j] = rs->genpoly[j-1];
+ }
+ /* rs->genpoly[0] can never be zero */
+ rs->genpoly[0] = rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[0]] + root)];
+ }
+ /* convert rs->genpoly[] to index form for quicker encoding */
+ for (i = 0; i <= nroots; i++)
+ rs->genpoly[i] = rs->index_of[rs->genpoly[i]];
+
+ return rs;
+}
diff --git a/lib/int.h b/lib/int.h
new file mode 100644
index 0000000..056241e
--- /dev/null
+++ b/lib/int.h
@@ -0,0 +1,57 @@
+/* Include file to configure the RS codec for integer symbols
+ *
+ * Copyright 2002, Phil Karn, KA9Q
+ * May be used under the terms of the GNU General Public License (GPL)
+ */
+#define DTYPE int
+
+/* Reed-Solomon codec control block */
+struct rs {
+ int mm; /* Bits per symbol */
+ int nn; /* Symbols per block (= (1<<mm)-1) */
+ DTYPE *alpha_to; /* log lookup table */
+ DTYPE *index_of; /* Antilog lookup table */
+ DTYPE *genpoly; /* Generator polynomial */
+ int nroots; /* Number of generator roots = number of parity symbols */
+ int fcr; /* First consecutive root, index form */
+ int prim; /* Primitive element, index form */
+ int iprim; /* prim-th root of 1, index form */
+ int pad; /* Padding bytes in shortened block */
+};
+
+static int modnn(struct rs *rs,int x){
+ while (x >= rs->nn) {
+ x -= rs->nn;
+ x = (x >> rs->mm) + (x & rs->nn);
+ }
+ return x;
+}
+#define MODNN(x) modnn(rs,x)
+
+#define MM (rs->mm)
+#define NN (rs->nn)
+#define ALPHA_TO (rs->alpha_to)
+#define INDEX_OF (rs->index_of)
+#define GENPOLY (rs->genpoly)
+//#define NROOTS (rs->nroots)
+#define NROOTS (51)
+#define FCR (rs->fcr)
+#define PRIM (rs->prim)
+#define IPRIM (rs->iprim)
+#define PAD (rs->pad)
+#define A0 (NN)
+
+#define ENCODE_RS encode_rs_int
+#define DECODE_RS decode_rs_int
+#define INIT_RS init_rs_int
+#define FREE_RS free_rs_int
+
+void ENCODE_RS(void *p,DTYPE *data,DTYPE *parity);
+int DECODE_RS(void *p,DTYPE *data,int *eras_pos,int no_eras);
+void *INIT_RS(int symsize,int gfpoly,int fcr,
+ int prim,int nroots,int pad);
+void FREE_RS(void *p);
+
+
+
+
diff --git a/lib/interleave24.f90 b/lib/interleave24.f90
new file mode 100644
index 0000000..3cdd9c5
--- /dev/null
+++ b/lib/interleave24.f90
@@ -0,0 +1,43 @@
+subroutine interleave24(id,ndir)
+ integer*1 id(0:205),itmp(0:205)
+ integer j0(0:205)
+ logical first
+ data first/.true./
+ save first,j0
+
+ if(first) then
+ k=-1
+ do i=0,255
+ m=i
+ n=iand(m,1)
+ n=2*n + iand(m/2,1)
+ n=2*n + iand(m/4,1)
+ n=2*n + iand(m/8,1)
+ n=2*n + iand(m/16,1)
+ n=2*n + iand(m/32,1)
+ n=2*n + iand(m/64,1)
+ n=2*n + iand(m/128,1)
+ if(n.le.205) then
+ k=k+1
+ j0(k)=n
+ endif
+ enddo
+ first=.false.
+ endif
+
+ if(ndir.eq.1) then
+ do i=0,205
+ itmp(j0(i))=id(i)
+ enddo
+ else
+ do i=0,205
+ itmp(i)=id(j0(i))
+ enddo
+ endif
+
+ do i=0,205
+ id(i)=itmp(i)
+ enddo
+
+ return
+end subroutine interleave24
diff --git a/lib/interleave63.f90 b/lib/interleave63.f90
new file mode 100644
index 0000000..048244e
--- /dev/null
+++ b/lib/interleave63.f90
@@ -0,0 +1,25 @@
+subroutine interleave63(d1,idir)
+
+! Interleave (idir=1) or de-interleave (idir=-1) the array d1.
+
+ integer d1(0:6,0:8)
+ integer d2(0:8,0:6)
+
+ if(idir.ge.0) then
+ do i=0,6
+ do j=0,8
+ d2(j,i)=d1(i,j)
+ enddo
+ enddo
+ call move(d2,d1,63)
+ else
+ call move(d1,d2,63)
+ do i=0,6
+ do j=0,8
+ d1(i,j)=d2(j,i)
+ enddo
+ enddo
+ endif
+
+ return
+end subroutine interleave63
diff --git a/lib/interleave8.f90 b/lib/interleave8.f90
new file mode 100644
index 0000000..e13346e
--- /dev/null
+++ b/lib/interleave8.f90
@@ -0,0 +1,17 @@
+subroutine interleave8(idat,jdat)
+
+ integer idat(66),jdat(66)
+ integer ii(66),jj(66)
+ data ii/ &
+ 64,32,16,48, 8,40,24,56, 4,36,20,52,12,44,28,60, 2,66,34,18, &
+ 50,10,42,26,58, 6,38,22,54,14,46,30,62, 1,65,33,17,49, 9,41, &
+ 25,57, 5,37,21,53,13,45,29,61, 3,35,19,51,11,43,27,59, 7,39, &
+ 23,55,15,47,31,63/
+ data jj/ &
+ 34,17,51, 9,43,26,59, 5,39,22,55,13,47,30,63, 3,37,20,53,11, &
+ 45,28,61, 7,41,24,57,15,49,32,65, 2,36,19,52,10,44,27,60, 6, &
+ 40,23,56,14,48,31,64, 4,38,21,54,12,46,29,62, 8,42,25,58,16, &
+ 50,33,66, 1,35,18/
+
+ return
+end subroutine interleave8
diff --git a/lib/interleave9.f90 b/lib/interleave9.f90
new file mode 100644
index 0000000..e3026a9
--- /dev/null
+++ b/lib/interleave9.f90
@@ -0,0 +1,39 @@
+subroutine interleave9(ia,ndir,ib)
+ integer*1 ia(0:205),ib(0:205)
+ integer j0(0:205)
+ logical first
+ data first/.true./
+ save first,j0 !Save not working, or j0 overwritten ???
+
+ if(first) then
+ k=-1
+ do i=0,255
+ m=i
+ n=iand(m,1)
+ n=2*n + iand(m/2,1)
+ n=2*n + iand(m/4,1)
+ n=2*n + iand(m/8,1)
+ n=2*n + iand(m/16,1)
+ n=2*n + iand(m/32,1)
+ n=2*n + iand(m/64,1)
+ n=2*n + iand(m/128,1)
+ if(n.le.205) then
+ k=k+1
+ j0(k)=n
+ endif
+ enddo
+! first=.false.
+ endif
+
+ if(ndir.gt.0) then
+ do i=0,205
+ ib(j0(i))=ia(i)
+ enddo
+ else
+ do i=0,205
+ ib(i)=ia(j0(i))
+ enddo
+ endif
+
+ return
+end subroutine interleave9
diff --git a/lib/ipcomm.cpp b/lib/ipcomm.cpp
new file mode 100644
index 0000000..d845a60
--- /dev/null
+++ b/lib/ipcomm.cpp
@@ -0,0 +1,50 @@
+#include <QDebug>
+#include <QString>
+#include <QSharedMemory>
+#include <QSystemSemaphore>
+
+// Multiple instances: KK1D, 17 Jul 2013
+QSharedMemory mem_jt9;
+
+// Semaphore not changed, as the acquire/release calls do not
+// appear to be used anywhere.
+QSystemSemaphore sem_jt9("sem_jt9", 1, QSystemSemaphore::Open);
+
+extern "C" {
+ bool attach_jt9_();
+ bool create_jt9_(int nsize);
+ bool detach_jt9_();
+ bool lock_jt9_();
+ bool unlock_jt9_();
+ char* address_jt9_();
+ int size_jt9_();
+// Multiple instances: wrapper for QSharedMemory::setKey()
+ bool setkey_jt9_(char* mykey, int mykey_len);
+
+ bool acquire_jt9_();
+ bool release_jt9_();
+
+ extern struct {
+ char c[10];
+ } jt9com_;
+}
+
+bool attach_jt9_() {return mem_jt9.attach();}
+bool create_jt9_(int nsize) {return mem_jt9.create(nsize);}
+bool detach_jt9_() {return mem_jt9.detach();}
+bool lock_jt9_() {return mem_jt9.lock();}
+bool unlock_jt9_() {return mem_jt9.unlock();}
+char* address_jt9_() {return (char*)mem_jt9.constData();}
+int size_jt9_() {return (int)mem_jt9.size();}
+
+// Multiple instances:
+bool setkey_jt9_(char* mykey, int mykey_len) {
+ char *tempstr = (char *)calloc(mykey_len+1,1);
+ memset(tempstr, 0, mykey_len+1);
+ strncpy(tempstr, mykey, mykey_len);
+ QString s1 = QString(QLatin1String(tempstr));
+ mem_jt9.setKey(s1);
+ return true;}
+
+bool acquire_jt9_() {return sem_jt9.acquire();}
+bool release_jt9_() {return sem_jt9.release();}
diff --git a/lib/jt65.f90 b/lib/jt65.f90
new file mode 100644
index 0000000..10f7525
--- /dev/null
+++ b/lib/jt65.f90
@@ -0,0 +1,68 @@
+program jt65
+
+! Test the JT65 decoder for WSJT-X
+
+ parameter (NZMAX=60*12000)
+ integer*4 ihdr(11)
+ integer*2 id2(NZMAX)
+ real*4 dd(NZMAX)
+ character*80 infile
+ integer*2 nfmt2,nchan2,nbitsam2,nbytesam2
+ character*4 ariff,awave,afmt,adata
+ common/hdr/ariff,lenfile,awave,afmt,lenfmt,nfmt2,nchan2, &
+ nsamrate,nbytesec,nbytesam2,nbitsam2,adata,ndata
+ common/tracer/limtrace,lu
+ equivalence (lenfile,ihdr(2))
+
+ nargs=iargc()
+ if(nargs.lt.1) then
+ print*,'Usage: jt65 file1 [file2 ...]'
+ go to 999
+ endif
+ limtrace=0
+ lu=12
+
+ newdat=1
+ ntol=50
+ nfa=2700
+! nfb=4000
+ nfqso=933
+ nagain=0
+
+ open(12,file='timer.out',status='unknown')
+ open(22,file='kvasd.dat',access='direct',recl=1024,status='unknown')
+
+ call timer('jt65 ',0)
+
+ do ifile=1,nargs
+ call getarg(ifile,infile)
+ open(10,file=infile,access='stream',status='old',err=998)
+
+ call timer('read ',0)
+ read(10) ihdr
+ nutc=ihdr(1) !Silence compiler warning
+ i1=index(infile,'.wav')
+ read(infile(i1-4:i1-1),*,err=10) nutc
+ go to 20
+10 nutc=0
+20 npts=52*12000
+ read(10) id2(1:npts)
+ call timer('read ',1)
+ dd(1:npts)=id2(1:npts)
+ dd(npts+1:)=0.
+
+ call timer('jt65a ',0)
+ call jt65a(dd,npts,newdat,nutc,ntol,nfa,nfqso,nagain,ndecoded)
+ call timer('jt65a ',1)
+ enddo
+
+ call timer('jt65 ',1)
+ call timer('jt65 ',101)
+ call four2a(a,-1,1,1,1) !Free the memory used for plans
+ call filbig(a,-1,1,0.0,0,0,0,0,0) ! (ditto)
+ go to 999
+
+998 print*,'Cannot open file:'
+ print*,infile
+
+999 end program jt65
diff --git a/lib/jt65a.f90 b/lib/jt65a.f90
new file mode 100644
index 0000000..0c061ed
--- /dev/null
+++ b/lib/jt65a.f90
@@ -0,0 +1,85 @@
+subroutine jt65a(dd,npts,newdat,nutc,nfa,nfqso,ntol,nagain,ndecoded)
+
+! Process dd() data to find and decode JT65 signals.
+
+ parameter (NSZ=3413)
+ parameter (NZMAX=60*12000)
+ parameter (NFFT=8192)
+ real dd(NZMAX)
+ real*4 ss(322,NSZ)
+ real*4 savg(NSZ)
+ logical done(NSZ)
+ real a(5)
+ character decoded*22
+ save
+
+ if(newdat.ne.0) then
+ call timer('symsp65 ',0)
+ call symspec65(dd,npts,ss,nhsym,savg) !Get normalized symbol spectra
+ call timer('symsp65 ',1)
+ endif
+
+ df=12000.0/NFFT !df = 12000.0/16384 = 0.732 Hz
+ ftol=16.0 !Frequency tolerance (Hz)
+ mode65=1 !Decoding JT65A only, for now.
+ done=.false.
+ freq0=-999.
+
+ do nqd=1,0,-1
+ if(nqd.eq.1) then !Quick decode, at fQSO
+ fa=nfqso - ntol
+ fb=nfqso + ntol
+ else !Wideband decode at all freqs
+ fa=200
+ fb=nfa
+ endif
+ ia=max(51,nint(fa/df))
+ ib=min(NSZ-51,nint(fb/df))
+
+ thresh0=1.5
+
+ do i=ia,ib !Search over freq range
+ freq=i*df
+ if(savg(i).lt.thresh0 .or. done(i)) cycle
+
+ call timer('ccf65 ',0)
+ call ccf65(ss(1,i),nhsym,savg(i),sync1,dt,flipk,syncshort,snr2,dt2)
+ call timer('ccf65 ',1)
+
+ ftest=abs(freq-freq0)
+ thresh1=1.0
+ if(nqd.eq.1 .and. ntol.le.100) thresh1=0.
+ if(sync1.lt.thresh1 .or. ftest.lt.ftol) cycle
+
+ nflip=nint(flipk)
+ call timer('decod65a',0)
+ call decode65a(dd,npts,newdat,freq,nflip,mode65,sync2,a,dt, &
+ nbmkv,nhist,decoded)
+ call timer('decod65a',1)
+
+ ftest=abs(freq+a(1)-freq0)
+ if(ftest.lt.ftol) cycle
+
+ if(decoded.ne.' ') then
+ ndecoded=1
+ nfreq=nint(freq+a(1))
+ ndrift=nint(2.0*a(2))
+ s2db=10.0*log10(sync2) - 32 !### empirical (was 40) ###
+ nsnr=nint(s2db)
+ if(nsnr.lt.-30) nsnr=-30
+ if(nsnr.gt.-1) nsnr=-1
+ write(*,1010) nutc,nsnr,dt,nfreq,decoded
+1010 format(i4.4,i4,f5.1,i5,1x,'#',1x,a22)
+ write(13,1012) nutc,nint(sync1),nsnr,dt,float(nfreq),ndrift, &
+ decoded,nbmkv
+1012 format(i4.4,i4,i5,f6.1,f8.0,i4,3x,a22,' JT65',i4)
+ freq0=freq+a(1)
+ i2=min(NSZ,i+15) !### ??? ###
+ done(i:i2)=.true.
+ endif
+ enddo
+ if(nagain.eq.1) exit
+ enddo
+
+ return
+end subroutine jt65a
diff --git a/lib/jt9.f90 b/lib/jt9.f90
new file mode 100644
index 0000000..1f0a619
--- /dev/null
+++ b/lib/jt9.f90
@@ -0,0 +1,111 @@
+program jt9
+
+! Decoder for JT9. Can run stand-alone, reading data from *.wav files;
+! or as the back end of wsjt-x, with data placed in a shared memory region.
+
+ include 'constants.f90'
+ integer*4 ihdr(11)
+ real*4 s(NSMAX)
+ integer*2 id2
+ character*80 arg,infile
+ common/jt9com/ss(184,NSMAX),savg(NSMAX),id2(NMAX),nutc,ndiskdat, &
+ ntr,mousefqso,newdat,nfa,nfb,ntol,kin,nzhsym,nsynced,ndecoded
+ common/tracer/limtrace,lu
+
+ nargs=iargc()
+ if(nargs.lt.1) then
+ print*,'Usage: jt9 TRperiod ndepth rxfreq file1 [file2 ...]'
+ print*,' Reads data from *.wav files.'
+ print*,''
+ print*,' jt9 -s <key>'
+ print*,' Gets data from shared memory region with key==<key>'
+ go to 999
+ endif
+ call getarg(1,arg)
+ if(arg(1:2).eq.'-s') then
+! Multiple instances:
+ call getarg(2,arg)
+ i0=len(trim(arg))
+ call jt9a(trim(arg))
+ go to 999
+ endif
+ read(arg,*) ntrperiod
+ call getarg(2,arg)
+ read(arg,*) ndepth
+ call getarg(3,arg)
+ read(arg,*) nrxfreq
+ ifile1=4
+
+ limtrace=0
+ lu=12
+
+ do ifile=ifile1,nargs
+ call getarg(ifile,infile)
+ open(10,file=infile,access='stream',status='old',err=998)
+ read(10) ihdr
+ nutc0=ihdr(1) !Silence compiler warning
+ i1=index(infile,'.wav')
+ read(infile(i1-4:i1-1),*,err=1) nutc0
+ go to 2
+1 nutc0=0
+2 nsps=0
+ if(ntrperiod.eq.1) then
+ nsps=6912
+ nzhsym=173
+ else if(ntrperiod.eq.2) then
+ nsps=15360
+ nzhsym=178
+ else if(ntrperiod.eq.5) then
+ nsps=40960
+ nzhsym=172
+ else if(ntrperiod.eq.10) then
+ nsps=82944
+ nzhsym=171
+ else if(ntrperiod.eq.30) then
+ nsps=252000
+ nzhsym=167
+ endif
+ if(nsps.eq.0) stop 'Error: bad TRperiod'
+
+ kstep=nsps/2
+ k=0
+ nhsym0=-999
+ npts=(60*ntrperiod-6)*12000
+ if(ifile.eq.ifile1) then
+ open(12,file='timer.out',status='unknown')
+ call timer('jt9 ',0)
+ endif
+
+ id2=0 !??? Why is this necessary ???
+
+ do iblk=1,npts/kstep
+ k=iblk*kstep
+ call timer('read_wav',0)
+ read(10,end=10) id2(k-kstep+1:k)
+ call timer('read_wav',1)
+
+ nhsym=(k-2048)/kstep
+ if(nhsym.ge.1 .and. nhsym.ne.nhsym0) then
+! Emit signal readyForFFT
+ ingain=0
+ call timer('symspec ',0)
+ call symspec(k,ntrperiod,nsps,ingain,slope,pxdb,s,df3,ihsym,npts8)
+ call timer('symspec ',1)
+ nhsym0=nhsym
+ if(ihsym.ge.173) go to 10
+ endif
+ enddo
+
+10 close(10)
+ call fillcom(nutc0,ndepth,nrxfreq)
+ call decoder(ss,id2)
+ enddo
+
+ call timer('jt9 ',1)
+ call timer('jt9 ',101)
+ go to 999
+
+998 print*,'Cannot open file:'
+ print*,infile
+
+999 end program jt9
diff --git a/lib/jt9a.f90 b/lib/jt9a.f90
new file mode 100644
index 0000000..113533c
--- /dev/null
+++ b/lib/jt9a.f90
@@ -0,0 +1,72 @@
+subroutine jt9a(thekey)
+
+ character(len=*), intent(in):: thekey
+
+! These routines connect the shared memory region to the decoder.
+ interface
+ function address_jt9()
+ integer*1, pointer :: address_jt9
+ end function address_jt9
+ end interface
+
+ integer*1 attach_jt9
+! integer*1 lock_jt9,unlock_jt9
+ integer size_jt9
+ integer*1, pointer :: p_jt9
+ character*80 cwd
+! Multiple instances:
+ character*80 mykey
+ logical fileExists
+ common/tracer/limtrace,lu
+
+! Multiple instances:
+ i0 = len(trim(thekey))
+
+ call getcwd(cwd)
+ open(12,file='timer.out',status='unknown')
+
+ limtrace=0
+! limtrace=-1 !Disable all calls to timer()
+ lu=12
+
+! Multiple instances: set the shared memory key before attaching
+ mykey=trim(repeat(thekey,1))
+ i0 = len(mykey)
+ i0=setkey_jt9(trim(mykey))
+
+ i1=attach_jt9()
+
+10 inquire(file=trim(cwd)//'/.lock',exist=fileExists)
+ if(fileExists) then
+ call sleep_msec(100)
+ go to 10
+ endif
+
+ inquire(file=trim(cwd)//'/.quit',exist=fileExists)
+ if(fileExists) then
+! call ftnquit
+ i1=detach_jt9()
+ go to 999
+ endif
+ if(i1.eq.999999) stop !Silence compiler warning
+
+ nbytes=size_jt9()
+ if(nbytes.le.0) then
+ print*,'jt9a: Shared memory mem_jt9 does not exist.'
+ print*,"Must start 'jt9 -s <thekey>' from within WSJT-X."
+ go to 999
+ endif
+ p_jt9=>address_jt9()
+ call timer('jt9b ',0)
+ call jt9b(p_jt9,nbytes)
+ call timer('jt9b ',1)
+
+100 inquire(file=trim(cwd)//'/.lock',exist=fileExists)
+ if(fileExists) go to 10
+ call sleep_msec(100)
+ go to 100
+
+999 call timer('jt9b ',101)
+
+ return
+end subroutine jt9a
diff --git a/lib/jt9b.f90 b/lib/jt9b.f90
new file mode 100644
index 0000000..63de536
--- /dev/null
+++ b/lib/jt9b.f90
@@ -0,0 +1,12 @@
+subroutine jt9b(jt9com,nbytes)
+
+ include 'constants.f90'
+ integer*1 jt9com(0:nbytes-1)
+ kss=0
+ ksavg=kss + 4*184*NSMAX
+ kid2=ksavg + 4*NSMAX
+ knutc=kid2 + 2*NTMAX*12000
+ call jt9c(jt9com(kss),jt9com(ksavg),jt9com(kid2),jt9com(knutc))
+
+ return
+end subroutine jt9b
diff --git a/lib/jt9c.f90 b/lib/jt9c.f90
new file mode 100644
index 0000000..57b3cb2
--- /dev/null
+++ b/lib/jt9c.f90
@@ -0,0 +1,21 @@
+subroutine jt9c(ss,savg,id2,nparams0)
+
+ include 'constants.f90'
+ real*4 ss(184*NSMAX),savg(NSMAX)
+ integer*2 id2(NTMAX*12000)
+
+ integer nparams0(21),nparams(21)
+ character*20 datetime
+ common/npar/nutc,ndiskdat,ntrperiod,nfqso,newdat,npts8,nfa,nfb,ntol, &
+ kin,nzhsym,nsave,nagain,ndepth,ntxmode,nmode,datetime
+ equivalence (nparams,nutc)
+
+ nutc=id2(1)+int(savg(1)) !Silence compiler warning
+ nparams=nparams0 !Copy parameters into common/npar/
+
+ call flush(6)
+! if(sum(nparams).ne.0) call decoder(ss,id2)
+ call decoder(ss,id2)
+
+ return
+end subroutine jt9c
diff --git a/lib/jt9code.f90 b/lib/jt9code.f90
new file mode 100644
index 0000000..a4f0d3e
--- /dev/null
+++ b/lib/jt9code.f90
@@ -0,0 +1,29 @@
+program jt9code
+
+! Generate simulated data for testing of WSJT-X
+
+ character msg*22,msg0*22,decoded*22
+ integer*4 i4tone(85) !Channel symbols (values 0-8)
+ include 'jt9sync.f90'
+
+ nargs=iargc()
+ if(nargs.ne.1) then
+ print*,'Usage: jt9code "message"'
+ go to 999
+ endif
+
+ call getarg(1,msg0)
+ write(*,1000) msg0
+1000 format('Message:',3x,a22)
+ msg=msg0
+ ichk=0
+ itext=0
+ call genjt9(msg,ichk,decoded,i4tone,itext) !Encode message into tone #s
+ write(*,1002) i4tone
+1002 format('Channel symbols:'/(30i2))
+ if(itext.eq.0) write(*,1004) decoded
+1004 format('Decoded message:',1x,a22)
+ if(itext.ne.0) write(*,1005) decoded
+1005 format('Decoded message:',1x,a22,3x,'(free text)')
+
+999 end program jt9code
diff --git a/lib/jt9sim.f90 b/lib/jt9sim.f90
new file mode 100644
index 0000000..f4f0cf6
--- /dev/null
+++ b/lib/jt9sim.f90
@@ -0,0 +1,166 @@
+program jt9sim
+
+! Generate simulated data for testing of WSJT-X
+
+ parameter (NTMAX=120)
+ parameter (NMAX=NTMAX*12000)
+ integer ihdr(11)
+ integer*2 iwave !Generated waveform (no noise)
+ real*8 f0,f,dt,twopi,phi,dphi,baud,fspan,fsample,freq
+ character msg*22,msg0*22,message*22,msgsent*22,arg*8,fname*11
+
+ integer*4 i4tone(85) !Channel symbols (values 0-8)
+ integer*4 i4DataSymNoGray(69) !Data Symbols, values 0-7
+ integer*1 i1ScrambledBits(207) !Unpacked bits, scrambled order
+ integer*1 i1Bits(207) !Encoded information-carrying bits
+ integer*1 i1SoftSymbols(207)
+ include 'jt9sync.f90'
+ common/acom/dat(NMAX),iwave(NMAX)
+
+ nargs=iargc()
+ if(nargs.ne.6) then
+ print*,'Usage: jt9sim "message" fspan nsigs minutes SNR nfiles'
+ print*,'Example: "CQ K1ABC FN42" 200 20 2 -28 1'
+ print*,' '
+ print*,'Enter message = "" to use entries in msgs.txt.'
+ print*,'Enter SNR = 0 to generate a range of SNRs.'
+ go to 999
+ endif
+
+ call getarg(1,msg0)
+ message=msg0 !Transmitted message
+ call getarg(2,arg)
+ read(arg,*) fspan !Total freq range (Hz)
+ call getarg(3,arg)
+ read(arg,*) nsigs !Number of signals in each file
+ call getarg(4,arg)
+ read(arg,*) minutes !Length of file (1 2 5 10 30 minutes)
+ call getarg(5,arg)
+ read(arg,*) snrdb !S/N in dB (2500 hz reference BW)
+ call getarg(6,arg)
+ read(arg,*) nfiles !Number of files
+
+ rmsdb=25.
+ rms=10.0**(0.05*rmsdb)
+ fsample=12000.d0 !Sample rate (Hz)
+ dt=1.d0/fsample !Sample interval (s)
+ twopi=8.d0*atan(1.d0)
+ npts=12000*(60*minutes-6)
+ nsps=0
+ if(minutes.eq.1) nsps=6912
+ if(minutes.eq.2) nsps=15360
+ if(minutes.eq.5) nsps=40960
+ if(minutes.eq.10) nsps=82944
+ if(minutes.eq.30) nsps=252000
+ if(nsps.eq.0) stop 'Bad value for minutes.'
+
+ f0=1400.d0 !Center frequency (Hz)
+! f0=1500.0
+! if(minutes.eq.5) f0=1100.
+! if(minutes.eq.10) f0=1050.
+! if(minutes.eq.30) f0=1025.
+
+ ihdr=0 !Temporary ###
+ k=0 !Silence compiler warning
+
+ if(msg0(1:3).eq.'sin') read(msg0(4:),*) sinfreq
+
+ open(12,file='msgs.txt',status='old')
+
+ write(*,1000)
+1000 format('File N freq S/N Message'/ &
+ '---------------------------------------------------')
+
+ do ifile=1,nfiles !Loop over all files
+ nmin=(ifile-1)*minutes
+ ihr=nmin/60
+ imin=mod(nmin,60)
+ write(fname,1002) ihr,imin !Create output filename
+1002 format('000000_',2i2.2)
+ open(10,file=fname//'.wav',access='stream',status='unknown')
+
+ if(snrdb.lt.90) then
+ do i=1,npts
+ dat(i)=gran()
+ enddo
+ else
+ dat(1:npts)=0.
+ endif
+
+ if(msg0.ne.' ') then
+ call genjt9(message,msgsent,i4tone) !Encode message into tone #s
+ endif
+
+ rewind 12
+ do isig=1,nsigs !Loop over multiple signals
+
+ if(msg0.eq.' ') then
+ read(12,1004) message !Use pre-generated message texts
+1004 format(a22)
+ call genjt9(message,msgsent,i4tone)
+ endif
+
+ f=f0
+ if(nsigs.gt.1) f=f0 - 0.5d0*fspan + fspan*(isig-1.d0)/(nsigs-1.d0)
+ snrdbx=snrdb
+! snrdbx=snrdb + (ifile-1)*4.0
+ sig=10.0**(0.05*snrdbx)
+ write(*,1020) ifile,isig,f,snrdbx,msgsent
+1020 format(i3,i4,f10.3,f7.1,2x,a22)
+
+ phi=0.
+ baud=12000.d0/nsps
+ k=12000 !Start audio at t = 1.0 s
+! f1=0.0001 * (ifile-1)
+ f1=0.
+! print*,ifile-1,f1
+ dphi2=0.
+ ddphi2=twopi*f1*dt/60.0
+ do isym=1,85
+ freq=f + i4tone(isym)*baud
+ if(msg0(1:3).eq.'sin') freq=sinfreq
+ dphi=twopi*freq*dt + dphi2
+ do i=1,nsps
+ phi=phi + dphi
+ dphi2=dphi2 + ddphi2
+ if(phi.lt.-twopi) phi=phi+twopi
+ if(phi.gt.twopi) phi=phi-twopi
+ xphi=phi
+ k=k+1
+ dat(k)=dat(k) + sig*sin(xphi) !Use lookup table for i*2 sin(x) ?
+ enddo
+ enddo
+ enddo
+
+ do i=1,npts
+ iwave(i)=nint(rms*dat(i))
+ enddo
+
+ write(10) ihdr,iwave(1:npts)
+ close(10)
+
+! We're done! Now decode the data symbols from i4tone, as a test.
+ if(msg0.ne.' ') then
+ j=0
+ do i=1,85
+ if(isync(i).eq.1) cycle
+ j=j+1
+ i4DataSymNoGray(j)=igray(i4tone(i)-1,-1)
+ enddo
+ call unpackbits(i4DataSymNoGray,69,3,i1ScrambledBits)
+ call interleave9(i1ScrambledBits,-1,i1Bits)
+
+ do i=1,206
+ i4=-10
+ if(i1Bits(i).eq.1) i4=10
+ i4=i4+128
+ if(i4.le.127) i1SoftSymbols(k)=i4
+ if(i4.ge.128) i1SoftSymbols(k)=i4-256
+ enddo
+ limit=1000
+ call decode9(i1SoftSymbols,limit,nlim,msg)
+ if(msg.ne.msg0) print*,'Decode error: ',msg0,' ',msg
+ endif
+ enddo
+
+999 end program jt9sim
diff --git a/lib/jt9sync.f90 b/lib/jt9sync.f90
new file mode 100644
index 0000000..a8e3368
--- /dev/null
+++ b/lib/jt9sync.f90
@@ -0,0 +1,18 @@
+ integer ii(16) !Locations of sync symbols
+ data ii/ 1,2,5,10,16,23,33,35,51,52,55,60,66,73,83,85/
+
+ integer ii2(16) !Locations of sync half-symbols
+ data ii2/1,3,9,19,31,45,65,69,101,103,109,119,131,145,165,169/
+
+ integer ka(16),kb(16) !Reference symbols for sync
+ data ka/5,5,11,21,33,47,63,71,97,105,111,121,133,147,159,163/
+ data kb/7,7,13,23,35,49,67,73,99,107,113,123,135,149,161,167/
+
+
+ integer isync(85) !Sync vector
+ data isync/ &
+ 1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0, &
+ 0,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, &
+ 0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,1, &
+ 0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, &
+ 0,0,1,0,1/
diff --git a/lib/k2grid.f90 b/lib/k2grid.f90
new file mode 100644
index 0000000..aa76315
--- /dev/null
+++ b/lib/k2grid.f90
@@ -0,0 +1,12 @@
+subroutine k2grid(k,grid)
+ character grid*6
+
+ nlong=2*mod((k-1)/5,90)-179
+ if(k.gt.450) nlong=nlong+180
+ nlat=mod(k-1,5)+ 85
+ dlat=nlat
+ dlong=nlong
+ call deg2grid(dlong,dlat,grid)
+
+ return
+end subroutine k2grid
diff --git a/lib/libhamlib.dll.a b/lib/libhamlib.dll.a
new file mode 100644
index 0000000..7bb6d1b
Binary files /dev/null and b/lib/libhamlib.dll.a differ
diff --git a/lib/met8.21 b/lib/met8.21
new file mode 100644
index 0000000..a5d3006
--- /dev/null
+++ b/lib/met8.21
@@ -0,0 +1,256 @@
+ -25.6 1.000 -9.966 1.000000 0.000000
+ -25.4 1.000 -9.966 1.000000 0.000000
+ -25.2 1.000 -9.966 1.000000 0.000000
+ -25.0 1.000 -9.966 1.000000 0.000000
+ -24.8 1.000 -9.966 1.000000 0.000000
+ -24.6 1.000 -9.966 1.000000 0.000000
+ -24.4 1.000 -9.966 1.000000 0.000000
+ -24.2 1.000 -9.966 1.000000 0.000000
+ -24.0 1.000 -9.966 1.000000 0.000000
+ -23.8 1.000 -9.966 1.000000 0.000000
+ -23.6 1.000 -9.966 1.000000 0.000000
+ -23.4 1.000 -9.966 1.000000 0.000000
+ -23.2 1.000 -9.966 1.000000 0.000000
+ -23.0 1.000 -9.966 1.000000 0.000000
+ -22.8 1.000 -9.966 1.000000 0.000000
+ -22.6 1.000 -9.966 1.000000 0.000000
+ -22.4 1.000 -9.966 1.000000 0.000000
+ -22.2 1.000 -9.966 1.000000 0.000000
+ -22.0 1.000 -9.966 1.000000 0.000000
+ -21.8 1.000 -9.966 1.000000 0.000000
+ -21.6 1.000 -9.966 1.000000 0.000000
+ -21.4 1.000 -9.966 1.000000 0.000000
+ -21.2 1.000 -9.966 1.000000 0.000000
+ -21.0 1.000 -9.966 1.000000 0.000000
+ -20.8 1.000 -9.966 1.000000 0.000000
+ -20.6 1.000 -9.966 1.000000 0.000000
+ -20.4 1.000 -9.966 1.000000 0.000000
+ -20.2 1.000 -9.966 1.000000 0.000000
+ -20.0 1.000 -9.966 1.000000 0.000000
+ -19.8 1.000 -9.966 1.000000 0.000000
+ -19.6 1.000 -9.966 1.000000 0.000000
+ -19.4 1.000 -9.966 1.000000 0.000000
+ -19.2 1.000 -9.966 1.000000 0.000000
+ -19.0 1.000 -9.966 1.000000 0.000000
+ -18.8 1.000 -9.966 1.000000 0.000000
+ -18.6 1.000 -9.966 1.000000 0.000000
+ -18.4 1.000 -9.966 1.000000 0.000000
+ -18.2 1.000 -9.966 1.000000 0.000000
+ -18.0 1.000 -9.966 1.000000 0.000000
+ -17.8 1.000 -9.966 1.000000 0.000000
+ -17.6 1.000 -9.966 1.000000 0.000000
+ -17.4 1.000 -9.966 1.000000 0.000000
+ -17.2 1.000 -9.966 1.000000 0.000000
+ -17.0 1.000 -9.966 1.000000 0.000000
+ -16.8 1.000 -9.966 1.000000 0.000000
+ -16.6 1.000 -9.966 1.000000 0.000000
+ -16.4 1.000 -9.966 1.000000 0.000000
+ -16.2 1.000 -9.966 1.000000 0.000000
+ -16.0 0.988 -5.858 0.991379 0.008621
+ -15.8 1.000 -9.966 1.000000 0.000000
+ -15.6 0.991 -6.313 0.993711 0.006289
+ -15.4 0.993 -6.629 0.994950 0.005051
+ -15.2 1.000 -9.966 1.000000 0.000000
+ -15.0 0.995 -7.055 0.996241 0.003759
+ -14.8 1.000 -9.966 1.000000 0.000000
+ -14.6 0.991 -6.371 0.993958 0.006042
+ -14.4 1.000 -9.966 1.000000 0.000000
+ -14.2 0.991 -6.313 0.993711 0.006289
+ -14.0 0.992 -6.426 0.994186 0.005814
+ -13.8 0.991 -6.288 0.993600 0.006400
+ -13.6 0.990 -6.113 0.992775 0.007225
+ -13.4 0.990 -6.152 0.992968 0.007032
+ -13.2 0.992 -6.534 0.994606 0.005394
+ -13.0 0.996 -7.332 0.996898 0.003102
+ -12.8 0.990 -6.184 0.993121 0.006879
+ -12.6 0.994 -7.016 0.996136 0.003864
+ -12.4 0.993 -6.658 0.995049 0.004950
+ -12.2 0.991 -6.369 0.993953 0.006047
+ -12.0 0.992 -6.559 0.994699 0.005301
+ -11.8 0.989 -6.002 0.992197 0.007803
+ -11.6 0.991 -6.304 0.993671 0.006329
+ -11.4 0.987 -5.826 0.991188 0.008812
+ -11.2 0.985 -5.632 0.989919 0.010081
+ -11.0 0.989 -5.995 0.992162 0.007838
+ -10.8 0.984 -5.544 0.989284 0.010717
+ -10.6 0.983 -5.377 0.987966 0.012034
+ -10.4 0.979 -5.108 0.985502 0.014498
+ -10.2 0.977 -4.954 0.983869 0.016131
+ -10.0 0.971 -4.652 0.980118 0.019882
+ -9.8 0.975 -4.870 0.982896 0.017104
+ -9.6 0.974 -4.822 0.982324 0.017676
+ -9.4 0.970 -4.608 0.979490 0.020510
+ -9.2 0.970 -4.623 0.979702 0.020298
+ -9.0 0.970 -4.621 0.979679 0.020321
+ -8.8 0.967 -4.472 0.977465 0.022535
+ -8.6 0.962 -4.261 0.973915 0.026085
+ -8.4 0.960 -4.186 0.972538 0.027462
+ -8.2 0.957 -4.098 0.970806 0.029194
+ -8.0 0.956 -4.062 0.970061 0.029939
+ -7.8 0.953 -3.975 0.968209 0.031791
+ -7.6 0.942 -3.677 0.960918 0.039082
+ -7.4 0.946 -3.768 0.963301 0.036699
+ -7.2 0.937 -3.550 0.957308 0.042692
+ -7.0 0.933 -3.463 0.954652 0.045348
+ -6.8 0.929 -3.377 0.951866 0.048134
+ -6.6 0.920 -3.212 0.946042 0.053958
+ -6.4 0.917 -3.164 0.944202 0.055798
+ -6.2 0.911 -3.058 0.939981 0.060019
+ -6.0 0.903 -2.939 0.934818 0.065182
+ -5.8 0.895 -2.829 0.929642 0.070358
+ -5.6 0.884 -2.690 0.922540 0.077459
+ -5.4 0.877 -2.608 0.917972 0.082028
+ -5.2 0.869 -2.531 0.913509 0.086491
+ -5.0 0.858 -2.411 0.905967 0.094033
+ -4.8 0.846 -2.301 0.898525 0.101475
+ -4.6 0.834 -2.201 0.891269 0.108731
+ -4.4 0.821 -2.096 0.883085 0.116915
+ -4.2 0.806 -1.992 0.874340 0.125660
+ -4.0 0.790 -1.882 0.864307 0.135693
+ -3.8 0.775 -1.790 0.855445 0.144555
+ -3.6 0.755 -1.678 0.843726 0.156274
+ -3.4 0.737 -1.587 0.833538 0.166462
+ -3.2 0.713 -1.473 0.819841 0.180159
+ -3.0 0.691 -1.376 0.807345 0.192655
+ -2.8 0.667 -1.280 0.794093 0.205907
+ -2.6 0.640 -1.181 0.779404 0.220596
+ -2.4 0.612 -1.084 0.764178 0.235822
+ -2.2 0.581 -0.987 0.747708 0.252292
+ -2.0 0.548 -0.895 0.731037 0.268963
+ -1.8 0.510 -0.796 0.712035 0.287965
+ -1.6 0.472 -0.706 0.693474 0.306526
+ -1.4 0.425 -0.606 0.671514 0.328486
+ -1.2 0.378 -0.514 0.649948 0.350053
+ -1.0 0.328 -0.425 0.627452 0.372548
+ -0.8 0.274 -0.338 0.604549 0.395451
+ -0.6 0.212 -0.249 0.579151 0.420849
+ -0.4 0.146 -0.163 0.553389 0.446611
+ -0.2 0.075 -0.079 0.526648 0.473352
+ 0.0 0.000 0.000 0.500000 0.500000
+ 0.2 -0.079 0.075 0.473352 0.526648
+ 0.4 -0.163 0.146 0.446611 0.553389
+ 0.6 -0.249 0.212 0.420849 0.579151
+ 0.8 -0.338 0.274 0.395451 0.604549
+ 1.0 -0.425 0.328 0.372548 0.627452
+ 1.2 -0.514 0.378 0.350053 0.649948
+ 1.4 -0.606 0.425 0.328486 0.671514
+ 1.6 -0.706 0.472 0.306526 0.693474
+ 1.8 -0.796 0.510 0.287965 0.712035
+ 2.0 -0.895 0.548 0.268963 0.731037
+ 2.2 -0.987 0.581 0.252292 0.747708
+ 2.4 -1.084 0.612 0.235822 0.764178
+ 2.6 -1.181 0.640 0.220596 0.779404
+ 2.8 -1.280 0.667 0.205907 0.794093
+ 3.0 -1.376 0.691 0.192655 0.807345
+ 3.2 -1.473 0.713 0.180159 0.819841
+ 3.4 -1.587 0.737 0.166462 0.833538
+ 3.6 -1.678 0.755 0.156274 0.843726
+ 3.8 -1.790 0.775 0.144555 0.855445
+ 4.0 -1.882 0.790 0.135693 0.864307
+ 4.2 -1.992 0.806 0.125660 0.874340
+ 4.4 -2.096 0.821 0.116915 0.883085
+ 4.6 -2.201 0.834 0.108731 0.891269
+ 4.8 -2.301 0.846 0.101475 0.898525
+ 5.0 -2.411 0.858 0.094033 0.905967
+ 5.2 -2.531 0.869 0.086491 0.913509
+ 5.4 -2.608 0.877 0.082028 0.917972
+ 5.6 -2.690 0.884 0.077459 0.922540
+ 5.8 -2.829 0.895 0.070358 0.929642
+ 6.0 -2.939 0.903 0.065182 0.934818
+ 6.2 -3.058 0.911 0.060019 0.939981
+ 6.4 -3.164 0.917 0.055798 0.944202
+ 6.6 -3.212 0.920 0.053958 0.946042
+ 6.8 -3.377 0.929 0.048134 0.951866
+ 7.0 -3.463 0.933 0.045348 0.954652
+ 7.2 -3.550 0.937 0.042692 0.957308
+ 7.4 -3.768 0.946 0.036699 0.963301
+ 7.6 -3.677 0.942 0.039082 0.960918
+ 7.8 -3.975 0.953 0.031791 0.968210
+ 8.0 -4.062 0.956 0.029939 0.970061
+ 8.2 -4.098 0.957 0.029194 0.970806
+ 8.4 -4.186 0.960 0.027462 0.972538
+ 8.6 -4.261 0.962 0.026085 0.973915
+ 8.8 -4.472 0.967 0.022535 0.977465
+ 9.0 -4.621 0.970 0.020321 0.979679
+ 9.2 -4.623 0.970 0.020298 0.979702
+ 9.4 -4.608 0.970 0.020510 0.979490
+ 9.6 -4.822 0.974 0.017676 0.982324
+ 9.8 -4.870 0.975 0.017104 0.982896
+ 10.0 -4.652 0.971 0.019882 0.980118
+ 10.2 -4.954 0.977 0.016131 0.983869
+ 10.4 -5.108 0.979 0.014498 0.985502
+ 10.6 -5.377 0.983 0.012034 0.987966
+ 10.8 -5.544 0.984 0.010717 0.989284
+ 11.0 -5.995 0.989 0.007838 0.992162
+ 11.2 -5.632 0.985 0.010081 0.989919
+ 11.4 -5.826 0.987 0.008812 0.991188
+ 11.6 -6.304 0.991 0.006329 0.993671
+ 11.8 -6.002 0.989 0.007803 0.992197
+ 12.0 -6.559 0.992 0.005301 0.994699
+ 12.2 -6.369 0.991 0.006047 0.993953
+ 12.4 -6.658 0.993 0.004950 0.995049
+ 12.6 -7.016 0.994 0.003864 0.996136
+ 12.8 -6.184 0.990 0.006879 0.993121
+ 13.0 -7.332 0.996 0.003102 0.996898
+ 13.2 -6.534 0.992 0.005394 0.994606
+ 13.4 -6.152 0.990 0.007032 0.992968
+ 13.6 -6.113 0.990 0.007225 0.992775
+ 13.8 -6.288 0.991 0.006400 0.993600
+ 14.0 -6.426 0.992 0.005814 0.994186
+ 14.2 -6.313 0.991 0.006289 0.993711
+ 14.4 -9.966 1.000 0.000000 1.000000
+ 14.6 -6.371 0.991 0.006042 0.993958
+ 14.8 -9.966 1.000 0.000000 1.000000
+ 15.0 -7.055 0.995 0.003759 0.996241
+ 15.2 -9.966 1.000 0.000000 1.000000
+ 15.4 -6.629 0.993 0.005051 0.994949
+ 15.6 -6.313 0.991 0.006289 0.993711
+ 15.8 -9.966 1.000 0.000000 1.000000
+ 16.0 -5.858 0.988 0.008621 0.991379
+ 16.2 -9.966 1.000 0.000000 1.000000
+ 16.4 -9.966 1.000 0.000000 1.000000
+ 16.6 -9.966 1.000 0.000000 1.000000
+ 16.8 -9.966 1.000 0.000000 1.000000
+ 17.0 -9.966 1.000 0.000000 1.000000
+ 17.2 -9.966 1.000 0.000000 1.000000
+ 17.4 -9.966 1.000 0.000000 1.000000
+ 17.6 -9.966 1.000 0.000000 1.000000
+ 17.8 -9.966 1.000 0.000000 1.000000
+ 18.0 -9.966 1.000 0.000000 1.000000
+ 18.2 -9.966 1.000 0.000000 1.000000
+ 18.4 -9.966 1.000 0.000000 1.000000
+ 18.6 -9.966 1.000 0.000000 1.000000
+ 18.8 -9.966 1.000 0.000000 1.000000
+ 19.0 -9.966 1.000 0.000000 1.000000
+ 19.2 -9.966 1.000 0.000000 1.000000
+ 19.4 -9.966 1.000 0.000000 1.000000
+ 19.6 -9.966 1.000 0.000000 1.000000
+ 19.8 -9.966 1.000 0.000000 1.000000
+ 20.0 -9.966 1.000 0.000000 1.000000
+ 20.2 -9.966 1.000 0.000000 1.000000
+ 20.4 -9.966 1.000 0.000000 1.000000
+ 20.6 -9.966 1.000 0.000000 1.000000
+ 20.8 -9.966 1.000 0.000000 1.000000
+ 21.0 -9.966 1.000 0.000000 1.000000
+ 21.2 -9.966 1.000 0.000000 1.000000
+ 21.4 -9.966 1.000 0.000000 1.000000
+ 21.6 -9.966 1.000 0.000000 1.000000
+ 21.8 -9.966 1.000 0.000000 1.000000
+ 22.0 -9.966 1.000 0.000000 1.000000
+ 22.2 -9.966 1.000 0.000000 1.000000
+ 22.4 -9.966 1.000 0.000000 1.000000
+ 22.6 -9.966 1.000 0.000000 1.000000
+ 22.8 -9.966 1.000 0.000000 1.000000
+ 23.0 -9.966 1.000 0.000000 1.000000
+ 23.2 -9.966 1.000 0.000000 1.000000
+ 23.4 -9.966 1.000 0.000000 1.000000
+ 23.6 -9.966 1.000 0.000000 1.000000
+ 23.8 -9.966 1.000 0.000000 1.000000
+ 24.0 -9.966 1.000 0.000000 1.000000
+ 24.2 -9.966 1.000 0.000000 1.000000
+ 24.4 -9.966 1.000 0.000000 1.000000
+ 24.6 -9.966 1.000 0.000000 1.000000
+ 24.8 -9.966 1.000 0.000000 1.000000
+ 25.0 -9.966 1.000 0.000000 1.000000
+ 25.2 -9.966 1.000 0.000000 1.000000
+ 25.4 -9.966 1.000 0.000000 1.000000
diff --git a/lib/morse.f90 b/lib/morse.f90
new file mode 100644
index 0000000..de5f7a1
--- /dev/null
+++ b/lib/morse.f90
@@ -0,0 +1,86 @@
+subroutine morse(msg,idat,n)
+
+! Convert ascii message to a Morse code bit string.
+! Dash = 3 dots
+! Space between dots, dashes = 1 dot
+! Space between letters = 3 dots
+! Space between words = 7 dots
+
+ character*(*) msg
+ integer idat(250)
+ integer*1 ic(21,38)
+ data ic/ &
+ 1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,20, &
+ 1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,0,0,18, &
+ 1,0,1,0,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,16, &
+ 1,0,1,0,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,14, &
+ 1,0,1,0,1,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,12, &
+ 1,0,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,10, &
+ 1,1,1,0,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,12, &
+ 1,1,1,0,1,1,1,0,1,0,1,0,1,0,0,0,0,0,0,0,14, &
+ 1,1,1,0,1,1,1,0,1,1,1,0,1,0,1,0,0,0,0,0,16, &
+ 1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,0,0,0,18, &
+ 1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 6, &
+ 1,1,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,10, &
+ 1,1,1,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,12, &
+ 1,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, 8, &
+ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 2, &
+ 1,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,10, &
+ 1,1,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,10, &
+ 1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, 8, &
+ 1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 4, &
+ 1,0,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,14, &
+ 1,1,1,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,10, &
+ 1,0,1,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,10, &
+ 1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, 8, &
+ 1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 6, &
+ 1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,12, &
+ 1,0,1,1,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,12, &
+ 1,1,1,0,1,1,1,0,1,0,1,1,1,0,0,0,0,0,0,0,14, &
+ 1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, 8, &
+ 1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 6, &
+ 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 4, &
+ 1,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, 8, &
+ 1,0,1,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,10, &
+ 1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,10, &
+ 1,1,1,0,1,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,12, &
+ 1,1,1,0,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,14, &
+ 1,1,1,0,1,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,12, &
+ 1,1,1,0,1,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0,14, &
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 2/ !Incremental word space
+ save
+
+ msglen=len(msg)
+ idat=0
+ n=6
+ do k=1,msglen
+ jj=ichar(msg(k:k))
+ if(jj.ge.97 .and. jj.le.122) jj=jj-32 !Convert lower to upper case
+ if(jj.ge.48 .and. jj.le.57) j=jj-48 !Numbers
+ if(jj.ge.65 .and. jj.le.90) j=jj-55 !Letters
+ if(jj.eq.47) j=36 !Slash (/)
+ if(jj.eq.32) j=37 !Word space
+ j=j+1
+
+! Insert this character
+ nmax=ic(21,j)
+ do i=1,nmax
+ n=n+1
+ idat(n)=ic(i,j)
+ enddo
+
+! Insert character space of 2 dit lengths:
+ n=n+1
+ idat(n)=0
+ n=n+1
+ idat(n)=0
+ enddo
+
+! Insert word space at end of message
+ do j=1,4
+ n=n+1
+ idat(n)=0
+ enddo
+
+ return
+end subroutine morse
diff --git a/lib/move.f90 b/lib/move.f90
new file mode 100644
index 0000000..13783dc
--- /dev/null
+++ b/lib/move.f90
@@ -0,0 +1,7 @@
+subroutine move(x,y,n)
+ real x(n),y(n)
+ do i=1,n
+ y(i)=x(i)
+ enddo
+ return
+end subroutine move
diff --git a/lib/msgs.txt b/lib/msgs.txt
new file mode 100644
index 0000000..c38aba9
--- /dev/null
+++ b/lib/msgs.txt
@@ -0,0 +1,60 @@
+W1AAA K2BBB EM00
+W2CCC K3DDD EM01
+W3EEE K4FFF EM02
+W5GGG K6HHH EM03
+W7III K8JJJ EM04
+W9KKK K0LLL EM05
+G0MMM F1NNN JN06
+G2OOO F3PPP JN07
+G4QQQ F5RRR JN08
+G6SSS F7TTT JN09
+W1XAA K2XBB EM10
+W2XCC K3XDD EM11
+W3XEE K4XFF EM12
+W5XGG K6XHH EM13
+W7XII K8XJJ EM14
+W9XKK K0XLL EM15
+G0XMM F1XNN JN16
+G2XOO F3XPP JN17
+G4XQQ F5XRR JN18
+G6XSS F7XTT JN19
+W1YAA K2YBB EM20
+W2YCC K3YDD EM21
+W3YEE K4YFF EM22
+W5YGG K6YHH EM23
+W7YII K8YJJ EM24
+W9YKK K0YLL EM25
+G0YMM F1YNN JN26
+G2YOO F3YPP JN27
+G4YQQ F5YRR JN28
+G6YSS F7YTT JN29
+W1ZAA K2ZBB EM30
+W2ZCC K3ZDD EM31
+W3ZEE K4ZFF EM32
+W5ZGG K6ZHH EM33
+W7ZII K8ZJJ EM34
+W9ZKK K0ZLL EM35
+G0ZMM F1ZNN JN36
+G2ZOO F3ZPP JN37
+G4ZQQ F5ZRR JN38
+G6ZSS F7ZTT JN39
+W1AXA K2BXB EM40
+W2CXC K3DXD EM41
+W3EXE K4FXF EM42
+W5GXG K6HXH EM43
+W7IXI K8JXJ EM44
+W9KXK K0LXL EM45
+G0MXM F1NXN JN46
+G2OXO F3PXP JN47
+G4QXQ F5RXR JN48
+G6SXS F7TXT JN49
+W1AYA K2BYB EM50
+W2CYC K3DYD EM51
+W3EYE K4FYF EM52
+W5GYG K6HYH EM53
+W7IYI K8JYJ EM54
+W9KYK K0LYL EM55
+G0MYM F1NYN JN56
+G2OYO F3PYP JN57
+G4QYQ F5RYR JN58
+G6SYS F7TYT JN59
diff --git a/lib/n2grid.f90 b/lib/n2grid.f90
new file mode 100644
index 0000000..ed22a7d
--- /dev/null
+++ b/lib/n2grid.f90
@@ -0,0 +1,14 @@
+subroutine n2grid(n,grid)
+ character*4 grid
+
+ if(n.gt.-31 .or. n.lt.-70) stop 'Error in n2grid'
+ i=-(n+31) !NB: 0 <= i <= 39
+ i1=i/10
+ i2=mod(i,10)
+ grid(1:1)=char(ichar('A')+i1)
+ grid(2:2)='A'
+ grid(3:3)=char(ichar('0')+i2)
+ grid(4:4)='0'
+
+ return
+end subroutine n2grid
diff --git a/lib/nchar.f90 b/lib/nchar.f90
new file mode 100644
index 0000000..167992a
--- /dev/null
+++ b/lib/nchar.f90
@@ -0,0 +1,23 @@
+function nchar(c)
+
+! Convert ascii number, letter, or space to 0-36 for callsign packing.
+
+ character c*1
+
+ n=0 !Silence compiler warning
+ if(c.ge.'0' .and. c.le.'9') then
+ n=ichar(c)-ichar('0')
+ else if(c.ge.'A' .and. c.le.'Z') then
+ n=ichar(c)-ichar('A') + 10
+ else if(c.ge.'a' .and. c.le.'z') then
+ n=ichar(c)-ichar('a') + 10
+ else if(c.ge.' ') then
+ n=36
+ else
+ Print*,'Invalid character in callsign ',c,' ',ichar(c)
+ stop
+ endif
+ nchar=n
+
+ return
+end function nchar
diff --git a/lib/noisegen.f90 b/lib/noisegen.f90
new file mode 100644
index 0000000..f92a9df
--- /dev/null
+++ b/lib/noisegen.f90
@@ -0,0 +1,13 @@
+subroutine noisegen(d4,nmax)
+
+ real*4 d4(4,nmax)
+
+ do i=1,nmax
+ d4(1,i)=gran()
+ d4(2,i)=gran()
+ d4(3,i)=gran()
+ d4(4,i)=gran()
+ enddo
+
+ return
+end subroutine noisegen
diff --git a/lib/packbits.f90 b/lib/packbits.f90
new file mode 100644
index 0000000..8885186
--- /dev/null
+++ b/lib/packbits.f90
@@ -0,0 +1,21 @@
+subroutine packbits(dbits,nsymd,m0,sym)
+
+! Pack 0s and 1s from dbits() into sym() with m0 bits per word.
+! NB: nsymd is the number of packed output words.
+
+ integer sym(nsymd)
+ integer*1 dbits(*)
+
+ k=0
+ do i=1,nsymd
+ n=0
+ do j=1,m0
+ k=k+1
+ m=dbits(k)
+ n=ior(ishft(n,1),m)
+ enddo
+ sym(i)=n
+ enddo
+
+ return
+end subroutine packbits
diff --git a/lib/packcall.f90 b/lib/packcall.f90
new file mode 100644
index 0000000..c4de474
--- /dev/null
+++ b/lib/packcall.f90
@@ -0,0 +1,79 @@
+subroutine packcall(callsign,ncall,text)
+
+! Pack a valid callsign into a 28-bit integer.
+
+ parameter (NBASE=37*36*10*27*27*27)
+ character callsign*6,c*1,tmp*6
+ logical text
+
+ text=.false.
+
+! Work-around for Swaziland prefix:
+ if(callsign(1:4).eq.'3DA0') callsign='3D0'//callsign(5:6)
+
+ if(callsign(1:3).eq.'CQ ') then
+ ncall=NBASE + 1
+ if(callsign(4:4).ge.'0' .and. callsign(4:4).le.'9' .and. &
+ callsign(5:5).ge.'0' .and. callsign(5:5).le.'9' .and. &
+ callsign(6:6).ge.'0' .and. callsign(6:6).le.'9') then
+ read(callsign(4:6),*) nfreq
+ ncall=NBASE + 3 + nfreq
+ endif
+ return
+ else if(callsign(1:4).eq.'QRZ ') then
+ ncall=NBASE + 2
+ return
+ else if(callsign(1:3).eq.'DE ') then
+ ncall=267796945
+ return
+ endif
+
+ tmp=' '
+ if(callsign(3:3).ge.'0' .and. callsign(3:3).le.'9') then
+ tmp=callsign
+ else if(callsign(2:2).ge.'0' .and. callsign(2:2).le.'9') then
+ if(callsign(6:6).ne.' ') then
+ text=.true.
+ return
+ endif
+ tmp=' '//callsign(:5)
+ else
+ text=.true.
+ return
+ endif
+
+ do i=1,6
+ c=tmp(i:i)
+ if(c.ge.'a' .and. c.le.'z') &
+ tmp(i:i)=char(ichar(c)-ichar('a')+ichar('A'))
+ enddo
+
+ n1=0
+ if((tmp(1:1).ge.'A'.and.tmp(1:1).le.'Z').or.tmp(1:1).eq.' ') n1=1
+ if(tmp(1:1).ge.'0' .and. tmp(1:1).le.'9') n1=1
+ n2=0
+ if(tmp(2:2).ge.'A' .and. tmp(2:2).le.'Z') n2=1
+ if(tmp(2:2).ge.'0' .and. tmp(2:2).le.'9') n2=1
+ n3=0
+ if(tmp(3:3).ge.'0' .and. tmp(3:3).le.'9') n3=1
+ n4=0
+ if((tmp(4:4).ge.'A'.and.tmp(4:4).le.'Z').or.tmp(4:4).eq.' ') n4=1
+ n5=0
+ if((tmp(5:5).ge.'A'.and.tmp(5:5).le.'Z').or.tmp(5:5).eq.' ') n5=1
+ n6=0
+ if((tmp(6:6).ge.'A'.and.tmp(6:6).le.'Z').or.tmp(6:6).eq.' ') n6=1
+
+ if(n1+n2+n3+n4+n5+n6 .ne. 6) then
+ text=.true.
+ return
+ endif
+
+ ncall=nchar(tmp(1:1))
+ ncall=36*ncall+nchar(tmp(2:2))
+ ncall=10*ncall+nchar(tmp(3:3))
+ ncall=27*ncall+nchar(tmp(4:4))-10
+ ncall=27*ncall+nchar(tmp(5:5))-10
+ ncall=27*ncall+nchar(tmp(6:6))-10
+
+ return
+end subroutine packcall
diff --git a/lib/packdxcc.f90 b/lib/packdxcc.f90
new file mode 100644
index 0000000..74f2789
--- /dev/null
+++ b/lib/packdxcc.f90
@@ -0,0 +1,64 @@
+subroutine packdxcc(c,ng,ldxcc)
+
+ character*3 c
+ logical ldxcc
+
+ parameter (NZ=303)
+ character*5 pfx(NZ)
+ data pfx/ &
+ '1A ','1S ','3A ','3B6 ','3B8 ','3B9 ','3C ','3C0 ', &
+ '3D2 ', '3DA ','3V ','3W ','3X ','3Y ', &
+ '4J ','4L ','4S ','4U1 ', '4W ', &
+ '4X ','5A ','5B ','5H ','5N ','5R ','5T ','5U ', &
+ '5V ','5W ','5X ','5Z ','6W ','6Y ','7O ','7P ', &
+ '7Q ','7X ','8P ','8Q ','8R ','9A ','9G ','9H ', &
+ '9J ','9K ','9L ','9M2 ','9M6 ','9N ','9Q ','9U ', &
+ '9V ','9X ','9Y ','A2 ','A3 ','A4 ','A5 ','A6 ', &
+ 'A7 ','A9 ','AP ','BS7 ','BV ','BV9 ','BY ','C2 ', &
+ 'C3 ','C5 ','C6 ','C9 ','CE ','CE0 ', &
+ 'CE9 ','CM ','CN ','CP ','CT ','CT3 ','CU ','CX ', &
+ 'CY0 ','CY9 ','D2 ','D4 ','D6 ','DL ','DU ','E3 ', &
+ 'E4 ','EA ','EA6 ','EA8 ','EA9 ','EI ','EK ','EL ', &
+ 'EP ','ER ','ES ','ET ','EU ','EX ','EY ','EZ ', &
+ 'F ','FG ','FH ','FJ ','FK ', 'FM ','FO ', &
+ 'FP ','FR ', &
+ 'FT5 ', 'FW ','FY ','M ','MD ','MI ', &
+ 'MJ ','MM ', 'MU ','MW ','H4 ','H40 ','HA ', &
+ 'HB ','HB0 ','HC ','HC8 ','HH ','HI ','HK ','HK0 ', &
+ 'HL ','HM ','HP ','HR ','HS ','HV ','HZ ', &
+ 'I ','IG9 ','IS ','IT9 ','J2 ','J3 ','J5 ','J6 ', &
+ 'J7 ','J8 ','JA ','JD ', 'JT ','JW ', &
+ 'JX ','JY ','K ','KG4 ','KH0 ','KH1 ','KH2 ','KH3 ', &
+ 'KH4 ','KH5 ', 'KH6 ','KH7 ','KH8 ','KH9 ','KL ', &
+ 'KP1 ','KP2 ','KP4 ','KP5 ','LA ','LU ','LX ','LY ', &
+ 'LZ ','OA ','OD ','OE ','OH ','OH0 ','OJ0 ','OK ', &
+ 'OM ','ON ','OX ','OY ','OZ ','P2 ','P4 ','PA ', &
+ 'PJ2 ','PJ7 ','PY ','PY0 ', 'PZ ','R1F ', &
+ 'R1M ','S0 ','S2 ','S5 ','S7 ','S9 ','SM ','SP ', &
+ 'ST ','SU ','SV ', 'SV5 ','SV9 ','T2 ','T30 ', &
+ 'T31 ','T32 ','T33 ','T5 ','T7 ','T8 ','T9 ','TA ', &
+ 'TA1 ','TF ','TG ','TI ','TI9 ','TJ ','TK ','TL ', &
+ 'TN ','TR ','TT ','TU ','TY ','TZ ','UA ','UA2 ', &
+ 'UA9 ','UK ','UN ','UR ','V2 ','V3 ','V4 ','V5 ', &
+ 'V6 ','V7 ','V8 ','VE ','VK ','VK0 ', 'VK9 ', &
+ 'VP2 ', &
+ 'VP5 ','VP6 ', 'VP8 ', &
+ 'VP9 ','VQ9 ','VR ','VU ','VU4 ','VU7 ','XE ','XF4 ', &
+ 'XT ','XU ','XW ','XX9 ','XZ ','YA ','YB ','YI ', &
+ 'YJ ','YK ','YL ','YN ','YO ','YS ','YU ','YV ', &
+ 'YV0 ','Z2 ','Z3 ','ZA ','ZB ','ZC4 ','ZD7 ','ZD8 ', &
+ 'ZD9 ','ZF ','ZK1 ', 'ZK2 ','ZK3 ','ZL ','ZL7 ', &
+ 'ZL8 ','ZL9 ','ZP ','ZS ','ZS8 '/
+
+ ldxcc=.false.
+ ng=0
+ do i=1,NZ
+ if(pfx(i)(1:3).eq.c) go to 10
+ enddo
+ go to 20
+
+10 ng=180*180+61+i
+ ldxcc=.true.
+
+20 return
+end subroutine packdxcc
diff --git a/lib/packgrid.f90 b/lib/packgrid.f90
new file mode 100644
index 0000000..1cdb731
--- /dev/null
+++ b/lib/packgrid.f90
@@ -0,0 +1,76 @@
+subroutine packgrid(grid,ng,text)
+
+ parameter (NGBASE=180*180)
+ character*4 grid
+ character*1 c1
+ logical text
+
+ text=.false.
+ if(grid.eq.' ') go to 90 !Blank grid is OK
+
+! First, handle signal reports in the original range, -01 to -30 dB
+ if(grid(1:1).eq.'-') then
+ read(grid(2:3),*,err=800,end=800) n
+ if(n.ge.1 .and. n.le.30) then
+ ng=NGBASE+1+n
+ go to 900
+ endif
+ go to 10
+ else if(grid(1:2).eq.'R-') then
+ read(grid(3:4),*,err=800,end=800) n
+ if(n.ge.1 .and. n.le.30) then
+ ng=NGBASE+31+n
+ go to 900
+ endif
+ go to 10
+! Now check for RO, RRR, or 73 in the message field normally used for grid
+ else if(grid(1:4).eq.'RO ') then
+ ng=NGBASE+62
+ go to 900
+ else if(grid(1:4).eq.'RRR ') then
+ ng=NGBASE+63
+ go to 900
+ else if(grid(1:4).eq.'73 ') then
+ ng=NGBASE+64
+ go to 900
+ endif
+
+! Now check for extended-range signal reports: -50 to -31, and 0 to +49.
+10 n=99
+ c1=grid(1:1)
+ read(grid,*,err=20,end=20) n
+ go to 30
+20 read(grid(2:4),*,err=30,end=30) n
+30 if(n.ge.-50 .and. n.le.49) then
+ if(c1.eq.'R') then
+ write(grid,1002) n+50
+1002 format('LA',i2.2)
+ else
+ write(grid,1003) n+50
+1003 format('KA',i2.2)
+ endif
+ go to 40
+ endif
+
+! Maybe it's free text ?
+ if(grid(1:1).lt.'A' .or. grid(1:1).gt.'R') text=.true.
+ if(grid(2:2).lt.'A' .or. grid(2:2).gt.'R') text=.true.
+ if(grid(3:3).lt.'0' .or. grid(3:3).gt.'9') text=.true.
+ if(grid(4:4).lt.'0' .or. grid(4:4).gt.'9') text=.true.
+ if(text) go to 900
+
+! OK, we have a properly formatted grid locator
+40 call grid2deg(grid//'mm',dlong,dlat)
+ long=int(dlong)
+ lat=int(dlat+ 90.0)
+ ng=((long+180)/2)*180 + lat
+ go to 900
+
+90 ng=NGBASE + 1
+ go to 900
+
+800 text=.true.
+900 continue
+
+ return
+end subroutine packgrid
diff --git a/lib/packmsg.f90 b/lib/packmsg.f90
new file mode 100644
index 0000000..6c7619b
--- /dev/null
+++ b/lib/packmsg.f90
@@ -0,0 +1,113 @@
+subroutine packmsg(msg,dat,text)
+
+ parameter (NBASE=37*36*10*27*27*27)
+ parameter (NBASE2=262178562)
+ character*22 msg
+ integer dat(12)
+ character*12 c1,c2
+ character*4 c3
+ character*6 grid6
+ logical text1,text2,text3,text
+
+ text=.false.
+! Convert all letters to upper case
+ iz=22
+ do i=1,22
+ if(msg(i:i).ge.'a' .and. msg(i:i).le.'z') &
+ msg(i:i)= char(ichar(msg(i:i))+ichar('A')-ichar('a'))
+ if(msg(i:i).ne.' ') iz=i
+ enddo
+ do iter=1,5 !Collapse multiple blanks into one
+ ib2=index(msg(1:iz),' ')
+ if(ib2.lt.1) go to 5
+ msg=msg(1:ib2)//msg(ib2+2:)
+ iz=iz-1
+ enddo
+
+5 if(msg(1:6).eq.'CQ DX ') msg(3:3)='9'
+
+! See if it's a CQ message
+ if(msg(1:3).eq.'CQ ') then
+ i=3
+! ... and if so, does it have a reply frequency?
+ if(msg(4:4).ge.'0' .and. msg(4:4).le.'9' .and. &
+ msg(5:5).ge.'0' .and. msg(5:5).le.'9' .and. &
+ msg(6:6).ge.'0' .and. msg(6:6).le.'9') i=7
+ go to 1
+ endif
+
+ do i=1,22
+ if(msg(i:i).eq.' ') go to 1 !Get 1st blank
+ enddo
+ go to 10 !Consider msg as plain text
+
+1 ia=i
+ c1=msg(1:ia-1)
+ do i=ia+1,22
+ if(msg(i:i).eq.' ') go to 2 !Get 2nd blank
+ enddo
+ go to 10 !Consider msg as plain text
+
+2 ib=i
+ c2=msg(ia+1:ib-1)
+
+ do i=ib+1,22
+ if(msg(i:i).eq.' ') go to 3 !Get 3rd blank
+ enddo
+ go to 10 !Consider msg as plain text
+
+3 ic=i
+ c3=' '
+ if(ic.ge.ib+1) c3=msg(ib+1:ic)
+ if(c3.eq.'OOO ') c3=' ' !Strip out the OOO flag
+ call getpfx1(c1,k1,junk)
+ call packcall(c1,nc1,text1)
+ call getpfx1(c2,k2,nv2)
+ call packcall(c2,nc2,text2)
+ if(nv2.eq.0) then
+ if(k1.lt.0 .or. k2.lt.0 .or. k1*k2.ne.0) go to 10
+ if(k2.gt.0) k2=k2+450
+ k=max(k1,k2)
+ if(k.gt.0) then
+ call k2grid(k,grid6)
+ c3=grid6(:4)
+ endif
+ endif
+ call packgrid(c3,ng,text3)
+ if(nv2.eq.0 .and. (.not.text1) .and. (.not.text2) .and. &
+ (.not.text3)) go to 20
+ if(nv2.gt.0) then
+ if(nv2.eq.1) then
+ if(c1(1:3).eq.'CQ ') nc1=262178563 + k2
+ if(c1(1:4).eq.'QRZ ') nc1=264002072 + k2
+ if(c1(1:3).eq.'DE ') nc1=265825581 + k2
+ endif
+ if(nv2.eq.2) then
+ if(c1(1:3).eq.'CQ ') nc1=267649090 + k2
+ if(c1(1:4).eq.'QRZ ') nc1=267698375 + k2
+ if(c1(1:3).eq.'DE ') nc1=267747660 + k2
+ endif
+ go to 20
+ endif
+
+! The message will be treated as plain text.
+10 text=.true.
+ call packtext(msg,nc1,nc2,ng)
+ ng=ng+32768
+
+! Encode data into 6-bit words
+20 dat(1)=iand(ishft(nc1,-22),63) !6 bits
+ dat(2)=iand(ishft(nc1,-16),63) !6 bits
+ dat(3)=iand(ishft(nc1,-10),63) !6 bits
+ dat(4)=iand(ishft(nc1, -4),63) !6 bits
+ dat(5)=4*iand(nc1,15)+iand(ishft(nc2,-26),3) !4+2 bits
+ dat(6)=iand(ishft(nc2,-20),63) !6 bits
+ dat(7)=iand(ishft(nc2,-14),63) !6 bits
+ dat(8)=iand(ishft(nc2, -8),63) !6 bits
+ dat(9)=iand(ishft(nc2, -2),63) !6 bits
+ dat(10)=16*iand(nc2,3)+iand(ishft(ng,-12),15) !2+4 bits
+ dat(11)=iand(ishft(ng,-6),63)
+ dat(12)=iand(ng,63)
+
+ return
+end subroutine packmsg
diff --git a/lib/packtext.f90 b/lib/packtext.f90
new file mode 100644
index 0000000..10f3488
--- /dev/null
+++ b/lib/packtext.f90
@@ -0,0 +1,47 @@
+subroutine packtext(msg,nc1,nc2,nc3)
+
+ parameter (MASK28=2**28 - 1)
+ character*13 msg
+ character*42 c
+ data c/'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ +-./?'/
+
+ nc1=0
+ nc2=0
+ nc3=0
+
+ do i=1,5 !First 5 characters in nc1
+ do j=1,42 !Get character code
+ if(msg(i:i).eq.c(j:j)) go to 10
+ enddo
+ j=37
+10 j=j-1 !Codes should start at zero
+ nc1=42*nc1 + j
+ enddo
+
+ do i=6,10 !Characters 6-10 in nc2
+ do j=1,42 !Get character code
+ if(msg(i:i).eq.c(j:j)) go to 20
+ enddo
+ j=37
+20 j=j-1 !Codes should start at zero
+ nc2=42*nc2 + j
+ enddo
+
+ do i=11,13 !Characters 11-13 in nc3
+ do j=1,42 !Get character code
+ if(msg(i:i).eq.c(j:j)) go to 30
+ enddo
+ j=37
+30 j=j-1 !Codes should start at zero
+ nc3=42*nc3 + j
+ enddo
+
+! We now have used 17 bits in nc3. Must move one each to nc1 and nc2.
+ nc1=nc1+nc1
+ if(iand(nc3,32768).ne.0) nc1=nc1+1
+ nc2=nc2+nc2
+ if(iand(nc3,65536).ne.0) nc2=nc2+1
+ nc3=iand(nc3,32767)
+
+ return
+end subroutine packtext
diff --git a/lib/pctile.f90 b/lib/pctile.f90
new file mode 100644
index 0000000..35ee3a7
--- /dev/null
+++ b/lib/pctile.f90
@@ -0,0 +1,22 @@
+subroutine pctile(x,npts,npct,xpct)
+
+ parameter (NMAX=32768)
+ real*4 x(npts)
+ real*4 tmp(NMAX)
+
+ if(npts.le.0) then
+ xpct=1.0
+ go to 900
+ endif
+ if(npts.gt.NMAX) stop
+
+ tmp(1:npts)=x
+ call sort(npts,tmp)
+ j=nint(npts*0.01*npct)
+ if(j.lt.1) j=1
+ if(j.gt.npts) j=npts
+ xpct=tmp(j)
+
+900 continue
+ return
+end subroutine pctile
diff --git a/lib/peakdt9.f90 b/lib/peakdt9.f90
new file mode 100644
index 0000000..eac256e
--- /dev/null
+++ b/lib/peakdt9.f90
@@ -0,0 +1,54 @@
+subroutine peakdt9(c2,nz2,nsps8,nspsd,c3,nz3,xdt)
+
+ complex c2(0:4096-1)
+ complex c3(0:4096-1)
+ complex z
+ real p(0:3300)
+ include 'jt9sync.f90'
+
+ p=0.
+ i0=5*nspsd
+ do i=0,nz2-1
+ z=1.e-3*sum(c2(max(i-(nspsd-1),0):i))
+ p(i0+i)=real(z)**2 + aimag(z)**2 !Integrated symbol power at freq=0
+ enddo
+
+ call getlags(nsps8,lag0,lag1,lag2)
+ tsymbol=nsps8/1500.0
+ dtlag=tsymbol/nspsd
+ smax=0.
+ lagpk=0
+ do lag=lag1,lag2
+ sum0=0.
+ sum1=0.
+ j=-nspsd
+ do i=1,85
+ j=j+nspsd
+ if(isync(i).eq.1) then
+ sum1=sum1+p(j+lag)
+ else
+ sum0=sum0+p(j+lag)
+ endif
+ enddo
+ ss=(sum1/16.0)/(sum0/69.0) - 1.0
+ xdt=(lag-lag0)*dtlag
+ if(ss.gt.smax) then
+ smax=ss
+ lagpk=lag
+ endif
+ enddo
+
+ xdt=(lagpk-lag0)*dtlag
+
+ nz3=nspsd*85
+ do i=0,nz3-1
+ j=i+lagpk-i0-nspsd+1
+ if(j.ge.0 .and. j.le.nz2) then
+ c3(i)=c2(j)
+ else
+ c3(i)=0.
+ endif
+ enddo
+
+ return
+end subroutine peakdt9
diff --git a/lib/peakup.f90 b/lib/peakup.f90
new file mode 100644
index 0000000..8e5aeda
--- /dev/null
+++ b/lib/peakup.f90
@@ -0,0 +1,8 @@
+subroutine peakup(ym,y0,yp,dx)
+
+ b=(yp-ym)/2.0
+ c=(yp+ym-2.0*y0)/2.0
+ dx=-b/(2.0*c)
+
+ return
+end subroutine peakup
diff --git a/lib/pfx.f90 b/lib/pfx.f90
new file mode 100644
index 0000000..ca48718
--- /dev/null
+++ b/lib/pfx.f90
@@ -0,0 +1,50 @@
+ parameter (NZ=339) !Total number of prefixes
+ parameter (NZ2=12) !Total number of suffixes
+ character*1 sfx(NZ2)
+ character*5 pfx(NZ)
+
+ data sfx/'P','0','1','2','3','4','5','6','7','8','9','A'/
+ data pfx/ &
+ '1A ','1S ','3A ','3B6 ','3B8 ','3B9 ','3C ','3C0 ', &
+ '3D2 ','3D2C ','3D2R ','3DA ','3V ','3W ','3X ','3Y ', &
+ '3YB ','3YP ','4J ','4L ','4S ','4U1I ','4U1U ','4W ', &
+ '4X ','5A ','5B ','5H ','5N ','5R ','5T ','5U ', &
+ '5V ','5W ','5X ','5Z ','6W ','6Y ','7O ','7P ', &
+ '7Q ','7X ','8P ','8Q ','8R ','9A ','9G ','9H ', &
+ '9J ','9K ','9L ','9M2 ','9M6 ','9N ','9Q ','9U ', &
+ '9V ','9X ','9Y ','A2 ','A3 ','A4 ','A5 ','A6 ', &
+ 'A7 ','A9 ','AP ','BS7 ','BV ','BV9 ','BY ','C2 ', &
+ 'C3 ','C5 ','C6 ','C9 ','CE ','CE0X ','CE0Y ','CE0Z ', &
+ 'CE9 ','CM ','CN ','CP ','CT ','CT3 ','CU ','CX ', &
+ 'CY0 ','CY9 ','D2 ','D4 ','D6 ','DL ','DU ','E3 ', &
+ 'E4 ','EA ','EA6 ','EA8 ','EA9 ','EI ','EK ','EL ', &
+ 'EP ','ER ','ES ','ET ','EU ','EX ','EY ','EZ ', &
+ 'F ','FG ','FH ','FJ ','FK ','FKC ','FM ','FO ', &
+ 'FOA ','FOC ','FOM ','FP ','FR ','FRG ','FRJ ','FRT ', &
+ 'FT5W ','FT5X ','FT5Z ','FW ','FY ','M ','MD ','MI ', &
+ 'MJ ','MM ', 'MU ','MW ','H4 ','H40 ','HA ', &
+ 'HB ','HB0 ','HC ','HC8 ','HH ','HI ','HK ','HK0A ', &
+ 'HK0M ','HL ','HM ','HP ','HR ','HS ','HV ','HZ ', &
+ 'I ','IS ','IS0 ', 'J2 ','J3 ','J5 ','J6 ', &
+ 'J7 ','J8 ','JA ','JDM ','JDO ','JT ','JW ', &
+ 'JX ','JY ','K ','KG4 ','KH0 ','KH1 ','KH2 ','KH3 ', &
+ 'KH4 ','KH5 ','KH5K ','KH6 ','KH7 ','KH8 ','KH9 ','KL ', &
+ 'KP1 ','KP2 ','KP4 ','KP5 ','LA ','LU ','LX ','LY ', &
+ 'LZ ','OA ','OD ','OE ','OH ','OH0 ','OJ0 ','OK ', &
+ 'OM ','ON ','OX ','OY ','OZ ','P2 ','P4 ','PA ', &
+ 'PJ2 ','PJ7 ','PY ','PY0F ','PT0S ','PY0T ','PZ ','R1F ', &
+ 'R1M ','S0 ','S2 ','S5 ','S7 ','S9 ','SM ','SP ', &
+ 'ST ','SU ','SV ','SVA ','SV5 ','SV9 ','T2 ','T30 ', &
+ 'T31 ','T32 ','T33 ','T5 ','T7 ','T8 ','T9 ','TA ', &
+ 'TF ','TG ','TI ','TI9 ','TJ ','TK ','TL ', &
+ 'TN ','TR ','TT ','TU ','TY ','TZ ','UA ','UA2 ', &
+ 'UA9 ','UK ','UN ','UR ','V2 ','V3 ','V4 ','V5 ', &
+ 'V6 ','V7 ','V8 ','VE ','VK ','VK0H ','VK0M ','VK9C ', &
+ 'VK9L ','VK9M ','VK9N ','VK9W ','VK9X ','VP2E ','VP2M ','VP2V ', &
+ 'VP5 ','VP6 ','VP6D ','VP8 ','VP8G ','VP8H ','VP8O ','VP8S ', &
+ 'VP9 ','VQ9 ','VR ','VU ','VU4 ','VU7 ','XE ','XF4 ', &
+ 'XT ','XU ','XW ','XX9 ','XZ ','YA ','YB ','YI ', &
+ 'YJ ','YK ','YL ','YN ','YO ','YS ','YU ','YV ', &
+ 'YV0 ','Z2 ','Z3 ','ZA ','ZB ','ZC4 ','ZD7 ','ZD8 ', &
+ 'ZD9 ','ZF ','ZK1N ','ZK1S ','ZK2 ','ZK3 ','ZL ','ZL7 ', &
+ 'ZL8 ','ZL9 ','ZP ','ZS ','ZS8 ','KC4 ','E5 '/
diff --git a/lib/pfxdump.f90 b/lib/pfxdump.f90
new file mode 100644
index 0000000..7587dbf
--- /dev/null
+++ b/lib/pfxdump.f90
@@ -0,0 +1,13 @@
+subroutine pfxdump(fname)
+ character*(*) fname
+ include 'pfx.f90'
+
+ open(11,file=fname,status='unknown')
+ write(11,1001) sfx
+1001 format('Supported Suffixes:'/(11('/',a1,2x)))
+ write(11,1002) pfx
+1002 format(/'Supported Add-On DXCC Prefixes:'/(15(a5,1x)))
+ close(11)
+
+ return
+end subroutine pfxdump
diff --git a/lib/ps24.f90 b/lib/ps24.f90
new file mode 100644
index 0000000..241e49f
--- /dev/null
+++ b/lib/ps24.f90
@@ -0,0 +1,27 @@
+subroutine ps24(dat,nfft,s)
+
+ parameter (NMAX=2520+2)
+ parameter (NHMAX=NMAX/2-1)
+ real dat(nfft)
+ real dat2(NMAX)
+ real s(NHMAX)
+ complex c(0:NMAX)
+ equivalence(dat2,c)
+
+ nh=nfft/2
+ do i=1,nh
+ dat2(i)=dat(i)/128.0 !### Why 128 ??
+ enddo
+ do i=nh+1,nfft
+ dat2(i)=0.
+ enddo
+
+ call four2a(c,nfft,1,-1,0)
+
+ fac=1.0/nfft
+ do i=1,nh
+ s(i)=fac*(real(c(i))**2 + aimag(c(i))**2)
+ enddo
+
+ return
+end subroutine ps24
diff --git a/lib/ptt.c b/lib/ptt.c
new file mode 100644
index 0000000..902193f
--- /dev/null
+++ b/lib/ptt.c
@@ -0,0 +1,50 @@
+#include <windows.h>
+#include <stdio.h>
+
+int ptt_(int *nport, int *ntx, int *iptt)
+{
+ static HANDLE hFile;
+ static int open=0;
+ char s[10];
+ int i3=1,i4=1,i5=1,i6=1,i9=1,i00=1;
+
+ if(*nport==0) {
+ *iptt=*ntx;
+ return(0);
+ }
+
+ if(*ntx && (!open)) {
+ sprintf(s,"\\\\.\\COM%d",*nport);
+ hFile=CreateFile(TEXT(s),GENERIC_WRITE,0,NULL,OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,NULL);
+ if(hFile==INVALID_HANDLE_VALUE) {
+ // printf("PTT: Cannot open COM port %d.\n",*nport);
+ return 1;
+ }
+ open=1;
+ }
+
+ if(*ntx && open) {
+ i3=EscapeCommFunction(hFile,3);
+ i5=EscapeCommFunction(hFile,5);
+ *iptt=1;
+ }
+
+ else {
+ i4=EscapeCommFunction(hFile,4);
+ i6=EscapeCommFunction(hFile,6);
+ i9=EscapeCommFunction(hFile,9);
+ i00=CloseHandle(hFile);
+ *iptt=0;
+ open=0;
+ }
+ /*
+ if(i3==0) return 3;
+ if(i4==0) return 4;
+ if(i5==0) return 5;
+ if(i6==0) return 6;
+ if(i9==0) return 9;
+ if(i00==0) return 10;
+ */
+ return 0;
+}
diff --git a/lib/rig_control.c b/lib/rig_control.c
new file mode 100644
index 0000000..7c8b2f6
--- /dev/null
+++ b/lib/rig_control.c
@@ -0,0 +1,99 @@
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "tstrig.h"
+
+RIG *my_rig; // handle to rig
+
+int set_conf(RIG *my_rig, char *conf_parms);
+
+//------------------------------------------------------------------------
+int set_conf(RIG *my_rig, char *conf_parms)
+{
+ char *p, *q, *n;
+ int iret;
+
+ p = conf_parms;
+ while (p && *p != '\0') {
+ /* FIXME: left hand value of = cannot be null */
+ q = strchr(p, '=');
+ if ( !q )
+ return -RIG_EINVAL;
+ *q++ = '\0';
+ n = strchr(q, ',');
+ if (n) *n++ = '\0';
+ iret = rig_set_conf(my_rig, rig_token_lookup(my_rig, p), q);
+ if (iret != RIG_OK)
+ return iret;
+ p = n;
+ }
+ return RIG_OK;
+}
+
+//------------------------------------------------------------------------
+int rigOpen(int verbose, rig_model_t my_model, const char* rig_file,
+ int serial_rate, const char* conf_parms2)
+{
+ int iret; /* generic return code from functions */
+ char *civaddr = NULL; /* NULL means no need to set conf */
+ // const char *rig_file;
+ // const char *conf_parms2;
+ // int serial_rate;
+
+ rig_set_debug(verbose);
+ my_rig=rig_init(my_model);
+
+ if (!my_rig) {
+ // fprintf(stderr, "Unknown rig num %d, or initialization error.\n",my_model);
+ return -1;
+ }
+
+ // rig_file="COM1";
+ // serial_rate=4800;
+ // conf_parms2="data_bits=8,stop_bits=2,serial_handshake=Hardware";
+
+ iret=set_conf(my_rig, conf_parms2);
+ if (iret!=RIG_OK) {
+ // fprintf(stderr, "Config parameter error: %s\n", rigerror(iret));
+ return -2;
+ }
+
+ if (rig_file)
+ strncpy(my_rig->state.rigport.pathname, rig_file, FILPATHLEN - 1);
+
+ if (serial_rate!=0)
+ my_rig->state.rigport.parm.serial.rate = serial_rate;
+
+ if (civaddr)
+ rig_set_conf(my_rig, rig_token_lookup(my_rig, "civaddr"), civaddr);
+
+ iret = rig_open(my_rig);
+ if(iret!=0) return -3;
+ return 0;
+}
+
+int rigSetFreq(int fHz)
+{
+ return rig_set_freq(my_rig,RIG_VFO_CURR,fHz);
+}
+
+int rigFreq(int *fHz)
+{
+ int iret=0;
+ freq_t freq;
+ iret=rig_get_freq(my_rig, RIG_VFO_CURR, &freq);
+ *fHz=freq;
+ return iret;
+}
+
+int rigSetPTT(int iptt)
+{
+ return rig_set_ptt(my_rig, RIG_VFO_CURR, iptt);
+}
+
+void rigClose()
+{
+ rig_close(my_rig);
+ rig_cleanup(my_rig);
+}
diff --git a/lib/rs.h b/lib/rs.h
new file mode 100644
index 0000000..06cbe34
--- /dev/null
+++ b/lib/rs.h
@@ -0,0 +1,35 @@
+/* User include file for the Reed-Solomon codec
+ * Copyright 2002, Phil Karn KA9Q
+ * May be used under the terms of the GNU General Public License (GPL)
+ */
+
+/* General purpose RS codec, 8-bit symbols */
+void encode_rs_char(void *rs,unsigned char *data,unsigned char *parity);
+int decode_rs_char(void *rs,unsigned char *data,int *eras_pos,
+ int no_eras);
+void *init_rs_char(int symsize,int gfpoly,
+ int fcr,int prim,int nroots,
+ int pad);
+void free_rs_char(void *rs);
+
+/* General purpose RS codec, integer symbols */
+void encode_rs_int(void *rs,int *data,int *parity);
+int decode_rs_int(void *rs,int *data,int *eras_pos,int no_eras);
+void *init_rs_int(int symsize,int gfpoly,int fcr,
+ int prim,int nroots,int pad);
+void free_rs_int(void *rs);
+
+/* CCSDS standard (255,223) RS codec with conventional (*not* dual-basis)
+ * symbol representation
+ */
+void encode_rs_8(unsigned char *data,unsigned char *parity,int pad);
+int decode_rs_8(unsigned char *data,int *eras_pos,int no_eras,int pad);
+
+/* CCSDS standard (255,223) RS codec with dual-basis symbol representation */
+void encode_rs_ccsds(unsigned char *data,unsigned char *parity,int pad);
+int decode_rs_ccsds(unsigned char *data,int *eras_pos,int no_eras,int pad);
+
+/* Tables to map from conventional->dual (Taltab) and
+ * dual->conventional (Tal1tab) bases
+ */
+extern unsigned char Taltab[],Tal1tab[];
diff --git a/lib/s3avg.f90 b/lib/s3avg.f90
new file mode 100644
index 0000000..f8f68ac
--- /dev/null
+++ b/lib/s3avg.f90
@@ -0,0 +1,60 @@
+subroutine s3avg(nsave,mode65,nutc,nhz,xdt,npol,ntol,s3,nsum,nkv,decoded)
+
+! Save the current synchronized spectra, s3(64,63), for possible
+! decoding of average.
+
+ real s3(64,63) !Synchronized spectra for 63 symbols
+ real s3a(64,63,64) !Saved spectra
+ real s3b(64,63) !Average spectra
+ integer iutc(64),ihz(64),ipol(64)
+ real dt(64)
+ character*22 decoded
+ logical ltext,first
+ data first/.true./
+ save
+
+ if(first) then
+ iutc=-1
+ ihz=0
+ ipol=0
+ first=.false.
+ ihzdiff=min(100,ntol)
+ dtdiff=0.2
+ endif
+
+ do i=1,64
+ if(nutc.eq.iutc(i) .and. abs(nhz-ihz(i)).lt.ihzdiff) then
+ nsave=mod(nsave-1+64,64)+1
+ go to 10
+ endif
+ enddo
+
+ iutc(nsave)=nutc !Save UTC
+ ihz(nsave)=nhz !Save freq in Hz
+ ipol(nsave)=npol !Save pol
+ dt(nsave)=xdt !Save DT
+ s3a(1:64,1:63,nsave)=s3 !Save the spectra
+
+10 s3b=0.
+ do i=1,64 !Accumulate avg spectra
+ if(iutc(i).lt.0) cycle
+ if(mod(iutc(i),2).ne.mod(nutc,2)) cycle !Use only same sequence
+ if(abs(nhz-ihz(i)).gt.ihzdiff) cycle !Freq must match
+ if(abs(xdt-dt(i)).gt.dtdiff) cycle !DT must match
+ s3b=s3b + s3a(1:64,1:63,i)
+ nsum=nsum+1
+ enddo
+
+ decoded=' '
+ if(nsum.ge.2) then !Try decoding the sverage
+ nadd=mode65*nsum
+ call extract(s3b,nadd,ncount,nhist,decoded,ltext) !Extract the message
+ nkv=nsum
+ if(ncount.lt.0) then
+ nkv=0
+ decoded=' '
+ endif
+ endif
+
+ return
+end subroutine s3avg
diff --git a/lib/sec_midn.f90 b/lib/sec_midn.f90
new file mode 100644
index 0000000..0bbe62c
--- /dev/null
+++ b/lib/sec_midn.f90
@@ -0,0 +1,11 @@
+real function sec_midn()
+ sec_midn=secnds(0.0)
+ return
+end function sec_midn
+
+subroutine sleep_msec(n)
+
+ call usleep(1000*n)
+
+ return
+end subroutine sleep_msec
diff --git a/lib/setup65.f90 b/lib/setup65.f90
new file mode 100644
index 0000000..608b41b
--- /dev/null
+++ b/lib/setup65.f90
@@ -0,0 +1,96 @@
+subroutine setup65
+
+! Defines arrays related to the JT65 pseudo-random synchronizing pattern.
+! Executed at program start.
+
+ integer nprc(126)
+ common/prcom/pr(126),mdat(126),mref(126,2),mdat2(126),mref2(126,2)
+
+! JT65
+ data nprc/ &
+ 1,0,0,1,1,0,0,0,1,1,1,1,1,1,0,1,0,1,0,0, &
+ 0,1,0,1,1,0,0,1,0,0,0,1,1,1,0,0,1,1,1,1, &
+ 0,1,1,0,1,1,1,1,0,0,0,1,1,0,1,0,1,0,1,1, &
+ 0,0,1,1,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,1, &
+ 1,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,0,1, &
+ 0,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,0,0,1,1, &
+ 1,1,1,1,1,1/
+ data mr2/0/ !Silence compiler warning
+
+! Put the appropriate pseudo-random sequence into pr
+ nsym=126
+ do i=1,nsym
+ pr(i)=2*nprc(i)-1
+ enddo
+
+! Determine locations of data and reference symbols
+ k=0
+ mr1=0
+ do i=1,nsym
+ if(pr(i).lt.0.0) then
+ k=k+1
+ mdat(k)=i
+ else
+ mr2=i
+ if(mr1.eq.0) mr1=i
+ endif
+ enddo
+ nsig=k
+
+! Determine the reference symbols for each data symbol.
+ do k=1,nsig
+ m=mdat(k)
+ mref(k,1)=mr1
+ do n=1,10 !Get ref symbol before data
+ if((m-n).gt.0) then
+ if (pr(m-n).gt.0.0) go to 10
+ endif
+ enddo
+ go to 12
+10 mref(k,1)=m-n
+12 mref(k,2)=mr2
+ do n=1,10 !Get ref symbol after data
+ if((m+n).le.nsym) then
+ if (pr(m+n).gt.0.0) go to 20
+ endif
+ enddo
+ cycle
+20 mref(k,2)=m+n
+ enddo
+
+! Now do it all again, using opposite logic on pr(i)
+ k=0
+ mr1=0
+ do i=1,nsym
+ if(pr(i).gt.0.0) then
+ k=k+1
+ mdat2(k)=i
+ else
+ mr2=i
+ if(mr1.eq.0) mr1=i
+ endif
+ enddo
+ nsig=k
+
+ do k=1,nsig
+ m=mdat2(k)
+ mref2(k,1)=mr1
+ do n=1,10
+ if((m-n).gt.0) then
+ if (pr(m-n).lt.0.0) go to 110
+ endif
+ enddo
+ go to 112
+110 mref2(k,1)=m-n
+112 mref2(k,2)=mr2
+ do n=1,10
+ if((m+n).le.nsym) then
+ if (pr(m+n).lt.0.0) go to 120
+ endif
+ enddo
+ cycle
+120 mref2(k,2)=m+n
+ enddo
+
+ return
+end subroutine setup65
diff --git a/lib/sleep.h b/lib/sleep.h
new file mode 100644
index 0000000..df60bc9
--- /dev/null
+++ b/lib/sleep.h
@@ -0,0 +1,32 @@
+/*
+ * sleep.h 1.0 02/03/10
+ *
+ * Defines cross-platform sleep, usleep, etc.
+ *
+ * By Wu Yongwei
+ *
+ */
+
+#ifndef _SLEEP_H
+#define _SLEEP_H
+
+#ifdef _WIN32
+# if defined(_NEED_SLEEP_ONLY) && (defined(_MSC_VER) || defined(__MINGW32__))
+# include <stdlib.h>
+# define sleep(t) _sleep((t) * 1000)
+# else
+# include <windows.h>
+# define sleep(t) Sleep((t) * 1000)
+# endif
+# ifndef _NEED_SLEEP_ONLY
+# define msleep(t) Sleep(t)
+# define usleep(t) Sleep((t) / 1000)
+# endif
+#else
+# include <unistd.h>
+# ifndef _NEED_SLEEP_ONLY
+# define msleep(t) usleep((t) * 1000)
+# endif
+#endif
+
+#endif /* _SLEEP_H */
diff --git a/lib/sleep_msec.f90 b/lib/sleep_msec.f90
new file mode 100644
index 0000000..1a8dbe4
--- /dev/null
+++ b/lib/sleep_msec.f90
@@ -0,0 +1,4 @@
+subroutine sleep_msec(n)
+ call usleep(n*1000)
+ return
+end subroutine sleep_msec
diff --git a/lib/slope.f90 b/lib/slope.f90
new file mode 100644
index 0000000..5581ade
--- /dev/null
+++ b/lib/slope.f90
@@ -0,0 +1,40 @@
+subroutine slope(y,npts,xpk)
+
+! Remove best-fit slope from data in y(i). When fitting the straight line,
+! ignore the peak around xpk +/- 2.
+
+ real y(npts)
+ real x(100)
+
+ do i=1,npts
+ x(i)=i
+ enddo
+
+ sumw=0.
+ sumx=0.
+ sumy=0.
+ sumx2=0.
+ sumxy=0.
+ sumy2=0.
+
+ do i=1,npts
+ if(abs(i-xpk).gt.2.0) then
+ sumw=sumw + 1.0
+ sumx=sumx + x(i)
+ sumy=sumy + y(i)
+ sumx2=sumx2 + x(i)**2
+ sumxy=sumxy + x(i)*y(i)
+ sumy2=sumy2 + y(i)**2
+ endif
+ enddo
+
+ delta=sumw*sumx2 - sumx**2
+ a=(sumx2*sumy - sumx*sumxy) / delta
+ b=(sumw*sumxy - sumx*sumy) / delta
+
+ do i=1,npts
+ y(i)=y(i)-(a + b*x(i))
+ enddo
+
+ return
+end subroutine slope
diff --git a/lib/smo121.f90 b/lib/smo121.f90
new file mode 100644
index 0000000..7ae30ad
--- /dev/null
+++ b/lib/smo121.f90
@@ -0,0 +1,13 @@
+subroutine smo121(x,nz)
+
+ real x(nz)
+
+ x0=x(1)
+ do i=2,nz-1
+ x1=x(i)
+ x(i)=0.5*x(i) + 0.25*(x0+x(i+1))
+ x0=x1
+ enddo
+
+ return
+end subroutine smo121
diff --git a/lib/softsym.f90 b/lib/softsym.f90
new file mode 100644
index 0000000..8eda5e7
--- /dev/null
+++ b/lib/softsym.f90
@@ -0,0 +1,50 @@
+subroutine softsym(id2,npts8,nsps8,newdat,fpk,syncpk,snrdb,xdt, &
+ freq,drift,schk,i1SoftSymbols)
+
+! Compute the soft symbols
+
+ complex c2(0:4096-1)
+ complex c3(0:4096-1)
+ complex c5(0:4096-1)
+ real a(3)
+ integer*1 i1SoftSymbolsScrambled(207)
+ integer*1 i1SoftSymbols(207)
+ include 'jt9sync.f90'
+
+ nspsd=16
+ ndown=nsps8/nspsd
+
+! Mix, low-pass filter, and downsample to 16 samples per symbol
+ call timer('downsam9',0)
+ call downsam9(id2,npts8,nsps8,newdat,nspsd,fpk,c2,nz2)
+ call timer('downsam9',1)
+
+ call timer('peakdt9 ',0)
+ call peakdt9(c2,nz2,nsps8,nspsd,c3,nz3,xdt) !Find DT
+ call timer('peakdt9 ',1)
+
+ fsample=1500.0/ndown
+ a=0.
+ call timer('afc9 ',0)
+ call afc9(c3,nz3,fsample,a,syncpk) !Find deltaF, fDot, fDDot
+ call timer('afc9 ',1)
+ freq=fpk - a(1)
+ drift=-2.0*a(2)
+
+ call timer('twkfreq ',0)
+ call twkfreq(c3,c5,nz3,fsample,a) !Correct for delta f, f1, f2 ==> a(1:3)
+ call timer('twkfreq ',1)
+
+! Compute soft symbols (in scrambled order)
+ call timer('symspec2',0)
+ call symspec2(c5,nz3,nsps8,nspsd,fsample,freq,drift,snrdb,schk, &
+ i1SoftSymbolsScrambled)
+ call timer('symspec2',1)
+
+! Remove interleaving
+ call timer('interlv9',0)
+ call interleave9(i1SoftSymbolsScrambled,-1,i1SoftSymbols)
+ call timer('interlv9',1)
+
+ return
+end subroutine softsym
diff --git a/lib/sort.f90 b/lib/sort.f90
new file mode 100644
index 0000000..281ce02
--- /dev/null
+++ b/lib/sort.f90
@@ -0,0 +1,4 @@
+subroutine sort(n,arr)
+ call ssort(arr,tmp,n,1)
+ return
+end subroutine sort
diff --git a/lib/ss.bat b/lib/ss.bat
new file mode 100644
index 0000000..37f669a
--- /dev/null
+++ b/lib/ss.bat
@@ -0,0 +1 @@
+svn status | grep -v '?'
diff --git a/lib/ssort.f90 b/lib/ssort.f90
new file mode 100644
index 0000000..7d71238
--- /dev/null
+++ b/lib/ssort.f90
@@ -0,0 +1,264 @@
+subroutine ssort (x,y,n,kflag)
+! Sort an array and optionally make the same interchanges in
+! an auxiliary array. the array may be sorted in increasing
+! or decreasing order. a slightly modified quicksort
+! algorithm is used.
+
+! ssort sorts array x and optionally makes the same interchanges in
+! array y. the array x may be sorted in increasing order or
+! decreasing order. a slightly modified quicksort algorithm is used.
+
+! Description of parameters
+! x - array of values to be sorted
+! y - array to be (optionally) carried along
+! n - number of values in array x to be sorted
+! kflag - control parameter
+! = 2 means sort x in increasing order and carry y along.
+! = 1 means sort x in increasing order (ignoring y)
+! = -1 means sort x in decreasing order (ignoring y)
+! = -2 means sort x in decreasing order and carry y along.
+
+ integer kflag, n
+ integer x(n), y(n)
+ real r
+ integer t, tt, tty, ty
+ integer i, ij, j, k, kk, l, m, nn
+ integer il(21), iu(21)
+
+ nn = n
+ if (nn .lt. 1) then
+! print*,'ssort: The number of sort elements is not positive.'
+! print*,'ssort: n = ',nn,' kflag = ',kflag
+ return
+ endif
+
+ kk = abs(kflag)
+ if (kk.ne.1 .and. kk.ne.2) then
+ print *,'the sort control parameter, k, is not 2, 1, -1, or -2.'
+ return
+ endif
+
+! Alter array x to get decreasing order if needed
+
+ if (kflag .le. -1) then
+ do i=1,nn
+ x(i) = -x(i)
+ enddo
+ endif
+
+ if (kk .eq. 2) go to 100
+
+! Sort x only
+
+ m = 1
+ i = 1
+ j = nn
+ r = 0.375e0
+
+20 if (i .eq. j) go to 60
+ if (r .le. 0.5898437e0) then
+ r = r+3.90625e-2
+ else
+ r = r-0.21875e0
+ endif
+
+30 k = i
+
+! Select a central element of the array and save it in location t
+
+ ij = i + int((j-i)*r)
+ t = x(ij)
+
+! If first element of array is greater than t, interchange with t
+
+ if (x(i) .gt. t) then
+ x(ij) = x(i)
+ x(i) = t
+ t = x(ij)
+ endif
+ l = j
+
+! If last element of array is less than than t, interchange with t
+ if (x(j) .lt. t) then
+ x(ij) = x(j)
+ x(j) = t
+ t = x(ij)
+
+! If first element of array is greater than t, interchange with t
+ if (x(i) .gt. t) then
+ x(ij) = x(i)
+ x(i) = t
+ t = x(ij)
+ endif
+ endif
+
+! Find an element in the second half of the array which is smaller than t
+40 l = l-1
+ if (x(l) .gt. t) go to 40
+
+! Find an element in the first half of the array which is greater than t
+50 k = k+1
+ if (x(k) .lt. t) go to 50
+
+! Interchange these elements
+ if (k .le. l) then
+ tt = x(l)
+ x(l) = x(k)
+ x(k) = tt
+ go to 40
+ endif
+
+! Save upper and lower subscripts of the array yet to be sorted
+ if (l-i .gt. j-k) then
+ il(m) = i
+ iu(m) = l
+ i = k
+ m = m+1
+ else
+ il(m) = k
+ iu(m) = j
+ j = l
+ m = m+1
+ endif
+ go to 70
+
+! Begin again on another portion of the unsorted array
+60 m = m-1
+ if (m .eq. 0) go to 190
+ i = il(m)
+ j = iu(m)
+
+70 if (j-i .ge. 1) go to 30
+ if (i .eq. 1) go to 20
+ i = i-1
+
+80 i = i+1
+ if (i .eq. j) go to 60
+ t = x(i+1)
+ if (x(i) .le. t) go to 80
+ k = i
+
+90 x(k+1) = x(k)
+ k = k-1
+ if (t .lt. x(k)) go to 90
+ x(k+1) = t
+ go to 80
+
+! Sort x and carry y along
+
+100 m = 1
+ i = 1
+ j = nn
+ r = 0.375e0
+
+110 if (i .eq. j) go to 150
+ if (r .le. 0.5898437e0) then
+ r = r+3.90625e-2
+ else
+ r = r-0.21875e0
+ endif
+
+ 120 k = i
+! Select a central element of the array and save it in location t
+ ij = i + int((j-i)*r)
+ t = x(ij)
+ ty = y(ij)
+
+! If first element of array is greater than t, interchange with t
+ if (x(i) .gt. t) then
+ x(ij) = x(i)
+ x(i) = t
+ t = x(ij)
+ y(ij) = y(i)
+ y(i) = ty
+ ty = y(ij)
+ endif
+ l = j
+
+! If last element of array is less than t, interchange with t
+ if (x(j) .lt. t) then
+ x(ij) = x(j)
+ x(j) = t
+ t = x(ij)
+ y(ij) = y(j)
+ y(j) = ty
+ ty = y(ij)
+
+! If first element of array is greater than t, interchange with t
+ if (x(i) .gt. t) then
+ x(ij) = x(i)
+ x(i) = t
+ t = x(ij)
+ y(ij) = y(i)
+ y(i) = ty
+ ty = y(ij)
+ endif
+ endif
+
+! Find an element in the second half of the array which is smaller than t
+130 l = l-1
+ if (x(l) .gt. t) go to 130
+
+! Find an element in the first half of the array which is greater than t
+140 k = k+1
+ if (x(k) .lt. t) go to 140
+
+! Interchange these elements
+ if (k .le. l) then
+ tt = x(l)
+ x(l) = x(k)
+ x(k) = tt
+ tty = y(l)
+ y(l) = y(k)
+ y(k) = tty
+ go to 130
+ endif
+
+! Save upper and lower subscripts of the array yet to be sorted
+ if (l-i .gt. j-k) then
+ il(m) = i
+ iu(m) = l
+ i = k
+ m = m+1
+ else
+ il(m) = k
+ iu(m) = j
+ j = l
+ m = m+1
+ endif
+ go to 160
+
+! Begin again on another portion of the unsorted array
+150 m = m-1
+ if (m .eq. 0) go to 190
+ i = il(m)
+ j = iu(m)
+
+160 if (j-i .ge. 1) go to 120
+ if (i .eq. 1) go to 110
+ i = i-1
+
+170 i = i+1
+ if (i .eq. j) go to 150
+ t = x(i+1)
+ ty = y(i+1)
+ if (x(i) .le. t) go to 170
+ k = i
+
+180 x(k+1) = x(k)
+ y(k+1) = y(k)
+ k = k-1
+ if (t .lt. x(k)) go to 180
+ x(k+1) = t
+ y(k+1) = ty
+ go to 170
+
+! Clean up
+190 if (kflag .le. -1) then
+ do i=1,nn
+ x(i) = -x(i)
+ enddo
+ endif
+
+ return
+end subroutine ssort
diff --git a/lib/stdmsg.f90 b/lib/stdmsg.f90
new file mode 100644
index 0000000..bc8d489
--- /dev/null
+++ b/lib/stdmsg.f90
@@ -0,0 +1,12 @@
+logical*1 function stdmsg(msg0)
+
+ character*22 msg0,msg
+ integer dat(12)
+ logical text
+
+ call packmsg(msg0,dat,text)
+ call unpackmsg(dat,msg)
+ stdmsg=msg.eq.msg0 .and. (.not.text)
+
+ return
+end function stdmsg
diff --git a/lib/symspec.f90 b/lib/symspec.f90
new file mode 100644
index 0000000..2facb49
--- /dev/null
+++ b/lib/symspec.f90
@@ -0,0 +1,113 @@
+subroutine symspec(k,ntrperiod,nsps,ingain,slope,pxdb,s,df3,ihsym,npts8)
+
+! Input:
+! k pointer to the most recent new data
+! ntrperiod T/R sequence length, minutes
+! nsps samples per symbol, at 12000 Hz
+! ndiskdat 0/1 to indicate if data from disk
+! nb 0/1 status of noise blanker (off/on)
+! nbslider NB setting, 0-100
+
+! Output:
+! pxdb power (0-60 dB)
+! s() current spectrum for waterfall display
+! ihsym index number of this half-symbol (1-184)
+
+! jt9com
+! ss() JT9 symbol spectra at half-symbol steps
+! savg() average spectra for waterfall display
+
+ include 'constants.f90'
+ real*4 w3(MAXFFT3)
+ real*4 s(NSMAX)
+ real*4 scale(NSMAX)
+ real*4 ssum(NSMAX)
+ real*4 xc(0:MAXFFT3-1)
+ complex cx(0:MAXFFT3/2)
+ integer*2 id2
+ common/jt9com/ss(184,NSMAX),savg(NSMAX),id2(NMAX),nutc,ndiskdat, &
+ ntr,mousefqso,newdat,nfa,nfb,ntol,kin,nzhsym,nsynced,ndecoded
+ data rms/999.0/,k0/99999999/,nfft3z/0/,slope0/0.0/
+ equivalence (xc,cx)
+ save
+
+ if(ntrperiod.eq.-999) stop !Silence compiler warning
+ nfft3=16384 !df=12000.0/16384 = 0.732422
+ jstep=nsps/2 !Step size = half-symbol in id2()
+ if(k.gt.NMAX) go to 900
+ if(k.lt.2048) then !(2048 was nfft3) (Any need for this ???)
+ ihsym=0
+ go to 900 !Wait for enough samples to start
+ endif
+
+ if(nfft3.ne.nfft3z .or. slope.ne.slope0) then !New nfft3, compute window
+ pi=4.0*atan(1.0)
+ do i=1,nfft3
+ w3(i)=2.0*(sin(i*pi/nfft3))**2 !Window for nfft3 spectrum
+ enddo
+ nfft3z=nfft3
+ nh=NSMAX/2
+ do i=1,NSMAX
+ x=slope*float(i)/nh - 1.0 + 2.6
+ scale(i)=10.0**x
+ enddo
+ slope0=slope
+ endif
+
+ if(k.lt.k0) then !Start a new data block
+ ja=0
+ ssum=0.
+ ihsym=0
+ if(ndiskdat.eq.0) id2(k+1:)=0 !Needed to prevent "ghosts". Not sure why.
+ endif
+ gain=10.0**(0.05*ingain)
+ sq=0.
+ do i=k0+1,k
+ x1=id2(i)
+ sq=sq + x1*x1
+ enddo
+ sq=sq * gain**2
+ rms=sqrt(sq/(k-k0))
+ pxdb=0.
+ if(rms.gt.0.0) pxdb=20.0*log10(rms)
+ if(pxdb.gt.60.0) pxdb=60.0
+
+
+ k0=k
+ ja=ja+jstep !Index of first sample
+
+ fac0=0.1
+ do i=0,nfft3-1 !Copy data into cx
+ j=ja+i-(nfft3-1)
+ xc(i)=0.
+ if(j.ge.1) xc(i)=fac0*id2(j)
+ enddo
+
+ if(ihsym.lt.184) ihsym=ihsym+1
+
+ xc(0:nfft3-1)=w3(1:nfft3)*xc(0:nfft3-1) !Apply window w3
+ call four2a(xc,nfft3,1,-1,0) !Real-to-complex FFT
+
+ n=min(184,ihsym)
+ df3=12000.0/nfft3 !JT9-1: 0.732 Hz = 0.42 * tone spacing
+! i0=nint(1000.0/df3)
+ i0=0
+ iz=min(NSMAX,nint(5000.0/df3))
+ fac=(1.0/nfft3)**2
+ do i=1,iz
+ j=i0+i-1
+ if(j.lt.0) j=j+nfft3
+ sx=fac*(real(cx(j))**2 + aimag(cx(j))**2)
+ ss(n,i)=sx
+ ssum(i)=ssum(i) + sx
+ s(i)=gain*sx
+ enddo
+
+! s=0.05*s/ref
+ s=scale*s
+ savg=scale*ssum/ihsym
+
+900 npts8=k/8
+
+ return
+end subroutine symspec
diff --git a/lib/symspec2.f90 b/lib/symspec2.f90
new file mode 100644
index 0000000..92dc571
--- /dev/null
+++ b/lib/symspec2.f90
@@ -0,0 +1,88 @@
+subroutine symspec2(c5,nz3,nsps8,nspsd,fsample,freq,drift,snrdb,schk, &
+ i1SoftSymbolsScrambled)
+
+! Compute soft symbols from the final downsampled data
+
+ complex c5(0:4096-1)
+ complex z
+ integer*1 i1SoftSymbolsScrambled(207)
+ real aa(3)
+ real ss2(0:8,85)
+ real ss3(0:7,69)
+ include 'jt9sync.f90'
+ data scale/10.0/
+
+ aa(1)=-1500.0/nsps8
+ aa(2)=0.
+ aa(3)=0.
+ do i=0,8 !Loop over the 9 tones
+ if(i.ge.1) call twkfreq(c5,c5,nz3,fsample,aa)
+ m=0
+ k=-1
+ do j=1,85 !Loop over all symbols
+ z=0.
+ do n=1,nspsd !Sum over 16 samples
+ k=k+1
+ z=z+c5(k)
+ enddo
+ ss2(i,j)=real(z)**2 + aimag(z)**2 !Symbol speactra, data and sync
+ if(i.ge.1 .and. isync(j).eq.0) then
+ m=m+1
+ ss3(i-1,m)=ss2(i,j) !Symbol speactra, data only
+ endif
+ enddo
+ enddo
+
+ call chkss2(ss2,freq,drift,schk)
+ if(schk.lt.2.0) go to 900
+
+ ss=0.
+ sig=0.
+ do j=1,69
+ smax=0.
+ do i=0,7
+ smax=max(smax,ss3(i,j))
+ ss=ss+ss3(i,j)
+ enddo
+ sig=sig+smax
+ ss=ss-smax
+ enddo
+ ave=ss/(69*7) !Baseline
+ call pctile(ss2,9*85,35,xmed)
+ ss3=ss3/ave
+ sig=sig/69. !Signal
+ t=max(1.0,sig - 1.0)
+ snrdb=db(t) - 61.3
+
+ m0=3
+ k=0
+ do j=1,69
+ smax=0.
+ do i=0,7
+ if(ss3(i,j).gt.smax) smax=ss3(i,j)
+ enddo
+
+ do m=m0-1,0,-1 !Get bit-wise soft symbols
+ if(m.eq.2) then
+ r1=max(ss3(4,j),ss3(5,j),ss3(6,j),ss3(7,j))
+ r0=max(ss3(0,j),ss3(1,j),ss3(2,j),ss3(3,j))
+ else if(m.eq.1) then
+ r1=max(ss3(2,j),ss3(3,j),ss3(4,j),ss3(5,j))
+ r0=max(ss3(0,j),ss3(1,j),ss3(6,j),ss3(7,j))
+ else
+ r1=max(ss3(1,j),ss3(2,j),ss3(4,j),ss3(7,j))
+ r0=max(ss3(0,j),ss3(3,j),ss3(5,j),ss3(6,j))
+ endif
+
+ k=k+1
+ i4=nint(scale*(r1-r0))
+ if(i4.lt.-127) i4=-127
+ if(i4.gt.127) i4=127
+ i4=i4+128
+ if(i4.le.127) i1SoftSymbolsScrambled(k)=i4
+ if(i4.ge.128) i1SoftSymbolsScrambled(k)=i4-256
+ enddo
+ enddo
+
+900 return
+end subroutine symspec2
diff --git a/lib/symspec65.f90 b/lib/symspec65.f90
new file mode 100644
index 0000000..5f6da88
--- /dev/null
+++ b/lib/symspec65.f90
@@ -0,0 +1,47 @@
+subroutine symspec65(dd,npts,ss,nhsym,savg)
+
+! Compute JT65 symbol spectra at half-symbol steps
+
+ parameter (NFFT=8192)
+ parameter (NSZ=3413) !NFFT*5000/12000
+ parameter (MAXHSYM=322)
+ real*8 hstep
+ real*4 dd(npts)
+ real*4 ss(MAXHSYM,NSZ)
+ real*4 savg(NSZ)
+ real*4 x(NFFT)
+ complex c(0:NFFT/2)
+ common/refspec/dfref,ref(NSZ)
+ equivalence (x,c)
+ save /refspec/
+
+ hstep=2048.d0*12000.d0/11025.d0 !half-symbol = 2229.116 samples
+ nsps=nint(2*hstep)
+ df=12000.0/NFFT
+ nhsym=npts/hstep - 1.0
+ savg=0.
+ fac1=1.e-3
+
+ do j=1,nhsym
+ i0=(j-1)*hstep
+ x(1:nsps)=fac1*dd(i0+1:i0+nsps)
+ x(nsps+1:)=0.
+ call four2a(c,NFFT,1,-1,0) !r2c forward FFT
+ do i=1,NSZ
+ s=real(c(i))**2 + aimag(c(i))**2
+ ss(j,i)=s
+ savg(i)=savg(i)+s
+ enddo
+ enddo
+ savg=savg/nhsym
+
+ call flat65(ss,nhsym,MAXHSYM,NSZ,ref) !Flatten the 2d spectrum, saving
+ dfref=df ! the reference spectrum ref()
+
+ savg=savg/ref
+ do j=1,nhsym
+ ss(j,1:NSZ)=ss(j,1:NSZ)/ref
+ enddo
+
+ return
+end subroutine symspec65
diff --git a/lib/sync24.f90 b/lib/sync24.f90
new file mode 100644
index 0000000..cf6bf5a
--- /dev/null
+++ b/lib/sync24.f90
@@ -0,0 +1,179 @@
+subroutine sync24(dat,jz,DFTolerance,NFreeze,MouseDF,mode,mode4, &
+ dtx,dfx,snrx,snrsync,ccfblue,ccfred1,flip,width)
+
+! Synchronizes JT4 data, finding the best-fit DT and DF.
+
+ parameter (NFFTMAX=2520) !Max length of FFTs
+ parameter (NHMAX=NFFTMAX/2) !Max length of power spectra
+ parameter (NSMAX=525) !Max number of half-symbol steps
+ integer DFTolerance !Range of DF search
+ real dat(jz)
+ real psavg(NHMAX) !Average spectrum of whole record
+ real s2(NHMAX,NSMAX) !2d spectrum, stepped by half-symbols
+ real ccfblue(-5:540) !CCF with pseudorandom sequence
+ real ccfred(-450:450) !Peak of ccfblue, as function of freq
+ real ccfred1(-224:224) !Peak of ccfblue, as function of freq
+ real tmp(1260)
+ save
+
+! Do FFTs of twice symbol length, stepped by half symbols. Note that
+! we have already downsampled the data by factor of 2.
+
+ nsym=207
+ nfft=2520
+ nh=nfft/2
+ nq=nfft/4
+ nsteps=jz/nq - 1
+ df=0.5*11025.0/nfft
+ psavg(1:nh)=0.
+
+ do j=1,nsteps !Compute spectrum for each step, get average
+ k=(j-1)*nq + 1
+ call ps24(dat(k),nfft,s2(1,j))
+ psavg(1:nh)=psavg(1:nh) + s2(1:nh,j)
+ enddo
+
+ call flat1(psavg,s2,nh,nsteps,NHMAX,NSMAX) !Flatten spectra
+
+! Set freq and lag ranges
+ famin=200.
+ fbmax=2700.
+ fa=famin
+ fb=fbmax
+ if(NFreeze.eq.1) then
+ fa=max(famin,1270.46+MouseDF-DFTolerance)
+ fb=min(fbmax,1270.46+MouseDF+DFTolerance)
+ else
+ fa=max(famin,1270.46+MouseDF-600)
+ fb=min(fbmax,1270.46+MouseDF+600)
+ endif
+ ia=fa/df
+ ib=fb/df
+ if(mode.eq.7) then
+ ia=ia - 3*mode4
+ ib=ib - 3*mode4
+ endif
+ i0=nint(1270.46/df)
+ lag1=-5
+ lag2=59
+ syncbest=-1.e30
+ syncbest2=-1.e30
+ ccfred=0.
+
+ do i=ia,ib !Find best frequency channel for CCF
+
+ call xcor24(s2,i,nsteps,nsym,lag1,lag2,mode4,ccfblue,ccf0,lagpk0,flip)
+ j=i-i0
+ if(mode.eq.7) j=j + 3*mode4
+ if(j.ge.-372 .and. j.le.372) ccfred(j)=ccf0
+
+! Find rms of the CCF, without main peak
+ call slope(ccfblue(lag1),lag2-lag1+1,lagpk0-lag1+1.0)
+ sync=abs(ccfblue(lagpk0))
+ ppmax=psavg(i)-1.0
+
+! Find best sync value
+ if(sync.gt.syncbest2) then
+ ipk2=i
+ lagpk2=lagpk0
+ syncbest2=sync
+ endif
+
+! We are most interested if snrx will be more than -30 dB.
+ if(ppmax.gt.0.2938) then !Corresponds to snrx.gt.-30.0
+ if(sync.gt.syncbest) then
+ ipk=i
+ lagpk=lagpk0
+ syncbest=sync
+ endif
+ endif
+ enddo
+
+! If we found nothing with snrx > -30 dB, take the best sync that *was* found.
+ if(syncbest.lt.-10.) then
+ ipk=ipk2
+ lagpk=lagpk2
+ syncbest=syncbest2
+ endif
+
+ dfx=(ipk-i0)*df
+ if(mode.eq.7) dfx=dfx + 3*mode4*df
+
+! Peak up in time, at best whole-channel frequency
+ call xcor24(s2,ipk,nsteps,nsym,lag1,lag2,mode4,ccfblue,ccfmax,lagpk,flip)
+ xlag=lagpk
+ if(lagpk.gt.lag1 .and. lagpk.lt.lag2) then
+ call peakup(ccfblue(lagpk-1),ccfmax,ccfblue(lagpk+1),dx2)
+ xlag=lagpk+dx2
+ endif
+
+! Find rms of the CCF, without the main peak
+ call slope(ccfblue(lag1),lag2-lag1+1,xlag-lag1+1.0)
+ sq=0.
+ nsq=0
+ do lag=lag1,lag2
+ if(abs(lag-xlag).gt.2.0) then
+ sq=sq+ccfblue(lag)**2
+ nsq=nsq+1
+ endif
+ enddo
+ rms=sqrt(sq/nsq)
+ snrsync=abs(ccfblue(lagpk))/rms - 1.1 !Empirical
+
+ dt=2.0/11025.0
+ istart=xlag*nq
+ dtx=istart*dt
+ snrx=-99.0
+ ppmax=psavg(ipk)-1.0
+
+ if(ppmax.gt.0.0001) then
+ snrx=db(ppmax*df/2500.0) + 7.5 !Empirical
+ if(mode.eq.7) snrx=snrx + 3.0 !Empirical
+ endif
+ if(snrx.lt.-33.0) snrx=-33.0
+
+! Compute width of sync tone to outermost -3 dB points
+ i1=max(-450,ia-i0)
+ i2=min(450,ib-i0)
+ call pctile(ccfred(i1),i2-i1+1,45,base)
+
+ jpk=ipk-i0
+ if(abs(jpk).gt.450) then
+ print*,'sync24 a:',jpk,ipk,i0
+ snrsync=0.
+ go to 999
+ else
+ stest=base + 0.5*(ccfred(jpk)-base) ! -3 dB
+ endif
+ do i=-10,0
+ if(jpk+i.ge.-371) then
+ if(ccfred(jpk+i).gt.stest) go to 30
+ endif
+ enddo
+ i=0
+30 continue
+ if(abs(jpk+i-1).gt.450 .or. abs(jpk+i).gt.450) then
+ print*,'sync24 b:',jpk,i
+ else
+ x1=i-0.5
+ endif
+
+ do i=10,0,-1
+ if(jpk+i.le.371) then
+ if(ccfred(jpk+i).gt.stest) go to 32
+ endif
+ enddo
+ i=0
+32 x2=i+0.5
+ width=x2-x1
+ if(width.gt.1.2) width=sqrt(width**2 - 1.44)
+ width=df*width
+ width=max(0.0,min(99.0,width))
+
+ do i=-224,224
+ ccfred1(i)=ccfred(i)
+ enddo
+
+999 return
+end subroutine sync24
+
diff --git a/lib/sync9.f90 b/lib/sync9.f90
new file mode 100644
index 0000000..433e11f
--- /dev/null
+++ b/lib/sync9.f90
@@ -0,0 +1,101 @@
+subroutine sync9(ss,nzhsym,lag1,lag2,ia,ib,ccfred,red2,ipkbest)
+
+ include 'constants.f90'
+! parameter (NSMAX=1365) !Max length of saved spectra
+ real ss(184,NSMAX)
+ real ss1(184)
+ real ccfred(NSMAX)
+ real savg(NSMAX)
+ real savg2(NSMAX)
+ real smo(-5:25)
+ real sq(NSMAX)
+ real red2(NSMAX)
+ include 'jt9sync.f90'
+
+ ipk=0
+ ipkbest=0
+ sbest=0.
+ ccfred=0.
+
+ do i=ia,ib !Loop over freq range
+ ss1=ss(1:184,i)
+ call pctile(ss1,nzhsym,40,xmed)
+! xmed=sum(ss1(1:nzhsym))/nzhsym
+
+ ss1=ss1/xmed - 1.0
+ do j=1,nzhsym
+ if(ss1(j).gt.3.0) ss1(j)=3.0
+ enddo
+
+ call pctile(ss1,nzhsym,45,sbase)
+ ss1=ss1-sbase
+ sq0=dot_product(ss1(1:nzhsym),ss1(1:nzhsym))
+ rms=sqrt(sq0/(nzhsym-1))
+
+ smax=0.
+ do lag=lag1,lag2 !DT = 2.5 to 5.0 s
+ sum1=0.
+ sq2=sq0
+ nsum=nzhsym
+ do j=1,16 !Sum over 16 sync symbols
+ k=ii2(j) + lag
+ if(k.ge.1 .and. k.le.nzhsym) then
+ sum1=sum1 + ss1(k)
+ sq2=sq2 - ss1(k)*ss1(k)
+ nsum=nsum-1
+ endif
+ enddo
+ if(sum1.gt.smax) then
+ smax=sum1
+ ipk=i
+ endif
+ rms=sqrt(sq2/(nsum-1))
+ enddo
+ ccfred(i)=smax !Best at this freq, over all lags
+ if(smax.gt.sbest) then
+ sbest=smax
+ ipkbest=ipk
+ endif
+ enddo
+
+ call pctile(ccfred(ia),ib-ia+1,50,xmed)
+ if(xmed.le.0.0) xmed=1.0
+ ccfred=2.0*ccfred/xmed
+
+ savg=0.
+ do j=1,nzhsym
+ savg(ia:ib)=savg(ia:ib) + ss(j,ia:ib)
+ enddo
+! df=1500.0/2048.0 ! 0.732422
+! df9=12000.0/6912.0 ! 1.736111
+ savg(ia:ib)=savg(ia:ib)/nzhsym
+ smo(0:20)=1.0/21.0
+ smo(-5:-1)=-(1.0/21.0)*(21.0/10.0)
+ smo(21:25)=smo(-5)
+
+ do i=ia,ib
+ sm=0.
+ do j=-5,25
+ if(i+j.ge.1 .and. i+j.lt.NSMAX) sm=sm + smo(j)*savg(i+j)
+ enddo
+ savg2(i)=sm
+ sq(i)=sm*sm
+ enddo
+
+ call pctile(sq(ia:ib),ib-ia+1,20,sq0)
+ rms=sqrt(sq0)
+ savg2(ia:ib)=savg2(ia:ib)/(5.0*rms)
+
+ red2=0.
+ do i=ia+11,ib-10
+ ref=max(savg2(i-10),savg2(i+10))
+ red2(i)=savg2(i)-ref
+ if(red2(i).lt.-99.0) red2(i)=-99.0
+ if(red2(i).gt.99.0) red2(i)=99.0
+! write(30,3001) i,i*df+1000.0,savg2(i),red2(i),ccfred(i)
+!3001 format(i8,4f10.3)
+ enddo
+! call flush(30)
+
+ return
+end subroutine sync9
diff --git a/lib/tab.c b/lib/tab.c
new file mode 100644
index 0000000..3cd419a
--- /dev/null
+++ b/lib/tab.c
@@ -0,0 +1,36 @@
+/* 8-bit parity lookup table, generated by partab.c */
+unsigned char Partab[] = {
+ 0, 1, 1, 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0, 1, 1, 0,
+};
+
diff --git a/lib/timer.f90 b/lib/timer.f90
new file mode 100644
index 0000000..1637493
--- /dev/null
+++ b/lib/timer.f90
@@ -0,0 +1,112 @@
+subroutine timer(dname,k)
+
+! Times procedure number n between a call with k=0 (tstart) and with
+! k=1 (tstop). Accumulates sums of these times in array ut (user time).
+! Also traces all calls (for debugging purposes) if limtrace.gt.0
+
+ character*8 dname,name(50),space,ename
+ character*16 sname
+ logical on(50)
+ real ut(50),ut0(50),dut(50)
+ integer ncall(50),nlevel(50),nparent(50)
+ integer onlevel(0:10)
+ common/tracer/ limtrace,lu
+ data eps/0.000001/,ntrace/0/
+ data level/0/,nmax/0/,space/' '/
+ data limtrace/0/,lu/-1/
+ save
+
+ if(limtrace.lt.0) go to 999
+ if(lu.lt.1) lu=6
+ if(k.gt.1) go to 40 !Check for "all done" (k>1)
+ onlevel(0)=0
+
+ do n=1,nmax !Check for existing name
+ if(name(n).eq.dname) go to 20
+ enddo
+
+ nmax=nmax+1 !This is a new one
+ n=nmax
+ ncall(n)=0
+ on(n)=.false.
+ ut(n)=eps
+ name(n)=dname
+
+20 if(k.eq.0) then !Get start times (k=0)
+ if(on(n)) print*,'Error in timer: ',dname,' already on.'
+ level=level+1 !Increment the level
+ on(n)=.true.
+ call system_clock(icount,irate)
+ ut0(n)=float(icount)/irate
+ ncall(n)=ncall(n)+1
+ if(ncall(n).gt.1.and.nlevel(n).ne.level) then
+ nlevel(n)=-1
+ else
+ nlevel(n)=level
+ endif
+ nparent(n)=onlevel(level-1)
+ onlevel(level)=n
+
+ else if(k.eq.1) then !Get stop times and accumulate sums. (k=1)
+ if(on(n)) then
+ on(n)=.false.
+ call system_clock(icount,irate)
+ ut1=float(icount)/irate
+ ut(n)=ut(n)+ut1-ut0(n)
+ endif
+ level=level-1
+ endif
+
+ ntrace=ntrace+1
+ if(ntrace.lt.limtrace) write(lu,1020) ntrace,dname,k,level,nparent(n)
+1020 format(i8,': ',a8,3i5)
+ go to 998
+
+! Write out the timer statistics
+
+40 write(lu,1040)
+1040 format(/' name time frac dtime', &
+ ' dfrac calls level parent'/73('-'))
+
+ if(k.gt.100) then
+ ndiv=k-100
+ do i=1,nmax
+ ncall(i)=ncall(i)/ndiv
+ ut(i)=ut(i)/ndiv
+ enddo
+ endif
+
+ total=ut(1)
+ sum=0.
+ sumf=0.
+ do i=1,nmax
+ dut(i)=ut(i)
+ do j=i,nmax
+ if(nparent(j).eq.i) dut(i)=dut(i)-ut(j)
+ enddo
+ utf=ut(i)/total
+ dutf=dut(i)/total
+ sum=sum+dut(i)
+ sumf=sumf+dutf
+ kk=nlevel(i)
+ sname=space(1:kk)//name(i)//space(1:8-kk)
+ ename=space
+ if(i.ge.2) ename=name(nparent(i))
+ write(lu,1060) float(i),sname,ut(i),utf,dut(i),dutf, &
+ ncall(i),nlevel(i),ename
+1060 format(f4.0,a16,2(f10.2,f6.2),i7,i5,2x,a8)
+ enddo
+
+ write(lu,1070) sum,sumf
+1070 format(/36x,f10.2,f6.2)
+ nmax=0
+ eps=0.000001
+ ntrace=0
+ level=0
+ space=' '
+ onlevel(0)=0
+
+998 flush(lu)
+
+999 return
+end subroutine timer
diff --git a/lib/timeval.h b/lib/timeval.h
new file mode 100644
index 0000000..100dda5
--- /dev/null
+++ b/lib/timeval.h
@@ -0,0 +1,74 @@
+/*
+ * timeval.h 1.0 01/12/19
+ *
+ * Defines gettimeofday, timeval, etc. for Win32
+ *
+ * By Wu Yongwei
+ *
+ */
+
+#ifndef _TIMEVAL_H
+#define _TIMEVAL_H
+
+#ifdef _WIN32
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <time.h>
+
+#ifndef __GNUC__
+#define EPOCHFILETIME (116444736000000000i64)
+#else
+#define EPOCHFILETIME (116444736000000000LL)
+#endif
+
+//struct timeval {
+// long tv_sec; /* seconds */
+// long tv_usec; /* microseconds */
+//};
+
+struct timezone {
+ int tz_minuteswest; /* minutes W of Greenwich */
+ int tz_dsttime; /* type of dst correction */
+};
+
+__inline int gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+ FILETIME ft;
+ LARGE_INTEGER li;
+ __int64 t;
+ static int tzflag;
+
+ if (tv)
+ {
+ GetSystemTimeAsFileTime(&ft);
+ li.LowPart = ft.dwLowDateTime;
+ li.HighPart = ft.dwHighDateTime;
+ t = li.QuadPart; /* In 100-nanosecond intervals */
+ t -= EPOCHFILETIME; /* Offset to the Epoch time */
+ t /= 10; /* In microseconds */
+ tv->tv_sec = (long)(t / 1000000);
+ tv->tv_usec = (long)(t % 1000000);
+ }
+
+ if (tz)
+ {
+ if (!tzflag)
+ {
+ _tzset();
+ tzflag++;
+ }
+ tz->tz_minuteswest = _timezone / 60;
+ tz->tz_dsttime = _daylight;
+ }
+
+ return 0;
+}
+
+#else /* _WIN32 */
+
+#include <sys/time.h>
+
+#endif /* _WIN32 */
+
+#endif /* _TIMEVAL_H */
diff --git a/lib/tstrig.c b/lib/tstrig.c
new file mode 100644
index 0000000..2e77fea
--- /dev/null
+++ b/lib/tstrig.c
@@ -0,0 +1,26 @@
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "tstrig.h"
+
+int set_conf(RIG *my_rig, char *conf_parms);
+
+int rig_control(rig_model_t my_model, int verbose);
+
+int main (int argc, char *argv[])
+{
+ rig_model_t my_model = RIG_MODEL_DUMMY;
+ int verbose=0;
+
+ my_model=214;
+ rig_control(my_model,verbose);
+ return 0;
+}
+
+/*
+gcc -c -Wall -I../include rig_control.c
+gcc -c -Wall -I../include tstrig.c
+gcc -o tstrig.exe -Wl,--enable-auto-import tstrig.o rig_control.o libhamlib.dll.a
+strip tstrig.exe
+*/
diff --git a/lib/tstrig.h b/lib/tstrig.h
new file mode 100644
index 0000000..ce62d3d
--- /dev/null
+++ b/lib/tstrig.h
@@ -0,0 +1,50 @@
+/*
+ * rigctl_parse.h - (C) Stephane Fillod 2000-2010
+ *
+ * This program test/control a radio using Hamlib.
+ * It takes commands in interactive mode as well as
+ * from command line options.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef RIGCTL_PARSE_H
+#define RIGCTL_PARSE_H
+
+#include <stdio.h>
+#include <hamlib/rig.h>
+
+/*
+ * external prototype
+ */
+
+int dumpcaps (RIG *, FILE *);
+int dumpconf (RIG *, FILE *);
+
+/*
+ * Prototypes
+ */
+void usage_rig(FILE *);
+void version();
+void list_models();
+int dump_chan(FILE *, RIG*, channel_t*);
+int print_conf_list(const struct confparams *cfp, rig_ptr_t data);
+int set_conf(RIG *my_rig, char *conf_parms);
+
+int rigctl_parse(RIG *my_rig, FILE *fin, FILE *fout, char *argv[], int argc);
+
+#endif /* RIGCTL_PARSE_H */
diff --git a/lib/twkfreq.f90 b/lib/twkfreq.f90
new file mode 100644
index 0000000..0a9b34d
--- /dev/null
+++ b/lib/twkfreq.f90
@@ -0,0 +1,28 @@
+subroutine twkfreq(c3,c4,npts,fsample,a)
+
+ complex c3(npts)
+ complex c4(npts)
+ complex w,wstep
+ real a(3)
+ data twopi/6.283185307/
+
+! Mix the complex signal
+ w=1.0
+ wstep=1.0
+ x0=0.5*(npts+1)
+ s=2.0/npts
+ do i=1,npts
+ x=s*(i-x0)
+ if(mod(i,100).eq.1) then
+ p2=1.5*x*x - 0.5
+! p3=2.5*(x**3) - 1.5*x
+! p4=4.375*(x**4) - 3.75*(x**2) + 0.375
+ dphi=(a(1) + x*a(2) + p2*a(3)) * (twopi/fsample)
+ wstep=cmplx(cos(dphi),sin(dphi))
+ endif
+ w=w*wstep
+ c4(i)=w*c3(i)
+ enddo
+
+ return
+end subroutine twkfreq
diff --git a/lib/twkfreq65.f90 b/lib/twkfreq65.f90
new file mode 100644
index 0000000..85847c7
--- /dev/null
+++ b/lib/twkfreq65.f90
@@ -0,0 +1,25 @@
+subroutine twkfreq65(c4aa,n5,a)
+
+ complex c4aa(n5)
+ real a(5)
+ complex w,wstep
+ data twopi/6.283185307/
+
+! Apply AFC corrections to the c4aa data
+ w=1.0
+ wstep=1.0
+ x0=0.5*(n5+1)
+ s=2.0/n5
+ do i=1,n5
+ x=s*(i-x0)
+ if(mod(i,100).eq.1) then
+ p2=1.5*x*x - 0.5
+ dphi=(a(1) + x*a(2) + p2*a(3)) * (twopi/1378.125)
+ wstep=cmplx(cos(dphi),sin(dphi))
+ endif
+ w=w*wstep
+ c4aa(i)=w*c4aa(i)
+ enddo
+
+ return
+end subroutine twkfreq65
diff --git a/lib/unpackbits.f90 b/lib/unpackbits.f90
new file mode 100644
index 0000000..a3ff15f
--- /dev/null
+++ b/lib/unpackbits.f90
@@ -0,0 +1,22 @@
+subroutine unpackbits(sym,nsymd,m0,dbits)
+
+! Unpack bits from sym() into dbits(), one bit per byte.
+! NB: nsymd is the number of input words, and m0 their length.
+! there will be m0*nsymd output bytes, each 0 or 1.
+
+ integer sym(nsymd)
+ integer*1 dbits(*)
+
+ k=0
+ do i=1,nsymd
+ mask=ishft(1,m0-1)
+ do j=1,m0
+ k=k+1
+ dbits(k)=0
+ if(iand(mask,sym(i)).ne.0) dbits(k)=1
+ mask=ishft(mask,-1)
+ enddo
+ enddo
+
+ return
+end subroutine unpackbits
diff --git a/lib/unpackcall.f90 b/lib/unpackcall.f90
new file mode 100644
index 0000000..f738926
--- /dev/null
+++ b/lib/unpackcall.f90
@@ -0,0 +1,142 @@
+subroutine unpackcall(ncall,word,iv2,psfx)
+
+ parameter (NBASE=37*36*10*27*27*27)
+ character word*12,c*37,psfx*4
+
+ data c/'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ '/
+
+ n=ncall
+ iv2=0
+ if(n.ge.262177560) go to 20
+ word='......'
+ if(n.ge.262177560) go to 999 !Plain text message ...
+ i=mod(n,27)+11
+ word(6:6)=c(i:i)
+ n=n/27
+ i=mod(n,27)+11
+ word(5:5)=c(i:i)
+ n=n/27
+ i=mod(n,27)+11
+ word(4:4)=c(i:i)
+ n=n/27
+ i=mod(n,10)+1
+ word(3:3)=c(i:i)
+ n=n/10
+ i=mod(n,36)+1
+ word(2:2)=c(i:i)
+ n=n/36
+ i=n+1
+ word(1:1)=c(i:i)
+ do i=1,4
+ if(word(i:i).ne.' ') go to 10
+ enddo
+ go to 999
+10 word=word(i:)
+ go to 999
+
+20 if(n.ge.267796946) go to 999
+
+! We have a JT65v2 message
+ if((n.ge.262178563) .and. (n.le.264002071)) Then
+! CQ with prefix
+ iv2=1
+ n=n-262178563
+ i=mod(n,37)+1
+ psfx(4:4)=c(i:i)
+ n=n/37
+ i=mod(n,37)+1
+ psfx(3:3)=c(i:i)
+ n=n/37
+ i=mod(n,37)+1
+ psfx(2:2)=c(i:i)
+ n=n/37
+ i=n+1
+ psfx(1:1)=c(i:i)
+ endif
+
+ if((n.ge.264002072) .and. (n.le.265825580)) Then
+! QRZ with prefix
+ iv2=2
+ n=n-264002072
+ i=mod(n,37)+1
+ psfx(4:4)=c(i:i)
+ n=n/37
+ i=mod(n,37)+1
+ psfx(3:3)=c(i:i)
+ n=n/37
+ i=mod(n,37)+1
+ psfx(2:2)=c(i:i)
+ n=n/37
+ i=n+1
+ psfx(1:1)=c(i:i)
+ endif
+
+ if((n.ge.265825581) .and. (n.le.267649089)) Then
+! DE with prefix
+ iv2=3
+ n=n-265825581
+ i=mod(n,37)+1
+ psfx(4:4)=c(i:i)
+ n=n/37
+ i=mod(n,37)+1
+ psfx(3:3)=c(i:i)
+ n=n/37
+ i=mod(n,37)+1
+ psfx(2:2)=c(i:i)
+ n=n/37
+ i=n+1
+ psfx(1:1)=c(i:i)
+ endif
+
+ if((n.ge.267649090) .and. (n.le.267698374)) Then
+! CQ with suffix
+ iv2=4
+ n=n-267649090
+ i=mod(n,37)+1
+ psfx(3:3)=c(i:i)
+ n=n/37
+ i=mod(n,37)+1
+ psfx(2:2)=c(i:i)
+ n=n/37
+ i=n+1
+ psfx(1:1)=c(i:i)
+ endif
+
+ if((n.ge.267698375) .and. (n.le.267747659)) Then
+! QRZ with suffix
+ iv2=5
+ n=n-267698375
+ i=mod(n,37)+1
+ psfx(3:3)=c(i:i)
+ n=n/37
+ i=mod(n,37)+1
+ psfx(2:2)=c(i:i)
+ n=n/37
+ i=n+1
+ psfx(1:1)=c(i:i)
+ endif
+
+ if((n.ge.267747660) .and. (n.le.267796944)) Then
+! DE with suffix
+ iv2=6
+ n=n-267747660
+ i=mod(n,37)+1
+ psfx(3:3)=c(i:i)
+ n=n/37
+ i=mod(n,37)+1
+ psfx(2:2)=c(i:i)
+ n=n/37
+ i=n+1
+ psfx(1:1)=c(i:i)
+ endif
+
+ if(n.eq.267796945) Then
+! DE with no prefix or suffix
+ iv2=7
+ psfx = ' '
+ endif
+
+999 if(word(1:3).eq.'3D0') word='3DA0'//word(4:)
+
+ return
+end subroutine unpackcall
diff --git a/lib/unpackgrid.f90 b/lib/unpackgrid.f90
new file mode 100644
index 0000000..84dc744
--- /dev/null
+++ b/lib/unpackgrid.f90
@@ -0,0 +1,45 @@
+subroutine unpackgrid(ng,grid)
+
+ parameter (NGBASE=180*180)
+ character grid*4,grid6*6
+
+ grid=' '
+ if(ng.ge.32400) go to 10
+ dlat=mod(ng,180)-90
+ dlong=(ng/180)*2 - 180 + 2
+ call deg2grid(dlong,dlat,grid6)
+ grid=grid6(:4)
+ if(grid(1:2).eq.'KA') then
+ read(grid(3:4),*) n
+ n=n-50
+ write(grid,1001) n
+1001 format(i3.2)
+ if(grid(1:1).eq.' ') grid(1:1)='+'
+ else if(grid(1:2).eq.'LA') then
+ read(grid(3:4),*) n
+ n=n-50
+ write(grid,1002) n
+1002 format('R',i3.2)
+ if(grid(2:2).eq.' ') grid(2:2)='+'
+ endif
+ go to 900
+
+10 n=ng-NGBASE-1
+ if(n.ge.1 .and.n.le.30) then
+ write(grid,1012) -n
+1012 format(i3.2)
+ else if(n.ge.31 .and.n.le.60) then
+ n=n-30
+ write(grid,1022) -n
+1022 format('R',i3.2)
+ else if(n.eq.61) then
+ grid='RO'
+ else if(n.eq.62) then
+ grid='RRR'
+ else if(n.eq.63) then
+ grid='73'
+ endif
+
+900 return
+end subroutine unpackgrid
+
diff --git a/lib/unpackmsg.f90 b/lib/unpackmsg.f90
new file mode 100644
index 0000000..aca7cfc
--- /dev/null
+++ b/lib/unpackmsg.f90
@@ -0,0 +1,107 @@
+subroutine unpackmsg(dat,msg)
+
+ parameter (NBASE=37*36*10*27*27*27)
+ parameter (NGBASE=180*180)
+ integer dat(12)
+ character c1*12,c2*12,grid*4,msg*22,grid6*6,psfx*4,junk2*4
+ logical cqnnn
+
+ cqnnn=.false.
+ nc1=ishft(dat(1),22) + ishft(dat(2),16) + ishft(dat(3),10)+ &
+ ishft(dat(4),4) + iand(ishft(dat(5),-2),15)
+
+ nc2=ishft(iand(dat(5),3),26) + ishft(dat(6),20) + &
+ ishft(dat(7),14) + ishft(dat(8),8) + ishft(dat(9),2) + &
+ iand(ishft(dat(10),-4),3)
+
+ ng=ishft(iand(dat(10),15),12) + ishft(dat(11),6) + dat(12)
+
+ if(ng.ge.32768) then
+ call unpacktext(nc1,nc2,ng,msg)
+ go to 100
+ endif
+
+ call unpackcall(nc1,c1,iv2,psfx)
+ if(iv2.eq.0) then
+! This is an "original JT65" message
+ if(nc1.eq.NBASE+1) c1='CQ '
+ if(nc1.eq.NBASE+2) c1='QRZ '
+ nfreq=nc1-NBASE-3
+ if(nfreq.ge.0 .and. nfreq.le.999) then
+ write(c1,1002) nfreq
+1002 format('CQ ',i3.3)
+ cqnnn=.true.
+ endif
+ endif
+
+ call unpackcall(nc2,c2,junk1,junk2)
+ call unpackgrid(ng,grid)
+
+ if(iv2.gt.0) then
+! This is a JT65v2 message
+ do i=1,4
+ if(ichar(psfx(i:i)).eq.0) psfx(i:i)=' '
+ enddo
+
+ n1=len_trim(psfx)
+ n2=len_trim(c2)
+ if(iv2.eq.1) msg='CQ '//psfx(:n1)//'/'//c2(:n2)//' '//grid
+ if(iv2.eq.2) msg='QRZ '//psfx(:n1)//'/'//c2(:n2)//' '//grid
+ if(iv2.eq.3) msg='DE '//psfx(:n1)//'/'//c2(:n2)//' '//grid
+ if(iv2.eq.4) msg='CQ '//c2(:n2)//'/'//psfx(:n1)//' '//grid
+ if(iv2.eq.5) msg='QRZ '//c2(:n2)//'/'//psfx(:n1)//' '//grid
+ if(iv2.eq.6) msg='DE '//c2(:n2)//'/'//psfx(:n1)//' '//grid
+ if(iv2.eq.7) msg='DE '//c2(:n2)//' '//grid
+ go to 100
+ else
+
+ endif
+
+ grid6=grid//'ma'
+ call grid2k(grid6,k)
+ if(k.ge.1 .and. k.le.450) call getpfx2(k,c1)
+ if(k.ge.451 .and. k.le.900) call getpfx2(k,c2)
+
+ i=index(c1,char(0))
+ if(i.ge.3) c1=c1(1:i-1)//' '
+ i=index(c2,char(0))
+ if(i.ge.3) c2=c2(1:i-1)//' '
+
+ msg=' '
+ j=0
+ if(cqnnn) then
+ msg=c1//' '
+ j=7 !### ??? ###
+ go to 10
+ endif
+
+ do i=1,12
+ j=j+1
+ msg(j:j)=c1(i:i)
+ if(c1(i:i).eq.' ') go to 10
+ enddo
+ j=j+1
+ msg(j:j)=' '
+
+10 do i=1,12
+ if(j.le.21) j=j+1
+ msg(j:j)=c2(i:i)
+ if(c2(i:i).eq.' ') go to 20
+ enddo
+ if(j.le.21) j=j+1
+ msg(j:j)=' '
+
+20 if(k.eq.0) then
+ do i=1,4
+ if(j.le.21) j=j+1
+ msg(j:j)=grid(i:i)
+ enddo
+ if(j.le.21) j=j+1
+ msg(j:j)=' '
+ endif
+
+100 continue
+ if(msg(1:6).eq.'CQ9DX ') msg(3:3)=' '
+
+ return
+end subroutine unpackmsg
diff --git a/lib/unpacktext.f90 b/lib/unpacktext.f90
new file mode 100644
index 0000000..62451f9
--- /dev/null
+++ b/lib/unpacktext.f90
@@ -0,0 +1,35 @@
+subroutine unpacktext(nc1,nc2,nc3,msg)
+
+ character*22 msg
+ character*44 c
+ data c/'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ +-./?'/
+
+ nc3=iand(nc3,32767) !Remove the "plain text" bit
+ if(iand(nc1,1).ne.0) nc3=nc3+32768
+ nc1=nc1/2
+ if(iand(nc2,1).ne.0) nc3=nc3+65536
+ nc2=nc2/2
+
+ do i=5,1,-1
+ j=mod(nc1,42)+1
+ msg(i:i)=c(j:j)
+ nc1=nc1/42
+ enddo
+
+ do i=10,6,-1
+ j=mod(nc2,42)+1
+ msg(i:i)=c(j:j)
+ nc2=nc2/42
+ enddo
+
+ do i=13,11,-1
+ j=mod(nc3,42)+1
+ msg(i:i)=c(j:j)
+ nc3=nc3/42
+ enddo
+ msg(14:22) = ' '
+
+ return
+end subroutine unpacktext
+
+
diff --git a/lib/vit216.c b/lib/vit216.c
new file mode 100644
index 0000000..38984d2
--- /dev/null
+++ b/lib/vit216.c
@@ -0,0 +1,219 @@
+/* Viterbi decoder for arbitrary convolutional code
+ * viterbi27 and viterbi37 for the r=1/2 and r=1/3 K=7 codes are faster
+ * Copyright 1999 Phil Karn, KA9Q
+ * May be used under the terms of the GNU Public License
+ */
+
+/* Select code here */
+
+#define V216
+
+
+#ifdef V216
+#define K 16 /* Constraint length */
+#define N 2 /* Number of symbols per data bit */
+#define Polys Poly216 /* Select polynomials here */
+#endif
+
+/* Rate 1/2 codes */
+unsigned int Poly216[] = {0126723, 0152711}; /* k = 16 */
+
+#include <memory.h>
+#define NULL ((void *)0)
+
+#define LONGBITS 32
+#define LOGLONGBITS 5
+
+#undef max
+#define max(x,y) ((x) > (y) ? (x) : (y))
+#define D (1 << max(0,K-LOGLONGBITS-1))
+#define MAXNBITS 200 /* Maximum frame size (user bits) */
+
+extern unsigned char Partab[]; /* Parity lookup table */
+
+int Syms[1 << K];
+int VDInit = 0;
+
+int parity(int x)
+{
+ x ^= (x >> 16);
+ x ^= (x >> 8);
+ return Partab[x & 0xff];
+}
+
+// Wrapper for calling "encode" from Fortran:
+//void __stdcall ENCODE(
+void enc216_(
+unsigned char data[], // User data, 8 bits per byte
+int *nbits, // Number of user bits
+unsigned char symbols[], // Encoded one-bit symbols, 8 per byte
+int *nsymbols, // Number of symbols
+int *kk, // K
+int *nn) // N
+{
+ int nbytes;
+ nbytes=(*nbits+7)/8; // Always encode multiple of 8 information bits
+ enc216(symbols,data,nbytes,0,0); // Do the encoding
+ *nsymbols=(*nbits+K-1)*N; // Return number of encoded symbols
+ *kk=K;
+ *nn=N;
+}
+
+/* Convolutionally encode data into binary symbols */
+ enc216(unsigned char symbols[], unsigned char data[],
+ unsigned int nbytes, unsigned int startstate,
+ unsigned int endstate)
+{
+ int i,j,k,n=-1;
+ unsigned int encstate = startstate;
+
+ for(k=0; k<nbytes; k++) {
+ for(i=7;i>=0;i--){
+ encstate = (encstate + encstate) + ((data[k] >> i) & 1);
+ for(j=0;j<N;j++) {
+ n=n+1;
+ symbols[n] = parity(encstate & Polys[j]);
+ }
+ }
+ }
+ // Flush out with zero tail. (No need, if tail-biting code.)
+ for(i=0; i<K-1;i++){
+ encstate = (encstate << 1) | ((endstate >> i) & 1);
+ for(j=0;j<N;j++) {
+ n=n+1;
+ symbols[n] = parity(encstate & Polys[j]);
+ }
+ }
+ return 0;
+}
+
+// Wrapper for calling "viterbi" from Fortran:
+//void __stdcall VITERBI(
+void vit216_(
+unsigned char symbols[], /* Raw deinterleaved input symbols */
+unsigned int *Nbits, /* Number of decoded information bits */
+int mettab[2][256], /* Metric table, [sent sym][rx symbol] */
+unsigned char ddec[], /* Decoded output data */
+long *Metric /* Final path metric (bigger is better) */
+){
+ long metric;
+ vit216(&metric,ddec,symbols,*Nbits,mettab,0,0);
+ *Metric=metric;
+}
+
+/* Viterbi decoder */
+int vit216(
+long *metric, /* Final path metric (returned value) */
+unsigned char *data, /* Decoded output data */
+unsigned char *symbols, /* Raw deinterleaved input symbols */
+unsigned int nbits, /* Number of output bits */
+int mettab[2][256], /* Metric table, [sent sym][rx symbol] */
+unsigned int startstate, /* Encoder starting state */
+unsigned int endstate /* Encoder ending state */
+){
+ int bitcnt = -(K-1);
+ long m0,m1;
+ int i,j,sym,ipp;
+ int mets[1 << N];
+ unsigned long paths[(MAXNBITS+K-1)*D];
+ unsigned long *pp,mask;
+ long cmetric[1 << (K-1)],nmetric[1 << (K-1)];
+
+ memset(paths,0,sizeof(paths));
+
+ // Initialize on first time through:
+ if(!VDInit){
+ for(i=0;i<(1<<K);i++){
+ sym = 0;
+ for(j=0;j<N;j++)
+ sym = (sym << 1) + parity(i & Polys[j]);
+ Syms[i] = sym;
+ }
+ VDInit++;
+ }
+
+ // Keep only lower K-1 bits of specified startstate and endstate
+ startstate &= ~((1<<(K-1)) - 1);
+ endstate &= ~((1<<(K-1)) - 1);
+
+ /* Initialize starting metrics */
+ for(i=0;i< 1<<(K-1);i++)
+ cmetric[i] = -999999;
+ cmetric[startstate] = 0;
+
+ pp = paths;
+ ipp=0;
+ for(;;){ /* For each data bit */
+ /* Read input symbols and compute branch metrics */
+ for(i=0;i< 1<<N;i++){
+ mets[i] = 0;
+ for(j=0;j<N;j++){
+ mets[i] += mettab[(i >> (N-j-1)) & 1][symbols[j]];
+ }
+ }
+ symbols += N;
+ /* Run the add-compare-select operations */
+ mask = 1;
+ for(i=0;i< 1 << (K-1);i+=2){
+ int b1,b2;
+
+ b1 = mets[Syms[i]];
+ nmetric[i] = m0 = cmetric[i/2] + b1;
+ b2 = mets[Syms[i+1]];
+ b1 -= b2;
+ m1 = cmetric[(i/2) + (1<<(K-2))] + b2;
+
+ if(m1 > m0){
+ nmetric[i] = m1;
+ *pp |= mask;
+ }
+
+ m0 -= b1;
+ nmetric[i+1] = m0;
+ m1 += b1;
+
+ if(m1 > m0){
+ nmetric[i+1] = m1;
+ *pp |= mask << 1;
+ }
+
+ mask <<= 2;
+ if(mask == 0){
+ mask = 1;
+ pp++;
+ ipp++;
+ }
+ }
+ if(mask != 1){
+ pp++;
+ ipp++;
+ }
+ if(++bitcnt == nbits){
+ *metric = nmetric[endstate];
+ break;
+ }
+ memcpy(cmetric,nmetric,sizeof(cmetric));
+ }
+
+ /* Chain back from terminal state to produce decoded data */
+ if(data == NULL)
+ return 0;/* Discard output */
+ memset(data,0,(nbits+7)/8); /* round up in case nbits % 8 != 0 */
+
+ for(i=nbits-1;i >= 0;i--){
+ // int a0,a1;
+ pp -= D;
+ ipp -= D;
+ m0=endstate >> LOGLONGBITS;
+ m1=1L << (endstate & (LONGBITS-1));
+ if(pp[m0] & m1) {
+ // a0=nmetric[endstate];
+ endstate |= (1 << (K-1));
+ // a1=nmetric[endstate];
+ data[i>>3] |= 0x80 >> (i&7);
+ // printf("B %d %d %d %d\n",*metric,i,a0,a1);
+ }
+ endstate >>= 1;
+ }
+ return 0;
+}
diff --git a/lib/wrapkarn.c b/lib/wrapkarn.c
new file mode 100644
index 0000000..1b1a631
--- /dev/null
+++ b/lib/wrapkarn.c
@@ -0,0 +1,70 @@
+#include <math.h>
+#include <stdio.h>
+#include <float.h>
+#include <limits.h>
+#include <stdlib.h>
+#include "rs.h"
+
+static void *rs;
+static int first=1;
+
+void rs_encode_(int *dgen, int *sent)
+// Encode JT65 data dgen[12], producing sent[63].
+{
+ int dat1[12];
+ int b[51];
+ int i;
+
+ if(first) {
+ // Initialize the JT65 codec
+ rs=init_rs_int(6,0x43,3,1,51,0);
+ first=0;
+ }
+
+ // Reverse data order for the Karn codec.
+ for(i=0; i<12; i++) {
+ dat1[i]=dgen[11-i];
+ }
+ // Compute the parity symbols
+ encode_rs_int(rs,dat1,b);
+
+ // Move parity symbols and data into sent[] array, in reverse order.
+ for (i = 0; i < 51; i++) sent[50-i] = b[i];
+ for (i = 0; i < 12; i++) sent[i+51] = dat1[11-i];
+}
+
+void rs_decode_(int *recd0, int *era0, int *numera0, int *decoded, int *nerr)
+// Decode JT65 received data recd0[63], producing decoded[12].
+// Erasures are indicated in era0[numera]. The number of corrected
+// errors is *nerr. If the data are uncorrectable, *nerr=-1 is returned.
+{
+ int numera;
+ int i;
+ int era_pos[50];
+ int recd[63];
+
+ if(first) {
+ rs=init_rs_int(6,0x43,3,1,51,0);
+ first=0;
+ }
+
+ numera=*numera0;
+ for(i=0; i<12; i++) recd[i]=recd0[62-i];
+ for(i=0; i<51; i++) recd[12+i]=recd0[50-i];
+ if(numera)
+ for(i=0; i<numera; i++) era_pos[i]=era0[i];
+ *nerr=decode_rs_int(rs,recd,era_pos,numera);
+ for(i=0; i<12; i++) decoded[i]=recd[11-i];
+}
+
+
+void rs_encode__(int *dgen, int *sent)
+{
+ rs_encode_(dgen, sent);
+}
+
+void rs_decode__(int *recd0, int *era0, int *numera0, int *decoded, int *nerr)
+{
+ rs_decode_(recd0, era0, numera0, decoded, nerr);
+}
+
diff --git a/lib/wsjt24.f90 b/lib/wsjt24.f90
new file mode 100644
index 0000000..574f1dd
--- /dev/null
+++ b/lib/wsjt24.f90
@@ -0,0 +1,181 @@
+subroutine wsjt24(dat,npts,cfile6,NClearAve,MinSigdB, &
+ DFTolerance,NFreeze,mode,mode4,Nseg,MouseDF,NAgain, &
+ idf,lumsg,lcum,nspecial,ndf,NSyncOK,ccfblue,ccfred,ndiag)
+
+! Orchestrates the process of decoding JT4 messages, using data that
+! have been 2x downsampled.
+! No message averaging and no deep search, at present.
+
+ parameter (MAXAVE=120)
+ real dat(npts) !Raw data
+ real*4 ccfblue(-5:540) !CCF in time
+ real*4 ccfred(-224:224) !CCF in frequency
+ integer DFTolerance
+ logical first
+ logical lcum
+ character decoded*22,cfile6*6,special*5,cooo*3
+ character*22 avemsg1,avemsg2,deepmsg
+ character*77 line,ave1,ave2
+ character*1 csync,c1
+ character*12 mycall
+ character*12 hiscall
+ character*6 hisgrid
+ character submode*1
+ real*4 ccfbluesum(-5:540),ccfredsum(-224:224)
+ common/ave/ppsave(207,7,MAXAVE),nflag(MAXAVE),nsave,iseg(MAXAVE)
+ data first/.true./,ns10/0/,ns20/0/
+ save
+
+ if(first) then
+ nsave=0
+ first=.false.
+ ave1=' '
+ ave2=' '
+ ccfblue=0.
+ ccfred=0.
+ if(nspecial.eq.999) go to 900 !Silence compiler warning
+ endif
+
+ ndepth=3 !###
+ naggressive=0
+ if(ndepth.ge.2) naggressive=1
+ nq1=3
+ nq2=6
+ if(naggressive.eq.1) nq1=1
+
+ if(NClearAve.ne.0) then
+ nsave=0 !Clear the averaging accumulators
+ ns10=0
+ ns20=0
+ ave1=' '
+ ave2=' '
+ endif
+ if(MinSigdB.eq.99 .or. MinSigdB.eq.-99) then
+ ns10=0 !For Include/Exclude ?
+ ns20=0
+ endif
+
+! Attempt to synchronize: look for sync pattern, get DF and DT.
+ call sync24(dat,npts,DFTolerance,NFreeze,MouseDF,mode, &
+ mode4,dtx,dfx,snrx,snrsync,ccfblue,ccfred,flip,width)
+
+ csync=' '
+ decoded=' '
+ deepmsg=' '
+ special=' '
+ cooo=' '
+ ncount=-1 !Flag for RS decode of current record
+ ncount1=-1 !Flag for RS Decode of ave1
+ ncount2=-1 !Flag for RS Decode of ave2
+ NSyncOK=0
+ nqual1=0
+ nqual2=0
+
+ if(nsave.lt.MAXAVE .and. (NAgain.eq.0 .or. NClearAve.eq.1)) nsave=nsave+1
+ if(nsave.le.0) go to 900 !Prevent bounds error
+
+ nflag(nsave)=0 !Clear the "good sync" flag
+ iseg(nsave)=Nseg !Set the RX segment to 1 or 2
+ nsync=nint(snrsync-3.0)
+ nsnr=nint(snrx)
+ if(nsnr.lt.-30 .or. nsync.lt.0) nsync=0
+ nsnrlim=-33
+ if(nsync.lt.MinSigdB .or. nsnr.lt.nsnrlim) go to 200
+
+! If we get here, we have achieved sync!
+ NSyncOK=1
+ nflag(nsave)=1 !Mark this RX file as good
+ csync='*'
+ if(flip.lt.0.0) then
+ csync='#'
+ cooo='O ?'
+ endif
+
+ call decode24(dat,npts,dtx,dfx,flip,mode,mode4,decoded, &
+ ncount,deepmsg,qual,submode)
+
+200 kvqual=0
+ if(ncount.ge.0) kvqual=1
+ nqual=qual
+ if(ndiag.eq.0 .and. nqual.gt.10) nqual=10
+ if(nqual.ge.nq1 .and.kvqual.eq.0) decoded=deepmsg
+
+ ndf=nint(dfx)
+ if(flip.lt.0.0 .and. (kvqual.eq.1 .or. nqual.ge.nq2)) cooo='OOO'
+ if(kvqual.eq.0.and.nqual.ge.nq1.and.nqual.lt.nq2) cooo(2:3)=' ?'
+ if(decoded.eq.' ') cooo=' '
+ do i=1,22
+ c1=decoded(i:i)
+ if(c1.ge.'a' .and. c1.le.'z') decoded(i:i)=char(ichar(c1)-32)
+ enddo
+ jdf=ndf+idf
+
+! call cs_lock('wsjt24')
+ write(line,1010) cfile6,nsync,nsnr,dtx-1.0,jdf,nint(width), &
+ csync,special,decoded(1:19),cooo,kvqual,nqual,submode
+1010 format(a6,i3,i5,f5.1,i5,i3,1x,a1,1x,a5,a19,1x,a3,i3,i5,1x,a1)
+
+! Blank all end-of-line stuff if no decode
+ if(line(31:40).eq.' ') line=line(:30)
+
+ if(lcum) write(21,1011) line
+
+! Write decoded msg unless this is an "Exclude" request:
+ if(MinSigdB.lt.99) write(*,1011) line
+1011 format(a77)
+
+ if(nsave.ge.1) call avemsg4(1,mode4,ndepth, &
+ avemsg1,nused1,nq1,nq2,neme,mycall,hiscall,hisgrid,qual1, &
+ ns1,ncount1)
+ if(nsave.ge.1) call avemsg4(2,mode4,ndepth, &
+ avemsg2,nused2,nq1,nq2,neme,mycall,hiscall,hisgrid,qual2, &
+ ns2,ncount2)
+ nqual1=qual1
+ nqual2=qual2
+ if(ndiag.eq.0 .and. nqual1.gt.10) nqual1=10
+ if(ndiag.eq.0 .and. nqual2.gt.10) nqual2=10
+ nc1=0
+ nc2=0
+ if(ncount1.ge.0) nc1=1
+ if(ncount2.ge.0) nc2=1
+
+! Write the average line
+ if(ns1.ge.1) then
+ if(ns1.lt.10) write(ave1,1021) cfile6,1,nused1,ns1,avemsg1,nc1,nqual1
+1021 format(a6,i3,i4,'/',i1,20x,a19,i7,i5)
+ if(ns1.ge.10 .and. nsave.le.99) write(ave1,1022) cfile6, &
+ 1,nused1,ns1,avemsg1,nc1,nqual1
+1022 format(a6,i3,i4,'/',i2,19x,a19,i7,i5)
+ if(ns1.ge.100) write(ave1,1023) cfile6,1,nused1,ns1, &
+ avemsg1,nc1,nqual1
+1023 format(a6,i3,i4,'/',i3,18x,a19,i7,i5)
+ if(lcum .and. (avemsg1.ne.' ')) &
+ write(21,1011) ave1
+ ns10=ns1
+ endif
+
+! If Monitor segment #2 is available, write that line also
+ if(ns2.ge.1) then
+ if(ns2.lt.10) write(ave2,1021) cfile6,2,nused2,ns2,avemsg2,nc2,nqual2
+ if(ns2.ge.10 .and. nsave.le.99) write(ave2,1022) cfile6, &
+ 2,nused2,ns2,avemsg2,nc2,nqual2
+ if(ns2.ge.100) write(ave2,1023) cfile6,2,nused2,ns2,avemsg2,nc2,nqual2
+ if(lcum .and. (avemsg2.ne.' ')) &
+ write(21,1011) ave2
+ ns20=ns2
+ endif
+
+ if(ave1(31:40).eq.' ') ave1=ave1(:30)
+ if(ave2(31:40).eq.' ') ave2=ave2(:30)
+ write(12,1011) ave1
+ write(12,1011) ave2
+ call flush(12)
+! call cs_unlock
+
+900 continue
+
+ ccfbluesum=ccfbluesum + ccfblue
+ ccfredsum=ccfredsum + ccfred
+
+ return
+end subroutine wsjt24
diff --git a/lib/wsjt24d.f90 b/lib/wsjt24d.f90
new file mode 100644
index 0000000..005e809
--- /dev/null
+++ b/lib/wsjt24d.f90
@@ -0,0 +1,43 @@
+program wsjt24d
+
+ real*4 dat(60*11025/2)
+ character*6 cfile6
+ character*12 arg
+ real ccfblue(-5:540) !X-cor function in JT65 mode (blue line)
+ real ccfred(450) !Average spectrum of the whole file
+ integer dftolerance
+
+ nargs=iargc()
+ if(nargs.ne.2) then
+ print*,'Usage: wspr24d ifile1 ifile2'
+ go to 999
+ endif
+ call getarg(1,arg)
+ read(arg,*) ifile1
+ call getarg(2,arg)
+ read(arg,*) ifile2
+
+ open(23,file='CALL3.TXT',status='old')
+ open(50,file='vk7mo.dat',form='unformatted',status='old')
+
+ do ifile=1,ifile2
+ read(50,end=999) jz,cfile6,NClearAve,MinSigdB,DFTolerance,NFreeze, &
+ mode,mode4,Nseg,MouseDF2,NAgain,idf,lumsg,lcum,nspecial,ndf, &
+ NSyncOK,dat(1:jz)
+ if(ifile.lt.ifile1) cycle
+
+! write(*,3000) ifile,cfile6,jz,mode,mode4,idf
+!3000 format(i3,2x,a6,i10,3i5)
+
+ dftolerance=100
+ nfreeze=1
+ neme=0
+
+! call wsjt24(dat(4097),jz-4096,cfile6,NClearAve,MinSigdB,DFTolerance, &
+ call wsjt24(dat,jz,cfile6,NClearAve,MinSigdB,DFTolerance, &
+ NFreeze,mode,mode4,Nseg,MouseDF2,NAgain,idf,lumsg,lcum,nspecial, &
+ ndf,NSyncOK,ccfblue,ccfred,ndiag)
+ if(ifile.ge.ifile2) exit
+ enddo
+
+999 end program wsjt24d
diff --git a/lib/xcor24.f90 b/lib/xcor24.f90
new file mode 100644
index 0000000..b76093b
--- /dev/null
+++ b/lib/xcor24.f90
@@ -0,0 +1,94 @@
+subroutine xcor24(s2,ipk,nsteps,nsym,lag1,lag2,mode4,ccf,ccf0,lagpk,flip)
+
+! Computes ccf of a row of s2 and the pseudo-random array pr2. Returns
+! peak of the CCF and the lag at which peak occurs. For JT65, the
+! CCF peak may be either positive or negative, with negative implying
+! the "OOO" message.
+
+ parameter (NHMAX=1260) !Max length of power spectra
+ parameter (NSMAX=525) !Max number of half-symbol steps
+ real s2(NHMAX,NSMAX) !2d spectrum, stepped by half-symbols
+ real a(NSMAX)
+ real ccf(-5:540)
+ integer npr2(207)
+ real pr2(207)
+ logical first
+ data lagmin/0/ !Silence g77 warning
+ data first/.true./
+ data npr2/ &
+ 0,0,0,0,1,1,0,0,0,1,1,0,1,1,0,0,1,0,1,0,0,0,0,0,0,0,1,1,0,0, &
+ 0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,1,1,0,1,0,1,1,1,1,1,0,1,0,0,0, &
+ 1,0,0,1,0,0,1,1,1,1,1,0,0,0,1,0,1,0,0,0,1,1,1,1,0,1,1,0,0,1, &
+ 0,0,0,1,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,1,1,0,1,0,1, &
+ 0,1,1,1,0,0,1,0,1,1,0,1,1,1,1,0,0,0,0,1,1,0,1,1,0,0,0,1,1,1, &
+ 0,1,1,1,0,1,1,1,0,0,1,0,0,0,1,1,0,1,1,0,0,1,0,0,0,1,1,1,1,1, &
+ 1,0,0,1,1,0,0,0,0,1,1,0,0,0,1,0,1,1,0,1,1,1,1,0,1,0,1/
+ save
+
+ if(first) then
+ do i=1,207
+ pr2(i)=2*npr2(i)-1
+ enddo
+ first=.false.
+ endif
+
+ do j=1,nsteps
+ n=2*mode4
+ if(mode4.eq.1) then
+ a(j)=max(s2(ipk+n,j),s2(ipk+3*n,j)) - max(s2(ipk ,j),s2(ipk+2*n,j))
+ else
+ kz=mode4/2
+ ss0=0.
+ ss1=0.
+ ss2=0.
+ ss3=0.
+ wsum=0.
+ do k=-kz+1,kz-1
+ w=float(kz-iabs(k))/mode4
+ wsum=wsum+w
+ if(ipk+k.lt.1 .or. ipk+3*n+k.gt.1260) then
+ print*,'xcor24:',ipk,n,k
+ else
+ ss0=ss0 + w*s2(ipk +k,j)
+ ss1=ss1 + w*s2(ipk+ n+k,j)
+ ss2=ss2 + w*s2(ipk+2*n+k,j)
+ ss3=ss3 + w*s2(ipk+3*n+k,j)
+ endif
+ enddo
+ a(j)=(max(ss1,ss3) - max(ss0,ss2))/sqrt(wsum)
+ endif
+ enddo
+
+ ccfmax=0.
+ ccfmin=0.
+ do lag=lag1,lag2
+ x=0.
+ do i=1,nsym
+ j=2*i-1+lag
+ if(j.ge.1 .and. j.le.nsteps) x=x+a(j)*pr2(i)
+ enddo
+ ccf(lag)=2*x !The 2 is for plotting scale
+ if(ccf(lag).gt.ccfmax) then
+ ccfmax=ccf(lag)
+ lagpk=lag
+ endif
+
+ if(ccf(lag).lt.ccfmin) then
+ ccfmin=ccf(lag)
+ lagmin=lag
+ endif
+ enddo
+
+ ccf0=ccfmax
+ flip=1.0
+ if(-ccfmin.gt.ccfmax) then
+ do lag=lag1,lag2
+ ccf(lag)=-ccf(lag)
+ enddo
+ lagpk=lagmin
+ ccf0=-ccfmin
+ flip=-1.0
+ endif
+
+ return
+end subroutine xcor24
diff --git a/lib/zplot9.f90 b/lib/zplot9.f90
new file mode 100644
index 0000000..6c56c9f
--- /dev/null
+++ b/lib/zplot9.f90
@@ -0,0 +1,31 @@
+subroutine zplot9(s,freq,drift)
+
+ real s(0:8,85)
+ character*1 line(85),mark(0:6)
+ data mark/' ',' ','.','-','+','X','$'/
+ include 'jt9sync.f90'
+
+ write(32,1000) freq,drift
+1000 format('Freq:',f7.1,' Drift:',f5.1,' ',60('-'))
+ do j=8,0,-1
+ do i=1,85
+ n=(s(j,i))
+ if(n.lt.0) n=0
+ if(n.gt.6) n=6
+ line(i)=mark(n)
+ enddo
+ write(32,1010) j,line
+1010 format(i1,1x,85a1)
+ enddo
+ do i=1,85
+ line(i)=' '
+ if(isync(i).eq.1) line(i)='@'
+ enddo
+ write(32,1015)
+1015 format(87('-'))
+ write(32,1020) line
+1020 format(2x,85a1)
+ call flush(32)
+
+ return
+end subroutine zplot9
diff --git a/logqso.cpp b/logqso.cpp
new file mode 100644
index 0000000..f5690a1
--- /dev/null
+++ b/logqso.cpp
@@ -0,0 +1,174 @@
+#include "logqso.h"
+#include "ui_logqso.h"
+#include <QString>
+#include <QDebug>
+
+
+LogQSO::LogQSO(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::LogQSO)
+{
+ ui->setupUi(this);
+}
+
+LogQSO::~LogQSO()
+{
+ delete ui;
+}
+
+void LogQSO::initLogQSO(QString hisCall, QString hisGrid, QString mode,
+ QString rptSent, QString rptRcvd, QDateTime dateTime,
+ double dialFreq, QString myCall, QString myGrid,
+ bool noSuffix, bool toRTTY, bool dBtoComments)
+{
+ ui->call->setText(hisCall);
+ ui->grid->setText(hisGrid);
+ ui->txPower->setText("");
+ ui->comments->setText("");
+ if(m_saveTxPower) ui->txPower->setText(m_txPower);
+ if(m_saveComments) ui->comments->setText(m_comments);
+ if(dBtoComments) {
+ QString t=mode;
+ if(rptSent!="") t+=" Sent: " + rptSent;
+ if(rptRcvd!="") t+=" Rcvd: " + rptRcvd;
+ ui->comments->setText(t);
+ }
+ if(noSuffix and mode.mid(0,3)=="JT9") mode="JT9";
+ if(toRTTY and mode.mid(0,3)=="JT9") mode="RTTY";
+ ui->mode->setText(mode);
+ ui->sent->setText(rptSent);
+ ui->rcvd->setText(rptRcvd);
+ m_dateTime=dateTime;
+ QString date=dateTime.toString("yyyy-MM-dd");
+ ui->date->setText(date);
+ QString time=dateTime.toString("hhmm");
+ ui->time->setText(time);
+ m_dialFreq=dialFreq;
+ m_myCall=myCall;
+ m_myGrid=myGrid;
+ QString band="";
+ if(dialFreq>0.135 and dialFreq<0.139) band="2200m";
+ if(dialFreq>0.45 and dialFreq<0.55) band="630m";
+ if(dialFreq>1.8 and dialFreq<2.0) band="160m";
+ if(dialFreq>3.5 and dialFreq<4.0) band="80m";
+ if(dialFreq>5.1 and dialFreq<5.45) band="60m";
+ if(dialFreq>7.0 and dialFreq<7.3) band="40m";
+ if(dialFreq>10.0 and dialFreq<10.15) band="30m";
+ if(dialFreq>14.0 and dialFreq<14.35) band="20m";
+ if(dialFreq>18.068 and dialFreq<18.168) band="17m";
+ if(dialFreq>21.0 and dialFreq<21.45) band="15m";
+ if(dialFreq>24.890 and dialFreq<24.990) band="12m";
+ if(dialFreq>28.0 and dialFreq<29.7) band="10m";
+ if(dialFreq>50.0 and dialFreq<54.0) band="6m";
+ if(dialFreq>70.0 and dialFreq<71.0) band="4m";
+ if(dialFreq>144.0 and dialFreq<148.0) band="2m";
+ if(dialFreq>222.0 and dialFreq<225.0) band="1.25m";
+ if(dialFreq>420.0 and dialFreq<450.0) band="70cm";
+ if(dialFreq>902.0 and dialFreq<928.0) band="33cm";
+ if(dialFreq>1240.0 and dialFreq<1300.0) band="23cm";
+ if(dialFreq>2300.0 and dialFreq<2450.0) band="13cm";
+ if(dialFreq>3300.0 and dialFreq<3500.0) band="9cm";
+ if(dialFreq>5650.0 and dialFreq<5925.0) band="6cm";
+ if(dialFreq>10000.0 and dialFreq<10500.0) band="3cm";
+ if(dialFreq>24000.0 and dialFreq<24250.0) band="1.25cm";
+ if(dialFreq>47000.0 and dialFreq<47200.0) band="6mm";
+ if(dialFreq>75500.0 and dialFreq<81000.0) band="4mm";
+ ui->band->setText(band);
+ ui->cbTxPower->setChecked(m_saveTxPower);
+ ui->cbComments->setChecked(m_saveComments);
+}
+
+void LogQSO::accept()
+{
+ QString hisCall,hisGrid,mode,rptSent,rptRcvd,date,time,band;
+ QString comments,name;
+
+ hisCall=ui->call->text();
+ hisGrid=ui->grid->text();
+ mode=ui->mode->text();
+ rptSent=ui->sent->text();
+ rptRcvd=ui->rcvd->text();
+ date=ui->date->text();
+ date=date.mid(0,4) + date.mid(5,2) + date.mid(8,2);
+ time=ui->time->text();
+ band=ui->band->text();
+ name=ui->name->text();
+ m_txPower=ui->txPower->text();
+ comments=ui->comments->text();
+ m_comments=comments;
+ QString strDialFreq(QString::number(m_dialFreq,'f',6));
+
+//Log this QSO to file "wsjtx_log.adi"
+ QFile f2("wsjtx_log.adi");
+ if(!f2.open(QIODevice::Text | QIODevice::Append)) {
+ QMessageBox m;
+ m.setText("Cannot open file \"wsjtx_log.adi\".");
+ m.exec();
+ } else {
+ QTextStream out(&f2);
+ if(f2.size()==0) out << "WSJT-X ADIF Export<eoh>" << endl;
+
+ QString t;
+ t="<call:" + QString::number(hisCall.length()) + ">" + hisCall;
+ t+=" <gridsquare:" + QString::number(hisGrid.length()) + ">" + hisGrid;
+ t+=" <mode:" + QString::number(mode.length()) + ">" + mode;
+ t+=" <rst_sent:" + QString::number(rptSent.length()) + ">" + rptSent;
+ t+=" <rst_rcvd:" + QString::number(rptRcvd.length()) + ">" + rptRcvd;
+ t+=" <qso_date:8>" + date;
+ t+=" <time_on:4>" + time;
+ t+=" <band:" + QString::number(band.length()) + ">" + band;
+ t+=" <freq:" + QString::number(strDialFreq.length()) + ">" + strDialFreq;
+ t+=" <station_callsign:" + QString::number(m_myCall.length()) + ">" +
+ m_myCall;
+ t+=" <my_gridsquare:" + QString::number(m_myGrid.length()) + ">" +
+ m_myGrid;
+ if(m_txPower!="") t+= " <tx_pwr:" + QString::number(m_txPower.length()) +
+ ">" + m_txPower;
+ if(comments!="") t+=" <comment:" + QString::number(comments.length()) +
+ ">" + comments;
+ if(name!="") t+=" <name:" + QString::number(name.length()) +
+ ">" + name;
+ t+=" <eor>";
+ out << t << endl;
+ f2.close();
+ }
+
+//Log this QSO to file "wsjtx.log"
+ QFile f("wsjtx.log");
+ if(!f.open(QIODevice::Text | QIODevice::Append)) {
+ QMessageBox m;
+ m.setText("Cannot open file \"wsjtx.log\".");
+ m.exec();
+ } else {
+ QString logEntry=m_dateTime.date().toString("yyyy-MMM-dd,") +
+ m_dateTime.time().toString("hh:mm,") + hisCall + "," +
+ hisGrid + "," + strDialFreq + "," + mode +
+ "," + rptSent + "," + rptRcvd;
+ if(m_txPower!="") logEntry += "," + m_txPower;
+ if(comments!="") logEntry += "," + comments;
+ if(name!="") logEntry += "," + name;
+ QTextStream out(&f);
+ out << logEntry << endl;
+ f.close();
+ }
+
+//Clean up and finish logging
+ emit(acceptQSO(true));
+ QDialog::accept();
+}
+
+void LogQSO::reject()
+{
+ emit(acceptQSO(false));
+ QDialog::reject();
+}
+
+void LogQSO::on_cbTxPower_toggled(bool checked)
+{
+ m_saveTxPower=checked;
+}
+
+void LogQSO::on_cbComments_toggled(bool checked)
+{
+ m_saveComments=checked;
+}
diff --git a/logqso.h b/logqso.h
new file mode 100644
index 0000000..06b2edf
--- /dev/null
+++ b/logqso.h
@@ -0,0 +1,53 @@
+#ifndef LogQSO_H
+#define LogQSO_H
+
+#ifdef QT5
+#include <QtWidgets>
+#else
+#include <QtGui>
+#endif
+
+namespace Ui {
+class LogQSO;
+}
+
+class LogQSO : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit LogQSO(QWidget *parent = 0);
+ ~LogQSO();
+ void initLogQSO(QString hisCall, QString hisGrid, QString mode,
+ QString rptSent, QString rptRcvd, QDateTime dateTime,
+ double dialFreq, QString myCall, QString myGrid,
+ bool noSuffix, bool toRTTY, bool dBtoComments);
+
+ double m_dialFreq;
+
+ bool m_saveTxPower;
+ bool m_saveComments;
+
+ QString m_myCall;
+ QString m_myGrid;
+ QString m_txPower;
+ QString m_comments;
+
+ QDateTime m_dateTime;
+
+public slots:
+ void accept();
+ void reject();
+
+signals:
+ void acceptQSO(bool accepted);
+
+private slots:
+ void on_cbTxPower_toggled(bool checked);
+ void on_cbComments_toggled(bool checked);
+
+private:
+ Ui::LogQSO *ui;
+};
+
+#endif // LogQSO_H
diff --git a/logqso.ui b/logqso.ui
new file mode 100644
index 0000000..a9c6fe9
--- /dev/null
+++ b/logqso.ui
@@ -0,0 +1,759 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>LogQSO</class>
+ <widget class="QDialog" name="LogQSO">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>372</width>
+ <height>305</height>
+ </rect>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>Log QSO</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <spacer name="verticalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::MinimumExpanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Click OK to confirm the following QSO:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::MinimumExpanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_5">
+ <item>
+ <widget class="QLabel" name="lab1">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>70</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>70</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Call</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lab2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>100</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Date</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lab3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <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>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Time</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lab4">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <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>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Mode</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lab5">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <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>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Band</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="QLineEdit" name="call">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>70</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>70</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="date">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>100</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="time">
+ <property name="minimumSize">
+ <size>
+ <width>50</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="mode">
+ <property name="sizePolicy">
+ <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>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="band">
+ <property name="sizePolicy">
+ <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>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::MinimumExpanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QLabel" name="lab6">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <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>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Rpt Sent</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lab7">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <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>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Rpt Rcvd</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lab8">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <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>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Grid</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lab9">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>100</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Name</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLineEdit" name="sent">
+ <property name="sizePolicy">
+ <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>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="rcvd">
+ <property name="sizePolicy">
+ <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>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="grid">
+ <property name="sizePolicy">
+ <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>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="name">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>100</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::MinimumExpanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_6">
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="minimumSize">
+ <size>
+ <width>65</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Tx power</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="txPower"/>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbTxPower">
+ <property name="text">
+ <string>Retain</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::MinimumExpanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="lab10">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>65</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Comments</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="comments">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="cbComments">
+ <property name="text">
+ <string>Retain</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>call</tabstop>
+ <tabstop>date</tabstop>
+ <tabstop>time</tabstop>
+ <tabstop>mode</tabstop>
+ <tabstop>band</tabstop>
+ <tabstop>sent</tabstop>
+ <tabstop>rcvd</tabstop>
+ <tabstop>grid</tabstop>
+ <tabstop>name</tabstop>
+ <tabstop>txPower</tabstop>
+ <tabstop>cbTxPower</tabstop>
+ <tabstop>comments</tabstop>
+ <tabstop>cbComments</tabstop>
+ <tabstop>buttonBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>LogQSO</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>LogQSO</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..add1ab1
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,60 @@
+#ifdef QT5
+#include <QtWidgets>
+#else
+#include <QtGui>
+#endif
+#include <QApplication>
+#include <portaudio.h>
+#include "mainwindow.h"
+
+// Multiple instances:
+QSharedMemory mem_jt9;
+QUuid my_uuid;
+QString my_key;
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+
+ QFile f("fonts.txt");
+ if(f.open(QIODevice::ReadOnly)) {
+ QTextStream in(&f); //Example:
+ QString fontFamily; // helvetica
+ qint32 fontSize,fontWeight; // 8,50
+ in >> fontFamily >> fontSize >> fontWeight;
+ f.close();
+ QFont font;
+ font=QFont(fontFamily,fontSize,fontWeight);
+ a.setFont(font);
+ }
+
+ // Create and initialize shared memory segment
+ // Multiple instances: generate shared memory keys with UUID
+ my_uuid = QUuid::createUuid();
+ my_key = my_uuid.toString();
+ mem_jt9.setKey(my_key);
+
+ if(!mem_jt9.attach()) {
+ if (!mem_jt9.create(sizeof(jt9com_))) {
+ QMessageBox::critical( 0, "Error", "Unable to create shared memory segment.");
+ exit(1);
+ }
+ }
+ char *to = (char*)mem_jt9.data();
+ int size=sizeof(jt9com_);
+ if(jt9com_.newdat==0) {
+ }
+ memset(to,0,size); //Zero all decoding params in shared memory
+
+ //Initialize Portaudio
+ PaError paerr=Pa_Initialize();
+ if(paerr!=paNoError) {
+ QMessageBox::critical( 0, "Error", "Unable to initialize PortAudio.");
+ exit(1);
+ }
+
+// Multiple instances: Call MainWindow() with the UUID key
+ MainWindow w(&mem_jt9, &my_key);
+ w.show();
+ return a.exec();
+}
diff --git a/mainwindow.cpp b/mainwindow.cpp
new file mode 100644
index 0000000..7b50ec8
--- /dev/null
+++ b/mainwindow.cpp
@@ -0,0 +1,3052 @@
+//------------------------------------------------------------- MainWindow
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+#include "devsetup.h"
+#include "plotter.h"
+#include "about.h"
+#include "widegraph.h"
+#include "sleep.h"
+#include "getfile.h"
+#include <portaudio.h>
+#include "logqso.h"
+
+#ifdef QT5
+#include <QtConcurrent/QtConcurrentMap>
+#include <QtConcurrent/QtConcurrentRun>
+#endif
+
+int itone[126]; //Audio tones for all Tx symbols
+int icw[250]; //Dits for CW ID
+int outBufSize;
+int rc;
+qint32 g_COMportOpen;
+qint32 g_iptt;
+static int nc1=1;
+wchar_t buffer[256];
+bool btxok; //True if OK to transmit
+bool btxMute;
+double outputLatency; //Latency in seconds
+double dFreq[]={0.13613,0.4742,1.838,3.576,5.357,7.076,10.138,14.076,
+ 18.102,21.076,24.917,28.076,50.276,70.091,144.489,432.178};
+
+WideGraph* g_pWideGraph = NULL;
+LogQSO* logDlg = NULL;
+Rig* rig = NULL;
+QTextEdit* pShortcuts;
+QTcpSocket* socket = new QTcpSocket(0);
+
+QString rev="$Rev: 3496 $";
+QString Program_Title_Version=" WSJT-X v1.1, r" + rev.mid(6,4) +
+ " by K1JT";
+
+//-------------------------------------------------- MainWindow constructor
+// Multiple instances: new arg *thekey
+MainWindow::MainWindow(QSharedMemory *shdmem, QString *thekey, QWidget *parent) :
+ QMainWindow(parent),
+ ui(new Ui::MainWindow)
+{
+ ui->setupUi(this);
+ on_EraseButton_clicked();
+ QActionGroup* paletteGroup = new QActionGroup(this);
+ ui->actionCuteSDR->setActionGroup(paletteGroup);
+ ui->actionLinrad->setActionGroup(paletteGroup);
+ ui->actionAFMHot->setActionGroup(paletteGroup);
+ ui->actionBlue->setActionGroup(paletteGroup);
+
+ QActionGroup* modeGroup = new QActionGroup(this);
+ ui->actionJT9_1->setActionGroup(modeGroup);
+ ui->actionJT65->setActionGroup(modeGroup);
+ ui->actionJT9_JT65->setActionGroup(modeGroup);
+
+
+ QActionGroup* saveGroup = new QActionGroup(this);
+ ui->actionNone->setActionGroup(saveGroup);
+ ui->actionSave_decoded->setActionGroup(saveGroup);
+ ui->actionSave_all->setActionGroup(saveGroup);
+
+ QActionGroup* DepthGroup = new QActionGroup(this);
+ ui->actionQuickDecode->setActionGroup(DepthGroup);
+ ui->actionMediumDecode->setActionGroup(DepthGroup);
+ ui->actionDeepestDecode->setActionGroup(DepthGroup);
+
+ QButtonGroup* txMsgButtonGroup = new QButtonGroup;
+ txMsgButtonGroup->addButton(ui->txrb1,1);
+ txMsgButtonGroup->addButton(ui->txrb2,2);
+ txMsgButtonGroup->addButton(ui->txrb3,3);
+ txMsgButtonGroup->addButton(ui->txrb4,4);
+ txMsgButtonGroup->addButton(ui->txrb5,5);
+ txMsgButtonGroup->addButton(ui->txrb6,6);
+ connect(txMsgButtonGroup,SIGNAL(buttonClicked(int)),SLOT(set_ntx(int)));
+ connect(ui->decodedTextBrowser2,SIGNAL(selectCallsign(bool,bool)),this,
+ SLOT(doubleClickOnCall(bool,bool)));
+ connect(ui->decodedTextBrowser,SIGNAL(selectCallsign(bool,bool)),this,
+ SLOT(doubleClickOnCall2(bool,bool)));
+
+ setWindowTitle(Program_Title_Version);
+ connect(&soundInThread, SIGNAL(readyForFFT(int)),
+ this, SLOT(dataSink(int)));
+ connect(&soundInThread, SIGNAL(error(QString)), this,
+ SLOT(showSoundInError(QString)));
+ connect(&soundInThread, SIGNAL(status(QString)), this,
+ SLOT(showStatusMessage(QString)));
+ createStatusBar();
+
+ connect(&proc_jt9, SIGNAL(readyReadStandardOutput()),
+ this, SLOT(readFromStdout()));
+
+ connect(&proc_jt9, SIGNAL(error(QProcess::ProcessError)),
+ this, SLOT(jt9_error()));
+
+ connect(&proc_jt9, SIGNAL(readyReadStandardError()),
+ this, SLOT(readFromStderr()));
+
+ ui->bandComboBox->setEditable(true);
+ ui->bandComboBox->lineEdit()->setReadOnly(true);
+ ui->bandComboBox->lineEdit()->setAlignment(Qt::AlignCenter);
+ for(int i = 0; i < ui->bandComboBox->count(); i++)
+ ui->bandComboBox->setItemData(i, Qt::AlignCenter, Qt::TextAlignmentRole);
+
+ ui->tx5->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(ui->tx5, SIGNAL(customContextMenuRequested(const QPoint&)),
+ this, SLOT(showMacros(const QPoint&)));
+
+ ui->freeTextMsg->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(ui->freeTextMsg, SIGNAL(customContextMenuRequested(const QPoint&)),
+ this, SLOT(showMacros(const QPoint&)));
+
+ QTimer *guiTimer = new QTimer(this);
+ connect(guiTimer, SIGNAL(timeout()), this, SLOT(guiUpdate()));
+ guiTimer->start(100); //Don't change the 100 ms!
+ ptt0Timer = new QTimer(this);
+ ptt0Timer->setSingleShot(true);
+ connect(ptt0Timer, SIGNAL(timeout()), this, SLOT(stopTx2()));
+ ptt1Timer = new QTimer(this);
+ ptt1Timer->setSingleShot(true);
+ connect(ptt1Timer, SIGNAL(timeout()), this, SLOT(startTx2()));
+
+ logQSOTimer = new QTimer(this);
+ logQSOTimer->setSingleShot(true);
+ connect(logQSOTimer, SIGNAL(timeout()), this, SLOT(on_logQSOButton_clicked()));
+
+ tuneButtonTimer= new QTimer(this);
+ tuneButtonTimer->setSingleShot(true);
+ connect(tuneButtonTimer, SIGNAL(timeout()), this,
+ SLOT(on_stopTxButton_clicked()));
+
+ killFileTimer = new QTimer(this);
+ killFileTimer->setSingleShot(true);
+ connect(killFileTimer, SIGNAL(timeout()), this, SLOT(killFile()));
+
+ m_auto=false;
+ m_waterfallAvg = 1;
+ m_txFirst=false;
+ btxMute=false;
+ btxok=false;
+ m_restart=false;
+ m_transmitting=false;
+ m_killAll=false;
+ m_widebandDecode=false;
+ m_ntx=1;
+ m_myCall="";
+ m_myGrid="FN20qi";
+ m_appDir = QApplication::applicationDirPath();
+ m_saveDir="/users/joe/wsjtx/install/save";
+ m_rxFreq=1500;
+ m_txFreq=1500;
+ m_setftx=0;
+ m_loopall=false;
+ m_startAnother=false;
+ m_saveDecoded=false;
+ m_saveAll=false;
+ m_sec0=-1;
+ m_palette="Linrad";
+ m_RxLog=1; //Write Date and Time to RxLog
+ m_nutc0=9999;
+ m_mode="JT9";
+ m_rpt="-15";
+ m_TRperiod=60;
+ m_inGain=0;
+ m_dataAvailable=false;
+ g_iptt=0;
+ g_COMportOpen=0;
+ m_secID=0;
+ m_promptToLog=false;
+ m_blankLine=false;
+ m_insertBlank=false;
+ m_clearCallGrid=false;
+ m_bMiles=false;
+ m_decodedText2=false;
+ m_freeText=false;
+ m_msErase=0;
+ m_sent73=false;
+ m_watchdogLimit=5;
+ m_tune=false;
+ m_repeatMsg=0;
+ m_bRigOpen=false;
+ m_secBandChanged=0;
+ m_bMultipleOK=false;
+ m_dontReadFreq=false;
+ m_lockTxFreq=false;
+ ui->readFreq->setEnabled(false);
+ m_QSOmsg="";
+ m_CATerror=false;
+ decodeBusy(false);
+
+ signalMeter = new SignalMeter(ui->meterFrame);
+ signalMeter->resize(50, 160);
+
+// qDebug() << signalMeter->size();
+
+ ui->labAz->setStyleSheet("border: 0px;");
+ ui->labDist->setStyleSheet("border: 0px;");
+
+ mem_jt9 = shdmem;
+// Multiple instances:
+ mykey_jt9 = thekey;
+ readSettings(); //Restore user's setup params
+ if(m_dFreq.length()<=1) { //Use the startup default frequencies
+ m_dFreq.clear();
+ for(int i=0; i<16; i++) {
+ QString t;
+ t.sprintf("%f",dFreq[i]);
+ m_dFreq.append(t);
+ }
+ }
+
+#ifdef WIN32
+ if(!m_bMultipleOK) {
+ while(true) {
+ int iret=killbyname("jt9.exe");
+ if(iret == 603) break;
+ if(iret != 0) msgBox("KillByName return code: " +
+ QString::number(iret));
+ }
+ }
+#endif
+
+ QFile lockFile(m_appDir + "/.lock"); //Create .lock so jt9 will wait
+ lockFile.open(QIODevice::ReadWrite);
+ //QFile quitFile(m_appDir + "/.lock");
+ //quitFile.remove();
+
+// Multiple instances: make the Qstring key into command line arg
+// Multiple instances: start "jt9 -s <thekey>"
+ QByteArray ba = mykey_jt9->toLocal8Bit();
+ const char *bc = ba.data();
+ proc_jt9.start(QDir::toNativeSeparators('"' + m_appDir + '"' + "/jt9 -s " + bc));
+
+ m_pbdecoding_style1="QPushButton{background-color: cyan; \
+ border-style: outset; border-width: 1px; border-radius: 5px; \
+ border-color: black; min-width: 5em; padding: 3px;}";
+ m_pbmonitor_style="QPushButton{background-color: #00ff00; \
+ border-style: outset; border-width: 1px; border-radius: 5px; \
+ border-color: black; min-width: 5em; padding: 3px;}";
+ m_pbAutoOn_style="QPushButton{background-color: red; \
+ border-style: outset; border-width: 1px; border-radius: 5px; \
+ border-color: black; min-width: 5em; padding: 3px;}";
+ m_pbTune_style="QPushButton{background-color: red; \
+ border-style: outset; border-width: 1px; border-radius: 5px; \
+ border-color: black; min-width: 5em; padding: 3px;}";
+
+ genStdMsgs(m_rpt);
+ if(m_mode!="JT9" and m_mode!="JT65" and m_mode!="JT9+JT65") m_mode="JT9";
+ on_actionWide_Waterfall_triggered(); //###
+ g_pWideGraph->setRxFreq(m_rxFreq);
+ g_pWideGraph->setTxFreq(m_txFreq);
+ g_pWideGraph->setLockTxFreq(m_lockTxFreq);
+ g_pWideGraph->setFmin(m_fMin);
+ g_pWideGraph->setModeTx(m_mode);
+ g_pWideGraph->setModeTx(m_modeTx);
+ dialFreqChanged2(m_dialFreq);
+
+ connect(g_pWideGraph, SIGNAL(setFreq3(int,int)),this,
+ SLOT(setFreq4(int,int)));
+
+ if(m_mode=="JT9") on_actionJT9_1_triggered();
+ if(m_mode=="JT65") on_actionJT65_triggered();
+ if(m_mode=="JT9+JT65") on_actionJT9_JT65_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()));
+
+ soundInThread.setInputDevice(m_paInDevice);
+ soundInThread.start(QThread::HighestPriority);
+ soundOutThread.setOutputDevice(m_paOutDevice);
+ soundOutThread.setTxFreq(m_txFreq);
+ soundOutThread.setTune(false);
+ m_monitoring=!m_monitorStartOFF; // Start with Monitoring ON/OFF
+ soundInThread.setMonitoring(m_monitoring);
+ m_diskData=false;
+
+// Create "m_worked", a dictionary of all calls in wsjtx.log
+ QFile f("wsjtx.log");
+ f.open(QIODevice::ReadOnly | QIODevice::Text);
+ QTextStream in(&f);
+ QString line,t,callsign;
+ for(int i=0; i<99999; i++) {
+ line=in.readLine();
+ if(line.length()<=0) break;
+ t=line.mid(18,12);
+ callsign=t.mid(0,t.indexOf(","));
+ }
+ f.close();
+
+ if(ui->actionLinrad->isChecked()) on_actionLinrad_triggered();
+ if(ui->actionCuteSDR->isChecked()) on_actionCuteSDR_triggered();
+ if(ui->actionAFMHot->isChecked()) on_actionAFMHot_triggered();
+ if(ui->actionBlue->isChecked()) on_actionBlue_triggered();
+
+ ui->decodedTextLabel->setFont(ui->decodedTextBrowser2->font());
+ ui->decodedTextLabel2->setFont(ui->decodedTextBrowser->font());
+ t="UTC dB DT Freq Message";
+ ui->decodedTextLabel->setText(t);
+ ui->decodedTextLabel2->setText(t);
+
+#ifdef WIN32
+ if(m_pskReporter) {
+ rc=ReporterInitialize(NULL,NULL);
+ if(rc==0) {
+ m_pskReporterInit=true;
+ } else {
+ m_pskReporterInit=false;
+ rc=ReporterGetInformation(buffer,256);
+ msgBox(QString::fromStdWString(buffer));
+ }
+ }
+#endif
+
+#ifdef UNIX
+ psk_Reporter = new PSK_Reporter(this);
+ psk_Reporter->setLocalStation(m_myCall,m_myGrid, "WSJT-X r" + rev.mid(6,4) );
+#endif
+
+ ui->label_9->setStyleSheet("QLabel{background-color: #aabec8}");
+ ui->label_10->setStyleSheet("QLabel{background-color: #aabec8}");
+ ui->labUTC->setStyleSheet( \
+ "QLabel { background-color : black; color : yellow; }");
+ ui->labDialFreq->setStyleSheet( \
+ "QLabel { background-color : black; color : yellow; }");
+
+ QFile f2("ALL.TXT");
+ f2.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
+ QTextStream out(&f2);
+ out << QDateTime::currentDateTimeUtc().toString("yyyy-MMM-dd hh:mm")
+ << " " << m_dialFreq << " MHz " << m_mode << endl;
+ f2.close();
+} // End of MainWindow constructor
+
+//--------------------------------------------------- MainWindow destructor
+MainWindow::~MainWindow()
+{
+ writeSettings();
+ if (soundInThread.isRunning()) {
+ soundInThread.quit();
+ soundInThread.wait(3000);
+ }
+ if (soundOutThread.isRunning()) {
+ soundOutThread.quitExecution=true;
+ soundOutThread.wait(3000);
+ }
+ if(!m_decoderBusy) {
+ QFile lockFile(m_appDir + "/.lock");
+ lockFile.remove();
+ }
+ delete ui;
+}
+
+//-------------------------------------------------------- writeSettings()
+void MainWindow::writeSettings()
+{
+ QString inifile = m_appDir + "/wsjtx.ini";
+ QSettings settings(inifile, QSettings::IniFormat);
+
+ settings.beginGroup("MainWindow");
+ settings.setValue("geometry", saveGeometry());
+ settings.setValue("MRUdir", m_path);
+ settings.setValue("TxFirst",m_txFirst);
+ settings.setValue("DXcall",ui->dxCallEntry->text());
+ settings.setValue("DXgrid",ui->dxGridEntry->text());
+ if(g_pWideGraph->isVisible()) {
+ m_wideGraphGeom = g_pWideGraph->geometry();
+ settings.setValue("WideGraphGeom",m_wideGraphGeom);
+ m_fMin=g_pWideGraph->getFmin();
+ }
+ settings.endGroup();
+
+ settings.beginGroup("Common");
+ settings.setValue("MyCall",m_myCall);
+ settings.setValue("MyGrid",m_myGrid);
+ settings.setValue("IDint",m_idInt);
+ settings.setValue("PTTmethod",m_pttMethodIndex);
+ settings.setValue("PTTport",m_pttPort);
+ settings.setValue("SaveDir",m_saveDir);
+ char soundName[128];
+ if (Pa_GetDeviceInfo( m_paInDevice)) { // store name, number may be different next time
+ snprintf( soundName, sizeof( soundName), "%s:%s",
+ Pa_GetHostApiInfo( Pa_GetDeviceInfo( m_paInDevice)->hostApi)->name,
+ Pa_GetDeviceInfo( m_paInDevice)->name);
+ settings.setValue("SoundInName", soundName);
+ }
+ if (Pa_GetDeviceInfo( m_paOutDevice)) { // store name, number may be different next time
+ snprintf( soundName, sizeof( soundName), "%s:%s",
+ Pa_GetHostApiInfo( Pa_GetDeviceInfo( m_paOutDevice)->hostApi)->name,
+ Pa_GetDeviceInfo( m_paOutDevice)->name);
+ settings.setValue("SoundOutName", soundName);
+ }
+ settings.setValue("PaletteCuteSDR",ui->actionCuteSDR->isChecked());
+ settings.setValue("PaletteLinrad",ui->actionLinrad->isChecked());
+ settings.setValue("PaletteAFMHot",ui->actionAFMHot->isChecked());
+ settings.setValue("PaletteBlue",ui->actionBlue->isChecked());
+ settings.setValue("Mode",m_mode);
+ settings.setValue("ModeTx",m_modeTx);
+ settings.setValue("SaveNone",ui->actionNone->isChecked());
+ settings.setValue("SaveDecoded",ui->actionSave_decoded->isChecked());
+ settings.setValue("SaveAll",ui->actionSave_all->isChecked());
+ settings.setValue("NDepth",m_ndepth);
+ settings.setValue("MonitorOFF",m_monitorStartOFF);
+ settings.setValue("DialFreq",m_dialFreq);
+ settings.setValue("RxFreq",m_rxFreq);
+ settings.setValue("TxFreq",m_txFreq);
+ settings.setValue("InGain",m_inGain);
+ settings.setValue("PSKReporter",m_pskReporter);
+ settings.setValue("After73",m_After73);
+ settings.setValue("Macros",m_macro);
+ settings.setValue("DefaultFreqs",m_dFreq);
+ settings.setValue("toRTTY",m_toRTTY);
+ settings.setValue("NoSuffix",m_noSuffix);
+ settings.setValue("dBtoComments",m_dBtoComments);
+ settings.setValue("catEnabled",m_catEnabled);
+ settings.setValue("Rig",m_rig);
+ settings.setValue("RigIndex",m_rigIndex);
+ settings.setValue("CATport",m_catPort);
+ settings.setValue("CATportIndex",m_catPortIndex);
+ settings.setValue("SerialRate",m_serialRate);
+ settings.setValue("SerialRateIndex",m_serialRateIndex);
+ settings.setValue("DataBits",m_dataBits);
+ settings.setValue("DataBitsIndex",m_dataBitsIndex);
+ settings.setValue("StopBits",m_stopBits);
+ settings.setValue("StopBitsIndex",m_stopBitsIndex);
+ settings.setValue("Handshake",m_handshake);
+ settings.setValue("HandshakeIndex",m_handshakeIndex);
+ settings.setValue("BandIndex",m_band);
+ settings.setValue("PromptToLog",m_promptToLog);
+ settings.setValue("InsertBlank",m_insertBlank);
+ settings.setValue("ClearCallGrid",m_clearCallGrid);
+ settings.setValue("Miles",m_bMiles);
+ settings.setValue("GUItab",ui->tabWidget->currentIndex());
+ settings.setValue("QuickCall",m_quickCall);
+ settings.setValue("73TxDisable",m_73TxDisable);
+ settings.setValue("Runaway",m_runaway);
+ settings.setValue("Tx2QSO",m_tx2QSO);
+ settings.setValue("MultipleOK",m_bMultipleOK);
+ settings.setValue("DTRoff",m_bDTRoff);
+ settings.setValue("pttData",m_pttData);
+ settings.setValue("LogQSOgeom",m_logQSOgeom);
+ settings.setValue("Polling",m_poll);
+ settings.setValue("OutBufSize",outBufSize);
+ settings.setValue("LockTxFreq",m_lockTxFreq);
+ settings.setValue("SaveTxPower",m_saveTxPower);
+ settings.setValue("SaveComments",m_saveComments);
+ settings.setValue("TxPower",m_txPower);
+ settings.setValue("LogComments",m_logComments);
+ settings.setValue("PSKantenna",m_pskAntenna);
+ settings.setValue("Fmin",m_fMin);
+ settings.setValue("TxSplit",m_bSplit);
+ settings.setValue("UseXIT",m_bXIT);
+ settings.setValue("Plus2kHz",m_plus2kHz);
+ settings.endGroup();
+}
+
+//---------------------------------------------------------- readSettings()
+void MainWindow::readSettings()
+{
+ QString inifile = m_appDir + "/wsjtx.ini";
+ QSettings settings(inifile, QSettings::IniFormat);
+ settings.beginGroup("MainWindow");
+ restoreGeometry(settings.value("geometry").toByteArray());
+ ui->dxCallEntry->setText(settings.value("DXcall","").toString());
+ ui->dxGridEntry->setText(settings.value("DXgrid","").toString());
+ m_wideGraphGeom = settings.value("WideGraphGeom", \
+ QRect(45,30,726,301)).toRect();
+ m_path = settings.value("MRUdir", m_appDir + "/save").toString();
+ m_txFirst = settings.value("TxFirst",false).toBool();
+ ui->txFirstCheckBox->setChecked(m_txFirst);
+ settings.endGroup();
+
+ settings.beginGroup("Common");
+ m_myCall=settings.value("MyCall","").toString();
+ morse_(m_myCall.toLatin1().data(),icw,&m_ncw,m_myCall.length());
+ m_myGrid=settings.value("MyGrid","").toString();
+ m_idInt=settings.value("IDint",0).toInt();
+ m_pttMethodIndex=settings.value("PTTmethod",1).toInt();
+ m_pttPort=settings.value("PTTport",0).toInt();
+ m_saveDir=settings.value("SaveDir",m_appDir + "/save").toString();
+
+ char soundName[128];
+ QString savedName = settings.value( "SoundInName", "default").toString();
+ for (m_paInDevice = Pa_GetDeviceCount() - 1; m_paInDevice >= 0; m_paInDevice--) {
+ snprintf( soundName, sizeof( soundName), "%s:%s",
+ Pa_GetHostApiInfo( Pa_GetDeviceInfo( m_paInDevice)->hostApi)->name,
+ Pa_GetDeviceInfo( m_paInDevice)->name);
+ if ((savedName == soundName) && (Pa_GetDeviceInfo(m_paInDevice)->maxInputChannels > 0))
+ break;
+ }
+ if (m_paInDevice < 0) { // no match for device name?
+ m_paInDevice = Pa_GetDefaultInputDevice();
+ if (m_paInDevice == paNoDevice) // no default input device?
+ m_paInDevice = 0;
+ }
+
+ savedName = settings.value("SoundOutName", "default").toString();
+ for (m_paOutDevice = Pa_GetDeviceCount() - 1; m_paOutDevice >= 0; m_paOutDevice--) {
+ snprintf( soundName, sizeof( soundName), "%s:%s",
+ Pa_GetHostApiInfo( Pa_GetDeviceInfo( m_paOutDevice)->hostApi)->name,
+ Pa_GetDeviceInfo( m_paOutDevice)->name);
+ if ((savedName == soundName) && (Pa_GetDeviceInfo(m_paOutDevice)->maxOutputChannels > 0))
+ break;
+ }
+ if (m_paOutDevice < 0) { // no match for device name?
+ m_paOutDevice = Pa_GetDefaultOutputDevice();
+ if (m_paOutDevice == paNoDevice) // no default output device?
+ m_paOutDevice = 0;
+ }
+
+ ui->actionCuteSDR->setChecked(settings.value(
+ "PaletteCuteSDR",false).toBool());
+ ui->actionLinrad->setChecked(settings.value(
+ "PaletteLinrad",true).toBool());
+ ui->actionAFMHot->setChecked(settings.value(
+ "PaletteAFMHot",false).toBool());
+ ui->actionBlue->setChecked(settings.value(
+ "PaletteBlue",false).toBool());
+ m_mode=settings.value("Mode","JT9").toString();
+ m_modeTx=settings.value("ModeTx","JT9").toString();
+ if(m_modeTx=="JT9") ui->pbTxMode->setText("Tx JT9 @");
+ if(m_modeTx=="JT65") ui->pbTxMode->setText("Tx JT65 #");
+ ui->actionNone->setChecked(settings.value("SaveNone",true).toBool());
+ ui->actionSave_decoded->setChecked(settings.value(
+ "SaveDecoded",false).toBool());
+ ui->actionSave_all->setChecked(settings.value("SaveAll",false).toBool());
+ m_dialFreq=settings.value("DialFreq",14.078).toDouble();
+ m_rxFreq=settings.value("RxFreq",1500).toInt();
+ ui->RxFreqSpinBox->setValue(m_rxFreq);
+ m_txFreq=settings.value("TxFreq",1500).toInt();
+ ui->TxFreqSpinBox->setValue(m_txFreq);
+ soundOutThread.setTxFreq(m_txFreq);
+ m_saveDecoded=ui->actionSave_decoded->isChecked();
+ m_saveAll=ui->actionSave_all->isChecked();
+ m_ndepth=settings.value("NDepth",3).toInt();
+ m_inGain=settings.value("InGain",0).toInt();
+ ui->inGain->setValue(m_inGain);
+ m_monitorStartOFF=settings.value("MonitorOFF",false).toBool();
+ ui->actionMonitor_OFF_at_startup->setChecked(m_monitorStartOFF);
+ m_pskReporter=settings.value("PSKReporter",false).toBool();
+ m_After73=settings.value("After73",false).toBool();
+ m_macro=settings.value("Macros","TNX 73 GL").toStringList();
+ m_dFreq=settings.value("DefaultFreqs","").toStringList();
+ m_toRTTY=settings.value("toRTTY",false).toBool();
+ ui->actionConvert_JT9_x_to_RTTY->setChecked(m_toRTTY);
+ m_noSuffix=settings.value("NoSuffix",false).toBool();
+ ui->actionLog_JT9_without_submode->setChecked(m_noSuffix);
+ m_dBtoComments=settings.value("dBtoComments",false).toBool();
+ ui->actionLog_dB_reports_to_Comments->setChecked(m_dBtoComments);
+ m_rig=settings.value("Rig",214).toInt();
+ m_rigIndex=settings.value("RigIndex",100).toInt();
+ m_catPort=settings.value("CATport","None").toString();
+ m_catPortIndex=settings.value("CATportIndex",0).toInt();
+ m_serialRate=settings.value("SerialRate",4800).toInt();
+ m_serialRateIndex=settings.value("SerialRateIndex",1).toInt();
+ m_dataBits=settings.value("DataBits",8).toInt();
+ m_dataBitsIndex=settings.value("DataBitsIndex",1).toInt();
+ m_stopBits=settings.value("StopBits",2).toInt();
+ m_stopBitsIndex=settings.value("StopBitsIndex",1).toInt();
+ m_handshake=settings.value("Handshake","None").toString();
+ m_handshakeIndex=settings.value("HandshakeIndex",0).toInt();
+ m_band=settings.value("BandIndex",7).toInt();
+ ui->bandComboBox->setCurrentIndex(m_band);
+ dialFreqChanged2(m_dialFreq);
+ m_catEnabled=settings.value("catEnabled",false).toBool();
+ m_promptToLog=settings.value("PromptToLog",false).toBool();
+ ui->actionPrompt_to_log_QSO->setChecked(m_promptToLog);
+ m_insertBlank=settings.value("InsertBlank",false).toBool();
+ ui->actionBlank_line_between_decoding_periods->setChecked(m_insertBlank);
+ m_clearCallGrid=settings.value("ClearCallGrid",false).toBool();
+ ui->actionClear_DX_Call_and_Grid_after_logging->setChecked(m_clearCallGrid);
+ m_bMiles=settings.value("Miles",false).toBool();
+ ui->actionDisplay_distance_in_miles->setChecked(m_bMiles);
+ int n=settings.value("GUItab",0).toInt();
+ ui->tabWidget->setCurrentIndex(n);
+ m_quickCall=settings.value("QuickCall",false).toBool();
+ ui->actionDouble_click_on_call_sets_Tx_Enable->setChecked(m_quickCall);
+ m_73TxDisable=settings.value("73TxDisable",false).toBool();
+ ui->action_73TxDisable->setChecked(m_73TxDisable);
+ m_runaway=settings.value("Runaway",false).toBool();
+ ui->actionRunaway_Tx_watchdog->setChecked(m_runaway);
+ m_tx2QSO=settings.value("Tx2QSO",false).toBool();
+ ui->actionTx2QSO->setChecked(m_tx2QSO);
+ m_bMultipleOK=settings.value("MultipleOK",false).toBool();
+ ui->actionAllow_multiple_instances->setChecked(m_bMultipleOK);
+ m_bDTRoff=settings.value("DTRoff",false).toBool();
+ m_pttData=settings.value("pttData",false).toBool();
+ m_poll=settings.value("Polling",0).toInt();
+ m_logQSOgeom=settings.value("LogQSOgeom",QRect(500,400,424,283)).toRect();
+ outBufSize=settings.value("OutBufSize",4096).toInt();
+ m_lockTxFreq=settings.value("LockTxFreq",false).toBool();
+ ui->cbTxLock->setChecked(m_lockTxFreq);
+ m_saveTxPower=settings.value("SaveTxPower",false).toBool();
+ m_saveComments=settings.value("SaveComments",false).toBool();
+ m_txPower=settings.value("TxPower","").toString();
+ m_logComments=settings.value("LogComments","").toString();
+ m_pskAntenna=settings.value("PSKantenna","").toString();
+ m_fMin=settings.value("fMin",2500).toInt();
+ m_bSplit=settings.value("TxSplit",false).toBool();
+ m_bXIT=settings.value("UseXit",false).toBool();
+ m_plus2kHz=settings.value("Plus2kHz",false).toBool();
+ ui->cbPlus2kHz->setChecked(m_plus2kHz);
+ settings.endGroup();
+
+ if(!ui->actionLinrad->isChecked() && !ui->actionCuteSDR->isChecked() &&
+ !ui->actionAFMHot->isChecked() && !ui->actionBlue->isChecked()) {
+ on_actionLinrad_triggered();
+ ui->actionLinrad->setChecked(true);
+ }
+ if(m_ndepth==1) ui->actionQuickDecode->setChecked(true);
+ if(m_ndepth==2) ui->actionMediumDecode->setChecked(true);
+ if(m_ndepth==3) ui->actionDeepestDecode->setChecked(true);
+
+ statusChanged();
+}
+
+//-------------------------------------------------------------- dataSink()
+void MainWindow::dataSink(int k)
+{
+ static float s[NSMAX];
+ static int ihsym=0;
+ static int nzap=0;
+ static int trmin;
+ static int npts8;
+ static float px=0.0;
+ static float df3;
+ static float slope;
+
+ if(m_diskData) {
+ jt9com_.ndiskdat=1;
+ } else {
+ jt9com_.ndiskdat=0;
+ }
+
+// Get power, spectrum, and ihsym
+ trmin=m_TRperiod/60;
+ slope=0.0;
+ if(g_pWideGraph!=NULL) slope=(float)g_pWideGraph->getSlope();
+ symspec_(&k,&trmin,&m_nsps,&m_inGain,&slope,&px,s,&df3,&ihsym,&npts8);
+ if(ihsym <=0) return;
+ QString t;
+ m_pctZap=nzap*100.0/m_nsps;
+ t.sprintf(" Rx noise: %5.1f ",px);
+ signalMeter->setValue(px); // Update thermometer
+ if(m_monitoring || m_diskData) {
+ g_pWideGraph->dataSink2(s,df3,ihsym,m_diskData);
+ }
+
+ if(ihsym == m_hsymStop) {
+ m_dataAvailable=true;
+ jt9com_.npts8=(ihsym*m_nsps)/16;
+ jt9com_.newdat=1;
+ jt9com_.nagain=0;
+ jt9com_.nzhsym=m_hsymStop;
+ QDateTime t = QDateTime::currentDateTimeUtc();
+ m_dateTime=t.toString("yyyy-MMM-dd hh:mm");
+ decode(); //Start decoder
+ if(!m_diskData) { //Always save; may delete later
+ int ihr=t.time().toString("hh").toInt();
+ int imin=t.time().toString("mm").toInt();
+ imin=imin - (imin%(m_TRperiod/60));
+ QString t2;
+ t2.sprintf("%2.2d%2.2d",ihr,imin);
+ m_fname=m_saveDir + "/" + t.date().toString("yyMMdd") + "_" +
+ t2 + ".wav";
+ *future2 = QtConcurrent::run(savewav, m_fname, m_TRperiod);
+ watcher2->setFuture(*future2);
+ }
+ }
+ soundInThread.m_dataSinkBusy=false;
+}
+
+void MainWindow::showSoundInError(const QString& errorMsg)
+ {QMessageBox::critical(this, tr("Error in SoundIn"), errorMsg);}
+
+void MainWindow::showStatusMessage(const QString& statusMsg)
+ {statusBar()->showMessage(statusMsg);}
+
+void MainWindow::on_actionDeviceSetup_triggered() //Setup Dialog
+{
+ DevSetup dlg(this);
+ dlg.m_myCall=m_myCall;
+ dlg.m_myGrid=m_myGrid;
+ dlg.m_pskAntenna=m_pskAntenna;
+ dlg.m_idInt=m_idInt;
+ dlg.m_pttMethodIndex=m_pttMethodIndex;
+ dlg.m_pttPort=m_pttPort;
+ dlg.m_saveDir=m_saveDir;
+ dlg.m_paInDevice=m_paInDevice;
+ dlg.m_paOutDevice=m_paOutDevice;
+ dlg.m_pskReporter=m_pskReporter;
+ dlg.m_After73=m_After73;
+ dlg.m_macro=m_macro;
+ dlg.m_dFreq=m_dFreq;
+ dlg.m_catEnabled=m_catEnabled;
+ dlg.m_rig=m_rig;
+ dlg.m_rigIndex=m_rigIndex;
+ dlg.m_catPort=m_catPort;
+ dlg.m_catPortIndex=m_catPortIndex;
+ dlg.m_serialRate=m_serialRate;
+ dlg.m_serialRateIndex=m_serialRateIndex;
+ dlg.m_dataBits=m_dataBits;
+ dlg.m_dataBitsIndex=m_dataBitsIndex;
+ dlg.m_stopBits=m_stopBits;
+ dlg.m_stopBitsIndex=m_stopBitsIndex;
+ dlg.m_handshake=m_handshake;
+ dlg.m_handshakeIndex=m_handshakeIndex;
+ dlg.m_bDTRoff=m_bDTRoff;
+ dlg.m_pttData=m_pttData;
+ dlg.m_poll=m_poll;
+ dlg.m_bSplit=m_bSplit;
+ dlg.m_bXIT=m_bXIT;
+
+ if(m_bRigOpen) {
+ rig->close();
+ ui->readFreq->setStyleSheet("");
+ ui->readFreq->setEnabled(false);
+ if(m_rig<9900) delete rig;
+ m_bRigOpen=false;
+ m_catEnabled=false;
+ m_CATerror=false;
+ }
+
+ dlg.initDlg();
+ if(dlg.exec() == QDialog::Accepted) {
+ m_myCall=dlg.m_myCall;
+ m_myGrid=dlg.m_myGrid;
+ m_pskAntenna=dlg.m_pskAntenna;
+ m_idInt=dlg.m_idInt;
+ m_pttMethodIndex=dlg.m_pttMethodIndex;
+ m_pttPort=dlg.m_pttPort;
+ m_saveDir=dlg.m_saveDir;
+ m_paInDevice=dlg.m_paInDevice;
+ m_paOutDevice=dlg.m_paOutDevice;
+ m_macro=dlg.m_macro;
+ m_dFreq=dlg.m_dFreq;
+ m_catEnabled=dlg.m_catEnabled;
+ m_rig=dlg.m_rig;
+ m_rigIndex=dlg.m_rigIndex;
+ m_catPort=dlg.m_catPort;
+ m_catPortIndex=dlg.m_catPortIndex;
+ m_serialRate=dlg.m_serialRate;
+ m_serialRateIndex=dlg.m_serialRateIndex;
+ m_dataBits=dlg.m_dataBits;
+ m_dataBitsIndex=dlg.m_dataBitsIndex;
+ m_stopBits=dlg.m_stopBits;
+ m_stopBitsIndex=dlg.m_stopBitsIndex;
+ m_handshake=dlg.m_handshake;
+ m_handshakeIndex=dlg.m_handshakeIndex;
+ m_bDTRoff=dlg.m_bDTRoff;
+ m_pttData=dlg.m_pttData;
+ m_poll=dlg.m_poll;
+
+#ifdef WIN32
+ if(dlg.m_pskReporter!=m_pskReporter) {
+ if(dlg.m_pskReporter) {
+ int rc=ReporterInitialize(NULL,NULL);
+ if(rc==0) {
+ m_pskReporterInit=true;
+ } else {
+ m_pskReporterInit=false;
+ rc=ReporterGetInformation(buffer,256);
+ msgBox(QString::fromStdWString(buffer));
+ }
+ } else {
+ rc=ReporterUninitialize();
+ m_pskReporterInit=false;
+ }
+ }
+#endif
+ m_pskReporter=dlg.m_pskReporter;
+
+#ifdef UNIX
+ if(m_pskReporter) {
+ psk_Reporter->setLocalStation(m_myCall,m_myGrid, "WSJT-X r" + rev.mid(6,4) );
+ }
+#endif
+
+ m_After73=dlg.m_After73;
+
+ if(dlg.m_restartSoundIn) {
+ soundInThread.quit();
+ soundInThread.wait(1000);
+ soundInThread.setInputDevice(m_paInDevice);
+ soundInThread.start(QThread::HighestPriority);
+ }
+
+ if(dlg.m_restartSoundOut) {
+ soundOutThread.quitExecution=true;
+ soundOutThread.wait(1000);
+ soundOutThread.setOutputDevice(m_paOutDevice);
+ }
+ }
+ m_catEnabled=dlg.m_catEnabled;
+
+ if(m_catEnabled) {
+ rigOpen();
+ } else {
+ ui->readFreq->setStyleSheet("");
+ }
+
+ if(dlg.m_bSplit!=m_bSplit or dlg.m_bXIT!=m_bXIT) {
+ m_bSplit=dlg.m_bSplit;
+ m_bXIT=dlg.m_bXIT;
+ if(m_bSplit or m_bXIT) setXIT(m_txFreq);
+ if(m_bRigOpen and !m_bSplit) {
+ int ret=rig->setSplitFreq(MHz(m_dialFreq),RIG_VFO_B);
+ if(ret!=RIG_OK) {
+ QString rt;
+ rt.sprintf("Setting VFO_B failed: %d",ret);
+ msgBox(rt);
+ }
+ }
+ }
+}
+
+void MainWindow::on_monitorButton_clicked() //Monitor
+{
+ m_monitoring=true;
+ soundInThread.setMonitoring(true);
+ m_diskData=false;
+}
+
+void MainWindow::on_actionLinrad_triggered() //Linrad palette
+{
+ if(g_pWideGraph != NULL) g_pWideGraph->setPalette("Linrad");
+}
+
+void MainWindow::on_actionCuteSDR_triggered() //CuteSDR palette
+{
+ if(g_pWideGraph != NULL) g_pWideGraph->setPalette("CuteSDR");
+}
+
+void MainWindow::on_actionAFMHot_triggered()
+{
+ if(g_pWideGraph != NULL) g_pWideGraph->setPalette("AFMHot");
+}
+
+void MainWindow::on_actionBlue_triggered()
+{
+ if(g_pWideGraph != NULL) g_pWideGraph->setPalette("Blue");
+}
+
+void MainWindow::on_actionAbout_triggered() //Display "About"
+{
+ CAboutDlg dlg(this,Program_Title_Version);
+ dlg.exec();
+}
+
+void MainWindow::on_autoButton_clicked() //Auto
+{
+ m_auto = !m_auto;
+ if(m_auto) {
+ ui->autoButton->setStyleSheet(m_pbAutoOn_style);
+ } else {
+ btxok=false;
+ ui->autoButton->setStyleSheet("");
+ on_monitorButton_clicked();
+ m_repeatMsg=0;
+ }
+}
+
+void MainWindow::keyPressEvent( QKeyEvent *e ) //keyPressEvent
+{
+ int n;
+ switch(e->key())
+ {
+ case Qt::Key_1:
+ if(e->modifiers() & Qt::AltModifier) {
+ on_txb1_clicked();
+ break;
+ }
+ case Qt::Key_2:
+ if(e->modifiers() & Qt::AltModifier) {
+ on_txb2_clicked();
+ break;
+ }
+ case Qt::Key_3:
+ if(e->modifiers() & Qt::AltModifier) {
+ on_txb3_clicked();
+ break;
+ }
+ case Qt::Key_4:
+ if(e->modifiers() & Qt::AltModifier) {
+ on_txb4_clicked();
+ break;
+ }
+ case Qt::Key_5:
+ if(e->modifiers() & Qt::AltModifier) {
+ on_txb5_clicked();
+ break;
+ }
+ case Qt::Key_6:
+ if(e->modifiers() & Qt::AltModifier) {
+ on_txb6_clicked();
+ break;
+ }
+ case Qt::Key_D:
+ if(e->modifiers() & Qt::ShiftModifier) {
+ if(!m_decoderBusy) {
+ jt9com_.newdat=0;
+ jt9com_.nagain=0;
+ decode();
+ break;
+ }
+ }
+ break;
+ case Qt::Key_F4:
+ ui->dxCallEntry->setText("");
+ ui->dxGridEntry->setText("");
+ genStdMsgs("");
+ m_ntx=6;
+ ui->txrb6->setChecked(true);
+ break;
+ case Qt::Key_F6:
+ if(e->modifiers() & Qt::ShiftModifier) {
+ on_actionDecode_remaining_files_in_directory_triggered();
+ }
+ break;
+ case Qt::Key_F11:
+ n=11;
+ if(e->modifiers() & Qt::ControlModifier) n+=100;
+ bumpFqso(n);
+ break;
+ case Qt::Key_F12:
+ n=12;
+ if(e->modifiers() & Qt::ControlModifier) n+=100;
+ bumpFqso(n);
+ break;
+ case Qt::Key_F:
+ if(e->modifiers() & Qt::ControlModifier) {
+ if(ui->tabWidget->currentIndex()==0) {
+ ui->tx5->clear();
+ ui->tx5->setFocus();
+ } else {
+ ui->freeTextMsg->clear();
+ ui->freeTextMsg->setFocus();
+ }
+ break;
+ }
+ case Qt::Key_G:
+ if(e->modifiers() & Qt::AltModifier) {
+ genStdMsgs(m_rpt);
+ break;
+ }
+ case Qt::Key_H:
+ if(e->modifiers() & Qt::AltModifier) {
+ on_stopTxButton_clicked();
+ break;
+ }
+ case Qt::Key_L:
+ if(e->modifiers() & Qt::ControlModifier) {
+ lookup();
+ genStdMsgs(m_rpt);
+ break;
+ }
+ case Qt::Key_V:
+ if(e->modifiers() & Qt::AltModifier) {
+ m_fileToSave=m_fname;
+ break;
+ }
+ }
+}
+
+void MainWindow::bumpFqso(int n) //bumpFqso()
+{
+ int i;
+ bool ctrl = (n>=100);
+ n=n%100;
+ i=g_pWideGraph->rxFreq();
+ if(n==11) i--;
+ if(n==12) i++;
+ g_pWideGraph->setRxFreq(i);
+ if(ctrl) {
+ ui->TxFreqSpinBox->setValue(i);
+ g_pWideGraph->setTxFreq(i);
+ }
+}
+
+void MainWindow::dialFreqChanged2(double f)
+{
+ m_dialFreq=f;
+ if(m_band<0 or m_band>15 or m_dFreq.length()<=1) return;
+ QString t;
+ t.sprintf("%.6f",m_dialFreq);
+ int n=t.length();
+ t=t.mid(0,n-3) + " " + t.mid(n-3,3);
+ double fBand=m_dFreq[m_band].toDouble();
+ if(qAbs(m_dialFreq-fBand)<0.01) {
+ ui->labDialFreq->setStyleSheet( \
+ "QLabel { background-color : black; color : yellow; }");
+ } else {
+ ui->labDialFreq->setStyleSheet( \
+ "QLabel { background-color : red; color : yellow; }");
+ ui->labDialFreq->setText(t);
+ }
+ ui->labDialFreq->setText(t);
+ statusChanged();
+ if(g_pWideGraph!=NULL) g_pWideGraph->setDialFreq(m_dialFreq);
+}
+
+void MainWindow::statusChanged()
+{
+ QFile f("wsjtx_status.txt");
+ if(f.open(QFile::WriteOnly | QIODevice::Text)) {
+ QTextStream out(&f);
+ out << m_dialFreq << ";" << m_mode << ";" << m_hisCall << ";"
+ << ui->rptSpinBox->value() << ";" << m_modeTx << endl;
+ f.close();
+ } else {
+ msgBox("Cannot open file \"wsjtx_status.txt\".");
+ return;
+ }
+}
+
+bool MainWindow::eventFilter(QObject *object, QEvent *event) //eventFilter()
+{
+ if (event->type() == QEvent::KeyPress) {
+ QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
+ MainWindow::keyPressEvent(keyEvent);
+ return QObject::eventFilter(object, event);
+ }
+ return QObject::eventFilter(object, event);
+}
+
+void MainWindow::createStatusBar() //createStatusBar
+{
+ lab1 = new QLabel("Receiving");
+ lab1->setAlignment(Qt::AlignHCenter);
+ lab1->setMinimumSize(QSize(80,18));
+ lab1->setStyleSheet("QLabel{background-color: #00ff00}");
+ lab1->setFrameStyle(QFrame::Panel | QFrame::Sunken);
+ statusBar()->addWidget(lab1);
+
+ lab2 = new QLabel("");
+ lab2->setAlignment(Qt::AlignHCenter);
+ lab2->setMinimumSize(QSize(150,18));
+ lab2->setFrameStyle(QFrame::Panel | QFrame::Sunken);
+ statusBar()->addWidget(lab2);
+
+ lab3 = new QLabel("");
+ lab3->setAlignment(Qt::AlignHCenter);
+ lab3->setMinimumSize(QSize(80,18));
+ lab3->setFrameStyle(QFrame::Panel | QFrame::Sunken);
+ statusBar()->addWidget(lab3);
+}
+
+void MainWindow::on_actionExit_triggered() //Exit()
+{
+ OnExit();
+}
+
+void MainWindow::closeEvent(QCloseEvent*)
+{
+ OnExit();
+}
+
+void MainWindow::OnExit()
+{
+ g_pWideGraph->saveSettings();
+ if(m_fname != "") killFile();
+ m_killAll=true;
+ mem_jt9->detach();
+ QFile quitFile(m_appDir + "/.quit");
+ quitFile.open(QIODevice::ReadWrite);
+ QFile lockFile(m_appDir + "/.lock");
+ lockFile.remove(); // Allow jt9 to terminate
+ bool b=proc_jt9.waitForFinished(1000);
+ if(!b) proc_jt9.kill();
+ quitFile.remove();
+ qApp->exit(0); // Exit the event loop
+}
+
+void MainWindow::on_stopButton_clicked() //stopButton
+{
+ m_monitoring=false;
+ soundInThread.setMonitoring(m_monitoring);
+ m_loopall=false;
+}
+
+void MainWindow::msgBox(QString t) //msgBox
+{
+ msgBox0.setText(t);
+ msgBox0.exec();
+}
+
+void MainWindow::on_actionOnline_Users_Guide_triggered() //Display manual
+{
+ QDesktopServices::openUrl(QUrl(
+ "http://www.physics.princeton.edu/pulsar/K1JT/WSJT-X_Users_Guide_v1.1.pdf",
+ QUrl::TolerantMode));
+}
+
+void MainWindow::on_actionWide_Waterfall_triggered() //Display Waterfalls
+{
+ if(g_pWideGraph==NULL) {
+ g_pWideGraph = new WideGraph(0);
+ g_pWideGraph->setWindowTitle("Wide Graph");
+ g_pWideGraph->setGeometry(m_wideGraphGeom);
+ Qt::WindowFlags flags = Qt::WindowCloseButtonHint |
+ Qt::WindowMinimizeButtonHint;
+ g_pWideGraph->setWindowFlags(flags);
+ connect(g_pWideGraph, SIGNAL(freezeDecode2(int)),this,
+ SLOT(freezeDecode(int)));
+ connect(g_pWideGraph, SIGNAL(f11f12(int)),this,
+ SLOT(bumpFqso(int)));
+ connect(g_pWideGraph, SIGNAL(setXIT2(int)),this,
+ SLOT(setXIT(int)));
+// connect(g_pWideGraph, SIGNAL(dialFreqChanged(double)),this,
+// SLOT(dialFreqChanged2(double)));
+ }
+ g_pWideGraph->show();
+}
+
+void MainWindow::on_actionOpen_triggered() //Open File
+{
+ m_monitoring=false;
+ soundInThread.setMonitoring(m_monitoring);
+ QString fname;
+ fname=QFileDialog::getOpenFileName(this, "Open File", m_path,
+ "WSJT Files (*.wav)");
+ if(fname != "") {
+ m_path=fname;
+ int i;
+ i=fname.indexOf(".wav") - 11;
+ if(i>=0) {
+ lab1->setStyleSheet("QLabel{background-color: #66ff66}");
+ lab1->setText(" " + fname.mid(i,15) + " ");
+ }
+ on_stopButton_clicked();
+ m_diskData=true;
+ *future1 = QtConcurrent::run(getfile, fname, m_TRperiod);
+ watcher1->setFuture(*future1); // call diskDat() when done
+ }
+}
+
+void MainWindow::on_actionOpen_next_in_directory_triggered() //Open Next
+{
+ int i,len;
+ QFileInfo fi(m_path);
+ QStringList list;
+ list= fi.dir().entryList().filter(".wav");
+ for (i = 0; i < list.size()-1; ++i) {
+ if(i==list.size()-2) m_loopall=false;
+ len=list.at(i).length();
+ if(list.at(i)==m_path.right(len)) {
+ int n=m_path.length();
+ QString fname=m_path.replace(n-len,len,list.at(i+1));
+ m_path=fname;
+ int i;
+ i=fname.indexOf(".wav") - 11;
+ if(i>=0) {
+ lab1->setStyleSheet("QLabel{background-color: #66ff66}");
+ lab1->setText(" " + fname.mid(i,len) + " ");
+ }
+ m_diskData=true;
+ *future1 = QtConcurrent::run(getfile, fname, m_TRperiod);
+ watcher1->setFuture(*future1);
+ return;
+ }
+ }
+}
+ //Open all remaining files
+void MainWindow::on_actionDecode_remaining_files_in_directory_triggered()
+{
+ m_loopall=true;
+ on_actionOpen_next_in_directory_triggered();
+}
+
+void MainWindow::diskDat() //diskDat()
+{
+ int k;
+ int kstep=m_nsps/2;
+ m_diskData=true;
+ for(int n=1; n<=m_hsymStop; n++) { // Do the half-symbol FFTs
+ k=(n+1)*kstep;
+ jt9com_.npts8=k/8;
+ dataSink(k);
+ if(n%10 == 1 or n == m_hsymStop)
+ qApp->processEvents(); //Keep GUI responsive
+ }
+}
+
+void MainWindow::diskWriteFinished() //diskWriteFinished
+{
+}
+
+//Delete ../save/*.wav
+void MainWindow::on_actionDelete_all_wav_files_in_SaveDir_triggered()
+{
+ int i;
+ QString fname;
+ int ret = QMessageBox::warning(this, "Confirm Delete",
+ "Are you sure you want to delete all *.wav files in\n" +
+ QDir::toNativeSeparators(m_saveDir) + " ?",
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ if(ret==QMessageBox::Yes) {
+ QDir dir(m_saveDir);
+ QStringList files=dir.entryList(QDir::Files);
+ QList<QString>::iterator f;
+ for(f=files.begin(); f!=files.end(); ++f) {
+ fname=*f;
+ i=(fname.indexOf(".wav"));
+ if(i>10) dir.remove(fname);
+ }
+ }
+}
+
+void MainWindow::on_actionNone_triggered() //Save None
+{
+ m_saveDecoded=false;
+ m_saveAll=false;
+ ui->actionNone->setChecked(true);
+}
+
+void MainWindow::on_actionSave_decoded_triggered()
+{
+ m_saveDecoded=true;
+ m_saveAll=false;
+ ui->actionSave_decoded->setChecked(true);
+}
+
+void MainWindow::on_actionSave_all_triggered() //Save All
+{
+ m_saveDecoded=false;
+ m_saveAll=true;
+ ui->actionSave_all->setChecked(true);
+}
+
+void MainWindow::on_actionKeyboard_shortcuts_triggered()
+{
+ pShortcuts = new QTextEdit(0);
+ pShortcuts->setReadOnly(true);
+ pShortcuts->setFontPointSize(10);
+ pShortcuts->setWindowTitle("Keyboard Shortcuts");
+ pShortcuts->setGeometry(QRect(45,50,430,460));
+ Qt::WindowFlags flags = Qt::WindowCloseButtonHint |
+ Qt::WindowMinimizeButtonHint;
+ pShortcuts->setWindowFlags(flags);
+ QString shortcuts = m_appDir + "/shortcuts.txt";
+ QFile f(shortcuts);
+ if(!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ msgBox("Cannot open " + shortcuts);
+ return;
+ }
+ QTextStream s(&f);
+ QString t;
+ for(int i=0; i<100; i++) {
+ t=s.readLine();
+ pShortcuts->append(t);
+ if(s.atEnd()) break;
+ }
+ pShortcuts->show();
+}
+
+void MainWindow::on_actionSpecial_mouse_commands_triggered()
+{
+ QTextEdit* pMouseCmnds;
+ pMouseCmnds = new QTextEdit(0);
+ pMouseCmnds->setReadOnly(true);
+ pMouseCmnds->setFontPointSize(10);
+ pMouseCmnds->setWindowTitle("Special Mouse Commands");
+ pMouseCmnds->setGeometry(QRect(45,50,440,300));
+ Qt::WindowFlags flags = Qt::WindowCloseButtonHint |
+ Qt::WindowMinimizeButtonHint;
+ pMouseCmnds->setWindowFlags(flags);
+ QString mouseCmnds = m_appDir + "/mouse_commands.txt";
+ QFile f(mouseCmnds);
+ if(!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ msgBox("Cannot open " + mouseCmnds);
+ return;
+ }
+ QTextStream s(&f);
+ QString t;
+ for(int i=0; i<100; i++) {
+ t=s.readLine();
+ pMouseCmnds->append(t);
+ if(s.atEnd()) break;
+ }
+ pMouseCmnds->show();
+}
+
+void MainWindow::on_DecodeButton_clicked() //Decode request
+{
+ if(!m_decoderBusy) {
+ jt9com_.newdat=0;
+ jt9com_.nagain=1;
+ decode();
+ }
+}
+
+void MainWindow::freezeDecode(int n) //freezeDecode()
+{
+ bool ctrl = (n>=100);
+ int i=g_pWideGraph->rxFreq();
+ if(ctrl) {
+ ui->TxFreqSpinBox->setValue(i);
+ g_pWideGraph->setTxFreq(i);
+ }
+ if((n%100)==2) on_DecodeButton_clicked();
+}
+
+void MainWindow::decode() //decode()
+{
+ if(!m_dataAvailable) return;
+ ui->DecodeButton->setStyleSheet(m_pbdecoding_style1);
+ if(jt9com_.newdat==1 && (!m_diskData)) {
+ qint64 ms = QDateTime::currentMSecsSinceEpoch() % 86400000;
+ int imin=ms/60000;
+ int ihr=imin/60;
+ imin=imin % 60;
+ imin=imin - (imin % (m_TRperiod/60));
+ jt9com_.nutc=100*ihr + imin;
+ }
+
+ jt9com_.nfqso=g_pWideGraph->rxFreq();
+ jt9com_.ndepth=m_ndepth;
+ jt9com_.ndiskdat=0;
+ if(m_diskData) jt9com_.ndiskdat=1;
+ int nfa=g_pWideGraph->getFmin();
+ int nfb=g_pWideGraph->getFmax();
+ if(m_mode=="JT9") nfa=200; //decode from 0 to fmax
+ if(m_mode=="JT65") nfa=nfb; //decode from 0 to fmax
+ jt9com_.nfa=nfa;
+ jt9com_.nfb=nfb;
+ jt9com_.ntol=20;
+ if(jt9com_.nutc < m_nutc0) m_RxLog |= 1; //Date and Time to all.txt
+ m_nutc0=jt9com_.nutc;
+ jt9com_.ntxmode=9;
+ if(m_modeTx=="JT65") jt9com_.ntxmode=65;
+ jt9com_.nmode=9;
+ if(m_mode=="JT65") jt9com_.nmode=65;
+ if(m_mode=="JT9+JT65") jt9com_.nmode=9+65;
+ jt9com_.ntrperiod=m_TRperiod;
+ m_nsave=0;
+ if(m_saveDecoded) m_nsave=2;
+ jt9com_.nsave=m_nsave;
+ strncpy(jt9com_.datetime, m_dateTime.toLatin1(), 20);
+
+ //newdat=1 ==> this is new data, must do the big FFT
+ //nagain=1 ==> decode only at fQSO +/- Tol
+
+ char *to = (char*)mem_jt9->data();
+ char *from = (char*) jt9com_.ss;
+ int size=sizeof(jt9com_);
+ if(jt9com_.newdat==0) {
+ int noffset = 4*184*NSMAX + 4*NSMAX + 2*NTMAX*12000;
+ to += noffset;
+ from += noffset;
+ size -= noffset;
+ }
+ memcpy(to, from, qMin(mem_jt9->size(), size));
+
+ QFile lockFile(m_appDir + "/.lock"); // Allow jt9 to start
+ lockFile.remove();
+ decodeBusy(true);
+}
+
+void MainWindow::jt9_error() //jt9_error
+{
+ if(!m_killAll) {
+ msgBox("Error starting or running\n" + m_appDir + "/jt9 -s");
+ exit(1);
+ }
+}
+
+void MainWindow::readFromStderr() //readFromStderr
+{
+ QByteArray t=proc_jt9.readAllStandardError();
+ msgBox(t);
+}
+
+void MainWindow::readFromStdout() //readFromStdout
+{
+ while(proc_jt9.canReadLine()) {
+ QByteArray t=proc_jt9.readLine();
+ if(t.indexOf("<DecodeFinished>") >= 0) {
+ m_bdecoded = (t.mid(23,1).toInt()==1);
+ bool keepFile=m_saveAll or (m_saveDecoded and m_bdecoded);
+ if(!keepFile and !m_diskData) killFileTimer->start(45*1000); //Kill in 45 s
+ jt9com_.nagain=0;
+ jt9com_.ndiskdat=0;
+ QFile lockFile(m_appDir + "/.lock");
+ lockFile.open(QIODevice::ReadWrite);
+ ui->DecodeButton->setStyleSheet("");
+ decodeBusy(false);
+ m_RxLog=0;
+ m_startAnother=m_loopall;
+ m_blankLine=true;
+ return;
+ } else {
+ QFile f("ALL.TXT");
+ f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
+ QTextStream out(&f);
+ if(m_RxLog && 1) {
+ out << QDateTime::currentDateTimeUtc().toString("yyyy-MMM-dd hh:mm")
+ << " " << m_dialFreq << " MHz " << m_mode << endl;
+ m_RxLog=0;
+ }
+ int n=t.length();
+ out << t.mid(0,n-2) << endl;
+ f.close();
+
+ QTextCursor cursor;
+ QTextBlockFormat bf;
+ if(m_insertBlank and m_blankLine and jt9com_.nagain==0) {
+ QString bg="#d3d3d3";
+ bf.setBackground(QBrush(QColor(bg)));
+ QString tt="----------------------------------------";
+ QString s = "<table border=0 cellspacing=0 width=100%><tr><td bgcolor=\"" +
+ bg + "\"><pre>" + tt + "</pre></td></tr></table>";
+ cursor = ui->decodedTextBrowser->textCursor();
+ cursor.movePosition(QTextCursor::End);
+ bf = cursor.blockFormat();
+ bf.setBackground(QBrush(QColor(bg)));
+ cursor.insertHtml(s);
+ m_blankLine=false;
+ }
+
+ QString bg="white";
+ if(t.indexOf(" CQ ")>0) bg="#66ff66"; //green
+ if(m_myCall!="" and t.indexOf(" "+m_myCall+" ")>0) bg="#ff6666"; //red
+ bool bQSO=abs(t.mid(14,4).toInt() - g_pWideGraph->rxFreq()) <= 10;
+ QString t1=t.replace("\n","").mid(0,t.length()-4);
+ QString s = "<table border=0 cellspacing=0 width=100%><tr><td bgcolor=\"" +
+ bg + "\"><pre>" + t1 + "</pre></td></tr></table>";
+ bool b65=t1.indexOf("#")==19;
+ if(bQSO) {
+ cursor = ui->decodedTextBrowser2->textCursor();
+ cursor.movePosition(QTextCursor::End);
+ bf = cursor.blockFormat();
+ bf.setBackground(QBrush(QColor(bg)));
+ cursor.insertHtml(s);
+ ui->decodedTextBrowser2->setTextCursor(cursor);
+ m_QSOmsg=t1;
+ if(b65 and m_modeTx!="JT65") on_pbTxMode_clicked();
+ if(!b65 and m_modeTx=="JT65") on_pbTxMode_clicked();
+ }
+
+ if(jt9com_.nagain==0) {
+ if(t.indexOf(" CQ ")>0) bg="#66ff66"; //green
+ if(m_myCall!="" and t.indexOf(" "+m_myCall+" ")>0) bg="#ff6666"; //red
+ QString s = "<table border=0 cellspacing=0 width=100%><tr><td bgcolor=\"" +
+ bg + "\"><pre>" + t1 + "</pre></td></tr></table>";
+ cursor = ui->decodedTextBrowser->textCursor();
+ cursor.movePosition(QTextCursor::End);
+ bf = cursor.blockFormat();
+ bf.setBackground(QBrush(QColor(bg)));
+ cursor.insertHtml(s);
+ ui->decodedTextBrowser->setTextCursor(cursor);
+ }
+
+ QString msg=t.mid(21);
+ int i1=msg.indexOf("\r");
+ if(i1>0) msg=msg.mid(0,i1-1) + " ";
+ bool b=stdmsg_(msg.mid(0,22).toLatin1().constData(),22);
+ QStringList w=msg.split(" ",QString::SkipEmptyParts);
+ if(b and w[0]==m_myCall) {
+ QString tt="";
+ if(w.length()>=3) tt=w[2];
+ bool ok;
+ i1=tt.toInt(&ok);
+ if(ok and i1>=-50 and i1<50) {
+ m_rptRcvd=tt;
+ } else {
+ if(tt.mid(0,1)=="R") {
+ i1=tt.mid(1).toInt(&ok);
+ if(ok and i1>=-50 and i1<50) {
+ m_rptRcvd=tt.mid(1);
+ }
+ }
+ }
+ }
+
+ int nsec=QDateTime::currentMSecsSinceEpoch()/1000-m_secBandChanged;
+ bool okToPost=(nsec>50);
+ QString msgmode="JT9";
+ if(b65) msgmode="JT65";
+ i1=msg.indexOf(" ");
+ QString c2=msg.mid(i1+1);
+ int i2=c2.indexOf(" ");
+ QString g2=c2.mid(i2+1,4);
+ c2=c2.mid(0,i2);
+ QString remote="call," + c2 + ",";
+ if(gridOK(g2)) remote += "gridsquare," + g2 + ",";
+ int nHz=t.mid(14,4).toInt();
+ uint nfreq=1000000.0*m_dialFreq + nHz + 0.5;
+ remote += "freq," + QString::number(nfreq);
+ int nsnr=t.mid(5,3).toInt();
+ remote += ",mode," + msgmode + ",snr," + QString::number(nsnr) + ",,";
+ wchar_t tremote[256];
+ remote.toWCharArray(tremote);
+
+#ifdef WIN32
+ if(m_pskReporterInit and b and !m_diskData and okToPost) {
+
+ QString local="station_callsign#" + m_myCall + "#" +
+ "my_gridsquare#" + m_myGrid + "#";
+ if(m_pskAntenna!="") local += "my_antenna#" + m_pskAntenna + "#";
+ local += "programid#WSJT-X#programversion#" + rev.mid(6,4) + "##";
+ wchar_t tlocal[256];
+ local.toWCharArray(tlocal);
+
+ int flags=REPORTER_SOURCE_AUTOMATIC;
+ rc=ReporterSeenCallsign(tremote,tlocal,flags);
+ if(rc!=0) {
+ ReporterGetInformation(buffer,256);
+ }
+ rc=ReporterTickle();
+ if(rc!=0) {
+ rc=ReporterGetInformation(buffer,256);
+ }
+ }
+#else
+ if(m_pskReporter and b and !m_diskData and okToPost) {
+ QString freq = QString::number(nfreq);
+ QString snr= QString::number(nsnr);
+ if(gridOK(g2)) {
+ psk_Reporter->addRemoteStation(c2,g2,freq,msgmode,snr,
+ QString::number(QDateTime::currentDateTime().toTime_t()));
+ }
+ }
+#endif
+ }
+ }
+}
+
+void MainWindow::killFile()
+{
+ if(m_fname==m_fileToSave) {
+ } else {
+ QFile savedFile(m_fname);
+ savedFile.remove();
+ }
+}
+
+void MainWindow::on_EraseButton_clicked() //Erase
+{
+ qint64 ms=QDateTime::currentMSecsSinceEpoch();
+ ui->decodedTextBrowser2->clear();
+ m_QSOmsg="";
+ if((ms-m_msErase)<500) {
+ ui->decodedTextBrowser->clear();
+ QFile f(m_appDir + "/decoded.txt");
+ if(f.exists()) f.remove();
+ }
+ m_msErase=ms;
+}
+
+void MainWindow::decodeBusy(bool b) //decodeBusy()
+{
+ m_decoderBusy=b;
+ ui->DecodeButton->setEnabled(!b);
+ ui->actionOpen->setEnabled(!b);
+ ui->actionOpen_next_in_directory->setEnabled(!b);
+ ui->actionDecode_remaining_files_in_directory->setEnabled(!b);
+}
+
+//------------------------------------------------------------- //guiUpdate()
+void MainWindow::guiUpdate()
+{
+ static int iptt0=0;
+ static bool btxok0=false;
+ static char message[29];
+ static char msgsent[29];
+ static int nsendingsh=0;
+ static int giptt00=-1;
+ static int gcomport00=-1;
+ static double onAirFreq0=0.0;
+ int ret=0;
+ QString rt;
+
+ double tx1=0.0;
+ double tx2=1.0 + 85.0*m_nsps/12000.0 + icw[0]*2560.0/48000.0;
+ if(m_modeTx=="JT65") tx2=1.0 + 126*4096/11025.0 + icw[0]*2560.0/48000.0;
+
+ if(!m_txFirst) {
+ tx1 += m_TRperiod;
+ tx2 += m_TRperiod;
+ }
+ qint64 ms = QDateTime::currentMSecsSinceEpoch() % 86400000;
+ int nsec=ms/1000;
+ double tsec=0.001*ms;
+ double t2p=fmod(tsec,2*m_TRperiod);
+ bool bTxTime = ((t2p >= tx1) and (t2p < tx2)) or m_tune;
+
+ if(m_auto or m_tune) {
+ QFile f("txboth");
+ if(f.exists() and fmod(tsec,m_TRperiod) < (1.0 + 85.0*m_nsps/12000.0)) {
+ bTxTime=true;
+ }
+
+ double onAirFreq=m_dialFreq+1.e-6*m_txFreq;
+ if(onAirFreq>10.139900 and onAirFreq<10.140320) {
+ bTxTime=false;
+ if(m_tune) on_tuneButton_clicked();
+ if(onAirFreq!=onAirFreq0) {
+ onAirFreq0=onAirFreq;
+ on_autoButton_clicked();
+ QString t="Please choose another Tx frequency.\n";
+ t+="WSJT-X will not knowingly transmit\n";
+ t+="in the WSPR sub-band on 30 m.";
+ msgBox0.setText(t);
+ msgBox0.show();
+ }
+ }
+
+ float fTR=float((nsec%m_TRperiod))/m_TRperiod;
+ if(g_iptt==0 and ((bTxTime and !btxMute and fTR<0.4) or m_tune )) {
+ icw[0]=m_ncw;
+
+//Raise PTT
+ if(m_catEnabled and m_bRigOpen and m_pttMethodIndex==0) {
+ g_iptt=1;
+ if(m_pttData) ret=rig->setPTT(RIG_PTT_ON_DATA, RIG_VFO_CURR);
+ if(!m_pttData) ret=rig->setPTT(RIG_PTT_ON_MIC, RIG_VFO_CURR);
+ if(ret!=RIG_OK) {
+ rt.sprintf("CAT control PTT failed: %d",ret);
+ msgBox(rt);
+ }
+
+ }
+
+ if(m_pttMethodIndex==1 or m_pttMethodIndex==2) { //DTR or RTS
+ ptt(m_pttPort,1,&g_iptt,&g_COMportOpen);
+ }
+ if(m_pttMethodIndex==3) { //VOX
+ g_iptt=1;
+ }
+ ptt1Timer->start(200); //Sequencer delay
+ }
+ if(!bTxTime || btxMute) {
+ btxok=false;
+ }
+ }
+
+// Calculate Tx tones when needed
+ if((g_iptt==1 && iptt0==0) || m_restart) {
+ QByteArray ba;
+ if(m_ntx == 1) ba=ui->tx1->text().toLocal8Bit();
+ if(m_ntx == 2) ba=ui->tx2->text().toLocal8Bit();
+ if(m_ntx == 3) ba=ui->tx3->text().toLocal8Bit();
+ if(m_ntx == 4) ba=ui->tx4->text().toLocal8Bit();
+ if(m_ntx == 5) ba=ui->tx5->text().toLocal8Bit();
+ if(m_ntx == 6) ba=ui->tx6->text().toLocal8Bit();
+ if(m_ntx == 7) ba=ui->genMsg->text().toLocal8Bit();
+ if(m_ntx == 8) ba=ui->freeTextMsg->text().toLocal8Bit();
+
+ ba2msg(ba,message);
+// ba2msg(ba,msgsent);
+ int len1=22;
+ int ichk=0,itext=0;
+ if(m_modeTx=="JT9") genjt9_(message,&ichk,msgsent,itone,&itext,len1,len1);
+ if(m_modeTx=="JT65") gen65_(message,&ichk,msgsent,itone,&itext,len1,len1);
+ msgsent[22]=0;
+ QString t=QString::fromLatin1(msgsent);
+ if(m_tune) t="TUNE";
+ lab2->setText("Last Tx: " + t);
+ if(m_restart) {
+ QFile f("ALL.TXT");
+ f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
+ QTextStream out(&f);
+ out << QDateTime::currentDateTimeUtc().toString("hhmm")
+ << " Transmitting " << m_dialFreq << " MHz " << m_modeTx
+ << ": " << t << endl;
+ f.close();
+ if(m_tx2QSO) displayTxMsg(t);
+ }
+
+ QStringList w=t.split(" ",QString::SkipEmptyParts);
+ t="";
+ if(w.length()==3) t=w[2];
+ icw[0]=0;
+ m_sent73=(t=="73" or itext!=0);
+ if(m_sent73) {
+ if(m_After73) icw[0]=m_ncw;
+ if(m_promptToLog and !m_tune) logQSOTimer->start(200);
+ }
+
+ if(m_idInt>0) {
+ int nmin=(m_sec0-m_secID)/60;
+ if(nmin >= m_idInt) {
+ icw[0]=m_ncw;
+ m_secID=m_sec0;
+ }
+ }
+
+ QString t2=QDateTime::currentDateTimeUtc().toString("hhmm");
+ if(itext==0 and w.length()>=3 and w[1]==m_myCall) {
+ int i1;
+ bool ok;
+ i1=t.toInt(&ok);
+ if(ok and i1>=-50 and i1<50) {
+ m_rptSent=t;
+ m_qsoStart=t2;
+ } else {
+ if(t.mid(0,1)=="R") {
+ i1=t.mid(1).toInt(&ok);
+ if(ok and i1>=-50 and i1<50) {
+ m_rptSent=t.mid(1);
+ m_qsoStart=t2;
+ }
+ }
+ }
+ }
+ if(itext==1 or (w.length()==3 and w[2]=="73")) m_qsoStop=t2;
+ m_restart=false;
+ }
+
+
+// If PTT was just raised, start a countdown for raising TxOK:
+// NB: could be better implemented with a timer
+ if(g_iptt == 1 && iptt0 == 0) {
+ nc1=-9; // TxDelay = 0.8 s
+ }
+ if(nc1 <= 0) {
+ nc1++;
+ }
+ if(nc1 == 0) {
+ QString t=QString::fromLatin1(msgsent);
+ if(t==m_msgSent0) {
+ m_repeatMsg++;
+ } else {
+ m_repeatMsg=0;
+ m_msgSent0=t;
+ }
+
+ signalMeter->setValue(0);
+ m_monitoring=false;
+ soundInThread.setMonitoring(false);
+ btxok=true;
+ m_transmitting=true;
+ ui->pbTxMode->setEnabled(false);
+ if(!m_tune) {
+ QFile f("ALL.TXT");
+ f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
+ QTextStream out(&f);
+ out << QDateTime::currentDateTimeUtc().toString("hhmm")
+ << " Transmitting " << m_dialFreq << " MHz " << m_modeTx
+ << ": " << t << endl;
+ f.close();
+ }
+ if(m_tx2QSO and !m_tune) displayTxMsg(t);
+ }
+
+ if(!btxok && btxok0 && g_iptt==1) stopTx();
+
+/*
+// If btxok was just lowered, start a countdown for lowering PTT
+ if(!btxok && btxok0 && g_iptt==1) nc0=-11; //RxDelay = 1.0 s
+ if(nc0 <= 0) {
+ nc0++;
+ }
+*/
+
+ if(m_monitoring) {
+ ui->monitorButton->setStyleSheet(m_pbmonitor_style);
+ } else {
+ ui->monitorButton->setStyleSheet("");
+ }
+
+ if(m_startAnother) {
+ m_startAnother=false;
+ on_actionOpen_next_in_directory_triggered();
+ }
+
+ if(m_catEnabled and !m_bRigOpen) {
+ rigOpen();
+ }
+
+ if(nsec != m_sec0) { //Once per second
+ QDateTime t = QDateTime::currentDateTimeUtc();
+ if(m_transmitting) {
+ if(nsendingsh==1) {
+ lab1->setStyleSheet("QLabel{background-color: #66ffff}");
+ } else if(nsendingsh==-1) {
+ lab1->setStyleSheet("QLabel{background-color: #ffccff}");
+ } else {
+ lab1->setStyleSheet("QLabel{background-color: #ffff33}");
+ }
+ if(m_tune) {
+ lab1->setText("Tx: TUNE");
+ } else {
+ char s[37];
+ sprintf(s,"Tx: %s",msgsent);
+ lab1->setText(s);
+ }
+ } else if(m_monitoring) {
+ lab1->setStyleSheet("QLabel{background-color: #00ff00}");
+ lab1->setText("Receiving ");
+ } else if (!m_diskData) {
+ lab1->setStyleSheet("");
+ lab1->setText("");
+ }
+
+ m_setftx=0;
+ QString utc = t.date().toString("yyyy MMM dd") + "\n " +
+ t.time().toString() + " ";
+ ui->labUTC->setText(utc);
+ if(!m_monitoring and !m_diskData) {
+ signalMeter->setValue(0);
+ }
+
+ if(m_catEnabled and m_poll>0 and (nsec%m_poll)==0 and !m_decoderBusy) {
+ double fMHz;
+ if(m_dontReadFreq) {
+ m_dontReadFreq=false;
+ } else if(!m_transmitting) {
+ for(int iter=0; iter<3; iter++) {
+ fMHz=rig->getFreq(RIG_VFO_CURR)/1000000.0;
+ if(fMHz<0.0 and iter>=2) {
+ rt.sprintf("Rig control error %d\nFailed to read frequency.",
+ int(1000000.0*fMHz));
+ msgBox(rt);
+ m_catEnabled=false;
+ ui->readFreq->setStyleSheet("QPushButton{background-color: red; \
+ border-width: 0px; border-radius: 5px;}");
+ }
+ }
+ int ndiff=1000000.0*(fMHz-m_dialFreq);
+ if(ndiff!=0) dialFreqChanged2(fMHz);
+ }
+ }
+
+ m_sec0=nsec;
+ }
+
+ if(g_iptt!=giptt00 or g_COMportOpen!=gcomport00) {
+ giptt00=g_iptt;
+ gcomport00=g_COMportOpen;
+ }
+
+ iptt0=g_iptt;
+ btxok0=btxok;
+} //End of GUIupdate
+
+void MainWindow::displayTxMsg(QString t)
+{
+ QString bg="yellow";
+ QTextBlockFormat bf;
+ QTextCursor cursor;
+ QString t1=" @ ";
+ if(m_modeTx=="JT65") t1=" # ";
+ QString t2;
+ t2.sprintf("%4d",m_txFreq);
+ t=QDateTime::currentDateTimeUtc().toString("hhmm") + \
+ " Tx " + t2 + t1 + t;
+ QString s = "<table border=0 cellspacing=0 width=100%><tr><td bgcolor=\"" +
+ bg + "\"><pre>" + t + "</pre></td></tr></table>";
+ cursor = ui->decodedTextBrowser2->textCursor();
+ cursor.movePosition(QTextCursor::End);
+ bf = cursor.blockFormat();
+ bf.setBackground(QBrush(QColor(bg)));
+ cursor.insertHtml(s);
+ ui->decodedTextBrowser2->setTextCursor(cursor);
+}
+
+void MainWindow::startTx2()
+{
+ if(!soundOutThread.isRunning()) {
+ QString t=ui->tx6->text();
+ double snr=t.mid(1,5).toDouble();
+ if(snr>0.0 or snr < -50.0) snr=99.0;
+ soundOutThread.setTxSNR(snr);
+ soundOutThread.m_modeTx=m_modeTx;
+ soundOutThread.start(QThread::HighestPriority);
+ signalMeter->setValue(0);
+ m_monitoring=false;
+ soundInThread.setMonitoring(false);
+ btxok=true;
+ m_transmitting=true;
+ ui->pbTxMode->setEnabled(false);
+ }
+}
+
+void MainWindow::stopTx()
+{
+ if (soundOutThread.isRunning()) {
+ soundOutThread.quitExecution=true;
+ soundOutThread.wait(3000);
+ }
+ m_transmitting=false;
+ ui->pbTxMode->setEnabled(true);
+ g_iptt=0;
+ lab1->setStyleSheet("");
+ lab1->setText("");
+ ptt0Timer->start(200); //Sequencer delay
+ m_monitoring=true;
+ soundInThread.setMonitoring(true);
+}
+
+void MainWindow::stopTx2()
+{
+ int ret=0;
+ QString rt;
+
+//Lower PTT
+ if(m_catEnabled and m_bRigOpen and m_pttMethodIndex==0) {
+ ret=rig->setPTT(RIG_PTT_OFF, RIG_VFO_CURR); //CAT control for PTT=0
+ if(ret!=RIG_OK) {
+ rt.sprintf("CAT control PTT failed: %d",ret);
+ msgBox(rt);
+ }
+ }
+ if(m_pttMethodIndex==1 or m_pttMethodIndex==2) {
+ ptt(m_pttPort,0,&g_iptt,&g_COMportOpen);
+ }
+ if(m_73TxDisable and m_sent73) on_stopTxButton_clicked();
+
+ if(m_runaway and m_repeatMsg>m_watchdogLimit) {
+ on_stopTxButton_clicked();
+ msgBox0.setText("Runaway Tx watchdog");
+ msgBox0.show();
+ m_repeatMsg=0;
+ }
+}
+
+void MainWindow::ba2msg(QByteArray ba, char message[]) //ba2msg()
+{
+ int iz=ba.length();
+ for(int i=0;i<22; i++) {
+ if(i<iz) {
+ message[i]=ba[i];
+ } else {
+ message[i]=32;
+ }
+ }
+ message[22]=0;
+}
+
+void MainWindow::on_txFirstCheckBox_stateChanged(int nstate) //TxFirst
+{
+ m_txFirst = (nstate==2);
+}
+
+void MainWindow::set_ntx(int n) //set_ntx()
+{
+ m_ntx=n;
+}
+
+void MainWindow::on_txb1_clicked() //txb1
+{
+ m_ntx=1;
+ ui->txrb1->setChecked(true);
+ m_restart=true;
+}
+
+void MainWindow::on_txb2_clicked() //txb2
+{
+ m_ntx=2;
+ ui->txrb2->setChecked(true);
+ m_restart=true;
+}
+
+void MainWindow::on_txb3_clicked() //txb3
+{
+ m_ntx=3;
+ ui->txrb3->setChecked(true);
+ m_restart=true;
+}
+
+void MainWindow::on_txb4_clicked() //txb4
+{
+ m_ntx=4;
+ ui->txrb4->setChecked(true);
+ m_restart=true;
+}
+
+void MainWindow::on_txb5_clicked() //txb5
+{
+ m_ntx=5;
+ ui->txrb5->setChecked(true);
+ m_restart=true;
+}
+
+void MainWindow::on_txb6_clicked() //txb6
+{
+ m_ntx=6;
+ ui->txrb6->setChecked(true);
+ m_restart=true;
+}
+
+void MainWindow::doubleClickOnCall2(bool shift, bool ctrl)
+{
+
+ m_decodedText2=true;
+ doubleClickOnCall(shift,ctrl);
+ m_decodedText2=false;
+}
+
+void MainWindow::doubleClickOnCall(bool shift, bool ctrl)
+{
+ QTextCursor cursor;
+ if(!m_decodedText2) cursor=ui->decodedTextBrowser2->textCursor();
+ if(m_decodedText2) cursor=ui->decodedTextBrowser->textCursor();
+ cursor.select(QTextCursor::LineUnderCursor);
+ int i2=cursor.position();
+ if(shift and i2==-9999) return; //Silence compiler warning
+
+ QString t;
+ if(!m_decodedText2) t= ui->decodedTextBrowser2->toPlainText(); //Full contents
+ if(m_decodedText2) t= ui->decodedTextBrowser->toPlainText();
+
+ QString t1 = t.mid(0,i2); //contents up to \n on selected line
+ int i1=t1.lastIndexOf("\n") + 1; //points to first char of line
+ QString t2 = t1.mid(i1,i2-i1); //selected line
+// if(t2.indexOf("Tx")==6) return; //Ignore Tx line
+ int i4=t.mid(i1).length();
+ if(i4>55) i4=55;
+ QString t3=t.mid(i1,i4);
+ int i5=t3.indexOf(" CQ DX ");
+ if(i5>0) t3=t3.mid(0,i5+3) + "_" + t3.mid(i5+4); //Make it "CQ_DX" (one word)
+ QStringList t4=t3.split(" ",QString::SkipEmptyParts);
+ if(t4.length() <5) return; //Skip the rest if no decoded text
+
+ int i9=m_QSOmsg.indexOf(t2);
+ if(i9<0 and t2.indexOf("Tx")==-1) {
+ QString bg="white";
+ if(t2.indexOf(" CQ ")>0) bg="#66ff66"; //green
+ if(m_myCall!="" and t2.indexOf(" "+m_myCall+" ")>0) bg="#ff6666"; //red
+ QTextBlockFormat bf;
+ QString s = "<table border=0 cellspacing=0 width=100%><tr><td bgcolor=\"" +
+ bg + "\"><pre>" + t2 + "</pre></td></tr></table>";
+ cursor = ui->decodedTextBrowser2->textCursor();
+ cursor.movePosition(QTextCursor::End);
+ bf = cursor.blockFormat();
+ bf.setBackground(QBrush(QColor(bg)));
+ cursor.insertHtml(s);
+ ui->decodedTextBrowser2->setTextCursor(cursor);
+ m_QSOmsg=t2;
+ }
+
+ int nfreq=t4.at(3).toInt();
+ if(t4.at(1)=="Tx") nfreq=t4.at(2).toInt();
+ g_pWideGraph->setRxFreq(nfreq); //Set Rx freq
+ if(t4.at(1)=="Tx") {
+ if(ctrl) ui->TxFreqSpinBox->setValue(nfreq); //Set Tx freq
+ return;
+ }
+ if(t4.at(4)=="@") {
+ m_modeTx="JT9";
+ ui->pbTxMode->setText("Tx JT9 @");
+ g_pWideGraph->setModeTx(m_modeTx);
+ }
+ if(t4.at(4)=="#") {
+ m_modeTx="JT65";
+ ui->pbTxMode->setText("Tx JT65 #");
+ g_pWideGraph->setModeTx(m_modeTx);
+ }
+ QString firstcall=t4.at(5);
+ // Don't change Tx freq if a station is calling me, unless m_lockTxFreq
+ // is true or CTRL is held down or
+ if((firstcall!=m_myCall) or m_lockTxFreq or ctrl) {
+ ui->TxFreqSpinBox->setValue(nfreq);
+ }
+ QString hiscall=t4.at(6);
+ QString hisgrid="";
+ if(t4.length()>=8) hisgrid=t4.at(7);
+ if(hiscall!=ui->dxCallEntry->text()) ui->dxGridEntry->setText("");
+ ui->dxCallEntry->setText(hiscall);
+ if(gridOK(hisgrid)) ui->dxGridEntry->setText(hisgrid);
+ if(ui->dxGridEntry->text()=="") lookup();
+ m_hisGrid=ui->dxGridEntry->text();
+ int n = 60*t2.mid(0,2).toInt() + t2.mid(2,2).toInt();
+ int nmod=n%(m_TRperiod/30);
+ m_txFirst=(nmod!=0);
+ ui->txFirstCheckBox->setChecked(m_txFirst);
+ QString rpt=t4.at(1);
+ if(rpt.indexOf(" ")==0) rpt="+" + rpt.mid(2,2);
+ if(rpt.indexOf(" -")==0) rpt=rpt.mid(1,2);
+ if(rpt.indexOf(" ")==0) rpt="+" + rpt.mid(1,2);
+ int nr=rpt.toInt();
+ if(nr<-50) rpt="-50";
+ if(nr>49) rpt="+49";
+ if(nr>=-9 and nr<=-1) rpt="-0" + rpt.mid(1);
+ if(nr>=0 and nr<=9) rpt="+0" + rpt;
+ if(nr>=10) rpt="+" + rpt;
+ ui->rptSpinBox->setValue(rpt.toInt());
+ genStdMsgs(rpt);
+ if(t2.indexOf(m_myCall)>=0) {
+ if(t4.length()>=7 and !gridOK(t4.at(7))) {
+ QString r=t4.at(7);
+ if(r.mid(0,3)=="RRR") {
+ m_ntx=5;
+ ui->txrb5->setChecked(true);
+ if(ui->tabWidget->currentIndex()==1) {
+ ui->genMsg->setText(ui->tx5->text());
+ m_ntx=7;
+ ui->rbGenMsg->setChecked(true);
+ }
+ } else if(r.mid(0,1)=="R") {
+ m_ntx=4;
+ ui->txrb4->setChecked(true);
+ if(ui->tabWidget->currentIndex()==1) {
+ ui->genMsg->setText(ui->tx4->text());
+ m_ntx=7;
+ ui->rbGenMsg->setChecked(true);
+ }
+ } else if(r.toInt()>=-50 and r.toInt()<=49) {
+ m_ntx=3;
+ ui->txrb3->setChecked(true);
+ if(ui->tabWidget->currentIndex()==1) {
+ ui->genMsg->setText(ui->tx3->text());
+ m_ntx=7;
+ ui->rbGenMsg->setChecked(true);
+ }
+ } else if(r.toInt()==73) {
+ m_ntx=5;
+ ui->txrb5->setChecked(true);
+ if(ui->tabWidget->currentIndex()==1) {
+ ui->genMsg->setText(ui->tx5->text());
+ m_ntx=7;
+ ui->rbGenMsg->setChecked(true);
+ }
+ }
+ } else {
+ m_ntx=2;
+ ui->txrb2->setChecked(true);
+ if(ui->tabWidget->currentIndex()==1) {
+ ui->genMsg->setText(ui->tx2->text());
+ m_ntx=7;
+ ui->rbGenMsg->setChecked(true);
+ }
+ }
+
+ } else {
+ m_ntx=1;
+ ui->txrb1->setChecked(true);
+ if(ui->tabWidget->currentIndex()==1) {
+ ui->genMsg->setText(ui->tx1->text());
+ m_ntx=7;
+ ui->rbGenMsg->setChecked(true);
+ }
+ }
+ if(m_quickCall) {
+ m_auto=true;
+ ui->autoButton->setStyleSheet(m_pbAutoOn_style);
+ }
+}
+
+void MainWindow::genStdMsgs(QString rpt) //genStdMsgs()
+{
+ QString t;
+ QString hisCall=ui->dxCallEntry->text().toUpper().trimmed();
+ ui->dxCallEntry->setText(hisCall);
+ if(hisCall=="") {
+ ui->labAz->setText("");
+ ui->labDist->setText("");
+ ui->tx1->setText("");
+ ui->tx2->setText("");
+ ui->tx3->setText("");
+ ui->tx4->setText("");
+ ui->tx5->setText("");
+ ui->tx6->setText("");
+ if(m_myCall!="" and m_myGrid!="") {
+ t="CQ " + m_myCall + " " + m_myGrid.mid(0,4);
+ msgtype(t, ui->tx6);
+ }
+ ui->genMsg->setText("");
+ ui->freeTextMsg->setText("");
+ return;
+ }
+ QString hisBase=baseCall(hisCall);
+ QString myBase=baseCall(m_myCall);
+ QString t0=hisBase + " " + myBase + " ";
+ t=t0 + m_myGrid.mid(0,4);
+ if(myBase!=m_myCall) t="DE " + m_myCall + " " + m_myGrid.mid(0,4);
+ msgtype(t, ui->tx1);
+ if(rpt == "") {
+ t=t+" OOO";
+ msgtype(t, ui->tx2);
+ msgtype("RO", ui->tx3);
+ msgtype("RRR", ui->tx4);
+ msgtype("73", ui->tx5);
+ } else {
+ t=t0 + rpt;
+ msgtype(t, ui->tx2);
+ t=t0 + "R" + rpt;
+ msgtype(t, ui->tx3);
+ t=t0 + "RRR";
+ msgtype(t, ui->tx4);
+ t=t0 + "73";
+ if(myBase!=m_myCall) t="DE " + m_myCall + " 73";
+ msgtype(t, ui->tx5);
+ }
+
+ t="CQ " + m_myCall + " " + m_myGrid.mid(0,4);
+ msgtype(t, ui->tx6);
+ m_ntx=1;
+ ui->txrb1->setChecked(true);
+ m_rpt=rpt;
+}
+
+QString MainWindow::baseCall(QString t)
+{
+ int n1=t.indexOf("/");
+ if(n1<0) return t;
+ int n2=t.length()-n1-1;
+ if(n2>=n1) return t.mid(n1+1);
+ return t.mid(0,n1);
+}
+
+void MainWindow::lookup() //lookup()
+{
+ QString hisCall=ui->dxCallEntry->text().toUpper().trimmed();
+ ui->dxCallEntry->setText(hisCall);
+ QString call3File = m_appDir + "/CALL3.TXT";
+ QFile f(call3File);
+ if(!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ msgBox("Cannot open " + call3File);
+ return;
+ }
+ char c[132];
+ qint64 n=0;
+ for(int i=0; i<999999; i++) {
+ n=f.readLine(c,sizeof(c));
+ if(n <= 0) {
+ ui->dxGridEntry->setText("");
+ break;
+ }
+ QString t=QString(c);
+ if(t.indexOf(hisCall)==0) {
+ int i1=t.indexOf(",");
+ QString hisgrid=t.mid(i1+1,6);
+ i1=hisgrid.indexOf(",");
+ if(i1>0) {
+ hisgrid=hisgrid.mid(0,4);
+ } else {
+ hisgrid=hisgrid.mid(0,4) + hisgrid.mid(4,2).toLower();
+ }
+ ui->dxGridEntry->setText(hisgrid);
+ break;
+ }
+ }
+ f.close();
+}
+
+void MainWindow::on_lookupButton_clicked() //Lookup button
+{
+ lookup();
+}
+
+void MainWindow::on_addButton_clicked() //Add button
+{
+ if(ui->dxGridEntry->text()=="") {
+ msgBox("Please enter a valid grid locator.");
+ return;
+ }
+ m_call3Modified=false;
+ QString hisCall=ui->dxCallEntry->text().toUpper().trimmed();
+ QString hisgrid=ui->dxGridEntry->text().trimmed();
+ QString newEntry=hisCall + "," + hisgrid;
+
+// int ret = QMessageBox::warning(this, "Add",
+// newEntry + "\n" + "Is this station known to be active on EME?",
+// QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+// if(ret==QMessageBox::Yes) {
+// newEntry += ",EME,,";
+// } else {
+ newEntry += ",,,";
+// }
+
+ QString call3File = m_appDir + "/CALL3.TXT";
+ QFile f1(call3File);
+ if(!f1.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ msgBox("Cannot open " + call3File);
+ return;
+ }
+ if(f1.size()==0) {
+ f1.close();
+ f1.open(QIODevice::WriteOnly | QIODevice::Text);
+ QTextStream out(&f1);
+ out << "ZZZZZZ" << endl;
+ f1.close();
+ f1.open(QIODevice::ReadOnly | QIODevice::Text);
+ }
+ QString tmpFile = m_appDir + "/CALL3.TMP";
+ QFile f2(tmpFile);
+ if(!f2.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ msgBox("Cannot open " + tmpFile);
+ return;
+ }
+ QTextStream in(&f1);
+ QTextStream out(&f2);
+ QString hc=hisCall;
+ QString hc1="";
+ QString hc2="AAAAAA";
+ QString s;
+ do {
+ s=in.readLine();
+ hc1=hc2;
+ if(s.mid(0,2)=="//") {
+ out << s + "\n";
+ } else {
+ int i1=s.indexOf(",");
+ hc2=s.mid(0,i1);
+ if(hc>hc1 && hc<hc2) {
+ out << newEntry + "\n";
+ if(s.mid(0,6)=="ZZZZZZ") {
+ out << s + "\n";
+// exit; //Statement has no effect!
+ }
+ m_call3Modified=true;
+ } else if(hc==hc2) {
+ QString t=s + "\n\n is already in CALL3.TXT\n" +
+ "Do you wish to replace it?";
+ int ret = QMessageBox::warning(this, "Add",t,
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ if(ret==QMessageBox::Yes) {
+ out << newEntry + "\n";
+ m_call3Modified=true;
+ }
+ } else {
+ if(s!="") out << s + "\n";
+ }
+ }
+ } while(!s.isNull());
+
+ f1.close();
+ if(hc>hc1 && !m_call3Modified) {
+ out << newEntry + "\n";
+ }
+ if(m_call3Modified) {
+ QFile f0(m_appDir + "/CALL3.OLD");
+ if(f0.exists()) f0.remove();
+ QFile f1(m_appDir + "/CALL3.TXT");
+ f1.rename(m_appDir + "/CALL3.OLD");
+ f2.rename(m_appDir + "/CALL3.TXT");
+ f2.close();
+ }
+}
+
+void MainWindow::msgtype(QString t, QLineEdit* tx) //msgtype()
+{
+ char message[23];
+ char msgsent[23];
+ int len1=22;
+
+ t=t.toUpper();
+ QByteArray s=t.toUpper().toLocal8Bit();
+ ba2msg(s,message);
+ int ichk=1,itext=0;
+ genjt9_(message,&ichk,msgsent,itone,&itext,len1,len1);
+ msgsent[22]=0;
+ bool text=false;
+ if(itext!=0) text=true;
+ QString t1;
+ t1.fromLatin1(msgsent);
+ if(text) t1=t1.mid(0,13);
+ QPalette p(tx->palette());
+ if(text) {
+ p.setColor(QPalette::Base,"#ffccff");
+ } else {
+ p.setColor(QPalette::Base,Qt::white);
+ }
+ tx->setPalette(p);
+ int len=t.length();
+ if(text) {
+ len=qMin(len,13);
+ tx->setText(t.mid(0,len).toUpper());
+ } else {
+ tx->setText(t);
+ }
+}
+
+void MainWindow::on_tx1_editingFinished() //tx1 edited
+{
+ QString t=ui->tx1->text();
+ msgtype(t, ui->tx1);
+}
+
+void MainWindow::on_tx2_editingFinished() //tx2 edited
+{
+ QString t=ui->tx2->text();
+ msgtype(t, ui->tx2);
+}
+
+void MainWindow::on_tx3_editingFinished() //tx3 edited
+{
+ QString t=ui->tx3->text();
+ msgtype(t, ui->tx3);
+}
+
+void MainWindow::on_tx4_editingFinished() //tx4 edited
+{
+ QString t=ui->tx4->text();
+ msgtype(t, ui->tx4);
+}
+
+void MainWindow::on_tx5_editingFinished() //tx5 edited
+{
+ QString t=ui->tx5->text();
+ msgtype(t, ui->tx5);
+}
+
+void MainWindow::on_tx6_editingFinished() //tx6 edited
+{
+ QString t=ui->tx6->text();
+ msgtype(t, ui->tx6);
+ double snr=t.mid(1,5).toDouble();
+ if(snr>0.0 or snr < -50.0) snr=99.0;
+ soundOutThread.setTxSNR(snr);
+}
+
+void MainWindow::on_dxCallEntry_textChanged(const QString &t) //dxCall changed
+{
+ m_hisCall=t.toUpper().trimmed();
+ ui->dxCallEntry->setText(m_hisCall);
+ statusChanged();
+}
+
+void MainWindow::on_dxGridEntry_textChanged(const QString &t) //dxGrid changed
+{
+ int n=t.length();
+ if(n!=4 and n!=6) {
+ ui->labAz->setText("");
+ ui->labDist->setText("");
+ return;
+ }
+ if(!t[0].isLetter() or !t[1].isLetter()) return;
+ if(!t[2].isDigit() or !t[3].isDigit()) return;
+ if(n==4) m_hisGrid=t.mid(0,2).toUpper() + t.mid(2,2);
+ if(n==6) m_hisGrid=t.mid(0,2).toUpper() + t.mid(2,2) +
+ t.mid(4,2).toLower();
+ ui->dxGridEntry->setText(m_hisGrid);
+ if(gridOK(m_hisGrid)) {
+ qint64 nsec = QDateTime::currentMSecsSinceEpoch() % 86400;
+ double utch=nsec/3600.0;
+ int nAz,nEl,nDmiles,nDkm,nHotAz,nHotABetter;
+
+ azdist_(m_myGrid.toLatin1().data(),m_hisGrid.toLatin1().data(),&utch,
+ &nAz,&nEl,&nDmiles,&nDkm,&nHotAz,&nHotABetter,6,6);
+ QString t;
+ t.sprintf("Az: %d",nAz);
+ ui->labAz->setText(t);
+ if(m_bMiles) t.sprintf("%d mi",int(0.621371*nDkm));
+ if(!m_bMiles) t.sprintf("%d km",nDkm);
+ ui->labDist->setText(t);
+ } else {
+ ui->labAz->setText("");
+ ui->labDist->setText("");
+ }
+}
+
+void MainWindow::on_genStdMsgsPushButton_clicked() //genStdMsgs button
+{
+ genStdMsgs(m_rpt);
+}
+
+void MainWindow::on_logQSOButton_clicked() //Log QSO button
+{
+ if(m_hisCall=="") return;
+ m_dateTimeQSO=QDateTime::currentDateTimeUtc();
+
+ logDlg = new LogQSO(0);
+ logDlg->m_saveTxPower=m_saveTxPower;
+ logDlg->m_saveComments=m_saveComments;
+ logDlg->m_txPower=m_txPower;
+ logDlg->m_comments=m_logComments;
+ logDlg->initLogQSO(m_hisCall,m_hisGrid,m_modeTx,m_rptSent,m_rptRcvd,
+ m_dateTimeQSO,m_dialFreq+m_txFreq/1.0e6,
+ m_myCall,m_myGrid,m_noSuffix,m_toRTTY,m_dBtoComments);
+ connect(logDlg, SIGNAL(acceptQSO(bool)),this,SLOT(acceptQSO2(bool)));
+ if(m_logQSOgeom != QRect(500,400,424,283)) logDlg->setGeometry(m_logQSOgeom);
+ logDlg->show();
+}
+
+void MainWindow::acceptQSO2(bool accepted)
+{
+ if(accepted) {
+ m_logQSOgeom=logDlg->geometry();
+ m_saveTxPower=logDlg->m_saveTxPower;
+ m_saveComments=logDlg->m_saveComments;
+ m_txPower=logDlg->m_txPower;
+ m_logComments=logDlg->m_comments;
+ if(m_clearCallGrid) {
+ m_hisCall="";
+ ui->dxCallEntry->setText("");
+ m_hisGrid="";
+ ui->dxGridEntry->setText("");
+ m_rptSent="";
+ m_rptRcvd="";
+ m_qsoStart="";
+ m_qsoStop="";
+ }
+ }
+}
+
+void MainWindow::on_actionJT9_1_triggered()
+{
+ m_mode="JT9";
+ if(m_modeTx!="JT9") on_pbTxMode_clicked();
+ statusChanged();
+ m_TRperiod=60;
+ m_nsps=6912;
+ m_hsymStop=173;
+ soundInThread.setPeriod(m_TRperiod,m_nsps);
+ soundOutThread.setPeriod(m_TRperiod,m_nsps);
+ lab3->setStyleSheet("QLabel{background-color: #ff6ec7}");
+ lab3->setText(m_mode);
+ ui->actionJT9_1->setChecked(true);
+ g_pWideGraph->setPeriod(m_TRperiod,m_nsps);
+ g_pWideGraph->setMode(m_mode);
+ g_pWideGraph->setModeTx(m_modeTx);
+ ui->pbTxMode->setEnabled(false);
+}
+
+void MainWindow::on_actionJT65_triggered()
+{
+ m_mode="JT65";
+ if(m_modeTx!="JT65") on_pbTxMode_clicked();
+ statusChanged();
+ m_TRperiod=60;
+ m_nsps=6912; //For symspec only
+ m_hsymStop=173;
+ soundInThread.setPeriod(m_TRperiod,m_nsps);
+ soundOutThread.setPeriod(m_TRperiod,m_nsps);
+ lab3->setStyleSheet("QLabel{background-color: #ffff00}");
+ lab3->setText(m_mode);
+ ui->actionJT65->setChecked(true);
+ g_pWideGraph->setPeriod(m_TRperiod,m_nsps);
+ g_pWideGraph->setMode(m_mode);
+ g_pWideGraph->setModeTx(m_modeTx);
+ ui->pbTxMode->setEnabled(false);
+}
+
+void MainWindow::on_actionJT9_JT65_triggered()
+{
+ m_mode="JT9+JT65";
+// if(m_modeTx!="JT9") on_pbTxMode_clicked();
+ statusChanged();
+ m_TRperiod=60;
+ m_nsps=6912;
+ m_hsymStop=173;
+ soundInThread.setPeriod(m_TRperiod,m_nsps);
+ soundOutThread.setPeriod(m_TRperiod,m_nsps);
+ lab3->setStyleSheet("QLabel{background-color: #ffa500}");
+ lab3->setText(m_mode);
+ ui->actionJT9_JT65->setChecked(true);
+ g_pWideGraph->setPeriod(m_TRperiod,m_nsps);
+ g_pWideGraph->setMode(m_mode);
+ g_pWideGraph->setModeTx(m_modeTx);
+ ui->pbTxMode->setEnabled(true);
+}
+
+void MainWindow::on_TxFreqSpinBox_valueChanged(int n)
+{
+ m_txFreq=n;
+ if(g_pWideGraph!=NULL) g_pWideGraph->setTxFreq(n);
+ if(m_lockTxFreq) ui->RxFreqSpinBox->setValue(n);
+ soundOutThread.setTxFreq(n);
+}
+
+void MainWindow::on_RxFreqSpinBox_valueChanged(int n)
+{
+ m_rxFreq=n;
+ if(g_pWideGraph!=NULL) g_pWideGraph->setRxFreq(n);
+ if(m_lockTxFreq) ui->TxFreqSpinBox->setValue(n);
+}
+
+void MainWindow::on_actionQuickDecode_triggered()
+{
+ m_ndepth=1;
+ ui->actionQuickDecode->setChecked(true);
+}
+
+void MainWindow::on_actionMediumDecode_triggered()
+{
+ m_ndepth=2;
+ ui->actionMediumDecode->setChecked(true);
+}
+
+void MainWindow::on_actionDeepestDecode_triggered()
+{
+ m_ndepth=3;
+ ui->actionDeepestDecode->setChecked(true);
+}
+
+void MainWindow::on_inGain_valueChanged(int n)
+{
+ m_inGain=n;
+}
+
+void MainWindow::on_actionMonitor_OFF_at_startup_triggered()
+{
+ m_monitorStartOFF=!m_monitorStartOFF;
+}
+
+void MainWindow::on_actionErase_ALL_TXT_triggered() //Erase ALL.TXT
+{
+ int ret = QMessageBox::warning(this, "Confirm Erase",
+ "Are you sure you want to erase file ALL.TXT ?",
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ if(ret==QMessageBox::Yes) {
+ QFile f("ALL.TXT");
+ f.remove();
+ m_RxLog=1;
+ }
+}
+
+void MainWindow::on_actionErase_wsjtx_log_adi_triggered()
+{
+ int ret = QMessageBox::warning(this, "Confirm Erase",
+ "Are you sure you want to erase file wsjtx_log.adi ?",
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ if(ret==QMessageBox::Yes) {
+ QFile f("wsjtx_log.adi");
+ f.remove();
+ }
+}
+
+void MainWindow::showMacros(const QPoint &pos)
+{
+ if(m_macro.length()<10) return;
+ QPoint globalPos = ui->tx5->mapToGlobal(pos);
+ QMenu popupMenu;
+ QAction* popup1 = new QAction(m_macro[0],ui->tx5);
+ QAction* popup2 = new QAction(m_macro[1],ui->tx5);
+ QAction* popup3 = new QAction(m_macro[2],ui->tx5);
+ QAction* popup4 = new QAction(m_macro[3],ui->tx5);
+ QAction* popup5 = new QAction(m_macro[4],ui->tx5);
+ QAction* popup6 = new QAction(m_macro[5],ui->tx5);
+ QAction* popup7 = new QAction(m_macro[6],ui->tx5);
+ QAction* popup8 = new QAction(m_macro[7],ui->tx5);
+ QAction* popup9 = new QAction(m_macro[8],ui->tx5);
+ QAction* popup10 = new QAction(m_macro[9],ui->tx5);
+
+ if(m_macro[0]!="") popupMenu.addAction(popup1);
+ if(m_macro[1]!="") popupMenu.addAction(popup2);
+ if(m_macro[2]!="") popupMenu.addAction(popup3);
+ if(m_macro[3]!="") popupMenu.addAction(popup4);
+ if(m_macro[4]!="") popupMenu.addAction(popup5);
+ if(m_macro[5]!="") popupMenu.addAction(popup6);
+ if(m_macro[6]!="") popupMenu.addAction(popup7);
+ if(m_macro[7]!="") popupMenu.addAction(popup8);
+ if(m_macro[8]!="") popupMenu.addAction(popup9);
+ if(m_macro[9]!="") popupMenu.addAction(popup10);
+
+ connect(popup1,SIGNAL(triggered()), this, SLOT(onPopup1()));
+ connect(popup2,SIGNAL(triggered()), this, SLOT(onPopup2()));
+ connect(popup3,SIGNAL(triggered()), this, SLOT(onPopup3()));
+ connect(popup4,SIGNAL(triggered()), this, SLOT(onPopup4()));
+ connect(popup5,SIGNAL(triggered()), this, SLOT(onPopup5()));
+ connect(popup6,SIGNAL(triggered()), this, SLOT(onPopup6()));
+ connect(popup7,SIGNAL(triggered()), this, SLOT(onPopup7()));
+ connect(popup8,SIGNAL(triggered()), this, SLOT(onPopup8()));
+ connect(popup9,SIGNAL(triggered()), this, SLOT(onPopup9()));
+ connect(popup10,SIGNAL(triggered()), this, SLOT(onPopup10()));
+ popupMenu.exec(globalPos);
+}
+
+void MainWindow::onPopup1() { ui->tx5->setText(m_macro[0]); freeText(); }
+void MainWindow::onPopup2() { ui->tx5->setText(m_macro[1]); freeText(); }
+void MainWindow::onPopup3() { ui->tx5->setText(m_macro[2]); freeText(); }
+void MainWindow::onPopup4() { ui->tx5->setText(m_macro[3]); freeText(); }
+void MainWindow::onPopup5() { ui->tx5->setText(m_macro[4]); freeText(); }
+void MainWindow::onPopup6() { ui->tx5->setText(m_macro[5]); freeText(); }
+void MainWindow::onPopup7() { ui->tx5->setText(m_macro[6]); freeText(); }
+void MainWindow::onPopup8() { ui->tx5->setText(m_macro[7]); freeText(); }
+void MainWindow::onPopup9() { ui->tx5->setText(m_macro[8]); freeText(); }
+void MainWindow::onPopup10() { ui->tx5->setText(m_macro[9]); freeText(); }
+
+void MainWindow::freeText() { ui->freeTextMsg->setText(ui->tx5->text()); }
+
+bool MainWindow::gridOK(QString g)
+{
+ bool b=g.mid(0,1).compare("A")>=0 and
+ g.mid(0,1).compare("R")<=0 and
+ g.mid(1,1).compare("A")>=0 and
+ g.mid(1,1).compare("R")<=0 and
+ g.mid(2,1).compare("0")>=0 and
+ g.mid(2,1).compare("9")<=0 and
+ g.mid(3,1).compare("0")>=0 and
+ g.mid(3,1).compare("9")<=0;
+ return b;
+}
+
+void MainWindow::on_actionConvert_JT9_x_to_RTTY_triggered(bool checked)
+{
+ m_toRTTY=checked;
+}
+
+void MainWindow::on_actionLog_JT9_without_submode_triggered(bool checked)
+{
+ m_noSuffix=checked;
+}
+
+void MainWindow::on_actionLog_dB_reports_to_Comments_triggered(bool checked)
+{
+ m_dBtoComments=checked;
+}
+
+void MainWindow::on_bandComboBox_activated(int index)
+{
+ int ret=0;
+ QString rt;
+
+ m_band=index;
+ QString t=m_dFreq[index];
+ m_dialFreq=t.toDouble();
+ if(m_plus2kHz) m_dialFreq+=0.002;
+ dialFreqChanged2(m_dialFreq);
+ m_repeatMsg=0;
+ m_secBandChanged=QDateTime::currentMSecsSinceEpoch()/1000;
+ if(m_catEnabled) {
+ if(!m_bRigOpen) {
+ rigOpen();
+ }
+ if(m_bRigOpen) {
+ m_dontReadFreq=true;
+ ret=rig->setFreq(MHz(m_dialFreq));
+ if(m_bSplit or m_bXIT) setXIT(m_txFreq);
+
+ if(g_pWideGraph!=NULL) {
+ bumpFqso(11);
+ bumpFqso(12);
+ }
+ if(ret!=RIG_OK) {
+ rt.sprintf("Set rig frequency failed: %d",ret);
+ msgBox(rt);
+ }
+ }
+ }
+ QFile f2("ALL.TXT");
+ f2.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
+ QTextStream out(&f2);
+ out << QDateTime::currentDateTimeUtc().toString("yyyy-MMM-dd hh:mm")
+ << " " << m_dialFreq << " MHz " << m_mode << endl;
+ f2.close();
+}
+
+void MainWindow::on_actionPrompt_to_log_QSO_triggered(bool checked)
+{
+ m_promptToLog=checked;
+}
+
+void MainWindow::on_actionBlank_line_between_decoding_periods_triggered(bool checked)
+{
+ m_insertBlank=checked;
+}
+
+void MainWindow::on_actionClear_DX_Call_and_Grid_after_logging_triggered(bool checked)
+{
+ m_clearCallGrid=checked;
+}
+
+void MainWindow::on_actionDisplay_distance_in_miles_triggered(bool checked)
+{
+ m_bMiles=checked;
+ on_dxGridEntry_textChanged(m_hisGrid);
+}
+
+void MainWindow::on_pbCallCQ_clicked()
+{
+ genStdMsgs(m_rpt);
+ ui->genMsg->setText(ui->tx6->text());
+ m_ntx=7;
+ ui->rbGenMsg->setChecked(true);
+ if(m_transmitting) m_restart=true;
+}
+
+void MainWindow::on_pbAnswerCaller_clicked()
+{
+ genStdMsgs(m_rpt);
+ ui->genMsg->setText(ui->tx2->text());
+ m_ntx=7;
+ ui->rbGenMsg->setChecked(true);
+ if(m_transmitting) m_restart=true;
+}
+
+void MainWindow::on_pbSendRRR_clicked()
+{
+ genStdMsgs(m_rpt);
+ ui->genMsg->setText(ui->tx4->text());
+ m_ntx=7;
+ ui->rbGenMsg->setChecked(true);
+ if(m_transmitting) m_restart=true;
+}
+
+void MainWindow::on_pbAnswerCQ_clicked()
+{
+ genStdMsgs(m_rpt);
+ ui->genMsg->setText(ui->tx1->text());
+ m_ntx=7;
+ ui->rbGenMsg->setChecked(true);
+ if(m_transmitting) m_restart=true;
+}
+
+void MainWindow::on_pbSendReport_clicked()
+{
+ genStdMsgs(m_rpt);
+ ui->genMsg->setText(ui->tx3->text());
+ m_ntx=7;
+ ui->rbGenMsg->setChecked(true);
+ if(m_transmitting) m_restart=true;
+}
+
+void MainWindow::on_pbSend73_clicked()
+{
+ genStdMsgs(m_rpt);
+ ui->genMsg->setText(ui->tx5->text());
+ m_ntx=7;
+ ui->rbGenMsg->setChecked(true);
+ if(m_transmitting) m_restart=true;
+}
+
+void MainWindow::on_rbGenMsg_toggled(bool checked)
+{
+ m_freeText=!checked;
+ if(!m_freeText) {
+ m_ntx=7;
+ if(m_transmitting) m_restart=true;
+ }
+}
+
+void MainWindow::on_rbFreeText_toggled(bool checked)
+{
+ m_freeText=checked;
+ if(m_freeText) {
+ m_ntx=8;
+ if (m_transmitting) m_restart=true;
+ }
+}
+
+void MainWindow::on_freeTextMsg_editingFinished()
+{
+ QString t=ui->freeTextMsg->text();
+ msgtype(t, ui->freeTextMsg);
+}
+
+void MainWindow::on_actionDouble_click_on_call_sets_Tx_Enable_triggered(bool checked)
+{
+ m_quickCall=checked;
+}
+
+void MainWindow::on_rptSpinBox_valueChanged(int n)
+{
+ m_rpt=QString::number(n);
+ int ntx0=m_ntx;
+ QString t=ui->tx5->text();
+ genStdMsgs(m_rpt);
+ ui->tx5->setText(t);
+ m_ntx=ntx0;
+ if(m_ntx==1) ui->txrb1->setChecked(true);
+ if(m_ntx==2) ui->txrb2->setChecked(true);
+ if(m_ntx==3) ui->txrb3->setChecked(true);
+ if(m_ntx==4) ui->txrb4->setChecked(true);
+ if(m_ntx==5) ui->txrb5->setChecked(true);
+ if(m_ntx==6) ui->txrb6->setChecked(true);
+ statusChanged();
+}
+
+void MainWindow::on_action_73TxDisable_triggered(bool checked)
+{
+ m_73TxDisable=checked;
+}
+
+void MainWindow::on_actionRunaway_Tx_watchdog_triggered(bool checked)
+{
+ m_runaway=checked;
+}
+
+void MainWindow::on_tuneButton_clicked()
+{
+ if(m_tune) {
+ nc1=1; //disable the countdown timer
+ tuneButtonTimer->start(250);
+ } else {
+ m_tune=true;
+ m_sent73=false;
+ soundOutThread.setTune(m_tune);
+ m_repeatMsg=0;
+ ui->tuneButton->setStyleSheet(m_pbTune_style);
+ }
+}
+
+void MainWindow::on_stopTxButton_clicked() //Stop Tx
+{
+ if(m_tune) {
+ m_tune=false;
+ soundOutThread.setTune(m_tune);
+ }
+ if(m_auto) on_autoButton_clicked();
+ btxok=false;
+ m_repeatMsg=0;
+ ui->tuneButton->setStyleSheet("");
+}
+
+void MainWindow::rigOpen()
+{
+ QString t;
+ int ret;
+ rig = new Rig();
+
+ if(m_rig<9900) {
+ if (!rig->init(m_rig)) {
+ msgBox("Rig init failure");
+ return;
+ }
+ QString sCATport=m_catPort;
+#ifdef WIN32
+ sCATport="\\\\.\\" + m_catPort; //Allow COM ports above 9
+#endif
+ rig->setConf("rig_pathname", sCATport.toLatin1().data());
+ char buf[80];
+ sprintf(buf,"%d",m_serialRate);
+ rig->setConf("serial_speed",buf);
+ sprintf(buf,"%d",m_dataBits);
+ rig->setConf("data_bits",buf);
+ sprintf(buf,"%d",m_stopBits);
+ rig->setConf("stop_bits",buf);
+ rig->setConf("serial_handshake",m_handshake.toLatin1().data());
+ if(m_bDTRoff) {
+ rig->setConf("rts_state","OFF");
+ rig->setConf("dtr_state","OFF");
+ }
+ }
+
+ ret=rig->open(m_rig);
+ if(ret==RIG_OK) {
+ m_bRigOpen=true;
+ if(m_poll==0) ui->readFreq->setEnabled(true);
+ m_CATerror=false;
+ } else {
+ t="Open rig failed";
+ msgBox(t);
+ m_catEnabled=false;
+ m_bRigOpen=false;
+ m_CATerror=true;
+ }
+
+ if(m_bRigOpen) {
+ if(m_poll>0) {
+ ui->readFreq->setStyleSheet("QPushButton{background-color: #00ff00; \
+ border-width: 0px; border-radius: 5px;}");
+ } else {
+ ui->readFreq->setStyleSheet("QPushButton{background-color: orange; \
+ border-width: 0px; border-radius: 5px;}");
+ }
+} else {
+if(m_CATerror) ui->readFreq->setStyleSheet("QPushButton{background-color: red; \
+ border-width: 0px; border-radius: 5px;}");
+if(!m_CATerror) ui->readFreq->setStyleSheet("");
+ }
+}
+
+void MainWindow::on_actionAllow_multiple_instances_triggered(bool checked)
+{
+ m_bMultipleOK=checked;
+}
+
+void MainWindow::on_pbR2T_clicked()
+{
+ int n=g_pWideGraph->rxFreq();
+ ui->TxFreqSpinBox->setValue(n);
+}
+
+void MainWindow::on_pbT2R_clicked()
+{
+ g_pWideGraph->setRxFreq(m_txFreq);
+}
+
+
+void MainWindow::on_readFreq_clicked()
+{
+ if(m_transmitting) return;
+ m_dontReadFreq=false;
+ double fMHz=rig->getFreq(RIG_VFO_CURR)/1000000.0;
+ if(fMHz<0.0) {
+ QString rt;
+ rt.sprintf("Rig control error %d\nFailed to read frequency.",
+ int(1000000.0*fMHz));
+ msgBox(rt);
+ m_catEnabled=false;
+ }
+ if(fMHz<0.01 or fMHz>1300.0) fMHz=0;
+ int ndiff=1000000.0*(fMHz-m_dialFreq);
+ if(ndiff!=0) dialFreqChanged2(fMHz);
+}
+
+void MainWindow::on_pbTxMode_clicked()
+{
+ if(m_modeTx=="JT9") {
+ m_modeTx="JT65";
+ ui->pbTxMode->setText("Tx JT65 #");
+ } else {
+ m_modeTx="JT9";
+ ui->pbTxMode->setText("Tx JT9 @");
+ }
+ g_pWideGraph->setModeTx(m_modeTx);
+ statusChanged();
+}
+
+void MainWindow::setXIT(int n)
+{
+ int ret;
+ int xit=0;
+ if(m_bRigOpen) {
+ xit=-1000;
+ if(n>1000) xit=0;
+ if(n>2000) xit=1000;
+ if(n>3000) xit=2000;
+ if(n>4000) xit=3000;
+ if(m_bXIT) {
+ ret=rig->setXit((shortfreq_t)xit,RIG_VFO_TX);
+ if(ret!=RIG_OK) {
+ QString rt;
+ rt.sprintf("Setting RIG_VFO_TX failed: %d",ret);
+ msgBox(rt);
+ }
+ }
+ if(m_bSplit) {
+ ret=rig->setSplitFreq(MHz(m_dialFreq)+xit,RIG_VFO_B);
+ }
+ }
+ if(m_bSplit) soundOutThread.setXIT(xit);
+ if(!m_bSplit) soundOutThread.setXIT(0);
+}
+
+void MainWindow::setFreq4(int rxFreq, int txFreq)
+{
+ m_rxFreq=rxFreq;
+ m_txFreq=txFreq;
+ ui->RxFreqSpinBox->setValue(m_rxFreq);
+ ui->TxFreqSpinBox->setValue(m_txFreq);
+}
+
+void MainWindow::on_cbTxLock_clicked(bool checked)
+{
+ m_lockTxFreq=checked;
+ g_pWideGraph->setLockTxFreq(m_lockTxFreq);
+ if(m_lockTxFreq) on_pbR2T_clicked();
+}
+
+void MainWindow::on_actionTx2QSO_triggered(bool checked)
+{
+ m_tx2QSO=checked;
+}
+
+void MainWindow::on_cbPlus2kHz_toggled(bool checked)
+{
+ m_plus2kHz=checked;
+ on_bandComboBox_activated(m_band);
+}
diff --git a/mainwindow.h b/mainwindow.h
new file mode 100644
index 0000000..51e0b41
--- /dev/null
+++ b/mainwindow.h
@@ -0,0 +1,392 @@
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+#ifdef QT5
+#include <QtWidgets>
+#else
+#include <QtGui>
+#endif
+#include <QTimer>
+#include <QDateTime>
+#include "soundin.h"
+#include "soundout.h"
+#include "commons.h"
+#include "psk_reporter.h"
+#include "rigclass.h"
+#include "signalmeter.h"
+
+#ifdef WIN32
+#include "PSKReporter.h"
+#endif
+
+//--------------------------------------------------------------- MainWindow
+namespace Ui {
+ class MainWindow;
+}
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+// Multiple instances: call MainWindow() with *thekey
+public:
+ explicit MainWindow(QSharedMemory *shdmem, QString *thekey, QWidget *parent = 0);
+ ~MainWindow();
+
+public slots:
+ void showSoundInError(const QString& errorMsg);
+ void showStatusMessage(const QString& statusMsg);
+ void dataSink(int k);
+ void diskDat();
+ void diskWriteFinished();
+ void freezeDecode(int n);
+ void guiUpdate();
+ void doubleClickOnCall(bool shift, bool ctrl);
+ void doubleClickOnCall2(bool shift, bool ctrl);
+ void readFromStdout();
+ void readFromStderr();
+ void jt9_error();
+ void setXIT(int n);
+ void setFreq4(int rxFreq, int txFreq);
+
+protected:
+ virtual void keyPressEvent( QKeyEvent *e );
+ void closeEvent(QCloseEvent*);
+ virtual bool eventFilter(QObject *object, QEvent *event);
+
+private slots:
+ void on_tx1_editingFinished();
+ void on_tx2_editingFinished();
+ void on_tx3_editingFinished();
+ void on_tx4_editingFinished();
+ void on_tx5_editingFinished();
+ void on_tx6_editingFinished();
+ void on_actionDeviceSetup_triggered();
+ void on_monitorButton_clicked();
+ void on_actionExit_triggered();
+ void on_actionAbout_triggered();
+ void OnExit();
+ void on_actionLinrad_triggered();
+ void on_actionCuteSDR_triggered();
+ void on_autoButton_clicked();
+ void on_stopTxButton_clicked();
+ void on_stopButton_clicked();
+ void on_actionOnline_Users_Guide_triggered();
+ void on_actionWide_Waterfall_triggered();
+ void on_actionOpen_triggered();
+ void on_actionOpen_next_in_directory_triggered();
+ void on_actionDecode_remaining_files_in_directory_triggered();
+ void on_actionDelete_all_wav_files_in_SaveDir_triggered();
+ void on_actionNone_triggered();
+ void on_actionSave_all_triggered();
+ void on_actionKeyboard_shortcuts_triggered();
+ void on_actionSpecial_mouse_commands_triggered();
+ void on_DecodeButton_clicked();
+ void decode();
+ void decodeBusy(bool b);
+ void on_EraseButton_clicked();
+ void on_txb1_clicked();
+ void on_txFirstCheckBox_stateChanged(int arg1);
+ void set_ntx(int n);
+ void on_txb2_clicked();
+ void on_txb3_clicked();
+ void on_txb4_clicked();
+ void on_txb5_clicked();
+ void on_txb6_clicked();
+ void on_lookupButton_clicked();
+ void on_addButton_clicked();
+ void on_dxCallEntry_textChanged(const QString &arg1);
+ void on_dxGridEntry_textChanged(const QString &arg1);
+ void on_genStdMsgsPushButton_clicked();
+ void on_logQSOButton_clicked();
+ void on_actionAFMHot_triggered();
+ void on_actionBlue_triggered();
+ void on_actionJT9_1_triggered();
+ void on_actionJT65_triggered();
+ void on_actionJT9_JT65_triggered();
+ void on_TxFreqSpinBox_valueChanged(int arg1);
+ void on_actionSave_decoded_triggered();
+ void on_actionQuickDecode_triggered();
+ void on_actionMediumDecode_triggered();
+ void on_actionDeepestDecode_triggered();
+ void on_inGain_valueChanged(int n);
+ void bumpFqso(int n);
+ void on_actionMonitor_OFF_at_startup_triggered();
+ void on_actionErase_ALL_TXT_triggered();
+ void on_actionErase_wsjtx_log_adi_triggered();
+ void showMacros(const QPoint& pos);
+ void onPopup1();
+ void onPopup2();
+ void onPopup3();
+ void onPopup4();
+ void onPopup5();
+ void onPopup6();
+ void onPopup7();
+ void onPopup8();
+ void onPopup9();
+ void onPopup10();
+ void on_actionConvert_JT9_x_to_RTTY_triggered(bool checked);
+ void on_actionLog_JT9_without_submode_triggered(bool checked);
+ void on_actionLog_dB_reports_to_Comments_triggered(bool checked);
+ void startTx2();
+ void stopTx();
+ void stopTx2();
+ void on_actionPrompt_to_log_QSO_triggered(bool checked);
+ void on_actionBlank_line_between_decoding_periods_triggered(bool checked);
+ void on_actionClear_DX_Call_and_Grid_after_logging_triggered(bool checked);
+ void on_actionDisplay_distance_in_miles_triggered(bool checked);
+ void on_pbCallCQ_clicked();
+ void on_pbAnswerCaller_clicked();
+ void on_pbSendRRR_clicked();
+ void on_pbAnswerCQ_clicked();
+ void on_pbSendReport_clicked();
+ void on_pbSend73_clicked();
+ void on_rbGenMsg_toggled(bool checked);
+ void on_rbFreeText_toggled(bool checked);
+ void on_freeTextMsg_editingFinished();
+ void on_actionDouble_click_on_call_sets_Tx_Enable_triggered(bool checked);
+ void on_rptSpinBox_valueChanged(int n);
+ void on_action_73TxDisable_triggered(bool checked);
+ void on_actionRunaway_Tx_watchdog_triggered(bool checked);
+ void killFile();
+ void on_tuneButton_clicked();
+ void on_actionAllow_multiple_instances_triggered(bool checked);
+ void on_pbR2T_clicked();
+ void on_pbT2R_clicked();
+ void acceptQSO2(bool accepted);
+ void on_bandComboBox_activated(int index);
+ void on_readFreq_clicked();
+ void on_pbTxMode_clicked();
+ void on_RxFreqSpinBox_valueChanged(int n);
+ void on_cbTxLock_clicked(bool checked);
+ void on_actionTx2QSO_triggered(bool checked);
+ void on_cbPlus2kHz_toggled(bool checked);
+
+private:
+ Ui::MainWindow *ui;
+
+ double m_dialFreq;
+
+ qint64 m_msErase;
+ qint64 m_secBandChanged;
+
+ qint32 m_idInt;
+ qint32 m_waterfallAvg;
+ qint32 m_pttMethodIndex;
+ qint32 m_ntx;
+ qint32 m_pttPort;
+ qint32 m_timeout;
+ qint32 m_rxFreq;
+ qint32 m_txFreq;
+ qint32 m_setftx;
+ qint32 m_ndepth;
+ qint32 m_sec0;
+ qint32 m_RxLog;
+ qint32 m_nutc0;
+ qint32 m_nrx;
+ qint32 m_hsym;
+ qint32 m_paInDevice;
+ qint32 m_paOutDevice;
+ qint32 m_TRperiod;
+ qint32 m_nsps;
+ qint32 m_hsymStop;
+ qint32 m_len1;
+ qint32 m_inGain;
+ qint32 m_nsave;
+ qint32 m_catPortIndex;
+ qint32 m_rig;
+ qint32 m_rigIndex;
+ qint32 m_serialRate;
+ qint32 m_serialRateIndex;
+ qint32 m_dataBits;
+ qint32 m_dataBitsIndex;
+ qint32 m_stopBits;
+ qint32 m_stopBitsIndex;
+ qint32 m_handshakeIndex;
+ qint32 m_ncw;
+ qint32 m_secID;
+ qint32 m_band;
+ qint32 m_repeatMsg;
+ qint32 m_watchdogLimit;
+ qint32 m_poll;
+ qint32 m_fMin;
+ qint32 m_fMax;
+
+ bool m_monitoring;
+ bool m_transmitting;
+ bool m_diskData;
+ bool m_loopall;
+ bool m_decoderBusy;
+ bool m_txFirst;
+ bool m_auto;
+ bool m_restart;
+ bool m_startAnother;
+ bool m_saveDecoded;
+ bool m_saveAll;
+ bool m_widebandDecode;
+ bool m_call3Modified;
+ bool m_dataAvailable;
+ bool m_killAll;
+ bool m_bdecoded;
+ bool m_monitorStartOFF;
+ bool m_pskReporter;
+ bool m_pskReporterInit;
+ bool m_noSuffix;
+ bool m_toRTTY;
+ bool m_dBtoComments;
+ bool m_catEnabled;
+ bool m_After73;
+ bool m_promptToLog;
+ bool m_blankLine;
+ bool m_insertBlank;
+ bool m_clearCallGrid;
+ bool m_bMiles;
+ bool m_decodedText2;
+ bool m_freeText;
+ bool m_quickCall;
+ bool m_73TxDisable;
+ bool m_sent73;
+ bool m_runaway;
+ bool m_tune;
+ bool m_bRigOpen;
+ bool m_bMultipleOK;
+ bool m_bDTRoff;
+ bool m_pttData;
+ bool m_dontReadFreq;
+ bool m_lockTxFreq;
+ bool m_saveTxPower;
+ bool m_saveComments;
+ bool m_tx2QSO;
+ bool m_CATerror;
+ bool m_bSplit;
+ bool m_bXIT;
+ bool m_plus2kHz;
+
+ char m_decoded[80];
+
+ float m_pctZap;
+
+ QRect m_wideGraphGeom;
+ QRect m_logQSOgeom;
+
+ QLabel* lab1; // labels in status bar
+ QLabel* lab2;
+ QLabel* lab3;
+ QLabel* lab4;
+ QLabel* lab5;
+ QLabel* lab6;
+
+ QMessageBox msgBox0;
+
+ QFuture<void>* future1;
+ QFuture<void>* future2;
+ QFuture<void>* future3;
+ QFutureWatcher<void>* watcher1;
+ QFutureWatcher<void>* watcher2;
+ QFutureWatcher<void>* watcher3;
+
+ QProcess proc_jt9;
+
+ QTimer* ptt1Timer; //StartTx delay
+ QTimer* ptt0Timer; //StopTx delay
+ QTimer* logQSOTimer;
+ QTimer* killFileTimer;
+ QTimer* tuneButtonTimer;
+
+ QString m_path;
+ QString m_pbdecoding_style1;
+ QString m_pbmonitor_style;
+ QString m_pbAutoOn_style;
+ QString m_pbTune_style;
+ QString m_myCall;
+ QString m_myGrid;
+ QString m_baseCall;
+ QString m_hisCall;
+ QString m_hisGrid;
+ QString m_appDir;
+ QString m_saveDir;
+ QString m_dxccPfx;
+ QString m_palette;
+ QString m_dateTime;
+ QString m_mode;
+ QString m_modeTx;
+ QString m_fname;
+ QString m_rpt;
+ QString m_rptSent;
+ QString m_rptRcvd;
+ QString m_qsoStart;
+ QString m_qsoStop;
+ QString m_catPort;
+ QString m_handshake;
+ QString m_cmnd;
+ QString m_msgSent0;
+ QString m_fileToSave;
+ QString m_QSOmsg;
+ QString m_txPower;
+ QString m_logComments;
+ QString m_pskAntenna;
+
+ QStringList m_macro;
+ QStringList m_dFreq;
+
+ QDateTime m_dateTimeQSO;
+
+ SoundInThread soundInThread; //Instantiate the audio threads
+ SoundOutThread soundOutThread;
+ QSharedMemory *mem_jt9;
+ // Multiple instances:
+ QString *mykey_jt9;
+ PSK_Reporter *psk_Reporter;
+ SignalMeter *signalMeter;
+
+//---------------------------------------------------- private functions
+ void readSettings();
+ void writeSettings();
+ void createStatusBar();
+ void updateStatusBar();
+ void msgBox(QString t);
+ void genStdMsgs(QString rpt);
+ void lookup();
+ void ba2msg(QByteArray ba, char* message);
+ void msgtype(QString t, QLineEdit* tx);
+ void stub();
+ void statusChanged();
+ void dialFreqChanged2(double f);
+ void freeText();
+ void displayTxMsg(QString t);
+ void rigOpen();
+ bool gridOK(QString g);
+ QString baseCall(QString t);
+};
+
+extern void getfile(QString fname, int ntrperiod);
+extern void savewav(QString fname, int ntrperiod);
+extern int killbyname(const char* progName);
+extern void getDev(int* numDevices,char hostAPI_DeviceName[][50],
+ int minChan[], int maxChan[],
+ int minSpeed[], int maxSpeed[]);
+extern int ptt(int nport, int ntx, int* iptt, int* nopen);
+
+extern "C" {
+//----------------------------------------------------- C and Fortran routines
+void symspec_(int* k, int* ntrperiod, int* nsps, int* ingain, float* slope,
+ float* px, float s[], float* df3, int* nhsym, int* npts8);
+
+void genjt9_(char* msg, int* ichk, char* msgsent, int itone[],
+ int* itext, int len1, int len2);
+
+void gen65_(char* msg, int* ichk, char* msgsent, int itone[],
+ int* itext, int len1, int len2);
+
+bool stdmsg_(const char* msg, int len);
+
+void azdist_(char* MyGrid, char* HisGrid, double* utch, int* nAz, int* nEl,
+ int* nDmiles, int* nDkm, int* nHotAz, int* nHotABetter,
+ int len1, int len2);
+
+void morse_(char* msg, int* icw, int* ncw, int len);
+
+int ptt_(int nport, int ntx, int* iptt, int* nopen);
+
+}
+
+#endif // MAINWINDOW_H
diff --git a/mainwindow.ui b/mainwindow.ui
new file mode 100644
index 0000000..5c58f21
--- /dev/null
+++ b/mainwindow.ui
@@ -0,0 +1,2925 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>760</width>
+ <height>552</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>760</width>
+ <height>475</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>936</width>
+ <height>1028</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>SpecJT by K1JT</string>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="horizontalSpacing">
+ <number>3</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>1</number>
+ </property>
+ <item row="4" column="0">
+ <widget class="DisplayText" name="decodedTextBrowser">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>100</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>500</width>
+ <height>1000</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <family>Courier New</family>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::Panel</enum>
+ </property>
+ <property name="verticalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOn</enum>
+ </property>
+ <property name="horizontalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOff</enum>
+ </property>
+ <property name="html">
+ <string notr="true"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'Courier New'; font-size:10pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></string>
+ </property>
+ <property name="acceptRichText">
+ <bool>false</bool>
+ </property>
+ <property name="openLinks">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLabel" name="decodedTextLabel2">
+ <property name="minimumSize">
+ <size>
+ <width>300</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>500</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="palette">
+ <palette>
+ <active>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>252</red>
+ <green>252</green>
+ <blue>252</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>170</red>
+ <green>170</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>252</red>
+ <green>252</green>
+ <blue>252</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>170</red>
+ <green>170</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>170</red>
+ <green>170</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>170</red>
+ <green>170</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <property name="autoFillBackground">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>UTC dB DT Freq Dr </string>
+ </property>
+ <property name="indent">
+ <number>5</number>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="decodedTextLabel">
+ <property name="minimumSize">
+ <size>
+ <width>300</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>500</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="palette">
+ <palette>
+ <active>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>252</red>
+ <green>252</green>
+ <blue>252</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>170</red>
+ <green>170</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>252</red>
+ <green>252</green>
+ <blue>252</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>170</red>
+ <green>170</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>170</red>
+ <green>170</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>170</red>
+ <green>170</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <property name="autoFillBackground">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>UTC dB DT Freq Dr </string>
+ </property>
+ <property name="indent">
+ <number>5</number>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="DisplayText" name="decodedTextBrowser2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>100</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>500</width>
+ <height>1000</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <family>Courier New</family>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ <property name="verticalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOn</enum>
+ </property>
+ <property name="horizontalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOff</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="label_7">
+ <property name="maximumSize">
+ <size>
+ <width>500</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ <weight>50</weight>
+ <bold>false</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Rx Frequency</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_6">
+ <property name="maximumSize">
+ <size>
+ <width>500</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ <weight>50</weight>
+ <bold>false</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Band Activity</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="Line" name="line">
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="Line" name="line_2">
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QPushButton" name="logQSOButton">
+ <property name="minimumSize">
+ <size>
+ <width>50</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Enter this QSO in ADIF log</string>
+ </property>
+ <property name="text">
+ <string>Log &QSO</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="stopButton">
+ <property name="minimumSize">
+ <size>
+ <width>50</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Stop monitoring</string>
+ </property>
+ <property name="text">
+ <string>&Stop</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="monitorButton">
+ <property name="sizePolicy">
+ <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>16777215</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Start monitoring</string>
+ </property>
+ <property name="text">
+ <string>&Monitor</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="EraseButton">
+ <property name="minimumSize">
+ <size>
+ <width>50</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Erase QSO Frequency window. Double-click for both windows</string>
+ </property>
+ <property name="text">
+ <string>&Erase</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="DecodeButton">
+ <property name="minimumSize">
+ <size>
+ <width>50</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Decode most recent Rx period at QSO Frequency (use shift for all freqs)</string>
+ </property>
+ <property name="text">
+ <string>&Decode</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="autoButton">
+ <property name="sizePolicy">
+ <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="toolTip">
+ <string>Toggle Tx Enable On/Off</string>
+ </property>
+ <property name="text">
+ <string>E&nable Tx</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="stopTxButton">
+ <property name="sizePolicy">
+ <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="toolTip">
+ <string>Set Tx Enable OFF</string>
+ </property>
+ <property name="text">
+ <string>&Halt Tx</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="tuneButton">
+ <property name="toolTip">
+ <string>Assert PTT and emit a pure tone</string>
+ </property>
+ <property name="text">
+ <string>&Tune</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="2" column="0" rowspan="5">
+ <widget class="QFrame" name="meterFrame">
+ <property name="minimumSize">
+ <size>
+ <width>50</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="3">
+ <widget class="QLabel" name="labAz">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>23</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>23</height>
+ </size>
+ </property>
+ <property name="autoFillBackground">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="indent">
+ <number>4</number>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="2">
+ <widget class="QComboBox" name="bandComboBox">
+ <property name="toolTip">
+ <string>Select operating band</string>
+ </property>
+ <property name="currentIndex">
+ <number>7</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>2200 m</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>630 m</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>160 m</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>80 m</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>60 m</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>40 m</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>30 m</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>20 m</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>17 m</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>15 m</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>12 m</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>10 m</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>6 m</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>4 m</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>2 m</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Other</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QPushButton" name="readFreq">
+ <property name="maximumSize">
+ <size>
+ <width>15</width>
+ <height>15</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>If orange, click to read dial frequency once</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3" colspan="2">
+ <widget class="QLabel" name="labDialFreq">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>140</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>158</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>16</pointsize>
+ <weight>50</weight>
+ <bold>false</bold>
+ </font>
+ </property>
+ <property name="toolTip">
+ <string>USB dial frequency</string>
+ </property>
+ <property name="text">
+ <string>14.078</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="6">
+ <widget class="QCheckBox" name="txFirstCheckBox">
+ <property name="minimumSize">
+ <size>
+ <width>105</width>
+ <height>23</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>105</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Check to Tx in even minutes, uncheck for odd minutes</string>
+ </property>
+ <property name="text">
+ <string>Tx even</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="8" rowspan="7">
+ <widget class="QFrame" name="frame_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>283</width>
+ <height>222</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>200</height>
+ </size>
+ </property>
+ <property name="tabPosition">
+ <enum>QTabWidget::West</enum>
+ </property>
+ <property name="tabShape">
+ <enum>QTabWidget::Triangular</enum>
+ </property>
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>1</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="leftMargin">
+ <number>4</number>
+ </property>
+ <property name="topMargin">
+ <number>1</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <property name="horizontalSpacing">
+ <number>6</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>5</number>
+ </property>
+ <item row="1" column="2">
+ <widget class="QPushButton" name="txb1">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Switch to this Tx message NOW</string>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="text">
+ <string>Tx 1</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QRadioButton" name="txrb4">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>16</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Send this message in next Tx interval</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <attribute name="buttonGroup">
+ <string>buttonGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QRadioButton" name="txrb1">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>16</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Send this message in next Tx interval</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <attribute name="buttonGroup">
+ <string>buttonGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QRadioButton" name="txrb3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>16</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Send this message in next Tx interval</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <attribute name="buttonGroup">
+ <string>buttonGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLineEdit" name="tx1">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>200</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>150</width>
+ <height>24</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>150</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <family>Droid Sans</family>
+ <weight>50</weight>
+ <bold>false</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="2">
+ <widget class="QPushButton" name="txb3">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Switch to this Tx message NOW</string>
+ </property>
+ <property name="text">
+ <string>Tx 3</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="2">
+ <widget class="QPushButton" name="txb4">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Switch to this Tx message NOW</string>
+ </property>
+ <property name="text">
+ <string>Tx 4</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="label_5">
+ <property name="toolTip">
+ <string>Queue up the next Tx message</string>
+ </property>
+ <property name="text">
+ <string>Next</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLineEdit" name="tx6">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>200</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>150</width>
+ <height>24</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>150</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLineEdit" name="tx5">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>200</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>150</width>
+ <height>24</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>150</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Right-click to select a macro message</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="2">
+ <widget class="QPushButton" name="txb5">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Switch to this Tx message NOW</string>
+ </property>
+ <property name="text">
+ <string>Tx 5</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QRadioButton" name="txrb2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>16</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Send this message in next Tx interval</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <attribute name="buttonGroup">
+ <string>buttonGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="label_2">
+ <property name="toolTip">
+ <string>Switch to this Tx message NOW</string>
+ </property>
+ <property name="text">
+ <string>Now</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QPushButton" name="genStdMsgsPushButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>200</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>150</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>150</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Generate standard messages for minimal QSO</string>
+ </property>
+ <property name="text">
+ <string>Generate Std Msgs</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLineEdit" name="tx2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>200</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>150</width>
+ <height>24</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>150</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLineEdit" name="tx3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>200</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>150</width>
+ <height>24</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>150</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="2">
+ <widget class="QPushButton" name="txb6">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Switch to this Tx message NOW</string>
+ </property>
+ <property name="text">
+ <string>Tx 6</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QPushButton" name="txb2">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Switch to this Tx message NOW</string>
+ </property>
+ <property name="text">
+ <string>Tx 2</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="QRadioButton" name="txrb6">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>16</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Send this message in next Tx interval</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <attribute name="buttonGroup">
+ <string>buttonGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QRadioButton" name="txrb5">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>16</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Send this message in next Tx interval</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <attribute name="buttonGroup">
+ <string>buttonGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLineEdit" name="tx4">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>200</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>150</width>
+ <height>24</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>150</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_2">
+ <attribute name="title">
+ <string>2</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_9">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_7">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="leftMargin">
+ <number>2</number>
+ </property>
+ <property name="rightMargin">
+ <number>2</number>
+ </property>
+ <item>
+ <layout class="QGridLayout" name="gridLayout_4">
+ <property name="spacing">
+ <number>2</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_9">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Calling CQ </string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QPushButton" name="pbCallCQ">
+ <property name="toolTip">
+ <string>Generate a CQ message</string>
+ </property>
+ <property name="text">
+ <string>CQ</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QPushButton" name="pbSendRRR">
+ <property name="toolTip">
+ <string>Generate message with RRR</string>
+ </property>
+ <property name="text">
+ <string>RRR</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QPushButton" name="pbAnswerCaller">
+ <property name="toolTip">
+ <string>Generate message with report</string>
+ </property>
+ <property name="text">
+ <string>dB</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="label_10">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Answering CQ</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QPushButton" name="pbAnswerCQ">
+ <property name="toolTip">
+ <string>Generate message for replying to a CQ</string>
+ </property>
+ <property name="text">
+ <string>Grid</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QPushButton" name="pbSendReport">
+ <property name="toolTip">
+ <string>Generate message with R+report</string>
+ </property>
+ <property name="text">
+ <string>R+dB</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QPushButton" name="pbSend73">
+ <property name="toolTip">
+ <string>Generate message with 73</string>
+ </property>
+ <property name="text">
+ <string>73</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QLineEdit" name="genMsg">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>150</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="rbGenMsg">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>26</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Send this standard (generated) message</string>
+ </property>
+ <property name="text">
+ <string>Gen msg</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLineEdit" name="freeTextMsg">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>150</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="rbFreeText">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>26</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Send this free-text message (max 13 characters)</string>
+ </property>
+ <property name="text">
+ <string>Free msg</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="3">
+ <widget class="QCheckBox" name="cbPlus2kHz">
+ <property name="text">
+ <string> +2 kHz</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <widget class="QLabel" name="label_3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>23</height>
+ </size>
+ </property>
+ <property name="palette">
+ <palette>
+ <active>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>252</red>
+ <green>252</green>
+ <blue>252</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>159</red>
+ <green>175</green>
+ <blue>213</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>252</red>
+ <green>252</green>
+ <blue>252</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>159</red>
+ <green>175</green>
+ <blue>213</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>159</red>
+ <green>175</green>
+ <blue>213</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>159</red>
+ <green>175</green>
+ <blue>213</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <property name="autoFillBackground">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>DX Call</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="indent">
+ <number>2</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="4">
+ <widget class="QLabel" name="label_4">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>23</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="palette">
+ <palette>
+ <active>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>252</red>
+ <green>252</green>
+ <blue>252</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>159</red>
+ <green>175</green>
+ <blue>213</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>252</red>
+ <green>252</green>
+ <blue>252</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>159</red>
+ <green>175</green>
+ <blue>213</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>159</red>
+ <green>175</green>
+ <blue>213</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>159</red>
+ <green>175</green>
+ <blue>213</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <property name="autoFillBackground">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>DX Grid</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="indent">
+ <number>2</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="6">
+ <widget class="QPushButton" name="pbTxMode">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Tx JT9</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" rowspan="5">
+ <widget class="QSlider" name="inGain">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>160</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>160</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Digital gain for audio input</string>
+ </property>
+ <property name="minimum">
+ <number>-50</number>
+ </property>
+ <property name="maximum">
+ <number>50</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="3">
+ <widget class="QLineEdit" name="dxCallEntry">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>70</width>
+ <height>27</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>74</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Callsign of station to be worked</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="4">
+ <widget class="QLineEdit" name="dxGridEntry">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>70</width>
+ <height>27</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>74</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Locator of station to be worked</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="6">
+ <widget class="QSpinBox" name="TxFreqSpinBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>113</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>105</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Audio Tx frequency</string>
+ </property>
+ <property name="suffix">
+ <string> Hz</string>
+ </property>
+ <property name="prefix">
+ <string>Tx </string>
+ </property>
+ <property name="minimum">
+ <number>200</number>
+ </property>
+ <property name="maximum">
+ <number>5000</number>
+ </property>
+ <property name="value">
+ <number>1500</number>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="4">
+ <widget class="QLabel" name="labDist">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>23</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>23</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="5">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>33</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="3" column="6">
+ <widget class="QSpinBox" name="RxFreqSpinBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>113</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="suffix">
+ <string> Hz</string>
+ </property>
+ <property name="prefix">
+ <string>Rx </string>
+ </property>
+ <property name="minimum">
+ <number>200</number>
+ </property>
+ <property name="maximum">
+ <number>5000</number>
+ </property>
+ <property name="value">
+ <number>1500</number>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="7">
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>13</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="4" column="3">
+ <widget class="QPushButton" name="lookupButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>74</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Search for callsign in database</string>
+ </property>
+ <property name="text">
+ <string>&Lookup</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="4">
+ <widget class="QPushButton" name="addButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>74</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Add callsign and locator to database</string>
+ </property>
+ <property name="text">
+ <string>Add</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="6">
+ <layout class="QHBoxLayout" name="horizontalLayout_5">
+ <property name="spacing">
+ <number>5</number>
+ </property>
+ <property name="sizeConstraint">
+ <enum>QLayout::SetFixedSize</enum>
+ </property>
+ <item>
+ <widget class="QPushButton" name="pbR2T">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>48</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Set Tx frequency to Rx Frequency</string>
+ </property>
+ <property name="text">
+ <string>Tx=Rx</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pbT2R">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>48</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Set Rx frequency to Tx Frequency</string>
+ </property>
+ <property name="text">
+ <string>Rx=Tx</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="5" column="3" rowspan="2" colspan="2">
+ <widget class="QLabel" name="labUTC">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>130</width>
+ <height>60</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>158</width>
+ <height>60</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>16</pointsize>
+ </font>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Sunken</enum>
+ </property>
+ <property name="lineWidth">
+ <number>2</number>
+ </property>
+ <property name="midLineWidth">
+ <number>0</number>
+ </property>
+ <property name="text">
+ <string> 01:23:45 </string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="6">
+ <widget class="QCheckBox" name="cbTxLock">
+ <property name="text">
+ <string>Lock Tx=Rx</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="6">
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <property name="spacing">
+ <number>5</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label_8">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Report</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="rptSpinBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>55</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>55</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Signal report (dB0</string>
+ </property>
+ <property name="minimum">
+ <number>-50</number>
+ </property>
+ <property name="maximum">
+ <number>49</number>
+ </property>
+ <property name="value">
+ <number>-15</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menuBar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>760</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <widget class="QMenu" name="menuFile">
+ <property name="title">
+ <string>File</string>
+ </property>
+ <addaction name="actionOpen"/>
+ <addaction name="actionOpen_next_in_directory"/>
+ <addaction name="actionDecode_remaining_files_in_directory"/>
+ <addaction name="separator"/>
+ <addaction name="actionDelete_all_wav_files_in_SaveDir"/>
+ <addaction name="actionErase_ALL_TXT"/>
+ <addaction name="actionErase_wsjtx_log_adi"/>
+ <addaction name="separator"/>
+ <addaction name="actionExit"/>
+ </widget>
+ <widget class="QMenu" name="menuSetup">
+ <property name="title">
+ <string>Setup</string>
+ </property>
+ <widget class="QMenu" name="menuAdvanced">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="title">
+ <string>Advanced</string>
+ </property>
+ <addaction name="actionAllow_multiple_instances"/>
+ </widget>
+ <addaction name="actionDeviceSetup"/>
+ <addaction name="separator"/>
+ <addaction name="actionMonitor_OFF_at_startup"/>
+ <addaction name="actionConvert_JT9_x_to_RTTY"/>
+ <addaction name="actionLog_dB_reports_to_Comments"/>
+ <addaction name="actionPrompt_to_log_QSO"/>
+ <addaction name="actionBlank_line_between_decoding_periods"/>
+ <addaction name="actionClear_DX_Call_and_Grid_after_logging"/>
+ <addaction name="actionDisplay_distance_in_miles"/>
+ <addaction name="actionDouble_click_on_call_sets_Tx_Enable"/>
+ <addaction name="action_73TxDisable"/>
+ <addaction name="actionRunaway_Tx_watchdog"/>
+ <addaction name="actionTx2QSO"/>
+ <addaction name="separator"/>
+ <addaction name="menuAdvanced"/>
+ </widget>
+ <widget class="QMenu" name="menuView">
+ <property name="title">
+ <string>View</string>
+ </property>
+ <widget class="QMenu" name="menuWaterfall_palette">
+ <property name="title">
+ <string>Waterfall palette</string>
+ </property>
+ <addaction name="actionLinrad"/>
+ <addaction name="actionCuteSDR"/>
+ <addaction name="actionAFMHot"/>
+ <addaction name="actionBlue"/>
+ </widget>
+ <addaction name="actionWide_Waterfall"/>
+ <addaction name="separator"/>
+ <addaction name="menuWaterfall_palette"/>
+ </widget>
+ <widget class="QMenu" name="menuDecode">
+ <property name="title">
+ <string>Decode</string>
+ </property>
+ <addaction name="actionQuickDecode"/>
+ <addaction name="actionMediumDecode"/>
+ <addaction name="actionDeepestDecode"/>
+ </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">
+ <property name="title">
+ <string>Help</string>
+ </property>
+ <addaction name="actionOnline_Users_Guide"/>
+ <addaction name="actionKeyboard_shortcuts"/>
+ <addaction name="actionSpecial_mouse_commands"/>
+ <addaction name="actionAbout"/>
+ </widget>
+ <widget class="QMenu" name="menuMode">
+ <property name="title">
+ <string>Mode</string>
+ </property>
+ <addaction name="actionJT9_1"/>
+ <addaction name="actionJT65"/>
+ <addaction name="actionJT9_JT65"/>
+ </widget>
+ <addaction name="menuFile"/>
+ <addaction name="menuSetup"/>
+ <addaction name="menuView"/>
+ <addaction name="menuMode"/>
+ <addaction name="menuDecode"/>
+ <addaction name="menuSave"/>
+ <addaction name="menuHelp"/>
+ </widget>
+ <widget class="QStatusBar" name="statusBar"/>
+ <action name="actionExit">
+ <property name="text">
+ <string>Exit</string>
+ </property>
+ </action>
+ <action name="actionDeviceSetup">
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Configuration</string>
+ </property>
+ <property name="shortcut">
+ <string>F2</string>
+ </property>
+ </action>
+ <action name="actionAbout">
+ <property name="text">
+ <string> About WSJT-X</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+F1</string>
+ </property>
+ </action>
+ <action name="actionAstro_Data">
+ <property name="text">
+ <string>Astro Data</string>
+ </property>
+ <property name="shortcut">
+ <string>Shift+F10</string>
+ </property>
+ </action>
+ <action name="actionBand_Map">
+ <property name="text">
+ <string>Band Map</string>
+ </property>
+ </action>
+ <action name="actionMessages">
+ <property name="text">
+ <string>Messages</string>
+ </property>
+ </action>
+ <action name="actionWide_Waterfall">
+ <property name="text">
+ <string>Waterfall</string>
+ </property>
+ </action>
+ <action name="actionOpen">
+ <property name="text">
+ <string>Open</string>
+ </property>
+ </action>
+ <action name="actionOpen_next_in_directory">
+ <property name="text">
+ <string>Open next in directory</string>
+ </property>
+ <property name="shortcut">
+ <string>F6</string>
+ </property>
+ </action>
+ <action name="actionDecode_remaining_files_in_directory">
+ <property name="text">
+ <string>Decode remaining files in directory</string>
+ </property>
+ <property name="shortcut">
+ <string>Shift+F6</string>
+ </property>
+ </action>
+ <action name="actionDelete_all_wav_files_in_SaveDir">
+ <property name="text">
+ <string>Delete all *.wav files in SaveDir</string>
+ </property>
+ </action>
+ <action name="actionErase_Band_Map_and_Messages">
+ <property name="text">
+ <string>Erase Band Map and Messages</string>
+ </property>
+ </action>
+ <action name="actionLinrad">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Linrad</string>
+ </property>
+ </action>
+ <action name="actionCuteSDR">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>CuteSDR</string>
+ </property>
+ </action>
+ <action name="actionFind_Delta_Phi">
+ <property name="text">
+ <string>Find Delta Phi</string>
+ </property>
+ </action>
+ <action name="actionF4_sets_Tx6">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>F4 sets Tx6</string>
+ </property>
+ </action>
+ <action name="actionNo_shorthands_if_Tx1">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>No shorthand decodes if Tx1</string>
+ </property>
+ </action>
+ <action name="actionQuickDecode">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Fast</string>
+ </property>
+ </action>
+ <action name="actionNone">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>None</string>
+ </property>
+ </action>
+ <action name="actionSave_all">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Save all</string>
+ </property>
+ </action>
+ <action name="action50">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>50</string>
+ </property>
+ </action>
+ <action name="action144">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>144</string>
+ </property>
+ </action>
+ <action name="action222">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>222</string>
+ </property>
+ </action>
+ <action name="action432">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>432</string>
+ </property>
+ </action>
+ <action name="action1296">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>1296</string>
+ </property>
+ </action>
+ <action name="action2304">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>2304</string>
+ </property>
+ </action>
+ <action name="actionOnline_Users_Guide">
+ <property name="text">
+ <string>Online User's Guide</string>
+ </property>
+ <property name="shortcut">
+ <string>F1</string>
+ </property>
+ </action>
+ <action name="actionKeyboard_shortcuts">
+ <property name="text">
+ <string>Keyboard shortcuts</string>
+ </property>
+ <property name="shortcut">
+ <string>F3</string>
+ </property>
+ </action>
+ <action name="actionSpecial_mouse_commands">
+ <property name="text">
+ <string>Special mouse commands</string>
+ </property>
+ <property name="shortcut">
+ <string>F5</string>
+ </property>
+ </action>
+ <action name="actionAvailable_suffixes_and_add_on_prefixes">
+ <property name="text">
+ <string>Available suffixes and add-on-prefixes</string>
+ </property>
+ </action>
+ <action name="actionJT65A">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>JT65A</string>
+ </property>
+ </action>
+ <action name="actionJT65B">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>JT65B</string>
+ </property>
+ </action>
+ <action name="actionJT65C">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>JT65C</string>
+ </property>
+ </action>
+ <action name="actionI_Q_Calibration">
+ <property name="text">
+ <string>I/Q Calibration</string>
+ </property>
+ <property name="shortcut">
+ <string>F7</string>
+ </property>
+ </action>
+ <action name="actionAdjust_IQ_Calibration">
+ <property name="text">
+ <string>Adjust I/Q Calibration</string>
+ </property>
+ </action>
+ <action name="actionApply_IQ_Calibration">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Apply I/Q Calibration</string>
+ </property>
+ </action>
+ <action name="actionAFMHot">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>AFMHot</string>
+ </property>
+ </action>
+ <action name="actionBlue">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Blue</string>
+ </property>
+ </action>
+ <action name="actionFUNcube_Dongle">
+ <property name="text">
+ <string>FUNcube Dongle Settings</string>
+ </property>
+ </action>
+ <action name="actionJT9_1">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>JT9</string>
+ </property>
+ </action>
+ <action name="actionJT9_2">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>JT9-2</string>
+ </property>
+ </action>
+ <action name="actionJT9_5">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>JT9-5</string>
+ </property>
+ </action>
+ <action name="actionJT9_10">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>JT9-10</string>
+ </property>
+ </action>
+ <action name="actionJT9_30">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>JT9-30</string>
+ </property>
+ </action>
+ <action name="actionSave_synced">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Save synced</string>
+ </property>
+ </action>
+ <action name="actionSave_decoded">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Save decoded</string>
+ </property>
+ </action>
+ <action name="actionMediumDecode">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Normal</string>
+ </property>
+ </action>
+ <action name="actionDeepestDecode">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Deepest</string>
+ </property>
+ </action>
+ <action name="actionMonitor_OFF_at_startup">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Monitor OFF at startup</string>
+ </property>
+ </action>
+ <action name="actionErase_ALL_TXT">
+ <property name="text">
+ <string>Erase ALL.TXT</string>
+ </property>
+ </action>
+ <action name="actionErase_wsjtx_log_adi">
+ <property name="text">
+ <string>Erase wsjtx_log.adi</string>
+ </property>
+ </action>
+ <action name="actionLog_JT9_without_submode">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Log JT9 without submode</string>
+ </property>
+ </action>
+ <action name="actionConvert_JT9_x_to_RTTY">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Convert mode to RTTY for logging</string>
+ </property>
+ </action>
+ <action name="actionLog_dB_reports_to_Comments">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Log dB reports to Comments</string>
+ </property>
+ </action>
+ <action name="actionPrompt_to_log_QSO">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Prompt me to log QSO</string>
+ </property>
+ </action>
+ <action name="actionBlank_line_between_decoding_periods">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Blank line between decoding periods</string>
+ </property>
+ </action>
+ <action name="actionClear_DX_Call_and_Grid_after_logging">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Clear DX Call and Grid after logging</string>
+ </property>
+ </action>
+ <action name="actionDistance_in_miles">
+ <property name="text">
+ <string>Distance in miles</string>
+ </property>
+ </action>
+ <action name="actionDisplay_distance_in_miles">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Display distance in miles</string>
+ </property>
+ </action>
+ <action name="actionDouble_click_on_call_sets_Tx_Enable">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Double-click on call sets Tx Enable</string>
+ </property>
+ </action>
+ <action name="action_73TxDisable">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Tx disabled after sending 73</string>
+ </property>
+ </action>
+ <action name="actionRunaway_Tx_watchdog">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Runaway Tx watchdog</string>
+ </property>
+ </action>
+ <action name="actionAllow_multiple_instances">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Allow multiple instances</string>
+ </property>
+ </action>
+ <action name="actionLockTxFreq">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Tx freq locked to Rx freq</string>
+ </property>
+ </action>
+ <action name="actionJT65">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>JT65</string>
+ </property>
+ </action>
+ <action name="actionJT9_JT65">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>JT9+JT65</string>
+ </property>
+ </action>
+ <action name="actionTx2QSO">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Tx messages to Rx Frequency window</string>
+ </property>
+ </action>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <customwidgets>
+ <customwidget>
+ <class>DisplayText</class>
+ <extends>QTextBrowser</extends>
+ <header>displaytext.h</header>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>logQSOButton</tabstop>
+ <tabstop>stopButton</tabstop>
+ <tabstop>monitorButton</tabstop>
+ <tabstop>EraseButton</tabstop>
+ <tabstop>DecodeButton</tabstop>
+ <tabstop>autoButton</tabstop>
+ <tabstop>stopTxButton</tabstop>
+ <tabstop>tuneButton</tabstop>
+ <tabstop>bandComboBox</tabstop>
+ <tabstop>readFreq</tabstop>
+ <tabstop>inGain</tabstop>
+ <tabstop>dxCallEntry</tabstop>
+ <tabstop>dxGridEntry</tabstop>
+ <tabstop>txFirstCheckBox</tabstop>
+ <tabstop>TxFreqSpinBox</tabstop>
+ <tabstop>pbR2T</tabstop>
+ <tabstop>pbT2R</tabstop>
+ <tabstop>rptSpinBox</tabstop>
+ <tabstop>tabWidget</tabstop>
+ <tabstop>genStdMsgsPushButton</tabstop>
+ <tabstop>tx1</tabstop>
+ <tabstop>tx2</tabstop>
+ <tabstop>tx3</tabstop>
+ <tabstop>tx4</tabstop>
+ <tabstop>tx5</tabstop>
+ <tabstop>tx6</tabstop>
+ <tabstop>txrb1</tabstop>
+ <tabstop>txrb2</tabstop>
+ <tabstop>txrb3</tabstop>
+ <tabstop>txrb4</tabstop>
+ <tabstop>txrb5</tabstop>
+ <tabstop>txrb6</tabstop>
+ <tabstop>txb1</tabstop>
+ <tabstop>txb2</tabstop>
+ <tabstop>txb3</tabstop>
+ <tabstop>txb4</tabstop>
+ <tabstop>txb5</tabstop>
+ <tabstop>txb6</tabstop>
+ <tabstop>decodedTextBrowser</tabstop>
+ <tabstop>decodedTextBrowser2</tabstop>
+ <tabstop>genMsg</tabstop>
+ <tabstop>pbAnswerCaller</tabstop>
+ <tabstop>rbFreeText</tabstop>
+ <tabstop>pbSendRRR</tabstop>
+ <tabstop>freeTextMsg</tabstop>
+ <tabstop>pbAnswerCQ</tabstop>
+ <tabstop>pbSendReport</tabstop>
+ <tabstop>pbSend73</tabstop>
+ <tabstop>rbGenMsg</tabstop>
+ <tabstop>pbCallCQ</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>monitorButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>MainWindow</receiver>
+ <slot>update()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>264</x>
+ <y>275</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>126</x>
+ <y>515</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+ <buttongroups>
+ <buttongroup name="buttonGroup">
+ <property name="exclusive">
+ <bool>true</bool>
+ </property>
+ </buttongroup>
+ </buttongroups>
+</ui>
diff --git a/meterwidget.cpp b/meterwidget.cpp
new file mode 100644
index 0000000..b48aa65
--- /dev/null
+++ b/meterwidget.cpp
@@ -0,0 +1,51 @@
+// Simple bargraph meter
+// Implemented by Edson Pereira PY2SDR
+
+#include "meterwidget.h"
+
+MeterWidget::MeterWidget(QWidget *parent) :
+ QWidget(parent),
+ m_signal(0)
+{
+ for ( int i = 0; i < 10; i++ ) {
+ signalQueue.enqueue(0);
+ }
+}
+
+void MeterWidget::setValue(int value)
+{
+ m_signal = value;
+ signalQueue.enqueue(value);
+ signalQueue.dequeue();
+
+ // Get signal peak
+ int tmp = 0;
+ for (int i = 0; i < signalQueue.size(); ++i) {
+ if (signalQueue.at(i) > tmp)
+ tmp = signalQueue.at(i);
+ }
+ m_sigPeak = tmp;
+
+ update();
+}
+
+void MeterWidget::paintEvent( QPaintEvent * )
+{
+ int pos;
+ QPainter p;
+
+ p.begin(this);
+
+ // Sanitize
+ m_signal = m_signal < 0 ? 0 : m_signal;
+ m_signal = m_signal > 60 ? 60 : m_signal;
+
+ pos = m_signal * 2;
+ QRect r(0, height() - pos, width(), pos );
+ p.fillRect(r, QColor( 255, 150, 0 ));
+
+ // Draw peak hold indicator
+ p.setPen(Qt::black);
+ pos = m_sigPeak * 2;
+ p.drawLine(0, height() - pos, 10, height() - pos);
+}
diff --git a/meterwidget.h b/meterwidget.h
new file mode 100644
index 0000000..7b51efb
--- /dev/null
+++ b/meterwidget.h
@@ -0,0 +1,30 @@
+#ifndef METERWIDGET_H
+#define METERWIDGET_H
+
+#include <QWidget>
+#include <QtGui>
+#include <QQueue>
+
+class MeterWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit MeterWidget(QWidget *parent = 0);
+
+signals:
+
+public slots:
+ void setValue(int value);
+
+private:
+ QQueue<int> signalQueue;
+
+ int m_signal;
+ int m_sigPeak;
+
+protected:
+ void paintEvent( QPaintEvent * );
+
+};
+
+#endif // METERWIDGET_H
diff --git a/mouse_commands.txt b/mouse_commands.txt
new file mode 100644
index 0000000..8e26589
--- /dev/null
+++ b/mouse_commands.txt
@@ -0,0 +1,18 @@
+Click on Action
+__________________________________________________________
+
+Waterfall: Set Rx frequency
+ Double-click to set Rx frequency and decode there
+ Ctrl-click to set Rx and Tx frequencies and decode
+
+Decoded text: Double-click to copy second callsign to Dx Call,
+ locator to Dx Grid; change Rx and Tx frequencies to
+ decoded signal's frequency; generate standard messages.
+ If first callsign is your own, Tx frequency is not
+ changed unless Ctrl is held down when double-clicking.
+
+Erase button: Click to erase QSO window
+ Double-click to erase QSO and Band Activity windows
+
+Tx5 Entry: Right-click to select a macro message
+
diff --git a/paInputDevice.c b/paInputDevice.c
new file mode 100644
index 0000000..641bd85
--- /dev/null
+++ b/paInputDevice.c
@@ -0,0 +1,56 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+void paInputDevice(int id, char* hostAPI_DeviceName, int* minChan,
+ int* maxChan, int* minSpeed, int* maxSpeed)
+{
+ int i, j, k;
+ char pa_device_name[128];
+ char pa_device_hostapi[128];
+ double pa_device_max_speed;
+ double pa_device_min_speed;
+ int pa_device_max_bytes;
+ int pa_device_min_bytes;
+ int pa_device_max_channels;
+ int pa_device_min_channels;
+ char p2[50];
+ char *p,*p1;
+ static int iret, numDevices, valid_dev_cnt;
+
+ iret=pa_get_device_info (id,
+ &pa_device_name,
+ &pa_device_hostapi,
+ &pa_device_max_speed,
+ &pa_device_min_speed,
+ &pa_device_max_bytes,
+ &pa_device_min_bytes,
+ &pa_device_max_channels,
+ &pa_device_min_channels);
+
+ if (iret >= 0 ) {
+ valid_dev_cnt++;
+
+ p1="";
+ p=strstr(pa_device_hostapi,"MME");
+ if(p!=NULL) p1="MME";
+ p=strstr(pa_device_hostapi,"Direct");
+ if(p!=NULL) p1="DirectX";
+ p=strstr(pa_device_hostapi,"WASAPI");
+ if(p!=NULL) p1="WASAPI";
+ p=strstr(pa_device_hostapi,"ASIO");
+ if(p!=NULL) p1="ASIO";
+ p=strstr(pa_device_hostapi,"WDM-KS");
+ if(p!=NULL) p1="WDM-KS";
+
+ sprintf(p2,"%-8s %-39s",p1,pa_device_name);
+ for(i=0; i<50; i++) {
+ hostAPI_DeviceName[i]=p2[i];
+ if(p2[i]==0) break;
+ }
+ *minChan=pa_device_min_channels;
+ *maxChan=pa_device_max_channels;
+ *minSpeed=(int)pa_device_min_speed;
+ *maxSpeed=(int)pa_device_max_speed;
+ }
+}
diff --git a/pa_get_device_info.c b/pa_get_device_info.c
new file mode 100644
index 0000000..ac6bc9f
--- /dev/null
+++ b/pa_get_device_info.c
@@ -0,0 +1,172 @@
+#include <portaudio.h>
+#include <stdio.h>
+
+#define MAX_LATENCY 20
+
+PaStream *in_stream;
+//------------------------------------------------------- pa_get_device_info
+int pa_get_device_info (int n,
+ void *pa_device_name,
+ void *pa_device_hostapi,
+ double *pa_device_max_speed,
+ double *pa_device_min_speed,
+ int *pa_device_max_bytes,
+ int *pa_device_min_bytes,
+ int *pa_device_max_channels,
+ int *pa_device_min_channels )
+{
+
+ (void) n ;
+ (void) pa_device_name;
+ (void) pa_device_hostapi;
+ (void) pa_device_max_speed;
+ (void) pa_device_min_speed;
+ (void) pa_device_max_bytes;
+ (void) pa_device_min_bytes;
+ (void) pa_device_max_channels;
+ (void) pa_device_min_channels;
+ const PaDeviceInfo *deviceInfo;
+ PaError pa_err;
+ PaStreamParameters inputParameters;
+ int i,j, speed_warning;
+ int minBytes, maxBytes;
+ double maxStandardSampleRate;
+ double minStandardSampleRate;
+ int minInputChannels;
+ int maxInputChannels;
+
+// negative terminated list
+ static double standardSampleRates[] = {8000.0, 9600.0,
+ 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0,
+ 44100.0, 48000.0, 88200.0, 96000.0, 192000.0, -1};
+// *******************************************************
+
+
+ *pa_device_max_speed=0;
+ *pa_device_min_speed=0;
+ *pa_device_max_bytes=0;
+ *pa_device_min_bytes=0;
+ *pa_device_max_channels=0;
+ *pa_device_min_channels=0;
+ minInputChannels=0;
+ if(n >= Pa_GetDeviceCount() ) return -1;
+ deviceInfo = Pa_GetDeviceInfo(n);
+ if (deviceInfo->maxInputChannels==0) return -1;
+ sprintf((char*)(pa_device_name),"%s",deviceInfo->name);
+ sprintf((char*)(pa_device_hostapi),"%s",
+ Pa_GetHostApiInfo( deviceInfo->hostApi )->name);
+ speed_warning=0;
+
+// bypass bug in Juli@ ASIO driver:
+// this driver hangs after a Pa_IsFormatSupported call
+ i = strncmp(deviceInfo->name, "ASIO 2.0 - ESI Juli@", 19);
+ if (i == 0) {
+ minStandardSampleRate=44100;
+ maxStandardSampleRate=192000;
+ minBytes=1;
+ maxBytes=4;
+ maxInputChannels= deviceInfo->maxInputChannels;
+ minInputChannels= 1;
+ goto end_pa_get_device_info;
+ }
+
+// Investigate device capabilities.
+// Check min and max samplerates with 16 bit data.
+ maxStandardSampleRate=0;
+ minStandardSampleRate=0;
+ inputParameters.device = n;
+ inputParameters.channelCount = deviceInfo->maxInputChannels;
+ inputParameters.sampleFormat = paInt16;
+ inputParameters.suggestedLatency = 0;
+ inputParameters.hostApiSpecificStreamInfo = NULL;
+
+// ************************************************************************
+//filter for portaudio Windows hostapi's with non experts.
+//only allow ASIO or WASAPI or WDM-KS
+ i = strncmp(Pa_GetHostApiInfo(deviceInfo->hostApi)->name, "ASIO", 4);
+ if (i==0 ) goto end_filter_hostapi;
+ i = strncmp(Pa_GetHostApiInfo(deviceInfo->hostApi)->name,
+ "Windows WASAPI", 14);
+ if (i==0 ) goto end_filter_hostapi;
+ i = strncmp(Pa_GetHostApiInfo(deviceInfo->hostApi)->name,
+ "Windows WDM-KS", 14);
+ if (i==0 ) goto end_filter_hostapi;
+ speed_warning=1;
+end_filter_hostapi:;
+
+// ************************************************************************
+ i=0;
+ while(standardSampleRates[i] > 0 && minStandardSampleRate==0) {
+ pa_err=Pa_IsFormatSupported(&inputParameters, NULL,
+ standardSampleRates[i] );
+ if(pa_err == paDeviceUnavailable) return -1;
+ if(pa_err == paInvalidDevice) return -1;
+ if(pa_err == paFormatIsSupported ) {
+ minStandardSampleRate=standardSampleRates[i];
+ }
+ i++;
+ }
+ if(minStandardSampleRate == 0) return -1;
+ j=i;
+ while(standardSampleRates[i] > 0 ) i++;
+ i--;
+ while(i >= j && maxStandardSampleRate==0) {
+ pa_err=Pa_IsFormatSupported(&inputParameters, NULL,
+ standardSampleRates[i] );
+ if(pa_err == paDeviceUnavailable) return -1;
+ if(pa_err == paInvalidDevice) return -1;
+ if( pa_err == paFormatIsSupported ) {
+ maxStandardSampleRate=standardSampleRates[i];
+ }
+ i--;
+ }
+
+// check if min SampleRate = max SampleRate
+ if(maxStandardSampleRate==0 && (minStandardSampleRate != 0)) {
+ maxStandardSampleRate= minStandardSampleRate;
+ }
+
+// check min and max bytes
+ minBytes=2;
+ maxBytes=2;
+ inputParameters.sampleFormat = paUInt8;
+ pa_err=Pa_IsFormatSupported(&inputParameters, NULL,
+ maxStandardSampleRate );
+ if( pa_err == paFormatIsSupported ) {
+ minBytes=1;
+ }
+ inputParameters.sampleFormat = paInt32;
+ pa_err=Pa_IsFormatSupported(&inputParameters, NULL,
+ maxStandardSampleRate );
+ if( pa_err == paFormatIsSupported ) {
+ maxBytes=4;
+ }
+
+// check min channel count
+ maxInputChannels= deviceInfo->maxInputChannels;
+ inputParameters.channelCount = 1;
+ inputParameters.sampleFormat = paInt16;
+ pa_err=paFormatIsSupported+32000;
+ while(pa_err != paFormatIsSupported &&
+ ( inputParameters.channelCount < (maxInputChannels+1)) ) {
+ pa_err=Pa_IsFormatSupported(&inputParameters, NULL,
+ maxStandardSampleRate );
+ inputParameters.channelCount++;
+ }
+ if( pa_err == paFormatIsSupported ) {
+ minInputChannels=inputParameters.channelCount-1;
+ } else {
+ return -1;
+ }
+
+end_pa_get_device_info:;
+
+ *pa_device_max_speed=maxStandardSampleRate;
+ *pa_device_min_speed=minStandardSampleRate;
+ *pa_device_max_bytes=maxBytes;
+ *pa_device_min_bytes=minBytes;
+ *pa_device_max_channels= maxInputChannels;
+ *pa_device_min_channels= minInputChannels;
+
+ return speed_warning;
+}
diff --git a/plotter.cpp b/plotter.cpp
new file mode 100644
index 0000000..a43bdbf
--- /dev/null
+++ b/plotter.cpp
@@ -0,0 +1,565 @@
+#include "plotter.h"
+#include <math.h>
+#include <QDebug>
+
+#define MAX_SCREENSIZE 2048
+
+
+CPlotter::CPlotter(QWidget *parent) : //CPlotter Constructor
+ QFrame(parent)
+{
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ setFocusPolicy(Qt::StrongFocus);
+ setAttribute(Qt::WA_PaintOnScreen,false);
+ setAutoFillBackground(false);
+ setAttribute(Qt::WA_OpaquePaintEvent, false);
+ setAttribute(Qt::WA_NoSystemBackground, true);
+
+ m_StartFreq = 0;
+ m_nSpan=2; //used for FFT bins/pixel
+ m_fSpan=(float)m_nSpan;
+ m_hdivs = HORZ_DIVS;
+ m_FreqUnits = 1;
+ m_Running = false;
+ m_paintEventBusy=false;
+ m_WaterfallPixmap = QPixmap(0,0);
+ m_2DPixmap = QPixmap(0,0);
+ m_ScalePixmap = QPixmap(0,0);
+ m_OverlayPixmap = QPixmap(0,0);
+ m_Size = QSize(0,0);
+ m_rxFreq = 1020;
+ m_line = 0;
+ m_fSample = 12000;
+ m_nsps=6912;
+ m_dBStepSize=10;
+ m_Percent2DScreen = 30; //percent of screen used for 2D display
+ m_txFreq=0;
+}
+
+CPlotter::~CPlotter() { } // Destructor
+
+QSize CPlotter::minimumSizeHint() const
+{
+ return QSize(50, 50);
+}
+
+QSize CPlotter::sizeHint() const
+{
+ return QSize(180, 180);
+}
+
+void CPlotter::resizeEvent(QResizeEvent* ) //resizeEvent()
+{
+ if(!size().isValid()) return;
+ if( m_Size != size() ) { //if changed, resize pixmaps to new screensize
+ m_Size = size();
+ m_w = m_Size.width();
+ m_h = m_Size.height();
+ m_h1 = (100-m_Percent2DScreen)*(m_Size.height())/100;
+ m_h2 = (m_Percent2DScreen)*(m_Size.height())/100;
+
+ m_2DPixmap = QPixmap(m_Size.width(), m_h2);
+ m_2DPixmap.fill(Qt::black);
+ m_WaterfallPixmap = QPixmap(m_Size.width(), m_h1);
+ m_OverlayPixmap = QPixmap(m_Size.width(), m_h2);
+ m_OverlayPixmap.fill(Qt::black);
+
+ m_WaterfallPixmap.fill(Qt::black);
+ m_2DPixmap.fill(Qt::black);
+ m_ScalePixmap = QPixmap(m_w,30);
+ m_ScalePixmap.fill(Qt::white);
+ }
+ DrawOverlay();
+}
+
+void CPlotter::paintEvent(QPaintEvent *) // paintEvent()
+{
+ if(m_paintEventBusy) return;
+ m_paintEventBusy=true;
+ QPainter painter(this);
+ painter.drawPixmap(0,0,m_ScalePixmap);
+ painter.drawPixmap(0,30,m_WaterfallPixmap);
+ painter.drawPixmap(0,m_h1,m_2DPixmap);
+ m_paintEventBusy=false;
+}
+
+void CPlotter::draw(float swide[], int i0) //draw()
+{
+ int j,y2;
+ float y;
+
+ m_i0=i0;
+ double gain = pow(10.0,0.05*(m_plotGain+7));
+
+//move current data down one line (must do this before attaching a QPainter object)
+ m_WaterfallPixmap.scroll(0,1,0,0,m_w,m_h1);
+ QPainter painter1(&m_WaterfallPixmap);
+ m_2DPixmap = m_OverlayPixmap.copy(0,0,m_w,m_h2);
+ QPainter painter2D(&m_2DPixmap);
+
+ painter2D.setPen(Qt::green);
+
+ QPoint LineBuf[MAX_SCREENSIZE];
+ j=0;
+
+// int iz=XfromFreq(2000.0);
+ int iz=XfromFreq(5000.0);
+ m_fMax=FreqfromX(iz);
+ for(int i=0; i<iz; i++) {
+ if(i>iz) swide[i]=0;
+ y=0.0;
+ if(swide[i]>0.0) y = 10.0*log10(swide[i]);
+ int y1 = 5.0*gain*y + 10*(m_plotZero-4);
+ if (y1<0) y1=0;
+ if (y1>254) y1=254;
+ if (swide[i]>1.e29) y1=255;
+ painter1.setPen(m_ColorTbl[y1]);
+ painter1.drawPoint(i,0);
+ y2=0;
+ if(m_bCurrent) y2 = 0.4*gain*y - 15;
+ if(m_bCumulative) {
+ float sum=0.0;
+ int j=m_binsPerPixel*i;
+ for(int k=0; k<m_binsPerPixel; k++) {
+ sum+=jt9com_.savg[j++];
+ }
+ y2=gain*6.0*log10(sum/m_binsPerPixel) - 10.0;
+ }
+ y2 += m_plotZero;
+ if(i==iz-1) painter2D.drawPolyline(LineBuf,j);
+ LineBuf[j].setX(i);
+ LineBuf[j].setY(m_h-(y2+0.8*m_h));
+ j++;
+ }
+
+ if(swide[0]>1.0e29) m_line=0;
+ m_line++;
+ if(m_line == 13) {
+ UTCstr();
+ painter1.setPen(Qt::white);
+ painter1.drawText(5,10,m_sutc);
+ }
+ update(); //trigger a new paintEvent
+}
+
+void CPlotter::UTCstr()
+{
+ int ihr,imin;
+ if(jt9com_.ndiskdat != 0) {
+ ihr=jt9com_.nutc/100;
+ imin=jt9com_.nutc % 100;
+ } else {
+ qint64 ms = QDateTime::currentMSecsSinceEpoch() % 86400000;
+ imin=ms/60000;
+ ihr=imin/60;
+ imin=imin % 60;
+ imin=imin - (imin % (m_TRperiod/60));
+ }
+ sprintf(m_sutc,"%2.2d:%2.2d",ihr,imin);
+}
+
+void CPlotter::DrawOverlay() //DrawOverlay()
+{
+ if(m_OverlayPixmap.isNull()) return;
+ if(m_WaterfallPixmap.isNull()) return;
+ int w = m_WaterfallPixmap.width();
+ int x,y,x1,x2;
+// int nHzDiv[11]={0,50,100,200,200,200,500,500,500,500,500};
+ float pixperdiv;
+
+ QRect rect;
+ QPainter painter(&m_OverlayPixmap);
+ painter.initFrom(this);
+ QLinearGradient gradient(0, 0, 0 ,m_h2); //fill background with gradient
+ gradient.setColorAt(1, Qt::black);
+ gradient.setColorAt(0, Qt::darkBlue);
+ painter.setBrush(gradient);
+ painter.drawRect(0, 0, m_w, m_h2);
+ painter.setBrush(Qt::SolidPattern);
+
+ double df = m_binsPerPixel*m_fftBinWidth;
+ pixperdiv = m_freqPerDiv/df;
+ y = m_h2 - m_h2/VERT_DIVS;
+ m_hdivs = w*df/m_freqPerDiv + 0.9999;
+ for( int i=1; i<m_hdivs; i++) //draw vertical grids
+ {
+ x = (int)( (float)i*pixperdiv );
+ if(x >= 0 and x<=m_w) {
+ painter.setPen(QPen(Qt::white, 1,Qt::DotLine));
+ painter.drawLine(x, 0, x , y);
+ painter.drawLine(x, m_h2-5, x , m_h2);
+ }
+ }
+
+ pixperdiv = (float)m_h2 / (float)VERT_DIVS;
+ painter.setPen(QPen(Qt::white, 1,Qt::DotLine));
+ for( int i=1; i<VERT_DIVS; i++) //draw horizontal grids
+ {
+ y = (int)( (float)i*pixperdiv );
+ painter.drawLine(0, y, w, y);
+ }
+
+ QRect rect0;
+ QPainter painter0(&m_ScalePixmap);
+ painter0.initFrom(this);
+
+ //create Font to use for scales
+ QFont Font("Arial");
+ Font.setPointSize(12);
+ QFontMetrics metrics(Font);
+ Font.setWeight(QFont::Normal);
+ painter0.setFont(Font);
+ painter0.setPen(Qt::black);
+
+ if(m_binsPerPixel < 1) m_binsPerPixel=1;
+ m_fSpan = w*df;
+ int n=m_fSpan/10;
+ m_freqPerDiv=10;
+ if(n>25) m_freqPerDiv=50;
+ if(n>70) m_freqPerDiv=100;
+ if(n>140) m_freqPerDiv=200;
+ if(n>310) m_freqPerDiv=500;
+ m_hdivs = w*df/m_freqPerDiv + 0.9999;
+ m_ScalePixmap.fill(Qt::white);
+ painter0.drawRect(0, 0, w, 30);
+
+//draw tick marks on upper scale
+ pixperdiv = m_freqPerDiv/df;
+ for( int i=1; i<m_hdivs; i++) { //major ticks
+ x = (int)( (float)i*pixperdiv );
+ painter0.drawLine(x,18,x,30);
+ }
+ int minor=5;
+ if(m_freqPerDiv==200) minor=4;
+ for( int i=1; i<minor*m_hdivs; i++) { //minor ticks
+ x = i*pixperdiv/minor;
+ painter0.drawLine(x,24,x,30);
+ }
+
+ //draw frequency values
+ MakeFrequencyStrs();
+ for( int i=0; i<=m_hdivs; i++) {
+ if(0==i) {
+ //left justify the leftmost text
+ x = (int)( (float)i*pixperdiv);
+ rect0.setRect(x,0, (int)pixperdiv, 20);
+ painter0.drawText(rect0, Qt::AlignLeft|Qt::AlignVCenter,
+ m_HDivText[i]);
+ }
+ else if(m_hdivs == i) {
+ //right justify the rightmost text
+ x = (int)( (float)i*pixperdiv - pixperdiv);
+ rect0.setRect(x,0, (int)pixperdiv, 20);
+ painter0.drawText(rect0, Qt::AlignRight|Qt::AlignVCenter,
+ m_HDivText[i]);
+ } else {
+ //center justify the rest of the text
+ x = (int)( (float)i*pixperdiv - pixperdiv/2);
+ rect0.setRect(x,0, (int)pixperdiv, 20);
+ painter0.drawText(rect0, Qt::AlignHCenter|Qt::AlignVCenter,
+ m_HDivText[i]);
+ }
+ }
+
+ float bw=9.0*12000.0/m_nsps;
+ if(m_modeTx=="JT65") bw=66.0*11025.0/4096.0;
+
+ QPen pen0(Qt::green, 3); //Mark Rx Freq with green
+ painter0.setPen(pen0);
+ x1=XfromFreq(m_rxFreq);
+ x2=XfromFreq(m_rxFreq+bw);
+ painter0.drawLine(x1,24,x1,30);
+ painter0.drawLine(x1,28,x2,28);
+ painter0.drawLine(x2,24,x2,30);
+
+ if(m_mode=="JT9+JT65") {
+ QPen pen2(Qt::blue, 3); //Mark the JT65 | JT9 divider
+ painter0.setPen(pen2);
+ x1=XfromFreq(m_fMin);
+ if(x1<2) x1=2;
+ x2=x1+30;
+ painter0.drawLine(x1,8,x1,28);
+ }
+
+ QPen pen1(Qt::red, 3); //Mark Tx freq with red
+ painter0.setPen(pen1);
+ x1=XfromFreq(m_txFreq);
+ x2=XfromFreq(m_txFreq+bw);
+ painter0.drawLine(x1,17,x1,21);
+ painter0.drawLine(x1,17,x2,17);
+ painter0.drawLine(x2,17,x2,21);
+
+ if(m_dialFreq>10.13 and m_dialFreq< 10.15) {
+ float f1=1.0e6*(10.1401 - m_dialFreq);
+ float f2=f1+200.0;
+ x1=XfromFreq(f1);
+ x2=XfromFreq(f2);
+ if(x1<=m_w and x2>=0) {
+ QPen pen1(QColor(255,165,0),3); //Mark WSPR sub-band orange
+ painter0.setPen(pen1);
+ painter0.drawLine(x1,9,x2,9);
+ }
+ }
+}
+
+void CPlotter::MakeFrequencyStrs() //MakeFrequencyStrs
+{
+ float freq;
+ for(int i=0; i<=m_hdivs; i++) {
+ freq = m_StartFreq + i*m_freqPerDiv;
+ m_HDivText[i].setNum((int)freq);
+ // StartFreq += m_freqPerDiv;
+ }
+}
+
+int CPlotter::XfromFreq(float f) //XfromFreq()
+{
+// float w = m_WaterfallPixmap.width();
+ int x = int(m_w * (f - m_StartFreq)/m_fSpan + 0.5);
+ if(x<0 ) return 0;
+ if(x>m_w) return m_w;
+ return x;
+}
+
+float CPlotter::FreqfromX(int x) //FreqfromX()
+{
+// return float(1000.0 + x*m_binsPerPixel*m_fftBinWidth);
+ return float(x*m_binsPerPixel*m_fftBinWidth);
+}
+
+void CPlotter::SetRunningState(bool running) //SetRunningState()
+{
+ m_Running = running;
+}
+
+void CPlotter::setPlotZero(int plotZero) //setPlotZero()
+{
+ m_plotZero=plotZero;
+}
+
+int CPlotter::getPlotZero() //getPlotZero()
+{
+ return m_plotZero;
+}
+
+void CPlotter::setPlotGain(int plotGain) //setPlotGain()
+{
+ m_plotGain=plotGain;
+}
+
+int CPlotter::getPlotGain() //getPlotGain()
+{
+ return m_plotGain;
+}
+
+void CPlotter::SetStartFreq(quint64 f) //SetStartFreq()
+{
+ m_StartFreq=f;
+// resizeEvent(NULL);
+ DrawOverlay();
+}
+
+qint64 CPlotter::startFreq() //startFreq()
+{
+ return m_StartFreq;
+}
+
+int CPlotter::plotWidth(){return m_WaterfallPixmap.width();}
+void CPlotter::UpdateOverlay() {DrawOverlay();}
+void CPlotter::setDataFromDisk(bool b) {m_dataFromDisk=b;}
+
+void CPlotter::setRxRange(int fMin)
+{
+ m_fMin=fMin;
+}
+
+void CPlotter::setBinsPerPixel(int n) // set nbpp
+{
+ m_binsPerPixel = n;
+ DrawOverlay(); //Redraw scales and ticks
+ update(); //trigger a new paintEvent}
+}
+
+int CPlotter::binsPerPixel() // get nbpp
+{
+ return m_binsPerPixel;
+}
+
+void CPlotter::setRxFreq(int x, bool bf) //setRxFreq()
+{
+ if(bf) {
+ m_rxFreq=x; // x is freq in Hz
+ m_xClick=XfromFreq(m_rxFreq);
+ } else {
+ if(x<0) x=0; // x is pixel number
+ if(x>m_Size.width()) x=m_Size.width();
+ m_rxFreq=int(FreqfromX(x)+0.5);
+ m_xClick=x;
+ }
+ emit setFreq1(m_rxFreq,m_txFreq);
+ DrawOverlay();
+ update();
+}
+
+int CPlotter::rxFreq() {return m_rxFreq;} //get rxFreq
+
+void CPlotter::mousePressEvent(QMouseEvent *event) //mousePressEvent
+{
+ int x=event->x();
+ setRxFreq(x,false); // Wideband waterfall
+ bool ctrl = (event->modifiers() & Qt::ControlModifier);
+ int n=1;
+ if(ctrl) n+=100;
+ emit freezeDecode1(n);
+ if(ctrl or m_lockTxFreq) setTxFreq(m_rxFreq);
+}
+
+void CPlotter::mouseDoubleClickEvent(QMouseEvent *event) //mouse2click
+{
+// int x=event->x();
+// setRxFreq(x,false);
+ bool ctrl = (event->modifiers() & Qt::ControlModifier);
+ int n=2;
+ if(ctrl) n+=100;
+ emit freezeDecode1(n);
+}
+
+void CPlotter::setNSpan(int n) //setNSpan()
+{
+ m_nSpan=n;
+}
+
+void CPlotter::setPalette(QString palette) //setPalette()
+{
+ if(palette=="Linrad") {
+ float twopi=6.2831853;
+ float r,g,b,phi,x;
+ for(int i=0; i<256; i++) {
+ r=0.0;
+ if(i>105 and i<=198) {
+ phi=(twopi/4.0) * (i-105.0)/(198.0-105.0);
+ r=sin(phi);
+ } else if(i>=198) {
+ r=1.0;
+ }
+
+ g=0.0;
+ if(i>35 and i<198) {
+ phi=(twopi/4.0) * (i-35.0)/(122.5-35.0);
+ g=0.625*sin(phi);
+ } else if(i>=198) {
+ x=(i-186.0);
+ g=-0.014 + 0.0144*x -0.00007*x*x +0.000002*x*x*x;
+ if(g>1.0) g=1.0;
+ }
+
+ b=0.0;
+ if(i<=117) {
+ phi=(twopi/2.0) * i/117.0;
+ b=0.4531*sin(phi);
+ } else if(i>186) {
+ x=(i-186.0);
+ b=-0.014 + 0.0144*x -0.00007*x*x +0.000002*x*x*x;
+ if(b>1.0) b=1.0;
+ }
+ m_ColorTbl[i].setRgb(int(255.0*r),int(255.0*g),int(255.0*b));
+ }
+ m_ColorTbl[255].setRgb(255,255,100);
+
+ }
+
+ if(palette=="CuteSDR") {
+ for( int i=0; i<256; i++) {
+ if( (i<43) )
+ m_ColorTbl[i].setRgb( 0,0, 255*(i)/43);
+ if( (i>=43) && (i<87) )
+ m_ColorTbl[i].setRgb( 0, 255*(i-43)/43, 255 );
+ if( (i>=87) && (i<120) )
+ m_ColorTbl[i].setRgb( 0,255, 255-(255*(i-87)/32));
+ if( (i>=120) && (i<154) )
+ m_ColorTbl[i].setRgb( (255*(i-120)/33), 255, 0);
+ if( (i>=154) && (i<217) )
+ m_ColorTbl[i].setRgb( 255, 255 - (255*(i-154)/62), 0);
+ if( (i>=217) )
+ m_ColorTbl[i].setRgb( 255, 0, 128*(i-217)/38);
+ }
+ m_ColorTbl[255].setRgb(255,255,100);
+ }
+
+ if(palette=="Blue") {
+ FILE* fp=fopen("blue.dat","r");
+ int n,r,g,b;
+ float xr,xg,xb;
+ for(int i=0; i<256; i++) {
+ int nn=fscanf(fp,"%d%f%f%f",&n,&xr,&xg,&xb);
+ r=255.0*xr + 0.5;
+ g=255.0*xg + 0.5;
+ b=255.0*xb + 0.5;
+ m_ColorTbl[i].setRgb(r,g,b);
+ if(nn==-999999) i++; //Silence compiler warning
+ }
+ }
+
+ if(palette=="AFMHot") {
+ FILE* fp=fopen("afmhot.dat","r");
+ int n,r,g,b;
+ float xr,xg,xb;
+ for(int i=0; i<256; i++) {
+ int nn=fscanf(fp,"%d%f%f%f",&n,&xr,&xg,&xb);
+ r=255.0*xr + 0.5;
+ g=255.0*xg + 0.5;
+ b=255.0*xb + 0.5;
+ m_ColorTbl[i].setRgb(r,g,b);
+ if(nn==-999999) i++; //Silence compiler warning
+ }
+ }
+
+}
+
+double CPlotter::fGreen()
+{
+ return m_fGreen;
+}
+
+void CPlotter::setNsps(int ntrperiod, int nsps) //setNSpan()
+{
+ m_TRperiod=ntrperiod;
+ m_nsps=nsps;
+ m_fftBinWidth=1500.0/2048.0;
+ if(m_nsps==15360) m_fftBinWidth=1500.0/2048.0;
+ if(m_nsps==40960) m_fftBinWidth=1500.0/6144.0;
+ if(m_nsps==82944) m_fftBinWidth=1500.0/12288.0;
+ if(m_nsps==252000) m_fftBinWidth=1500.0/32768.0;
+ DrawOverlay(); //Redraw scales and ticks
+ update(); //trigger a new paintEvent}
+}
+
+void CPlotter::setTxFreq(int n) //setTol()
+{
+ m_txFreq=n;
+ emit setFreq1(m_rxFreq,m_txFreq);
+ DrawOverlay();
+ update();
+}
+
+void CPlotter::setMode(QString mode)
+{
+ m_mode=mode;
+}
+
+void CPlotter::setModeTx(QString modeTx)
+{
+ m_modeTx=modeTx;
+}
+
+int CPlotter::getFmax()
+{
+ return m_fMax;
+}
+
+void CPlotter::setDialFreq(double d)
+{
+ m_dialFreq=d;
+ DrawOverlay();
+ update();
+}
diff --git a/plotter.h b/plotter.h
new file mode 100644
index 0000000..b491cf9
--- /dev/null
+++ b/plotter.h
@@ -0,0 +1,139 @@
+///////////////////////////////////////////////////////////////////////////
+// Some code in this file and accompanying files is based on work by
+// Moe Wheatley, AE4Y, released under the "Simplified BSD License".
+// For more details see the accompanying file LICENSE_WHEATLEY.TXT
+///////////////////////////////////////////////////////////////////////////
+
+#ifndef PLOTTER_H
+#define PLOTTER_H
+
+#ifdef QT5
+#include <QtWidgets>
+#else
+#include <QtGui>
+#endif
+#include <QFrame>
+#include <QImage>
+#include <cstring>
+#include "commons.h"
+
+#define VERT_DIVS 7 //specify grid screen divisions
+#define HORZ_DIVS 20
+
+class CPlotter : public QFrame
+{
+ Q_OBJECT
+public:
+ explicit CPlotter(QWidget *parent = 0);
+ ~CPlotter();
+
+ QSize minimumSizeHint() const;
+ QSize sizeHint() const;
+ QColor m_ColorTbl[256];
+
+ bool m_bCurrent;
+ bool m_bCumulative;
+ bool m_lockTxFreq;
+
+ float m_fSpan;
+
+ qint32 m_plotZero;
+ qint32 m_plotGain;
+ qint32 m_nSpan;
+ qint32 m_binsPerPixel;
+ qint32 m_w;
+
+ void draw(float sw[], int i0); //Update the waterfall
+ void SetRunningState(bool running);
+ void setPlotZero(int plotZero);
+ int getPlotZero();
+ void setPlotGain(int plotGain);
+ int getPlotGain();
+ void SetStartFreq(quint64 f);
+ qint64 startFreq();
+ int plotWidth();
+ void setNSpan(int n);
+ void UpdateOverlay();
+ void setDataFromDisk(bool b);
+ void setRxRange(int fMin);
+ void setBinsPerPixel(int n);
+ int binsPerPixel();
+ void setRxFreq(int n, bool bf);
+ void DrawOverlay();
+ int rxFreq();
+ void setPalette(QString palette);
+ void setFsample(int n);
+ void setNsps(int ntrperiod, int nsps);
+ void setTxFreq(int n);
+ void setMode(QString mode);
+ void setModeTx(QString modeTx);
+ double fGreen();
+ void SetPercent2DScreen(int percent){m_Percent2DScreen=percent;}
+ int getFmax();
+ void setDialFreq(double d);
+
+signals:
+ void freezeDecode1(int n);
+ void setFreq1(int rxFreq, int txFreq);
+
+protected:
+ //re-implemented widget event handlers
+ void paintEvent(QPaintEvent *event);
+ void resizeEvent(QResizeEvent* event);
+
+private:
+
+ void MakeFrequencyStrs();
+ void UTCstr();
+ int XfromFreq(float f);
+ float FreqfromX(int x);
+ qint64 RoundFreq(qint64 freq, int resolution);
+
+ QPixmap m_WaterfallPixmap;
+ QPixmap m_2DPixmap;
+ QPixmap m_ScalePixmap;
+ QPixmap m_OverlayPixmap;
+// QPixmap m_LowerScalePixmap;
+ QSize m_Size;
+ QString m_Str;
+ QString m_HDivText[483];
+ QString m_mode;
+ QString m_modeTx;
+
+ bool m_Running;
+ bool m_paintEventBusy;
+ bool m_dataFromDisk;
+
+ double m_fGreen;
+ double m_fftBinWidth;
+ double m_dialFreq;
+
+ qint64 m_StartFreq;
+
+ qint32 m_dBStepSize;
+ qint32 m_FreqUnits;
+ qint32 m_hdivs;
+ qint32 m_line;
+ qint32 m_fSample;
+ qint32 m_i0;
+ qint32 m_xClick;
+ qint32 m_freqPerDiv;
+ qint32 m_nsps;
+ qint32 m_Percent2DScreen;
+ qint32 m_h;
+ qint32 m_h1;
+ qint32 m_h2;
+ qint32 m_TRperiod;
+ qint32 m_rxFreq;
+ qint32 m_txFreq;
+ qint32 m_fMin;
+ qint32 m_fMax;
+
+ char m_sutc[6];
+
+private slots:
+ void mousePressEvent(QMouseEvent *event);
+ void mouseDoubleClickEvent(QMouseEvent *event);
+};
+
+#endif // PLOTTER_H
diff --git a/psk_reporter.cpp b/psk_reporter.cpp
new file mode 100644
index 0000000..6856d17
--- /dev/null
+++ b/psk_reporter.cpp
@@ -0,0 +1,104 @@
+// KISS Interface for posting spots to PSK Reporter web site
+// Implemented by Edson Pereira PY2SDR
+//
+// Reports will be sent in batch mode every 5 minutes.
+
+#include "psk_reporter.h"
+
+PSK_Reporter::PSK_Reporter(QObject *parent) :
+ QObject(parent),
+ m_sequenceNumber(0)
+{
+ m_header_h = "000Allllttttttttssssssssiiiiiiii";
+
+ // We use 50E2 and 50E3 for link Id
+ m_rxInfoDescriptor_h = "0003002450E200030000"
+ "8002FFFF0000768F" // 2. Rx Call
+ "8004FFFF0000768F" // 4. Rx Grid
+ "8008FFFF0000768F" // 8. Rx Soft
+ "0000";
+
+ m_txInfoDescriptor_h = "0002003C50E30007"
+ "8001FFFF0000768F" // 1. Tx Call
+ "800500040000768F" // 5. Tx Freq
+ "800600010000768F" // 6. Tx snr
+ "800AFFFF0000768F" // 10. Tx Mode
+ "8003FFFF0000768F" // 3. Tx Grid
+ "800B00010000768F" // 11. Tx info src
+ "00960004"; // Report time
+
+
+ qsrand(QDateTime::currentDateTime().toTime_t());
+ m_randomId_h = QString("%1").arg(qrand(),8,16,QChar('0'));
+
+ m_udpSocket = new QUdpSocket(this);
+
+ reportTimer = new QTimer(this);
+ connect(reportTimer, SIGNAL(timeout()), this, SLOT(sendReport()));
+}
+
+void PSK_Reporter::setLocalStation(QString call, QString gridSquare, QString programInfo)
+{
+ m_rxCall = call;
+ m_rxGrid = gridSquare;
+ m_progId = programInfo;
+ reportTimer->start(5*60*1000); // 5 minutes;
+}
+
+void PSK_Reporter::addRemoteStation(QString call, QString grid, QString freq, QString mode, QString snr, QString time )
+{
+ QHash<QString,QString> spot;
+ spot["call"] = call;
+ spot["grid"] = grid;
+ spot["snr"] = snr;
+ spot["freq"] = freq;
+ spot["mode"] = mode;
+ spot["time"] = time;
+ m_spotQueue.enqueue(spot);
+}
+
+void PSK_Reporter::sendReport()
+{
+ if (m_spotQueue.isEmpty())
+ return;
+
+ // Header
+ QString header_h = m_header_h;
+ header_h.replace("tttttttt", QString("%1").arg(QDateTime::currentDateTime().toTime_t(),8,16,QChar('0')));
+ header_h.replace("ssssssss", QString("%1").arg(++m_sequenceNumber,8,16,QChar('0')));
+ header_h.replace("iiiiiiii", m_randomId_h);
+
+ // Receiver information
+ QString rxInfoData_h = "50E2llll";
+ rxInfoData_h += QString("%1").arg(m_rxCall.length(),2,16,QChar('0')) + m_rxCall.toUtf8().toHex();
+ rxInfoData_h += QString("%1").arg(m_rxGrid.length(),2,16,QChar('0')) + m_rxGrid.toUtf8().toHex();
+ rxInfoData_h += QString("%1").arg(m_progId.length(),2,16,QChar('0')) + m_progId.toUtf8().toHex();
+ rxInfoData_h += "0000";
+ rxInfoData_h.replace("50E2llll", "50E2" + QString("%1").arg(rxInfoData_h.length()/2,4,16,QChar('0')));
+
+ // Sender information
+ QString txInfoData_h = "50E3llll";
+ while (!m_spotQueue.isEmpty()) {
+ QHash<QString,QString> spot = m_spotQueue.dequeue();
+ txInfoData_h += QString("%1").arg(spot["call"].length(),2,16,QChar('0')) + spot["call"].toUtf8().toHex();
+ txInfoData_h += QString("%1").arg(spot["freq"].toLongLong(),8,16,QChar('0'));
+ txInfoData_h += QString("%1").arg(spot["snr"].toInt(),8,16,QChar('0')).right(2);
+ txInfoData_h += QString("%1").arg(spot["mode"].length(),2,16,QChar('0')) + spot["mode"].toUtf8().toHex();
+ txInfoData_h += QString("%1").arg(spot["grid"].length(),2,16,QChar('0')) + spot["grid"].toUtf8().toHex();
+ txInfoData_h += QString("%1").arg(1,2,16,QChar('0')); // REPORTER_SOURCE_AUTOMATIC
+ txInfoData_h += QString("%1").arg(spot["time"].toInt(),8,16,QChar('0'));
+ }
+ txInfoData_h += "0000";
+ txInfoData_h.replace("50E3llll", "50E3" + QString("%1").arg(txInfoData_h.length()/2,4,16,QChar('0')));
+
+ // Build report
+ QString report_h = header_h + m_rxInfoDescriptor_h + m_txInfoDescriptor_h + rxInfoData_h + txInfoData_h;
+ report_h.replace("000Allll", "000A" + QString("%1").arg(report_h.length()/2,4,16,QChar('0')));
+ QByteArray report = QByteArray::fromHex(report_h.toUtf8());
+
+ // Get IP address for pskreporter.info and send report via UDP
+ QHostInfo info = QHostInfo::fromName("report.pskreporter.info");
+ m_udpSocket->writeDatagram(report,info.addresses().at(0),4739);
+}
+
+
diff --git a/psk_reporter.h b/psk_reporter.h
new file mode 100644
index 0000000..abadda1
--- /dev/null
+++ b/psk_reporter.h
@@ -0,0 +1,41 @@
+#ifndef PSK_REPORTER_H
+#define PSK_REPORTER_H
+
+#include <QtCore>
+#include <QUdpSocket>
+#include <QHostInfo>
+
+class PSK_Reporter : public QObject
+{
+ Q_OBJECT
+public:
+ explicit PSK_Reporter(QObject *parent = 0);
+ void setLocalStation(QString call, QString grid, QString programInfo);
+ void addRemoteStation(QString call, QString grid, QString freq, QString mode, QString snr, QString time);
+
+signals:
+
+public slots:
+ void sendReport();
+
+private:
+ QString m_header_h;
+ QString m_rxInfoDescriptor_h;
+ QString m_txInfoDescriptor_h;
+ QString m_randomId_h;
+ QString m_linkId_h;
+
+ QString m_rxCall;
+ QString m_rxGrid;
+ QString m_progId;
+
+ QQueue< QHash<QString,QString> > m_spotQueue;
+
+ QUdpSocket *m_udpSocket;
+
+ QTimer *reportTimer;
+
+ int m_sequenceNumber;
+};
+
+#endif // PSK_REPORTER_H
diff --git a/rigclass.cpp b/rigclass.cpp
new file mode 100644
index 0000000..3f61e03
--- /dev/null
+++ b/rigclass.cpp
@@ -0,0 +1,324 @@
+/**
+ * \file src/rigclass.cc
+ * \brief Ham Radio Control Libraries C++ interface
+ * \author Stephane Fillod
+ * \date 2001-2003
+ *
+ * Hamlib C++ interface is a frontend implementing wrapper functions.
+ */
+
+/**
+ *
+ * Hamlib C++ bindings - main file
+ * Copyright (c) 2001-2003 by Stephane Fillod
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <hamlib/rig.h>
+#include "rigclass.h"
+#include <QDebug>
+#include <QHostAddress>
+
+static int hamlibpp_freq_event(RIG *rig, vfo_t vfo, freq_t freq, rig_ptr_t arg);
+
+static int hamlibpp_freq_event(RIG *rig, vfo_t vfo, freq_t freq, rig_ptr_t arg)
+{
+ if (!rig || !rig->state.obj)
+ return -RIG_EINVAL;
+
+/* assert rig == ((Rig*)rig->state.obj).theRig */
+ return ((Rig*)rig->state.obj)->FreqEvent(vfo, freq, arg);
+}
+
+Rig::Rig()
+{
+ rig_set_debug_level( RIG_DEBUG_WARN);
+}
+
+Rig::~Rig() {
+ theRig->state.obj = NULL;
+ rig_cleanup(theRig);
+ caps = NULL;
+}
+
+int Rig::init(rig_model_t rig_model)
+{
+ int initOk;
+
+ theRig = rig_init(rig_model);
+ if (!theRig)
+ initOk = false;
+ else
+ initOk = true;
+
+ caps = theRig->caps;
+ theRig->callbacks.freq_event = &hamlibpp_freq_event;
+ theRig->state.obj = (rig_ptr_t)this;
+
+ return initOk;
+}
+
+int Rig::open(int n) {
+ m_hrd=false;
+ m_cmndr=false;
+ if(n<9900) {
+ if(n==-99999) return -1; //Silence compiler warning
+ return rig_open(theRig);
+ }
+
+#ifdef WIN32 // Ham radio Deluxe or Commander (Windows only)
+ if(n==9999) {
+ m_hrd=true;
+ bool bConnect=false;
+ bConnect = HRDInterfaceConnect(L"localhost",7809);
+ if(bConnect) {
+ const wchar_t* context=HRDInterfaceSendMessage(L"Get Context");
+ m_context="[" + QString::fromWCharArray (context,-1) + "] ";
+ HRDInterfaceFreeString(context);
+ return 0;
+ } else {
+ m_hrd=false;
+ return -1;
+ }
+ }
+ if(n==9998) {
+ if(socket->state()==QAbstractSocket::ConnectedState) {
+ socket->abort();
+ }
+
+ if(socket->state()==QAbstractSocket::UnconnectedState) {
+ socket->connectToHost(QHostAddress::LocalHost, 52002);
+ if(!socket->waitForConnected(1000)) {
+ return -1;
+ }
+ }
+ QString t;
+ t="<command:10>CmdGetFreq<parameters:0>";
+ QByteArray ba = t.toLocal8Bit();
+ const char* buf=ba.data();
+ socket->write(buf);
+ socket->waitForReadyRead(1000);
+ QByteArray reply=socket->read(128);
+ if(reply.indexOf("<CmdFreq:")==0) {
+ m_cmndr=true;
+ return 0;
+ }
+ }
+#endif
+ return -1;
+}
+
+int Rig::close(void) {
+#ifdef WIN32 // Ham Radio Deluxe only on Windows
+ if(m_hrd) {
+ HRDInterfaceDisconnect();
+ return 0;
+ } else if(m_cmndr) {
+ socket->close();
+ return 0;
+ } else
+#endif
+ {
+ return rig_close(theRig);
+ }
+}
+
+int Rig::setConf(const char *name, const char *val)
+{
+ return rig_set_conf(theRig, tokenLookup(name), val);
+}
+
+int Rig::setFreq(freq_t freq, vfo_t vfo) {
+#ifdef WIN32 // Ham Radio Deluxe (only on Windows)
+ if(m_hrd) {
+ QString t;
+ int nhz=(int)freq;
+ t=m_context + "Set Frequency-Hz " + QString::number(nhz);
+ const wchar_t* cmnd = (const wchar_t*) t.utf16();
+ const wchar_t* result=HRDInterfaceSendMessage(cmnd);
+ QString t2=QString::fromWCharArray (result,-1);
+ HRDInterfaceFreeString(result);
+ if(t2=="OK") {
+ return 0;
+ } else {
+ return -1;
+ }
+ } else if(m_cmndr) {
+ QString t;
+ double f=0.001*freq;
+ t.sprintf("<command:10>CmdSetFreq<parameters:23><xcvrfreq:10>%10.3f",f);
+ QByteArray ba = t.toLocal8Bit();
+ const char* buf=ba.data();
+ socket->write(buf);
+ socket->waitForBytesWritten(1000);
+ return 0;
+ } else
+#endif
+ {
+ return rig_set_freq(theRig, vfo, freq);
+ }
+}
+
+int Rig::setXit(shortfreq_t xit, vfo_t vfo)
+{
+ return rig_set_xit(theRig, vfo, xit);
+}
+
+int Rig::setVFO(vfo_t vfo)
+{
+ return rig_set_vfo(theRig, vfo);
+}
+
+vfo_t Rig::getVFO()
+{
+ vfo_t vfo;
+ rig_get_vfo(theRig, &vfo);
+ return vfo;
+}
+
+int Rig::setSplitFreq(freq_t tx_freq, vfo_t vfo) {
+#ifdef WIN32 // Ham Radio Deluxe only on Windows
+ if(m_hrd) {
+ QString t;
+ int nhz=(int)tx_freq;
+ t=m_context + "Set Frequency-Hz " + QString::number(nhz);
+ const wchar_t* cmnd = (const wchar_t*) t.utf16();
+ const wchar_t* result=HRDInterfaceSendMessage(cmnd);
+ QString t2=QString::fromWCharArray (result,-1);
+ HRDInterfaceFreeString(result);
+ if(t2=="OK") {
+ return 0;
+ } else {
+ return -1;
+ }
+ } else if(m_cmndr) {
+ QString t;
+ double f=0.001*tx_freq;
+ t.sprintf("<command:12>CmdSetTxFreq<parameters:23><xcvrfreq:10>%10.3f",f);
+ QByteArray ba = t.toLocal8Bit();
+ const char* buf=ba.data();
+ socket->write(buf);
+ socket->waitForBytesWritten(1000);
+ return 0;
+ } else
+#endif
+ {
+ return rig_set_split_freq(theRig, vfo, tx_freq);
+ }
+}
+
+freq_t Rig::getFreq(vfo_t vfo)
+{
+ freq_t freq;
+#ifdef WIN32 // Ham Radio Deluxe (only on Windows)
+ if(m_hrd) {
+ const wchar_t* cmnd = (const wchar_t*) (m_context+"Get Frequency").utf16();
+ const wchar_t* freqString=HRDInterfaceSendMessage(cmnd);
+ QString t2=QString::fromWCharArray (freqString,-1);
+ HRDInterfaceFreeString(freqString);
+ freq=t2.toDouble();
+ return freq;
+ } else if(m_cmndr) {
+ QString t;
+ t="<command:10>CmdGetFreq<parameters:0>";
+ QByteArray ba = t.toLocal8Bit();
+ const char* buf=ba.data();
+ socket->write(buf);
+ socket->waitForReadyRead(1000);
+ QByteArray reply=socket->read(128);
+ QString t2(reply);
+ if(t2.indexOf("<CmdFreq:")==0) {
+ int i1=t2.indexOf(">");
+ t2=t2.mid(i1+1).replace(",","");
+ freq=1000.0*t2.toDouble();
+ return freq;
+ } else {
+ return -1.0;
+ }
+ } else
+#endif
+ {
+ int iret=rig_get_freq(theRig, vfo, &freq);
+// iret should be 0. Negative values mean rig_get_freq() failed.
+ if(iret<0) freq=-1.0;
+ return freq;
+ }
+}
+
+int Rig::setMode(rmode_t mode, pbwidth_t width, vfo_t vfo) {
+ return rig_set_mode(theRig, vfo, mode, width);
+}
+
+rmode_t Rig::getMode(pbwidth_t& width, vfo_t vfo) {
+ rmode_t mode;
+ rig_get_mode(theRig, vfo, &mode, &width);
+ return mode;
+}
+
+int Rig::setPTT(ptt_t ptt, vfo_t vfo)
+{
+#ifdef WIN32 // Ham Radio Deluxe only on Windows
+ if(m_hrd) {
+ wchar_t* cmnd;
+
+ if(ptt==0) {
+ cmnd = (wchar_t*) (m_context +
+ "Set Button-Select TX 0").utf16();
+ } else {
+ cmnd = (wchar_t*) (m_context +
+ "Set Button-Select TX 1").utf16();
+ }
+ const wchar_t* result=HRDInterfaceSendMessage(cmnd);
+ QString t2=QString::fromWCharArray (result,-1);
+ HRDInterfaceFreeString(result);
+ if(t2=="OK") {
+ return 0;
+ } else {
+ return -1;
+ }
+ } else if(m_cmndr) {
+ QString t;
+ if(ptt==0) t="<command:5>CmdRX<parameters:0>";
+ if(ptt>0) t="<command:5>CmdTX<parameters:0>";
+ QByteArray ba = t.toLocal8Bit();
+ const char* buf=ba.data();
+ socket->write(buf);
+ socket->waitForBytesWritten(1000);
+ return 0;
+ } else
+#endif
+ {
+ return rig_set_ptt(theRig, vfo, ptt);
+ }
+}
+
+ptt_t Rig::getPTT(vfo_t vfo)
+{
+ ptt_t ptt;
+ rig_get_ptt(theRig, vfo, &ptt);
+ return ptt;
+}
+
+token_t Rig::tokenLookup(const char *name)
+{
+ return rig_token_lookup(theRig, name);
+}
diff --git a/rigclass.h b/rigclass.h
new file mode 100644
index 0000000..9c933e7
--- /dev/null
+++ b/rigclass.h
@@ -0,0 +1,98 @@
+/*
+ * Hamlib C++ bindings - API header
+ * Copyright (c) 2001-2002 by Stephane Fillod
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _RIGCLASS_H
+#define _RIGCLASS_H 1
+
+#include <hamlib/rig.h>
+#include <iostream>
+#include <QString>
+#include <QTcpSocket>
+
+extern QTcpSocket* socket;
+
+class BACKEND_IMPEXP Rig {
+private:
+ RIG* theRig; // Global ref. to the rig
+ bool m_hrd;
+ bool m_cmndr;
+ QString m_context;
+
+
+protected:
+public:
+ Rig();
+ virtual ~Rig();
+
+ const struct rig_caps *caps;
+
+ // Initialize rig
+ int init(rig_model_t rig_model);
+
+ // This method open the communication port to the rig
+ int open(int n);
+
+ // This method close the communication port to the rig
+ int close(void);
+
+ int setConf(const char *name, const char *val);
+ token_t tokenLookup(const char *name);
+
+ int setFreq(freq_t freq, vfo_t vfo = RIG_VFO_CURR);
+ freq_t getFreq(vfo_t vfo = RIG_VFO_CURR);
+ int setMode(rmode_t, pbwidth_t width = RIG_PASSBAND_NORMAL, vfo_t vfo = RIG_VFO_CURR);
+ rmode_t getMode(pbwidth_t&, vfo_t vfo = RIG_VFO_CURR);
+ int setVFO(vfo_t);
+ vfo_t getVFO();
+ int setXit(shortfreq_t xit, vfo_t vfo);
+ int setSplitFreq(freq_t tx_freq, vfo_t vfo = RIG_VFO_CURR);
+ int setPTT (ptt_t ptt, vfo_t vfo = RIG_VFO_CURR);
+ ptt_t getPTT (vfo_t vfo = RIG_VFO_CURR);
+
+ // callbacks available in your derived object
+ virtual int FreqEvent(vfo_t, freq_t, rig_ptr_t) const {
+ return RIG_OK;
+ }
+ virtual int ModeEvent(vfo_t, rmode_t, pbwidth_t, rig_ptr_t) const {
+ return RIG_OK;
+ }
+ virtual int VFOEvent(vfo_t, rig_ptr_t) const {
+ return RIG_OK;
+ }
+ virtual int PTTEvent(vfo_t, ptt_t, rig_ptr_t) const {
+ return RIG_OK;
+ }
+ virtual int DCDEvent(vfo_t, dcd_t, rig_ptr_t) const {
+ return RIG_OK;
+ }
+};
+
+#ifdef WIN32
+extern "C" {
+ bool HRDInterfaceConnect(const wchar_t *host, const ushort);
+ void HRDInterfaceDisconnect();
+ bool HRDInterfaceIsConnected();
+ wchar_t* HRDInterfaceSendMessage(const wchar_t *msg);
+ void HRDInterfaceFreeString(const wchar_t *lstring);
+}
+#endif
+
+#endif // _RIGCLASS_H
diff --git a/shortcuts.txt b/shortcuts.txt
new file mode 100644
index 0000000..821ec70
--- /dev/null
+++ b/shortcuts.txt
@@ -0,0 +1,26 @@
+F1 Online User's Guide
+Ctrl+F1 About WSJT-X
+F2 Open configuration window
+F3 Display keyboard shortcuts
+F4 Clear Dx Call and Dx Grid entries
+Alt+F4 Exit program
+F5 Display special mouse commands
+F6 Open next in directory
+F11 Move Rx frequency down 1 Hz
+Ctrl+F11 Move Rx and Tx frequencies down 1 Hz
+F12 Move Rx frequency up 1 Hz
+Ctrl+F12 Move Rx and Tx frequencies up 1 Hz
+Shift+F6 Decode remaining files in directory
+Alt+D Decode again at QSO frequency
+Shift+D Full-bandwidth decode (both windows)
+Alt+E Erase()
+Ctrl+F Edit the free text message box
+Alt+G Generate standard messages
+Alt+H Halt Tx()
+Ctrl+L Lookup callsign in database, generate standard messages
+Alt M Monitor()
+Alt+N Enable Tx()
+Alt+Q Log QSO()
+Alt+S Stop()
+Alt+T Tune
+Alt+V Save the most recently completed *.wav file
diff --git a/signalmeter.cpp b/signalmeter.cpp
new file mode 100644
index 0000000..537b900
--- /dev/null
+++ b/signalmeter.cpp
@@ -0,0 +1,53 @@
+// Simple bargraph dB meter
+// Implemented by Edson Pereira PY2SDR
+//
+// Limits and geometry are hardcded for now.
+
+#include "signalmeter.h"
+
+SignalMeter::SignalMeter(QWidget *parent) :
+ QWidget(parent)
+{
+ resize(parent->size());
+
+ m_meter = new MeterWidget(this);
+ m_meter->setGeometry(10, 10, 10, 120);
+
+ m_label = new QLabel(this);
+ m_label->setGeometry(10, 135, 20, 20);
+
+ QLabel *dbLabel = new QLabel(this);
+ dbLabel->setText("dB");
+ dbLabel->setGeometry(30, 135, 20, 20);
+}
+
+SignalMeter::~SignalMeter()
+{
+
+}
+
+void SignalMeter::paintEvent( QPaintEvent * )
+{
+ QPainter p;
+ p.begin(this);
+ p.drawLine(22, 10, 22, 130);
+
+ for ( int i = 0; i <= 60; i += 10 ) {
+ p.drawLine(22, i*2 + 10, 25, i*2 + 10);
+ }
+
+ for ( int i = 10; i < 60; i += 10 ) {
+ p.drawText(30, i*2 + 15, QString::number(60 - i));
+ }
+}
+
+void SignalMeter::setValue(int value)
+{
+ m_meter->setValue(value);
+ m_label->setText(QString::number(value));
+}
+
+void SignalMeter::resizeEvent(QResizeEvent *s)
+{
+ resize(s->size());
+}
diff --git a/signalmeter.h b/signalmeter.h
new file mode 100644
index 0000000..ea1aa62
--- /dev/null
+++ b/signalmeter.h
@@ -0,0 +1,32 @@
+#ifndef SIGNALMETER_H
+#define SIGNALMETER_H
+
+#include <QtGui>
+#include <QLabel>
+#include <meterwidget.h>
+
+class SignalMeter : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit SignalMeter(QWidget *parent = 0);
+ ~SignalMeter();
+
+public slots:
+ void setValue(int value);
+
+private:
+ MeterWidget *m_meter;
+
+ QLabel *m_label;
+
+ int m_signal;
+ int m_sigPeak;
+
+protected:
+ void paintEvent( QPaintEvent * );
+ void resizeEvent(QResizeEvent *s);
+};
+
+#endif // SIGNALMETER_H
diff --git a/sleep.h b/sleep.h
new file mode 100644
index 0000000..c11188c
--- /dev/null
+++ b/sleep.h
@@ -0,0 +1,16 @@
+#ifndef SLEEP_H
+#define SLEEP_H
+#include <qthread.h>
+
+class Sleep : public QThread
+{
+public:
+ static void msleep(int ms) {
+ QThread::msleep(ms);
+ }
+ static int idealThreadCount() {
+ return QThread::idealThreadCount();
+ }
+};
+
+#endif // SLEEP_H
diff --git a/soundin.cpp b/soundin.cpp
new file mode 100644
index 0000000..332e5d3
--- /dev/null
+++ b/soundin.cpp
@@ -0,0 +1,208 @@
+#include "soundin.h"
+#include <stdexcept>
+
+#define FRAMES_PER_BUFFER 1024
+//#define NSMAX 1365
+#define NSMAX 6827
+#define NTMAX 120
+
+extern "C" {
+#include <portaudio.h>
+extern struct {
+ float ss[184*NSMAX]; //This is "common/jt9com/..." in fortran
+ float savg[NSMAX];
+// float c0[2*NTMAX*1500];
+ short int d2[NTMAX*12000];
+ int nutc; //UTC as integer, HHMM
+ int ndiskdat; //1 ==> data read from *.wav file
+ int ntrperiod; //TR period (seconds)
+ int mousefqso; //User-selected QSO freq (kHz)
+ int newdat; //1 ==> new data, must do long FFT
+ int npts8; //npts in c0() array
+ int nfa; //Low decode limit (Hz)
+ int nfb; //High decode limit (Hz)
+ int ntol; //+/- decoding range around fQSO (Hz)
+ int kin;
+ int nzhsym;
+ int nsave;
+ int nagain;
+ int ndepth;
+ int ntxmode;
+ int nmode;
+ char datetime[20];
+} jt9com_;
+}
+
+typedef struct
+{
+ int kin; //Parameters sent to/from the portaudio callback function
+ int ncall;
+ bool bzero;
+ bool monitoring;
+} paUserData;
+
+//--------------------------------------------------------------- a2dCallback
+extern "C" int a2dCallback( const void *inputBuffer, void *outputBuffer,
+ unsigned long framesToProcess,
+ const PaStreamCallbackTimeInfo* timeInfo,
+ PaStreamCallbackFlags statusFlags,
+ void *userData )
+
+// This routine called by the PortAudio engine when samples are available.
+// It may be called at interrupt level, so don't do anything
+// that could mess up the system like calling malloc() or free().
+
+{
+ paUserData *udata=(paUserData*)userData;
+ (void) outputBuffer; //Prevent unused variable warnings.
+ (void) timeInfo;
+ (void) userData;
+ int nbytes,k;
+
+ udata->ncall++;
+ if( (statusFlags&paInputOverflow) != 0) {
+ qDebug() << "Input Overflow in a2dCallback";
+ }
+ if(udata->bzero) { //Start of a new Rx sequence
+ udata->kin=0; //Reset buffer pointer
+ udata->bzero=false;
+ }
+
+ nbytes=2*framesToProcess; //Bytes per frame
+ k=udata->kin;
+ if(udata->monitoring) {
+ memcpy(&jt9com_.d2[k],inputBuffer,nbytes); //Copy all samples to d2
+ }
+ udata->kin += framesToProcess;
+ jt9com_.kin=udata->kin;
+
+ return paContinue;
+}
+
+void SoundInThread::run() //SoundInThread::run()
+{
+ quitExecution = false;
+
+//---------------------------------------------------- Soundcard Setup
+ PaError paerr;
+ PaStreamParameters inParam;
+ PaStream *inStream;
+ paUserData udata;
+
+ udata.kin=0; //Buffer pointer
+ udata.ncall=0; //Number of callbacks
+ udata.bzero=false; //Flag to request reset of kin
+ udata.monitoring=m_monitoring;
+
+ inParam.device=m_nDevIn; //### Input Device Number ###
+ inParam.channelCount=1; //Number of analog channels
+ inParam.sampleFormat=paInt16; //Get i*2 from Portaudio
+ inParam.suggestedLatency=0.05;
+ inParam.hostApiSpecificStreamInfo=NULL;
+
+ paerr=Pa_IsFormatSupported(&inParam,NULL,12000.0);
+ if(paerr<0) {
+ emit error("PortAudio says requested soundcard format not supported.");
+// return;
+ }
+ qDebug() << "";
+ paerr=Pa_OpenStream(&inStream, //Input stream
+ &inParam, //Input parameters
+ NULL, //No output parameters
+ 12000.0, //Sample rate
+ FRAMES_PER_BUFFER, //Frames per buffer
+// paClipOff+paDitherOff, //No clipping or dithering
+ paClipOff, //No clipping
+ a2dCallback, //Input callback routine
+ &udata); //userdata
+
+ paerr=Pa_StartStream(inStream);
+ if(paerr<0) {
+ emit error("Failed to start audio input stream.");
+ return;
+ }
+
+ bool qe = quitExecution;
+ static int ntr0=99;
+ int k=0;
+ int nsec;
+ int ntr;
+ int nBusy=0;
+ int nstep0=0;
+ int nsps0=0;
+ qint64 ms0 = QDateTime::currentMSecsSinceEpoch();
+
+//---------------------------------------------- Soundcard input loop
+ while (!qe) {
+ qe = quitExecution;
+ if (qe) break;
+ udata.monitoring=m_monitoring;
+ qint64 ms = QDateTime::currentMSecsSinceEpoch();
+ m_SamFacIn=1.0;
+ if(udata.ncall>100) {
+ m_SamFacIn=udata.ncall*FRAMES_PER_BUFFER*1000.0/(12000.0*(ms-ms0-50));
+ }
+ ms=ms % 86400000;
+ nsec = ms/1000; // Time according to this computer
+ ntr = nsec % m_TRperiod;
+
+// Reset buffer pointer and symbol number at start of minute
+ if(ntr < ntr0 or !m_monitoring or m_nsps!=nsps0) {
+ nstep0=0;
+ nsps0=m_nsps;
+ udata.bzero=true;
+ }
+ k=udata.kin;
+ if(m_monitoring) {
+ int kstep=m_nsps/2;
+// m_step=k/kstep;
+ m_step=(k-1)/kstep;
+ if(m_step != nstep0) {
+ if(m_dataSinkBusy) {
+ nBusy++;
+ } else {
+// m_dataSinkBusy=true;
+// emit readyForFFT(k); //Signal to compute new FFTs
+ emit readyForFFT(k-1); //Signal to compute new FFTs
+ }
+ nstep0=m_step;
+ }
+ }
+ msleep(100);
+ ntr0=ntr;
+ }
+ Pa_StopStream(inStream);
+ Pa_CloseStream(inStream);
+}
+
+void SoundInThread::setInputDevice(int n) //setInputDevice()
+{
+ if (isRunning()) return;
+ this->m_nDevIn=n;
+}
+
+void SoundInThread::quit() //quit()
+{
+ quitExecution = true;
+}
+
+void SoundInThread::setMonitoring(bool b) //setMonitoring()
+{
+ m_monitoring = b;
+}
+
+void SoundInThread::setPeriod(int ntrperiod, int nsps)
+{
+ m_TRperiod=ntrperiod;
+ m_nsps=nsps;
+}
+
+int SoundInThread::mstep()
+{
+ return m_step;
+}
+
+double SoundInThread::samFacIn()
+{
+ return m_SamFacIn;
+}
diff --git a/soundin.h b/soundin.h
new file mode 100644
index 0000000..955f08d
--- /dev/null
+++ b/soundin.h
@@ -0,0 +1,50 @@
+#ifndef SOUNDIN_H
+#define SOUNDIN_H
+
+#include <QtCore>
+#include <QDebug>
+
+
+// Thread gets audio data from soundcard and signals when a buffer of
+// specified size is available.
+class SoundInThread : public QThread
+{
+ Q_OBJECT
+ bool quitExecution; // if true, thread exits gracefully
+
+protected:
+ virtual void run();
+
+public:
+ bool m_dataSinkBusy;
+
+ SoundInThread():
+ quitExecution(false),
+ m_dataSinkBusy(false)
+ {
+ }
+
+ void setInputDevice(qint32 n);
+ void setMonitoring(bool b);
+ void setPeriod(int ntrperiod, int nsps);
+ int mstep();
+ double samFacIn();
+
+signals:
+ void readyForFFT(int k);
+ void error(const QString& message);
+ void status(const QString& message);
+
+public slots:
+ void quit();
+
+private:
+ double m_SamFacIn; //(Input sample rate)/12000.0
+ qint32 m_step;
+ qint32 m_nDevIn;
+ qint32 m_TRperiod;
+ qint32 m_TRperiod0;
+ qint32 m_nsps;
+ bool m_monitoring;
+};
+#endif // SOUNDIN_H
diff --git a/soundout.cpp b/soundout.cpp
new file mode 100644
index 0000000..8693237
--- /dev/null
+++ b/soundout.cpp
@@ -0,0 +1,270 @@
+#include "soundout.h"
+
+//#define FRAMES_PER_BUFFER 1024
+
+extern "C" {
+#include <portaudio.h>
+}
+
+extern float gran(); //Noise generator (for tests only)
+extern int itone[126]; //Audio tones for all Tx symbols
+extern int icw[250]; //Dits for CW ID
+extern int outBufSize;
+extern bool btxok;
+extern bool btxMute;
+extern double outputLatency;
+
+typedef struct //Parameters sent to or received from callback function
+{
+ double txsnrdb;
+ double dnsps;
+ int ntrperiod;
+ int ntxfreq;
+ int xit;
+ int ncall;
+ int nsym;
+ bool txMute;
+ bool bRestart;
+ bool btune;
+} paUserData;
+
+//--------------------------------------------------------------- d2aCallback
+extern "C" int d2aCallback(const void *inputBuffer, void *outputBuffer,
+ unsigned long framesToProcess,
+ const PaStreamCallbackTimeInfo* timeInfo,
+ PaStreamCallbackFlags statusFlags,
+ void *userData )
+{
+ paUserData *udata=(paUserData*)userData;
+ short *wptr = (short*)outputBuffer;
+
+ static double twopi=2.0*3.141592653589793238462;
+ static double baud;
+ static double phi=0.0;
+ static double dphi;
+ static double freq;
+ static double snr;
+ static double fac;
+ static double amp;
+ static int ic=0,j=0;
+ static int isym0=-999;
+ static short int i2;
+ int isym,nspd;
+
+ udata->ncall++;
+ if(udata->bRestart) {
+ // Time according to this computer
+ qint64 ms = QDateTime::currentMSecsSinceEpoch() % 86400000;
+ int mstr = ms % (1000*udata->ntrperiod );
+ if(mstr<1000) return paContinue;
+ ic=(mstr-1000)*48;
+ udata->bRestart=false;
+ srand(mstr); //Initialize random seed
+ }
+ isym=ic/(4.0*udata->dnsps); //Actual fsample=48000
+ if(udata->btune) isym=0; //If tuning, send pure tone
+ if(udata->txsnrdb < 0.0) {
+ snr=pow(10.0,0.05*(udata->txsnrdb-6.0));
+ fac=3000.0;
+ if(snr>1.0) fac=3000.0/snr;
+ }
+
+ if(isym>=udata->nsym and icw[0]>0) { //Output the CW ID
+ freq=udata->ntxfreq - udata->xit;
+ dphi=twopi*freq/48000.0;
+
+// float wpm=20.0;
+// int nspd=1.2*48000.0/wpm;
+// nspd=3072; //18.75 WPM
+ nspd=2048 + 512; //22.5 WPM
+ int ic0=udata->nsym*4*udata->dnsps;
+ for(uint i=0 ; i<framesToProcess; i++ ) {
+ phi += dphi;
+ if(phi>twopi) phi -= twopi;
+ i2=32767.0*sin(phi);
+ j=(ic-ic0)/nspd + 1;
+ if(icw[j]==0) i2=0;
+ if(udata->txsnrdb < 0.0) {
+ int i4=fac*(gran() + i2*snr/32768.0);
+ if(i4>32767) i4=32767;
+ if(i4<-32767) i4=-32767;
+ i2=i4;
+ }
+ if(!btxok or btxMute) i2=0;
+ *wptr++ = i2; //left
+#ifdef UNIX
+ *wptr++ = i2; //right
+#endif
+ ic++;
+ }
+ if(j>icw[0]) return paComplete;
+ if(statusFlags==999999 and timeInfo==NULL and
+ inputBuffer==NULL) return paContinue; //Silence compiler warning:
+ return paContinue;
+ }
+
+ baud=12000.0/udata->dnsps;
+ amp=32767.0;
+ int i0=(udata->nsym-0.017)*4.0*udata->dnsps;
+ int i1=udata->nsym*4.0*udata->dnsps;
+ if(udata->btune) { //If tuning, no ramp down
+ i0=999*udata->dnsps;
+ i1=i0;
+ }
+ for(uint i=0 ; i<framesToProcess; i++ ) {
+ isym=ic/(4.0*udata->dnsps); //Actual fsample=48000
+ if(udata->btune) isym=0; //If tuning, send pure tone
+ if(isym!=isym0) {
+ freq=udata->ntxfreq + itone[isym]*baud - udata->xit;
+ dphi=twopi*freq/48000.0;
+ isym0=isym;
+ }
+ phi += dphi;
+ if(phi>twopi) phi -= twopi;
+ if(ic>i0) amp=0.98*amp;
+ if(ic>i1) amp=0.0;
+ i2=amp*sin(phi);
+ if(udata->txsnrdb < 0.0) {
+ int i4=fac*(gran() + i2*snr/32768.0);
+ if(i4>32767) i4=32767;
+ if(i4<-32767) i4=-32767;
+ i2=i4;
+ }
+ if(!btxok or btxMute) i2=0;
+ *wptr++ = i2; //left
+#ifdef UNIX
+ *wptr++ = i2; //right
+#endif
+ ic++;
+ }
+ if(amp==0.0) {
+ if(icw[0]==0) return paComplete;
+ phi=0.0;
+ }
+ return paContinue;
+}
+
+void SoundOutThread::run()
+{
+ PaError paerr;
+ PaStreamParameters outParam;
+ PaStream *outStream;
+ paUserData udata;
+ quitExecution = false;
+
+ outParam.device=m_nDevOut; //Output device number
+ outParam.channelCount=1; //Number of analog channels
+#ifdef UNIX
+ outParam.channelCount=2; //Number of analog channels
+#endif
+ outParam.sampleFormat=paInt16; //Send short ints to PortAudio
+ outParam.suggestedLatency=0.05;
+ outParam.hostApiSpecificStreamInfo=NULL;
+
+ paerr=Pa_IsFormatSupported(NULL,&outParam,48000.0);
+ if(paerr<0) {
+ qDebug() << "PortAudio says requested output format not supported.";
+ qDebug() << paerr << m_nDevOut;
+ return;
+ }
+
+ udata.txsnrdb=99.0;
+ udata.dnsps=m_nsps;
+ udata.nsym=85;
+ if(m_modeTx=="JT65") {
+ udata.dnsps=4096.0*12000.0/11025.0;
+ udata.nsym=126;
+ }
+ udata.ntrperiod=m_TRperiod;
+ udata.ntxfreq=m_txFreq;
+ udata.xit=m_xit;
+ udata.ncall=0;
+ udata.txMute=m_txMute;
+ udata.bRestart=true;
+ udata.btune=m_tune;
+
+ paerr=Pa_OpenStream(&outStream, //Output stream
+ NULL, //No input parameters
+ &outParam, //Output parameters
+ 48000.0, //Sample rate
+ outBufSize, //Frames per buffer
+ paClipOff, //No clipping
+ d2aCallback, //output callbeck routine
+ &udata); //userdata
+
+ paerr=Pa_StartStream(outStream);
+ if(paerr<0) {
+ qDebug() << "Failed to start audio output stream.";
+ return;
+ }
+ const PaStreamInfo* p=Pa_GetStreamInfo(outStream);
+ outputLatency = p->outputLatency;
+ bool qe = quitExecution;
+ qint64 ms0 = QDateTime::currentMSecsSinceEpoch();
+
+//---------------------------------------------- Soundcard output loop
+ while (!qe) {
+ qe = quitExecution;
+ if (qe) break;
+
+ udata.txsnrdb=m_txsnrdb;
+ udata.dnsps=m_nsps;
+ udata.nsym=85;
+ if(m_modeTx=="JT65") {
+ udata.dnsps=4096.0*12000.0/11025.0;
+ udata.nsym=126;
+ }
+ udata.ntrperiod=m_TRperiod;
+ udata.ntxfreq=m_txFreq;
+ udata.xit=m_xit;
+ udata.txMute=m_txMute;
+ udata.btune=m_tune;
+
+ m_SamFacOut=1.0;
+ if(udata.ncall>400) {
+ qint64 ms = QDateTime::currentMSecsSinceEpoch();
+ m_SamFacOut=udata.ncall*outBufSize*1000.0/(48000.0*(ms-ms0-50));
+ }
+ msleep(100);
+ }
+ Pa_StopStream(outStream);
+ Pa_CloseStream(outStream);
+}
+
+void SoundOutThread::setOutputDevice(int n) //setOutputDevice()
+{
+ if (isRunning()) return;
+ this->m_nDevOut=n;
+}
+
+void SoundOutThread::setPeriod(int ntrperiod, int nsps)
+{
+ m_TRperiod=ntrperiod;
+ m_nsps=nsps;
+}
+
+void SoundOutThread::setTxFreq(int n)
+{
+ m_txFreq=n;
+}
+
+void SoundOutThread::setXIT(int n)
+{
+ m_xit=n;
+
+}
+
+void SoundOutThread::setTxSNR(double snr)
+{
+ m_txsnrdb=snr;
+}
+
+void SoundOutThread::setTune(bool b)
+{
+ m_tune=b;
+}
+
+double SoundOutThread::samFacOut()
+{
+ return m_SamFacOut;
+}
diff --git a/soundout.h b/soundout.h
new file mode 100644
index 0000000..a289afc
--- /dev/null
+++ b/soundout.h
@@ -0,0 +1,53 @@
+#ifndef SOUNDOUT_H
+#define SOUNDOUT_H
+#include <QtCore>
+#include <QDebug>
+
+// An instance of this thread sends audio data to a specified soundcard.
+// Output can be muted while underway, preserving waveform timing when
+// transmission is resumed.
+
+class SoundOutThread : public QThread
+{
+ Q_OBJECT
+
+protected:
+ virtual void run();
+
+public:
+// Constructs (but does not start) a SoundOutThread
+ SoundOutThread()
+ : quitExecution(false) // Initialize some private members
+ , m_txOK(false)
+ , m_txMute(false)
+ {
+ }
+
+public:
+ void setOutputDevice(qint32 n);
+ void setPeriod(int ntrperiod, int nsps);
+ void setTxFreq(int n);
+ void setXIT(int n);
+ void setTxSNR(double snr);
+ void setTune(bool b);
+ double samFacOut();
+ bool quitExecution; //If true, thread exits gracefully
+ QString m_modeTx;
+
+// Private members
+private:
+ double m_txsnrdb; //if < 0, add noise to Tx audio
+ double m_SamFacOut; //(Output sample rate)/48000.0
+
+ qint32 m_nDevOut; //Output device number
+ qint32 m_TRperiod; //T/R period (s)
+ qint32 m_nsps; //Samples per symbol (at 12000 Hz)
+ qint32 m_txFreq;
+ qint32 m_xit;
+
+ bool m_txOK; //Enable Tx audio
+ bool m_txMute; //Mute temporarily
+ bool m_tune;
+};
+
+#endif
diff --git a/ss.bat b/ss.bat
new file mode 100644
index 0000000..37f669a
--- /dev/null
+++ b/ss.bat
@@ -0,0 +1 @@
+svn status | grep -v '?'
diff --git a/sss.bat b/sss.bat
new file mode 100644
index 0000000..7b51c8c
--- /dev/null
+++ b/sss.bat
@@ -0,0 +1 @@
+svn status
diff --git a/widegraph.cpp b/widegraph.cpp
new file mode 100644
index 0000000..3efa1f2
--- /dev/null
+++ b/widegraph.cpp
@@ -0,0 +1,314 @@
+#include "widegraph.h"
+#include "ui_widegraph.h"
+#include "commons.h"
+
+WideGraph::WideGraph(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::WideGraph)
+{
+ ui->setupUi(this);
+ this->setWindowFlags(Qt::Dialog);
+ this->installEventFilter(parent); //Installing the filter
+ ui->widePlot->setCursor(Qt::CrossCursor);
+ this->setMaximumWidth(2048);
+ this->setMaximumHeight(880);
+ ui->widePlot->setMaximumHeight(800);
+ ui->widePlot->m_bCurrent=false;
+
+ connect(ui->widePlot, SIGNAL(freezeDecode1(int)),this,
+ SLOT(wideFreezeDecode(int)));
+
+ connect(ui->widePlot, SIGNAL(setFreq1(int,int)),this,
+ SLOT(setFreq2(int,int)));
+
+ m_fMin=3000;
+ ui->fMinSpinBox->setValue(m_fMin);
+
+ //Restore user's settings
+ QString inifile(QApplication::applicationDirPath());
+ inifile += "/wsjtx.ini";
+ QSettings settings(inifile, QSettings::IniFormat);
+
+ settings.beginGroup("WideGraph");
+ ui->widePlot->setPlotZero(settings.value("PlotZero", 0).toInt());
+ ui->widePlot->setPlotGain(settings.value("PlotGain", 0).toInt());
+ ui->zeroSpinBox->setValue(ui->widePlot->getPlotZero());
+ ui->gainSpinBox->setValue(ui->widePlot->getPlotGain());
+ int n = settings.value("FreqSpan",2).toInt();
+ int w = settings.value("PlotWidth",1000).toInt();
+ ui->widePlot->m_w=w;
+ ui->freqSpanSpinBox->setValue(n);
+ ui->widePlot->setNSpan(n);
+ m_waterfallAvg = settings.value("WaterfallAvg",5).toInt();
+ ui->waterfallAvgSpinBox->setValue(m_waterfallAvg);
+ ui->widePlot->m_bCurrent=settings.value("Current",false).toBool();
+ ui->widePlot->m_bCumulative=settings.value("Cumulative",true).toBool();
+ if(ui->widePlot->m_bCurrent) ui->spec2dComboBox->setCurrentIndex(0);
+ if(ui->widePlot->m_bCumulative) ui->spec2dComboBox->setCurrentIndex(1);
+ int nbpp=settings.value("BinsPerPixel",2).toInt();
+ ui->widePlot->setBinsPerPixel(nbpp);
+ m_slope=settings.value("Slope",0.0).toDouble();
+ ui->slopeSpinBox->setValue(m_slope);
+ settings.endGroup();
+}
+
+WideGraph::~WideGraph()
+{
+ saveSettings();
+ delete ui;
+}
+
+void WideGraph::saveSettings()
+{
+ //Save user's settings
+ QString inifile(QApplication::applicationDirPath());
+ inifile += "/wsjtx.ini";
+ QSettings settings(inifile, QSettings::IniFormat);
+
+ settings.beginGroup("WideGraph");
+ settings.setValue("PlotZero",ui->widePlot->m_plotZero);
+ settings.setValue("PlotGain",ui->widePlot->m_plotGain);
+ settings.setValue("PlotWidth",ui->widePlot->plotWidth());
+ settings.setValue("FreqSpan",ui->freqSpanSpinBox->value());
+ settings.setValue("WaterfallAvg",ui->waterfallAvgSpinBox->value());
+ settings.setValue("Current",ui->widePlot->m_bCurrent);
+ settings.setValue("Cumulative",ui->widePlot->m_bCumulative);
+ settings.setValue("BinsPerPixel",ui->widePlot->binsPerPixel());
+ settings.setValue("Slope",m_slope);
+ settings.endGroup();
+}
+
+void WideGraph::dataSink2(float s[], float df3, int ihsym,
+ int ndiskdata)
+{
+ static float splot[NSMAX];
+ static float swide[2048];
+ int nbpp = ui->widePlot->binsPerPixel();
+ static int n=0;
+
+ //Average spectra over specified number, m_waterfallAvg
+ if (n==0) {
+ for (int i=0; i<NSMAX; i++)
+ splot[i]=s[i];
+ } else {
+ for (int i=0; i<NSMAX; i++)
+ splot[i] += s[i];
+ }
+ n++;
+
+ if (n>=m_waterfallAvg) {
+ for (int i=0; i<NSMAX; i++)
+ splot[i] /= n; //Normalize the average
+ n=0;
+
+// int w=ui->widePlot->plotWidth();
+ int i0=-1; //###
+ int i=i0;
+ int jz=5000.0/(nbpp*df3);
+ for (int j=0; j<jz; j++) {
+ float sum=0;
+ for (int k=0; k<nbpp; k++) {
+ i++;
+ sum += splot[i];
+ }
+ swide[j]=sum;
+ }
+
+// Time according to this computer
+ qint64 ms = QDateTime::currentMSecsSinceEpoch() % 86400000;
+ int ntr = (ms/1000) % m_TRperiod;
+ if((ndiskdata && ihsym <= m_waterfallAvg) || (!ndiskdata && ntr<m_ntr0)) {
+ for (int i=0; i<2048; i++) {
+ swide[i] = 1.e30;
+ }
+ }
+ m_ntr0=ntr;
+ ui->widePlot->draw(swide,i0);
+ }
+}
+
+void WideGraph::on_freqSpanSpinBox_valueChanged(int n)
+{
+ ui->widePlot->setBinsPerPixel(n);
+}
+
+void WideGraph::on_waterfallAvgSpinBox_valueChanged(int n)
+{
+ m_waterfallAvg = n;
+}
+
+void WideGraph::on_zeroSpinBox_valueChanged(int value)
+{
+ ui->widePlot->setPlotZero(value);
+}
+
+void WideGraph::on_gainSpinBox_valueChanged(int value)
+{
+ ui->widePlot->setPlotGain(value);
+}
+
+void WideGraph::keyPressEvent(QKeyEvent *e)
+{
+ switch(e->key())
+ {
+ int n;
+ case Qt::Key_F11:
+ n=11;
+ if(e->modifiers() & Qt::ControlModifier) n+=100;
+ emit f11f12(n);
+ break;
+ case Qt::Key_F12:
+ n=12;
+ if(e->modifiers() & Qt::ControlModifier) n+=100;
+ emit f11f12(n);
+ break;
+ default:
+ e->ignore();
+ }
+}
+
+void WideGraph::setRxFreq(int n)
+{
+ m_rxFreq=n;
+ ui->widePlot->setRxFreq(m_rxFreq,true);
+ if(m_lockTxFreq) setTxFreq(m_rxFreq);
+}
+
+int WideGraph::rxFreq()
+{
+ return ui->widePlot->rxFreq();
+}
+
+int WideGraph::nSpan()
+{
+ return ui->widePlot->m_nSpan;
+}
+
+float WideGraph::fSpan()
+{
+ return ui->widePlot->m_fSpan;
+}
+
+int WideGraph::nStartFreq()
+{
+ return ui->widePlot->startFreq();
+}
+
+void WideGraph::wideFreezeDecode(int n)
+{
+ emit freezeDecode2(n);
+}
+
+void WideGraph::setRxRange(int fMin)
+{
+ ui->widePlot->setRxRange(fMin);
+ ui->widePlot->DrawOverlay();
+ ui->widePlot->update();
+}
+
+int WideGraph::getFmin()
+{
+ return m_fMin;
+}
+
+int WideGraph::getFmax()
+{
+ int n=ui->widePlot->getFmax();
+ if(n>5000) n=5000;
+ return n;
+}
+
+void WideGraph::setFmin(int n)
+{
+ m_fMin = n;
+ ui->fMinSpinBox->setValue(n);
+ setRxRange(m_fMin);
+}
+
+void WideGraph::setPalette(QString palette)
+{
+ ui->widePlot->setPalette(palette);
+}
+
+double WideGraph::fGreen()
+{
+ return ui->widePlot->fGreen();
+}
+
+void WideGraph::setPeriod(int ntrperiod, int nsps)
+{
+ m_TRperiod=ntrperiod;
+ m_nsps=nsps;
+ ui->widePlot->setNsps(ntrperiod, nsps);
+}
+
+void WideGraph::setTxFreq(int n)
+{
+ emit setXIT2(n);
+ ui->widePlot->setTxFreq(n);
+}
+
+void WideGraph::setMode(QString mode)
+{
+ m_mode=mode;
+ ui->fMinSpinBox->setEnabled(m_mode=="JT9+JT65");
+ ui->widePlot->setMode(mode);
+ ui->widePlot->DrawOverlay();
+ ui->widePlot->update();
+}
+
+void WideGraph::setModeTx(QString modeTx)
+{
+ m_modeTx=modeTx;
+ ui->widePlot->setModeTx(modeTx);
+ ui->widePlot->DrawOverlay();
+ ui->widePlot->update();
+}
+
+void WideGraph::on_spec2dComboBox_currentIndexChanged(const QString &arg1)
+{
+ ui->widePlot->m_bCurrent=false;
+ ui->widePlot->m_bCumulative=false;
+ if(arg1=="Current") ui->widePlot->m_bCurrent=true;
+ if(arg1=="Cumulative") ui->widePlot->m_bCumulative=true;
+}
+
+void WideGraph::on_fMinSpinBox_valueChanged(int n)
+{
+ m_fMin=n;
+ setRxRange(m_fMin);
+}
+
+void WideGraph::on_slopeSpinBox_valueChanged(double d)
+{
+ m_slope=d;
+}
+
+void WideGraph::setSlope(double d)
+{
+ m_slope=d;
+ ui->slopeSpinBox->setValue(d);
+}
+
+void WideGraph::setLockTxFreq(bool b)
+{
+ m_lockTxFreq=b;
+ ui->widePlot->m_lockTxFreq=b;
+}
+double WideGraph::getSlope()
+{
+ return m_slope;
+}
+
+void WideGraph::setFreq2(int rxFreq, int txFreq)
+{
+ m_rxFreq=rxFreq;
+ m_txFreq=txFreq;
+ emit setFreq3(rxFreq,txFreq);
+}
+
+void WideGraph::setDialFreq(double d)
+{
+ m_dialFreq=d;
+ ui->widePlot->setDialFreq(d);
+}
diff --git a/widegraph.h b/widegraph.h
new file mode 100644
index 0000000..194998d
--- /dev/null
+++ b/widegraph.h
@@ -0,0 +1,89 @@
+#ifndef WIDEGRAPH_H
+#define WIDEGRAPH_H
+#include <QDialog>
+
+namespace Ui {
+ class WideGraph;
+}
+
+class WideGraph : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit WideGraph(QWidget *parent = 0);
+ ~WideGraph();
+
+ void dataSink2(float s[], float df3, int ihsym, int ndiskdata);
+ void setRxFreq(int n);
+ int rxFreq();
+ int nSpan();
+ int nStartFreq();
+ int getFmin();
+ int getFmax();
+ float fSpan();
+ void saveSettings();
+ void setRxRange(int fMin);
+ void setFmin(int n);
+ void setPalette(QString palette);
+ void setFsample(int n);
+ void setPeriod(int ntrperiod, int nsps);
+ void setTxFreq(int n);
+ void setMode(QString mode);
+ void setModeTx(QString modeTx);
+ void setSlope(double d);
+ void setLockTxFreq(bool b);
+ double getSlope();
+ double fGreen();
+
+ qint32 m_rxFreq;
+ qint32 m_txFreq;
+
+signals:
+ void freezeDecode2(int n);
+ void f11f12(int n);
+ void setXIT2(int n);
+ void setFreq3(int rxFreq, int txFreq);
+
+public slots:
+ void wideFreezeDecode(int n);
+ void setFreq2(int rxFreq, int txFreq);
+ void setDialFreq(double d);
+
+protected:
+ virtual void keyPressEvent( QKeyEvent *e );
+
+private slots:
+ void on_waterfallAvgSpinBox_valueChanged(int arg1);
+ void on_freqSpanSpinBox_valueChanged(int arg1);
+ void on_zeroSpinBox_valueChanged(int arg1);
+ void on_gainSpinBox_valueChanged(int arg1);
+ void on_spec2dComboBox_currentIndexChanged(const QString &arg1);
+ void on_fMinSpinBox_valueChanged(int n);
+ void on_slopeSpinBox_valueChanged(double d);
+
+private:
+ double m_slope;
+ double m_dialFreq;
+
+ qint32 m_waterfallAvg;
+ qint32 m_fSample;
+ qint32 m_TRperiod;
+ qint32 m_nsps;
+ qint32 m_ntr0;
+ qint32 m_fMin;
+ qint32 m_fMax;
+
+ bool m_lockTxFreq;
+
+ QString m_mode;
+ QString m_modeTx;
+
+ Ui::WideGraph *ui;
+};
+
+#ifdef WIN32
+extern int set570(double freq_MHz);
+#endif
+
+#endif // WIDEGRAPH_H
diff --git a/widegraph.ui b/widegraph.ui
new file mode 100644
index 0000000..42faba8
--- /dev/null
+++ b/widegraph.ui
@@ -0,0 +1,398 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>WideGraph</class>
+ <widget class="QDialog" name="WideGraph">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>799</width>
+ <height>326</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="CPlotter" name="widePlot">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>400</width>
+ <height>100</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Sunken</enum>
+ </property>
+ <property name="lineWidth">
+ <number>1</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item>
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="freqSpanSpinBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>110</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>38</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Compression factor for frequency scale</string>
+ </property>
+ <property name="suffix">
+ <string/>
+ </property>
+ <property name="prefix">
+ <string>Bins/Pixel </string>
+ </property>
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>1000</number>
+ </property>
+ <property name="singleStep">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>2</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_6">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Minimum</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>8</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="waterfallAvgSpinBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>38</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Number of FFTs averaged (controls waterfall scrolling rate)</string>
+ </property>
+ <property name="prefix">
+ <string>N Avg </string>
+ </property>
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>20</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Minimum</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>8</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="gainSpinBox">
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>38</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Scaling (dB) applied to spectra before plotting</string>
+ </property>
+ <property name="prefix">
+ <string>Gain </string>
+ </property>
+ <property name="minimum">
+ <number>-20</number>
+ </property>
+ <property name="maximum">
+ <number>20</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_7">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Minimum</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>8</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="zeroSpinBox">
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>38</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Constant offset applied to waterfall data</string>
+ </property>
+ <property name="suffix">
+ <string/>
+ </property>
+ <property name="prefix">
+ <string>Zero </string>
+ </property>
+ <property name="minimum">
+ <number>-100</number>
+ </property>
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDoubleSpinBox" name="slopeSpinBox">
+ <property name="minimumSize">
+ <size>
+ <width>60</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="prefix">
+ <string>Slope </string>
+ </property>
+ <property name="decimals">
+ <number>1</number>
+ </property>
+ <property name="minimum">
+ <double>-2.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>2.000000000000000</double>
+ </property>
+ <property name="singleStep">
+ <double>0.100000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Minimum</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>8</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="fMinSpinBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>110</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Decode JT65 below this frequency, JT9 above</string>
+ </property>
+ <property name="suffix">
+ <string> JT9</string>
+ </property>
+ <property name="prefix">
+ <string>JT65 </string>
+ </property>
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>5000</number>
+ </property>
+ <property name="singleStep">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>3000</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_8">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Minimum</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>8</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QComboBox" name="spec2dComboBox">
+ <property name="toolTip">
+ <string>Select data for display curve</string>
+ </property>
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>Current</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Cumulative</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>CPlotter</class>
+ <extends>QFrame</extends>
+ <header>plotter.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/wsjt.ico b/wsjt.ico
new file mode 100644
index 0000000..8a55550
Binary files /dev/null and b/wsjt.ico differ
diff --git a/wsjtx.iss b/wsjtx.iss
new file mode 100644
index 0000000..8d550fa
--- /dev/null
+++ b/wsjtx.iss
@@ -0,0 +1,23 @@
+[Setup]
+AppName=wsjtx
+AppVerName=wsjtx Version 1.1.0 r3488
+AppCopyright=Copyright (C) 2001-2013 by Joe Taylor, K1JT
+DefaultDirName=c:\wsjtx2
+DefaultGroupName=wsjtx2
+
+[Files]
+Source: "c:\Users\joe\wsjt\wsjtx_install\*.exe"; DestDir: "{app}"
+Source: "c:\Users\joe\wsjt\wsjtx_install\*.dll"; DestDir: "{app}";
+Source: "c:\Users\joe\wsjt\wsjtx_install\*.dat"; DestDir: "{app}";
+Source: "c:\Users\joe\wsjt\wsjtx_install\wsjt.ico"; DestDir: "{app}";
+Source: "c:\Users\joe\wsjt\wsjtx_install\CALL3.TXT"; DestDir: "{app}"; Flags: onlyifdoesntexist
+Source: "c:\Users\joe\wsjt\wsjtx\shortcuts.txt"; DestDir: "{app}"
+Source: "c:\Users\joe\wsjt\wsjtx\mouse_commands.txt"; DestDir: "{app}"
+Source: "c:\Users\joe\wsjt\wsjtx\WSJT-X_Users_Guide_v1.1.pdf"; DestDir: "{app}"
+Source: "c:\Users\joe\wsjt\wsjtx_install\save\Samples\130418_1742.wav"; DestDir: "{app}\save\Samples";
+Source: "c:\Users\joe\wsjt\wsjtx_install\save\Samples\130610_2343.wav"; DestDir: "{app}\save\Samples";
+
+[Icons]
+Name: "{group}\wsjtx2"; Filename: "{app}\wsjtx.exe"; WorkingDir: {app}; IconFilename: {app}\wsjt.ico
+Name: "{userdesktop}\wsjtx2"; Filename: "{app}\wsjtx.exe"; WorkingDir: {app}; IconFilename: {app}\wsjt.ico
+
diff --git a/wsjtx.pro b/wsjtx.pro
new file mode 100644
index 0000000..92270a5
--- /dev/null
+++ b/wsjtx.pro
@@ -0,0 +1,81 @@
+#-------------------------------------------------
+#
+# Project created by QtCreator 2011-07-07T08:39:24
+#
+#-------------------------------------------------
+
+QT += core gui network
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+CONFIG += thread
+#CONFIG += console
+
+TARGET = wsjtx
+DESTDIR = ../wsjtx_install
+VERSION = 1.1
+TEMPLATE = app
+DEFINES = QT4
+
+win32 {
+DEFINES += WIN32
+F90 = g95
+g95.output = ${QMAKE_FILE_BASE}.o
+g95.commands = $$F90 -c -O2 -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
+g95.input = F90_SOURCES
+QMAKE_EXTRA_COMPILERS += g95
+}
+
+unix {
+DEFINES += UNIX
+F90 = gfortran
+gfortran.output = ${QMAKE_FILE_BASE}.o
+gfortran.commands = $$F90 -c -O2 -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
+gfortran.input = F90_SOURCES
+QMAKE_EXTRA_COMPILERS += gfortran
+}
+
+SOURCES += main.cpp mainwindow.cpp plotter.cpp about.cpp \
+ soundin.cpp soundout.cpp devsetup.cpp widegraph.cpp \
+ getfile.cpp displaytext.cpp getdev.cpp logqso.cpp \
+ psk_reporter.cpp rigclass.cpp \
+ signalmeter.cpp \
+ meterwidget.cpp
+
+win32 {
+SOURCES += killbyname.cpp
+}
+
+HEADERS += mainwindow.h plotter.h soundin.h soundout.h \
+ about.h devsetup.h widegraph.h getfile.h \
+ commons.h sleep.h displaytext.h logqso.h \
+ psk_reporter.h rigclass.h \
+ signalmeter.h \
+ meterwidget.h
+
+# (Is the following really needed???)
+#DEFINES += __cplusplus
+
+FORMS += mainwindow.ui about.ui devsetup.ui widegraph.ui \
+ logqso.ui
+
+RC_FILE = wsjtx.rc
+
+unix {
+LIBS += ../wsjtx/lib/libjt9.a
+LIBS += -lhamlib
+LIBS += -lportaudio -lgfortran -lfftw3f
+}
+
+win32 {
+INCLUDEPATH += ../../hamlib-1.2.15.3/include
+LIBS += ../../hamlib-1.2.15.3/src/.libs/libhamlib.dll.a
+#LIBS += ../../hamlib-1.2.15.3/lib/gcc/libhamlib.dll.a
+LIBS += ../wsjtx/lib/libjt9.a
+LIBS += ../wsjtx/libfftw3f_win.a
+LIBS += ../wsjtx/libpskreporter.a
+LIBS += ../wsjtx/libHRDInterface001.a
+#LIBS += ../QtSupport/palir-02.dll
+LIBS += /users/joe/wsjt/QtSupport/palir-02.dll
+LIBS += libwsock32
+LIBS += C:/MinGW/lib/libf95.a
+
+}
diff --git a/wsjtx.rc b/wsjtx.rc
new file mode 100644
index 0000000..9a0de81
--- /dev/null
+++ b/wsjtx.rc
@@ -0,0 +1 @@
+IDI_ICON1 ICON DISCARDABLE "wsjt.ico"
diff --git a/wsjtx_changelog.txt b/wsjtx_changelog.txt
new file mode 100644
index 0000000..ea05cf7
--- /dev/null
+++ b/wsjtx_changelog.txt
@@ -0,0 +1,791 @@
+ WSJT-X ChangeLog
+------------------------------------------------------------------
+
+May 30, 2013: Version 1.0, r3323
+--------------------------------
+
+With this release of WSJT-X Version 1.0 we include a few (relatively
+minor) enhancements in response to user requests, as well as some
+program polishing and cleanup. Active program development will
+continue, but new releases will become less frequent.
+
+1. New option on the Setup menu: "Tx freq locked to Rx freq".
+
+2. Double-click on a decoded "73" message now sets Tx5, rather than Tx6.
+
+3. New keyboard shortcuts: Alt+1 through Alt+6 set the next Tx message
+ at the corresponding number.
+
+4. PTT control via Ham Radio Deluxe has been imnplemented and tested.
+
+5. "Tool Tips" are now provided for most on-screen controls.
+
+6. Under Linux and OS X, listings of available audio devices and APIs
+ have been corrected.
+
+7. Tab order among GUI controls has been cleaned up.
+
+8. Updates to the WSJT-X User's Guide.
+
+
+May 22, 2013: v0.99, r3297
+--------------------------
+
+1. CAT control via Ham Radio Deluxe is now available. For setup
+ details see item #5 at the top of page 6 of the updated WSJT-X
+ User's Guide.
+
+2. Submodes JT9-5, JT8-10, JT9-30 have been de-activated. (As far as I
+ know, nobody was using them.) This action makes the program smaller
+ by some 150 MB and able to run effectively on some older computers.
+
+3. Bizarre ordering of COM port numbers on the drop-down list has been
+ corrected, and suitable serial ports added to the list displayed in
+ Linux.
+
+4. Gray bar between decoding periods now contains a dashed line.
+
+5. Corrected a bug that prevented use of Setup | Configuration with
+ no existing wsjtx.ini file.
+
+May 17, 2013: v0.95, r3278
+--------------------------
+1. Double-clicking on a decoded text line in "Band Activity" window
+ now copies the line into the "QSO Frequency" window if it was not
+ already there.
+
+2. Option "Color highlighting in left window" removed from Setup
+ menu. Highlighting is now always done.
+
+3. Positions of "QSO Frequency" and "Band Activity" windows have been
+ swapped.
+
+4. F4 was restored to its previous use; F5 is now used to display
+ Special Mouse Commands
+
+5. Small square between Band selector and Frequency readout was made
+ a control button. Orange indicates one-way CAT control from
+ program to radio, red indicates bi-directional control. Clicking
+ the orange button causes a one-time readout of dial frequency.
+
+6. If Save=None, the last recorded file is deleted on program exit.
+ This prevents unwanted accumulation of files in the Save
+ directory.
+
+7. Status-bar messages were re-arranged in a more logical order.
+
+8. Tx signal report was added to wsjtx_status.txt (for JT-Alert)
+
+9. More informative labels were placed on the "Tab 2" GUI controls.
+
+10. Better default scaling for the "Cumulative" spectrum.
+
+11. New algorithm for identifying JT9 signals to send to decoder,
+ resulting major improvements in decoder speed.
+
+12. Bug fixes:
+ - Incorrect displayed frequencies for JT9-2 signals
+ - Infinitely repeated "Error rigOpen -1" messages
+ - User tries to open CAT control using busy or nonexistent serial port
+
+13. Many updates to the User's Guide
+
+
+May 2, 2013: v0.95, r3251
+-------------------------
+
+1. The "band change" function is executed whenever the Band combobox
+ is activated, even if the selected band has not changed.
+
+2. The program does not set rig mode. That task is left to the user.
+
+3. Time interval for polling rig frequency is now a user parameter on
+ the setup screen. I set mine to 1 second, which works fine with
+ the Kenwood TS-2000. Set it to 0 if you want no polling for
+ frequency (which means unidirectional CAT control from program to
+ radio). Choose something like 10 s for the K3.
+
+4. Much new work on the WSJT-X User's Guide, which is approaching its
+ final form for Version 1.0. Please read it and tell us about
+ anything you find unclear or missing!
+
+These changes address nearly all of the CAT issues found by a few
+users -- those with K3, IC-746, IC-706, in particular.
+
+One additional piece of advice when running WSJT-X in Windows: connect
+and turn on the radio and any interface equipment before starting
+WSJT-X, and exit the program before turning such equipment off.
+
+April 29, 2013: v0.95, r3243
+----------------------------
+
+1. Now has bi-directionsl CAT control using direct calls to hamlib
+ functions. Highlights displayed dial frequency with red background
+ if frequency differs from nominal for the selected band by more
+ than 100 kHz. (Is there a more useful or logical condition to
+ flag?) Small red square between Band selector and Dial Frequency
+ display to indicate that CAT control is active. Mode is set to USB
+ on startup. (Note: CAT control diagnostics are presently rather
+ rudimentary, we're still working on this. Feedback is welcome!)
+
+2. New controls on Setup | Configuration screen:
+ - RTS/DTR OFF -- needed by K2 and maybe other radios
+ - Data / Mic -- select CAT-control PTT type
+ - Test CAT Control -- try settings before returning to main screen
+ - Test PTT -- try settings for toggling PTT On/Off
+
+3. Help menu now provides displays of Keyboard Shortcuts (quick access
+ via F3) and Special Mouse Commands (F4).
+
+4. Option "Setup | Advanced | Allow multiple instances" enables the
+ use of more than one instance of WSJT-X for special applications.
+ (The program must be copied into and run from different
+ directories.)
+
+5. No posts to PSK Reporter if band was changed during the reception
+ period.
+
+6. Improved behavior of Tune button.
+
+7. Improved inter-process communication between WSJT-X and JT-Alert-X.
+
+8. Better interaction between "Report" spinner control and Tx messages.
+
+9. Removed the NB checkbox and slider. (Has anyone found these useful?)
+
+10. New buttons on main window: "Tx=Rx" sets Tx frequency to current
+ Rx frequency; "Rx=Tx" does the opposite.
+
+11. Log QSO confirmation window is now "non-modal": you can keep it
+ open and still access controls on the main window.
+
+12. Tab-order has been rationalized on most screens.
+
+13. Dial frequency and mode written to file ALL.TXT.
+
+14. Double-click on decoded line sets Tx message #3 if message has
+ the form "MyCall Call2 rpt".
+
+15. Bug causing occasional, seemingly unpredictable program crashes
+ has been fixed.
+
+16. The WSJT-X User's Guide is somewhat closer to being complete. User
+ feedback on the Guide will be most welcome. What is unclear? What
+ is missing?
+
+April 17, 2013: v0.9, r3195
+---------------------------
+1. Sorry, the CAT control changes in r3187/3188 were a dismal failure
+in many stations, and they introduced other bugs as well. This revision
+goes back to uni-directional CAT control: the program can set the
+radio's dial frequency and do T/R switching, but that's all. The band
+setting is not reset on program startup.
+
+2. Logic for the Tune button has been corrected.
+
+3. For Linux compile-it-yourself enthusiasts: the interface to
+PSK Reporter is now working undel Linux.
+
+April 16, 2013: v0.9, r3188
+---------------------------
+
+1. CAT control now reads and follows changes in radio's dial
+frequency. Readout gets red highlighting if radio is on wrong band.
+On program restart, band is reset to the last selected band.
+
+2. New "Tune" button generates an unmodulated carrier. Toggle button
+a second time to turn Tx off.
+
+3. Added labels at top of "Tab 2" and enlarged the text entry fields.
+
+4. Fixed the broken logic for "Runaway Tx watchdog".
+
+5. Fixed "Prompt me to log QSO" so that it no longer requires also
+setting "ID after 73".
+
+6. Additional changes of (eventual) interest to Linux users. Code for
+sending spots to PSK Reporter now in place.
+
+April 13, 2013: v0.9, r3166
+---------------------------
+1. Option to send Tx messages (highlighted in yellow) to the QSO window.
+
+2. Prevent starting a transmission more than 24 sec into a Tx period.
+
+3. "Setup | Options" changed to "Setup | Configuration".
+
+4. Type Alt-V to save the most recently completed Rx file.
+
+5. Fixed bug that truncated Rx messages to 16 characters.
+
+6. Internal program changes that should provide better user diagnostics
+when necessary at program startup.
+
+April 11, 2013: v0.9, r3157
+---------------------------
+1. Maximum size of several window areas increased to accommodate system
+fonts set larger than default.
+
+2. New behavior of Erase button: click once to erase the left (QSO) window,
+twice to erase both decoded text windows.
+
+3. Keyboard shortcuts:
+ Alt-D: decode again at QSO frequency (same as clicking the Decode() button)
+ Shift-D: do another full decode in both windows
+ Alt-E: Erase()
+ Ctrl-F: Edit the free text message box
+ Alt-H: Halt Tx()
+ Alt M: Monitor()
+ Alt-N: Enable Tx()
+ Alt-Q: Log QSO()
+ Alt-S: Stop()
+
+4. New Setup options: "Tx disabled after sending 73" and "Runaway Tx
+watchdog".
+
+5. Fixed bug in saving the "report received" for logging purposes.
+
+6. Corrected the logic for "Runaway Tx watchdog".
+
+7. Fixed bug that truncated characters 17 and 18 of decoded messages.
+
+April 10, 2013: v0.9, r3151
+---------------------------
+1. Blank line between decoding periods is now in the right-hand
+text window, where it should be.
+2. Decoding range defined by fMin and fMax is now enforced.
+
+April 9, 2013: v0.9, r3143
+--------------------------
+This minor release restores the decoding speed of earlier revisions
+and corrects a bug that prevented sending CW ID.
+
+April 9, 2013: v0.9, r3142
+--------------------------
+
+This version of WSJT-X has a number of significant changes. Please
+read the following notes carefully. Also -- even if you are already
+familiar with WSJT-X -- be sure to read the updated WSJT-X User's
+Guide at
+http://www.physics.princeton.edu/pulsar/K1JT/WSJT-X_Users_Guide.pdf ,
+especially pages 3 and 4.
+
+Changes since v0.8 r3118 include the following:
+
+1. There are now two scrolling windows for decoded text. The left
+window contains decodes only from close to the designated QSO
+frequency. The right window includes signals over the full decoding
+range.
+
+2. An alternative set of controls is now available for generating and
+selecting Tx messages. Some may find these more convenient to use
+than the Tx1 through Tx6 message boxes.
+
+3. A number of new user options are available on the Setup menu:
+ - Blank line between decoding periods (right window only)
+ - Clear DX Call and DX Grid after logging QSO
+ - Display distances in miles
+ - Runaway Tx watchdog
+ - Background colors for left window
+ - Double-click on decoded message sets Tx Enable
+
+4. New or changed on-screen features
+ - "Tol" replaced by fMin and fMax on waterfall screen (see User's Guide)
+ - Spinner control for signal report
+ - On waterfall scale: green marker for Rx freq, red for Tx. blue
+ for decoding range
+
+5. New behavior
+ - "CQ DX" is now treated properly when decoded line is double-clicked
+ - Message formate for compound callsigns (e.g., PJ4/K1ABC, G4XYZ/P)
+ are now handled correctly. (Some restrictions apply, and will
+ be spelled out in the completed User's Guide.)
+ - Decode button now causes a decode only at the specified Rx frequency.
+ - Click on waterfall spectrum sets Rx freq; double-click also invokes
+ decoder (as though Decode button had been clicked). CTRL-click moves
+ both Rx and Tx freqs.
+ - Amplitude at end of transmission is ramped down to prevent a final
+ key click.
+
+6. The following bugs have been fixed:
+ - Logic error in decoder
+ - Certain non-standard Tx messages could cause a program crash.
+ - Certain (rarely used) messages did not pack/unpack correctly
+
+April 2, 2013: v0.8, r3118
+--------------------------
+1. Improved interface to program JT-Alert, by VK3AMA.
+
+2. The LogQSO confirmation dialog no longer blocks the GUI updating
+ process.
+
+3. A blank line with gray background separates the decoded text lines for
+ each new invocation of the decoder.
+
+4. New suggested default frequencies: 5.357, 18.104, and 24.918 MHz.
+ Be sure to edit these entries on the 'Default Frequencies' tab of the
+ Setup screen. (When you have done this once, the new values will be
+ remembered.)
+
+5. The LogQSO button now does nothing is the 'DX call' entry field is
+ blank.
+
+6. Several minor bugs were fixed.
+
+
+March 27, 2013: v0.8, r3113
+---------------------------
+1. Bug fix: VOX control of T/R switching now works.
+
+2. Potentially useful error messages now appear when CAT control
+ has failed.
+
+3. Added an instruction on the Log QSO confirmation screen.
+
+4. Clear the DXcall and DXgrid entries after logging a QSO.
+
+March 26, 2013: v0.8, r3112
+---------------------------
+
+Edson Pereira, PY2SDR, recently became an active contributor to this
+open-source project. Edson and I have been very busy over the past
+few days! WSJT-X revision 3112 has many changes and new features.
+
+1. The GUI layout has been adjusted and optimized.
+
+2. CAT control is now operational, offering optional control of your
+ radio's dial frequency and T/R status. Go to the Setup | Options
+ window to select the necessary parameters.
+
+3. CW ID has been implemented. You can have your ID sent after a fixed
+ time interval, or automatically when you transmit a "73" or free
+ text message.
+
+4. Default dial frequencies are available for each band on a new tab
+ on the Setup | Options window. Please note: some of these
+ frequencies are probably wrong! You can edit them as needed.
+ (Please let us know if the original values are inconsistent with
+ actual practice on any band.)
+
+5. Several new options appear on the Setup menu. Try them!
+
+6. Azimuth and Distance information is displayed whenever a valid grid
+ locator appears in the "Dx Grid" box.
+
+7. The decoder has again been adjusted for better compromise between
+ sensitivity and decoding time.
+
+8. The User's Guide is out of date, and needs work. We hope to get to
+ that task soon.
+
+9. Very important for some would-be users: WSJT-X now runs properly
+ under Linux. We haven't made a package yet, so for now you must
+ compile your own. If you don't know how, we hope to be set up
+ to make packages before too long.
+
+10. If you know someone who might be interested in contributing to the
+ development of WSJT-X and related projects, please send him/her
+ our way! We're especially looking for someone interested in
+ producing packaged Linux distributions -- for example, *.deb or
+ *.rpm packages, but other programming help is also wanted.
+
+As always: please report bugs, and don't be bashful about sending us
+your feature requests!
+
+March 22, 2013: v0.7, r3071
+---------------------------
+1. Correct a bug that (still) allowed display of previous decodes
+when nothing new was decoded.
+
+2. Add a user confirmation screen activated when you click Log QSO.
+This lets you edit or add information before it is written to the
+ADIF file.
+
+3. Tx message macros and now available. Configure them on the Setup
+window. They are invoked as a pop-up menu by right-clicking on the
+Tx5 message window; then select the desired message by left-clicking
+on the desired message.
+
+March 20, 2013: v0.7, r3063
+---------------------------
+1. Add Frequency to the generated ADIF records.
+
+2. Correct a decoder bug that led to duplication of previous output
+when nothing new was decoded.
+
+March 19, 2013: v0.7, r3061
+---------------------------
+1. Allow Windows COM port numbers up to 99.
+
+2. Replace status files wsjtx_qrg.txt and wsjtx_txcall.txt with
+a single file, wsjtx_status.txt.
+
+3. Combine wsjtx_rx.log and wsjtx_tx.log into a single file ALL.TXT.
+
+4. "Log QSO" now writes a file in ADIF format.
+
+5. Starting to implement popup macros for Tx message #5.
+
+6. Big improvement in decoding speed.
+
+*** More changes to come! Please report any problems, especially
+*** with the ADIF-format log.
+
+March 12, 2013: v0.6, r3046
+---------------------------
+1. Decoded calls can now be uploaded to the PSK Reporter web site.
+Check the box "Enable PSK Reporter" on the Setup screen, and go to
+http://pskreporter.info/pskmap.html to see the spots. Be sure to
+enter your "Dial Frequency (MHz)" at lower right of the Wide Graph
+window. (Rig control features are yet to come...)
+
+2. Added some interfaces to permit use with the program JT-Alert,
+by VK3AMA. Look for this capability in the near future.
+
+March 6, 2013: v0.5, r3038
+--------------------------
+1. Selection of Current/Cumulative/JT9Sync for the 2d spectral display
+changed to a combobox.
+
+2. Double-click on decoded text does not change frequency settings
+if first decoded call is MyCall.
+
+March 1, 2013: v0.5, r3026
+--------------------------
+1. The horizontal scale of 2d spectra (e.g., the "red curve") is now
+correct when the user has selected FFT Bins/Pixel > 1.
+
+2. Double-clicking on a decoded text line now selects the second
+callsign independent of exactly where one has clicked on the line.
+In addition, it sets the selected frequencies (both Tx and Rx) to
+the frequency of the decoded transmission.
+
+December 11, 2012: v0.5, r2791
+------------------------------
+1. Messages of the form "CQ DX K1ABC" are now supported.
+
+November 30, 2012: v0.5, r2788
+------------------------------
+1. A bug was introduced when support for positive signal reports was
+added. It could cause a program crash when certain free-text messages
+were composed for transmission. The bug has been fixed.
+
+2. In the slower JT9 sub-modes, the UTC listed on decoded text lines
+has been changed to the start time of the Rx sequence, rather than the
+time of the final minute.
+
+3. The waterfall's "Auto Zero" button had no function, and has been
+removed.
+
+4. In previous revisions the installer put a number of DLLs into
+the Windows system directory, normally C:\Windows\System32. This
+revision installs the DLLs to the WSJT-X installation directory.
+
+
+November 29, 2012: v0.5, r2786
+------------------------------
+1. In r2783, the companion program jt9.exe (started automatically when
+you start WSJT-X) was a CPU hog for no good reason. This was an
+oversight on my part, and the bug has been corrected.
+
+2. The program should now run correctly if installed in a directory
+whose name contains embedded spaces. (Under Vista and Win7, however,
+it's still not a good idea to install WSJT-X into C:\Program Files,
+because of restricted write permissions there.)
+
+3. In r2783 and earlier, stopping a transmission by toggling to "Auto
+OFF" would terminate Tx audio and release PTT almost simultaneously,
+possibly hot-switching your T/R relay(s). This has been corrected so
+that proper sequencing takes place.
+
+
+November 28, 2012: v0.5, r2783
+------------------------------
+This revision has an unusually large number of changes relative to the
+previous release, v0.4 r2746. These changes include:
+
+1. PTT control via COM ports COM10 and higher is enabled.
+
+2. Improved decoder performance: higher speed as well as better
+chances of success. Moderate amounts of frequency drift are detected
+and compensated. Computed S/N values are more reliable. Time offsets
+from -2.5 to +5 s are now supported, which makes JT9 usable for EME.
+(EME tests on 144 MHz have been successful, and performance on that
+propagation mode appears to be good.)
+
+3. Tx Frequency now tracks the selected QSO Frequency (unless you hold
+down the CTRL key when setting QSO Frequency via mouse-clicks or the
+F11/F12 keys).
+
+4. Decoded text containing "CQ " is highlighted with green background;
+text including "MyCall" is highlighted in red.
+
+5. In previous versions, signal reports were required to be in the
+range -30 to -01 dB. In v0.5 r2782 the range has been extended to -50
+to +49 dB. There is backward compatibility for the range -30 to -01,
+but reports in the range -50 to -31 and 0 to +49 will NOT be decoded
+correctly by previous program versions. It is important to upgrade!
+
+6. Items "Save Synced" and "Save Decoded" are now implemented.
+
+7. UTC Date, JT9 submode, and a parameter related to the decoding
+procedure are now included in file wsjtx_rx.log.
+
+8. Editing of Tx messages (in any of the six Tx message boxes) is
+complete when you hit "Tab" or "Return". The message is then parsed
+and converted to the form in which it will be displayed if decoding is
+successful. Free-text messages are trimmed to 13 characters and
+highlighted with a pink background.
+
+9. The most recent transmitted message is displayed in the right-most
+label on the status bar. This can be useful if you have lost track of
+where you were in a QSO.
+
+10. By default, the program now starts with Monitor ON. An option on
+the Setup menu allows you to select "Monitor OFF at startup".
+
+11. Better scaling is provided for the red "JT9 Sync" curve. Note
+that JT9 signals in the active sub-mode should appear in this plot as
+a bump of width equal to the total signal bandwidth, with a narrow and
+slightly higher bump at the left edge. The narrow bump is the
+frequency of the Sync tone, which is defined as the nominal frequency
+of the JT9 signal.
+
+12. Basic QSO information is now written to file wsjt.log when you
+click the "Log QSO" button.
+
+13. The WSJT-X User's Guide has been updated.
+
+14. Other known bugs have been fixed. There will probably be new
+ones! When you find one, or if you know of any old ones that have NOT
+been fixed, please send me email.
+
+Summary of Present Status
+----------------------------------------------------------------------
+I believe that WSJT-X is now a stable and very usable program. Many
+thousands of QSOs have been made with JT9-1, mostly at HF -- I have
+made nearly 100, myself. Also a number of QSOs have also been
+completed at MF, and successful tests have been made on 2m EME, etc.
+A number of QSOs have also been made with JT9-2.
+
+As far as I know the slower modes (JT9-5, JT9-10, and JT9-30) also
+work correctly. (Certainly they do in my laboratory test setup.)
+Most people will find these modes too slow for "everyday" use, and
+they require high frequency stability. It remains to be seen whether
+they will be widely used.
+
+An alternative approach to obtaining improved sensitivity would be to
+give the decoder an ability to average over several successive
+transmissions. For example, the average of five JT9-1 transmissions
+could reach a decoding threshold around -32 dB, only 2 dB worse than a
+single JT9-5 transmission. Because of QSB, the shorter transmissions
+may actually succeed in less total time. Stability requirements would
+be those of JT9-1, much less stringent than those of JT9-5.
+
+Program development is not finished, by any means. I will be grateful
+for your feedback on performance issues, as well as your "wish-list"
+of features to be added. As always, example recordings of files that
+you think should have decoded, but did not, will be much appreciated.
+
+November 16, 2012: v0.4, r2746
+------------------------------
+
+Changes from v0.4 r2731 include the following:
+
+1. Valid signal reports are now generated by double-clicking on a
+callsign in the decoded text window.
+
+2. Consecutive spaces in a Tx message are now collapsed into a single
+space.
+
+3. Decoding speed is much improved, especially when strong (possibly
+non-JT9) signals are present and "Tol" is set to a relatively large
+value.
+
+4. Scaling of the "JT9 Sync" plot (red curve) is more reasonable.
+
+5. Layout of widgets on the main window has been improved.
+
+6. Several minor bug fixes.
+
+November 14, 2012: v0.4, r2731
+------------------------------
+
+A number of known bugs have been fixed, and the JT9 decoder is
+significantly improved. Among other improvements, the program is now
+much less fussy about timing issues.
+
+November 6, 2012: v0.3, r2717
+------------------------------
+
+Changes from r2713 include the following:
+
+1. A bug in the decoder that led to erratic behavior (failed decodes)
+under certain conditions has been corrected. Decoding is now much
+more reliable.
+
+2. A valid algorithm is now used to calculate S/N values for received
+JT9 signals.
+
+3. The header format of recorded *.wav files has been corrected.
+These files will now play correctly in Windows programs that expect
+the standard header.
+
+November 6, 2012: v0.2, r2713
+------------------------------
+
+Changes from r2711 include the following:
+
+1. Updates to the Quick-Start User's Guide,
+http://www.physics.princeton.edu/pulsar/K1JT/WSJT-X_Users_Guide.pdf
+
+2. Double-click on waterfall now sets Tol to a reduced
+(mode-dependent) value.
+
+3. Tol is saved and restored on program restart.
+
+4. A "digital gain" slider was added next to the green-bar audio level
+indicator. With the slider at mid-range, the scale reads correctly in
+dB above the least significant bit of 16-bit audio data.
+
+5. There is now a test that rejects at least one type of data that is
+sufficiently corrupt to cause Eddie's best friend, the message
+"15P6715P67WCV".
+
+6. Several minor tweaks to improve decoder performance.
+
+7. The program now starts with Monitor OFF. You must click Monitor to
+start accepting audio. For some types of testing, this may be an
+advantage. This startup condition may be changed again, in the
+future.
+
+October 31, 2012: v0.2, r2711
+-----------------------------
+
+Three significant changes since r2706:
+
+1. Three options are now provided on the "Decode" menu, controlling
+the "depth" of the decoding process. For most purposes I suggest you
+should use "Normal", but feel free to experiment with the others.
+
+2. Decoding of multiple signals in one Rx interval has been improved.
+
+3. Handling of strong signals has been improved.
+
+October 309, 2012: v0.2, r2706
+------------------------------
+
+Changes since r2702 include the following:
+
+1. The problem with "ghost" signals is fixed.
+
+2. A problem causing very long decode times under certain
+circumstances has been fixed. Please note: decode times on any recent
+PC should no more than a few seconds!
+
+3. I have re-directed the program's fatal error messages so they will
+be sent to the command-prompt window from which you started the
+program. Please send me full reports on any such messages you observe,
+preferably with details on how to reproduce the problem.
+
+#########################################################################
+
+Some additional information ...
+
+1. Yes, the JT9 modes require good stability in all system
+oscillators. The present JT9 bdecoder does not attempt to track
+frequency drifts. Such capability will be added, however. We have
+been using digital modes for EME for nearly ten years now, at 144 MHz
+and higher. There are more than 1000 WSJT users on EME, using all
+kinds of rige. We have learned how to deal with reasonable rates of
+drift. Surely if we can do these things at VHF, we can do them much
+more easily at MF and LF.
+
+2. If you're sure that you have seen degraded JT9 performance because
+of frequency stability issues, don't just complain on the LF
+reflector. Document your case and send me an example file with a
+drifting JT9 signal. Making WSJT-X and JT9 better is partly YOUR
+responsibility!
+
+3. In other ways as well, test files are needed. I can make many
+tests myself, but I can't foresee all the problems others will have.
+That's what the "Save All" function is for! In these early tests,
+always run with "Save All" checked, just in case you will want to
+refer back to something that happened. You may want to send me the
+file in question. You can always clean out your "Save" directory by
+using "File | Delete all *.wav files in SaveDir". I need good
+examples of signals that fail to decode for any unknown reason. Also
+some good examples of atmospheric or other impulsive noise, for
+testing the noise blanker.
+
+4. I have added a page of "Hints for New Users" to the online WSJT-X
+User's Guide,
+http://www.physics.princeton.edu/pulsar/K1JT/WSJT-X_Users_Guide.pdf .
+Please read it! ... and let me know if you find other operational
+details of WSJT-X that need explanation. This will likely be
+especially true for those not already familiar with older versions of
+WSJT.
+
+5. An operational suggestion: In many ways the different JT9 submodes
+are treated as distinct modes. If you receive a JT9-x signal in a
+different submode than the one you have selected, you won't decode
+it. For this reason, if JT9 is to become popular we'll probably need
+to choose one or two of the submodes for general use, and perhaps
+assign a narrow slice of the band to each one. Note that "message
+averaging" in the Rx software can make two or three JT9-2
+transmissions as good as one JT9-5 transmission, with the advantage
+that you will copy sooner if signals are better than required for
+JT9-5. Message averaging is not yet present in the JT9 decoder... but
+in future it can be. Again, we have dealt with such issues very
+effectively on EME -- and can do so at MF/LF, for sure.
+
+6. On the topic of CW, Beacons, WSPR, JT9, etc. I really don't
+understand what all the fuss is about. Surely there is room for
+everybody? Maybe I'm just too new here to understand? (Mal, is this
+mostly just a matter of "Mal being Mal"???)
+
+On the HF bands, the WSPR sub-band is just 200 Hz wide. If we did the
+same on 630 m, the WSPR sub-band would take up less than 3% of the 7
+kHz band. If that's too much, we could cut it in half, or even less,
+and still have enough WSPR space. Moreover, a "slow WSPR", if
+warranted, would require even less bandwidth. Similar comments apply
+to JT9. The bandwidth of JT9 signals is significantly less than that
+of CW, for comparable information rates. There should be enough
+spectrum for both, even in our narrow MF and LF bands.
+
+7. As for performance comparisons between JT9 and WSPR: WSPR is a
+mature program, and its decoder has been optimized and tweaked over a
+period approaching five years. You are playing with JT9 in infancy.
+With help (as opposed to simple complaints) from users, it will
+improve rapidly.
+
+October 29, 2012: v0.2, r2702
+-----------------------------
+Changes since version 0.1, r2696 include the following:
+
+1. Sample rate for audio output has been changed from 12000 to 48000
+Hz. Tx audio may now be generated at any frequency from 500 to 20000
+Hz.
+
+2. The Decoder now tries to decode all synchronizable signals in the
+"green zone", that is, within "Tol" Hz of the selected QSO
+frequency. (Before, by default it decoded only the signal producing
+the highest "sync" value. Other signals could be decoded by manually
+setting the QSO frequency and reducing Tol as needed.)
+
+3. The user's selected QSO Frequency is now saved and restored on
+program restart.
+
+4. The problem with re-initialization after changing sub-modes has
+been fixed.
+
+5. The problem (for some users) of not releasing PTT after end of a
+transmission has been fixed.
+
+6. The program now writes a log of all decodes to a file wsjtx_rx.log
+in the wsjtx directory.
+
+
+October 25, 2012: v0.1, r2695
+-----------------------------
+Initial version of WSJT-X (experimental WSJT) released for testing.
diff --git a/wsjtx_opti.iss b/wsjtx_opti.iss
new file mode 100644
index 0000000..1fbfedc
--- /dev/null
+++ b/wsjtx_opti.iss
@@ -0,0 +1,23 @@
+[Setup]
+AppName=wsjtx
+AppVerName=wsjtx Version 1.1.0 r3478
+AppCopyright=Copyright (C) 2001-2013 by Joe Taylor, K1JT
+DefaultDirName=c:\wsjtx2
+DefaultGroupName=wsjtx2
+
+[Files]
+Source: "c:\Users\joe\wsjt\wsjtx_install\*.exe"; DestDir: "{app}"
+Source: "c:\Users\joe\wsjt\wsjtx_install\*.dll"; DestDir: "{app}";
+Source: "c:\Users\joe\wsjt\wsjtx_install\*.dat"; DestDir: "{app}";
+Source: "c:\Users\joe\wsjt\wsjtx_install\wsjt.ico"; DestDir: "{app}";
+Source: "c:\Users\joe\wsjt\wsjtx_install\CALL3.TXT"; DestDir: "{app}"; Flags: onlyifdoesntexist
+Source: "c:\Users\joe\wsjt\wsjtx\shortcuts.txt"; DestDir: "{app}"
+Source: "c:\Users\joe\wsjt\wsjtx\mouse_commands.txt"; DestDir: "{app}"
+Source: "c:\Users\joe\wsjt\wsjtx\WSJT-X_Users_Guide_v1.1.pdf"; DestDir: "{app}"
+Source: "c:\Users\joe\wsjt\wsjtx_install\save\Samples\130418_1742.wav"; DestDir: "{app}\save\Samples";
+Source: "c:\Users\joe\wsjt\wsjtx_install\save\Samples\130610_2343.wav"; DestDir: "{app}\save\Samples";
+
+[Icons]
+Name: "{group}\wsjtx2"; Filename: "{app}\wsjtx.exe"; WorkingDir: {app}; IconFilename: {app}\wsjt.ico
+Name: "{userdesktop}\wsjtx2"; Filename: "{app}\wsjtx.exe"; WorkingDir: {app}; IconFilename: {app}\wsjt.ico
+
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-hamradio/wsjtx.git
More information about the pkg-hamradio-commits
mailing list