From 5f03d97a9ec74b6968b1ad75e3c4e4c471d17b7a Mon Sep 17 00:00:00 2001 From: Joe Taylor Date: Fri, 18 Jan 2019 11:51:15 -0500 Subject: [PATCH] Implement basic Rx capability for FT2 in WSJT-X. --- CMakeLists.txt | 3 + lib/ft2/ft2_decode.f90 | 28 ++++-- ...getcandidates2.f90 => getcandidates2a.f90} | 4 +- models/Modes.cpp | 3 +- models/Modes.hpp | 1 + widgets/mainwindow.cpp | 97 ++++++++++++++++++- widgets/mainwindow.h | 3 + widgets/mainwindow.ui | 9 ++ 8 files changed, 132 insertions(+), 16 deletions(-) rename lib/ft2/{getcandidates2.f90 => getcandidates2a.f90} (93%) diff --git a/CMakeLists.txt b/CMakeLists.txt index ef0bac291..a058fa258 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -509,6 +509,8 @@ set (wsjt_FSRCS lib/mskrtd.f90 lib/fsk4hf/ft2sim.f90 lib/fsk4hf/ft2d.f90 + lib/ft2/cdatetime.f90 + lib/ft2/ft2_decode.f90 lib/77bit/my_hash.f90 lib/wsprd/osdwspr.f90 lib/ft8/osd174_91.f90 @@ -550,6 +552,7 @@ set (wsjt_FSRCS lib/sync64.f90 lib/sync65.f90 lib/fsk4hf/getcandidates2.f90 + lib/ft2/getcandidates2a.f90 lib/ft8/sync8.f90 lib/ft8/sync8d.f90 lib/sync9.f90 diff --git a/lib/ft2/ft2_decode.f90 b/lib/ft2/ft2_decode.f90 index e26fc5567..5f7eb95e0 100644 --- a/lib/ft2/ft2_decode.f90 +++ b/lib/ft2/ft2_decode.f90 @@ -1,13 +1,14 @@ -subroutine ft2_decode(cdatetime,nfqso,iwave,ndecodes,mycall,hiscall,nrx) +subroutine ft2_decode(cdatetime0,nfqso,iwave,ndecodes,mycall,hiscall,nrx,line) use crc use packjt77 include 'ft2_params.f90' character message*37,c77*77 + character*61 line character*37 decodes(100) character*120 data_dir - character*17 cdatetime - character*6 mycall,hiscall + character*17 cdatetime0,cdatetime,cdt + character*6 mycall,hiscall,hhmmss complex c2(0:NMAX/16-1) !Complex waveform complex cb(0:NMAX/16-1) complex cd(0:144*10-1) !Complex waveform @@ -30,6 +31,12 @@ subroutine ft2_decode(cdatetime,nfqso,iwave,ndecodes,mycall,hiscall,nrx) logical unpk77_success data s16/0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0/ + hhmmss=' ' + if(cdatetime0==' ') then + cdt=cdatetime() + hhmmss=cdt(8:13) + endif + fs=12000.0/NDOWN !Sample rate dt=1/fs !Sample interval after downsample (s) tt=NSPS*dt !Duration of "itone" symbols (s) @@ -63,7 +70,7 @@ subroutine ft2_decode(cdatetime,nfqso,iwave,ndecodes,mycall,hiscall,nrx) syncmin=0.2 maxcand=100 nfqso=-1 - call getcandidates2(iwave,fa,fb,maxcand,savg,candidate,ncand) + call getcandidates2a(iwave,fa,fb,maxcand,savg,candidate,ncand) ndecodes=0 do icand=1,ncand f0=candidate(1,icand) @@ -191,11 +198,15 @@ subroutine ft2_decode(cdatetime,nfqso,iwave,ndecodes,mycall,hiscall,nrx) xsnr=db(sybest*sybest) - 115.0 !### Rough estimate of S/N ### nsnr=nint(xsnr) freq=f0+dfbest - write(*,1000) cdatetime,nsnr,ibest/750.0,nint(freq),message, & + write(line,1000) hhmmss,nsnr,ibest/750.0,nint(freq),message +1000 format(a6,i4,f5.2,i5,' + ',1x,a37) + open(24,file='all_ft2.txt',status='unknown',position='append') + write(24,1002) cdatetime0,nsnr,ibest/750.0,nint(freq),message, & nseq,nharderror,nhardmin - write(12,1000) cdatetime,nsnr,ibest/750.0,nint(freq),message, & - nseq,nharderror,nhardmin -1000 format(a17,i4,f6.2,i5,' Rx ',a37,3i5) + if(hhmmss.eq.' ') write(*,1002) cdatetime0,nsnr, & + ibest/750.0,nint(freq),message,nseq,nharderror,nhardmin +1002 format(a17,i4,f6.2,i5,' Rx ',a37,3i5) + close(24) !### Temporary: assume most recent decoded message conveys "hiscall". i0=index(message,' ') @@ -290,4 +301,3 @@ subroutine ft2_downsample(iwave,f0,c) c=c1(0:NMAX/16-1) return end subroutine ft2_downsample - diff --git a/lib/ft2/getcandidates2.f90 b/lib/ft2/getcandidates2a.f90 similarity index 93% rename from lib/ft2/getcandidates2.f90 rename to lib/ft2/getcandidates2a.f90 index dd5dac507..8e7209c9c 100644 --- a/lib/ft2/getcandidates2.f90 +++ b/lib/ft2/getcandidates2a.f90 @@ -1,4 +1,4 @@ -subroutine getcandidates2(id,fa,fb,maxcand,savg,candidate,ncand) +subroutine getcandidates2a(id,fa,fb,maxcand,savg,candidate,ncand) ! For now, hardwired to find the largest peak in the average spectrum @@ -61,4 +61,4 @@ subroutine getcandidates2(id,fa,fb,maxcand,savg,candidate,ncand) endif return -end subroutine getcandidates2 +end subroutine getcandidates2a diff --git a/models/Modes.cpp b/models/Modes.cpp index 9d21459c7..b823e3649 100644 --- a/models/Modes.cpp +++ b/models/Modes.cpp @@ -23,7 +23,8 @@ namespace "MSK144", "QRA64", "FreqCal", - "FT8" + "FT8", + "FT2" }; std::size_t constexpr mode_names_size = sizeof (mode_names) / sizeof (mode_names[0]); } diff --git a/models/Modes.hpp b/models/Modes.hpp index cdf299749..6af3e5ef3 100644 --- a/models/Modes.hpp +++ b/models/Modes.hpp @@ -49,6 +49,7 @@ public: QRA64, FreqCal, FT8, + FT2, MODES_END_SENTINAL_AND_COUNT // this must be last }; Q_ENUM (Mode) diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index a3c031c53..54e37905f 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -159,6 +159,10 @@ extern "C" { void plotsave_(float swide[], int* m_w , int* m_h1, int* irow); void chkcall_(char* w, char* basc_call, bool cok, int len1, int len2); + + void ft2_decode_(char* cdatetime, int* nfqso, short int id[], int* ndecodes, + char* mycall6, char* hiscall6, int* nrx, char* line, + int len1, int len2, int len3, int len4); } int volatile itone[NUM_ISCAT_SYMBOLS]; //Audio tones for all Tx symbols @@ -544,6 +548,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, on_EraseButton_clicked (); QActionGroup* modeGroup = new QActionGroup(this); + ui->actionFT2->setActionGroup(modeGroup); ui->actionFT8->setActionGroup(modeGroup); ui->actionJT9->setActionGroup(modeGroup); ui->actionJT65->setActionGroup(modeGroup); @@ -874,6 +879,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, if(m_bFast9) m_bFastMode=true; ui->cbFast9->setChecked(m_bFast9 or m_bFastMode); + if(m_mode=="FT2") on_actionFT2_triggered(); if(m_mode=="FT8") on_actionFT8_triggered(); if(m_mode=="JT4") on_actionJT4_triggered(); if(m_mode=="JT9") on_actionJT9_triggered(); @@ -1345,7 +1351,8 @@ void MainWindow::dataSink(qint64 frames) if(m_monitoring || m_diskData) { m_wideGraph->dataSink2(s,m_df3,m_ihsym,m_diskData); } - if(m_mode=="MSK144") return; + if(m_mode=="FT2") ft2Data(k); + if(m_mode=="MSK144" or m_mode=="FT2") return; fixStop(); if (m_mode == "FreqCal" @@ -1546,7 +1553,6 @@ void MainWindow::fastSink(qint64 frames) { int k (frames); bool decodeNow=false; - if(k < m_k0) { //New sequence ? memcpy(fast_green2,fast_green,4*703); //Copy fast_green[] to fast_green2[] memcpy(fast_s2,fast_s,4*703*64); //Copy fast_s[] into fast_s2[] @@ -3836,6 +3842,7 @@ void MainWindow::guiUpdate() //Once per second: if(nsec != m_sec0) { +// qDebug() << "cc oneSec" << dec_data.params.kin << m_ihsym; // if((!m_msgAvgWidget or (m_msgAvgWidget and !m_msgAvgWidget->isVisible())) // and (SpecOp::NONE < m_config.special_op_id()) and (SpecOp::HOUND > m_config.special_op_id())) on_actionFox_Log_triggered(); if(m_freqNominal!=0 and m_freqNominal<50000000 and m_config.enable_VHF_features()) { @@ -5497,6 +5504,52 @@ void MainWindow::displayWidgets(qint64 n) genStdMsgs (m_rpt, true); } +void MainWindow::on_actionFT2_triggered() +{ + m_mode="FT2"; + m_modeTx="FT2"; + m_TRperiod=2147483647; + bool bVHF=m_config.enable_VHF_features(); + m_bFast9=false; + m_bFastMode=false; + WSPR_config(false); + switch_mode (Modes::FT2); + m_nsps=6912; + m_FFTSize = m_nsps/2; + Q_EMIT FFTSize (m_FFTSize); + m_hsymStop=50; + setup_status_bar (bVHF); + m_toneSpacing=0.0; //??? + ui->actionFT2->setChecked(true); //??? + m_wideGraph->setMode(m_mode); + m_wideGraph->setModeTx(m_modeTx); + VHF_features_enabled(bVHF); + ui->cbAutoSeq->setChecked(false); + m_fastGraph->hide(); + m_wideGraph->show(); + ui->decodedTextLabel2->setText(" UTC dB DT Freq Message"); + m_wideGraph->setPeriod(m_TRperiod,m_nsps); + m_modulator->setTRPeriod(m_TRperiod); // TODO - not thread safe + m_detector->setTRPeriod(m_TRperiod); // TODO - not thread safe + ui->label_7->setText("Rx Frequency"); + ui->label_6->setText("Band Activity"); + ui->decodedTextLabel->setText( " UTC dB DT Freq Message"); + displayWidgets(nWidgets("111010000100111000010000100110001")); + ui->txrb2->setEnabled(true); + ui->txrb4->setEnabled(true); + ui->txrb5->setEnabled(true); + ui->txrb6->setEnabled(true); + ui->txb2->setEnabled(true); + ui->txb4->setEnabled(true); + ui->txb5->setEnabled(true); + ui->txb6->setEnabled(true); + ui->txFirstCheckBox->setEnabled(true); + ui->cbAutoSeq->setEnabled(true); + ui->labDXped->setVisible(false); + ui->labDXped->setText(""); + statusChanged(); +} + void MainWindow::on_actionFT8_triggered() { m_mode="FT8"; @@ -5599,8 +5652,6 @@ void MainWindow::on_actionFT8_triggered() statusChanged(); } - - void MainWindow::on_actionJT4_triggered() { m_mode="JT4"; @@ -8499,3 +8550,41 @@ void MainWindow::write_all(QString txRx, QString message) MessageBox::warning_message(this, tr ("Log File Error"), message2); }); } } + +void MainWindow::ft2Data(int k) +{ + static int nhsec0=-1; + short id[30000]; + int nhsec=k/6000; + if(nhsec!=nhsec0) { + //Process FT2 data at 0.5 s intervals + int j=k-30000; + if(j<0) j+=NRING; + for(int i=0; i<30000; i++) { + id[i]=dec_data.d2[j]; + j++; + if(j>=NRING) j=j-NRING; + } + if(k>=NRING) { + k=k-NRING; + dec_data.params.kin=k; + } + char cdatetime[]=" "; + char mycall6[] ="K1JT "; + char hiscall6[]="K9AN "; + char line[61]; + int nfqso=1500; + int ndecodes=0; + int nrx=-1; + ft2_decode_(cdatetime,&nfqso,id,&ndecodes,mycall6,hiscall6,&nrx,&line[0], + 17,6,6,61); + line[60]=0; + if(ndecodes>0) { + QString sline{QString::fromLatin1(line)}; + DecodedText decodedtext {sline.replace(QChar::LineFeed,"")}; + ui->decodedTextBrowser->displayDecodedText (decodedtext,m_baseCall,m_mode, + m_config.DXCC(),m_logBook,m_currentBand,m_config.ppfx()); + } + nhsec0=nhsec; + } +} diff --git a/widgets/mainwindow.h b/widgets/mainwindow.h index acabffe7f..fad9262c9 100644 --- a/widgets/mainwindow.h +++ b/widgets/mainwindow.h @@ -49,6 +49,7 @@ #define NUM_CW_SYMBOLS 250 #define TX_SAMPLE_RATE 48000 #define N_WIDGETS 33 +#define NRING 432000 extern int volatile itone[NUM_ISCAT_SYMBOLS]; //Audio tones for all Tx symbols extern int volatile icw[NUM_CW_SYMBOLS]; //Dits for CW ID @@ -200,6 +201,7 @@ private slots: void on_actionJT65_triggered(); void on_actionJT9_JT65_triggered(); void on_actionJT4_triggered(); + void on_actionFT2_triggered(); void on_actionFT8_triggered(); void on_TxFreqSpinBox_valueChanged(int arg1); void on_actionSave_decoded_triggered(); @@ -309,6 +311,7 @@ private slots: void on_comboBoxHoundSort_activated (int index); void not_GA_warning_message (); void checkMSK144ContestType(); + void ft2Data(int k); int setTxMsg(int n); bool stdCall(QString const& w); diff --git a/widgets/mainwindow.ui b/widgets/mainwindow.ui index 4e39e6d6c..ca9551ec2 100644 --- a/widgets/mainwindow.ui +++ b/widgets/mainwindow.ui @@ -2705,6 +2705,7 @@ list. The list can be maintained in Settings (F2). Mode + @@ -3338,6 +3339,14 @@ list. The list can be maintained in Settings (F2). Erase WSPR hashtable + + + true + + + FT2 + +