diff --git a/src/main/java/io/github/dsheirer/source/tuner/TunerController.java b/src/main/java/io/github/dsheirer/source/tuner/TunerController.java index 4b9a102a..92e5e053 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/TunerController.java +++ b/src/main/java/io/github/dsheirer/source/tuner/TunerController.java @@ -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 { @@ -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 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; + } } \ No newline at end of file diff --git a/src/main/java/io/github/dsheirer/source/tuner/manager/CenterFrequencyCalculator.java b/src/main/java/io/github/dsheirer/source/tuner/manager/CenterFrequencyCalculator.java index c61b8ba2..dbf18db7 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/manager/CenterFrequencyCalculator.java +++ b/src/main/java/io/github/dsheirer/source/tuner/manager/CenterFrequencyCalculator.java @@ -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) diff --git a/src/main/java/io/github/dsheirer/source/tuner/manager/HeterodyneChannelSourceManager.java b/src/main/java/io/github/dsheirer/source/tuner/manager/HeterodyneChannelSourceManager.java index 6ba6085f..180bfc7c 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/manager/HeterodyneChannelSourceManager.java +++ b/src/main/java/io/github/dsheirer/source/tuner/manager/HeterodyneChannelSourceManager.java @@ -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); + } } } }