mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
Merge pull request #420 from DSheirer/419-heterdyne-channelizer-center-frequency-tuning
419 Heterodyne Channelizer Center Frequency Calculations
This commit is contained in:
@@ -26,12 +26,15 @@ import io.github.dsheirer.source.ISourceEventProcessor;
|
||||
import io.github.dsheirer.source.SourceEvent;
|
||||
import io.github.dsheirer.source.SourceEventListenerToProcessorAdapter;
|
||||
import io.github.dsheirer.source.SourceException;
|
||||
import io.github.dsheirer.source.tuner.channel.TunerChannel;
|
||||
import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.frequency.FrequencyController;
|
||||
import io.github.dsheirer.source.tuner.frequency.FrequencyController.Tunable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.SortedSet;
|
||||
|
||||
public abstract class TunerController implements Tunable, ISourceEventProcessor, ISourceEventListener,
|
||||
IReusableComplexBufferProvider, Listener<ReusableComplexBuffer>
|
||||
{
|
||||
@@ -361,4 +364,85 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
|
||||
{
|
||||
broadcast(complexBuffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the current center frequency and bandwidth is correct to source the tuner channel
|
||||
*
|
||||
* @param tunerChannel to test
|
||||
* @return true if the current center frequency and bandwidth is correct for the channel
|
||||
*/
|
||||
public boolean isTunedFor(TunerChannel tunerChannel)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(tunerChannel.getMinFrequency() < getMinTunedFrequency())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(tunerChannel.getMaxFrequency() > getMaxTunedFrequency())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(hasMiddleUnusableBandwidth())
|
||||
{
|
||||
long minAvoid = getFrequency() - getMiddleUnusableHalfBandwidth();
|
||||
long maxAvoid = getFrequency() + getMiddleUnusableHalfBandwidth();
|
||||
|
||||
if(tunerChannel.overlaps(minAvoid, maxAvoid))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(SourceException se)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the current center frequency and bandwidth is correct to source the tuner channel set
|
||||
*
|
||||
* @param tunerChannels to test
|
||||
* @return true if the current center frequency and bandwidth is correct for the channel set
|
||||
*/
|
||||
public boolean isTunedFor(SortedSet<TunerChannel> tunerChannels)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(tunerChannels.first().getMinFrequency() < getMinTunedFrequency())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(tunerChannels.last().getMaxFrequency() > getMaxTunedFrequency())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(hasMiddleUnusableBandwidth())
|
||||
{
|
||||
long minAvoid = getFrequency() - getMiddleUnusableHalfBandwidth();
|
||||
long maxAvoid = getFrequency() + getMiddleUnusableHalfBandwidth();
|
||||
|
||||
for(TunerChannel tunerChannel: tunerChannels)
|
||||
{
|
||||
if(tunerChannel.overlaps(minAvoid, maxAvoid))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(SourceException se)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -54,48 +54,57 @@ public class CenterFrequencyCalculator
|
||||
//Start by placing the highest frequency channel at the high end of the spectrum
|
||||
candidateFrequency = maxChannelFrequency - (tunerController.getUsableBandwidth() / 2);
|
||||
|
||||
//Iterate the channels and make sure that none of them overlap the center DC spike buffer, if one exists
|
||||
if(tunerController.getMiddleUnusableHalfBandwidth() > 0)
|
||||
if(maxChannelFrequency - minChannelFrequency <= tunerController.getUsableHalfBandwidth())
|
||||
{
|
||||
boolean processingRequired = true;
|
||||
|
||||
while(isValidCandidateFrequency && processingRequired)
|
||||
candidateFrequency = minChannelFrequency - tunerController.getMiddleUnusableHalfBandwidth();
|
||||
isValidCandidateFrequency = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Iterate the channels and make sure that none of them overlap the center DC spike buffer, if one exists
|
||||
if(tunerController.getMiddleUnusableHalfBandwidth() > 0)
|
||||
{
|
||||
processingRequired = false;
|
||||
boolean processingRequired = true;
|
||||
|
||||
long minAvoid = candidateFrequency - tunerController.getMiddleUnusableHalfBandwidth();
|
||||
long maxAvoid = candidateFrequency + tunerController.getMiddleUnusableHalfBandwidth();
|
||||
|
||||
//If any of the center channel(s) overlap the central DC spike avoid area, we'll iteratively
|
||||
//increase the tuned frequency causing the set of channels to move left in the tuned bandwidth until
|
||||
//we either find a good center tune frequency, or we walk the lowest frequency channel out of the
|
||||
//minimum tuned range, in which case we'll throw an exception indicating we don't have a solution.
|
||||
for(TunerChannel channel : channels)
|
||||
while(isValidCandidateFrequency && processingRequired)
|
||||
{
|
||||
if(channel.overlaps(minAvoid, maxAvoid))
|
||||
processingRequired = false;
|
||||
|
||||
long minAvoid = candidateFrequency - tunerController.getMiddleUnusableHalfBandwidth();
|
||||
long maxAvoid = candidateFrequency + tunerController.getMiddleUnusableHalfBandwidth();
|
||||
|
||||
//If any of the center channel(s) overlap the central DC spike avoid area, we'll iteratively
|
||||
//increase the tuned frequency causing the set of channels to move left in the tuned bandwidth until
|
||||
//we either find a good center tune frequency, or we walk the lowest frequency channel out of the
|
||||
//minimum tuned range, in which case we'll throw an exception indicating we don't have a solution.
|
||||
for(TunerChannel channel : channels)
|
||||
{
|
||||
//Calculate a tuned frequency adjustment that places this overlapping channel just to the
|
||||
//left of the central DC spike avoid zone
|
||||
long adjustment = channel.getMaxFrequency() - minAvoid + 1;
|
||||
|
||||
//If the candidate frequency doesn't push the lowest channel out of bounds, make adjustment
|
||||
if(candidateFrequency + adjustment - (tunerController.getUsableBandwidth() / 2) <= minChannelFrequency)
|
||||
if(channel.overlaps(minAvoid, maxAvoid))
|
||||
{
|
||||
candidateFrequency += adjustment;
|
||||
processingRequired = true;
|
||||
}
|
||||
//Otherwise, punt and indicate that we can't find a center frequency or add the channel
|
||||
else
|
||||
{
|
||||
isValidCandidateFrequency = false;
|
||||
}
|
||||
//Calculate a tuned frequency adjustment that places this overlapping channel just to the
|
||||
//left of the central DC spike avoid zone
|
||||
long adjustment = channel.getMaxFrequency() - minAvoid + 1;
|
||||
|
||||
//break out of the for/each loop, so that we can start over again with all of the channels
|
||||
break;
|
||||
//If the candidate frequency doesn't push the lowest channel out of bounds, make adjustment
|
||||
if(candidateFrequency + adjustment - (tunerController.getUsableBandwidth() / 2) <= minChannelFrequency)
|
||||
{
|
||||
candidateFrequency += adjustment;
|
||||
processingRequired = true;
|
||||
}
|
||||
//Otherwise, punt and indicate that we can't find a center frequency or add the channel
|
||||
else
|
||||
{
|
||||
isValidCandidateFrequency = false;
|
||||
}
|
||||
|
||||
//break out of the for/each loop, so that we can start over again with all of the channels
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(isValidCandidateFrequency)
|
||||
|
||||
@@ -108,23 +108,26 @@ public class HeterodyneChannelSourceManager extends ChannelSourceManager
|
||||
*/
|
||||
private void updateTunerFrequency()
|
||||
{
|
||||
long centerFrequency = CenterFrequencyCalculator.getCenterFrequency(mTunerController, getTunerChannels());
|
||||
|
||||
if(centerFrequency == CenterFrequencyCalculator.INVALID_FREQUENCY)
|
||||
if(!mTunerController.isTunedFor(getTunerChannels()))
|
||||
{
|
||||
mLog.error("Couldn't calculate center frequency for tuner and tuner channels");
|
||||
return;
|
||||
}
|
||||
long centerFrequency = CenterFrequencyCalculator.getCenterFrequency(mTunerController, getTunerChannels());
|
||||
|
||||
if(centerFrequency != mTunerController.getFrequency())
|
||||
{
|
||||
try
|
||||
if(centerFrequency == CenterFrequencyCalculator.INVALID_FREQUENCY)
|
||||
{
|
||||
mTunerController.setFrequency(centerFrequency);
|
||||
mLog.error("Couldn't calculate center frequency for tuner and tuner channels");
|
||||
return;
|
||||
}
|
||||
catch(SourceException se)
|
||||
|
||||
if(centerFrequency != mTunerController.getFrequency())
|
||||
{
|
||||
mLog.error("Couldn't update tuner center frequency to " + centerFrequency, se);
|
||||
try
|
||||
{
|
||||
mTunerController.setFrequency(centerFrequency);
|
||||
}
|
||||
catch(SourceException se)
|
||||
{
|
||||
mLog.error("Couldn't update tuner center frequency to " + centerFrequency, se);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user