Changed decode timing to better decode signals
This commit is contained in:
		
							parent
							
								
									b54e3e89aa
								
							
						
					
					
						commit
						305c0fdb12
					
				| @ -9,13 +9,12 @@ | |||||||
| #define JS8_USE_REFSPEC    0       // compute the signal refspec
 | #define JS8_USE_REFSPEC    0       // compute the signal refspec
 | ||||||
| #define JS8_USE_IHSYM      0       // compute ihsym manually instead of from symspec
 | #define JS8_USE_IHSYM      0       // compute ihsym manually instead of from symspec
 | ||||||
| #define JS8_RING_BUFFER    1       // use a ring buffer instead of clearing the decode frames
 | #define JS8_RING_BUFFER    1       // use a ring buffer instead of clearing the decode frames
 | ||||||
| #define JS8_DECODER_E2S    0       // decode every 2 seconds instead of at the half symbol stop
 |  | ||||||
| 
 | 
 | ||||||
| #define JS8_NUM_SYMBOLS    79 | #define JS8_NUM_SYMBOLS    79 | ||||||
| #define JS8_ENABLE_JS8A    1 | #define JS8_ENABLE_JS8A    1 | ||||||
| #define JS8_ENABLE_JS8B    1 | #define JS8_ENABLE_JS8B    1 | ||||||
| #define JS8_ENABLE_JS8C    1 | #define JS8_ENABLE_JS8C    1 | ||||||
| #define JS8_ENABLE_JS8E    1 | #define JS8_ENABLE_JS8E    0 | ||||||
| 
 | 
 | ||||||
| #define JS8A_SYMBOL_SAMPLES 1920 | #define JS8A_SYMBOL_SAMPLES 1920 | ||||||
| #define JS8A_TX_SECONDS     15 | #define JS8A_TX_SECONDS     15 | ||||||
|  | |||||||
							
								
								
									
										212
									
								
								mainwindow.cpp
									
									
									
									
									
								
							
							
						
						
									
										212
									
								
								mainwindow.cpp
									
									
									
									
									
								
							| @ -1235,7 +1235,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, | |||||||
