1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
|
#include "soundin.h"
#include <math.h>
#ifdef Q_OS_WIN32
#include <windows.h>
#else
#include <sys/socket.h>
#endif
#define NFFT 32768
#define FRAMES_PER_BUFFER 1024
extern "C"
{
struct
{
double d8[60*96000]; //This is "common/datcom/..." in fortran
float ss[400*NFFT];
float savg[NFFT]; //Avg spectra at 0,45,90,135 deg pol
double fcenter; //Center freq from Linrad (MHz)
int nutc; //UTC as integer, HHMM
float fselected; //Selected frequency for nagain decodes
int mousedf; //User-selected DF
int mousefqso; //User-selected QSO freq (kHz)
int nagain; //1 ==> decode only at fQSO +/- Tol
int ndepth; //How much hinted decoding to do?
int ndiskdat; //1 ==> data read from *.iq file
int ntx60; //Number of seconds transmitted in Q65-60x
int newdat; //1 ==> new data, must do long FFT
int nfa; //Low decode limit (kHz)
int nfb; //High decode limit (kHz)
int nfcal; //Frequency correction, for calibration (Hz)
int nfshift; //Shift of displayed center freq (kHz)
int ntx30a; //Number of seconds transmitted in first half minute , Q65-30x
int ntx30b; //Number of seconds transmitted in second half minute, Q65-30x
int ntol; //+/- decoding range around fQSO (Hz)
int junk5; //
int junk4; //
int nfsample; //Input sample rate
int junk3; //
int nBaseSubmode; //Base submode for Q65-60x (aka m_modeQ65)
int ndop00; //EME Self Doppler
int nsave; //Number of s3(64,63) spectra saved
int max_drift; //Maximum Q65 drift: units symbol_rate/TxT
int offset; //Offset in Hz
int nhsym; //Number of available JT65 half-symbols
char mycall[12];
char mygrid[6];
char hiscall[12];
char hisgrid[6];
char datetime[20];
int junk1; //Used to test extent of copy to shared memory
int junk2;
bool bAlso30; //Process for 30-second submode as well as 60-second
} datcom_;
}
namespace
{
struct COMWrapper
{
explicit COMWrapper ()
{
#ifdef Q_OS_WIN32
// required because Qt only does this for GUI thread
CoInitializeEx (nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
#endif
}
~COMWrapper ()
{
#ifdef Q_OS_WIN32
CoUninitialize ();
#endif
}
};
}
void SoundInThread::run() //SoundInThread::run()
{
quitExecution = false;
if (m_net) {
inputUDP();
return;
}
}
void SoundInThread::setScale(qint32 n)
{
m_dB=n;
}
void SoundInThread::setPort(int n) //setPort()
{
if (isRunning()) return;
this->m_udpPort=n;
}
void SoundInThread::setRate(double rate) //setRate()
{
if (isRunning()) return;
this->m_rate = rate;
}
void SoundInThread::setBufSize(unsigned n) //setBufSize()
{
if (isRunning()) return;
this->bufSize = n;
}
void SoundInThread::setFadd(double x)
{
m_fAdd=x;
}
void SoundInThread::quit() //quit()
{
quitExecution = true;
}
void SoundInThread::setNetwork(bool b) //setNetwork()
{
m_net = b;
}
void SoundInThread::setMonitoring(bool b) //setMonitoring()
{
m_monitoring = b;
}
void SoundInThread::setNrx(int n) //setNrx()
{
m_nrx = n;
}
int SoundInThread::nrx()
{
return m_nrx;
}
int SoundInThread::mhsym()
{
return m_hsym;
}
void SoundInThread::setPeriod(int n)
{
m_TRperiod=n;
}
//--------------------------------------------------------------- inputUDP()
void SoundInThread::inputUDP()
{
udpSocket = new QUdpSocket();
if(!udpSocket->bind(m_udpPort,QUdpSocket::ShareAddress) )
{
emit error(tr("UDP Socket bind failed."));
return;
}
// Set this socket's total buffer space for received UDP packets
udpSocket->setSocketOption (QUdpSocket::ReceiveBufferSizeSocketOption, 141600);
bool qe = quitExecution;
struct linradBuffer {
double cfreq;
int msec;
float userfreq;
int iptr;
quint16 iblk;
qint8 nrx;
char iusb;
double d8[174];
} b;
int ntr0=99;
int k=0;
int nsec;
int ntr;
int nhsym0=0;
int iz=174;
// Main loop for input of UDP packets over the network:
while (!qe) {
qe = quitExecution;
if (qe) break;
if (!udpSocket->hasPendingDatagrams()) {
// msleep(2); // Sleep if no packet available
QObject().thread()->usleep(2000);
} else {
int nBytesRead = udpSocket->readDatagram((char *)&b,1416);
if (nBytesRead != 1416) qDebug() << "UDP Read Error:" << nBytesRead;
qint64 ms = QDateTime::currentMSecsSinceEpoch() % 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_TRperiod!=m_TRperiod0) {
k=0;
nhsym0=0;
m_TRperiod0=m_TRperiod;
}
ntr0=ntr;
if(m_monitoring) {
m_nrx=b.nrx;
if(m_nrx == +1) iz=348; //One RF channel, i*2 data
if(m_nrx == -1 or m_nrx == +2) iz=174; //One Rf channel, r*4 data
// or 2 RF channels, i*2 data
if(m_nrx == -2) iz=87; // Two RF channels, r*4 data
// If buffer will not overflow, move data into datcom_
if ((k+iz) <= 60*96000) {
int nsam=-1;
recvpkt_(&nsam, &b.iblk, &b.nrx, &k, b.d8, b.d8, &m_dB);
datcom_.fcenter=b.cfreq + m_fAdd;
}
m_hsym=(k-2048)/14400; //14400 = 0.15 * 96000
if(m_hsym != nhsym0) {
if(!m_dataSinkBusy) {
m_dataSinkBusy=true;
emit readyForFFT(k); //Signal to compute new FFTs
}
nhsym0=m_hsym;
}
}
}
}
delete udpSocket;
}
|