diff --git a/commons.h b/commons.h index 357f116f1..1745c9f5b 100644 --- a/commons.h +++ b/commons.h @@ -12,10 +12,10 @@ extern struct { 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 nfqso; //User-selected QSO freq (kHz) int nagain; //1 ==> decode only at fQSO +/- Tol int newdat; //1 ==> new data, must do long FFT - int nfa; //Low decode limit (kHz) + int npts8; //npts for c0() array int nfb; //High decode limit (kHz) int ntol; //+/- decoding range around fQSO (Hz) int kin; diff --git a/jt9.txt b/jt9.txt index a2bea4ab1..ef232e9ab 100644 --- a/jt9.txt +++ b/jt9.txt @@ -1,7 +1,7 @@ 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 convolutional code with constraint length K=32, rate -r=1/2, and a zero tail, leading to an encoded message length of +(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 @@ -10,12 +10,14 @@ used for synchronization, so a transmission requires a total of 207/3 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. +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. +channel. Numbers following "JT9-" in the sub-mode names specify the +T/R period in minutes. -------------------------------------------------------------------------- Mode nsps nsps2 df tsym BW S/N* Tdec Tfree Factors @@ -46,12 +48,12 @@ Receiving 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. + 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, and sync tone should be + 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. diff --git a/lib/decoder.f90 b/lib/decoder.f90 index 3a628a536..167a8d00a 100644 --- a/lib/decoder.f90 +++ b/lib/decoder.f90 @@ -14,7 +14,7 @@ subroutine decoder(ntrSeconds,c0) integer*2 id2 complex c0(NDMAX) common/jt9com/ss(184,NSMAX),savg(NSMAX),id2(NMAX),nutc,ndiskdat, & - ntr,mousefqso,nagain,newdat,nfa,nfb,ntol,kin + ntr,nfqso,nagain,newdat,npts8,nfb,ntol,kin ntrMinutes=ntrSeconds/60 newdat=1 @@ -35,24 +35,22 @@ subroutine decoder(ntrSeconds,c0) ! Now do the decoding nutc=0 + kstep=nsps/2 tstep=kstep/12000.0 - ntol=500 - nfqso=1500 - ! Get sync, approx freq call sync9(ss,tstep,df3,ntol,nfqso,sync,fpk,red) - npts8=170880 !### TEST ONLY ### + print*,'A',nfqso,ntol,fpk call spec9(c0,npts8,nsps,fpk,xdt,i1SoftSymbols) call decode9(i1SoftSymbols,msg) - open(73,file='decoded.txt',status='unknown') - rewind 73 + open(13,file='decoded.txt',status='unknown') + rewind 13 ! write(*,1010) nutc,sync,xdt,1000.0+fpk,msg - write(73,1010) nutc,sync,xdt,1000.0+fpk,msg + write(13,1010) nutc,sync,xdt,1000.0+fpk,msg 1010 format(i4.4,3f7.1,2x,a22) - call flush(73) - close(73) + call flush(13) + close(13) return end subroutine decoder diff --git a/lib/spec9.f90 b/lib/spec9.f90 index 04c76ebe6..d4968ce86 100644 --- a/lib/spec9.f90 +++ b/lib/spec9.f90 @@ -2,6 +2,7 @@ subroutine spec9(c0,npts8,nsps,fpk,xdt,i1SoftSymbols) parameter (MAXFFT=31500) complex c0(0:npts8-1) + complex c1(0:2700000) real ssym(0:7,69) complex c(0:MAXFFT-1) integer*1 i1SoftSymbolsScrambled(207) @@ -27,17 +28,17 @@ subroutine spec9(c0,npts8,nsps,fpk,xdt,i1SoftSymbols) phi=phi+dphi if(phi.gt.twopi) phi=phi-twopi if(phi.lt.-twopi) phi=phi+twopi - c0(i)=cmplx(aimag(c0(i)),real(c0(i)))*cmplx(cos(phi),sin(phi)) + c1(i)=cmplx(aimag(c0(i)),real(c0(i)))*cmplx(cos(phi),sin(phi)) enddo nsps8=nsps/8 foffset=fpk istart=1520 - call peakdf9(c0,npts8,nsps8,istart,foffset,idf) + call peakdf9(c1,npts8,nsps8,istart,foffset,idf) fpk=fpk + idf*0.1*1500.0/nsps8 foffset=foffset + idf*0.1*1500.0/nsps8 - call peakdt9(c0,npts8,nsps8,istart,foffset,idt) + call peakdt9(c1,npts8,nsps8,istart,foffset,idt) istart=istart + 0.0625*nsps8*idt xdt=istart/1500.0 - 1.0 ! write(*,3002) 0.0625*nsps8*idt/1500.0,idf*0.1*1500.0/nsps8 @@ -57,7 +58,7 @@ subroutine spec9(c0,npts8,nsps,fpk,xdt,i1SoftSymbols) k=k+1 ia=(j-1)*nsps8 + istart ib=ia+nsps8-1 - c(0:nfft-1)=c0(ia:ib) + c(0:nfft-1)=c1(ia:ib) phi=0. do i=0,nfft-1 diff --git a/lib/symspec.f90 b/lib/symspec.f90 index be50d5886..4a04cec02 100644 --- a/lib/symspec.f90 +++ b/lib/symspec.f90 @@ -37,7 +37,7 @@ subroutine symspec(k,ntrperiod,nsps,nb,nbslider,pxdb,s,red, & data rms/999.0/,k0/99999999/,ntrperiod0/0/,nfft3z/0/ save - if(ntrperiod.eq.1) nfft3=1024 + if(ntrperiod.eq.1) nfft3=2048 if(ntrperiod.eq.2) nfft3=2048 if(ntrperiod.eq.5) nfft3=6144 if(ntrperiod.eq.10) nfft3=12288 diff --git a/mainwindow.cpp b/mainwindow.cpp index b1665335f..cf3448d41 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -373,9 +373,9 @@ void MainWindow::dataSink(int k) ntr0=ntr; n=0; } - if(ihsym == m_hsymStop) { - jt9com_.newdat=1; - jt9com_.nagain=0; + // This is a bit strange. Why do we need the "-3" ?? + if(ihsym == m_hsymStop-3) { + jt9com_.npts8=(ihsym*m_nsps)/16; QDateTime t = QDateTime::currentDateTimeUtc(); m_dateTime=t.toString("yyyy-MMM-dd hh:mm"); decode(); //Start the decoder @@ -509,19 +509,17 @@ void MainWindow::keyPressEvent( QKeyEvent *e ) //keyPressEvent case Qt::Key_F11: if(e->modifiers() & Qt::ShiftModifier) { } else { - int n0=g_pWideGraph->DF(); - int n=(n0 + 10000) % 5; - if(n==0) n=5; - g_pWideGraph->setDF(n0-n); + int n=g_pWideGraph->QSOfreq(); + n--; + g_pWideGraph->setQSOfreq(n); } break; case Qt::Key_F12: if(e->modifiers() & Qt::ShiftModifier) { } else { - int n0=g_pWideGraph->DF(); - int n=(n0 + 10000) % 5; - if(n==0) n=5; - g_pWideGraph->setDF(n0+n); + int n=g_pWideGraph->QSOfreq(); + n++; + g_pWideGraph->setQSOfreq(n); } break; case Qt::Key_G: @@ -726,10 +724,12 @@ void MainWindow::on_actionDecode_remaining_files_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 - int k=(n+1)*kstep; + k=(n+1)*kstep; + jt9com_.npts8=k/8; dataSink(k); if(n%10 == 1 or n == m_hsymStop) qApp->processEvents(); //Keep GUI responsive } @@ -831,12 +831,16 @@ void MainWindow::on_DecodeButton_clicked() //Decode request void MainWindow::freezeDecode(int n) //freezeDecode() { - + decode(); } void MainWindow::decode() //decode() { - m_len1=80; + jt9com_.newdat=1; + jt9com_.nagain=0; + jt9com_.nfqso=g_pWideGraph->QSOfreq(); + m_tol=g_pWideGraph->Tol(); + jt9com_.ntol=m_tol; *future3 = QtConcurrent::run(decoder_, &m_TRperiod, &c0[0]); watcher3->setFuture(*future3); } diff --git a/mainwindow.h b/mainwindow.h index 8a42a2ea0..880d350ff 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -136,6 +136,7 @@ private: qint32 m_nsps; qint32 m_hsymStop; qint32 m_len1; + qint32 m_fQSO; bool m_monitoring; bool m_transmitting; diff --git a/mainwindow.ui b/mainwindow.ui index eeee7578f..4359b2f37 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -66,7 +66,7 @@ - UTC T dB DF + UTC T dB Freq diff --git a/plotter.cpp b/plotter.cpp index 003529114..c7ebe6440 100644 --- a/plotter.cpp +++ b/plotter.cpp @@ -27,7 +27,7 @@ CPlotter::CPlotter(QWidget *parent) : //CPlotter Constructor m_ScalePixmap = QPixmap(0,0); m_OverlayPixmap = QPixmap(0,0); m_Size = QSize(0,0); - m_fQSO = 1050; + m_fQSO = 1020; m_line = 0; m_fSample = 12000; m_nsps=6912; @@ -296,7 +296,7 @@ void CPlotter::DrawOverlay() //DrawOverlay() } } - QPen pen0(Qt::green, 3); //Mark Cal Freq with green tick + QPen pen0(Qt::green, 3); //Mark QSO Freq with green tick painter0.setPen(pen0); x = m_xClick; painter0.drawLine(x,15,x,30); @@ -407,6 +407,7 @@ void CPlotter::setFQSO(int x, bool bf) //setFQSO() { if(bf) { m_fQSO=x; // x is freq in kHz + m_xClick=XfromFreq(m_fQSO); } else { if(x<0) x=0; // x is pixel number if(x>m_Size.width()) x=m_Size.width(); @@ -564,7 +565,7 @@ double CPlotter::fGreen() void CPlotter::setNsps(int n) //setNSpan() { m_nsps=n; - m_fftBinWidth=1500.0/1024.0; + 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; diff --git a/soundin.cpp b/soundin.cpp index 76bfc3915..ca6209c09 100644 --- a/soundin.cpp +++ b/soundin.cpp @@ -16,7 +16,7 @@ extern struct { int mousefqso; //User-selected QSO freq (kHz) int nagain; //1 ==> decode only at fQSO +/- Tol int newdat; //1 ==> new data, must do long FFT - int nfa; //Low decode limit (kHz) + int npts8; //npts in c0() array int nfb; //High decode limit (kHz) int ntol; //+/- decoding range around fQSO (Hz) int kin; diff --git a/widegraph.cpp b/widegraph.cpp index c48153307..a89e544bb 100644 --- a/widegraph.cpp +++ b/widegraph.cpp @@ -183,6 +183,12 @@ void WideGraph::keyPressEvent(QKeyEvent *e) } } +void WideGraph::setQSOfreq(int n) +{ + m_qsoFreq=n; + ui->widePlot->setFQSO(m_qsoFreq,true); +} + int WideGraph::QSOfreq() { return ui->widePlot->fQSO(); diff --git a/widegraph.h b/widegraph.h index 967381f2b..6e3da63a5 100644 --- a/widegraph.h +++ b/widegraph.h @@ -18,6 +18,7 @@ public: void dataSink2(float s[], float red[], float df3, int ihsym, int ndiskdata, uchar lstrong[]); + void setQSOfreq(int n); int QSOfreq(); int nSpan(); int nStartFreq();