Code cleanup. Implement use of fQSO, ntol, etc.

git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@2671 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Joe Taylor 2012-10-19 19:26:07 +00:00
parent 2a11cd7c5e
commit dd0fb0c743
12 changed files with 58 additions and 44 deletions

View File

@ -12,10 +12,10 @@ extern struct {
int nutc; //UTC as integer, HHMM int nutc; //UTC as integer, HHMM
int ndiskdat; //1 ==> data read from *.wav file int ndiskdat; //1 ==> data read from *.wav file
int ntrperiod; //TR period (seconds) 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 nagain; //1 ==> decode only at fQSO +/- Tol
int newdat; //1 ==> new data, must do long FFT 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 nfb; //High decode limit (kHz)
int ntol; //+/- decoding range around fQSO (Hz) int ntol; //+/- decoding range around fQSO (Hz)
int kin; int kin;

18
jt9.txt
View File

@ -1,7 +1,7 @@
JT9 is a mode designed for amateur QSOs at MF and LF. The mode uses 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 the same 72-bit structured messages as JT65. Error control coding
(ECC) uses a convolutional code with constraint length K=32, rate (ECC) uses a strong convolutional code with constraint length K=32,
r=1/2, and a zero tail, leading to an encoded message length of 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 (72+31)*2 = 206 information-carrying bits. Modulation is 9-FSK: 8
tones for data, one for synchronization. Sixteen symbol intervals are tones for data, one for synchronization. Sixteen symbol intervals are
used for synchronization, so a transmission requires a total of 207/3 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 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 per symbol (at 12000 samples per second) is a number with no prime
factor greater than 7. This choice makes for efficient FFTs. Tone 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 spacing of the 9-FSK modulation is df=1/tsym=12000/nsps, equal to the
the keying rate. The total occupied bandwidth is 9*df. 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 Parameters of five JT9 sub-modes are summarized in the following
table, along with S/N thresholds measured by simulation on an AWGN 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 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 2. Filter to 1000 Hz bandwidth and downsample (1/8) to 1500 Hz, saving
complex data to array c0(2,700,000). complex data to array c0(2,700,000).
3. Compute spectra at half-symbol steps. Use for waterfall display 3. Compute spectra at half-symbol steps. Use for waterfall display
s(22000) and save in ss(184,22000) and s(22000) and save in ss(184,22000) and savg(22000) for detecting
savg(22000), for detecting sync vectors. sync vectors.
4. At time Tdec, find sync vectors in ss(); get approx DF or list of DFs 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. 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?). 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. close to zero frequency.
7. Use afc65b method to get improved values of DF, DT. 7. Use afc65b method to get improved values of DF, DT.
8. Tweak freq and time offset to 0. 8. Tweak freq and time offset to 0.

View File

@ -14,7 +14,7 @@ subroutine decoder(ntrSeconds,c0)
integer*2 id2 integer*2 id2
complex c0(NDMAX) complex c0(NDMAX)
common/jt9com/ss(184,NSMAX),savg(NSMAX),id2(NMAX),nutc,ndiskdat, & 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 ntrMinutes=ntrSeconds/60
newdat=1 newdat=1
@ -35,24 +35,22 @@ subroutine decoder(ntrSeconds,c0)
! Now do the decoding ! Now do the decoding
nutc=0 nutc=0
kstep=nsps/2
tstep=kstep/12000.0 tstep=kstep/12000.0
ntol=500
nfqso=1500
! Get sync, approx freq ! Get sync, approx freq
call sync9(ss,tstep,df3,ntol,nfqso,sync,fpk,red) 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 spec9(c0,npts8,nsps,fpk,xdt,i1SoftSymbols)
call decode9(i1SoftSymbols,msg) call decode9(i1SoftSymbols,msg)
open(73,file='decoded.txt',status='unknown') open(13,file='decoded.txt',status='unknown')
rewind 73 rewind 13
! write(*,1010) nutc,sync,xdt,1000.0+fpk,msg ! 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) 1010 format(i4.4,3f7.1,2x,a22)
call flush(73) call flush(13)
close(73) close(13)
return return
end subroutine decoder end subroutine decoder

View File

