mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-14 09:37:36 -05:00
#39 WIP polyphase channelizers.
This commit is contained in:
@@ -834,9 +834,10 @@ public class FilterFactory
|
|||||||
if(logResults)
|
if(logResults)
|
||||||
{
|
{
|
||||||
mLog.debug("Polyphase TunerChannelizer Filter Design Summary");
|
mLog.debug("Polyphase TunerChannelizer Filter Design Summary");
|
||||||
mLog.debug("-------------------------------------------");
|
mLog.debug("-----------------------------------------------------");
|
||||||
|
mLog.debug("Window Type: " + windowType.name());
|
||||||
mLog.debug("Channels: " + channels);
|
mLog.debug("Channels: " + channels);
|
||||||
mLog.debug("Taps Per Channel: " + tapsPerChannel);
|
mLog.debug("Taps Per Channel: " + tapsPerChannel + " (Requested:" + tapsPerChannel + ")");
|
||||||
mLog.debug("Filter Length: " + (taps.length + 1));
|
mLog.debug("Filter Length: " + (taps.length + 1));
|
||||||
mLog.debug("Channel Bandwidth: " + channelBandwidth);
|
mLog.debug("Channel Bandwidth: " + channelBandwidth);
|
||||||
mLog.debug("Cutoff Frequency: " + (sampleRate * cutoffFrequency));
|
mLog.debug("Cutoff Frequency: " + (sampleRate * cutoffFrequency));
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import sample.complex.ComplexBuffer;
|
|||||||
import source.ISourceEventListener;
|
import source.ISourceEventListener;
|
||||||
import source.SourceEvent;
|
import source.SourceEvent;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
|
|||||||
@@ -187,6 +187,9 @@ public class ChannelIndexCalculator
|
|||||||
*/
|
*/
|
||||||
public List<Integer> getPolyphaseChannelIndexes(TunerChannel tunerChannel) throws IllegalArgumentException
|
public List<Integer> getPolyphaseChannelIndexes(TunerChannel tunerChannel) throws IllegalArgumentException
|
||||||
{
|
{
|
||||||
|
long min = getMinimumFrequency();
|
||||||
|
long max = getMaximumFrequency();
|
||||||
|
|
||||||
if(tunerChannel.getMinFrequency() < getMinimumFrequency() ||
|
if(tunerChannel.getMinFrequency() < getMinimumFrequency() ||
|
||||||
tunerChannel.getMaxFrequency() > getMaximumFrequency())
|
tunerChannel.getMaxFrequency() > getMaximumFrequency())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import source.tuner.TunerChannel;
|
|||||||
import source.tuner.configuration.TunerConfigurationModel;
|
import source.tuner.configuration.TunerConfigurationModel;
|
||||||
import source.tuner.test.TestTuner;
|
import source.tuner.test.TestTuner;
|
||||||
import spectrum.DFTProcessor;
|
import spectrum.DFTProcessor;
|
||||||
|
import spectrum.DFTResultsListener;
|
||||||
import spectrum.DFTSize;
|
import spectrum.DFTSize;
|
||||||
import spectrum.SpectrumPanel;
|
import spectrum.SpectrumPanel;
|
||||||
import spectrum.converter.ComplexDecibelConverter;
|
import spectrum.converter.ComplexDecibelConverter;
|
||||||
@@ -56,8 +57,6 @@ public class ChannelizerViewer extends JFrame
|
|||||||
private ChannelArrayPanel mChannelPanel;
|
private ChannelArrayPanel mChannelPanel;
|
||||||
private int mChannelCount;
|
private int mChannelCount;
|
||||||
private int mChannelsPerRow;
|
private int mChannelsPerRow;
|
||||||
private int mFilterTapsPerChannel;
|
|
||||||
private int mSampleRate;
|
|
||||||
private long mToneFrequency;
|
private long mToneFrequency;
|
||||||
private DFTSize mMainPanelDFTSize = DFTSize.FFT32768;
|
private DFTSize mMainPanelDFTSize = DFTSize.FFT32768;
|
||||||
private DFTSize mChannelPanelDFTSize = DFTSize.FFT00512;
|
private DFTSize mChannelPanelDFTSize = DFTSize.FFT00512;
|
||||||
@@ -66,19 +65,15 @@ public class ChannelizerViewer extends JFrame
|
|||||||
/**
|
/**
|
||||||
* GUI Test utility for researching polyphase channelizers.
|
* GUI Test utility for researching polyphase channelizers.
|
||||||
*
|
*
|
||||||
* @param channelCount
|
|
||||||
* @param channelsPerRow
|
* @param channelsPerRow
|
||||||
*/
|
*/
|
||||||
public ChannelizerViewer(int channelCount, int channelsPerRow, int tapsPerChannel)
|
public ChannelizerViewer(int channelsPerRow)
|
||||||
{
|
{
|
||||||
mChannelCount = channelCount;
|
|
||||||
mChannelsPerRow = channelsPerRow;
|
|
||||||
mFilterTapsPerChannel = tapsPerChannel;
|
|
||||||
|
|
||||||
mSampleRate = mChannelCount * CHANNEL_BANDWIDTH;
|
|
||||||
|
|
||||||
mTestTuner = new TestTuner();
|
mTestTuner = new TestTuner();
|
||||||
|
|
||||||
|
mChannelCount = mTestTuner.getSampleRate() / CHANNEL_BANDWIDTH;
|
||||||
|
mChannelsPerRow = channelsPerRow;
|
||||||
|
|
||||||
mToneFrequency = mTestTuner.getTunerController().getFrequency() +
|
mToneFrequency = mTestTuner.getTunerController().getFrequency() +
|
||||||
(int)(CHANNEL_BANDWIDTH * 1); //Set to channel 1 as default
|
(int)(CHANNEL_BANDWIDTH * 1); //Set to channel 1 as default
|
||||||
|
|
||||||
@@ -115,7 +110,7 @@ public class ChannelizerViewer extends JFrame
|
|||||||
{
|
{
|
||||||
if(mPrimarySpectrumPanel == null)
|
if(mPrimarySpectrumPanel == null)
|
||||||
{
|
{
|
||||||
mPrimarySpectrumPanel = new PrimarySpectrumPanel(mSettingsManager, mSampleRate);
|
mPrimarySpectrumPanel = new PrimarySpectrumPanel(mSettingsManager, mTestTuner.getSampleRate());
|
||||||
mPrimarySpectrumPanel.setPreferredSize(new Dimension(1000, 200));
|
mPrimarySpectrumPanel.setPreferredSize(new Dimension(1000, 200));
|
||||||
mPrimarySpectrumPanel.setDFTSize(mMainPanelDFTSize);
|
mPrimarySpectrumPanel.setDFTSize(mMainPanelDFTSize);
|
||||||
mTestTuner.addListener(mPrimarySpectrumPanel);
|
mTestTuner.addListener(mPrimarySpectrumPanel);
|
||||||
@@ -132,7 +127,7 @@ public class ChannelizerViewer extends JFrame
|
|||||||
mControlPanel.setLayout(new MigLayout("insets 0 0 0 0", "", ""));
|
mControlPanel.setLayout(new MigLayout("insets 0 0 0 0", "", ""));
|
||||||
|
|
||||||
mControlPanel.add(new JLabel("Tone:"), "align left");
|
mControlPanel.add(new JLabel("Tone:"), "align left");
|
||||||
int maximumFrequencyOffset = mSampleRate / 2;
|
int maximumFrequencyOffset = mTestTuner.getSampleRate() / 2;
|
||||||
long minimumFrequency = mTestTuner.getTunerController().getFrequency() - maximumFrequencyOffset;
|
long minimumFrequency = mTestTuner.getTunerController().getFrequency() - maximumFrequencyOffset;
|
||||||
long maximumFrequency = mTestTuner.getTunerController().getFrequency() + maximumFrequencyOffset;
|
long maximumFrequency = mTestTuner.getTunerController().getFrequency() + maximumFrequencyOffset;
|
||||||
|
|
||||||
@@ -154,9 +149,9 @@ public class ChannelizerViewer extends JFrame
|
|||||||
mControlPanel.add(spinner);
|
mControlPanel.add(spinner);
|
||||||
mControlPanel.add(new JLabel("Hz"));
|
mControlPanel.add(new JLabel("Hz"));
|
||||||
|
|
||||||
mControlPanel.add(new JLabel("Sample Rate: " + mSampleRate + " Hz"), "push,align right");
|
mControlPanel.add(new JLabel("Sample Rate: " + mTestTuner.getSampleRate() + " Hz"), "push,align right");
|
||||||
|
|
||||||
mControlPanel.add(new JLabel("Max: " + (mSampleRate / 2) + " Hz"), "push,align right");
|
mControlPanel.add(new JLabel("Max: " + (mTestTuner.getSampleRate() / 2) + " Hz"), "push,align right");
|
||||||
mControlPanel.add(new JLabel("Channels: " + mChannelCount), "push,align right");
|
mControlPanel.add(new JLabel("Channels: " + mChannelCount), "push,align right");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,15 +191,20 @@ public class ChannelizerViewer extends JFrame
|
|||||||
{
|
{
|
||||||
setLayout(new MigLayout("insets 0 0 0 0", "fill", "fill"));
|
setLayout(new MigLayout("insets 0 0 0 0", "fill", "fill"));
|
||||||
|
|
||||||
long spectralBandwidth = mChannelCount * CHANNEL_BANDWIDTH;
|
long spectralBandwidth = mTestTuner.getSampleRate();
|
||||||
long halfSpectralBandwidth = spectralBandwidth / 2;
|
long halfSpectralBandwidth = spectralBandwidth / 2;
|
||||||
|
|
||||||
|
int channelToLog = -1;
|
||||||
|
|
||||||
for(int x = 0; x < mChannelCount; x++)
|
for(int x = 0; x < mChannelCount; x++)
|
||||||
{
|
{
|
||||||
//place the channels left and right of 10.0 MHz
|
//place the channels left and right of 10.0 MHz
|
||||||
long frequency = mTestTuner.getTunerController().getFrequency() +
|
long frequency = mTestTuner.getTunerController().getFrequency() +
|
||||||
((x * CHANNEL_BANDWIDTH) - halfSpectralBandwidth);
|
((x * CHANNEL_BANDWIDTH) - halfSpectralBandwidth) + (CHANNEL_BANDWIDTH / 2);
|
||||||
ChannelPanel channelPanel = new ChannelPanel(mSettingsManager, CHANNEL_BANDWIDTH * 2, frequency, CHANNEL_BANDWIDTH);
|
|
||||||
|
mLog.debug("Channel " + x + " Frequency: " + frequency);
|
||||||
|
|
||||||
|
ChannelPanel channelPanel = new ChannelPanel(mSettingsManager, CHANNEL_BANDWIDTH * 2, frequency, CHANNEL_BANDWIDTH, (x == channelToLog));
|
||||||
channelPanel.setDFTSize(mChannelPanelDFTSize);
|
channelPanel.setDFTSize(mChannelPanelDFTSize);
|
||||||
|
|
||||||
if(x % mChannelsPerRow == mChannelsPerRow - 1)
|
if(x % mChannelsPerRow == mChannelsPerRow - 1)
|
||||||
@@ -260,8 +260,9 @@ public class ChannelizerViewer extends JFrame
|
|||||||
private DFTProcessor mDFTProcessor = new DFTProcessor(SampleType.COMPLEX);
|
private DFTProcessor mDFTProcessor = new DFTProcessor(SampleType.COMPLEX);
|
||||||
private ComplexDecibelConverter mComplexDecibelConverter = new ComplexDecibelConverter();
|
private ComplexDecibelConverter mComplexDecibelConverter = new ComplexDecibelConverter();
|
||||||
private SpectrumPanel mSpectrumPanel;
|
private SpectrumPanel mSpectrumPanel;
|
||||||
|
private long mFrequency;
|
||||||
|
|
||||||
public ChannelPanel(SettingsManager settingsManager, int sampleRate, long frequency, int bandwidth)
|
public ChannelPanel(SettingsManager settingsManager, int sampleRate, long frequency, int bandwidth, boolean enableLogging)
|
||||||
{
|
{
|
||||||
setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[grow,fill]"));
|
setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[grow,fill]"));
|
||||||
mSpectrumPanel = new SpectrumPanel(settingsManager);
|
mSpectrumPanel = new SpectrumPanel(settingsManager);
|
||||||
@@ -269,14 +270,32 @@ public class ChannelizerViewer extends JFrame
|
|||||||
|
|
||||||
mDFTProcessor.addConverter(mComplexDecibelConverter);
|
mDFTProcessor.addConverter(mComplexDecibelConverter);
|
||||||
mDFTProcessor.process(SourceEvent.sampleRateChange(sampleRate));
|
mDFTProcessor.process(SourceEvent.sampleRateChange(sampleRate));
|
||||||
|
|
||||||
mComplexDecibelConverter.addListener(mSpectrumPanel);
|
mComplexDecibelConverter.addListener(mSpectrumPanel);
|
||||||
|
|
||||||
|
mFrequency = frequency;
|
||||||
|
|
||||||
TunerChannel tunerChannel = new TunerChannel(frequency, bandwidth);
|
TunerChannel tunerChannel = new TunerChannel(frequency, bandwidth);
|
||||||
mSource = (PolyphaseChannelSource)mTestTuner.getChannelSource(tunerChannel);
|
mSource = (PolyphaseChannelSource)mTestTuner.getChannelSource(tunerChannel);
|
||||||
|
|
||||||
if(mSource != null)
|
if(mSource != null)
|
||||||
{
|
{
|
||||||
mSource.setListener(mDFTProcessor);
|
if(enableLogging)
|
||||||
|
{
|
||||||
|
mSource.setListener(new Listener<ComplexBuffer>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void receive(ComplexBuffer complexBuffer)
|
||||||
|
{
|
||||||
|
mLog.debug("Sending samples to DFT processor: " + complexBuffer.getSamples().length);
|
||||||
|
mDFTProcessor.receive(complexBuffer);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mSource.setListener(mDFTProcessor);
|
||||||
|
}
|
||||||
mSource.start(ThreadPool.SCHEDULED);
|
mSource.start(ThreadPool.SCHEDULED);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -298,6 +317,7 @@ public class ChannelizerViewer extends JFrame
|
|||||||
@Override
|
@Override
|
||||||
public void receive(ComplexBuffer complexBuffer)
|
public void receive(ComplexBuffer complexBuffer)
|
||||||
{
|
{
|
||||||
|
mLog.debug("Got a buffer for the channel dft processor");
|
||||||
mDFTProcessor.receive(complexBuffer);
|
mDFTProcessor.receive(complexBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,11 +330,9 @@ public class ChannelizerViewer extends JFrame
|
|||||||
|
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
{
|
{
|
||||||
int channelCount = 160;
|
int channelsPerRow = 4;
|
||||||
int channelsPerRow = 20;
|
|
||||||
int tapsPerChannel = 17;
|
|
||||||
|
|
||||||
final ChannelizerViewer frame = new ChannelizerViewer(channelCount, channelsPerRow, tapsPerChannel);
|
final ChannelizerViewer frame = new ChannelizerViewer(channelsPerRow);
|
||||||
|
|
||||||
EventQueue.invokeLater(new Runnable()
|
EventQueue.invokeLater(new Runnable()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -77,14 +77,14 @@ public class ComplexPolyphaseChannelizerM2 extends AbstractComplexPolyphaseChann
|
|||||||
*
|
*
|
||||||
* @param sampleRate to be channelized.
|
* @param sampleRate to be channelized.
|
||||||
*/
|
*/
|
||||||
private ComplexPolyphaseChannelizerM2(int sampleRate) throws FilterDesignException
|
private ComplexPolyphaseChannelizerM2(int sampleRate, int tapsPerFilter) throws FilterDesignException
|
||||||
{
|
{
|
||||||
super(sampleRate / DEFAULT_CHANNEL_BANDWIDTH, DEFAULT_CHANNEL_BANDWIDTH);
|
super(sampleRate / DEFAULT_CHANNEL_BANDWIDTH, DEFAULT_CHANNEL_BANDWIDTH);
|
||||||
|
|
||||||
mLog.debug("Sample Rate: " + sampleRate);
|
mLog.debug("Sample Rate: " + sampleRate);
|
||||||
|
|
||||||
float[] filterTaps = FilterFactory.getSincChannelizer(getChannelSampleRate(), getChannelCount(),
|
float[] filterTaps = FilterFactory.getSincChannelizer(getChannelSampleRate(), getChannelCount(),
|
||||||
15, Window.WindowType.BLACKMAN_HARRIS_7, true);
|
tapsPerFilter, Window.WindowType.BLACKMAN_HARRIS_7, true);
|
||||||
|
|
||||||
initFilters(filterTaps);
|
initFilters(filterTaps);
|
||||||
}
|
}
|
||||||
@@ -97,7 +97,7 @@ public class ComplexPolyphaseChannelizerM2 extends AbstractComplexPolyphaseChann
|
|||||||
* @return channelizer
|
* @return channelizer
|
||||||
* @throws IllegalArgumentException if the sample rate argument is not an even multiple of 25.0 kHz
|
* @throws IllegalArgumentException if the sample rate argument is not an even multiple of 25.0 kHz
|
||||||
*/
|
*/
|
||||||
public static ComplexPolyphaseChannelizerM2 create(int sampleRate) throws IllegalArgumentException,
|
public static ComplexPolyphaseChannelizerM2 create(int sampleRate, int tapsPerFilter) throws IllegalArgumentException,
|
||||||
FilterDesignException
|
FilterDesignException
|
||||||
{
|
{
|
||||||
if(sampleRate % (2 * DEFAULT_CHANNEL_BANDWIDTH) != 0)
|
if(sampleRate % (2 * DEFAULT_CHANNEL_BANDWIDTH) != 0)
|
||||||
@@ -105,7 +105,7 @@ public class ComplexPolyphaseChannelizerM2 extends AbstractComplexPolyphaseChann
|
|||||||
throw new IllegalArgumentException("Sample rate must be an even multiple of 25 kHz");
|
throw new IllegalArgumentException("Sample rate must be an even multiple of 25 kHz");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ComplexPolyphaseChannelizerM2(sampleRate);
|
return new ComplexPolyphaseChannelizerM2(sampleRate, tapsPerFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public class PolyphaseChannelManager implements Listener<SourceEvent>
|
|||||||
private static final int CHANNEL_BANDWIDTH = 12500;
|
private static final int CHANNEL_BANDWIDTH = 12500;
|
||||||
private static final double CHANNEL_OVERSAMPLING = 2.0;
|
private static final double CHANNEL_OVERSAMPLING = 2.0;
|
||||||
private static final int CHANNEL_SAMPLE_RATE = (int)(CHANNEL_BANDWIDTH * CHANNEL_OVERSAMPLING);
|
private static final int CHANNEL_SAMPLE_RATE = (int)(CHANNEL_BANDWIDTH * CHANNEL_OVERSAMPLING);
|
||||||
|
private static final int POLYPHASE_FILTER_TAPS_PER_CHANNEL = 17;
|
||||||
|
|
||||||
private Tuner mTuner;
|
private Tuner mTuner;
|
||||||
private List<PolyphaseChannelSource> mChannelSources = new CopyOnWriteArrayList<>();
|
private List<PolyphaseChannelSource> mChannelSources = new CopyOnWriteArrayList<>();
|
||||||
@@ -232,7 +233,9 @@ public class PolyphaseChannelManager implements Listener<SourceEvent>
|
|||||||
{
|
{
|
||||||
if(mPolyphaseChannelizer == null)
|
if(mPolyphaseChannelizer == null)
|
||||||
{
|
{
|
||||||
mPolyphaseChannelizer = ComplexPolyphaseChannelizerM2.create(sampleRate);
|
mPolyphaseChannelizer = ComplexPolyphaseChannelizerM2.create(sampleRate,
|
||||||
|
POLYPHASE_FILTER_TAPS_PER_CHANNEL);
|
||||||
|
|
||||||
mBufferProcessor.setListener(mPolyphaseChannelizer);
|
mBufferProcessor.setListener(mPolyphaseChannelizer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import source.SourceEvent;
|
|||||||
import source.SourceException;
|
import source.SourceException;
|
||||||
import source.tuner.TunerChannel;
|
import source.tuner.TunerChannel;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@@ -67,15 +68,29 @@ public class PolyphaseChannelSource extends ComplexSource implements ISourceEven
|
|||||||
mPolyphaseChannelOutputProcessor = outputProcessor;
|
mPolyphaseChannelOutputProcessor = outputProcessor;
|
||||||
mUpstreamSourceEventHandler = new UpstreamSourceEventHandler(externalEventListener);;
|
mUpstreamSourceEventHandler = new UpstreamSourceEventHandler(externalEventListener);;
|
||||||
mChannelSampleRate = channelSampleRate;
|
mChannelSampleRate = channelSampleRate;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the listener to receive complex sample buffers from this channel source
|
* Registers the listener to receive complex sample buffers from this channel source
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setListener(Listener<ComplexBuffer> listener)
|
public void setListener(final Listener<ComplexBuffer> listener)
|
||||||
{
|
{
|
||||||
mComplexBufferAssembler.setListener(listener);
|
// mComplexBufferAssembler.setListener(listener);
|
||||||
|
|
||||||
|
mComplexBufferAssembler.setListener(new Listener<ComplexBuffer>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void receive(ComplexBuffer complexBuffer)
|
||||||
|
{
|
||||||
|
if(mTunerChannel.getFrequency() == 99981250)
|
||||||
|
{
|
||||||
|
// mLog.debug(Arrays.toString(complexBuffer.getSamples()));
|
||||||
|
}
|
||||||
|
listener.receive(complexBuffer);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package dsp.filter.channelizer;
|
package dsp.filter.channelizer;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import sample.Listener;
|
import sample.Listener;
|
||||||
import sample.OverflowableTransferQueue;
|
import sample.OverflowableTransferQueue;
|
||||||
import sample.real.IOverflowListener;
|
import sample.real.IOverflowListener;
|
||||||
@@ -31,6 +33,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
|
|
||||||
public class ScheduledBufferProcessor<E> implements Listener<E>
|
public class ScheduledBufferProcessor<E> implements Listener<E>
|
||||||
{
|
{
|
||||||
|
private final static Logger mLog = LoggerFactory.getLogger(ScheduledBufferProcessor.class);
|
||||||
|
|
||||||
private OverflowableTransferQueue<E> mQueue;
|
private OverflowableTransferQueue<E> mQueue;
|
||||||
private Listener<E> mListener;
|
private Listener<E> mListener;
|
||||||
private ScheduledFuture<?> mScheduledFuture;
|
private ScheduledFuture<?> mScheduledFuture;
|
||||||
@@ -59,6 +63,15 @@ public class ScheduledBufferProcessor<E> implements Listener<E>
|
|||||||
public ScheduledBufferProcessor(int maximumSize, int resetThreshold, long distributionInterval, int maxBuffersPerInterval)
|
public ScheduledBufferProcessor(int maximumSize, int resetThreshold, long distributionInterval, int maxBuffersPerInterval)
|
||||||
{
|
{
|
||||||
mQueue = new OverflowableTransferQueue<>(maximumSize, resetThreshold);
|
mQueue = new OverflowableTransferQueue<>(maximumSize, resetThreshold);
|
||||||
|
|
||||||
|
mQueue.setOverflowListener(new IOverflowListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void sourceOverflow(boolean overflow)
|
||||||
|
{
|
||||||
|
mLog.error("Overflow state changed - overflow:" + overflow);
|
||||||
|
}
|
||||||
|
});
|
||||||
mDistributionInterval = distributionInterval;
|
mDistributionInterval = distributionInterval;
|
||||||
mMaxBuffersPerInterval = maxBuffersPerInterval;
|
mMaxBuffersPerInterval = maxBuffersPerInterval;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,14 +33,14 @@ public abstract class ChannelOutputProcessor implements IPolyphaseChannelOutputP
|
|||||||
{
|
{
|
||||||
private final static Logger mLog = LoggerFactory.getLogger(ChannelOutputProcessor.class);
|
private final static Logger mLog = LoggerFactory.getLogger(ChannelOutputProcessor.class);
|
||||||
|
|
||||||
private static final int OVERFLOW_THRESHOLD = 25000 * 3; //25 kHz * 3 seconds
|
|
||||||
private static final int RESET_THRESHOLD = (int)(OVERFLOW_THRESHOLD * .25); //reset at 25%
|
|
||||||
|
|
||||||
private OverflowableTransferQueue<float[]> mChannelResultsQueue;
|
private OverflowableTransferQueue<float[]> mChannelResultsQueue;
|
||||||
private List<float[]> mChannelResultsToProcess = new ArrayList<>();
|
private List<float[]> mChannelResultsToProcess = new ArrayList<>();
|
||||||
|
private int mMaxResultsToProcess;
|
||||||
|
|
||||||
private int mInputChannelCount;
|
private int mInputChannelCount;
|
||||||
|
//TODO: swap this out and use the LowPhaseNoiseOscillator
|
||||||
private Oscillator mFrequencyCorrectionMixer;
|
private Oscillator mFrequencyCorrectionMixer;
|
||||||
|
private boolean mFrequencyCorrectionEnabled;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for polyphase channelizer output channel processing. Provides built-in frequency translation
|
* Base class for polyphase channelizer output channel processing. Provides built-in frequency translation
|
||||||
@@ -54,7 +54,9 @@ public abstract class ChannelOutputProcessor implements IPolyphaseChannelOutputP
|
|||||||
{
|
{
|
||||||
mInputChannelCount = inputChannelCount;
|
mInputChannelCount = inputChannelCount;
|
||||||
mFrequencyCorrectionMixer = new Oscillator(0, sampleRate);
|
mFrequencyCorrectionMixer = new Oscillator(0, sampleRate);
|
||||||
mChannelResultsQueue = new OverflowableTransferQueue<>(OVERFLOW_THRESHOLD, RESET_THRESHOLD);
|
mMaxResultsToProcess = sampleRate / 10 * 2; //process at 100 millis interval, twice the expected inflow rate
|
||||||
|
|
||||||
|
mChannelResultsQueue = new OverflowableTransferQueue<>(sampleRate * 3, (int)(sampleRate * 0.5));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -72,33 +74,27 @@ public abstract class ChannelOutputProcessor implements IPolyphaseChannelOutputP
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mChannelResultsQueue.drainTo(mChannelResultsToProcess, 1000);
|
int count = mChannelResultsQueue.drainTo(mChannelResultsToProcess, mMaxResultsToProcess);
|
||||||
|
|
||||||
while(!mChannelResultsToProcess.isEmpty())
|
if(count > 0)
|
||||||
{
|
{
|
||||||
for(float[] channelResults: mChannelResultsToProcess)
|
process(mChannelResultsToProcess, listener);
|
||||||
{
|
|
||||||
process(channelResults, listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
mChannelResultsToProcess.clear();
|
|
||||||
mChannelResultsQueue.drainTo(mChannelResultsToProcess, 1000);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(Throwable throwable)
|
catch(Throwable throwable)
|
||||||
{
|
{
|
||||||
mLog.error("Error while processing polyphase channel samples", throwable);
|
mLog.error("Error while processing polyphase channel samples", throwable);
|
||||||
mChannelResultsToProcess.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mChannelResultsToProcess.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sub-class implementation to process one polyphase channelizer result array.
|
* Sub-class implementation to process one polyphase channelizer result array.
|
||||||
* @param channelResult to process
|
* @param channelResults to process
|
||||||
* @param listener to receive the channel complex sample
|
* @param listener to receive the channel complex sample
|
||||||
*/
|
*/
|
||||||
public abstract void process(float[] channelResult, ComplexSampleListener listener);
|
public abstract void process(List<float[]> channelResults, ComplexSampleListener listener);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,16 +129,8 @@ public abstract class ChannelOutputProcessor implements IPolyphaseChannelOutputP
|
|||||||
*/
|
*/
|
||||||
protected float getFrequencyCorrectedInphase(float inphase, float quadrature)
|
protected float getFrequencyCorrectedInphase(float inphase, float quadrature)
|
||||||
{
|
{
|
||||||
//Only apply frequency correction if the oscillator is set to a non-zero frequency offset
|
return Complex.multiplyInphase(inphase, quadrature, mFrequencyCorrectionMixer.inphase(),
|
||||||
if(mFrequencyCorrectionMixer.enabled())
|
mFrequencyCorrectionMixer.quadrature());
|
||||||
{
|
|
||||||
return Complex.multiplyInphase(inphase, quadrature, mFrequencyCorrectionMixer.inphase(),
|
|
||||||
mFrequencyCorrectionMixer.quadrature());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return inphase;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -155,16 +143,8 @@ public abstract class ChannelOutputProcessor implements IPolyphaseChannelOutputP
|
|||||||
*/
|
*/
|
||||||
protected float getFrequencyCorrectedQuadrature(float inphase, float quadrature)
|
protected float getFrequencyCorrectedQuadrature(float inphase, float quadrature)
|
||||||
{
|
{
|
||||||
//Only apply frequency correction if the oscillator is set to a non-zero frequency offset
|
return Complex.multiplyQuadrature(inphase, quadrature, mFrequencyCorrectionMixer.inphase(),
|
||||||
if(mFrequencyCorrectionMixer.enabled())
|
mFrequencyCorrectionMixer.quadrature());
|
||||||
{
|
|
||||||
return Complex.multiplyQuadrature(inphase, quadrature, mFrequencyCorrectionMixer.inphase(),
|
|
||||||
mFrequencyCorrectionMixer.quadrature());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return quadrature;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -177,6 +157,16 @@ public abstract class ChannelOutputProcessor implements IPolyphaseChannelOutputP
|
|||||||
public void setFrequencyCorrection(long frequencyCorrection)
|
public void setFrequencyCorrection(long frequencyCorrection)
|
||||||
{
|
{
|
||||||
mFrequencyCorrectionMixer.setFrequency(frequencyCorrection);
|
mFrequencyCorrectionMixer.setFrequency(frequencyCorrection);
|
||||||
|
|
||||||
|
mFrequencyCorrectionEnabled = (frequencyCorrection != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if this channel has a frequency correction offset
|
||||||
|
*/
|
||||||
|
public boolean hasFrequencyCorrection()
|
||||||
|
{
|
||||||
|
return mFrequencyCorrectionEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,17 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package dsp.filter.channelizer.output;
|
package dsp.filter.channelizer.output;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import sample.complex.ComplexSampleListener;
|
import sample.complex.ComplexSampleListener;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class OneChannelOutputProcessor extends ChannelOutputProcessor
|
public class OneChannelOutputProcessor extends ChannelOutputProcessor
|
||||||
{
|
{
|
||||||
|
private final static Logger mLog = LoggerFactory.getLogger(OneChannelOutputProcessor.class);
|
||||||
|
|
||||||
private int mChannelOffset;
|
private int mChannelOffset;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,6 +42,7 @@ public class OneChannelOutputProcessor extends ChannelOutputProcessor
|
|||||||
{
|
{
|
||||||
super(1, sampleRate);
|
super(1, sampleRate);
|
||||||
setPolyphaseChannelIndices(channelIndexes);
|
setPolyphaseChannelIndices(channelIndexes);
|
||||||
|
mLog.debug("Sample Rate:" + sampleRate + " PolyPhase Channel Indexes:" + channelIndexes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,21 +67,31 @@ public class OneChannelOutputProcessor extends ChannelOutputProcessor
|
|||||||
* Extract the channel from the channel results array, apply frequency translation, and deliver the
|
* Extract the channel from the channel results array, apply frequency translation, and deliver the
|
||||||
* extracted frequency-corrected channel I/Q sample set to the complex sample listener.
|
* extracted frequency-corrected channel I/Q sample set to the complex sample listener.
|
||||||
*
|
*
|
||||||
* @param channels to process containing an array of channel I/Q sample pairs (I0,Q0,I1,Q1...In,Qn)
|
* @param channelResults to process containing a list of channel array of I/Q sample pairs (I0,Q0,I1,Q1...In,Qn)
|
||||||
* @param listener to receive the extracted, frequency-translated channel results
|
* @param listener to receive the extracted, frequency-translated channel results
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void process(float[] channels, ComplexSampleListener listener)
|
public void process(List<float[]> channelResults, ComplexSampleListener listener)
|
||||||
{
|
{
|
||||||
if(channels.length < mChannelOffset + 1)
|
for(float[] channels: channelResults)
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("Polyphase channelizer output channels array is not large enough to " +
|
if(channels.length < mChannelOffset + 1)
|
||||||
"cover this single channel output processor with channel offset [" + mChannelOffset + "]");
|
{
|
||||||
|
throw new IllegalArgumentException("Polyphase channelizer output channels array is not large enough to " +
|
||||||
|
"cover this single channel output processor with channel offset [" + mChannelOffset + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
float i = channels[mChannelOffset];
|
||||||
|
float q = channels[mChannelOffset + 1];
|
||||||
|
|
||||||
|
if(hasFrequencyCorrection())
|
||||||
|
{
|
||||||
|
listener.receive(getFrequencyCorrectedInphase(i, q), getFrequencyCorrectedQuadrature(i, q));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
listener.receive(i, q);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float i = channels[mChannelOffset];
|
|
||||||
float q = channels[mChannelOffset + 1];
|
|
||||||
|
|
||||||
listener.receive(getFrequencyCorrectedInphase(i, q), getFrequencyCorrectedQuadrature(i, q));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,16 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package dsp.filter.channelizer.output;
|
package dsp.filter.channelizer.output;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import sample.complex.ComplexSampleListener;
|
import sample.complex.ComplexSampleListener;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class TwoChannelOutputProcessor extends ChannelOutputProcessor
|
public class TwoChannelOutputProcessor extends ChannelOutputProcessor
|
||||||
{
|
{
|
||||||
|
private final static Logger mLog = LoggerFactory.getLogger(TwoChannelOutputProcessor.class);
|
||||||
|
|
||||||
private int mChannelOffset1;
|
private int mChannelOffset1;
|
||||||
private int mChannelOffset2;
|
private int mChannelOffset2;
|
||||||
|
|
||||||
@@ -66,12 +70,13 @@ public class TwoChannelOutputProcessor extends ChannelOutputProcessor
|
|||||||
* Extract the channel from the channel results array, apply frequency translation, and deliver the
|
* Extract the channel from the channel results array, apply frequency translation, and deliver the
|
||||||
* extracted frequency-corrected channel I/Q sample set to the complex sample listener.
|
* extracted frequency-corrected channel I/Q sample set to the complex sample listener.
|
||||||
*
|
*
|
||||||
* @param channels to process containing an array of channel I/Q sample pairs (I0,Q0,I1,Q1...In,Qn)
|
* @param channelResults to process containing an array of channel I/Q sample pairs (I0,Q0,I1,Q1...In,Qn)
|
||||||
* @param listener to receive the extracted, frequency-translated channel results
|
* @param listener to receive the extracted, frequency-translated channel results
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void process(float[] channels, ComplexSampleListener listener)
|
public void process(List<float[]> channelResults, ComplexSampleListener listener)
|
||||||
{
|
{
|
||||||
|
mLog.debug("I got channel results - doing nothing !!");
|
||||||
// if(channels.length < mChannelOffset + 1)
|
// if(channels.length < mChannelOffset + 1)
|
||||||
// {
|
// {
|
||||||
// throw new IllegalArgumentException("Polyphase channelizer output channels array is not large enough to " +
|
// throw new IllegalArgumentException("Polyphase channelizer output channels array is not large enough to " +
|
||||||
|
|||||||
@@ -74,6 +74,14 @@ public class OverflowableTransferQueue<E>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes and returns a single element from the head of the queue or null if the queue is empty
|
||||||
|
*/
|
||||||
|
public E poll()
|
||||||
|
{
|
||||||
|
return mQueue.poll();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves elements from the queue into the collection up to the maximum number of elements specified
|
* Retrieves elements from the queue into the collection up to the maximum number of elements specified
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -168,6 +168,14 @@ public abstract class Tuner implements ITunerChannelProvider
|
|||||||
mSampleBroadcaster.removeListener(listener);
|
mSampleBroadcaster.removeListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of registered complex sample buffer listeners
|
||||||
|
*/
|
||||||
|
public int getListenerCount()
|
||||||
|
{
|
||||||
|
return mSampleBroadcaster.getListenerCount();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides access to the internal sample broadcaster for sub-class use (ie protected).
|
* Provides access to the internal sample broadcaster for sub-class use (ie protected).
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
package source.tuner.test;
|
package source.tuner.test;
|
||||||
|
|
||||||
import dsp.mixer.LowPhaseNoiseOscillator;
|
import dsp.mixer.LowPhaseNoiseOscillator;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import sample.Listener;
|
import sample.Listener;
|
||||||
import sample.complex.ComplexBuffer;
|
import sample.complex.ComplexBuffer;
|
||||||
import util.ThreadPool;
|
import util.ThreadPool;
|
||||||
@@ -28,12 +30,40 @@ import java.util.concurrent.TimeUnit;
|
|||||||
|
|
||||||
public class SampleGenerator
|
public class SampleGenerator
|
||||||
{
|
{
|
||||||
|
private final static Logger mLog = LoggerFactory.getLogger(SampleGenerator.class);
|
||||||
|
|
||||||
private LowPhaseNoiseOscillator mOscillator;
|
private LowPhaseNoiseOscillator mOscillator;
|
||||||
|
private int mSweepUpdateInterval;
|
||||||
private Listener<ComplexBuffer> mListener;
|
private Listener<ComplexBuffer> mListener;
|
||||||
private long mInterval;
|
private long mInterval;
|
||||||
private int mSamplesPerInterval;
|
private int mSamplesPerInterval;
|
||||||
private ScheduledFuture<?> mScheduledFuture;
|
private ScheduledFuture<?> mScheduledFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates complex sample buffers at the specified sample rate with a unity gain tone at the specified
|
||||||
|
* frequency. This generator runs via a scheduled thread pool and generates samples at the specified time
|
||||||
|
* interval.
|
||||||
|
*
|
||||||
|
* @param sampleRate of the complex samples
|
||||||
|
* @param frequency of the tone produced by the generator
|
||||||
|
* @param interval in milliseconds for generating samples
|
||||||
|
* @param sweepUpdateRate to turn on sweeping of the tone frequency where the frequency is incremented by the
|
||||||
|
* rate specified at each interval, resetting to 1 Hz after reaching/exceeding the highest frequency.
|
||||||
|
*/
|
||||||
|
public SampleGenerator(int sampleRate, long frequency, long interval, int sweepUpdateRate)
|
||||||
|
{
|
||||||
|
if(Math.abs(sweepUpdateRate) >= sampleRate)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Sweep update rate cannot be greater than sample rate");
|
||||||
|
}
|
||||||
|
|
||||||
|
mOscillator = new LowPhaseNoiseOscillator(sampleRate, frequency);
|
||||||
|
mInterval = interval;
|
||||||
|
mSweepUpdateInterval = sweepUpdateRate;
|
||||||
|
|
||||||
|
updateSamplesPerInterval();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates complex sample buffers at the specified sample rate with a unity gain tone at the specified
|
* Generates complex sample buffers at the specified sample rate with a unity gain tone at the specified
|
||||||
* frequency. This generator runs via a scheduled thread pool and generates samples at the specified time
|
* frequency. This generator runs via a scheduled thread pool and generates samples at the specified time
|
||||||
@@ -45,10 +75,7 @@ public class SampleGenerator
|
|||||||
*/
|
*/
|
||||||
public SampleGenerator(int sampleRate, long frequency, long interval)
|
public SampleGenerator(int sampleRate, long frequency, long interval)
|
||||||
{
|
{
|
||||||
mOscillator = new LowPhaseNoiseOscillator(sampleRate, frequency);
|
this(sampleRate, frequency, interval, 0);
|
||||||
mInterval = interval;
|
|
||||||
|
|
||||||
updateSamplesPerInterval();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,7 +83,9 @@ public class SampleGenerator
|
|||||||
*/
|
*/
|
||||||
private void updateSamplesPerInterval()
|
private void updateSamplesPerInterval()
|
||||||
{
|
{
|
||||||
mSamplesPerInterval = (int)((double)mOscillator.getSampleRate() * ((double)mInterval / 1000.0) * 2.0);
|
mSamplesPerInterval = (int)((double)mOscillator.getSampleRate() * ((double)mInterval / 1000.0));
|
||||||
|
|
||||||
|
mLog.debug("Sample Generator: " + mSamplesPerInterval + " samples every " + mInterval + " ms.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -141,6 +170,24 @@ public class SampleGenerator
|
|||||||
{
|
{
|
||||||
float[] samples = mOscillator.generate(mSamplesPerInterval);
|
float[] samples = mOscillator.generate(mSamplesPerInterval);
|
||||||
mListener.receive(new ComplexBuffer(samples));
|
mListener.receive(new ComplexBuffer(samples));
|
||||||
|
|
||||||
|
if(mSweepUpdateInterval != 0)
|
||||||
|
{
|
||||||
|
long updatedFrequency = mOscillator.getFrequency() + mSweepUpdateInterval;
|
||||||
|
|
||||||
|
if(updatedFrequency > mOscillator.getSampleRate() / 2)
|
||||||
|
{
|
||||||
|
mOscillator.setFrequency(mOscillator.getSampleRate() / -2);
|
||||||
|
}
|
||||||
|
else if(updatedFrequency < mOscillator.getSampleRate() / -2)
|
||||||
|
{
|
||||||
|
mOscillator.setFrequency(mOscillator.getSampleRate() / 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mOscillator.setFrequency(updatedFrequency);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,9 +49,6 @@ public class TestTuner extends Tuner
|
|||||||
{
|
{
|
||||||
super("Test Tuner", new TestTunerController());
|
super("Test Tuner", new TestTunerController());
|
||||||
|
|
||||||
mLog.debug("Initializing test tuner. Tuner Controller's sample rate is:" + getTunerController().getSampleRate());
|
|
||||||
mLog.debug("Initializing test tuner. Test Tuner Controller's sample rate is:" + getTestTunerController().getSampleRate());
|
|
||||||
|
|
||||||
mPolyphaseChannelManager = new PolyphaseChannelManager(this);
|
mPolyphaseChannelManager = new PolyphaseChannelManager(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class TestTunerController extends TunerController
|
|||||||
public static final long MINIMUM_FREQUENCY = 1000000l; //1 MHz
|
public static final long MINIMUM_FREQUENCY = 1000000l; //1 MHz
|
||||||
public static final long MAXIMUM_FREQUENCY = 10000000000l; //10 GHz
|
public static final long MAXIMUM_FREQUENCY = 10000000000l; //10 GHz
|
||||||
public static final long DEFAULT_FREQUENCY = 100000000; //100 MHz
|
public static final long DEFAULT_FREQUENCY = 100000000; //100 MHz
|
||||||
public static final int DEFAULT_SAMPLE_RATE = 1000000; //1 MHz
|
public static final int DEFAULT_SAMPLE_RATE = 50000; //25 kHz
|
||||||
public static final int DC_NOISE_BANDWIDTH = 5000; // +/-5 kHz
|
public static final int DC_NOISE_BANDWIDTH = 5000; // +/-5 kHz
|
||||||
public static final double USABLE_BANDWIDTH = 0.90; //90% usable bandwidth - 5% unusable on either end
|
public static final double USABLE_BANDWIDTH = 0.90; //90% usable bandwidth - 5% unusable on either end
|
||||||
|
|
||||||
@@ -46,7 +46,9 @@ public class TestTunerController extends TunerController
|
|||||||
{
|
{
|
||||||
super(MINIMUM_FREQUENCY, MAXIMUM_FREQUENCY, DC_NOISE_BANDWIDTH, USABLE_BANDWIDTH);
|
super(MINIMUM_FREQUENCY, MAXIMUM_FREQUENCY, DC_NOISE_BANDWIDTH, USABLE_BANDWIDTH);
|
||||||
|
|
||||||
mSampleGenerator = new SampleGenerator(DEFAULT_SAMPLE_RATE, DEFAULT_FREQUENCY, 100);
|
int sweepRate = 0; //Hz per interval
|
||||||
|
|
||||||
|
mSampleGenerator = new SampleGenerator(DEFAULT_SAMPLE_RATE, DEFAULT_FREQUENCY, 100, sweepRate);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user