Fixed jumping frequency by better signal frequency tweaking after sync
This commit is contained in:
		
							parent
							
								
									aee8de2b64
								
							
						
					
					
						commit
						6f111cdb73
					
				@ -1,6 +1,6 @@
 | 
				
			|||||||
subroutine baselinejs8(s,nfa,nfb,sbase)
 | 
					subroutine baselinejs8(s,nfa,nfb,sbase)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
! Fit baseline to spectrum (for FT8)
 | 
					! Fit baseline to spectrum (for JS8)
 | 
				
			||||||
! Input:  s(npts)         Linear scale in power
 | 
					! Input:  s(npts)         Linear scale in power
 | 
				
			||||||
! Output: sbase(npts)    Baseline
 | 
					! Output: sbase(npts)    Baseline
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
subroutine genjs8(msg,mygrid,bcontest,i3bit,msgsent,msgbits,itone)
 | 
					subroutine genjs8(msg,mygrid,bcontest,i3bit,msgsent,msgbits,itone)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
! Encode an FT8 message, producing array itone().
 | 
					! Encode an JS8 message, producing array itone().
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  use crc
 | 
					  use crc
 | 
				
			||||||
  use packjt
 | 
					  use packjt
 | 
				
			||||||
 | 
				
			|||||||
@ -137,7 +137,7 @@ subroutine js8dec(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly,   &
 | 
				
			|||||||
    delf=ifr*0.5
 | 
					    delf=ifr*0.5
 | 
				
			||||||
    dphi=twopi*delf*dt2
 | 
					    dphi=twopi*delf*dt2
 | 
				
			||||||
    phi=0.0
 | 
					    phi=0.0
 | 
				
			||||||
    do i=1,NDOWNSPS
 | 
					    do i=1,(4*NSPS/NDOWN)
 | 
				
			||||||
      ctwk(i)=cmplx(cos(phi),sin(phi))
 | 
					      ctwk(i)=cmplx(cos(phi),sin(phi))
 | 
				
			||||||
      phi=mod(phi+dphi,twopi)
 | 
					      phi=mod(phi+dphi,twopi)
 | 
				
			||||||
    enddo
 | 
					    enddo
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
subroutine syncjs8d(cd0,i0,ctwk,itwk,sync)
 | 
					subroutine syncjs8d(cd0,i0,ctwk,itwk,sync)
 | 
				
			||||||
! Compute sync power for a complex, downsampled FT8 signal.
 | 
					! Compute sync power for a complex, downsampled JS8 signal.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  !include 'js8_params.f90'
 | 
					  !include 'js8_params.f90'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -4127,6 +4127,14 @@ void MainWindow::decodeDone ()
 | 
				
			|||||||
  m_blankLine=true;
 | 
					  m_blankLine=true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QList<int> generateOffsets(int minOffset, int maxOffset){
 | 
				
			||||||
 | 
					    QList<int> offsets;
 | 
				
			||||||
 | 
					    for(int i = minOffset; i <= maxOffset; i++){
 | 
				
			||||||
 | 
					        offsets.append(i);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return offsets;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MainWindow::readFromStdout()                             //readFromStdout
 | 
					void MainWindow::readFromStdout()                             //readFromStdout
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  while(proc_js8.canReadLine()) {
 | 
					  while(proc_js8.canReadLine()) {
 | 
				
			||||||
@ -4203,12 +4211,11 @@ void MainWindow::readFromStdout()                             //readFromStdout
 | 
				
			|||||||
            int offset = decodedtext.frequencyOffset();
 | 
					            int offset = decodedtext.frequencyOffset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(!m_bandActivity.contains(offset)){
 | 
					            if(!m_bandActivity.contains(offset)){
 | 
				
			||||||
                QList<int> offsets = {
 | 
					                int range = 10;
 | 
				
			||||||
                    // offset - 60, offset - 61, offset - 62, offset - 63, offset - 64, offset - 65, offset - 66, offset - 67, offset - 68, offset - 69,
 | 
					                if(m_nSubMode == Varicode::JS8CallFast){ range = 15; }
 | 
				
			||||||
                    // offset + 60, offset + 61, offset + 62, offset + 63, offset + 64, offset + 65, offset + 66, offset + 67, offset + 68, offset + 69,
 | 
					                if(m_nSubMode == Varicode::JS8CallTurbo){ range = 30; }
 | 
				
			||||||
                    offset - 1, offset - 2, offset - 3, offset - 4, offset - 5, offset - 6, offset - 7, offset - 8, offset - 9, offset - 10,
 | 
					                QList<int> offsets = generateOffsets(offset-10, offset+10);
 | 
				
			||||||
                    offset + 1, offset + 2, offset + 3, offset + 4, offset + 5, offset + 6, offset + 7, offset + 8, offset + 9, offset + 10
 | 
					
 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
                foreach(int prevOffset, offsets){
 | 
					                foreach(int prevOffset, offsets){
 | 
				
			||||||
                    if(!m_bandActivity.contains(prevOffset)){ continue; }
 | 
					                    if(!m_bandActivity.contains(prevOffset)){ continue; }
 | 
				
			||||||
                    m_bandActivity[offset] = m_bandActivity[prevOffset];
 | 
					                    m_bandActivity[offset] = m_bandActivity[prevOffset];
 | 
				
			||||||
@ -4340,6 +4347,7 @@ void MainWindow::readFromStdout()                             //readFromStdout
 | 
				
			|||||||
                    logHeardGraph(cmd.from, cmd.to);
 | 
					                    logHeardGraph(cmd.from, cmd.to);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // merge any existing buffer to this frequency
 | 
				
			||||||
                hasExistingMessageBuffer(cmd.freq, true, nullptr);
 | 
					                hasExistingMessageBuffer(cmd.freq, true, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if(cmd.to == m_config.my_callsign()){
 | 
					                if(cmd.to == m_config.my_callsign()){
 | 
				
			||||||
@ -4538,12 +4546,12 @@ bool MainWindow::hasExistingMessageBuffer(int offset, bool drift, int *pPrevOffs
 | 
				
			|||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    QList<int> offsets = {
 | 
					    int range = 10;
 | 
				
			||||||
        //offset - 60, offset - 61, offset - 62, offset - 63, offset - 64, offset - 65, offset - 66, offset - 67, offset - 68, offset - 69,
 | 
					    if(m_nSubMode == Varicode::JS8CallFast){ range = 15; }
 | 
				
			||||||
        //offset + 60, offset + 61, offset + 62, offset + 63, offset + 64, offset + 65, offset + 66, offset + 67, offset + 68, offset + 69,
 | 
					    if(m_nSubMode == Varicode::JS8CallTurbo){ range = 30; }
 | 
				
			||||||
        offset - 1, offset - 2, offset - 3, offset - 4, offset - 5, offset - 6, offset - 7, offset - 8, offset - 9, offset - 10,
 | 
					
 | 
				
			||||||
        offset + 1, offset + 2, offset + 3, offset + 4, offset + 5, offset + 6, offset + 7, offset + 8, offset + 9, offset + 10
 | 
					    QList<int> offsets = generateOffsets(offset-range, offset+range);
 | 
				
			||||||
    };
 | 
					
 | 
				
			||||||
    foreach(int prevOffset, offsets){
 | 
					    foreach(int prevOffset, offsets){
 | 
				
			||||||
        if(!m_messageBuffer.contains(prevOffset)){ continue; }
 | 
					        if(!m_messageBuffer.contains(prevOffset)){ continue; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -4559,6 +4567,13 @@ bool MainWindow::hasExistingMessageBuffer(int offset, bool drift, int *pPrevOffs
 | 
				
			|||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool MainWindow::hasClosedExistingMessageBuffer(int offset){
 | 
				
			||||||
 | 
					    int range = 10;
 | 
				
			||||||
 | 
					    if(m_nSubMode == Varicode::JS8CallFast){ range = 15; }
 | 
				
			||||||
 | 
					    if(m_nSubMode == Varicode::JS8CallTurbo){ range = 30; }
 | 
				
			||||||
 | 
					    return offset - range <= m_lastClosedMessageBufferOffset && m_lastClosedMessageBufferOffset <= offset + range;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MainWindow::logCallActivity(CallDetail d, bool spot){
 | 
					void MainWindow::logCallActivity(CallDetail d, bool spot){
 | 
				
			||||||
    // don't log empty calls
 | 
					    // don't log empty calls
 | 
				
			||||||
    if(d.call.trimmed().isEmpty()){
 | 
					    if(d.call.trimmed().isEmpty()){
 | 
				
			||||||
@ -9953,10 +9968,15 @@ void MainWindow::processRxActivity() {
 | 
				
			|||||||
                d.utcTimestamp = qMin(d.utcTimestamp, lastCompound.utcTimestamp);
 | 
					                d.utcTimestamp = qMin(d.utcTimestamp, lastCompound.utcTimestamp);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        } else if(hasClosedExistingMessageBuffer(d.freq)){
 | 
				
			||||||
 | 
					            // incremental typeahead should just be displayed...
 | 
				
			||||||
 | 
					            // TODO: should the buffer be reopened?
 | 
				
			||||||
 | 
					            shouldDisplay = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        } else if(d.isDirected && d.text.contains("<....>")){
 | 
					        } else if(d.isDirected && d.text.contains("<....>")){
 | 
				
			||||||
            // if this is a _partial_ directed message, skip until the complete call comes through.
 | 
					            // if this is a _partial_ directed message, skip until the complete call comes through.
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        } else if(d.isDirected && d.text.contains(": HB ")){ // TODO: HEARTBEAT
 | 
					        } else if(d.isDirected && d.text.contains(": HB ")){ // TODO: HEARTBEAT
 | 
				
			||||||
            // if this is a heartbeat, process elsewhere...
 | 
					            // if this is a heartbeat, process elsewhere...
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
@ -10135,6 +10155,9 @@ void MainWindow::processCompoundActivity() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        m_rxCommandQueue.append(buffer.cmd);
 | 
					        m_rxCommandQueue.append(buffer.cmd);
 | 
				
			||||||
        m_messageBuffer.remove(freq);
 | 
					        m_messageBuffer.remove(freq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // TODO: only if to me?
 | 
				
			||||||
 | 
					        m_lastClosedMessageBufferOffset = freq;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -10158,20 +10181,24 @@ void MainWindow::processBufferedActivity() {
 | 
				
			|||||||
        if(!buffer.msgs.isEmpty()){
 | 
					        if(!buffer.msgs.isEmpty()){
 | 
				
			||||||
            dt = qMax(dt, buffer.msgs.last().utcTimestamp);
 | 
					            dt = qMax(dt, buffer.msgs.last().utcTimestamp);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // if the buffer has messages older than 1 minute, and we still haven't closed it, let's mark it as the last frame
 | 
				
			||||||
        if(dt.secsTo(DriftingDateTime::currentDateTimeUtc()) > 60 && !buffer.msgs.isEmpty()){
 | 
					        if(dt.secsTo(DriftingDateTime::currentDateTimeUtc()) > 60 && !buffer.msgs.isEmpty()){
 | 
				
			||||||
            // if the buffer has messages older than 1 minute, and we still haven't closed it, let's just mark it as the last frame
 | 
					 | 
				
			||||||
            buffer.msgs.last().bits |= Varicode::JS8CallLast;
 | 
					            buffer.msgs.last().bits |= Varicode::JS8CallLast;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // but, if the buffer is older than 1.5 minutes, and we still haven't closed it, just remove it and skip
 | 
				
			||||||
        if(dt.secsTo(DriftingDateTime::currentDateTimeUtc()) > 90){
 | 
					        if(dt.secsTo(DriftingDateTime::currentDateTimeUtc()) > 90){
 | 
				
			||||||
            // but, if the buffer is older than 2 minutes, and we still haven't closed it, just remove it
 | 
					 | 
				
			||||||
            m_messageBuffer.remove(freq);
 | 
					            m_messageBuffer.remove(freq);
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // if the buffer has no messages, skip
 | 
				
			||||||
        if (buffer.msgs.isEmpty()) {
 | 
					        if (buffer.msgs.isEmpty()) {
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // if the buffered message hasn't seen the last message, skip
 | 
				
			||||||
        if ((buffer.msgs.last().bits & Varicode::JS8CallLast) != Varicode::JS8CallLast) {
 | 
					        if ((buffer.msgs.last().bits & Varicode::JS8CallLast) != Varicode::JS8CallLast) {
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -10220,6 +10247,7 @@ void MainWindow::processBufferedActivity() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // regardless of valid or not, remove the "complete" buffered message from the buffer cache
 | 
					        // regardless of valid or not, remove the "complete" buffered message from the buffer cache
 | 
				
			||||||
        m_messageBuffer.remove(freq);
 | 
					        m_messageBuffer.remove(freq);
 | 
				
			||||||
 | 
					        m_lastClosedMessageBufferOffset = freq;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -137,6 +137,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 offset, bool drift, int *pPrevOffset);
 | 
				
			||||||
 | 
					  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);
 | 
				
			||||||
  QString lookupCallInCompoundCache(QString const &call);
 | 
					  QString lookupCallInCompoundCache(QString const &call);
 | 
				
			||||||
@ -843,6 +844,7 @@ private:
 | 
				
			|||||||
  QMap<int, int> m_rxFrameBlockNumbers; // freq -> block
 | 
					  QMap<int, int> m_rxFrameBlockNumbers; // freq -> block
 | 
				
			||||||
  QMap<int, QList<ActivityDetail>> m_bandActivity; // freq -> [(text, last timestamp), ...]
 | 
					  QMap<int, QList<ActivityDetail>> m_bandActivity; // freq -> [(text, last timestamp), ...]
 | 
				
			||||||
  QMap<int, MessageBuffer> m_messageBuffer; // freq -> (cmd, [frames, ...])
 | 
					  QMap<int, MessageBuffer> m_messageBuffer; // freq -> (cmd, [frames, ...])
 | 
				
			||||||
 | 
					  int m_lastClosedMessageBufferOffset;
 | 
				
			||||||
  QMap<QString, CallDetail> m_callActivity; // call -> (last freq, last timestamp)
 | 
					  QMap<QString, CallDetail> m_callActivity; // call -> (last freq, last timestamp)
 | 
				
			||||||
  QMap<QString, QDateTime> m_aprsCallCache;
 | 
					  QMap<QString, QDateTime> m_aprsCallCache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user