@ -2,6 +2,7 @@ subroutine spec9(c0,npts8,nsps,fpk,xdt,i1SoftSymbols)
parameter (MAXFFT=31500) parameter (MAXFFT=31500)
complex c0(0:npts8-1) complex c0(0:npts8-1)
complex c1(0:2700000)
real ssym(0:7,69) real ssym(0:7,69)
complex c(0:MAXFFT-1) complex c(0:MAXFFT-1)
integer*1 i1SoftSymbolsScrambled(207) integer*1 i1SoftSymbolsScrambled(207)
@ -27,17 +28,17 @@ subroutine spec9(c0,npts8,nsps,fpk,xdt,i1SoftSymbols)
phi=phi+dphi phi=phi+dphi
if(phi.gt.twopi) phi=phi-twopi if(phi.gt.twopi) phi=phi-twopi
if(phi.lt.-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 enddo
nsps8=nsps/8 nsps8=nsps/8
foffset=fpk foffset=fpk
istart=1520 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 fpk=fpk + idf*0.1*1500.0/nsps8
foffset=foffset + 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 istart=istart + 0.0625*nsps8*idt
xdt=istart/1500.0 - 1.0 xdt=istart/1500.0 - 1.0
! write(*,3002) 0.0625*nsps8*idt/1500.0,idf*0.1*1500.0/nsps8 ! 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 k=k+1
ia=(j-1)*nsps8 + istart ia=(j-1)*nsps8 + istart
ib=ia+nsps8-1 ib=ia+nsps8-1
c(0:nfft-1)=c0(ia:ib) c(0:nfft-1)=c1(ia:ib)
phi=0. phi=0.
do i=0,nfft-1 do i=0,nfft-1

View File

@ -37,7 +37,7 @@ subroutine symspec(k,ntrperiod,nsps,nb,nbslider,pxdb,s,red, &
data rms/999.0/,k0/99999999/,ntrperiod0/0/,nfft3z/0/ data rms/999.0/,k0/99999999/,ntrperiod0/0/,nfft3z/0/
save save
if(ntrperiod.eq.1) nfft3=1024 if(ntrperiod.eq.1) nfft3=2048
if(ntrperiod.eq.2) nfft3=2048 if(ntrperiod.eq.2) nfft3=2048
if(ntrperiod.eq.5) nfft3=6144 if(ntrperiod.eq.5) nfft3=6144
if(ntrperiod.eq.10) nfft3=12288 if(ntrperiod.eq.10) nfft3=12288

View File

@ -373,9 +373,9 @@ void MainWindow::dataSink(int k)
ntr0=ntr; ntr0=ntr;
n=0; n=0;
} }
if(ihsym == m_hsymStop) { // This is a bit strange. Why do we need the "-3" ??
jt9com_.newdat=1; if(ihsym == m_hsymStop-3) {
jt9com_.nagain=0; jt9com_.npts8=(ihsym*m_nsps)/16;
QDateTime t = QDateTime::currentDateTimeUtc(); QDateTime t = QDateTime::currentDateTimeUtc();
m_dateTime=t.toString("yyyy-MMM-dd hh:mm"); m_dateTime=t.toString("yyyy-MMM-dd hh:mm");
decode(); //Start the decoder decode(); //Start the decoder
@ -509,19 +509,17 @@ void MainWindow::keyPressEvent( QKeyEvent *e ) //keyPressEvent
case Qt::Key_F11: case Qt::Key_F11:
if(e->modifiers() & Qt::ShiftModifier) { if(e->modifiers() & Qt::ShiftModifier) {
} else { } else {
int n0=g_pWideGraph->DF(); int n=g_pWideGraph->QSOfreq();
int n=(n0 + 10000) % 5; n--;
if(n==0) n=5; g_pWideGraph->setQSOfreq(n);
g_pWideGraph->setDF(n0-n);
} }
break; break;
case Qt::Key_F12: case Qt::Key_F12:
if(e->modifiers() & Qt::ShiftModifier) { if(e->modifiers() & Qt::ShiftModifier) {
} else { } else {
int n0=g_pWideGraph->DF(); int n=g_pWideGraph->QSOfreq();
int n=(n0 + 10000) % 5; n++;
if(n==0) n=5; g_pWideGraph->setQSOfreq(n);
g_pWideGraph->setDF(n0+n);
} }
break; break;
case Qt::Key_G: case Qt::Key_G:
@ -726,10 +724,12 @@ void MainWindow::on_actionDecode_remaining_files_in_directory_triggered()
void MainWindow::diskDat() //diskDat() void MainWindow::diskDat() //diskDat()
{ {
int k;
int kstep=m_nsps/2; int kstep=m_nsps/2;
m_diskData=true; m_diskData=true;
for(int n=1; n<=m_hsymStop; n++) { // Do the half-symbol FFTs 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); dataSink(k);
if(n%10 == 1 or n == m_hsymStop) qApp->processEvents(); //Keep GUI responsive 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() void MainWindow::freezeDecode(int n) //freezeDecode()
{ {
decode();
} }
void MainWindow::decode() //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]); *future3 = QtConcurrent::run(decoder_, &m_TRperiod, &c0[0]);
watcher3->setFuture(*future3); watcher3->setFuture(*future3);
} }

View File

@ -136,6 +136,7 @@ private:
qint32 m_nsps; qint32 m_nsps;
qint32 m_hsymStop; qint32 m_hsymStop;
qint32 m_len1; qint32 m_len1;
qint32 m_fQSO;
bool m_monitoring; bool m_monitoring;
bool m_transmitting; bool m_transmitting;

View File

@ -66,7 +66,7 @@
</size> </size>
</property> </property>
<property name="title"> <property name="title">
<string> UTC T dB DF</string> <string> UTC T dB Freq</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_9"> <layout class="QVBoxLayout" name="verticalLayout_9">
<item> <item>

View File

@ -27,7 +27,7 @@ CPlotter::CPlotter(QWidget *parent) : //CPlotter Constructor
m_ScalePixmap = QPixmap(0,0); m_ScalePixmap = QPixmap(0,0);
m_OverlayPixmap = QPixmap(0,0); m_OverlayPixmap = QPixmap(0,0);
m_Size = QSize(0,0); m_Size = QSize(0,0);
m_fQSO = 1050; m_fQSO = 1020;
m_line = 0; m_line = 0;
m_fSample = 12000; m_fSample = 12000;
m_nsps=6912; 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); painter0.setPen(pen0);
x = m_xClick; x = m_xClick;
painter0.drawLine(x,15,x,30); painter0.drawLine(x,15,x,30);
@ -407,6 +407,7 @@ void CPlotter::setFQSO(int x, bool bf) //setFQSO()
{ {
if(bf) { if(bf) {
m_fQSO=x; // x is freq in kHz m_fQSO=x; // x is freq in kHz
m_xClick=XfromFreq(m_fQSO);
} else { } else {
if(x<0) x=0; // x is pixel number if(x<0) x=0; // x is pixel number
if(x>m_Size.width()) x=m_Size.width(); if(x>m_Size.width()) x=m_Size.width();
@ -564,7 +565,7 @@ double CPlotter::fGreen()
void CPlotter::setNsps(int n) //setNSpan() void CPlotter::setNsps(int n) //setNSpan()
{ {
m_nsps=n; 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==15360) m_fftBinWidth=1500.0/2048.0;
if(m_nsps==40960) m_fftBinWidth=1500.0/6144.0; if(m_nsps==40960) m_fftBinWidth=1500.0/6144.0;
if(m_nsps==82944) m_fftBinWidth=1500.0/12288.0; if(m_nsps==82944) m_fftBinWidth=1500.0/12288.0;

View File

@ -16,7 +16,7 @@ extern struct {
int mousefqso; //User-selected QSO freq (kHz) int mousefqso; //User-selected QSO freq (kHz)
int nagain; //1 ==> decode only at fQSO +/- Tol int nagain; //1 ==> decode only at fQSO +/- Tol
int newdat; //1 ==> new data, must do long FFT 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 nfb; //High decode limit (kHz)
int ntol; //+/- decoding range around fQSO (Hz) int ntol; //+/- decoding range around fQSO (Hz)
int kin; int kin;

View File

@ -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() int WideGraph::QSOfreq()
{ {
return ui->widePlot->fQSO(); return ui->widePlot->fQSO();

View File

@ -18,6 +18,7 @@ public:
void dataSink2(float s[], float red[], float df3, int ihsym, void dataSink2(float s[], float red[], float df3, int ihsym,
int ndiskdata, uchar lstrong[]); int ndiskdata, uchar lstrong[]);
void setQSOfreq(int n);
int QSOfreq(); int QSOfreq();
int nSpan(); int nSpan();
int nStartFreq(); int nStartFreq();