From 0951277915a9d7465ef27413332ce1510b8d00e9 Mon Sep 17 00:00:00 2001 From: denny Date: Sat, 12 Dec 2015 14:08:32 -0500 Subject: [PATCH] Tuner Controller update to better handle automatic center frequency calculation when additional channels are allocated. Incorporates tuner specific definition of overall usable bandwidth, so that tuners like airspy can specify 90% of 10 MHz (ie 9 MHz) is truly usable and the fringe 10% is unusable rolloff. Also includes tuner-specific defining of the width of the central spike, or a value of 0 indicates that the entire range is usable (ie airspy). --- src/controller/channel/Channel.java | 2 +- src/source/tuner/TunerChannel.java | 20 +- src/source/tuner/TunerController.java | 246 +++++++++++++----- .../tuner/airspy/AirspyTunerController.java | 118 +-------- src/source/tuner/fcd/FCDTunerController.java | 8 +- .../tuner/hackrf/HackRFTunerController.java | 4 +- .../tuner/rtl/RTL2832TunerController.java | 9 +- .../tuner/rtl/e4k/E4KTunerController.java | 6 +- .../tuner/rtl/r820t/R820TTunerController.java | 7 +- src/spectrum/SpectralDisplayPanel.java | 1 + 10 files changed, 224 insertions(+), 197 deletions(-) diff --git a/src/controller/channel/Channel.java b/src/controller/channel/Channel.java index 0ac11a9e..3503a0e7 100644 --- a/src/controller/channel/Channel.java +++ b/src/controller/channel/Channel.java @@ -1004,7 +1004,7 @@ public class Channel extends Configuration TunerChannel tunerChannel = getTunerChannel(); return tunerChannel != null && - tunerChannel.isWithin( minimum, maximum ); + tunerChannel.overlaps( minimum, maximum ); } public void addTrafficChannel( String channelID, Channel channel ) diff --git a/src/source/tuner/TunerChannel.java b/src/source/tuner/TunerChannel.java index c873753c..7ff6e32d 100644 --- a/src/source/tuner/TunerChannel.java +++ b/src/source/tuner/TunerChannel.java @@ -1,6 +1,6 @@ /******************************************************************************* * SDR Trunk - * Copyright (C) 2014 Dennis Sheirer + * Copyright (C) 2014,2015 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 @@ -71,13 +71,17 @@ public class TunerChannel implements Comparable } /** - * Indicates if any part of this tuner channel is contained within the - * minimum and maximum frequency values. + * Indicates if any part of this tuner channel overlaps the specified range */ - public boolean isWithin( long minimum, long maximum ) + public boolean overlaps( long minimum, long maximum ) { - return ( ( minimum <= getMinFrequency() && getMinFrequency() <= maximum ) || - ( minimum <= getMaxFrequency() && getMaxFrequency() <= maximum ) ); + long channelMin = getMinFrequency(); + long channelMax = getMaxFrequency(); + + return ( ( minimum <= channelMin && channelMin <= maximum ) || + ( minimum <= channelMax && channelMax <= maximum ) || + ( minimum <= channelMin && channelMax <= maximum ) || + ( channelMin <= minimum && maximum <= channelMax ) ); } public String toString() @@ -85,9 +89,9 @@ public class TunerChannel implements Comparable StringBuilder sb = new StringBuilder(); sb.append( "Channel: " ); - sb.append( ( mFrequency - ( mBandwidth / 2 ) ) ); + sb.append( getMinFrequency() ); sb.append( "-" ); - sb.append( ( mFrequency + ( mBandwidth / 2 ) ) ); + sb.append( getMaxFrequency() ); return sb.toString(); } diff --git a/src/source/tuner/TunerController.java b/src/source/tuner/TunerController.java index 0676e4f6..1cc26637 100644 --- a/src/source/tuner/TunerController.java +++ b/src/source/tuner/TunerController.java @@ -1,6 +1,6 @@ /******************************************************************************* * SDR Trunk - * Copyright (C) 2014 Dennis Sheirer + * Copyright (C) 2014,2015 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 @@ -19,7 +19,6 @@ package source.tuner; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.concurrent.RejectedExecutionException; import org.slf4j.Logger; @@ -39,25 +38,34 @@ public abstract class TunerController implements Tunable /* List of currently tuned channels being served to demod channels */ protected ArrayList mTunedChannels = new ArrayList(); - protected FrequencyController mFrequencyController; + private int mMiddleUnusable; + private double mUsableBandwidthPercentage; /** * Abstract tuner controller class. The tuner controller manages frequency * bandwidth and currently tuned channels that are being fed samples from * the tuner. * - * @param minimumFrequency - minimum uncorrected tunable frequency - * @param maximumFrequency - maximum uncorrected tunable frequency + * @param minimumFrequency minimum uncorrected tunable frequency + * @param maximumFrequency maximum uncorrected tunable frequency + * @param middleUnusable is the +/- value center DC spike to avoid for channels + * @param extantUnusable is the unusable space at the extreme ends of the spectrum + * * @throws SourceException - for any issues related to constructing the * class, tuning a frequency, or setting the bandwidth */ - public TunerController( long minimumFrequency, long maximumFrequency ) + public TunerController( long minimumFrequency, + long maximumFrequency, + int middleUnusable, + double usableBandwidthPercentage ) { mFrequencyController = new FrequencyController( this, minimumFrequency, maximumFrequency, 0.0d ); + mMiddleUnusable = middleUnusable; + mUsableBandwidthPercentage = usableBandwidthPercentage; } /** @@ -112,24 +120,21 @@ public abstract class TunerController implements Tunable return mFrequencyController.getMaximumFrequency(); } - public long getMinTunedFrequency() + private long getMinTunedFrequency() throws SourceException { - return mFrequencyController.getFrequency() - - ( mFrequencyController.getBandwidth() / 2 ); + return mFrequencyController.getFrequency() - ( getUsableBandwidth() / 2 ); } - public long getMaxTunedFrequency() + private long getMaxTunedFrequency() throws SourceException { - return mFrequencyController.getFrequency() + - ( mFrequencyController.getBandwidth() / 2 ); + return mFrequencyController.getFrequency() + ( getUsableBandwidth() / 2 ); } /** - * Indicates if the tuner can accomodate this new channel frequency and - * bandwidth, along with all of the existing tuned channels currently in - * place. + * Indicates if channel along with all of the other currently sourced + * channels can fit within the tunable bandwidth. */ - public boolean canTuneChannel( TunerChannel channel ) + private boolean canTune( TunerChannel channel ) { //Make sure we're within the tunable frequency range of this tuner if( getMinFrequency() < channel.getMinFrequency() && @@ -145,19 +150,27 @@ public abstract class TunerController implements Tunable //Sort the existing locks and get the min/max locked frequencies Collections.sort( mTunedChannels ); + int usableBandwidth = getUsableBandwidth(); long minLockedFrequency = mTunedChannels.get( 0 ).getMinFrequency(); long maxLockedFrequency = mTunedChannels .get( mTunedChannels.size() - 1 ).getMaxFrequency(); - //Requested channel is higher than min locked frequency + //Requested channel is within current locked channel frequency range if( minLockedFrequency <= channel.getMinFrequency() && - ( channel.getMaxFrequency() - minLockedFrequency ) <= getBandwidth() ) + channel.getMaxFrequency() <= maxLockedFrequency ) + { + return true; + } + + //Requested channel is higher than min locked frequency + if( channel.getMaxFrequency() > minLockedFrequency && + channel.getMaxFrequency() - minLockedFrequency <= usableBandwidth ) { return true; } //Requested channel is lower than the max locked frequency - else if( channel.getMaxFrequency() <= maxLockedFrequency && - ( maxLockedFrequency - channel.getMinFrequency() ) <= getBandwidth() ) + if( channel.getMinFrequency() <= maxLockedFrequency && + maxLockedFrequency - channel.getMinFrequency() <= usableBandwidth ) { return true; } @@ -166,26 +179,72 @@ public abstract class TunerController implements Tunable return false; } - + + /** + * Constructs a digital drop channel (DDC) as a tuner channel from from + * the tuner, or returns null if the channel cannot be sourced from the + * tuner. + * + * This controller can't provide a channel if the channel, along with the + * current set of sourced channels, can't be accomodated within the current + * tuner bandwidth, or if a center frequency cannot be calculated that will + * ensure all of the channels can be accomodated and any defined central DC + * spike avoided. + * + * @param threadPoolManager for the channel to use for runnables + * @param tuner to source the channel from + * @param channel with defined center frequency and bandwidth + * + * @return fully constructed tuner channel or null + * + * @throws RejectedExecutionException if the decimation processor has an error + */ public TunerChannelSource getChannel( ThreadPoolManager threadPoolManager, - Tuner tuner, TunerChannel tunerChannel ) - throws RejectedExecutionException, SourceException + Tuner tuner, TunerChannel channel ) throws RejectedExecutionException { TunerChannelSource source = null; - if( canTuneChannel( tunerChannel ) ) + if( canTune( channel ) ) { - mTunedChannels.add( tunerChannel ); - - updateLOFrequency(); - - source = new TunerChannelSource( threadPoolManager, - tuner, tunerChannel ); + try + { + mTunedChannels.add( channel ); + + if( requiresLOUpdate( channel ) ) + { + updateLOFrequency(); + } + + source = new TunerChannelSource( threadPoolManager, + tuner, channel ); + } + catch( SourceException se ) + { + mTunedChannels.remove( channel ); + source = null; + } } return source; } - + + /** + * Indicates if the tuner's LO frequency must be updated in order to + * accomodate the tuner channel + */ + private boolean requiresLOUpdate( TunerChannel channel ) throws SourceException + { + return !( getMinTunedFrequency() <= channel.getMinFrequency() && + channel.getMaxFrequency() <= getMaxTunedFrequency() && + ( ( mMiddleUnusable == 0 ) || + ( !channel.overlaps( getTunedFrequency() - mMiddleUnusable, + getTunedFrequency() + mMiddleUnusable ) ) ) ); + } + + /** + * Releases the currently sourced tuner channel from this tuner and shuts + * down the tuner if no other sources exist. + */ public void releaseChannel( TunerChannelSource tunerChannelSource ) { if( tunerChannelSource != null ) @@ -194,56 +253,115 @@ public abstract class TunerController implements Tunable } else { - mLog.error( "Tuner Controller - couldn't find the tuned channel " - + "to release it" ); + mLog.error( "Request to release channel that is not in current tuned channels set" ); } } /** - * Sets the Local Oscillator frequency to the middle of the currently - * locked frequency range, adjusting the left/right of a channel, if the - * middle falls within the locked range of any of the channels. Note: this - * will fail to set the correct frequency if multiple overlapping channel - * bandwidths are locked in the exact middle of the total locked channel - * frequency range. + * Sets the Local Oscillator frequency accomodate the current set of tuned + * channels. + * + * If there is only a single tuned channel, it is placed immediately to the + * right of the usable bandwidth right of the central DC spike. + * + * Otherwise, it places the highest channel frequency at the upper end of + * the tuner bandwidth, and then iteratively moves the center frequency + * higher until all channels fit within the bandwidth and none of the + * channels overlap any defined central DC spike unusable region. If a + * 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 + * can be calculated. If an exception is thrown, the current frequency is + * retained, so that the recently added channel can be removed and all other + * channels can continue as previously arranged. * - * @throws SourceException + * @throws SourceException if the set of tuner channels, including a recently + * added channel, cannot be tuned within the current tuner bandwidth and any + * central DC spike unusable region. */ - public void updateLOFrequency() throws SourceException + private void updateLOFrequency() throws SourceException { Collections.sort( mTunedChannels ); - long minLockedFrequency = mTunedChannels.get( 0 ).getMinFrequency(); - long maxLockedFrequency = mTunedChannels - .get( mTunedChannels.size() - 1 ).getMaxFrequency(); + long frequency = getFrequency(); + + boolean frequencyValid = true; - long middle = minLockedFrequency + - ( ( maxLockedFrequency - minLockedFrequency ) / 2 ); - long middleMin = middle - 10000; - long middleMax = middle + 10000; - - Iterator it = mTunedChannels.iterator(); - - while( it.hasNext() ) + //If there is only 1 channel, position it to the right of center + if( mTunedChannels.size() == 1 ) { - TunerChannel lock = it.next(); + frequency = mTunedChannels.get( 0 ).getMinFrequency() - mMiddleUnusable; + } + else + { + long minLockedFrequency = mTunedChannels.get( 0 ).getMinFrequency(); + long maxLockedFrequency = mTunedChannels + .get( mTunedChannels.size() - 1 ).getMaxFrequency(); - //If a locked channel overlaps our middle frequency lockout, adjust to - //the left or the right of that channel, whichever is closer - if( lock.getMinFrequency() < middleMax && middleMin < lock.getMaxFrequency() ) + //Start by placing the highest frequency channel at the high end of + //the spectrum + frequency = maxLockedFrequency - ( getUsableBandwidth() / 2 ); + + //Iterate the channels and make sure that none of them overlap the + //center DC spike buffer, if one exists + if( mMiddleUnusable > 0 ) { - if( middleMax - lock.getMinFrequency() < lock.getMaxFrequency() - middleMin ) + boolean processingRequired = true; + + while( frequencyValid && processingRequired ) { - middle = lock.getMinFrequency() - 10000; - } - else - { - middle = lock.getMaxFrequency() + 10000; + processingRequired = false; + + long minAvoid = frequency - mMiddleUnusable; + long maxAvoid = frequency + mMiddleUnusable; + + for( TunerChannel channel: mTunedChannels ) + { + if( channel.overlaps( minAvoid, maxAvoid ) ) + { + //Can we move the frequency lower so that the + //channel sits to the right of center? + long adjustment = channel.getMaxFrequency() - minAvoid; + + if( frequency + adjustment - + ( getUsableBandwidth() / 2 ) <= minLockedFrequency ) + { + frequency += adjustment; + processingRequired = true; + } + else + { + frequencyValid = false; + } + + //break out of the for/each loop, so that we can + //start over again with all of the channels + break; + } + } } } } - - mFrequencyController.setFrequency( middle ); + + if( frequencyValid ) + { + mFrequencyController.setFrequency( frequency ); + } + else + { + throw new SourceException( "Couldn't calculate viable center " + + "frequency from set of tuner channels" ); + } + } + + /** + * Usable bandwidth - total bandwidth minus the unusable space at either end + * of the spectrum. + */ + private int getUsableBandwidth() + { + return (int)( getBandwidth() * mUsableBandwidthPercentage ); } /** diff --git a/src/source/tuner/airspy/AirspyTunerController.java b/src/source/tuner/airspy/AirspyTunerController.java index 16577a55..9c8b9a1f 100644 --- a/src/source/tuner/airspy/AirspyTunerController.java +++ b/src/source/tuner/airspy/AirspyTunerController.java @@ -93,6 +93,7 @@ public class AirspyTunerController extends TunerController public static final long FREQUENCY_MIN = 24000000l; public static final long FREQUENCY_MAX = 1800000000l; public static final long FREQUENCY_DEFAULT = 101100000; + public static final double USABLE_BANDWIDTH_PERCENT = 0.90; public static final AirspySampleRate DEFAULT_SAMPLE_RATE = new AirspySampleRate( 0, 10000000, "10.00 MHz" ); @@ -136,7 +137,7 @@ public class AirspyTunerController extends TunerController public AirspyTunerController( Device device, ThreadPoolManager threadPoolManager ) throws SourceException { - super( FREQUENCY_MIN, FREQUENCY_MAX ); + super( FREQUENCY_MIN, FREQUENCY_MAX, 0, USABLE_BANDWIDTH_PERCENT ); mDevice = device; mThreadPoolManager = threadPoolManager; @@ -829,121 +830,6 @@ public class AirspyTunerController extends TunerController } } - /** - * Indicates if the tuner can accommodate this new channel frequency and - * bandwidth, along with all of the existing tuned channels currently in - * place. - */ - public boolean canTuneChannel( TunerChannel channel ) - { - //If this is the first lock, then we're good - if( mTunedChannels.isEmpty() ) - { - return true; - } - else - { - //Sort the existing locks and get the min/max locked frequencies - Collections.sort( mTunedChannels ); - - long minLockedFrequency = mTunedChannels.get( 0 ).getMinFrequency(); - long maxLockedFrequency = mTunedChannels - .get( mTunedChannels.size() - 1 ).getMaxFrequency(); - - if( channel.getMinFrequency() >= minLockedFrequency && - channel.getMaxFrequency() <= maxLockedFrequency ) - { - return true; - } - - int usable = getUsableBandwidth(); - - if( channel.getMinFrequency() < minLockedFrequency ) - { - return ( maxLockedFrequency - channel.getMinFrequency() ) <= usable; - } - - if( channel.getMaxFrequency() > maxLockedFrequency ) - { - return ( channel.getMaxFrequency() - minLockedFrequency ) <= usable; - } - } - - return false; - } - - /** - * Limits the usable bandwidth of the tuner to 90% of the bandwidth to - * account for roll-off at the band edges - */ - private int getUsableBandwidth() - { - return (int)( (double)getBandwidth() * 0.9d ); - } - - /** - * Overrides the default tuner controller method to limit the total bandwidth - * of the tuner to 90% and adjust the min tuned frequency accordingly - */ - public long getMinTunedFrequency() - { - return mFrequencyController.getFrequency() - ( getUsableBandwidth() / 2 ); - } - - /** - * Overrides the default tuner controller method to limit the total bandwidth - * of the tuner to 90% and adjust the max tuned frequency accordingly - */ - public long getMaxTunedFrequency() - { - return mFrequencyController.getFrequency() + ( getUsableBandwidth() / 2 ); - } - - public TunerChannelSource getChannel( ThreadPoolManager threadPoolManager, - Tuner tuner, TunerChannel tunerChannel ) - throws RejectedExecutionException, SourceException - { - TunerChannelSource source = null; - - if( canTuneChannel( tunerChannel ) ) - { - mTunedChannels.add( tunerChannel ); - - Collections.sort( mTunedChannels ); - - long min = mTunedChannels.get( 0 ).getMinFrequency(); - long max = mTunedChannels.get( mTunedChannels.size() - 1 ).getMaxFrequency(); - - /* Adjust the center frequency if the set of tuner channels don't - * currently fit within the usable bandwidth and current center frequency */ - if( !( getMinTunedFrequency() <= min && max <= getMaxTunedFrequency() ) ) - { - long freq = min + ( ( max - min ) / 2 ); - - mFrequencyController.setFrequency( freq ); - } - - source = new TunerChannelSource( threadPoolManager, - tuner, tunerChannel ); - } - - return source; - } - - public void releaseChannel( TunerChannelSource tunerChannelSource ) - { - if( tunerChannelSource != null ) - { - mTunedChannels.remove( tunerChannelSource.getTunerChannel() ); - } - else - { - mLog.error( "Tuner Controller - couldn't find the tuned channel " - + "to release it" ); - } - } - - /** * Airspy Board Identifier */ diff --git a/src/source/tuner/fcd/FCDTunerController.java b/src/source/tuner/fcd/FCDTunerController.java index 03a49b56..cead5092 100644 --- a/src/source/tuner/fcd/FCDTunerController.java +++ b/src/source/tuner/fcd/FCDTunerController.java @@ -46,6 +46,9 @@ public abstract class FCDTunerController extends TunerController private final static Logger mLog = LoggerFactory.getLogger( FCDTunerController.class ); + public static final double USABLE_BANDWIDTH_PERCENT = 1.0; + public static final int DC_SPIKE_AVOID_BUFFER = 2000; + public final static byte FCD_INTERFACE = (byte)0x2; public final static byte FCD_ENDPOINT_IN = (byte)0x82; public final static byte FCD_ENDPOINT_OUT = (byte)0x2; @@ -70,7 +73,10 @@ public abstract class FCDTunerController extends TunerController int minTunableFrequency, int maxTunableFrequency ) { - super( minTunableFrequency, maxTunableFrequency ); + super( minTunableFrequency, + maxTunableFrequency, + DC_SPIKE_AVOID_BUFFER, + USABLE_BANDWIDTH_PERCENT ); mDevice = device; mDeviceDescriptor = descriptor; diff --git a/src/source/tuner/hackrf/HackRFTunerController.java b/src/source/tuner/hackrf/HackRFTunerController.java index 8d27e7f4..bdc3bce2 100644 --- a/src/source/tuner/hackrf/HackRFTunerController.java +++ b/src/source/tuner/hackrf/HackRFTunerController.java @@ -108,6 +108,8 @@ public class HackRFTunerController extends TunerController public static final long MIN_FREQUENCY = 10000000l; public static final long MAX_FREQUENCY = 6000000000l; public static final long DEFAULT_FREQUENCY = 101100000; + public static final double USABLE_BANDWIDTH_PERCENT = 0.95; + public static final int DC_SPIKE_AVOID_BUFFER = 5000; public final static int TRANSFER_BUFFER_POOL_SIZE = 16; @@ -131,7 +133,7 @@ public class HackRFTunerController extends TunerController public HackRFTunerController( Device device, DeviceDescriptor descriptor, ThreadPoolManager threadPoolManager ) throws SourceException { - super( MIN_FREQUENCY, MAX_FREQUENCY ); + super( MIN_FREQUENCY, MAX_FREQUENCY, DC_SPIKE_AVOID_BUFFER, USABLE_BANDWIDTH_PERCENT ); mDevice = device; mDeviceDescriptor = descriptor; diff --git a/src/source/tuner/rtl/RTL2832TunerController.java b/src/source/tuner/rtl/RTL2832TunerController.java index d38a8cfb..c9eb524e 100644 --- a/src/source/tuner/rtl/RTL2832TunerController.java +++ b/src/source/tuner/rtl/RTL2832TunerController.java @@ -137,9 +137,14 @@ public abstract class RTL2832TunerController extends TunerController DeviceDescriptor deviceDescriptor, ThreadPoolManager threadPoolManager, long minTunableFrequency, - long maxTunableFrequency ) throws SourceException + long maxTunableFrequency, + int centerUnusableBandwidth, + double usableBandwidthPercentage ) throws SourceException { - super( minTunableFrequency, maxTunableFrequency ); + super( minTunableFrequency, + maxTunableFrequency, + centerUnusableBandwidth, + usableBandwidthPercentage ); mThreadPoolManager = threadPoolManager; diff --git a/src/source/tuner/rtl/e4k/E4KTunerController.java b/src/source/tuner/rtl/e4k/E4KTunerController.java index 57a58578..6bdfb149 100644 --- a/src/source/tuner/rtl/e4k/E4KTunerController.java +++ b/src/source/tuner/rtl/e4k/E4KTunerController.java @@ -44,6 +44,8 @@ public class E4KTunerController extends RTL2832TunerController public static final long MIN_FREQUENCY = 52000000; public static final long MAX_FREQUENCY = 2200000000l; + public static final double USABLE_BANDWIDTH_PERCENT = 0.95; + public static final int DC_SPIKE_AVOID_BUFFER = 15000; /* The local oscillator is defined by whole (integer) units of the oscillator * frequency and fractional units representing 1/65536th of the oscillator @@ -115,8 +117,8 @@ public class E4KTunerController extends RTL2832TunerController ThreadPoolManager threadPoolManager ) throws SourceException { - super( device, deviceDescriptor, threadPoolManager, - MIN_FREQUENCY, MAX_FREQUENCY ); + super( device, deviceDescriptor, threadPoolManager, MIN_FREQUENCY, + MAX_FREQUENCY, DC_SPIKE_AVOID_BUFFER, USABLE_BANDWIDTH_PERCENT ); } @Override diff --git a/src/source/tuner/rtl/r820t/R820TTunerController.java b/src/source/tuner/rtl/r820t/R820TTunerController.java index 4d8ec9ce..607482d4 100644 --- a/src/source/tuner/rtl/r820t/R820TTunerController.java +++ b/src/source/tuner/rtl/r820t/R820TTunerController.java @@ -47,6 +47,9 @@ public class R820TTunerController extends RTL2832TunerController public static final long MIN_FREQUENCY = 3180000; public static final long MAX_FREQUENCY = 1782030000; + public static final double USABLE_BANDWIDTH_PERCENT = 1.0; + public static final int DC_SPIKE_AVOID_BUFFER = 2500; + public static final int R820T_IF_FREQUENCY = 3570000; public static final byte VERSION = (byte)49; @@ -78,8 +81,8 @@ public class R820TTunerController extends RTL2832TunerController ThreadPoolManager threadPoolManager ) throws SourceException { - super( device, deviceDescriptor, threadPoolManager, - MIN_FREQUENCY, MAX_FREQUENCY ); + super( device, deviceDescriptor, threadPoolManager, MIN_FREQUENCY, + MAX_FREQUENCY, DC_SPIKE_AVOID_BUFFER, USABLE_BANDWIDTH_PERCENT ); } @Override diff --git a/src/spectrum/SpectralDisplayPanel.java b/src/spectrum/SpectralDisplayPanel.java index 4b1252c6..dce94b2c 100644 --- a/src/spectrum/SpectralDisplayPanel.java +++ b/src/spectrum/SpectralDisplayPanel.java @@ -28,6 +28,7 @@ import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; import java.text.DecimalFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Hashtable; import javax.swing.JCheckBoxMenuItem;