|         auto items = m_bandActivity.value(selectedOffset); |         auto items = m_bandActivity.value(selectedOffset); | ||||||
|         if(!items.isEmpty()){ |         if(!items.isEmpty()){ | ||||||
|             auto speed = items.last().speed; |             auto speed = items.last().speed; | ||||||
|             int submode = speedNameMode(speed); |             int submode = speedNameToSubmode(speed); | ||||||
|             if(submode != m_nSubMode){ |             if(submode != m_nSubMode){ | ||||||
|                 auto qrqAction = menu->addAction(QString("Jump to %1%2 speed").arg(speed.left(1)).arg(speed.mid(1).toLower())); |                 auto qrqAction = menu->addAction(QString("Jump to %1%2 speed").arg(speed.left(1)).arg(speed.mid(1).toLower())); | ||||||
|                 connect(qrqAction, &QAction::triggered, this, [this, submode](){ |                 connect(qrqAction, &QAction::triggered, this, [this, submode](){ | ||||||
| @ -1466,7 +1466,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|             auto speed = m_callActivity[selectedCall].speed; |             auto speed = m_callActivity[selectedCall].speed; | ||||||
|             int submode = speedNameMode(speed); |             int submode = speedNameToSubmode(speed); | ||||||
|             if(submode != m_nSubMode){ |             if(submode != m_nSubMode){ | ||||||
|                 auto qrqAction = menu->addAction(QString("Jump to %1%2 speed").arg(speed.left(1)).arg(speed.mid(1).toLower())); |                 auto qrqAction = menu->addAction(QString("Jump to %1%2 speed").arg(speed.left(1)).arg(speed.mid(1).toLower())); | ||||||
|                 connect(qrqAction, &QAction::triggered, this, [this, submode](){ |                 connect(qrqAction, &QAction::triggered, this, [this, submode](){ | ||||||
| @ -2534,8 +2534,6 @@ int MainWindow::computeStop(int submode, int period){ | |||||||
| #endif | #endif | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     } |     } | ||||||
|     stop = qFloor(float(symbolSamples*JS8_NUM_SYMBOLS + threshold*RX_SAMPLE_RATE)/(float)m_nsps*2.0); |     stop = qFloor(float(symbolSamples*JS8_NUM_SYMBOLS + threshold*RX_SAMPLE_RATE)/(float)m_nsps*2.0); | ||||||
| #endif | #endif | ||||||
| @ -2552,8 +2550,16 @@ int MainWindow::computeCycleStartForDecode(int cycle, int period){ | |||||||
|     return cycle * samplesPerCycle; |     return cycle * samplesPerCycle; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int MainWindow::computeFramesNeededForDecode(int submode, int period){ | int MainWindow::computeFramesNeededForDecode(int submode, int /*period*/){ | ||||||
|     return computeStop(submode, period) * m_nsps / 2.0; |     int symbolSamples = 0; | ||||||
|  |     float threshold = 0.0; | ||||||
|  |     switch(submode){ | ||||||
|  |         case Varicode::JS8CallNormal:    symbolSamples = JS8A_SYMBOL_SAMPLES; threshold = JS8A_START_DELAY_MS/1000.0 + 0.5; break; | ||||||
|  |         case Varicode::JS8CallFast:      symbolSamples = JS8B_SYMBOL_SAMPLES; threshold = JS8B_START_DELAY_MS/1000.0 + 0.5; break; | ||||||
|  |         case Varicode::JS8CallTurbo:     symbolSamples = JS8C_SYMBOL_SAMPLES; threshold = JS8C_START_DELAY_MS/1000.0 + 0.5; break; | ||||||
|  |         case Varicode::JS8CallUltraSlow: symbolSamples = JS8E_SYMBOL_SAMPLES; threshold = JS8E_START_DELAY_MS/1000.0 + 0.5; break; | ||||||
|  |     } | ||||||
|  |     return int(qFloor(float(symbolSamples*JS8_NUM_SYMBOLS + threshold*RX_SAMPLE_RATE))); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| //-------------------------------------------------------------- dataSink()
 | //-------------------------------------------------------------- dataSink()
 | ||||||
| @ -2670,13 +2676,7 @@ void MainWindow::dataSink(qint64 frames) | |||||||
|     dec_data.params.nagain=0; |     dec_data.params.nagain=0; | ||||||
|     dec_data.params.nzhsym=m_ihsym; |     dec_data.params.nzhsym=m_ihsym; | ||||||
| 
 | 
 | ||||||
|     // only decode once per second
 |     qDebug() << "dataSink k" << k; | ||||||
|     static int lastn = -1; |  | ||||||
|     int n = m_detector->secondInPeriod(); |  | ||||||
|     if(n == lastn){ |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|     lastn = n; |  | ||||||
| 
 | 
 | ||||||
|     decode(); |     decode(); | ||||||
| } | } | ||||||
| @ -3265,7 +3265,9 @@ void MainWindow::setSubmode(int submode){ | |||||||
|     on_actionJS8_triggered(); |     on_actionJS8_triggered(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int MainWindow::speedNameMode(QString speed){ | int MainWindow::speedNameToSubmode(QString speedName){ | ||||||
|  |     auto speed = speedName.toUpper().trimmed(); | ||||||
|  | 
 | ||||||
|     if(speed == modeSpeedName(Varicode::JS8CallNormal)){ |     if(speed == modeSpeedName(Varicode::JS8CallNormal)){ | ||||||
|         return Varicode::JS8CallNormal; |         return Varicode::JS8CallNormal; | ||||||
|     } |     } | ||||||
| @ -3278,7 +3280,8 @@ int MainWindow::speedNameMode(QString speed){ | |||||||
|     if(speed == modeSpeedName(Varicode::JS8CallUltraSlow)){ |     if(speed == modeSpeedName(Varicode::JS8CallUltraSlow)){ | ||||||
|         return Varicode::JS8CallUltraSlow; |         return Varicode::JS8CallUltraSlow; | ||||||
|     } |     } | ||||||
|     return -1; |     // default to the current submode
 | ||||||
|  |     return m_nSubMode; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -3979,44 +3982,55 @@ void MainWindow::decode(){ | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool MainWindow::decodeReady(int submode, int period, int *pSubmode, int *pPeriod){ | bool MainWindow::decodeReady(int submode, int period, int *pSubmode, int *pPeriod){ | ||||||
|  |     qDebug() << "decoder checking if ready..."; | ||||||
|  | 
 | ||||||
|     if(m_decoderBusy){ |     if(m_decoderBusy){ | ||||||
|  |         qDebug() << "decoder busy"; | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if(period == 0){ |     if(period == 0){ | ||||||
|  |         qDebug() << "decoder period is zero"; | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| #if JS8_RING_BUFFER | #if JS8_RING_BUFFER | ||||||
|     int k = dec_data.params.kin; |     int k = dec_data.params.kin; | ||||||
| 
 | 
 | ||||||
|     qint32 cycleSampleStartA = computeCycleStartForDecode(computeCurrentCycle(JS8A_TX_SECONDS), JS8A_TX_SECONDS); |     static int lastKA = -1; | ||||||
|  |     static qint32 lastCycleA = -1; | ||||||
|  |     qint32 cycleA = computeCurrentCycle(JS8A_TX_SECONDS); | ||||||
|  |     qint32 cycleSampleStartA = computeCycleStartForDecode(cycleA, JS8A_TX_SECONDS); | ||||||
|     qint32 framesNeededA = computeFramesNeededForDecode(Varicode::JS8CallNormal, JS8A_TX_SECONDS); |     qint32 framesNeededA = computeFramesNeededForDecode(Varicode::JS8CallNormal, JS8A_TX_SECONDS); | ||||||
|     bool couldDecodeA = k >= cycleSampleStartA + framesNeededA; |     bool couldDecodeA = cycleA != lastCycleA && k >= cycleSampleStartA + framesNeededA; | ||||||
|  |     if(couldDecodeA) lastCycleA = cycleA; | ||||||
| 
 | 
 | ||||||
|     qint32 cycleSampleStartB = computeCycleStartForDecode(computeCurrentCycle(JS8B_TX_SECONDS), JS8B_TX_SECONDS); |     static int lastKB = -1; | ||||||
|  |     static qint32 lastCycleB = -1; | ||||||
|  |     qint32 cycleB = computeCurrentCycle(JS8B_TX_SECONDS); | ||||||
|  |     qint32 cycleSampleStartB = computeCycleStartForDecode(cycleB, JS8B_TX_SECONDS); | ||||||
|     qint32 framesNeededB = computeFramesNeededForDecode(Varicode::JS8CallFast, JS8B_TX_SECONDS); |     qint32 framesNeededB = computeFramesNeededForDecode(Varicode::JS8CallFast, JS8B_TX_SECONDS); | ||||||
|     bool couldDecodeB = k >= cycleSampleStartB + framesNeededB; |     bool couldDecodeB = cycleB != lastCycleB && k >= cycleSampleStartB + framesNeededB; | ||||||
|  |     if(couldDecodeB) lastCycleB = cycleB; | ||||||
| 
 | 
 | ||||||
|     qint32 cycleSampleStartC = computeCycleStartForDecode(computeCurrentCycle(JS8C_TX_SECONDS), JS8C_TX_SECONDS); |     static int lastKC = -1; | ||||||
|  |     static qint32 lastCycleC = -1; | ||||||
|  |     qint32 cycleC = computeCurrentCycle(JS8C_TX_SECONDS); | ||||||
|  |     qint32 cycleSampleStartC = computeCycleStartForDecode(cycleC, JS8C_TX_SECONDS); | ||||||
|     qint32 framesNeededC = computeFramesNeededForDecode(Varicode::JS8CallTurbo, JS8C_TX_SECONDS); |     qint32 framesNeededC = computeFramesNeededForDecode(Varicode::JS8CallTurbo, JS8C_TX_SECONDS); | ||||||
|     bool couldDecodeC = k >= cycleSampleStartC + framesNeededC; |     bool couldDecodeC = cycleC != lastCycleC && k >= cycleSampleStartC + framesNeededC; | ||||||
|  |     if(couldDecodeC) lastCycleC = cycleC; | ||||||
| 
 | 
 | ||||||
| #if JS8_ENABLE_JS8E | #if JS8_ENABLE_JS8E | ||||||
|     int cycleE = computeCurrentCycle(JS8E_TX_SECONDS); |     static int lastKE = -1; | ||||||
|  |     static qint32 lastCycleE = -1; | ||||||
|  |     qint32 cycleE = computeCurrentCycle(JS8E_TX_SECONDS); | ||||||
|     qint32 cycleSampleStartE = computeCycleStartForDecode(cycleE, JS8E_TX_SECONDS); |     qint32 cycleSampleStartE = computeCycleStartForDecode(cycleE, JS8E_TX_SECONDS); | ||||||
|     qint32 framesNeededE = computeFramesNeededForDecode(Varicode::JS8CallUltraSlow, JS8E_TX_SECONDS); |     qint32 framesNeededE = computeFramesNeededForDecode(Varicode::JS8CallUltraSlow, JS8E_TX_SECONDS); | ||||||
|     bool couldDecodeE = k >= cycleSampleStartE + framesNeededE; |     bool couldDecodeE = cycleE != lastCycleE && k >= cycleSampleStartE + framesNeededE; | ||||||
| 
 |     if(couldDecodeE) lastCycleE = cycleE; | ||||||
|     // protect against multiple decodes for the same cycle
 |  | ||||||
|     static int lastDecodeCycleE = -1; |  | ||||||
|     if(couldDecodeE){ |  | ||||||
|         if(cycleE == lastDecodeCycleE){ |  | ||||||
|             couldDecodeE = false; |  | ||||||
|         } |  | ||||||
|         lastDecodeCycleE = cycleE; |  | ||||||
|     } |  | ||||||
| #else | #else | ||||||
|  |     static int lastKE = -1; | ||||||
|     qint32 cycleSampleStartE = 0; |     qint32 cycleSampleStartE = 0; | ||||||
|     qint32 framesNeededE = 0; |     qint32 framesNeededE = 0; | ||||||
|     bool couldDecodeE = false; |     bool couldDecodeE = false; | ||||||
| @ -4055,28 +4069,32 @@ bool MainWindow::decodeReady(int submode, int period, int *pSubmode, int *pPerio | |||||||
|     int decodes = 0; |     int decodes = 0; | ||||||
| 
 | 
 | ||||||
|     if(couldDecodeE && (multi || submode == Varicode::JS8CallUltraSlow)){ |     if(couldDecodeE && (multi || submode == Varicode::JS8CallUltraSlow)){ | ||||||
|         qDebug() << "could decode E from" << cycleSampleStartE << "to" << cycleSampleStartE + framesNeededE; |         qDebug() << "could decode E from" << cycleSampleStartE << "to" << cycleSampleStartE + framesNeededE << "--> last decode at" << lastKE; | ||||||
|  |         lastKE = k; | ||||||
|         submode = Varicode::JS8CallUltraSlow; |         submode = Varicode::JS8CallUltraSlow; | ||||||
|         period = JS8E_TX_SECONDS; |         period = JS8E_TX_SECONDS; | ||||||
|         dec_data.params.nsubmodes |= (Varicode::JS8CallUltraSlow << 1); |         dec_data.params.nsubmodes |= (Varicode::JS8CallUltraSlow << 1); | ||||||
|         decodes++; |         decodes++; | ||||||
|     } |     } | ||||||
|     if(couldDecodeC && (multi || submode == Varicode::JS8CallTurbo)){ |     if(couldDecodeC && (multi || submode == Varicode::JS8CallTurbo)){ | ||||||
|         qDebug() << "could decode C from" << cycleSampleStartC << "to" << cycleSampleStartC + framesNeededC; |         qDebug() << "could decode C from" << cycleSampleStartC << "to" << cycleSampleStartC + framesNeededC << "--> last decode at" << lastKC; | ||||||
|  |         lastKC = k; | ||||||
|         submode = Varicode::JS8CallTurbo; |         submode = Varicode::JS8CallTurbo; | ||||||
|         period = JS8C_TX_SECONDS; |         period = JS8C_TX_SECONDS; | ||||||
|         dec_data.params.nsubmodes |= (Varicode::JS8CallTurbo << 1); |         dec_data.params.nsubmodes |= (Varicode::JS8CallTurbo << 1); | ||||||
|         decodes++; |         decodes++; | ||||||
|     } |     } | ||||||
|     if(couldDecodeB && (multi || submode == Varicode::JS8CallFast)){ |     if(couldDecodeB && (multi || submode == Varicode::JS8CallFast)){ | ||||||
|         qDebug() << "could decode B from" << cycleSampleStartB << "to" << cycleSampleStartB + framesNeededB; |         qDebug() << "could decode B from" << cycleSampleStartB << "to" << cycleSampleStartB + framesNeededB << "--> last decode at" << lastKB; | ||||||
|  |         lastKB = k; | ||||||
|         submode = Varicode::JS8CallFast; |         submode = Varicode::JS8CallFast; | ||||||
|         period = JS8B_TX_SECONDS; |         period = JS8B_TX_SECONDS; | ||||||
|         dec_data.params.nsubmodes |= (Varicode::JS8CallFast << 1); |         dec_data.params.nsubmodes |= (Varicode::JS8CallFast << 1); | ||||||
|         decodes++; |         decodes++; | ||||||
|     } |     } | ||||||
|     if(couldDecodeA && (multi || submode == Varicode::JS8CallNormal)){ |     if(couldDecodeA && (multi || submode == Varicode::JS8CallNormal)){ | ||||||
|         qDebug() << "could decode A from" << cycleSampleStartA << "to" << cycleSampleStartA + framesNeededA; |         qDebug() << "could decode A from" << cycleSampleStartA << "to" << cycleSampleStartA + framesNeededA << "--> last decode at" << lastKA; | ||||||
|  |         lastKA = k; | ||||||
|         submode = Varicode::JS8CallNormal; |         submode = Varicode::JS8CallNormal; | ||||||
|         period = JS8A_TX_SECONDS; |         period = JS8A_TX_SECONDS; | ||||||
|         dec_data.params.nsubmodes |= (Varicode::JS8CallNormal + 1); |         dec_data.params.nsubmodes |= (Varicode::JS8CallNormal + 1); | ||||||
| @ -4087,24 +4105,11 @@ bool MainWindow::decodeReady(int submode, int period, int *pSubmode, int *pPerio | |||||||
|     if(pPeriod) *pPeriod=period; |     if(pPeriod) *pPeriod=period; | ||||||
| 
 | 
 | ||||||
|     if(!m_diskData && decodes == 0){ |     if(!m_diskData && decodes == 0){ | ||||||
|  |         qDebug() << "decoder has no modes ready for decoding"; | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #if JS8_DECODER_E2S |  | ||||||
|     // TODO: e2s works until the signal crosses a detector period boundary :/
 |  | ||||||
| 
 |  | ||||||
|     // decoding every 2 seconds
 |  | ||||||
|     static int lastn = 0; |  | ||||||
|     qint32 n = m_detector->secondInPeriod(); |  | ||||||
|     if(!m_diskData && (n == lastn || n % 2 != 0)){ |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     cycleSampleStart = qMax(0, dec_data.params.kin - framesNeeded); |  | ||||||
|     lastn = n; |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|     ui->DecodeButton->setChecked(true); |     ui->DecodeButton->setChecked(true); | ||||||
|     m_msec0 = DriftingDateTime::currentMSecsSinceEpoch(); |     m_msec0 = DriftingDateTime::currentMSecsSinceEpoch(); | ||||||
| 
 | 
 | ||||||
| @ -4224,71 +4229,6 @@ bool MainWindow::decodeReady(int submode, int period, int *pSubmode, int *pPerio | |||||||
|     strncpy(dec_data.params.hiscall,(hisCall + "            ").toLatin1 ().constData (), 12); |     strncpy(dec_data.params.hiscall,(hisCall + "            ").toLatin1 ().constData (), 12); | ||||||
|     strncpy(dec_data.params.hisgrid,(hisGrid + "      ").toLatin1 ().constData (), 6); |     strncpy(dec_data.params.hisgrid,(hisGrid + "      ").toLatin1 ().constData (), 6); | ||||||
| 
 | 
 | ||||||
| #if 0 |  | ||||||
|     // for waterfall computation
 |  | ||||||
|     memset(dec_data.d1, 0, sizeof(dec_data.d1)); |  | ||||||
| 
 |  | ||||||
|     int start = 0; |  | ||||||
|     int frames = 0; |  | ||||||
|     if(m_nSubMode == Varicode::JS8CallNormal){ |  | ||||||
|         start = dec_data.params.kposA; |  | ||||||
|         frames = dec_data.params.kszA; |  | ||||||
|     } |  | ||||||
|     else if(m_nSubMode == Varicode::JS8CallFast){ |  | ||||||
|         start = dec_data.params.kposB; |  | ||||||
|         frames = dec_data.params.kszB; |  | ||||||
|     } |  | ||||||
|     else if(m_nSubMode == Varicode::JS8CallTurbo){ |  | ||||||
|         start = dec_data.params.kposC; |  | ||||||
|         frames = dec_data.params.kszC; |  | ||||||
|     } |  | ||||||
|     else if(m_nSubMode == Varicode::JS8CallUltra){ |  | ||||||
|         start = dec_data.params.kposE; |  | ||||||
|         frames = dec_data.params.kszE; |  | ||||||
|     } |  | ||||||
|     memcpy(dec_data.d1, dec_data.d2 + start, sizeof(dec_data.d2[0]) * frames); |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #if JS8_TWO_BUFFERS |  | ||||||
| #if JS8_RING_BUFFER |  | ||||||
|     // clear out d1
 |  | ||||||
|     memset(dec_data.d1, 0, sizeof(dec_data.d1)); |  | ||||||
| 
 |  | ||||||
|     // copy the whole sample if disk data, otherwise, copy only the needed frames
 |  | ||||||
|     if(m_diskData){ |  | ||||||
|       qDebug() << "try decode from" << 0 << "to" << dec_data.params.kin; |  | ||||||
|       memcpy(dec_data.d1, dec_data.d2, sizeof(dec_data.d2)); |  | ||||||
|     } else { |  | ||||||
|         // compute frames to copy for decoding
 |  | ||||||
|         int start = cycleSampleStart; |  | ||||||
|         int stop = qMax(start + framesNeeded, dec_data.params.kin);    // copy more than needed if available
 |  | ||||||
|         int framesAvailable = qMin(stop - start, dec_data.params.kin); // kin is the max available currently
 |  | ||||||
|         int framesMissing = qMax(0, framesNeeded - framesAvailable); |  | ||||||
| 
 |  | ||||||
|         qDebug() << "try decode from" << start << "to" << stop << "available" << framesAvailable << "missing" << framesMissing; |  | ||||||
| 
 |  | ||||||
| #if JS8_DECODER_E2S |  | ||||||
|         // TODO: missing frames happen if we run a decode period not relative to the period interval...
 |  | ||||||
|         //       we'll need to figure out the best way to use the ring buffer in these situations.
 |  | ||||||
| 
 |  | ||||||
|         if(missingFrames){ |  | ||||||
|             // the maximum frame is the period sample size
 |  | ||||||
|             int maxFrames = m_detector->period() * RX_SAMPLE_RATE; |  | ||||||
|             qDebug() << "-> copy missing frames from" << maxFrames-missingFrames << "to" << maxFrames << "to beginning of d1"; |  | ||||||
|             memcpy(dec_data.d1, &dec_data.d2[maxFrames-missingFrames], sizeof(dec_data.d2[0]) * missingFrames); |  | ||||||
|         } |  | ||||||
|         memcpy(dec_data.d1 + missingFrames, dec_data.d2 + start, sizeof(dec_data.d2[0]) * availableFrames); |  | ||||||
| #else |  | ||||||
|         memcpy(dec_data.d1, dec_data.d2 + start, sizeof(dec_data.d2[0]) * framesAvailable); |  | ||||||
| #endif |  | ||||||
|     } |  | ||||||
| #else |  | ||||||
|     qDebug() << "try decode from" << 0 << "to" << dec_data.params.kin; |  | ||||||
|     memset(dec_data.d1, 0, sizeof(dec_data.d1)); |  | ||||||
|     memcpy(dec_data.d1, dec_data.d2, sizeof(dec_data.d2)); |  | ||||||
| #endif |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -4442,6 +4382,9 @@ void MainWindow::decodeDone () | |||||||
| 
 | 
 | ||||||
| QList<int> generateOffsets(int minOffset, int maxOffset){ | QList<int> generateOffsets(int minOffset, int maxOffset){ | ||||||
|     QList<int> offsets; |     QList<int> offsets; | ||||||
|  | 
 | ||||||
|  |     // TODO: these offsets aren't ordered correctly...
 | ||||||
|  | 
 | ||||||
|     for(int i = minOffset; i <= maxOffset; i++){ |     for(int i = minOffset; i <= maxOffset; i++){ | ||||||
|         offsets.append(i); |         offsets.append(i); | ||||||
|     } |     } | ||||||
| @ -4531,7 +4474,7 @@ void MainWindow::readFromStdout()                             //readFromStdout | |||||||
|       if(m_messageDupeCache.contains(frame)){ |       if(m_messageDupeCache.contains(frame)){ | ||||||
|           // check to see if the frequency is near our previous frame
 |           // check to see if the frequency is near our previous frame
 | ||||||
|           auto cachedFreq = m_messageDupeCache.value(frame, 0); |           auto cachedFreq = m_messageDupeCache.value(frame, 0); | ||||||
|           if(qAbs(cachedFreq - frameOffset) <= rxThreshold()){ |           if(qAbs(cachedFreq - frameOffset) <= rxThreshold(decodedtext.submode())){ | ||||||
|             qDebug() << "duplicate frame from" << cachedFreq << "and" << frameOffset; |             qDebug() << "duplicate frame from" << cachedFreq << "and" << frameOffset; | ||||||
|             bValidFrame = false; |             bValidFrame = false; | ||||||
|           } |           } | ||||||
| @ -4559,7 +4502,7 @@ void MainWindow::readFromStdout()                             //readFromStdout | |||||||
|         int offset = decodedtext.frequencyOffset(); |         int offset = decodedtext.frequencyOffset(); | ||||||
| 
 | 
 | ||||||
|         if(!m_bandActivity.contains(offset)){ |         if(!m_bandActivity.contains(offset)){ | ||||||
|             int range = rxThreshold(); |             int range = rxThreshold(decodedtext.submode()); | ||||||
| 
 | 
 | ||||||
|             QList<int> offsets = generateOffsets(offset-range, offset+range); |             QList<int> offsets = generateOffsets(offset-range, offset+range); | ||||||
| 
 | 
 | ||||||
| @ -4587,13 +4530,13 @@ void MainWindow::readFromStdout()                             //readFromStdout | |||||||
| 
 | 
 | ||||||
|         // if we have any "first" frame, and a buffer is already established, clear it...
 |         // if we have any "first" frame, and a buffer is already established, clear it...
 | ||||||
|         int prevBufferOffset = -1; |         int prevBufferOffset = -1; | ||||||
|         if(((d.bits & Varicode::JS8CallFirst) == Varicode::JS8CallFirst) && hasExistingMessageBuffer(d.freq, true, &prevBufferOffset)){ |         if(((d.bits & Varicode::JS8CallFirst) == Varicode::JS8CallFirst) && hasExistingMessageBuffer(decodedtext.submode(), d.freq, true, &prevBufferOffset)){ | ||||||
|             qDebug() << "first message encountered, clearing existing buffer" << prevBufferOffset; |             qDebug() << "first message encountered, clearing existing buffer" << prevBufferOffset; | ||||||
|             m_messageBuffer.remove(d.freq); |             m_messageBuffer.remove(d.freq); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // if we have a data frame, and a message buffer has been established, buffer it...
 |         // if we have a data frame, and a message buffer has been established, buffer it...
 | ||||||
|         if(hasExistingMessageBuffer(d.freq, true, &prevBufferOffset) && !decodedtext.isCompound() && !decodedtext.isDirectedMessage()){ |         if(hasExistingMessageBuffer(decodedtext.submode(), d.freq, true, &prevBufferOffset) && !decodedtext.isCompound() && !decodedtext.isDirectedMessage()){ | ||||||
|             qDebug() << "buffering data" << d.freq << d.text; |             qDebug() << "buffering data" << d.freq << d.text; | ||||||
|             d.isBuffered = true; |             d.isBuffered = true; | ||||||
|             m_messageBuffer[d.freq].msgs.append(d); |             m_messageBuffer[d.freq].msgs.append(d); | ||||||
| @ -4655,7 +4598,7 @@ void MainWindow::readFromStdout()                             //readFromStdout | |||||||
|         } else { |         } else { | ||||||
|             qDebug() << "buffering compound call" << cd.freq << cd.call << cd.bits; |             qDebug() << "buffering compound call" << cd.freq << cd.call << cd.bits; | ||||||
| 
 | 
 | ||||||
|             hasExistingMessageBuffer(cd.freq, true, nullptr); |             hasExistingMessageBuffer(speedNameToSubmode(cd.speed), cd.freq, true, nullptr); | ||||||
|             m_messageBuffer[cd.freq].compound.append(cd); |             m_messageBuffer[cd.freq].compound.append(cd); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
| @ -4699,7 +4642,7 @@ void MainWindow::readFromStdout()                             //readFromStdout | |||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // merge any existing buffer to this frequency
 |             // merge any existing buffer to this frequency
 | ||||||
|             hasExistingMessageBuffer(cmd.freq, true, nullptr); |             hasExistingMessageBuffer(speedNameToSubmode(cmd.speed), cmd.freq, true, nullptr); | ||||||
| 
 | 
 | ||||||
|             if(cmd.to == m_config.my_callsign()){ |             if(cmd.to == m_config.my_callsign()){ | ||||||
|                 d.shouldDisplay = true; |                 d.shouldDisplay = true; | ||||||
| @ -4832,13 +4775,14 @@ bool MainWindow::hasExistingMessageBufferToMe(int *pOffset){ | |||||||
|     return false; |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool MainWindow::hasExistingMessageBuffer(int offset, bool drift, int *pPrevOffset){ | bool MainWindow::hasExistingMessageBuffer(int submode, int offset, bool drift, int *pPrevOffset){ | ||||||
|     if(m_messageBuffer.contains(offset)){ |     if(m_messageBuffer.contains(offset)){ | ||||||
|         if(pPrevOffset) *pPrevOffset = offset; |         if(pPrevOffset) *pPrevOffset = offset; | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     int range = rxThreshold(); | 
 | ||||||
|  |     int range = rxThreshold(submode); | ||||||
| 
 | 
 | ||||||
|     QList<int> offsets = generateOffsets(offset-range, offset+range); |     QList<int> offsets = generateOffsets(offset-range, offset+range); | ||||||
| 
 | 
 | ||||||
| @ -9648,12 +9592,12 @@ void MainWindow::tryNotify(const QString &key){ | |||||||
|     emit playNotification(path); |     emit playNotification(path); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int MainWindow::rxThreshold(){ | int MainWindow::rxThreshold(int submode){ | ||||||
|     int threshold = 10; |     int threshold = 10; | ||||||
|     if(m_nSubMode == Varicode::JS8CallFast){ threshold = 16; } |     if(submode == Varicode::JS8CallFast){ threshold = 16; } | ||||||
|     if(m_nSubMode == Varicode::JS8CallTurbo){ threshold = 32; } |     if(submode == Varicode::JS8CallTurbo){ threshold = 32; } | ||||||
| #if JS8E_IS_ULTRA | #if JS8E_IS_ULTRA | ||||||
|     if(m_nSubMode == Varicode::JS8CallUltraSlow){ threshold = 50; } |     if(submode == Varicode::JS8CallUltraSlow){ threshold = 50; } | ||||||
| #endif | #endif | ||||||
|     return threshold; |     return threshold; | ||||||
| } | } | ||||||
| @ -10007,8 +9951,8 @@ void MainWindow::clearCallsignSelected(){ | |||||||
|     ui->tableWidgetRXAll->clearSelection(); |     ui->tableWidgetRXAll->clearSelection(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool MainWindow::isRecentOffset(int offset){ | bool MainWindow::isRecentOffset(int submode, int offset){ | ||||||
|     if(abs(offset - currentFreqOffset()) <= rxThreshold()){ |     if(abs(offset - currentFreqOffset()) <= rxThreshold(submode)){ | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|     return ( |     return ( | ||||||
| @ -10139,7 +10083,7 @@ void MainWindow::processIdleActivity() { | |||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         auto submode = speedNameMode(last.speed); |         auto submode = speedNameToSubmode(last.speed); | ||||||
|         if(last.utcTimestamp.secsTo(now) < computeSubmodePeriod(submode)){ |         if(last.utcTimestamp.secsTo(now) < computeSubmodePeriod(submode)){ | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
| @ -10157,7 +10101,7 @@ void MainWindow::processIdleActivity() { | |||||||
|         d.freq = last.freq; |         d.freq = last.freq; | ||||||
|         d.speed = last.speed; |         d.speed = last.speed; | ||||||
| 
 | 
 | ||||||
|         if(hasExistingMessageBuffer(offset, false, nullptr)){ |         if(hasExistingMessageBuffer(speedNameToSubmode(d.speed), offset, false, nullptr)){ | ||||||
|             m_messageBuffer[offset].msgs.append(d); |             m_messageBuffer[offset].msgs.append(d); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -10182,10 +10126,12 @@ void MainWindow::processRxActivity() { | |||||||
| 
 | 
 | ||||||
|         // use the actual frequency and check its delta from our current frequency
 |         // use the actual frequency and check its delta from our current frequency
 | ||||||
|         // meaning, if our current offset is 1502 and the d.freq is 1492, the delta is <= 10;
 |         // meaning, if our current offset is 1502 and the d.freq is 1492, the delta is <= 10;
 | ||||||
|         bool shouldDisplay = abs(d.freq - freqOffset) <= rxThreshold(); |         int submode = speedNameToSubmode(d.speed); | ||||||
|  | 
 | ||||||
|  |         bool shouldDisplay = abs(d.freq - freqOffset) <= rxThreshold(submode); | ||||||
| 
 | 
 | ||||||
|         int prevOffset = d.freq; |         int prevOffset = d.freq; | ||||||
|         if(hasExistingMessageBuffer(d.freq, false, &prevOffset) && ( |         if(hasExistingMessageBuffer(submode, d.freq, false, &prevOffset) && ( | ||||||
|                 (m_messageBuffer[prevOffset].cmd.to == m_config.my_callsign()) || |                 (m_messageBuffer[prevOffset].cmd.to == m_config.my_callsign()) || | ||||||
|                 // (isAllCallIncluded(m_messageBuffer[prevOffset].cmd.to))     || // uncomment this if we want to incrementally print allcalls
 |                 // (isAllCallIncluded(m_messageBuffer[prevOffset].cmd.to))     || // uncomment this if we want to incrementally print allcalls
 | ||||||
|                 (isGroupCallIncluded(m_messageBuffer[prevOffset].cmd.to)) |                 (isGroupCallIncluded(m_messageBuffer[prevOffset].cmd.to)) | ||||||
|  | |||||||
							
								
								
									
										11
									
								
								mainwindow.h
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								mainwindow.h
									
									
									
									
									
								
							| @ -132,7 +132,7 @@ public slots: | |||||||
| 
 | 
 | ||||||
|   void playSoundFile(const QString &path); |   void playSoundFile(const QString &path); | ||||||
|   bool hasExistingMessageBufferToMe(int *pOffset); |   bool hasExistingMessageBufferToMe(int *pOffset); | ||||||
|   bool hasExistingMessageBuffer(int offset, bool drift, int *pPrevOffset); |   bool hasExistingMessageBuffer(int submode, int offset, bool drift, int *pPrevOffset); | ||||||
|   bool hasClosedExistingMessageBuffer(int offset); |   bool hasClosedExistingMessageBuffer(int offset); | ||||||
|   void logCallActivity(CallDetail d, bool spot=true); |   void logCallActivity(CallDetail d, bool spot=true); | ||||||
|   void logHeardGraph(QString from, QString to); |   void logHeardGraph(QString from, QString to); | ||||||
| @ -162,7 +162,7 @@ public slots: | |||||||
|   void resetMessageTransmitQueue(); |   void resetMessageTransmitQueue(); | ||||||
|   QPair<QString, int> popMessageFrame(); |   QPair<QString, int> popMessageFrame(); | ||||||
|   void tryNotify(const QString &key); |   void tryNotify(const QString &key); | ||||||
|   int rxThreshold(); |   int rxThreshold(int submode); | ||||||
| 
 | 
 | ||||||
| protected: | protected: | ||||||
|   void keyPressEvent (QKeyEvent *) override; |   void keyPressEvent (QKeyEvent *) override; | ||||||
| @ -718,6 +718,7 @@ private: | |||||||
|     int snr; |     int snr; | ||||||
|     int bits; |     int bits; | ||||||
|     float tdrift; |     float tdrift; | ||||||
|  |     int submode; | ||||||
|     QString speed; |     QString speed; | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
| @ -736,6 +737,7 @@ private: | |||||||
|     QString text; |     QString text; | ||||||
|     QString extra; |     QString extra; | ||||||
|     float tdrift; |     float tdrift; | ||||||
|  |     int submode; | ||||||
|     QString speed; |     QString speed; | ||||||
|     QString relayPath; |     QString relayPath; | ||||||
|   }; |   }; | ||||||
| @ -754,6 +756,7 @@ private: | |||||||
|     int snr; |     int snr; | ||||||
|     bool shouldDisplay; |     bool shouldDisplay; | ||||||
|     float tdrift; |     float tdrift; | ||||||
|  |     int submode; | ||||||
|     QString speed; |     QString speed; | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
| @ -945,7 +948,7 @@ private: | |||||||
|   void aprsLogReport(int offset, int snr, QString callsign, QString grid); |   void aprsLogReport(int offset, int snr, QString callsign, QString grid); | ||||||
|   Radio::Frequency dialFrequency(); |   Radio::Frequency dialFrequency(); | ||||||
|   void setSubmode(int submode); |   void setSubmode(int submode); | ||||||
|   int speedNameMode(QString speed); |   int speedNameToSubmode(QString speed); | ||||||
|   QString modeSpeedName(int submode); |   QString modeSpeedName(int submode); | ||||||
|   void updateCurrentBand(); |   void updateCurrentBand(); | ||||||
|   void displayDialFrequency (); |   void displayDialFrequency (); | ||||||
| @ -966,7 +969,7 @@ private: | |||||||
|   bool isGroupCallIncluded(const QString &text); |   bool isGroupCallIncluded(const QString &text); | ||||||
|   QString callsignSelected(bool useInputText=false); |   QString callsignSelected(bool useInputText=false); | ||||||
|   void callsignSelectedChanged(QString old, QString current); |   void callsignSelectedChanged(QString old, QString current); | ||||||
|   bool isRecentOffset(int offset); |   bool isRecentOffset(int submode, int offset); | ||||||
|   void markOffsetRecent(int offset); |   void markOffsetRecent(int offset); | ||||||
|   bool isDirectedOffset(int offset, bool *pIsAllCall); |   bool isDirectedOffset(int offset, bool *pIsAllCall); | ||||||
|   void markOffsetDirected(int offset, bool isAllCall); |   void markOffsetDirected(int offset, bool isAllCall); | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Jordan Sherer
						Jordan Sherer