Decoder restructuring to operate on a queue and catch up when required
This commit is contained in:
		
							parent
							
								
									5b43050a3a
								
							
						
					
					
						commit
						865cfa31f9
					
				
							
								
								
									
										384
									
								
								mainwindow.cpp
									
									
									
									
									
								
							
							
						
						
									
										384
									
								
								mainwindow.cpp
									
									
									
									
									
								
							| @ -2487,7 +2487,7 @@ void MainWindow::fixStop() | ||||
|     m_hsymStop = computeStop(m_nSubMode, m_TRperiod); | ||||
| } | ||||
| 
 | ||||
| int MainWindow::computeSubmodePeriod(int submode){ | ||||
| int MainWindow::computePeriodForSubmode(int submode){ | ||||
|     switch(submode){ | ||||
|         case Varicode::JS8CallNormal:     return JS8A_TX_SECONDS; | ||||
|         case Varicode::JS8CallFast:       return JS8B_TX_SECONDS; | ||||
| @ -2539,17 +2539,24 @@ int MainWindow::computeStop(int submode, int period){ | ||||
|     return stop; | ||||
| } | ||||
| 
 | ||||
| int MainWindow::computeCurrentCycle(int period){ | ||||
|     return m_detector->secondInPeriod() / period; | ||||
| } | ||||
| // int MainWindow::computeCurrentCycle(int period){
 | ||||
| //     return m_detector->secondInPeriod() / period;
 | ||||
| // }
 | ||||
| //
 | ||||
| // int MainWindow::computeCycleStartForDecode(int cycle, int period){
 | ||||
| //     qint32 samplesPerCycle = period * RX_SAMPLE_RATE;
 | ||||
| //     return cycle * samplesPerCycle;
 | ||||
| // }
 | ||||
| 
 | ||||
| int MainWindow::computeCycleStartForDecode(int cycle, int period){ | ||||
|     qint32 samplesPerCycle = period * RX_SAMPLE_RATE; | ||||
|     return cycle * samplesPerCycle; | ||||
| int MainWindow::computeCycleForDecode(int submode, int k){ | ||||
|     qint32 maxFrames = m_detector->period() * RX_SAMPLE_RATE; | ||||
|     qint32 cycleFrames = computeFramesPerCycleForDecode(submode); | ||||
|     qint32 currentCycle = (k / cycleFrames) % (maxFrames / cycleFrames); // we mod here so we loop back to zero correctly
 | ||||
|     return currentCycle; | ||||
| } | ||||
| 
 | ||||
| int MainWindow::computeFramesPerCycleForDecode(int submode){ | ||||
|     return computeSubmodePeriod(submode) * RX_SAMPLE_RATE; | ||||
|     return computePeriodForSubmode(submode) * RX_SAMPLE_RATE; | ||||
| } | ||||
| 
 | ||||
| int MainWindow::computeFramesNeededForDecode(int submode){ | ||||
| @ -2645,7 +2652,7 @@ void MainWindow::dataSink(qint64 frames) | ||||
| #else | ||||
|     // make sure the ssum global is reset every period cycle
 | ||||
|     static int lastCycle = -1; | ||||
|     int cycle = computeCurrentCycle(m_TRperiod); | ||||
|     int cycle = computeCycleForDecode(m_nSubMode, k); | ||||
|     if(cycle != lastCycle){ | ||||
|         qDebug() << "period loop, resetting ssum"; | ||||
|         memset(ssum, 0, sizeof(ssum)); | ||||
| @ -3958,16 +3965,14 @@ void MainWindow::on_ClrAvgButton_clicked() | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| bool MainWindow::isDecodeReady(int submode, qint32 k, qint32 k0, qint32 *pCurrentDecodeStart, qint32 *pNextDecodeStart, qint32 *pStart, qint32 *pSz){ | ||||
|     if(pCurrentDecodeStart == nullptr || pNextDecodeStart == nullptr || pStart == nullptr || pSz == nullptr){ | ||||
| bool MainWindow::isDecodeReady(int submode, qint32 k, qint32 k0, qint32 *pCurrentDecodeStart, qint32 *pNextDecodeStart, qint32 *pStart, qint32 *pSz, qint32 *pCycle){ | ||||
|     if(pCurrentDecodeStart == nullptr || pNextDecodeStart == nullptr){ | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     qint32 maxFrames = m_detector->period() * RX_SAMPLE_RATE; | ||||
| 
 | ||||
|     qint32 cycleFrames = computeFramesPerCycleForDecode(submode); | ||||
|     qint32 framesNeeded = computeFramesNeededForDecode(submode); | ||||
|     qint32 currentCycle = (k / cycleFrames) % (maxFrames / cycleFrames); // we mod here so we loop back to zero correctly
 | ||||
|     qint32 currentCycle = computeCycleForDecode(submode, k); | ||||
| 
 | ||||
|     // on buffer loop, prepare proper next decode start
 | ||||
|     if(k < k0){ | ||||
| @ -3980,8 +3985,9 @@ bool MainWindow::isDecodeReady(int submode, qint32 k, qint32 k0, qint32 *pCurren | ||||
|     if(ready){ | ||||
|         qDebug() << "-->" << submodeName(submode) << "from" << *pCurrentDecodeStart << "to" << *pCurrentDecodeStart+framesNeeded << "k" << k << "k0" << k0; | ||||
| 
 | ||||
|         *pStart = *pCurrentDecodeStart; | ||||
|         *pSz = qMax(framesNeeded, k-(*pCurrentDecodeStart)); | ||||
|         if(pCycle) *pCycle = currentCycle; | ||||
|         if(pStart) *pStart = *pCurrentDecodeStart; | ||||
|         if(pSz) *pSz = qMax(framesNeeded, k-(*pCurrentDecodeStart)); | ||||
| 
 | ||||
|         *pCurrentDecodeStart = *pNextDecodeStart; | ||||
|         *pNextDecodeStart = *pCurrentDecodeStart + cycleFrames; | ||||
| @ -3991,24 +3997,6 @@ bool MainWindow::isDecodeReady(int submode, qint32 k, qint32 k0, qint32 *pCurren | ||||
| } | ||||
| 
 | ||||
| void MainWindow::decode(){ | ||||
|     qint32 submode = m_nSubMode; | ||||
|     qint32 period = m_TRperiod; | ||||
| 
 | ||||
|     bool ready = decodeReady(submode, period, &submode, &period); | ||||
|     if(!ready){ | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     decodeStart(submode, period); | ||||
|     decodePrepareSaveAudio(submode, period); | ||||
| } | ||||
| 
 | ||||
| bool MainWindow::decodeReady(int submode, int period, int *pSubmode, int *pPeriod){ | ||||
| 
 | ||||
|     // compute the next decode for each submode
 | ||||
|     // enqueue those decodes that are "ready"
 | ||||
|     // on an interval, issue a decode
 | ||||
| 
 | ||||
|     static int k0 = 9999999; | ||||
|     int k = dec_data.params.kin; | ||||
| 
 | ||||
| @ -4016,121 +4004,194 @@ bool MainWindow::decodeReady(int submode, int period, int *pSubmode, int *pPerio | ||||
| 
 | ||||
|     if(isMessageQueuedForTransmit()){ | ||||
|         qDebug() << "--> decoder paused during transmit"; | ||||
|         return false; | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if(m_decoderBusy){ | ||||
|         qDebug() << "--> decoder busy"; | ||||
|         return false; | ||||
|     bool ready = decodeEnqueueReady(k, k0); | ||||
|     if(ready || !m_decoderQueue.isEmpty()){ | ||||
|         qDebug() << "--> decoder is ready to be run with" << m_decoderQueue.count() << "decode periods"; | ||||
|     } | ||||
| 
 | ||||
|     if(period == 0){ | ||||
|         qDebug() << "--> decoder period is zero"; | ||||
|         return false; | ||||
|     // TODO: this can be pulled out to an async process
 | ||||
|     qint32 submode = -1; | ||||
|     if(decodeProcessQueue(&submode)){ | ||||
|         decodeStart(); | ||||
|         decodePrepareSaveAudio(submode); | ||||
|     } | ||||
| 
 | ||||
|     k0=k; | ||||
| } | ||||
| 
 | ||||
| bool MainWindow::decodeEnqueueReady(qint32 k, qint32 k0){ | ||||
|     // compute the next decode for each submode
 | ||||
|     // enqueue those decodes that are "ready"
 | ||||
|     // on an interval, issue a decode
 | ||||
| 
 | ||||
|     static qint32 currentDecodeStartA = -1; | ||||
|     static qint32 nextDecodeStartA = -1; | ||||
|     qint32 startA = -1; | ||||
|     qint32 szA = -1; | ||||
|     bool couldDecodeA = isDecodeReady(Varicode::JS8CallNormal, k, k0, ¤tDecodeStartA, &nextDecodeStartA, &startA, &szA); | ||||
|     qint32 cycleA = -1; | ||||
|     bool couldDecodeA = isDecodeReady(Varicode::JS8CallNormal, k, k0, ¤tDecodeStartA, &nextDecodeStartA, &startA, &szA, &cycleA); | ||||
|     if(m_diskData){ | ||||
|         startA = 0; | ||||
|         szA = NTMAX*RX_SAMPLE_RATE-1; | ||||
|         couldDecodeA = true; | ||||
|     } | ||||
| 
 | ||||
|     static qint32 currentDecodeStartB = -1; | ||||
|     static qint32 nextDecodeStartB = -1; | ||||
|     qint32 startB = -1; | ||||
|     qint32 szB = -1; | ||||
|     bool couldDecodeB = isDecodeReady(Varicode::JS8CallFast, k, k0, ¤tDecodeStartB, &nextDecodeStartB, &startB, &szB); | ||||
|     qint32 cycleB = -1; | ||||
|     bool couldDecodeB = isDecodeReady(Varicode::JS8CallFast, k, k0, ¤tDecodeStartB, &nextDecodeStartB, &startB, &szB, &cycleB); | ||||
|     if(m_diskData){ | ||||
|         startB = 0; | ||||
|         szB = NTMAX*RX_SAMPLE_RATE-1; | ||||
|         couldDecodeB = true; | ||||
|     } | ||||
| 
 | ||||
|     static qint32 currentDecodeStartC = -1; | ||||
|     static qint32 nextDecodeStartC = -1; | ||||
|     qint32 startC = -1; | ||||
|     qint32 szC = -1; | ||||
|     bool couldDecodeC = isDecodeReady(Varicode::JS8CallTurbo, k, k0, ¤tDecodeStartC, &nextDecodeStartC, &startC, &szC); | ||||
|     qint32 cycleC = -1; | ||||
|     bool couldDecodeC = isDecodeReady(Varicode::JS8CallTurbo, k, k0, ¤tDecodeStartC, &nextDecodeStartC, &startC, &szC, &cycleC); | ||||
|     if(m_diskData){ | ||||
|         startC = 0; | ||||
|         szC = NTMAX*RX_SAMPLE_RATE-1; | ||||
|         couldDecodeC = true; | ||||
|     } | ||||
| 
 | ||||
| #if JS8_ENABLE_JS8E | ||||
|     static qint32 currentDecodeStartE = -1; | ||||
|     static qint32 nextDecodeStartE = -1; | ||||
|     qint32 startE = -1; | ||||
|     qint32 szE = -1; | ||||
|     bool couldDecodeE = isDecodeReady(Varicode::JS8CallUltraSlow, k, k0, ¤tDecodeStartE, &nextDecodeStartE, &startE, &szE); | ||||
| #endif | ||||
| 
 | ||||
|     k0 = k; | ||||
| 
 | ||||
| #if JS8_RING_BUFFER | ||||
| 
 | ||||
|     qint32 cycleE = -1; | ||||
|     bool couldDecodeE = isDecodeReady(Varicode::JS8CallUltraSlow, k, k0, ¤tDecodeStartE, &nextDecodeStartE, &startE, &szE, &cycleE); | ||||
|     if(m_diskData){ | ||||
|         dec_data.params.kposA = 0; | ||||
|         dec_data.params.kposB = 0; | ||||
|         dec_data.params.kposC = 0; | ||||
|         dec_data.params.kposE = 0; | ||||
|         dec_data.params.kszA  = NTMAX*RX_SAMPLE_RATE-1; | ||||
|         dec_data.params.kszB  = NTMAX*RX_SAMPLE_RATE-1; | ||||
|         dec_data.params.kszC  = NTMAX*RX_SAMPLE_RATE-1; | ||||
|         dec_data.params.kszE  = NTMAX*RX_SAMPLE_RATE-1; | ||||
|         dec_data.params.nsubmodes = 0; | ||||
|         couldDecodeA = true; | ||||
|         couldDecodeB = true; | ||||
|         couldDecodeC = true; | ||||
| #if JS8_ENABLE_JS8E | ||||
|         startE = 0; | ||||
|         szE = NTMAX*RX_SAMPLE_RATE-1; | ||||
|         couldDecodeE = true; | ||||
| #endif | ||||
|     } else { | ||||
|         // set the params for starting positions and sizes for decode
 | ||||
|         dec_data.params.kposA = startA; | ||||
|         dec_data.params.kposB = startB; | ||||
|         dec_data.params.kposC = startC; | ||||
| #if JS8_ENABLE_JS8E | ||||
|         dec_data.params.kposE = startE; | ||||
| #endif | ||||
|         dec_data.params.kszA  = szA; | ||||
|         dec_data.params.kszB  = szB; | ||||
|         dec_data.params.kszC  = szC; | ||||
| #if JS8_ENABLE_JS8E | ||||
|         dec_data.params.kszE  = szE; | ||||
| #endif | ||||
|         dec_data.params.nsubmodes = 0; | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
|     bool multi = ui->actionModeMultiDecoder->isChecked(); | ||||
|     int decodes = 0; | ||||
| 
 | ||||
|     if(couldDecodeA){ | ||||
|         DecodeParams d; | ||||
|         d.submode = Varicode::JS8CallNormal; | ||||
|         d.cycle = cycleA; | ||||
|         d.start = startA; | ||||
|         d.sz = szA; | ||||
|         m_decoderQueue.append(d); | ||||
|         decodes++; | ||||
|     } | ||||
| 
 | ||||
|     if(couldDecodeB){ | ||||
|         DecodeParams d; | ||||
|         d.submode = Varicode::JS8CallNormal; | ||||
|         d.cycle = cycleB; | ||||
|         d.start = startB; | ||||
|         d.sz = szB; | ||||
|         m_decoderQueue.append(d); | ||||
|         decodes++; | ||||
|     } | ||||
| 
 | ||||
|     if(couldDecodeC){ | ||||
|         DecodeParams d; | ||||
|         d.submode = Varicode::JS8CallNormal; | ||||
|         d.cycle = cycleC; | ||||
|         d.start = startC; | ||||
|         d.sz = szC; | ||||
|         m_decoderQueue.append(d); | ||||
|         decodes++; | ||||
|     } | ||||
| 
 | ||||
| #if JS8_ENABLE_JS8E | ||||
|     if(couldDecodeE && (multi || submode == Varicode::JS8CallUltraSlow)){ | ||||
|         //qDebug() << "could decode E from" << cycleSampleStartE << "to" << cycleSampleStartE + framesNeededE << "--> last decode at" << lastKE;
 | ||||
|         //lastKE = k;
 | ||||
|         submode = Varicode::JS8CallUltraSlow; | ||||
|         period = JS8E_TX_SECONDS; | ||||
|         dec_data.params.nsubmodes |= (Varicode::JS8CallUltraSlow << 1); | ||||
|     if(couldDecodeE){ | ||||
|         DecodeParams d; | ||||
|         d.submode = Varicode::JS8CallNormal; | ||||
|         d.cycle = cycleE; | ||||
|         d.start = startE; | ||||
|         d.sz = szE; | ||||
|         m_decoderQueue.append(d); | ||||
|         decodes++; | ||||
|     } | ||||
| #endif | ||||
|     if(couldDecodeC && (multi || submode == Varicode::JS8CallTurbo)){ | ||||
|         submode = Varicode::JS8CallTurbo; | ||||
|         period = JS8C_TX_SECONDS; | ||||
|         dec_data.params.nsubmodes |= (Varicode::JS8CallTurbo << 1); | ||||
|         decodes++; | ||||
|     } | ||||
|     if(couldDecodeB && (multi || submode == Varicode::JS8CallFast)){ | ||||
|         submode = Varicode::JS8CallFast; | ||||
|         period = JS8B_TX_SECONDS; | ||||
|         dec_data.params.nsubmodes |= (Varicode::JS8CallFast << 1); | ||||
|         decodes++; | ||||
|     } | ||||
|     if(couldDecodeA && (multi || submode == Varicode::JS8CallNormal)){ | ||||
|         submode = Varicode::JS8CallNormal; | ||||
|         period = JS8A_TX_SECONDS; | ||||
|         dec_data.params.nsubmodes |= (Varicode::JS8CallNormal + 1); | ||||
|         decodes++; | ||||
|     } | ||||
| 
 | ||||
|     if(pSubmode) *pSubmode=submode; | ||||
|     if(pPeriod) *pPeriod=period; | ||||
|     return decodes > 0; | ||||
| } | ||||
| 
 | ||||
|     if(!m_diskData && decodes == 0){ | ||||
| bool MainWindow::decodeProcessQueue(qint32 *pSubmode){ | ||||
|     if(m_decoderBusy){ | ||||
|         qDebug() << "--> decoder is busy!"; | ||||
|         return false; | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
|     if(m_decoderQueue.isEmpty()){ | ||||
|         qDebug() << "--> decoder has nothing to process!"; | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     int submode = -1; | ||||
|     int maxDecodes = 1; | ||||
| 
 | ||||
|     bool multi = ui->actionModeMultiDecoder->isChecked(); | ||||
|     if(multi){ | ||||
|         maxDecodes = JS8_ENABLE_JS8E ? 4 : 3; | ||||
|     } | ||||
| 
 | ||||
|     int count = m_decoderQueue.count(); | ||||
|     if(count > maxDecodes){ | ||||
|         qDebug() << "--> decoder skipping at least 1 decode cycle" << "count" << count << "max" << maxDecodes; | ||||
|     } | ||||
| 
 | ||||
|     while(!m_decoderQueue.isEmpty()){ | ||||
|         auto params = m_decoderQueue.front(); | ||||
|         m_decoderQueue.removeFirst(); | ||||
| 
 | ||||
|         // skip if we are not in multi mode and the submode doesn't equal the global submode
 | ||||
|         if(!multi && params.submode != m_nSubMode){ | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         if(submode == -1 || params.submode < submode){ | ||||
|             submode = params.submode; | ||||
|         } | ||||
| 
 | ||||
|         dec_data.params.nsubmodes = 0; | ||||
|         switch(params.submode){ | ||||
|         case Varicode::JS8CallNormal: | ||||
|             dec_data.params.kposA = params.start; | ||||
|             dec_data.params.kszA = params.sz; | ||||
|             dec_data.params.nsubmodes |= (params.submode + 1); | ||||
|             break; | ||||
|         case Varicode::JS8CallFast: | ||||
|             dec_data.params.kposB = params.start; | ||||
|             dec_data.params.kszB = params.sz; | ||||
|             dec_data.params.nsubmodes |= (params.submode << 1); | ||||
|             break; | ||||
|         case Varicode::JS8CallTurbo: | ||||
|             dec_data.params.kposC = params.start; | ||||
|             dec_data.params.kszC = params.sz; | ||||
|             dec_data.params.nsubmodes |= (params.submode << 1); | ||||
|             break; | ||||
|         case Varicode::JS8CallUltraSlow: | ||||
|             dec_data.params.kposE = params.start; | ||||
|             dec_data.params.kszE = params.sz; | ||||
|             dec_data.params.nsubmodes |= (params.submode << 1); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if(submode == -1){ | ||||
|         qDebug() << "--> decoder has no segments to decode!"; | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     int period = computePeriodForSubmode(submode); | ||||
| 
 | ||||
|     ui->DecodeButton->setChecked(true); | ||||
|     m_msec0 = DriftingDateTime::currentMSecsSinceEpoch(); | ||||
| @ -4251,11 +4312,14 @@ bool MainWindow::decodeReady(int submode, int period, int *pSubmode, int *pPerio | ||||
|     strncpy(dec_data.params.hiscall,(hisCall + "            ").toLatin1 ().constData (), 12); | ||||
|     strncpy(dec_data.params.hisgrid,(hisGrid + "      ").toLatin1 ().constData (), 6); | ||||
| 
 | ||||
|     // keep track of the minimum submode
 | ||||
|     if(pSubmode) *pSubmode = submode; | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void MainWindow::decodeStart(int submode, int period){ | ||||
|   qDebug() << "starting decode for submode" << submode << "and period" << period; | ||||
| void MainWindow::decodeStart(){ | ||||
|   qDebug() << "--> decoder starting"; | ||||
| 
 | ||||
|   //newdat=1  ==> this is new data, must do the big FFT
 | ||||
|   //nagain=1  ==> decode only at fQSO +/- Tol
 | ||||
| @ -4277,29 +4341,54 @@ void MainWindow::decodeStart(int submode, int period){ | ||||
|   decodeBusy(true); | ||||
| } | ||||
| 
 | ||||
| void MainWindow::decodePrepareSaveAudio(int submode, int period){ | ||||
| 
 | ||||
| void MainWindow::decodeBusy(bool b)                             //decodeBusy()
 | ||||
| { | ||||
|   if (!b) m_optimizingProgress.reset (); | ||||
|   m_decoderBusy=b; | ||||
|   if(m_decoderBusy){ | ||||
|     tx_status_label.setText("Decoding"); | ||||
|   } | ||||
|   ui->DecodeButton->setEnabled(!b); | ||||
|   ui->actionOpen->setEnabled(!b); | ||||
|   ui->actionOpen_next_in_directory->setEnabled(!b); | ||||
|   ui->actionDecode_remaining_files_in_directory->setEnabled(!b); | ||||
| 
 | ||||
|   statusUpdate (); | ||||
| } | ||||
| 
 | ||||
| void MainWindow::decodeDone () | ||||
| { | ||||
|   dec_data.params.nagain=0; | ||||
|   dec_data.params.ndiskdat=0; | ||||
|   m_nclearave=0; | ||||
|   QFile {m_config.temp_dir ().absoluteFilePath (".lock")}.open(QIODevice::ReadWrite); | ||||
|   ui->DecodeButton->setChecked (false); | ||||
|   decodeBusy(false); | ||||
|   m_RxLog=0; | ||||
|   m_blankLine=true; | ||||
| } | ||||
| 
 | ||||
| void MainWindow::decodePrepareSaveAudio(int submode){ | ||||
|     if(m_diskData){ | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     int period = computePeriodForSubmode(submode); | ||||
|     auto now = DriftingDateTime::currentDateTimeUtc(); | ||||
|     int n=now.time().second() % period; | ||||
|     if(n<(period/2)) n=n+period; | ||||
|     auto const& period_start=now.addSecs(-n); | ||||
|     m_fnameWE=m_config.save_directory().absoluteFilePath (period_start.toString("yyMMdd_hhmmss")); | ||||
|     m_fileToSave.clear (); | ||||
| 
 | ||||
|     if(!m_diskData) {                        //Always save; may delete later
 | ||||
|       if(m_mode=="FT8") { | ||||
|         int n=now.time().second() % period; | ||||
|         if(n<(period/2)) n=n+period; | ||||
|         auto const& period_start=now.addSecs(-n); | ||||
|         m_fnameWE=m_config.save_directory().absoluteFilePath (period_start.toString("yyMMdd_hhmmss")); | ||||
|       } else { | ||||
|         auto const& period_start = now.addSecs (-(now.time ().minute () % (period / 60)) * 60); | ||||
|         m_fnameWE=m_config.save_directory ().absoluteFilePath (period_start.toString ("yyMMdd_hhmm")); | ||||
|       } | ||||
|       m_fileToSave.clear (); | ||||
| 
 | ||||
|       if(m_saveAll or m_bAltV or (m_bDecoded and m_saveDecoded) or (m_mode!="MSK144" and m_mode!="FT8")) { | ||||
|           m_bAltV=false; | ||||
|           // the following is potential a threading hazard - not a good
 | ||||
|           // idea to pass pointer to be processed in another thread
 | ||||
|           m_saveWAVWatcher.setFuture (QtConcurrent::run (std::bind (&MainWindow::save_wave_file, | ||||
|                 this, m_fnameWE, &dec_data.d2[0], period, m_config.my_callsign(), | ||||
|                 m_config.my_grid(), m_mode, submode, m_freqNominal, m_hisCall, m_hisGrid))); | ||||
|       } | ||||
|     if(m_saveAll or m_bAltV or (m_bDecoded and m_saveDecoded)){ | ||||
|         m_bAltV=false; | ||||
|         // the following is potential a threading hazard - not a good
 | ||||
|         // idea to pass pointer to be processed in another thread
 | ||||
|         m_saveWAVWatcher.setFuture (QtConcurrent::run (std::bind (&MainWindow::save_wave_file, | ||||
|               this, m_fnameWE, &dec_data.d2[0], period, m_config.my_callsign(), | ||||
|               m_config.my_grid(), m_mode, submode, m_freqNominal, m_hisCall, m_hisGrid))); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -4390,18 +4479,6 @@ void MainWindow::resetHeartbeatTimer(bool stop){ | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void MainWindow::decodeDone () | ||||
| { | ||||
|   dec_data.params.nagain=0; | ||||
|   dec_data.params.ndiskdat=0; | ||||
|   m_nclearave=0; | ||||
|   QFile {m_config.temp_dir ().absoluteFilePath (".lock")}.open(QIODevice::ReadWrite); | ||||
|   ui->DecodeButton->setChecked (false); | ||||
|   decodeBusy(false); | ||||
|   m_RxLog=0; | ||||
|   m_blankLine=true; | ||||
| } | ||||
| 
 | ||||
| QList<int> generateOffsets(int minOffset, int maxOffset){ | ||||
|     QList<int> offsets; | ||||
| 
 | ||||
| @ -4425,7 +4502,7 @@ void MainWindow::readFromStdout()                             //readFromStdout | ||||
|         m_bDecoded = t.mid(20).trimmed().toInt() > 0; | ||||
|         int mswait=3*1000*m_TRperiod/4; | ||||
|         if(!m_diskData) killFileTimer.start(mswait); //Kill in 3/4 period
 | ||||
|         decodeDone (); | ||||
|         decodeDone(); | ||||
|         m_startAnother=m_loopall; | ||||
|         if(m_bNoMoreFiles) { | ||||
|           MessageBox::information_message(this, tr("No more files to open.")); | ||||
| @ -5011,19 +5088,6 @@ void MainWindow::on_EraseButton_clicked () | ||||
|   m_msErase=ms; | ||||
| } | ||||
| 
 | ||||
| void MainWindow::decodeBusy(bool b)                             //decodeBusy()
 | ||||
| { | ||||
|   if (!b) m_optimizingProgress.reset (); | ||||
|   m_decoderBusy=b; | ||||
|   tx_status_label.setText (m_decoderBusy ? "Decoding" : m_monitoring ? "Receiving" : ""); | ||||
|   ui->DecodeButton->setEnabled(!b); | ||||
|   ui->actionOpen->setEnabled(!b); | ||||
|   ui->actionOpen_next_in_directory->setEnabled(!b); | ||||
|   ui->actionDecode_remaining_files_in_directory->setEnabled(!b); | ||||
| 
 | ||||
|   statusUpdate (); | ||||
| } | ||||
| 
 | ||||
| //------------------------------------------------------------- //guiUpdate()
 | ||||
| void MainWindow::guiUpdate() | ||||
| { | ||||
| @ -7273,7 +7337,7 @@ void MainWindow::on_actionJS8_triggered() | ||||
|   m_wideGraph->setModeTx(m_modeTx); | ||||
|   VHF_features_enabled(bVHF); | ||||
|   ui->cbAutoSeq->setChecked(true); | ||||
|   m_TRperiod = computeSubmodePeriod(m_nSubMode); | ||||
|   m_TRperiod = computePeriodForSubmode(m_nSubMode); | ||||
|   m_wideGraph->show(); | ||||
|   ui->decodedTextLabel2->setText("  UTC   dB   DT Freq    Message"); | ||||
|   m_modulator->setTRPeriod(m_TRperiod); // TODO - not thread safe
 | ||||
| @ -10105,7 +10169,7 @@ void MainWindow::processIdleActivity() { | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         if(last.utcTimestamp.secsTo(now) < computeSubmodePeriod(last.submode)){ | ||||
|         if(last.utcTimestamp.secsTo(now) < computePeriodForSubmode(last.submode)){ | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										26
									
								
								mainwindow.h
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								mainwindow.h
									
									
									
									
									
								
							| @ -229,11 +229,13 @@ private slots: | ||||
|   void on_actionCopyright_Notice_triggered(); | ||||
|   void on_DecodeButton_clicked (bool); | ||||
|   void decode(); | ||||
|   bool isDecodeReady(int submode, qint32 k, qint32 k0, qint32 *pCurrentDecodeStart, qint32 *pNextDecodeStart, qint32 *pStart, qint32 *pSz); | ||||
|   bool decodeReady(int submode, int period, int *pSubmode, int *pPeriod); | ||||
|   void decodeStart(int submode, int period); | ||||
|   void decodePrepareSaveAudio(int submode, int period); | ||||
|   bool isDecodeReady(int submode, qint32 k, qint32 k0, qint32 *pCurrentDecodeStart, qint32 *pNextDecodeStart, qint32 *pStart, qint32 *pSz, qint32 *pCycle); | ||||
|   bool decodeEnqueueReady(qint32 k, qint32 k0); | ||||
|   bool decodeProcessQueue(qint32 *pSubmode); | ||||
|   void decodeStart(); | ||||
|   void decodePrepareSaveAudio(int submode); | ||||
|   void decodeBusy(bool b); | ||||
|   void decodeDone (); | ||||
|   void on_EraseButton_clicked(); | ||||
|   void set_dateTimeQSO(int m_ntx); | ||||
|   void set_ntx(int n); | ||||
| @ -810,6 +812,14 @@ private: | ||||
|       QDateTime date; | ||||
|   }; | ||||
| 
 | ||||
|   struct DecodeParams { | ||||
|       int submode; | ||||
|       int cycle; | ||||
|       int start; | ||||
|       int sz; | ||||
|   }; | ||||
| 
 | ||||
|   QQueue<DecodeParams> m_decoderQueue; | ||||
|   QMap<QString, int> m_messageDupeCache; // message frame -> freq offset seen
 | ||||
|   QMap<QString, QVariant> m_showColumnsCache; // table column:key -> show boolean
 | ||||
|   QMap<QString, QVariant> m_sortCache; // table key -> sort by
 | ||||
| @ -927,10 +937,11 @@ private: | ||||
|   void stub(); | ||||
|   void statusChanged(); | ||||
|   void fixStop(); | ||||
|   int computeSubmodePeriod(int submode); | ||||
|   int computePeriodForSubmode(int submode); | ||||
|   int computeStop(int submode, int period); | ||||
|   int computeCurrentCycle(int period); | ||||
|   int computeCycleStartForDecode(int cycle, int period); | ||||
|   //int computeCurrentCycle(int period);
 | ||||
|   //int computeCycleStartForDecode(int cycle, int period);
 | ||||
|   int computeCycleForDecode(int submode, int k); | ||||
|   int computeFramesPerCycleForDecode(int submode); | ||||
|   int computeFramesNeededForDecode(int submode); | ||||
|   bool shortList(QString callsign); | ||||
| @ -1017,7 +1028,6 @@ private: | ||||
|   void resetAutomaticIntervalTransmissions(bool stopCQ, bool stopHB); | ||||
|   void resetCQTimer(bool stop); | ||||
|   void resetHeartbeatTimer(bool stop); | ||||
|   void decodeDone (); | ||||
|   void subProcessFailed (QProcess *, int exit_code, QProcess::ExitStatus); | ||||
|   void subProcessError (QProcess *, QProcess::ProcessError); | ||||
|   void statusUpdate () const; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Jordan Sherer
						Jordan Sherer