| 
									
										
										
										
											2022-12-04 10:17:02 -05:00
										 |  |  | #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 | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2022-12-12 18:52:45 -05:00
										 |  |  |     double d8[60*96000];              //This is "common/datcom/..." in fortran
 | 
					
						
							| 
									
										
										
										
											2023-12-07 11:43:25 -05:00
										 |  |  |     float ss[400*NFFT]; | 
					
						
							| 
									
										
										
										
											2024-01-01 09:57:55 -05:00
										 |  |  |     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
 | 
					
						
							| 
									
										
										
										
											2023-01-16 17:45:14 -05:00
										 |  |  |     float fselected;                  //Selected frequency for nagain decodes
 | 
					
						
							| 
									
										
										
										
											2022-12-04 10:17:02 -05:00
										 |  |  |     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?
 | 
					
						
							| 
									
										
										
										
											2024-01-01 09:57:55 -05:00
										 |  |  |     int ndiskdat;                     //1 ==> data read from *.iq file
 | 
					
						
							|  |  |  |     int ntx60;                        //Number of seconds transmitted in Q65-60x
 | 
					
						
							| 
									
										
										
										
											2022-12-04 10:17:02 -05:00
										 |  |  |     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)
 | 
					
						
							| 
									
										
										
										
											2024-01-01 09:57:55 -05:00
										 |  |  |     int ntx30a;                       //Number of seconds transmitted in first half minute , Q65-30x
 | 
					
						
							|  |  |  |     int ntx30b;                       //Number of seconds transmitted in second half minute, Q65-30x
 | 
					
						
							| 
									
										
										
										
											2022-12-04 10:17:02 -05:00
										 |  |  |     int ntol;                         //+/- decoding range around fQSO (Hz)
 | 
					
						
							| 
									
										
										
										
											2024-01-03 13:51:37 -05:00
										 |  |  |     int junk5;                        //
 | 
					
						
							|  |  |  |     int junk4;                        //
 | 
					
						
							| 
									
										
										
										
											2022-12-04 10:17:02 -05:00
										 |  |  |     int nfsample;                     //Input sample rate
 | 
					
						
							| 
									
										
										
										
											2024-01-03 13:51:37 -05:00
										 |  |  |     int junk3;                        //
 | 
					
						
							| 
									
										
										
										
											2024-01-01 09:57:55 -05:00
										 |  |  |     int nBaseSubmode;                 //Base submode for Q65-60x (aka m_modeQ65)
 | 
					
						
							|  |  |  |     int ndop00;                       //EME Self Doppler
 | 
					
						
							| 
									
										
										
										
											2022-12-04 10:17:02 -05:00
										 |  |  |     int nsave;                        //Number of s3(64,63) spectra saved
 | 
					
						
							| 
									
										
										
										
											2024-01-01 09:57:55 -05:00
										 |  |  |     int max_drift;                    //Maximum Q65 drift: units symbol_rate/TxT
 | 
					
						
							|  |  |  |     int offset;                       //Offset in Hz
 | 
					
						
							|  |  |  |     int nhsym;                        //Number of available JT65 half-symbols
 | 
					
						
							| 
									
										
										
										
											2022-12-04 10:17:02 -05:00
										 |  |  |     char mycall[12]; | 
					
						
							|  |  |  |     char mygrid[6]; | 
					
						
							|  |  |  |     char hiscall[12]; | 
					
						
							|  |  |  |     char hisgrid[6]; | 
					
						
							|  |  |  |     char datetime[20]; | 
					
						
							| 
									
										
										
										
											2024-01-01 09:57:55 -05:00
										 |  |  |     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
 | 
					
						
							| 
									
										
										
										
											2022-12-04 10:17:02 -05:00
										 |  |  |   } 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()) { | 
					
						
							| 
									
										
										
										
											2022-12-06 10:21:52 -05:00
										 |  |  | //      msleep(2);                  // Sleep if no packet available
 | 
					
						
							|  |  |  |       QObject().thread()->usleep(2000); | 
					
						
							| 
									
										
										
										
											2022-12-04 10:17:02 -05:00
										 |  |  |     } 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; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2022-12-06 10:21:52 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-04 10:17:02 -05:00
										 |  |  |       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; | 
					
						
							| 
									
										
										
										
											2023-12-08 14:06:15 -05:00
										 |  |  |           recvpkt_(&nsam, &b.iblk, &b.nrx, &k, b.d8, b.d8, &m_dB); | 
					
						
							| 
									
										
										
										
											2022-12-10 18:13:36 -05:00
										 |  |  |           datcom_.fcenter=b.cfreq + m_fAdd; | 
					
						
							| 
									
										
										
										
											2022-12-04 10:17:02 -05:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-12-07 11:20:21 -05:00
										 |  |  |         m_hsym=(k-2048)/14400;           //14400 = 0.15 * 96000
 | 
					
						
							| 
									
										
										
										
											2022-12-04 10:17:02 -05:00
										 |  |  |         if(m_hsym != nhsym0) { | 
					
						
							| 
									
										
										
										
											2023-05-13 13:43:04 -04:00
										 |  |  |           if(!m_dataSinkBusy) { | 
					
						
							| 
									
										
										
										
											2022-12-04 10:17:02 -05:00
										 |  |  |             m_dataSinkBusy=true; | 
					
						
							|  |  |  |             emit readyForFFT(k);         //Signal to compute new FFTs
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           nhsym0=m_hsym; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   delete udpSocket; | 
					
						
							|  |  |  | } |