mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
#1397 Adds channel fft frequency overlay, cursor readout, pll tracking indicator, and channel bandwidth lines. (#1406)
Co-authored-by: Dennis Sheirer <dsheirer@github.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -29,6 +29,7 @@ public class SourceEvent
|
||||
public enum Event
|
||||
{
|
||||
NOTIFICATION_CHANNEL_COUNT_CHANGE,
|
||||
NOTIFICATION_CHANNEL_FREQUENCY_CORRECTION,
|
||||
NOTIFICATION_CHANNEL_FREQUENCY_CORRECTION_CHANGE,
|
||||
NOTIFICATION_CHANNEL_POWER,
|
||||
NOTIFICATION_CHANNEL_SAMPLE_RATE_CHANGE,
|
||||
@@ -40,6 +41,7 @@ public class SourceEvent
|
||||
NOTIFICATION_FREQUENCY_ROTATION_FAILURE,
|
||||
NOTIFICATION_MEASURED_FREQUENCY_ERROR,
|
||||
NOTIFICATION_MEASURED_FREQUENCY_ERROR_SYNC_LOCKED,
|
||||
NOTIFICATION_PLL_FREQUENCY,
|
||||
NOTIFICATION_RECORDING_FILE_LOADED,
|
||||
NOTIFICATION_SAMPLE_RATE_CHANGE,
|
||||
NOTIFICATION_SQUELCH_THRESHOLD,
|
||||
@@ -47,7 +49,6 @@ public class SourceEvent
|
||||
NOTIFICATION_TUNER_SHUTDOWN,
|
||||
NOTIFICATION_ERROR_STATE,
|
||||
|
||||
REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE,
|
||||
REQUEST_FREQUENCY_CHANGE,
|
||||
REQUEST_FREQUENCY_ROTATION,
|
||||
REQUEST_FREQUENCY_SELECTION,
|
||||
@@ -242,13 +243,13 @@ public class SourceEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new channel frequency correction change event
|
||||
* Creates a new PLL frequency error measurement notification event.
|
||||
*
|
||||
* @param frequencyCorrection in hertz
|
||||
* @param frequencyError in hertz
|
||||
*/
|
||||
public static SourceEvent channelFrequencyCorrectionChange(long frequencyCorrection)
|
||||
public static SourceEvent pllFrequencyMeasurement(long frequencyError)
|
||||
{
|
||||
return new SourceEvent(Event.NOTIFICATION_CHANNEL_FREQUENCY_CORRECTION_CHANGE, frequencyCorrection);
|
||||
return new SourceEvent(Event.NOTIFICATION_PLL_FREQUENCY, frequencyError);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -332,16 +333,6 @@ public class SourceEvent
|
||||
return new SourceEvent(Event.REQUEST_FREQUENCY_CHANGE, frequency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new channel frequency correction change request event
|
||||
*
|
||||
* @param frequency requested
|
||||
*/
|
||||
public static SourceEvent channelFrequencyCorrectionRequest(long frequency)
|
||||
{
|
||||
return new SourceEvent(Event.REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE, frequency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new start sample stream request event. This method uses the current system time in
|
||||
* milliseconds as the requested sample start time.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -50,9 +50,7 @@ public class HalfBandTunerChannelSource<T extends INativeBuffer> extends TunerCh
|
||||
private IRealDecimationFilter mIDecimationFilter;
|
||||
private IRealDecimationFilter mQDecimationFilter;
|
||||
private double mChannelSampleRate;
|
||||
private long mChannelFrequencyCorrection = 0;
|
||||
private long mTunerFrequency;
|
||||
private Listener<ComplexSamples> mListener;
|
||||
private StreamProcessorWithHeartbeat<ComplexSamples> mStreamHeartbeatProcessor;
|
||||
|
||||
/**
|
||||
@@ -131,38 +129,25 @@ public class HalfBandTunerChannelSource<T extends INativeBuffer> extends TunerCh
|
||||
updateMixerFrequencyOffset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Current frequency correction being applied to the channel sample stream
|
||||
*
|
||||
* @return correction in hertz
|
||||
*/
|
||||
public long getFrequencyCorrection()
|
||||
{
|
||||
return mChannelFrequencyCorrection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the frequency correction value and broadcasts the change to the registered downstream listener.
|
||||
*
|
||||
* @param correction current frequency correction value.
|
||||
*/
|
||||
public void setFrequencyCorrection(long correction)
|
||||
{
|
||||
mChannelFrequencyCorrection = correction;
|
||||
updateMixerFrequencyOffset();
|
||||
broadcastConsumerSourceEvent(SourceEvent.frequencyCorrectionChange(mChannelFrequencyCorrection));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the local mixer frequency offset from the tuned frequency,
|
||||
* channel's requested frequency, and channel frequency correction.
|
||||
*/
|
||||
private void updateMixerFrequencyOffset()
|
||||
{
|
||||
long offset = mTunerFrequency - getTunerChannel().getFrequency() - mChannelFrequencyCorrection;
|
||||
long offset = mTunerFrequency - getTunerChannel().getFrequency();
|
||||
mFrequencyCorrectionMixer.setFrequency(offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixer frequency applying offset to the samples.
|
||||
* @return mixer frequency
|
||||
*/
|
||||
public long getMixerFrequency()
|
||||
{
|
||||
return (long)mFrequencyCorrectionMixer.getFrequency();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sample rate of the incoming sample stream from the producer
|
||||
*
|
||||
@@ -174,28 +159,6 @@ public class HalfBandTunerChannelSource<T extends INativeBuffer> extends TunerCh
|
||||
//Not implemented. Sample rate changes are not permitted once sample stream starts
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the frequency correction for the outbound sample stream to the consumer
|
||||
*
|
||||
* @param correction in hertz
|
||||
*/
|
||||
@Override
|
||||
protected void setChannelFrequencyCorrection(long correction)
|
||||
{
|
||||
mChannelFrequencyCorrection = correction;
|
||||
broadcastConsumerSourceEvent(SourceEvent.channelFrequencyCorrectionChange(correction));
|
||||
updateMixerFrequencyOffset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Frequency correction value currently being applied to the outbound sample stream
|
||||
*/
|
||||
@Override
|
||||
public long getChannelFrequencyCorrection()
|
||||
{
|
||||
return mChannelFrequencyCorrection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the listener to receive the complex buffer sample output from this channel
|
||||
*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -29,13 +29,12 @@ import io.github.dsheirer.source.heartbeat.Heartbeat;
|
||||
import io.github.dsheirer.source.tuner.channel.rotation.FrequencyLockChangeRequest;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Multiple-frequency tuner channel source. Provides a wrapper around a tuner channel source and listens for external
|
||||
@@ -273,26 +272,6 @@ public class MultiFrequencyTunerChannelSource extends TunerChannelSource
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setChannelFrequencyCorrection(long correction)
|
||||
{
|
||||
if(mTunerChannelSource != null)
|
||||
{
|
||||
mTunerChannelSource.setChannelFrequencyCorrection(correction);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getChannelFrequencyCorrection()
|
||||
{
|
||||
if(mTunerChannelSource != null)
|
||||
{
|
||||
return mTunerChannelSource.getChannelFrequencyCorrection();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListener(Listener<ComplexSamples> complexSamplesListener)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -27,11 +27,10 @@ import io.github.dsheirer.source.ISourceEventListener;
|
||||
import io.github.dsheirer.source.SourceEvent;
|
||||
import io.github.dsheirer.source.tuner.TunerController;
|
||||
import io.github.dsheirer.util.Dispatcher;
|
||||
import java.util.Iterator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Pass-through channel source that simply passes complex sample buffers from the tuner controller
|
||||
* directly to the registered listener
|
||||
@@ -90,18 +89,6 @@ public class PassThroughChannelSource extends TunerChannelSource implements ISou
|
||||
mLog.debug("Request to set sample rate: " + sampleRate);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setChannelFrequencyCorrection(long correction)
|
||||
{
|
||||
mLog.debug("Request to set frequency correction: " + correction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getChannelFrequencyCorrection()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListener(Listener<ComplexSamples> listener)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -78,17 +78,6 @@ public abstract class TunerChannelSource extends ComplexSource implements ISourc
|
||||
*/
|
||||
protected abstract void setSampleRate(double sampleRate);
|
||||
|
||||
/**
|
||||
* Sets the frequency correction for the outbound sample stream to the consumer
|
||||
* @param correction in hertz
|
||||
*/
|
||||
protected abstract void setChannelFrequencyCorrection(long correction);
|
||||
|
||||
/**
|
||||
* Frequency correction value currently being applied to the outbound sample stream
|
||||
*/
|
||||
public abstract long getChannelFrequencyCorrection();
|
||||
|
||||
/**
|
||||
* Sets the listener to receive the complex buffer sample output from this channel
|
||||
* @param complexSamplesListener to receive complex buffers
|
||||
@@ -152,11 +141,11 @@ public abstract class TunerChannelSource extends ComplexSource implements ISourc
|
||||
{
|
||||
switch(sourceEvent.getEvent())
|
||||
{
|
||||
case NOTIFICATION_CHANNEL_FREQUENCY_CORRECTION_CHANGE:
|
||||
case NOTIFICATION_FREQUENCY_CHANGE:
|
||||
case NOTIFICATION_FREQUENCY_AND_SAMPLE_RATE_LOCKED:
|
||||
case NOTIFICATION_FREQUENCY_AND_SAMPLE_RATE_UNLOCKED:
|
||||
case NOTIFICATION_FREQUENCY_CORRECTION_CHANGE:
|
||||
case NOTIFICATION_PLL_FREQUENCY:
|
||||
case NOTIFICATION_STOP_SAMPLE_STREAM:
|
||||
//no-op
|
||||
break;
|
||||
@@ -172,10 +161,6 @@ public abstract class TunerChannelSource extends ComplexSource implements ISourc
|
||||
sourceEvent.setSource(this);
|
||||
broadcastProducerSourceEvent(sourceEvent);
|
||||
break;
|
||||
//Request events from the consumer
|
||||
case REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE:
|
||||
setChannelFrequencyCorrection(sourceEvent.getValue().longValue());
|
||||
break;
|
||||
case NOTIFICATION_FREQUENCY_ROTATION_FAILURE:
|
||||
case NOTIFICATION_FREQUENCY_ROTATION_SUCCESS:
|
||||
case NOTIFICATION_CHANNEL_POWER:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -169,7 +169,7 @@ public class PolyphaseChannelSourceManager extends ChannelSourceManager
|
||||
* @return optimal center tuned frequency for the set of currently sourced tuner channels.
|
||||
* @throws IllegalArgumentException if a center frequency cannot be determined for the set of tuner channels
|
||||
*/
|
||||
private long getCenterFrequency(SortedSet<TunerChannel> channels, long currentCenterFrequency)
|
||||
protected long getCenterFrequency(SortedSet<TunerChannel> channels, long currentCenterFrequency)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
if(channels.isEmpty())
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.manager;
|
||||
|
||||
import io.github.dsheirer.source.tuner.TunerController;
|
||||
import io.github.dsheirer.source.tuner.channel.TunerChannel;
|
||||
import java.util.SortedSet;
|
||||
|
||||
public class TestPolyphaseChannelSourceManager extends PolyphaseChannelSourceManager
|
||||
{
|
||||
private boolean mLockCenterFrequency = true;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
*
|
||||
* @param tunerController with a center tuned frequency that will be managed by this instance
|
||||
*/
|
||||
public TestPolyphaseChannelSourceManager(TunerController tunerController)
|
||||
{
|
||||
super(tunerController);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getCenterFrequency(SortedSet<TunerChannel> channels, long currentCenterFrequency) throws IllegalArgumentException
|
||||
{
|
||||
if(mLockCenterFrequency)
|
||||
{
|
||||
return currentCenterFrequency;
|
||||
}
|
||||
|
||||
return super.getCenterFrequency(channels, currentCenterFrequency);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,6 +20,7 @@ package io.github.dsheirer.source.tuner.test;
|
||||
|
||||
import io.github.dsheirer.buffer.FloatNativeBuffer;
|
||||
import io.github.dsheirer.buffer.INativeBuffer;
|
||||
import io.github.dsheirer.dsp.oscillator.AWGNOscillator;
|
||||
import io.github.dsheirer.dsp.oscillator.IComplexOscillator;
|
||||
import io.github.dsheirer.dsp.oscillator.OscillatorFactory;
|
||||
import io.github.dsheirer.sample.Broadcaster;
|
||||
@@ -59,7 +60,9 @@ public class SampleGenerator
|
||||
throw new IllegalArgumentException("Sweep update rate cannot be greater than sample rate");
|
||||
}
|
||||
|
||||
mComplexOscillator = OscillatorFactory.getComplexOscillator(frequency, sampleRate);
|
||||
// mComplexOscillator = OscillatorFactory.getComplexOscillator(frequency, sampleRate);
|
||||
IComplexOscillator oscillator = OscillatorFactory.getComplexOscillator(frequency, sampleRate);
|
||||
mComplexOscillator = new AWGNOscillator(oscillator, 0.003f);
|
||||
|
||||
mInterval = 1000 / (sampleRate / mSamplesPerInterval);
|
||||
mSweepUpdateInterval = sweepUpdateRate;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -22,6 +22,7 @@ import io.github.dsheirer.source.tuner.ITunerErrorListener;
|
||||
import io.github.dsheirer.source.tuner.Tuner;
|
||||
import io.github.dsheirer.source.tuner.TunerClass;
|
||||
import io.github.dsheirer.source.tuner.TunerType;
|
||||
import io.github.dsheirer.source.tuner.manager.TestPolyphaseChannelSourceManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -38,6 +39,7 @@ public class TestTuner extends Tuner
|
||||
public TestTuner(ITunerErrorListener tunerErrorListener)
|
||||
{
|
||||
super(new TestTunerController(), tunerErrorListener);
|
||||
setChannelSourceManager(new TestPolyphaseChannelSourceManager(getTunerController()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -33,7 +33,7 @@ public class TestTunerController extends TunerController
|
||||
private final static Logger mLog = LoggerFactory.getLogger(TestTunerController.class);
|
||||
|
||||
public static final long MINIMUM_FREQUENCY = 1l;
|
||||
public static final long MAXIMUM_FREQUENCY = 1000000000l;
|
||||
public static final long MAXIMUM_FREQUENCY = 1_000_000_000l;
|
||||
public static final int SAMPLE_RATE = 2_400_000;
|
||||
public static final int DC_NOISE_BANDWIDTH = 0;
|
||||
public static final double USABLE_BANDWIDTH_PERCENTAGE = 1.00;
|
||||
@@ -42,7 +42,7 @@ public class TestTunerController extends TunerController
|
||||
public static final long SAMPLE_GENERATION_INTERVAL = 1000 / SPECTRAL_FRAME_RATE;
|
||||
|
||||
private SampleGenerator mSampleGenerator;
|
||||
private long mFrequency = 100000000l;
|
||||
private long mFrequency = 460662500l;
|
||||
|
||||
/**
|
||||
* Tuner controller testing implementation.
|
||||
|
||||
Reference in New Issue
Block a user