From 98454942767dcd7c7ca9820f342883df38cff50a Mon Sep 17 00:00:00 2001 From: Joe Taylor Date: Fri, 3 Jun 2016 15:45:54 +0000 Subject: [PATCH] Install MSK144 as a new mode. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@6721 ab8295b8-cf94-4d9e-aec4-7959e3be5d79 --- Modes.cpp | 3 +- Modes.hpp | 1 + displaytext.cpp | 2 +- lib/fast_decode.f90 | 3 + lib/msk144_decode.f90 | 6 +- lib/msk144d.f90 | 2 +- mainwindow.cpp | 153 +++++++++++++++++++++++++----------------- mainwindow.h | 3 + mainwindow.ui | 25 +++++++ 9 files changed, 129 insertions(+), 69 deletions(-) diff --git a/Modes.cpp b/Modes.cpp index f8111b731..48ba03ee4 100644 --- a/Modes.cpp +++ b/Modes.cpp @@ -16,7 +16,8 @@ namespace "WSPR", "Echo", "ISCAT", - "JTMSK" + "JTMSK", + "MSK144" }; } diff --git a/Modes.hpp b/Modes.hpp index 36a0f29ae..a16e6729d 100644 --- a/Modes.hpp +++ b/Modes.hpp @@ -22,6 +22,7 @@ public: Echo, ISCAT, JTMSK, + MSK144, }; Q_ENUM (Mode) diff --git a/displaytext.cpp b/displaytext.cpp index 5fb86f084..b4607cd50 100644 --- a/displaytext.cpp +++ b/displaytext.cpp @@ -174,7 +174,7 @@ void DisplayText::displayTransmittedText(QString text, QString modeTx, qint32 tx QString t1=" @ "; if(modeTx=="JT4") t1=" $ "; if(modeTx=="JT65") t1=" # "; - if(modeTx=="JTMSK") t1=" & "; + if(modeTx=="JTMSK" or modeTx=="MSK144") t1=" & "; QString t2; t2.sprintf("%4d",txFreq); QString t; diff --git a/lib/fast_decode.f90 b/lib/fast_decode.f90 index 10eb523a1..9f5f460b8 100644 --- a/lib/fast_decode.f90 +++ b/lib/fast_decode.f90 @@ -31,6 +31,9 @@ subroutine fast_decode(id2,narg,line) else if(nmode.eq.103) then call jtmsk_decode(id2,narg,line) go to 900 + else if(nmode.eq.104) then + call msk144_decode(id2,ndat0,nutc,0,line) + go to 900 endif if(newdat.eq.1) then diff --git a/lib/msk144_decode.f90 b/lib/msk144_decode.f90 index 77033beb6..f732ce0de 100644 --- a/lib/msk144_decode.f90 +++ b/lib/msk144_decode.f90 @@ -1,4 +1,4 @@ -subroutine msk144_decode(id2,npts,nutc,line) +subroutine msk144_decode(id2,npts,nutc,nprint,line) ! Calls the experimental decoder for JTMSK 72ms ldpc messages @@ -67,8 +67,8 @@ subroutine msk144_decode(id2,npts,nutc,line) y=10.0**(0.1*(yellow(n)-1.5)) nsnr=max(-5,nint(db(y))) ! if(nsnr.gt.nsnr0 .and. nline.gt.0) then -! write(line(nline),1020) nutc,nsnr,t0,nint(freq),msg - write(*,1020) nutc,nsnr,t0,nint(freq),msg + write(line(nline),1020) nutc,nsnr,t0,nint(freq),msg + if(nprint.ne.0) write(*,1020) nutc,nsnr,t0,nint(freq),msg 1020 format(i6.6,i4,f5.1,i5,' & ',a22) nsnr0=nsnr ! go to 900 diff --git a/lib/msk144d.f90 b/lib/msk144d.f90 index c1d701d62..4218de8cb 100644 --- a/lib/msk144d.f90 +++ b/lib/msk144d.f90 @@ -63,7 +63,7 @@ program msk144d read(unit=wav%lun) id2(1:npts) close(unit=wav%lun) call timer('read ',1) - call msk144_decode(id2,npts,nutc,line) + call msk144_decode(id2,npts,nutc,1,line) enddo call timer('msk144 ',1) diff --git a/mainwindow.cpp b/mainwindow.cpp index 3a8753f2d..5d39b8b74 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -71,6 +71,9 @@ extern "C" { void genmsk_(char* msg, int* ichk, char* msgsent, int itone[], int* itext, int len1, int len2); + void genmsk144_(char* msg, int* ichk, char* msgsent, int itone[], + int* itext, int len1, int len2); + void gen65_(char* msg, int* ichk, char* msgsent, int itone[], int* itext, int len1, int len2); @@ -340,6 +343,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, ui->actionEcho->setActionGroup(modeGroup); ui->actionISCAT->setActionGroup(modeGroup); ui->actionJTMSK->setActionGroup(modeGroup); + ui->actionMSK144->setActionGroup(modeGroup); QActionGroup* saveGroup = new QActionGroup(this); ui->actionNone->setActionGroup(saveGroup); @@ -677,7 +681,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, m_config.transceiver_online (); bool b=m_config.enable_VHF_features() and (m_mode=="JT4" or m_mode=="JT65" or - m_mode=="ISCAT" or m_mode=="JT9" or m_mode=="JTMSK"); + m_mode=="ISCAT" or m_mode=="JT9" or m_mode=="JTMSK" or m_mode=="MSK144"); VHF_controls_visible(b); if(m_mode=="JT4") on_actionJT4_triggered(); @@ -689,6 +693,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, if(m_mode=="Echo") on_actionEcho_triggered(); if(m_mode=="ISCAT") on_actionISCAT_triggered(); if(m_mode=="JTMSK") on_actionJTMSK_triggered(); + if(m_mode=="MSK144") on_actionMSK144_triggered(); if(m_mode=="Echo") monitor(false); //Don't auto-start Monitor in Echo mode. @@ -922,12 +927,12 @@ void MainWindow::dataSink(qint64 frames) dec_data.params.ndiskdat=0; } - if(m_mode=="ISCAT" or m_mode=="JTMSK" or m_bFast9) { + if(m_mode=="ISCAT" or m_mode=="JTMSK" or m_mode=="MSK144" or m_bFast9) { fastSink(frames); - return; //### Had been commented out (2/4/2016) ### + return; } - // Get power, spectrum, and ihsym +// Get power, spectrum, and ihsym int trmin=m_TRperiod/60; // int k (frames - 1); dec_data.params.nfa=m_wideGraph->nStartFreq(); @@ -1193,7 +1198,8 @@ void MainWindow::on_actionSettings_triggered() //Setup Dialog auto_tx_label->setText (m_config.quick_call () ? "Auto-Tx-Enable Armed" : "Auto-Tx-Enable Disarmed"); displayDialFrequency (); bool b=m_config.enable_VHF_features() and (m_mode=="JT4" or m_mode=="JT65" or - m_mode=="ISCAT" or m_mode=="JT9" or m_mode=="JTMSK"); + m_mode=="ISCAT" or m_mode=="JT9" or m_mode=="JTMSK" or + m_mode=="MSK144"); VHF_features_enabled(b); VHF_controls_visible(b); } @@ -1923,7 +1929,7 @@ void MainWindow::decode() //decode() from += noffset; size -= noffset; } - if(m_mode=="ISCAT" or m_mode=="JTMSK" or m_bFast9) { + if(m_mode=="ISCAT" or m_mode=="JTMSK" or m_mode=="MSK144" or m_bFast9) { float t0=m_t0; float t1=m_t1; qApp->processEvents(); //Update the waterfall @@ -1949,6 +1955,7 @@ void MainWindow::decode() //decode() if(m_mode=="ISCAT") narg[9]=101; //ISCAT if(m_mode=="JT9") narg[9]=102; //Fast JT9 if(m_mode=="JTMSK") narg[9]=103; //JTMSK + if(m_mode=="MSK144") narg[9]=104; //MSK144 narg[10]=ui->RxFreqSpinBox->value(); narg[11]=m_Ftol; m_calls="<" + m_config.my_callsign() + " " + hisCall + ">"; @@ -1973,8 +1980,8 @@ void::MainWindow::fast_decode_done() for(int i=0; i<100; i++) { int i1=msg0.indexOf(m_baseCall); int i2=msg0.indexOf(m_hisCall); - if(((m_mode=="JTMSK") or m_bFast9) and m_bEME and tmax>=0.0 and i1>10 and - i2>i1+3) { //Here, "m_bEME" implies AutoSeq + if((m_mode=="JTMSK" or m_mode=="MSK144" or m_bFast9) and m_bEME and tmax>=0.0 and + i1>10 and i2>i1+3) { //Here, "m_bEME" implies AutoSeq processMessage(msg0,40,false); } if(m_msg[i][0]==0) break; @@ -2012,15 +2019,14 @@ void::MainWindow::fast_decode_done() msgBox("Cannot open \"" + f.fileName () + "\" for append:" + f.errorString ()); } - if(m_mode=="JT9" or m_mode=="JTMSK") { - // find and extract any report for myCall + if(m_mode=="JT9" or m_mode=="JTMSK" or m_mode=="MSK144") { +// find and extract any report for myCall QString msg=message.mid(0,4) + message.mid(6,-1); decodedtext=msg.replace("\n",""); bool stdMsg = decodedtext.report(m_baseCall, Radio::base_callsign(ui->dxCallEntry->text().toUpper().trimmed()), m_rptRcvd); - // extract details and send to PSKreporter -// int nsec=QDateTime::currentMSecsSinceEpoch()/1000-m_secBandChanged; +// extract details and send to PSKreporter if(m_config.spot_to_psk_reporter() and stdMsg and !m_diskData) { QString msgmode="JT9"; QString deCall; @@ -2277,7 +2283,9 @@ void MainWindow::guiUpdate() if(m_modeTx=="JT9") txDuration=1.0 + 85.0*m_nsps/12000.0; // JT9 if(m_modeTx=="JT65") txDuration=1.0 + 126*4096/11025.0; // JT65 if(m_mode=="WSPR-2") txDuration=2.0 + 162*8192/12000.0; // WSPR - if(m_mode=="ISCAT" or m_bFast9) txDuration=m_TRperiod-0.25; // ISCAT, JT9-fast, JTMSK + if(m_mode=="ISCAT" or m_mode=="JTMSK" or m_mode=="MSK144" or m_bFast9) { + txDuration=m_TRperiod-0.25; // ISCAT, JT9-fast, JTMSK, MSK144 + } //### if(m_mode=="WSPR-15") tx2=... double tx1=0.0; @@ -2325,7 +2333,7 @@ void MainWindow::guiUpdate() } } else { - // For all modes other than WSPR +// For all modes other than WSPR m_bTxTime = (t2p >= tx1) and (t2p < tx2); if(m_mode=="Echo") m_bTxTime = m_bTxTime and m_bEchoTxOK; } @@ -2362,17 +2370,14 @@ void MainWindow::guiUpdate() setXIT (ui->TxFreqSpinBox->value ()); // If "CQ nnn ..." feature is active, set the proper Tx frequency - if(m_config.offsetRxFreq() && ui->cbCQRx->isChecked() - && (m_monitoring || m_transmitting) - && m_config.is_transceiver_online () - && m_config.split_mode ()) - { + if(m_config.offsetRxFreq() && ui->cbCQRx->isChecked() && + (m_monitoring || m_transmitting) && m_config.is_transceiver_online () + && m_config.split_mode ()) { // All conditions are met, reset the transceiver Tx frequency: - Frequency tx_frequency {6 == m_ntx ? - m_callingFrequency : + Frequency tx_frequency {6 == m_ntx ? m_callingFrequency : m_freqTxNominal / 1000000 * 1000000 + 1000 * m_freqCQ + m_XIT}; - Q_EMIT m_config.transceiver_tx_frequency (tx_frequency); - } + Q_EMIT m_config.transceiver_tx_frequency (tx_frequency); + } Q_EMIT m_config.transceiver_ptt (true); //Assert the PTT ptt1Timer->start(200); //Sequencer delay @@ -2458,6 +2463,8 @@ void MainWindow::guiUpdate() len1, len1); if(m_modeTx=="JTMSK") genmsk_(message, &ichk, msgsent, const_cast (itone), &m_currentMessageType, len1, len1); + if(m_modeTx=="MSK144") genmsk144_(message, &ichk, msgsent, const_cast (itone), + &m_currentMessageType, len1, len1); msgsent[22]=0; } } @@ -2995,7 +3002,7 @@ void MainWindow::processMessage(QString const& messages, int position, bool ctrl QString rpt = decodedtext.report(); int n=rpt.toInt(); - if(m_mode=="JTMSK" and m_bShMsgs) { + if((m_mode=="JTMSK" or m_mode=="MSK144") and m_bShMsgs) { n=26; if(rpt.toInt()>4) n=27; if(rpt.toInt()>8) n=28; @@ -3149,7 +3156,7 @@ void MainWindow::genStdMsgs(QString rpt) //genStdMsgs() } else { int n=rpt.toInt(); rpt.sprintf("%+2.2d",n); - if(m_mode=="JTMSK" and m_bShMsgs) { + if((m_mode=="JTMSK" or m_mode=="MSK144") and m_bShMsgs) { int i=t0.length()-1; t0="<" + t0.mid(0,i) + "> "; if(n<26) n=26; @@ -3396,7 +3403,7 @@ void MainWindow::msgtype(QString t, QLineEdit* tx) //msgtype() bool short65=false; if(itype==6) text=true; if(itype==7) short65=true; - if(m_mode=="JTMSK" and t.mid(0,1)=="<") text=false; + if((m_mode=="JTMSK" or m_mode=="MSK144") and t.mid(0,1)=="<") text=false; QString t1; t1.fromLatin1(msgsent); if(text) t1=t1.mid(0,13); @@ -3408,13 +3415,15 @@ void MainWindow::msgtype(QString t, QLineEdit* tx) //msgtype() p.setColor(QPalette::Base,"#66ffff"); } else { p.setColor(QPalette::Base,Qt::white); - if(m_mode=="JTMSK" and t.mid(0,1)=="<") p.setColor(QPalette::Base,"#00ffff"); + if((m_mode=="JTMSK" or m_mode=="MSK144") and t.mid(0,1)=="<") { + p.setColor(QPalette::Base,"#00ffff"); + } } } tx->setPalette(p); int len=t.length(); auto pos = tx->cursorPosition (); - if(text && m_mode!="JTMSK" && t.mid(0,1)!="<") { + if(text && m_mode!="JTMSK" && m_mode!="MSK144" && t.mid(0,1)!="<") { len=qMin(len,13); tx->setText(t.mid(0,len).toUpper()); } else { @@ -3645,6 +3654,21 @@ void MainWindow::on_actionJTMSK_triggered() ui->ClrAvgButton->setVisible(false); } +void MainWindow::on_actionMSK144_triggered() +{ + on_actionJTMSK_triggered(); + m_mode="MSK144"; + m_modeTx="MSK144"; + ui->actionMSK144->setChecked(true); + switch_mode (Modes::MSK144); + statusChanged(); + m_nsps=6; + mode_label->setStyleSheet("QLabel{background-color: #ff6666}"); + mode_label->setText(m_mode); + m_toneSpacing=0.0; + ui->actionMSK144->setChecked(true); +} + void MainWindow::on_actionJT65_triggered() { if(m_mode=="JT4" or m_mode.startsWith ("WSPR")) { @@ -3897,7 +3921,7 @@ void MainWindow::switch_mode (Mode mode) ui->bandComboBox->setCurrentIndex (row); on_bandComboBox_activated (row); } - bool b=m_mode=="JTMSK"; + bool b=(m_mode=="JTMSK" or m_mode=="MSK144"); ui->sbCQRxFreq->setVisible(b); ui->cbCQRx->setVisible(b); ui->syncSpinBox->setVisible(!b); @@ -3947,7 +3971,7 @@ void MainWindow::fast_config(bool b) ui->cbEME->setText("EME delay"); ui->sbTR->setVisible(false); } - if(b and (m_bFast9 or m_mode=="JTMSK" or m_mode=="ISCAT")) { + if(b and (m_bFast9 or m_mode=="JTMSK" or m_mode=="MSK144" or m_mode=="ISCAT")) { ui->sbTR->setValue(m_TRindex); m_wideGraph->hide(); m_fastGraph->show(); @@ -4428,38 +4452,36 @@ void MainWindow::handle_transceiver_update (Transceiver::TransceiverState const& { m_lastMonitoredFrequency = m_freqNominal; } - if (m_lastDialFreq != m_freqNominal and (m_mode!="JTMSK" or !ui->cbCQRx->isChecked())) - { - m_lastDialFreq = m_freqNominal; - m_repeatMsg=0; - m_secBandChanged=QDateTime::currentMSecsSinceEpoch()/1000; - if(s.frequency () < 30000000u && !m_mode.startsWith ("WSPR")) { - // Write freq changes to ALL.TXT only below 30 MHz. - QFile f2 {m_dataDir.absoluteFilePath ("ALL.TXT")}; - if (f2.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) { - QTextStream out(&f2); - out << QDateTime::currentDateTimeUtc().toString("yyyy-MMM-dd hh:mm") - << " " << qSetRealNumberPrecision (12) << (m_freqNominal / 1.e6) << " MHz " - << m_mode << endl; - f2.close(); - } else { - msgBox("Cannot open \"" + f2.fileName () + "\" for append:" + f2.errorString ()); - } + if (m_lastDialFreq != m_freqNominal and ((m_mode!="JTMSK" and m_mode!="MSK144") or + !ui->cbCQRx->isChecked())) { + m_lastDialFreq = m_freqNominal; + m_repeatMsg=0; + m_secBandChanged=QDateTime::currentMSecsSinceEpoch()/1000; + if(s.frequency () < 30000000u && !m_mode.startsWith ("WSPR")) { + // Write freq changes to ALL.TXT only below 30 MHz. + QFile f2 {m_dataDir.absoluteFilePath ("ALL.TXT")}; + if (f2.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) { + QTextStream out(&f2); + out << QDateTime::currentDateTimeUtc().toString("yyyy-MMM-dd hh:mm") + << " " << qSetRealNumberPrecision (12) << (m_freqNominal / 1.e6) << " MHz " + << m_mode << endl; + f2.close(); + } else { + msgBox("Cannot open \"" + f2.fileName () + "\" for append:" + f2.errorString ()); } - - if (m_config.spot_to_psk_reporter ()) { - pskSetLocal (); - } - statusChanged(); - m_wideGraph->setDialFreq(m_freqNominal / 1.e6); } - } - else - { - m_freqTxNominal = s.split () ? s.tx_frequency () - m_astroCorrection.tx : s.frequency (); - } + + if (m_config.spot_to_psk_reporter ()) { + pskSetLocal (); + } + statusChanged(); + m_wideGraph->setDialFreq(m_freqNominal / 1.e6); + } + } else { + m_freqTxNominal = s.split () ? s.tx_frequency () - m_astroCorrection.tx : s.frequency (); + } if (m_astroWidget) m_astroWidget->nominal_frequency (m_freqNominal, m_freqTxNominal); - } + } // ensure frequency display is correct if (m_astroWidget && old_state.ptt () != s.ptt ()) setRig (); @@ -4538,12 +4560,17 @@ void MainWindow::transmit (double snr) true, fastmode, snr, m_TRperiod); } - if (m_modeTx == "JTMSK") { + if (m_modeTx == "JTMSK" or m_modeTx == "MSK144") { m_nsps=6; m_toneSpacing=6000.0/m_nsps; double f0=1000.0; - int nsym=NUM_JTMSK_SYMBOLS; - if(itone[35] < 0) nsym=35; + int nsym; + if (m_modeTx == "JTMSK") { + nsym=NUM_JTMSK_SYMBOLS; + if(itone[35] < 0) nsym=35; + } else { + nsym=NUM_MSK144_SYMBOLS; + } Q_EMIT sendMessage (nsym, double(m_nsps), f0, m_toneSpacing, m_soundOutput, m_config.audio_output_channel (), true, true, snr, m_TRperiod); @@ -4885,7 +4912,7 @@ void MainWindow::on_cbShMsgs_toggled(bool b) { ui->cbTx6->setEnabled(b); m_bShMsgs=b; - if(m_bShMsgs and m_mode=="JTMSK") ui->rptSpinBox->setValue(26); + if(m_bShMsgs and (m_mode=="JTMSK" or m_mode=="JTMSK")) ui->rptSpinBox->setValue(26); int itone0=itone[0]; int ntx=m_ntx; genStdMsgs(m_rpt); diff --git a/mainwindow.h b/mainwindow.h index 069ace871..b759255db 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -38,6 +38,7 @@ #define NUM_WSPR_SYMBOLS 162 //(50+31)*2, embedded sync #define NUM_ISCAT_SYMBOLS 1291 //30*11025/256 #define NUM_JTMSK_SYMBOLS 234 //(72+15+12)*2 + 3*11 sync + 3 f0-parity +#define NUM_MSK144_SYMBOLS 144 //s8 + d48 + s8 + d80 #define NUM_CW_SYMBOLS 250 #define TX_SAMPLE_RATE 48000 @@ -244,6 +245,8 @@ private slots: void on_sbCQRxFreq_valueChanged(int n); void on_cbCQRx_toggled(bool b); + void on_actionMSK144_triggered(); + private: Q_SIGNAL void initializeAudioOutputStream (QAudioDeviceInfo, unsigned channels, unsigned msBuffered) const; diff --git a/mainwindow.ui b/mainwindow.ui index a78e71121..2b6b0b20e 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -2,6 +2,14 @@ MainWindow + + + 0 + 0 + 896 + 565 + + WSJT-X by K1JT @@ -2282,6 +2290,14 @@ QPushButton[state="ok"] { + + + 0 + 0 + 896 + 21 + + File @@ -2358,6 +2374,7 @@ QPushButton[state="ok"] { + @@ -2819,6 +2836,14 @@ QPushButton[state="ok"] { <html><head/><body><p>Download sample audio files demonstrating the various modes.</p></body></html> + + + true + + + MSK144 + +