mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
Compare commits
3 Commits
master
...
v0.3.2-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cebd2da89f | ||
|
|
73b6ef164f | ||
|
|
b2c7ac8c66 |
@@ -6,8 +6,8 @@
|
|||||||
<!-- version properties -->
|
<!-- version properties -->
|
||||||
<property name="major" value="0"/>
|
<property name="major" value="0"/>
|
||||||
<property name="minor" value="3"/>
|
<property name="minor" value="3"/>
|
||||||
<property name="patch" value="1"/>
|
<property name="patch" value="2"/>
|
||||||
<property name="release" value="final"/>
|
<property name="release" value="-beta1"/>
|
||||||
<property name="filename" value="sdrtrunk_${major}.${minor}.${patch}${release}"/>
|
<property name="filename" value="sdrtrunk_${major}.${minor}.${patch}${release}"/>
|
||||||
|
|
||||||
<!-- Build properties -->
|
<!-- Build properties -->
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* SDR Trunk
|
* SDR Trunk
|
||||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
* Copyright (C) 2014-2017 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,13 +17,8 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package source.tuner;
|
package source.tuner;
|
||||||
|
|
||||||
import java.util.SortedSet;
|
|
||||||
import java.util.concurrent.ConcurrentSkipListSet;
|
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import source.SourceException;
|
import source.SourceException;
|
||||||
import source.tuner.configuration.TunerConfiguration;
|
import source.tuner.configuration.TunerConfiguration;
|
||||||
import source.tuner.frequency.FrequencyChangeEvent;
|
import source.tuner.frequency.FrequencyChangeEvent;
|
||||||
@@ -32,10 +27,13 @@ import source.tuner.frequency.FrequencyController;
|
|||||||
import source.tuner.frequency.FrequencyController.Tunable;
|
import source.tuner.frequency.FrequencyController.Tunable;
|
||||||
import source.tuner.frequency.IFrequencyChangeProcessor;
|
import source.tuner.frequency.IFrequencyChangeProcessor;
|
||||||
|
|
||||||
|
import java.util.SortedSet;
|
||||||
|
import java.util.concurrent.ConcurrentSkipListSet;
|
||||||
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
|
|
||||||
public abstract class TunerController implements Tunable, IFrequencyChangeProcessor
|
public abstract class TunerController implements Tunable, IFrequencyChangeProcessor
|
||||||
{
|
{
|
||||||
private final static Logger mLog =
|
private final static Logger mLog = LoggerFactory.getLogger(TunerController.class);
|
||||||
LoggerFactory.getLogger( TunerController.class );
|
|
||||||
|
|
||||||
/* List of currently tuned channels being served to demod channels */
|
/* List of currently tuned channels being served to demod channels */
|
||||||
private SortedSet<TunerChannel> mTunedChannels = new ConcurrentSkipListSet<>();
|
private SortedSet<TunerChannel> mTunedChannels = new ConcurrentSkipListSet<>();
|
||||||
@@ -44,36 +42,27 @@ public abstract class TunerController implements Tunable, IFrequencyChangeProces
|
|||||||
private double mUsableBandwidthPercentage;
|
private double mUsableBandwidthPercentage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract tuner controller class. The tuner controller manages frequency
|
* Abstract tuner controller class. The tuner controller manages frequency bandwidth and currently tuned channels
|
||||||
* bandwidth and currently tuned channels that are being fed samples from
|
* that are being fed samples from the tuner.
|
||||||
* the tuner.
|
|
||||||
*
|
*
|
||||||
* @param minimumFrequency minimum uncorrected tunable frequency
|
* @param minimumFrequency minimum uncorrected tunable frequency
|
||||||
* @param maximumFrequency maximum uncorrected tunable frequency
|
* @param maximumFrequency maximum uncorrected tunable frequency
|
||||||
* @param middleUnusable is the +/- value center DC spike to avoid for channels
|
* @param middleUnusable is the +/- value center DC spike to avoid for channels
|
||||||
* @param usableBandwidthPercentage is the unusable space at the extreme ends of the spectrum
|
* @param usableBandwidth percentage of usable bandwidth relative to space at the extreme ends of the spectrum
|
||||||
*
|
|
||||||
* @throws SourceException - for any issues related to constructing the
|
* @throws SourceException - for any issues related to constructing the
|
||||||
* class, tuning a frequency, or setting the bandwidth
|
* class, tuning a frequency, or setting the bandwidth
|
||||||
*/
|
*/
|
||||||
public TunerController( long minimumFrequency,
|
public TunerController(long minimumFrequency, long maximumFrequency, int middleUnusable, double usableBandwidth)
|
||||||
long maximumFrequency,
|
|
||||||
int middleUnusable,
|
|
||||||
double usableBandwidthPercentage )
|
|
||||||
{
|
{
|
||||||
mFrequencyController = new FrequencyController( this,
|
mFrequencyController = new FrequencyController(this, minimumFrequency, maximumFrequency, 0.0d);
|
||||||
minimumFrequency,
|
|
||||||
maximumFrequency,
|
|
||||||
0.0d );
|
|
||||||
mMiddleUnusable = middleUnusable;
|
mMiddleUnusable = middleUnusable;
|
||||||
mUsableBandwidthPercentage = usableBandwidthPercentage;
|
mUsableBandwidthPercentage = usableBandwidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies the settings in the tuner configuration
|
* Applies the settings in the tuner configuration
|
||||||
*/
|
*/
|
||||||
public abstract void apply( TunerConfiguration config )
|
public abstract void apply(TunerConfiguration config) throws SourceException;
|
||||||
throws SourceException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responds to requests to set the frequency
|
* Responds to requests to set the frequency
|
||||||
@@ -155,8 +144,7 @@ public abstract class TunerController implements Tunable, IFrequencyChangeProces
|
|||||||
private boolean canTune(TunerChannel channel)
|
private boolean canTune(TunerChannel channel)
|
||||||
{
|
{
|
||||||
//Make sure we're within the tunable frequency range of this tuner
|
//Make sure we're within the tunable frequency range of this tuner
|
||||||
if( getMinFrequency() < channel.getMinFrequency() &&
|
if(getMinFrequency() < channel.getMinFrequency() && getMaxFrequency() > channel.getMaxFrequency())
|
||||||
getMaxFrequency() > channel.getMaxFrequency() )
|
|
||||||
{
|
{
|
||||||
//If this is the first lock, then we're good
|
//If this is the first lock, then we're good
|
||||||
if(mTunedChannels.isEmpty())
|
if(mTunedChannels.isEmpty())
|
||||||
@@ -170,8 +158,7 @@ public abstract class TunerController implements Tunable, IFrequencyChangeProces
|
|||||||
long maxLockedFrequency = mTunedChannels.last().getMaxFrequency();
|
long maxLockedFrequency = mTunedChannels.last().getMaxFrequency();
|
||||||
|
|
||||||
//Requested channel is within current locked channel frequency range
|
//Requested channel is within current locked channel frequency range
|
||||||
if( minLockedFrequency <= channel.getMinFrequency() &&
|
if(minLockedFrequency <= channel.getMinFrequency() && channel.getMaxFrequency() <= maxLockedFrequency)
|
||||||
channel.getMaxFrequency() <= maxLockedFrequency )
|
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -182,6 +169,7 @@ public abstract class TunerController implements Tunable, IFrequencyChangeProces
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Requested channel is lower than the max locked frequency
|
//Requested channel is lower than the max locked frequency
|
||||||
if(channel.getMinFrequency() <= maxLockedFrequency &&
|
if(channel.getMinFrequency() <= maxLockedFrequency &&
|
||||||
maxLockedFrequency - channel.getMinFrequency() <= usableBandwidth)
|
maxLockedFrequency - channel.getMinFrequency() <= usableBandwidth)
|
||||||
@@ -195,25 +183,19 @@ public abstract class TunerController implements Tunable, IFrequencyChangeProces
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a digital drop channel (DDC) as a tuner channel from from
|
* Constructs a digital drop channel (DDC) as a tuner channel from from the tuner, or returns null if the channel
|
||||||
* the tuner, or returns null if the channel cannot be sourced from the
|
* cannot be sourced from the tuner.
|
||||||
* tuner.
|
|
||||||
*
|
*
|
||||||
* This controller can't provide a channel if the channel, along with the
|
* This controller can't provide a channel if the channel, along with the current set of sourced channels, can't be
|
||||||
* current set of sourced channels, can't be accomodated within the current
|
* accomodated within the current tuner bandwidth, or if a center frequency cannot be calculated that will ensure
|
||||||
* tuner bandwidth, or if a center frequency cannot be calculated that will
|
* all of the channels can be accomodated and any defined central DC spike avoided.
|
||||||
* ensure all of the channels can be accomodated and any defined central DC
|
|
||||||
* spike avoided.
|
|
||||||
*
|
*
|
||||||
* @param tuner to source the channel from
|
* @param tuner to source the channel from
|
||||||
* @param channel with defined center frequency and bandwidth
|
* @param channel with defined center frequency and bandwidth
|
||||||
*
|
|
||||||
* @return fully constructed tuner channel or null
|
* @return fully constructed tuner channel or null
|
||||||
*
|
|
||||||
* @throws RejectedExecutionException if the decimation processor has an error
|
* @throws RejectedExecutionException if the decimation processor has an error
|
||||||
*/
|
*/
|
||||||
public TunerChannelSource getChannel( Tuner tuner, TunerChannel channel )
|
public TunerChannelSource getChannel(Tuner tuner, TunerChannel channel) throws RejectedExecutionException
|
||||||
throws RejectedExecutionException
|
|
||||||
{
|
{
|
||||||
TunerChannelSource source = null;
|
TunerChannelSource source = null;
|
||||||
|
|
||||||
@@ -246,21 +228,20 @@ public abstract class TunerController implements Tunable, IFrequencyChangeProces
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates if the tuner's LO frequency must be updated in order to
|
* Indicates if the tuner's LO frequency must be updated in order to accommodate the tuner channel
|
||||||
* accomodate the tuner channel
|
|
||||||
*/
|
*/
|
||||||
private boolean requiresLOUpdate(TunerChannel channel) throws SourceException
|
private boolean requiresLOUpdate(TunerChannel channel) throws SourceException
|
||||||
{
|
{
|
||||||
return !( getMinTunedFrequency() <= channel.getMinFrequency() &&
|
boolean isBelow = channel.getMinFrequency() < getMinTunedFrequency();
|
||||||
channel.getMaxFrequency() <= getMaxTunedFrequency() &&
|
boolean isAbove = channel.getMaxFrequency() > getMaxTunedFrequency();
|
||||||
( ( mMiddleUnusable == 0 ) ||
|
boolean overlapsCenter = mMiddleUnusable > 0 &&
|
||||||
( !channel.overlaps( getTunedFrequency() - mMiddleUnusable,
|
channel.overlaps(getFrequency() - mMiddleUnusable, getFrequency() + mMiddleUnusable);
|
||||||
getTunedFrequency() + mMiddleUnusable ) ) ) );
|
|
||||||
|
return isAbove || isBelow || overlapsCenter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Releases the currently sourced tuner channel from this tuner and shuts
|
* Releases the currently sourced tuner channel from this tuner and shuts down the tuner if no other sources exist.
|
||||||
* down the tuner if no other sources exist.
|
|
||||||
*/
|
*/
|
||||||
public void releaseChannel(TunerChannelSource tunerChannelSource)
|
public void releaseChannel(TunerChannelSource tunerChannelSource)
|
||||||
{
|
{
|
||||||
@@ -271,82 +252,79 @@ public abstract class TunerController implements Tunable, IFrequencyChangeProces
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the Local Oscillator frequency accomodate the current set of tuned
|
* Sets the Local Oscillator frequency to accomodate the current set of tuned channels.
|
||||||
* channels.
|
|
||||||
*
|
*
|
||||||
* If there is only a single tuned channel, it is placed immediately to the
|
* If there is only a single tuned channel, it is placed immediately to the right of the usable bandwidth right
|
||||||
* right of the usable bandwidth right of the central DC spike.
|
* of the central DC spike.
|
||||||
*
|
*
|
||||||
* Otherwise, it places the highest channel frequency at the upper end of
|
* Otherwise, it places the highest channel frequency at the upper end of the tuner bandwidth, and then iteratively
|
||||||
* the tuner bandwidth, and then iteratively moves the center frequency
|
* moves the center frequency higher until all channels fit within the bandwidth and none of the channels overlap
|
||||||
* higher until all channels fit within the bandwidth and none of the
|
* any defined central DC spike unusable region. If a center tune frequency cannot be calculated, throw an
|
||||||
* channels overlap any defined central DC spike unusable region. If a
|
* exception so that the most recently added channel can be removed.
|
||||||
* center tune frequency cannot be calculated, throw an exception so that
|
|
||||||
* the most recently added channel can be removed.
|
|
||||||
*
|
*
|
||||||
* Note: the tuned frequency is not changed until a legitimate new frequency
|
* Note: the tuned frequency is not changed until a legitimate new frequency can be calculated. If an exception
|
||||||
* can be calculated. If an exception is thrown, the current frequency is
|
* is thrown, the current frequency is retained, so that the recently added channel can be removed and all other
|
||||||
* retained, so that the recently added channel can be removed and all other
|
|
||||||
* channels can continue as previously arranged.
|
* channels can continue as previously arranged.
|
||||||
*
|
*
|
||||||
* @throws SourceException if the set of tuner channels, including a recently
|
* @throws SourceException if the set of tuner channels, including a recently added channel, cannot be tuned
|
||||||
* added channel, cannot be tuned within the current tuner bandwidth and any
|
* within the current tuner bandwidth and any central DC spike unusable region.
|
||||||
* central DC spike unusable region.
|
|
||||||
*/
|
*/
|
||||||
private void updateLOFrequency() throws SourceException
|
private void updateLOFrequency() throws SourceException
|
||||||
{
|
{
|
||||||
long frequency = getFrequency();
|
long candidateFrequency;
|
||||||
|
|
||||||
boolean frequencyValid = true;
|
boolean isValidCandidateFrequency = true;
|
||||||
|
|
||||||
//If there is only 1 channel, position it to the right of center
|
//If there is only 1 channel set the center frequency so that the channel is positioned to the right of center
|
||||||
if(mTunedChannels.size() == 1)
|
if(mTunedChannels.size() == 1)
|
||||||
{
|
{
|
||||||
frequency = mTunedChannels.first().getMinFrequency() - mMiddleUnusable;
|
candidateFrequency = mTunedChannels.first().getMinFrequency() - mMiddleUnusable + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
long minLockedFrequency = mTunedChannels.first().getMinFrequency();
|
long minLockedFrequency = mTunedChannels.first().getMinFrequency();
|
||||||
long maxLockedFrequency = mTunedChannels.last().getMaxFrequency();
|
long maxLockedFrequency = mTunedChannels.last().getMaxFrequency();
|
||||||
|
|
||||||
//Start by placing the highest frequency channel at the high end of
|
//Start by placing the highest frequency channel at the high end of the spectrum
|
||||||
//the spectrum
|
candidateFrequency = maxLockedFrequency - (getUsableBandwidth() / 2);
|
||||||
frequency = maxLockedFrequency - ( getUsableBandwidth() / 2 );
|
|
||||||
|
|
||||||
//Iterate the channels and make sure that none of them overlap the
|
//Iterate the channels and make sure that none of them overlap the center DC spike buffer, if one exists
|
||||||
//center DC spike buffer, if one exists
|
|
||||||
if(mMiddleUnusable > 0)
|
if(mMiddleUnusable > 0)
|
||||||
{
|
{
|
||||||
boolean processingRequired = true;
|
boolean processingRequired = true;
|
||||||
|
|
||||||
while( frequencyValid && processingRequired )
|
while(isValidCandidateFrequency && processingRequired)
|
||||||
{
|
{
|
||||||
processingRequired = false;
|
processingRequired = false;
|
||||||
|
|
||||||
long minAvoid = frequency - mMiddleUnusable;
|
long minAvoid = candidateFrequency - mMiddleUnusable;
|
||||||
long maxAvoid = frequency + mMiddleUnusable;
|
long maxAvoid = candidateFrequency + mMiddleUnusable;
|
||||||
|
|
||||||
|
//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 : mTunedChannels)
|
for(TunerChannel channel : mTunedChannels)
|
||||||
{
|
{
|
||||||
if(channel.overlaps(minAvoid, maxAvoid))
|
if(channel.overlaps(minAvoid, maxAvoid))
|
||||||
{
|
{
|
||||||
//Can we move the frequency lower so that the
|
//Calculate a tuned frequency adjustment that places this overlapping channel just to the
|
||||||
//channel sits to the right of center?
|
//left of the central DC spike avoid zone
|
||||||
long adjustment = channel.getMaxFrequency() - minAvoid;
|
long adjustment = channel.getMaxFrequency() - minAvoid + 1;
|
||||||
|
|
||||||
if( frequency + adjustment -
|
//If the candidate frequency doesn't push the lowest channel out of bounds, make adjustment
|
||||||
( getUsableBandwidth() / 2 ) <= minLockedFrequency )
|
if(candidateFrequency + adjustment - (getUsableBandwidth() / 2) <= minLockedFrequency)
|
||||||
{
|
{
|
||||||
frequency += adjustment;
|
candidateFrequency += adjustment;
|
||||||
processingRequired = true;
|
processingRequired = true;
|
||||||
}
|
}
|
||||||
|
//Otherwise, punt and indicate that we can't find a center frequency or add the channel
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
frequencyValid = false;
|
isValidCandidateFrequency = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//break out of the for/each loop, so that we can
|
//break out of the for/each loop, so that we can start over again with all of the channels
|
||||||
//start over again with all of the channels
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -354,20 +332,18 @@ public abstract class TunerController implements Tunable, IFrequencyChangeProces
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( frequencyValid )
|
if(isValidCandidateFrequency)
|
||||||
{
|
{
|
||||||
mFrequencyController.setFrequency( frequency );
|
mFrequencyController.setFrequency(candidateFrequency);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new SourceException( "Couldn't calculate viable center "
|
throw new SourceException("Couldn't calculate viable center frequency from set of tuner channels");
|
||||||
+ "frequency from set of tuner channels" );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Usable bandwidth - total bandwidth minus the unusable space at either end
|
* Usable bandwidth - total bandwidth minus the unusable space at either end of the spectrum.
|
||||||
* of the spectrum.
|
|
||||||
*/
|
*/
|
||||||
private int getUsableBandwidth()
|
private int getUsableBandwidth()
|
||||||
{
|
{
|
||||||
@@ -375,11 +351,9 @@ public abstract class TunerController implements Tunable, IFrequencyChangeProces
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the listener to be notified any time that the tuner changes frequency
|
* Sets the listener to be notified any time that the tuner changes frequency or bandwidth/sample rate.
|
||||||
* or bandwidth/sample rate.
|
|
||||||
*
|
*
|
||||||
* Note: this is normally used by the Tuner. Any additional listeners can
|
* Note: this is normally used by the Tuner. Any additional listeners can be registered on the tuner.
|
||||||
* be registered on the tuner.
|
|
||||||
*/
|
*/
|
||||||
public void addListener(IFrequencyChangeProcessor processor)
|
public void addListener(IFrequencyChangeProcessor processor)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user