diff --git a/commons.h b/commons.h index f221ed322..163bb73d1 100644 --- a/commons.h +++ b/commons.h @@ -84,7 +84,7 @@ extern struct { float wave[606720]; int nslots; int i3bit[5]; - char cmsg[5][32]; + char cmsg[5][40]; char mycall[6]; } foxcom_; diff --git a/lib/ft8/foxgen.f90 b/lib/ft8/foxgen.f90 index 5feef8b88..9146bcdb2 100644 --- a/lib/ft8/foxgen.f90 +++ b/lib/ft8/foxgen.f90 @@ -17,7 +17,7 @@ subroutine foxgen() use crc parameter (NN=79,ND=58,KK=87,NSPS=4*1920) parameter (NWAVE=NN*NSPS,NFFT=614400,NH=NFFT/2) - character*32 cmsg + character*40 cmsg character*22 msg,msgsent character*6 mygrid character*87 cbits @@ -58,6 +58,7 @@ subroutine foxgen() msg=cmsg(n)(1:i1)//cmsg(n)(i2+1:i3-2)//' ' read(cmsg(n)(i4+2:i4+4),*) irpt endif +! print*,'Foxgen:',n,cmsg(n) call genft8(msg,mygrid,bcontest,0,msgsent,msgbits,itone) if(i3b.eq.1) then diff --git a/lib/ft8/foxgen_wrap.f90 b/lib/ft8/foxgen_wrap.f90 index 72a088727..3d9b43084 100644 --- a/lib/ft8/foxgen_wrap.f90 +++ b/lib/ft8/foxgen_wrap.f90 @@ -1,9 +1,9 @@ -subroutine foxgen_wrap(msg32,msgbits,itone) +subroutine foxgen_wrap(msg40,msgbits,itone) parameter (NN=79,ND=58,KK=87,NSPS=4*1920) parameter (NWAVE=NN*NSPS) - character*32 msg32,cmsg + character*40 msg40,cmsg character*6 mycall6 integer*1 msgbits(KK),msgbits2 integer itone(NN) @@ -11,10 +11,10 @@ subroutine foxgen_wrap(msg32,msgbits,itone) common/foxcom2/itone2(NN),msgbits2(KK) nslots=1 - i1=index(msg32,'<') - i2=index(msg32,'>') - mycall6=msg32(i1+1:i2-1)//' ' - cmsg(1)=msg32 + i1=index(msg40,'<') + i2=index(msg40,'>') + mycall6=msg40(i1+1:i2-1)//' ' + cmsg(1)=msg40 i3bit(1)=1 call foxgen() msgbits=msgbits2 diff --git a/lib/ft8/ft8sim.f90 b/lib/ft8/ft8sim.f90 index dfe38efaa..1b7bddf4c 100644 --- a/lib/ft8/ft8sim.f90 +++ b/lib/ft8/ft8sim.f90 @@ -8,7 +8,7 @@ program ft8sim parameter (NWAVE=NN*NSPS) type(hdr) h !Header for .wav file character arg*12,fname*17 - character msg32*32,msg*22,msgsent*22,msg0*22 + character msg40*40,msg*22,msgsent*22,msg0*22 character*6 mygrid6 logical bcontest complex c0(0:NMAX-1) @@ -30,7 +30,7 @@ program ft8sim print*,'Make nfiles negative to invoke 72-bit contest mode.' go to 999 endif - call getarg(1,msg32) !Message to be transmitted + call getarg(1,msg40) !Message to be transmitted call getarg(2,arg) read(arg,*) f0 !Frequency (only used for single-signal) call getarg(3,arg) @@ -66,18 +66,18 @@ program ft8sim txt=NN*NSPS/12000.0 ! Source-encode, then get itone() - if(index(msg32,';').le.0) then + if(index(msg40,';').le.0) then i3bit=0 - msg=msg32(1:22) + msg=msg40(1:22) call genft8(msg,mygrid6,bcontest,i3bit,msgsent,msgbits,itone) write(*,1000) f0,xdt,txt,snrdb,bw,msgsent 1000 format('f0:',f9.3,' DT:',f6.2,' TxT:',f6.1,' SNR:',f6.1, & ' BW:',f4.1,2x,a22) else - call foxgen_wrap(msg32,msgbits,itone) - write(*,1001) f0,xdt,txt,snrdb,bw,msg32 + call foxgen_wrap(msg40,msgbits,itone) + write(*,1001) f0,xdt,txt,snrdb,bw,msg40 1001 format('f0:',f9.3,' DT:',f6.2,' TxT:',f6.1,' SNR:',f6.1, & - ' BW:',f4.1,2x,a32) + ' BW:',f4.1,2x,a40) endif write(*,'(28i1,1x,28i1)') msgbits(1:56) diff --git a/mainwindow.cpp b/mainwindow.cpp index e3f527973..3f8f995bf 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -2740,7 +2740,7 @@ void::MainWindow::fast_decode_done() if(m_mode=="JT9" or m_mode=="MSK144") { // find and extract any report for myCall bool stdMsg = decodedtext.report(m_baseCall, - Radio::base_callsign(ui->dxCallEntry->text()), m_rptRcvd); + Radio::base_callsign(ui->dxCallEntry->text()), m_rptRcvd); // extract details and send to PSKreporter if (stdMsg) pskPost (decodedtext); @@ -2793,6 +2793,7 @@ void MainWindow::readFromStdout() //readFromStdout { while(proc_jt9.canReadLine()) { QByteArray t=proc_jt9.readLine(); + if(m_mode=="FT8" and !m_config.bHound() and t.contains(";")) continue; // qint64 ms=QDateTime::currentMSecsSinceEpoch() - m_msec0; // qDebug() << "A" << ms << t; bool bAvgMsg=false; @@ -7331,7 +7332,8 @@ void MainWindow::houndCallers() //Don't list a hound already in the queue if(!ui->textBrowser4->toPlainText().contains(paddedHoundCall)) { if(m_loggedByFox[houndCall].contains(m_lastBand) and - ui->cbNoDupes->isChecked()) continue; //already logged on this band + ui->cbNoDupes->isChecked()) continue; //already logged on this band + if(m_foxQSO.contains(houndCall)) continue; //still in the QSO map bool bmatch=false; for(int i=0; i7) m_foxMsgToBeSent[i]=m_foxMsgSent[i].mid(0,i1-1) + " RR73"; - } else { - m_foxMsgToBeSent[i]=m_foxMsgSent[i]; - } - } + m_foxQSO[houndCall].rcvd=rptRcvd.mid(1); //Save Fox's report for the log + m_foxRR73Queue.enqueue(houndCall); //Request RR73 to be sent to houndCall } void MainWindow::foxTxSequencer() @@ -7390,114 +7385,102 @@ void MainWindow::foxTxSequencer() * foxgen() to generate and accumulate the corresponding waveform. */ - for(int i=0; i " + rpt; //Tx msg } - int i1=m_foxMsgToBeSent[i].indexOf(";"); - if(i1>0) m_foxMsgToBeSent[i]=m_foxMsgToBeSent[i].mid(i1+2); - -TxTimeout: - QString fm; //Fox message to be transmitted in this slot - fm=m_foxMsgToBeSent[i]; //Default, if available - if(fm=="" or fm.mid(0,3)=="CQ ") { - if(!m_houndQueue.isEmpty()) { - QString t=m_houndQueue.dequeue(); //Fetch new hound call from queue - m_houndCall[i]=t.mid(0,6).trimmed(); //Save hound call for potential logging - m_houndGrid[i]=t.mid(11,4); //Also hound grid - rm_tb4(m_houndCall[i]); //Remove him from tb4 - QString rpt=t.mid(7,3); //Report to send him - fm= m_houndCall[i] + " " + m_config.my_callsign() + " " + rpt; //Tx message - } else { //If no hound in queue, we call CQ - fm=ui->comboBoxCQ->currentText() + " " + m_config.my_callsign(); - if(!fm.contains("/")) fm += " " + m_config.my_grid().mid(0,4); - } + // Log this QSO! + m_hisCall=hc1; + m_hisGrid=m_foxQSO[hc1].grid; + m_rptSent=m_foxQSO[hc1].sent; + m_rptRcvd=m_foxQSO[hc1].rcvd; + qDebug() << "Logged by Fox:" << islot << m_hisCall << m_hisGrid << m_rptSent + << m_rptRcvd << m_lastBand; + QDateTime logTime {QDateTime::currentDateTimeUtc ()}; + QString logLine=logTime.toString("yyyy-MM-dd hh:mm") + " " + m_hisCall + + " " + m_hisGrid + " " + m_rptSent + " " + m_rptRcvd + " " + m_lastBand; + if(m_msgAvgWidget != NULL and m_msgAvgWidget->isVisible()) { + m_msgAvgWidget->foxAddLog(logLine); } + on_logQSOButton_clicked(); + m_loggedByFox[hc1] += (m_lastBand + " "); + if(m_foxQSOqueue.contains(hc1)) m_foxQSOqueue.removeOne(hc1); - if(fm.contains(" RR73")) { -// Log this QSO! - m_hisCall=m_houndCall[i]; - m_hisGrid=m_houndGrid[i]; - m_rptSent=m_houndRptSent[i]; - m_rptRcvd=m_houndRptRcvd[i]; - qDebug() << "Logged by Fox:" << i << m_hisCall << m_hisGrid << m_rptSent - << m_rptRcvd << m_lastBand; + islot++; + //Generate tx waveform + foxGenWaveform(islot-1,fm); + if(islot >= m_Nslots) goto Transmit; + } - QDateTime now {QDateTime::currentDateTimeUtc ()}; - QString logLine=now.toString("yyyy-MM-dd hh:mm") + " " + m_hisCall + - " " + m_hisGrid + " " + m_rptSent + " " + m_rptRcvd + " " + m_lastBand; - if(m_msgAvgWidget != NULL and m_msgAvgWidget->isVisible()) { - m_msgAvgWidget->foxAddLog(logLine); - } +//One or more Tx slots are still available + while (!m_foxQSOqueue.isEmpty()) { + //should limit repeat transmissions here + hc1=m_foxQSOqueue.dequeue(); //Recover hound callsign from QSO queue + m_foxQSOqueue.enqueue(hc1); //Put him back in, at the end + fm = hc1 + " " + m_config.my_callsign() + " " + m_foxQSO[hc1].sent; //Tx msg + islot++; + //Generate tx waveform + foxGenWaveform(islot-1,fm); + if(islot >= m_Nslots) goto Transmit; + } - on_logQSOButton_clicked(); - m_loggedByFox[m_hisCall] += (m_lastBand + " "); +//One or more Tx slots are still available + while (!m_houndQueue.isEmpty()) { + t=m_houndQueue.dequeue(); //Fetch new hound from queue + hc1=t.mid(0,6).trimmed(); //hound call + m_foxQSOqueue.enqueue(hc1); //Put him in the QSO queue + m_foxQSO[hc1].grid=t.mid(11,4); //hound grid + rpt=t.mid(7,3); + m_foxQSO[hc1].sent=rpt; //Report to send him + m_foxQSO[hc1].t0=now; //QSO start time + rm_tb4(hc1); //Remove this hound from tb4 + fm = hc1 + " " + m_config.my_callsign() + " " + rpt; //Tx msg + islot++; + //Generate tx waveform + foxGenWaveform(islot-1,fm); + if(islot >= m_Nslots) goto Transmit; + } -//Find someone to call next - if(!m_houndQueue.isEmpty()) { - QString t=m_houndQueue.dequeue(); //Fetch next hound - m_houndCall[i]=t.mid(0,6).trimmed(); //Save hound call - m_houndGrid[i]=t.mid(11,4); //Also hound grid - rm_tb4(m_houndCall[i]); //Remove the call from tb4 - QString rpt=t.mid(7,3); //Report to send him - fm=fm.mid(0,6) + " RR73; " + m_houndCall[i] + " <" + m_config.my_callsign() + - "> " + rpt; - } else { - //Default to a standard (i3bit=0) message if queue is empty - fm=m_houndCall[i] + " " + m_config.my_callsign() + " RR73"; - m_houndCall[i]=""; - m_houndGrid[i]=""; - } - } + if(islot==0) { + //No tx message generated yet, so we'll call CQ + fm=ui->comboBoxCQ->currentText() + " " + m_config.my_callsign(); + if(!fm.contains("/")) fm += " " + m_config.my_grid().mid(0,4); + islot++; + foxGenWaveform(islot-1,fm); + } - if(!fm.contains(";")) { - fm.remove("<"); - fm.remove(">"); - } +Transmit: + foxcom_.nslots=islot; + QString foxCall=m_config.my_callsign() + " "; + strncpy(&foxcom_.mycall[0], foxCall.toLatin1(),6); //Copy Fox callsign into foxcom_ + foxgen_(); - if(m_houndCall[i]!=m_houndCall0[i]) m_nFoxMsgTimes[i]=0; //Reset the repeat counter - m_houndCall0[i]=m_houndCall[i]; - m_nFoxMsgTimes[i]++; - -// Check for Tx message timeout - if(ui->sbMaxRepeats->value() > 0 and m_nFoxMsgTimes[i] > ui->sbMaxRepeats->value() - and !fm.contains("CQ ")) { - m_houndCall[i]=""; - m_houndGrid[i]=""; - m_nFoxMsgTimes[i]=0; - m_foxMsgToBeSent[i]=""; - goto TxTimeout; - } - -//Send Tx message to right window - fm += " "; - fm=fm.mid(0,32); - QString txModeArg; - txModeArg.sprintf("FT8fox %d %2d",i+1,m_nFoxMsgTimes[i]); - ui->decodedTextBrowser2->displayTransmittedText(fm.trimmed(), txModeArg, - 300+60*i,m_config.color_TxMsg(),m_bFastMode); - -//Generate and accumulate the Tx waveform - foxcom_.i3bit[i]=0; - if(fm.indexOf("<")>0) foxcom_.i3bit[i]=1; - strncpy(&foxcom_.cmsg[i][0], fm.toLatin1(),32); //Copy this message into cmsg[i] - m_foxMsgSent[i]=fm.trimmed(); //What was actually sent - - i1=fm.indexOf(";"); - if(i1>0) fm=fm.mid(i1+2); //Remove the "houndCall RR73;" - m_foxMsgToBeSent[i]=fm; - - i1=qMax(fm.indexOf("+"),fm.indexOf("-")); - if(i1>6) { - m_houndRptSent[i]=fm.mid(i1,3); //Report sent to Hound in slot i + for(auto a: m_foxQSO.keys()) { + int ageSec=now-m_foxQSO[a].t0; + if(ageSec > 60) { //60 ==> max 4 calls (0 30 60 90) to a new Fox + m_foxQSO.remove(a); + m_foxQSOqueue.removeOne(a); + } else { +// qDebug() << "Age:" << a << ageSec; } } - foxcom_.nslots=m_Nslots; - QString mycall6=m_config.my_callsign() + " "; - strncpy(&foxcom_.mycall[0], mycall6.toLatin1(),6); //Copy mycall into foxcom_ - foxgen_(); } void MainWindow::rm_tb4(QString houndCall) @@ -7534,3 +7517,13 @@ void MainWindow::doubleClickOnFoxQueue(Qt::KeyboardModifiers modifiers) } m_houndQueue.swap(tmpQueue); } + +void MainWindow::foxGenWaveform(int i,QString fm) +{ +//Generate and accumulate the Tx waveform + fm += " "; + fm=fm.mid(0,40); + foxcom_.i3bit[i]=0; + if(fm.indexOf("<")>0) foxcom_.i3bit[i]=1; + strncpy(&foxcom_.cmsg[i][0], fm.toLatin1(),40); //Copy this message into cmsg[i] +} diff --git a/mainwindow.h b/mainwindow.h index e628f676d..64b334763 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -361,7 +361,6 @@ private: Modulator * m_modulator; SoundOutput * m_soundOutput; QThread m_audioThread; - QQueue m_houndQueue; qint64 m_msErase; qint64 m_secBandChanged; @@ -574,8 +573,21 @@ private: QSet m_pfx; QSet m_sfx; + struct FoxQSO + { + QString grid; + QString sent; + QString rcvd; + qint64 t0; + }; + + QMap m_foxQSO; QMap m_loggedByFox; + QQueue m_houndQueue; + QQueue m_foxQSOqueue; + QQueue m_foxRR73Queue; + QDateTime m_dateTimeQSOOn; QDateTime m_dateTimeLastTX; @@ -678,8 +690,9 @@ private: void write_transmit_entry (QString const& file_name); void selectHound(QString t); void houndCallers(); - void foxRxSequencer(QString houndCall, QString houndGrid); + void foxRxSequencer(QString houndCall, QString rptRcvd); void foxTxSequencer(); + void foxGenWaveform(int i,QString fm); }; extern int killbyname(const char* progName);