mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
[WIP] Cleanup. Removes the legacy Instrumentable, Taps, etc and related
gui components. Refactors the new DecoderFX application to the instrument package.
This commit is contained in:
@@ -1,302 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.dsp.fsk;
|
||||
|
||||
import io.github.dsheirer.buffer.BooleanAveragingBuffer;
|
||||
import io.github.dsheirer.dsp.symbol.SymbolEvent;
|
||||
import io.github.dsheirer.dsp.symbol.SymbolEvent.Shift;
|
||||
import io.github.dsheirer.instrument.Instrumentable;
|
||||
import io.github.dsheirer.instrument.tap.Tap;
|
||||
import io.github.dsheirer.instrument.tap.TapGroup;
|
||||
import io.github.dsheirer.instrument.tap.stream.SymbolEventTap;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.real.RealBuffer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Binary Frequency Shift Keying (FSK) decoder. Implements a BFSK correlation
|
||||
* decoder. Provides normal or inverted decoded output. Requires the symbol
|
||||
* rate to be an integer multiple of the sample rate.
|
||||
*
|
||||
* Implements a correlation decoder that correlates a modulated FSK signal upon
|
||||
* against a one-baud delayed version of itself, converting all float samples to
|
||||
* binary (0 or 1), and uses XOR to produce the correlation value. Low pass
|
||||
* filtering smoothes the correlated output.
|
||||
*
|
||||
* Automatically aligns to symbol timing during symbol transitions (0 to 1, or
|
||||
* 1 to 0) by inspecting the samples at the symbol edges and advancing or
|
||||
* retarding symbol window to maintain continuous symbol alignment.
|
||||
*
|
||||
* Use a DC-removal filter prior to this decoder to ensure samples don't have
|
||||
* a DC component.
|
||||
*
|
||||
* Implements instrumentable interface, so that slice events can be received
|
||||
* externally to analyze decoder performance.
|
||||
*/
|
||||
public class FSK2Decoder implements Instrumentable, Listener<RealBuffer>
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(FSK2Decoder.class);
|
||||
|
||||
public enum Output
|
||||
{
|
||||
NORMAL, INVERTED
|
||||
}
|
||||
|
||||
/* Instrumentation taps */
|
||||
private static final String INSTRUMENT_DECISION =
|
||||
"Tap Point: FSK2 Symbol Decision";
|
||||
private List<TapGroup> mAvailableTaps;
|
||||
private ArrayList<SymbolEventTap> mTaps = new ArrayList<SymbolEventTap>();
|
||||
|
||||
private Listener<Boolean> mListener;
|
||||
private BooleanAveragingBuffer mDelayBuffer;
|
||||
private BooleanAveragingBuffer mLowPassFilter;
|
||||
private Slicer mSlicer;
|
||||
private boolean mNormalOutput;
|
||||
private int mSamplesPerSymbol;
|
||||
private int mSymbolRate;
|
||||
|
||||
public FSK2Decoder(int sampleRate, int symbolRate, Output output)
|
||||
{
|
||||
/* Ensure we're using an integral symbolRate of the sampleRate */
|
||||
assert (sampleRate % symbolRate == 0);
|
||||
|
||||
mSamplesPerSymbol = (int) (sampleRate / symbolRate);
|
||||
mNormalOutput = (output == Output.NORMAL);
|
||||
mSymbolRate = symbolRate;
|
||||
|
||||
mDelayBuffer = new BooleanAveragingBuffer(mSamplesPerSymbol);
|
||||
mLowPassFilter = new BooleanAveragingBuffer(mSamplesPerSymbol);
|
||||
mSlicer = new Slicer(mSamplesPerSymbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes of all references to prepare for garbage collection
|
||||
*/
|
||||
public void dispose()
|
||||
{
|
||||
mListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Primary sample input
|
||||
*/
|
||||
@Override
|
||||
public void receive(RealBuffer buffer)
|
||||
{
|
||||
for(float sample : buffer.getSamples())
|
||||
{
|
||||
/* Square the sample. Greater than zero is a 1 (true) and less than
|
||||
* zero is a 0 (false) */
|
||||
boolean bitSample = (sample >= 0.0f);
|
||||
|
||||
/* Feed the delay buffer and fetch the one-baud delayed sample */
|
||||
boolean delayedBitSample = mDelayBuffer.get(bitSample);
|
||||
|
||||
/* Correlation: xor current bit with delayed bit */
|
||||
boolean softBit = bitSample ^ delayedBitSample;
|
||||
|
||||
/* Low pass filter to smooth the correlated values */
|
||||
boolean filteredSoftBit = mLowPassFilter.getAverage(softBit);
|
||||
|
||||
/* Send the filtered correlated bit to the slicer */
|
||||
mSlicer.receive(filteredSoftBit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a listener to receive the decoded FSK bits
|
||||
*/
|
||||
public void setListener(Listener<Boolean> listener)
|
||||
{
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the listener
|
||||
*/
|
||||
public void removeListener(Listener<Boolean> listener)
|
||||
{
|
||||
mListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Symbol slicer with auto-aligning baud timing
|
||||
*/
|
||||
public class Slicer
|
||||
{
|
||||
private BitSet mBitSet = new BitSet();
|
||||
private int mSymbolLength;
|
||||
private int mDecisionThreshold;
|
||||
private int mSampleCounter;
|
||||
|
||||
public Slicer(int samplesPerSymbol)
|
||||
{
|
||||
mSymbolLength = samplesPerSymbol;
|
||||
|
||||
mDecisionThreshold = (int) (mSymbolLength / 2);
|
||||
|
||||
/* Adjust for an odd number of samples per baud */
|
||||
if(mSymbolLength % 2 == 1)
|
||||
{
|
||||
mDecisionThreshold++;
|
||||
}
|
||||
}
|
||||
|
||||
public void receive(boolean softBit)
|
||||
{
|
||||
if(mSampleCounter >= 0)
|
||||
{
|
||||
if(softBit)
|
||||
{
|
||||
mBitSet.set(mSampleCounter);
|
||||
}
|
||||
else
|
||||
{
|
||||
mBitSet.clear(mSampleCounter);
|
||||
}
|
||||
}
|
||||
|
||||
mSampleCounter++;
|
||||
|
||||
if(mSampleCounter >= mSymbolLength)
|
||||
{
|
||||
boolean decision = mBitSet.cardinality() >= mDecisionThreshold;
|
||||
|
||||
send(decision);
|
||||
|
||||
/* Shift timing left if the left bit in the bitset is opposite
|
||||
* the decision and the right bit is the same */
|
||||
if((mBitSet.get(0) ^ decision) &&
|
||||
(!(mBitSet.get(mSymbolLength - 1) ^ decision)))
|
||||
{
|
||||
sendTapEvent(mBitSet, Shift.LEFT, decision);
|
||||
|
||||
reset();
|
||||
|
||||
mSampleCounter--;
|
||||
}
|
||||
/* Shift timing right if the left bit is the same as the
|
||||
* decision and the right bit is opposite */
|
||||
else if((!(mBitSet.get(0) ^ decision)) &&
|
||||
(mBitSet.get(mSymbolLength - 1) ^ decision))
|
||||
{
|
||||
sendTapEvent(mBitSet, Shift.RIGHT, decision);
|
||||
|
||||
/* Last bit from previous symbol to pre-fill next symbol */
|
||||
boolean previousSoftBit = mBitSet.get(mSymbolLength - 1);
|
||||
|
||||
reset();
|
||||
|
||||
if(previousSoftBit)
|
||||
{
|
||||
mBitSet.set(0);
|
||||
}
|
||||
|
||||
mSampleCounter++;
|
||||
}
|
||||
/* No shift */
|
||||
else
|
||||
{
|
||||
sendTapEvent(mBitSet, Shift.NONE, decision);
|
||||
|
||||
reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the bit decision to the listener
|
||||
*/
|
||||
private void send(boolean decision)
|
||||
{
|
||||
if(mListener != null)
|
||||
{
|
||||
mListener.receive(mNormalOutput ? decision : !decision);
|
||||
}
|
||||
}
|
||||
|
||||
private void reset()
|
||||
{
|
||||
mBitSet.clear();
|
||||
mSampleCounter = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends instrumentation tap event to all registered listeners
|
||||
*/
|
||||
private void sendTapEvent(BitSet bitset, Shift shift, boolean decision)
|
||||
{
|
||||
for(SymbolEventTap tap : mTaps)
|
||||
{
|
||||
SymbolEvent event =
|
||||
new SymbolEvent(bitset.get(0, mSymbolLength),
|
||||
mSymbolLength,
|
||||
decision,
|
||||
shift);
|
||||
|
||||
tap.receive(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get instrumentation taps
|
||||
*/
|
||||
@Override
|
||||
public List<TapGroup> getTapGroups()
|
||||
{
|
||||
if(mAvailableTaps == null)
|
||||
{
|
||||
mAvailableTaps = new ArrayList<TapGroup>();
|
||||
|
||||
TapGroup tapGroup = new TapGroup("FSK2 Decoder");
|
||||
tapGroup.add(new SymbolEventTap(INSTRUMENT_DECISION, 0, .025f));
|
||||
|
||||
mAvailableTaps.add(tapGroup);
|
||||
}
|
||||
|
||||
return mAvailableTaps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add instrumentation tap
|
||||
*/
|
||||
@Override
|
||||
public void registerTap(Tap tap)
|
||||
{
|
||||
if(tap instanceof SymbolEventTap && !mTaps.contains(tap))
|
||||
{
|
||||
mTaps.add((SymbolEventTap) tap);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove instrumentation tap
|
||||
*/
|
||||
@Override
|
||||
public void unregisterTap(Tap tap)
|
||||
{
|
||||
mTaps.remove(tap);
|
||||
}
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
package io.github.dsheirer.dsp.symbol;
|
||||
|
||||
import io.github.dsheirer.instrument.tap.stream.SymbolEventTap;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
/**
|
||||
* Symbol slicer with auto-aligning baud timing
|
||||
*/
|
||||
public class Slicer implements Listener<Boolean>
|
||||
{
|
||||
public enum Output{ NORMAL, INVERTED };
|
||||
|
||||
private BitSet mBitSet = new BitSet();
|
||||
private int mSymbolLength;
|
||||
private int mDecisionThreshold;
|
||||
private int mSampleCounter;
|
||||
private SymbolEventTap mSymbolEventTap;
|
||||
|
||||
private boolean mNormalOutput = true;
|
||||
private Listener<Boolean> mListener;
|
||||
|
||||
public Slicer( Output output, int samplesPerSymbol )
|
||||
{
|
||||
mNormalOutput = ( output == Output.NORMAL );
|
||||
|
||||
mSymbolLength = samplesPerSymbol;
|
||||
|
||||
/* Round up */
|
||||
mDecisionThreshold = (int)( mSymbolLength / 2 ) + ( mSymbolLength % 2 );
|
||||
}
|
||||
|
||||
public void receive( Boolean sample )
|
||||
{
|
||||
if( mSampleCounter >= 0 )
|
||||
{
|
||||
if( sample )
|
||||
{
|
||||
mBitSet.set( mSampleCounter );
|
||||
}
|
||||
else
|
||||
{
|
||||
mBitSet.clear( mSampleCounter );
|
||||
}
|
||||
}
|
||||
|
||||
mSampleCounter++;
|
||||
|
||||
if( mSampleCounter >= mSymbolLength )
|
||||
{
|
||||
boolean decision = mBitSet.cardinality() >= mDecisionThreshold;
|
||||
|
||||
send( decision );
|
||||
|
||||
/* Shift timing left if the left bit in the bitset is opposite
|
||||
* the decision and the right bit is the same */
|
||||
if( ( mBitSet.get( 0 ) ^ decision ) &&
|
||||
( !( mBitSet.get( mSymbolLength - 1 ) ^ decision ) ) )
|
||||
{
|
||||
sendTapEvent( mBitSet, SymbolEvent.Shift.LEFT, decision );
|
||||
|
||||
reset();
|
||||
|
||||
mSampleCounter--;
|
||||
}
|
||||
/* Shift timing right if the left bit is the same as the
|
||||
* decision and the right bit is opposite */
|
||||
else if( ( !( mBitSet.get( 0 ) ^ decision ) ) &&
|
||||
( mBitSet.get( mSymbolLength - 1 ) ^ decision ) )
|
||||
{
|
||||
sendTapEvent( mBitSet, SymbolEvent.Shift.RIGHT, decision );
|
||||
|
||||
/* Last bit from previous symbol to pre-fill next symbol */
|
||||
boolean previousSoftBit = mBitSet.get( mSymbolLength - 1 );
|
||||
|
||||
reset();
|
||||
|
||||
if( previousSoftBit )
|
||||
{
|
||||
mBitSet.set( 0 );
|
||||
}
|
||||
|
||||
mSampleCounter++;
|
||||
}
|
||||
/* No shift */
|
||||
else
|
||||
{
|
||||
sendTapEvent( mBitSet, SymbolEvent.Shift.NONE, decision );
|
||||
|
||||
reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the bit decision to the listener
|
||||
*/
|
||||
private void send( boolean decision )
|
||||
{
|
||||
if( mListener != null )
|
||||
{
|
||||
mListener.receive( mNormalOutput ? decision : !decision );
|
||||
}
|
||||
}
|
||||
|
||||
private void reset()
|
||||
{
|
||||
mBitSet.clear();
|
||||
mSampleCounter = 0;
|
||||
}
|
||||
|
||||
public void setListener( Listener<Boolean> listener)
|
||||
{
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
public void removeListener( Listener<Boolean> listener )
|
||||
{
|
||||
mListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends instrumentation tap event to all registered listeners
|
||||
*/
|
||||
private void sendTapEvent(BitSet bitset, SymbolEvent.Shift shift, boolean decision )
|
||||
{
|
||||
if( mSymbolEventTap != null )
|
||||
{
|
||||
SymbolEvent event =
|
||||
new SymbolEvent( bitset.get( 0, mSymbolLength ),
|
||||
mSymbolLength,
|
||||
decision,
|
||||
shift );
|
||||
|
||||
mSymbolEventTap.receive( event );
|
||||
}
|
||||
}
|
||||
|
||||
public void addTap( SymbolEventTap tap )
|
||||
{
|
||||
mSymbolEventTap = tap;
|
||||
}
|
||||
|
||||
public void removeTap()
|
||||
{
|
||||
mSymbolEventTap = null;
|
||||
}
|
||||
}
|
||||
@@ -13,9 +13,9 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer;
|
||||
package io.github.dsheirer.instrument;
|
||||
|
||||
import io.github.dsheirer.instrument.gui.viewer.decoder.DecoderPaneFactory;
|
||||
import io.github.dsheirer.instrument.decoder.DecoderPaneFactory;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.module.decode.p25.P25Decoder;
|
||||
import javafx.application.Application;
|
||||
@@ -1,54 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument;
|
||||
|
||||
import io.github.dsheirer.instrument.tap.Tap;
|
||||
import io.github.dsheirer.instrument.tap.TapGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Interface for classes that want to expose internal data, streams or events
|
||||
* to external listeners.
|
||||
*/
|
||||
public interface Instrumentable
|
||||
{
|
||||
/**
|
||||
* Returns the list of available tap point groups. Use the addTap() and
|
||||
* removeTap() to register a tap on the instrumentable class and then add
|
||||
* your TapListener(s) to the registered tap.
|
||||
*/
|
||||
public List<TapGroup> getTapGroups();
|
||||
|
||||
/**
|
||||
* Registers a tap on the instrumentable object.
|
||||
*
|
||||
* @param tap - one of the tap(s) obtained from getTaps() from the
|
||||
* instrumentable source
|
||||
*/
|
||||
public void registerTap( Tap tap );
|
||||
|
||||
/**
|
||||
* Unregisters a tap on the instrumentable object, if the tap is currently
|
||||
* registered.
|
||||
*
|
||||
* @param tap - one of the tap(s) obtained from getTaps() from the
|
||||
* instrumentable source
|
||||
*/
|
||||
public void unregisterTap( Tap tap );
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument;
|
||||
|
||||
import io.github.dsheirer.controller.channel.Channel.ChannelType;
|
||||
import io.github.dsheirer.instrument.tap.Tap;
|
||||
import io.github.dsheirer.instrument.tap.TapGroup;
|
||||
import io.github.dsheirer.module.Module;
|
||||
import io.github.dsheirer.module.ProcessingChain;
|
||||
import io.github.dsheirer.source.Source;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class InstrumentableProcessingChain extends ProcessingChain implements Instrumentable
|
||||
{
|
||||
public InstrumentableProcessingChain()
|
||||
{
|
||||
super(ChannelType.STANDARD);
|
||||
}
|
||||
|
||||
public void setSource(Source source) throws IllegalStateException
|
||||
{
|
||||
mSource = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TapGroup> getTapGroups()
|
||||
{
|
||||
List<TapGroup> groups = new ArrayList<>();
|
||||
|
||||
for(Module module : getModules())
|
||||
{
|
||||
if(module instanceof Instrumentable)
|
||||
{
|
||||
groups.addAll(((Instrumentable)module).getTapGroups());
|
||||
}
|
||||
}
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerTap(Tap tap)
|
||||
{
|
||||
for(Module module : getModules())
|
||||
{
|
||||
if(module instanceof Instrumentable)
|
||||
{
|
||||
((Instrumentable)module).registerTap(tap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterTap(Tap tap)
|
||||
{
|
||||
for(Module module : getModules())
|
||||
{
|
||||
if(module instanceof Instrumentable)
|
||||
{
|
||||
((Instrumentable)module).unregisterTap(tap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,9 +13,9 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer;
|
||||
package io.github.dsheirer.instrument;
|
||||
|
||||
import io.github.dsheirer.instrument.gui.viewer.decoder.AbstractDecoderPane;
|
||||
import io.github.dsheirer.instrument.decoder.AbstractDecoderPane;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.buffer.ReusableBuffer;
|
||||
import io.github.dsheirer.sample.buffer.ReusableBufferBroadcaster;
|
||||
@@ -1,4 +1,19 @@
|
||||
package io.github.dsheirer.instrument.gui.viewer;
|
||||
/*******************************************************************************
|
||||
* sdr-trunk
|
||||
* Copyright (C) 2014-2018 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 the Free Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program.
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
@@ -13,10 +13,10 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer;
|
||||
package io.github.dsheirer.instrument;
|
||||
|
||||
import io.github.dsheirer.instrument.gui.viewer.decoder.AbstractDecoderPane;
|
||||
import io.github.dsheirer.instrument.gui.viewer.decoder.DecoderPaneFactory;
|
||||
import io.github.dsheirer.instrument.decoder.AbstractDecoderPane;
|
||||
import io.github.dsheirer.instrument.decoder.DecoderPaneFactory;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.module.decode.p25.P25Decoder;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.chart;
|
||||
package io.github.dsheirer.instrument.chart;
|
||||
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.chart;
|
||||
package io.github.dsheirer.instrument.chart;
|
||||
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.chart;
|
||||
package io.github.dsheirer.instrument.chart;
|
||||
|
||||
import io.github.dsheirer.buffer.ComplexCircularBuffer;
|
||||
import io.github.dsheirer.dsp.gain.ComplexGain;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.chart;
|
||||
package io.github.dsheirer.instrument.chart;
|
||||
|
||||
import io.github.dsheirer.buffer.ComplexCircularBuffer;
|
||||
import io.github.dsheirer.dsp.gain.ComplexGain;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.chart;
|
||||
package io.github.dsheirer.instrument.chart;
|
||||
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import javafx.collections.FXCollections;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.chart;
|
||||
package io.github.dsheirer.instrument.chart;
|
||||
|
||||
import io.github.dsheirer.buffer.DoubleCircularBuffer;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.chart;
|
||||
package io.github.dsheirer.instrument.chart;
|
||||
|
||||
import io.github.dsheirer.dsp.psk.SymbolDecisionData;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.chart;
|
||||
package io.github.dsheirer.instrument.chart;
|
||||
|
||||
import io.github.dsheirer.buffer.DoubleCircularBuffer;
|
||||
import io.github.dsheirer.dsp.fm.FMDemodulator;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.chart;
|
||||
package io.github.dsheirer.instrument.chart;
|
||||
|
||||
import io.github.dsheirer.dsp.afsk.AFSK1200DecoderInstrumented;
|
||||
import io.github.dsheirer.message.Message;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.chart;
|
||||
package io.github.dsheirer.instrument.chart;
|
||||
|
||||
import io.github.dsheirer.module.decode.ltrnet.LTRNetDecoderInstrumented;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.chart;
|
||||
package io.github.dsheirer.instrument.chart;
|
||||
|
||||
import io.github.dsheirer.buffer.DoubleCircularBuffer;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.chart;
|
||||
package io.github.dsheirer.instrument.chart;
|
||||
|
||||
import io.github.dsheirer.buffer.RealCircularBuffer;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.chart;
|
||||
package io.github.dsheirer.instrument.chart;
|
||||
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.complex.Complex;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.chart;
|
||||
package io.github.dsheirer.instrument.chart;
|
||||
|
||||
import io.github.dsheirer.module.decode.ltrnet.LTRNetDecoderInstrumented;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
@@ -13,13 +13,13 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.decoder;
|
||||
package io.github.dsheirer.instrument.decoder;
|
||||
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.AFSK1200SampleBufferChart;
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.AFSK1200ZeroCrossingErrorDetectorChart;
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.DecodedSymbolChart;
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.IInstrumentedAFSK1200Decoder;
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.RealSampleLineChart;
|
||||
import io.github.dsheirer.instrument.chart.AFSK1200SampleBufferChart;
|
||||
import io.github.dsheirer.instrument.chart.AFSK1200ZeroCrossingErrorDetectorChart;
|
||||
import io.github.dsheirer.instrument.chart.DecodedSymbolChart;
|
||||
import io.github.dsheirer.instrument.chart.IInstrumentedAFSK1200Decoder;
|
||||
import io.github.dsheirer.instrument.chart.RealSampleLineChart;
|
||||
import io.github.dsheirer.message.Message;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.decoder;
|
||||
package io.github.dsheirer.instrument.decoder;
|
||||
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.SampleType;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.decoder;
|
||||
package io.github.dsheirer.instrument.decoder;
|
||||
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.decoder;
|
||||
package io.github.dsheirer.instrument.decoder;
|
||||
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.module.decode.p25.P25Decoder;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.decoder;
|
||||
package io.github.dsheirer.instrument.decoder;
|
||||
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.module.decode.fleetsync2.Fleetsync2DecoderInstrumented;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.decoder;
|
||||
package io.github.dsheirer.instrument.decoder;
|
||||
|
||||
import io.github.dsheirer.dsp.symbol.ISyncDetectListener;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
@@ -13,11 +13,11 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.decoder;
|
||||
package io.github.dsheirer.instrument.decoder;
|
||||
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.LTRNetSampleBufferChart;
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.RealSampleLineChart;
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.ZeroCrossingErrorDetectorChart;
|
||||
import io.github.dsheirer.instrument.chart.LTRNetSampleBufferChart;
|
||||
import io.github.dsheirer.instrument.chart.RealSampleLineChart;
|
||||
import io.github.dsheirer.instrument.chart.ZeroCrossingErrorDetectorChart;
|
||||
import io.github.dsheirer.message.Message;
|
||||
import io.github.dsheirer.message.MessageDirection;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.decoder;
|
||||
package io.github.dsheirer.instrument.decoder;
|
||||
|
||||
import io.github.dsheirer.dsp.symbol.ISyncDetectListener;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.decoder;
|
||||
package io.github.dsheirer.instrument.decoder;
|
||||
|
||||
import io.github.dsheirer.dsp.symbol.ISyncDetectListener;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
@@ -13,13 +13,13 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.decoder;
|
||||
package io.github.dsheirer.instrument.decoder;
|
||||
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.ComplexSampleLineChart;
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.DoubleLineChart;
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.EyeDiagramChart;
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.PhaseLineChart;
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.SymbolChart;
|
||||
import io.github.dsheirer.instrument.chart.ComplexSampleLineChart;
|
||||
import io.github.dsheirer.instrument.chart.DoubleLineChart;
|
||||
import io.github.dsheirer.instrument.chart.EyeDiagramChart;
|
||||
import io.github.dsheirer.instrument.chart.PhaseLineChart;
|
||||
import io.github.dsheirer.instrument.chart.SymbolChart;
|
||||
import io.github.dsheirer.message.Message;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.module.decode.p25.P25DecoderC4FMInstrumented;
|
||||
@@ -13,13 +13,13 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.decoder;
|
||||
package io.github.dsheirer.instrument.decoder;
|
||||
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.ComplexSampleLineChart;
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.DoubleLineChart;
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.EyeDiagramChart;
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.PhaseLineChart;
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.SymbolChart;
|
||||
import io.github.dsheirer.instrument.chart.ComplexSampleLineChart;
|
||||
import io.github.dsheirer.instrument.chart.DoubleLineChart;
|
||||
import io.github.dsheirer.instrument.chart.EyeDiagramChart;
|
||||
import io.github.dsheirer.instrument.chart.PhaseLineChart;
|
||||
import io.github.dsheirer.instrument.chart.SymbolChart;
|
||||
import io.github.dsheirer.message.Message;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.module.decode.p25.P25DecoderLSMInstrumented;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.decoder;
|
||||
package io.github.dsheirer.instrument.decoder;
|
||||
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
@@ -13,7 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui.viewer.decoder;
|
||||
package io.github.dsheirer.instrument.decoder;
|
||||
|
||||
import io.github.dsheirer.dsp.symbol.ISyncDetectListener;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
@@ -1,77 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui;
|
||||
|
||||
import io.github.dsheirer.gui.control.ConstellationViewer;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.complex.Complex;
|
||||
import io.github.dsheirer.source.IFrameLocationListener;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class ConstellationPanel extends JInternalFrame
|
||||
implements IFrameLocationListener, Listener<Complex>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private ConstellationViewer mConstellation = new ConstellationViewer( 48000, 4800 );
|
||||
|
||||
public ConstellationPanel()
|
||||
{
|
||||
initGui();
|
||||
}
|
||||
|
||||
private void initGui()
|
||||
{
|
||||
setLayout( new MigLayout( "insets 0 0 0 0 ", "[grow,fill]", "[grow,fill]" ) );
|
||||
|
||||
setTitle( "Constellation View" );
|
||||
setPreferredSize( new Dimension( 300, 300 ) );
|
||||
setSize( 300, 300 );
|
||||
|
||||
setResizable( true );
|
||||
setClosable( true );
|
||||
setIconifiable( true );
|
||||
setMaximizable( false );
|
||||
|
||||
add( mConstellation );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void frameLocationUpdated( int location )
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void frameLocationReset()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( Complex sample )
|
||||
{
|
||||
mConstellation.receive( sample );
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
package io.github.dsheirer.instrument.gui;
|
||||
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastModel;
|
||||
import io.github.dsheirer.controller.channel.Channel;
|
||||
import io.github.dsheirer.controller.channel.ChannelModel;
|
||||
import io.github.dsheirer.controller.channel.map.ChannelMapModel;
|
||||
import io.github.dsheirer.module.decode.DecodeConfigurationEditor;
|
||||
import io.github.dsheirer.module.decode.config.DecodeConfiguration;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.source.IControllableFileSource;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JDesktopPane;
|
||||
import javax.swing.JInternalFrame;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
public class DecoderSelectionFrame extends JInternalFrame
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Channel mChannel = new Channel();
|
||||
private DecodeConfigurationEditor mDecodeEditor = new DecodeConfigurationEditor(null);
|
||||
private PlaylistManager mPlaylistManager;
|
||||
|
||||
private IControllableFileSource mSource;
|
||||
private JDesktopPane mDesktop;
|
||||
|
||||
public DecoderSelectionFrame(JDesktopPane desktop, IControllableFileSource source)
|
||||
{
|
||||
AliasModel aliasModel = new AliasModel();
|
||||
BroadcastModel broadcastModel = new BroadcastModel(null);
|
||||
ChannelModel channelModel = new ChannelModel();
|
||||
ChannelMapModel channelMapModel = new ChannelMapModel();
|
||||
|
||||
mPlaylistManager = new PlaylistManager(aliasModel, broadcastModel, channelModel, channelMapModel);
|
||||
|
||||
mDesktop = desktop;
|
||||
mSource = source;
|
||||
|
||||
mDecodeEditor.setItem(mChannel);
|
||||
initGUI();
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout(new MigLayout("", "[grow,fill]", "[][][grow,fill]"));
|
||||
|
||||
setTitle("Decoders");
|
||||
setPreferredSize(new Dimension(700, 450));
|
||||
setSize(700, 450);
|
||||
|
||||
setResizable(true);
|
||||
setClosable(true);
|
||||
setIconifiable(true);
|
||||
setMaximizable(false);
|
||||
|
||||
add(mDecodeEditor, "wrap");
|
||||
|
||||
add(new AddDecoderButton(), "span");
|
||||
|
||||
}
|
||||
|
||||
public class AddDecoderButton extends JButton
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public AddDecoderButton()
|
||||
{
|
||||
super("Add");
|
||||
|
||||
addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent arg0)
|
||||
{
|
||||
mDecodeEditor.save();
|
||||
|
||||
Channel channel = mDecodeEditor.getItem();
|
||||
|
||||
if(channel != null)
|
||||
{
|
||||
DecodeConfiguration config = channel.getDecodeConfiguration();
|
||||
|
||||
if( config != null )
|
||||
{
|
||||
DecoderViewFrame decoderFrame = new DecoderViewFrame(mPlaylistManager, channel, mSource );
|
||||
|
||||
decoderFrame.setVisible( true );
|
||||
|
||||
mDesktop.add( decoderFrame );
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,355 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui;
|
||||
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.controller.channel.Channel;
|
||||
import io.github.dsheirer.controller.channel.ChannelModel;
|
||||
import io.github.dsheirer.controller.channel.ChannelProcessingManager;
|
||||
import io.github.dsheirer.controller.channel.map.ChannelMapModel;
|
||||
import io.github.dsheirer.instrument.Instrumentable;
|
||||
import io.github.dsheirer.instrument.InstrumentableProcessingChain;
|
||||
import io.github.dsheirer.instrument.tap.Tap;
|
||||
import io.github.dsheirer.instrument.tap.TapGroup;
|
||||
import io.github.dsheirer.instrument.tap.TapViewPanel;
|
||||
import io.github.dsheirer.instrument.tap.stream.BinaryTap;
|
||||
import io.github.dsheirer.instrument.tap.stream.BinaryTapViewPanel;
|
||||
import io.github.dsheirer.instrument.tap.stream.ComplexSampleTap;
|
||||
import io.github.dsheirer.instrument.tap.stream.ComplexSampleTapViewPanel;
|
||||
import io.github.dsheirer.instrument.tap.stream.ComplexTap;
|
||||
import io.github.dsheirer.instrument.tap.stream.ComplexTapViewPanel;
|
||||
import io.github.dsheirer.instrument.tap.stream.DibitTap;
|
||||
import io.github.dsheirer.instrument.tap.stream.DibitTapViewPanel;
|
||||
import io.github.dsheirer.instrument.tap.stream.EyeDiagramDataTap;
|
||||
import io.github.dsheirer.instrument.tap.stream.EyeDiagramDataTapPanel;
|
||||
import io.github.dsheirer.instrument.tap.stream.FloatTap;
|
||||
import io.github.dsheirer.instrument.tap.stream.FloatTapViewPanel;
|
||||
import io.github.dsheirer.instrument.tap.stream.QPSKTap;
|
||||
import io.github.dsheirer.instrument.tap.stream.QPSKTapPanel;
|
||||
import io.github.dsheirer.instrument.tap.stream.SymbolEventTap;
|
||||
import io.github.dsheirer.instrument.tap.stream.SymbolEventTapViewPanel;
|
||||
import io.github.dsheirer.message.Message;
|
||||
import io.github.dsheirer.module.Module;
|
||||
import io.github.dsheirer.module.decode.DecoderFactory;
|
||||
import io.github.dsheirer.module.decode.config.DecodeConfiguration;
|
||||
import io.github.dsheirer.module.log.EventLogManager;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.source.IControllableFileSource;
|
||||
import io.github.dsheirer.source.Source;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class DecoderViewFrame extends JInternalFrame implements Listener<Message>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final static Logger mLog = LoggerFactory.getLogger(DecoderViewFrame.class);
|
||||
|
||||
private DecodeConfiguration mDecodeConfig;
|
||||
private InstrumentableProcessingChain mProcessingChain;
|
||||
private IControllableFileSource mSource;
|
||||
|
||||
private HashMap<Tap,TapViewPanel> mPanelMap = new HashMap<Tap,TapViewPanel>();
|
||||
|
||||
public DecoderViewFrame(PlaylistManager playlistManager, Channel channel, IControllableFileSource source)
|
||||
{
|
||||
mSource = source;
|
||||
|
||||
mDecodeConfig = channel.getDecodeConfiguration();
|
||||
|
||||
mProcessingChain = new InstrumentableProcessingChain();
|
||||
|
||||
ChannelModel channelModel = new ChannelModel();
|
||||
ChannelMapModel channelMapModel = new ChannelMapModel();
|
||||
|
||||
ChannelProcessingManager channelProcessingManager = new ChannelProcessingManager(channelModel, channelMapModel,
|
||||
new AliasModel(), new EventLogManager(), null, null);
|
||||
|
||||
List<Module> modules = DecoderFactory.getModules(channelModel, channelMapModel, channelProcessingManager,
|
||||
new AliasModel(), channel, mProcessingChain.getChannelState().getMutableMetadata());
|
||||
|
||||
mProcessingChain.addModules(modules);
|
||||
|
||||
mProcessingChain.addMessageListener(this);
|
||||
|
||||
mProcessingChain.setSource((Source) mSource);
|
||||
|
||||
mProcessingChain.start();
|
||||
|
||||
initGui();
|
||||
}
|
||||
|
||||
private void initGui()
|
||||
{
|
||||
setLayout(new MigLayout("insets 0 0 0 0 ", "[grow,fill]", "[grow,fill]"));
|
||||
|
||||
setTitle("Decoder [" + mDecodeConfig.getDecoderType().getDisplayString() + "]");
|
||||
setPreferredSize(new Dimension(450, 250));
|
||||
setSize(450, 250);
|
||||
|
||||
setResizable(true);
|
||||
setClosable(true);
|
||||
setIconifiable(true);
|
||||
setMaximizable(false);
|
||||
|
||||
addMouseListener(new MouseListener()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent me)
|
||||
{
|
||||
if(me.getButton() == MouseEvent.BUTTON3)
|
||||
{
|
||||
JPopupMenu popup = new JPopupMenu();
|
||||
|
||||
popup.add(getTapContextMenu());
|
||||
|
||||
if(!mPanelMap.values().isEmpty())
|
||||
{
|
||||
popup.add(new JSeparator());
|
||||
|
||||
for(TapViewPanel panel : mPanelMap.values())
|
||||
{
|
||||
popup.add(panel.getContextMenu());
|
||||
}
|
||||
}
|
||||
|
||||
popup.show(DecoderViewFrame.this, me.getX(), me.getY());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent arg0)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent arg0)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent arg0)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent arg0)
|
||||
{
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private JMenu getTapContextMenu()
|
||||
{
|
||||
JMenu menu = new JMenu("Modules");
|
||||
|
||||
if(mProcessingChain != null)
|
||||
{
|
||||
for(Module module : mProcessingChain.getModules())
|
||||
{
|
||||
if(module instanceof Instrumentable)
|
||||
{
|
||||
List<TapGroup> groups = ((Instrumentable) module).getTapGroups();
|
||||
|
||||
for(TapGroup group : groups)
|
||||
{
|
||||
menu.add(new TapGroupMenu(group));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
public void add(Tap tap)
|
||||
{
|
||||
TapViewPanel panel = null;
|
||||
|
||||
switch(tap.getType())
|
||||
{
|
||||
case EVENT_SYNC_DETECT:
|
||||
break;
|
||||
case STREAM_BINARY:
|
||||
panel = new BinaryTapViewPanel((BinaryTap) tap);
|
||||
break;
|
||||
case STREAM_COMPLEX:
|
||||
panel = new ComplexTapViewPanel((ComplexTap) tap);
|
||||
break;
|
||||
case STREAM_COMPLEX_SAMPLE:
|
||||
panel = new ComplexSampleTapViewPanel((ComplexSampleTap) tap);
|
||||
break;
|
||||
case STREAM_DIBIT:
|
||||
panel = new DibitTapViewPanel((DibitTap) tap);
|
||||
break;
|
||||
case STREAM_EYE_DIAGRAM:
|
||||
panel = new EyeDiagramDataTapPanel((EyeDiagramDataTap) tap);
|
||||
break;
|
||||
case STREAM_FLOAT:
|
||||
panel = new FloatTapViewPanel((FloatTap) tap);
|
||||
break;
|
||||
case STREAM_QPSK:
|
||||
panel = new QPSKTapPanel((QPSKTap) tap);
|
||||
break;
|
||||
case STREAM_SYMBOL:
|
||||
panel = new SymbolEventTapViewPanel((SymbolEventTap) tap);
|
||||
break;
|
||||
}
|
||||
|
||||
if(panel != null)
|
||||
{
|
||||
add(panel, "span");
|
||||
|
||||
validate();
|
||||
|
||||
mPanelMap.put(tap, panel);
|
||||
|
||||
for(Module module : mProcessingChain.getModules())
|
||||
{
|
||||
if(module instanceof Instrumentable)
|
||||
{
|
||||
((Instrumentable) module).registerTap(tap);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.info("Tap panel is null, couldn't add for tap " +
|
||||
tap.getName() + "[" + tap.getType().toString() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(Tap tap)
|
||||
{
|
||||
for(Module module : mProcessingChain.getModules())
|
||||
{
|
||||
if(module instanceof Instrumentable)
|
||||
{
|
||||
((Instrumentable) module).unregisterTap(tap);
|
||||
}
|
||||
}
|
||||
|
||||
TapViewPanel panel = mPanelMap.get(tap);
|
||||
|
||||
remove(panel);
|
||||
|
||||
validate();
|
||||
|
||||
mPanelMap.remove(tap);
|
||||
}
|
||||
|
||||
public class AddAllTapsItem extends JMenuItem
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final List<Tap> mTaps;
|
||||
|
||||
public AddAllTapsItem(final List<Tap> taps)
|
||||
{
|
||||
super("All Taps");
|
||||
|
||||
mTaps = taps;
|
||||
|
||||
addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
for(Tap tap : mTaps)
|
||||
{
|
||||
DecoderViewFrame.this.add(tap);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class TapSelectionItem extends JCheckBoxMenuItem
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Tap mTap;
|
||||
|
||||
public TapSelectionItem(Tap tap)
|
||||
{
|
||||
super(tap.getName());
|
||||
|
||||
mTap = tap;
|
||||
|
||||
if(mPanelMap.keySet().contains(tap))
|
||||
{
|
||||
setSelected(true);
|
||||
}
|
||||
|
||||
addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent arg0)
|
||||
{
|
||||
if(mPanelMap.keySet().contains(mTap))
|
||||
{
|
||||
DecoderViewFrame.this.remove(mTap);
|
||||
}
|
||||
else
|
||||
{
|
||||
DecoderViewFrame.this.add(mTap);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(Message message)
|
||||
{
|
||||
mLog.info(message.toString());
|
||||
}
|
||||
|
||||
public class TapGroupMenu extends JMenu
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private TapGroup mTapGroup;
|
||||
|
||||
public TapGroupMenu(TapGroup tapGroup)
|
||||
{
|
||||
super(tapGroup.getName());
|
||||
|
||||
mTapGroup = tapGroup;
|
||||
|
||||
add(new AddAllTapsItem(mTapGroup.getTaps()));
|
||||
|
||||
add(new JSeparator());
|
||||
|
||||
for(Tap tap : mTapGroup.getTaps())
|
||||
{
|
||||
add(new TapSelectionItem(tap));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui;
|
||||
|
||||
import io.github.dsheirer.instrument.tap.TapListener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Observable;
|
||||
|
||||
public class SampleModel<T> extends Observable implements TapListener<T>
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( SampleModel.class );
|
||||
|
||||
private int mSampleCount = 2000;
|
||||
private int mDelay = 0;
|
||||
private ArrayList<T> mSamples = new ArrayList<T>();
|
||||
|
||||
public SampleModel()
|
||||
{
|
||||
}
|
||||
|
||||
public List<T> getSamples()
|
||||
{
|
||||
return Collections.unmodifiableList( mSamples );
|
||||
}
|
||||
|
||||
public void clearSamples()
|
||||
{
|
||||
mSamples.clear();
|
||||
|
||||
changed();
|
||||
}
|
||||
|
||||
public int getSampleCount()
|
||||
{
|
||||
return mSampleCount;
|
||||
}
|
||||
|
||||
public void setSampleCount( int count )
|
||||
{
|
||||
mSampleCount = count;
|
||||
|
||||
changed();
|
||||
}
|
||||
|
||||
public void setDelay( int delay )
|
||||
{
|
||||
mDelay = delay;
|
||||
}
|
||||
|
||||
public int getDelay()
|
||||
{
|
||||
return mDelay;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( T t )
|
||||
{
|
||||
if( mDelay > 0 )
|
||||
{
|
||||
mDelay--;
|
||||
}
|
||||
else
|
||||
{
|
||||
mSamples.add( t );
|
||||
|
||||
while( mSamples.size() > mSampleCount )
|
||||
{
|
||||
mSamples.remove( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
changed();
|
||||
}
|
||||
|
||||
private void changed()
|
||||
{
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
}
|
||||
}
|
||||
@@ -1,215 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui;
|
||||
|
||||
import io.github.dsheirer.source.IControllableFileSource;
|
||||
import io.github.dsheirer.source.IFrameLocationListener;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.io.IOException;
|
||||
|
||||
public class SourceControllerFrame extends JInternalFrame
|
||||
implements IFrameLocationListener
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( SourceControllerFrame.class );
|
||||
|
||||
private IControllableFileSource mSource;
|
||||
private JDesktopPane mDesktop;
|
||||
|
||||
private JLabel mCurrentPosition = new JLabel( "0" );
|
||||
|
||||
public SourceControllerFrame( IControllableFileSource source,
|
||||
JDesktopPane desktop )
|
||||
{
|
||||
mSource = source;
|
||||
mSource.setListener( this );
|
||||
|
||||
mDesktop = desktop;
|
||||
|
||||
initGui();
|
||||
}
|
||||
|
||||
private void initGui()
|
||||
{
|
||||
setTitle( "Source [" + mSource.getFile().getAbsolutePath() + "]" );
|
||||
setPreferredSize( new Dimension( 670, 70 ) );
|
||||
setSize( 670, 70 );
|
||||
|
||||
setResizable( true );
|
||||
setClosable( true );
|
||||
setIconifiable( true );
|
||||
setMaximizable( false );
|
||||
|
||||
JPanel panel = new JPanel();
|
||||
panel.setLayout( new MigLayout() );
|
||||
|
||||
JButton decoderButton = new JButton( "Decoders" );
|
||||
decoderButton.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
DecoderSelectionFrame frame =
|
||||
new DecoderSelectionFrame( mDesktop, mSource );
|
||||
|
||||
frame.setVisible( true );
|
||||
|
||||
mDesktop.add( frame );
|
||||
}
|
||||
} );
|
||||
}
|
||||
} );
|
||||
|
||||
panel.add( decoderButton );
|
||||
|
||||
panel.add( new JLabel( "Skip:" ) );
|
||||
panel.add( new SkipFramesField( mSource ) );
|
||||
panel.add( new NextFrameButton( mSource, "> 1", 1 ) );
|
||||
panel.add( new NextFrameButton( mSource, "> 10", 10 ) );
|
||||
panel.add( new NextFrameButton( mSource, "> 100", 100 ) );
|
||||
panel.add( new NextFrameButton( mSource, "> 1000", 1000 ) );
|
||||
panel.add( new JLabel( "Posn:" ) );
|
||||
panel.add( mCurrentPosition, "wrap" );
|
||||
|
||||
add( panel );
|
||||
}
|
||||
|
||||
public class NextFrameButton extends JButton
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IControllableFileSource mSource;
|
||||
private int mFrames;
|
||||
|
||||
public NextFrameButton( IControllableFileSource source,
|
||||
String label, int frames )
|
||||
{
|
||||
super( label );
|
||||
mSource = source;
|
||||
mFrames = frames;
|
||||
|
||||
addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
mSource.next( mFrames );
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
mLog.error( "Viewer - reading frames [" + mFrames +
|
||||
"] from source", e );
|
||||
|
||||
JOptionPane.showMessageDialog( SourceControllerFrame.this,
|
||||
"Can't read " + mFrames + " more frames [" +
|
||||
e.getLocalizedMessage() + "]",
|
||||
"Wave File Error",
|
||||
JOptionPane.ERROR_MESSAGE );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
public class SkipFramesField extends JTextField
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private IControllableFileSource mSource;
|
||||
|
||||
public SkipFramesField( IControllableFileSource source )
|
||||
{
|
||||
super( "0" );
|
||||
|
||||
mSource = source;
|
||||
|
||||
setMinimumSize( new Dimension( 100, getHeight() ) );
|
||||
|
||||
addFocusListener( new FocusListener()
|
||||
{
|
||||
@Override
|
||||
public void focusGained( FocusEvent arg0 ) {}
|
||||
|
||||
@Override
|
||||
public void focusLost( FocusEvent arg0 )
|
||||
{
|
||||
try
|
||||
{
|
||||
int framesToSkip = Integer.parseInt( getText() );
|
||||
|
||||
mSource.next( framesToSkip, false );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
mLog.error( "WaveSourceFrame - error skipping frames", e );
|
||||
|
||||
JOptionPane.showMessageDialog( SourceControllerFrame.this,
|
||||
"Can't skip [" + getText() + "] frames.",
|
||||
"Error",
|
||||
JOptionPane.ERROR_MESSAGE );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void frameLocationUpdated( final int location )
|
||||
{
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
mCurrentPosition.setText( String.valueOf( location ) );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void frameLocationReset()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,293 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.gui;
|
||||
|
||||
import io.github.dsheirer.properties.SystemProperties;
|
||||
import io.github.dsheirer.source.IControllableFileSource;
|
||||
import io.github.dsheirer.source.wave.ComplexWaveSource;
|
||||
import io.github.dsheirer.source.wave.RealWaveSource;
|
||||
import io.github.dsheirer.util.TimeStamp;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.*;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class Viewer
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( Viewer.class );
|
||||
|
||||
private JFrame mFrame;
|
||||
private JDesktopPane mDesktop;
|
||||
|
||||
private IControllableFileSource mSource;
|
||||
|
||||
public Viewer()
|
||||
{
|
||||
initGUI();
|
||||
}
|
||||
|
||||
public void setVisible( boolean visible )
|
||||
{
|
||||
mFrame.setVisible( visible );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the contents of the frame.
|
||||
*/
|
||||
private void initGUI()
|
||||
{
|
||||
/* Setup main JFrame window */
|
||||
mFrame = new JFrame();
|
||||
mFrame.setTitle( "SDRTrunk - Sample File Viewer" );
|
||||
mFrame.setBounds( 100, 100, 800, 600 );
|
||||
mFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
|
||||
|
||||
/* Multi-window desktop */
|
||||
mDesktop = new JDesktopPane();
|
||||
mFrame.add( mDesktop );
|
||||
|
||||
/* Menu items */
|
||||
JMenuBar menuBar = new JMenuBar();
|
||||
mFrame.setJMenuBar( menuBar );
|
||||
|
||||
JMenu fileMenu = new JMenu( "File" );
|
||||
menuBar.add( fileMenu );
|
||||
|
||||
fileMenu.add( new SourceFileItem() );
|
||||
fileMenu.add( new JSeparator() );
|
||||
|
||||
JMenuItem exitMenu = new JMenuItem( "Exit" );
|
||||
exitMenu.addActionListener( new ActionListener()
|
||||
{
|
||||
public void actionPerformed( ActionEvent event )
|
||||
{
|
||||
System.exit( 0 );
|
||||
}
|
||||
} );
|
||||
|
||||
fileMenu.add( exitMenu );
|
||||
|
||||
menuBar.add( new ScreenCaptureItem() );
|
||||
}
|
||||
|
||||
private void setSourceFile( File file )
|
||||
{
|
||||
mLog.info( "File selected [" + file.getAbsolutePath() + "]");
|
||||
|
||||
IControllableFileSource source = null;
|
||||
|
||||
/* Attempt to open file as a 1-channel float source */
|
||||
try
|
||||
{
|
||||
source = new RealWaveSource( file );
|
||||
source.open();
|
||||
|
||||
mLog.info( "File opened as float wave file" );
|
||||
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
mLog.error( "Couldn't open file as float single-channel source" );
|
||||
}
|
||||
|
||||
if( source == null )
|
||||
{
|
||||
/* Attempt to open file as a 2-channel complex source */
|
||||
try
|
||||
{
|
||||
ComplexWaveSource complex = new ComplexWaveSource( file );
|
||||
complex.open();
|
||||
|
||||
source = complex;
|
||||
|
||||
mLog.info( "File opened as complex wave file" );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
mLog.error( "Couldn't open file as float source", e);
|
||||
}
|
||||
}
|
||||
|
||||
if( source != null )
|
||||
{
|
||||
mSource = source;
|
||||
|
||||
SourceControllerFrame sourcePanel =
|
||||
new SourceControllerFrame( source, mDesktop );
|
||||
sourcePanel.setVisible( true );
|
||||
mDesktop.add( sourcePanel );
|
||||
}
|
||||
}
|
||||
|
||||
public static void main( String[] args )
|
||||
{
|
||||
final Viewer viewer = new Viewer();
|
||||
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
viewer.setVisible( true );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
public class SourceFileItem extends JMenuItem
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public SourceFileItem()
|
||||
{
|
||||
super( "Open" );
|
||||
|
||||
addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
final JFileChooser fc = new JFileChooser();
|
||||
fc.setFileFilter( new FileFilter()
|
||||
{
|
||||
@Override
|
||||
public boolean accept( File file )
|
||||
{
|
||||
return file.isDirectory() ||
|
||||
file.getName().endsWith( ".wav" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription()
|
||||
{
|
||||
return "Float or Complex 16-bit Wave Files";
|
||||
}
|
||||
} );
|
||||
|
||||
int val = fc.showOpenDialog( mFrame );
|
||||
|
||||
if( val == JFileChooser.APPROVE_OPTION )
|
||||
{
|
||||
final File file = fc.getSelectedFile();
|
||||
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
setSourceFile( file );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
public class ScreenCaptureItem extends JMenuItem
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ScreenCaptureItem()
|
||||
{
|
||||
super( "Screen Capture" );
|
||||
|
||||
addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Robot robot = new Robot();
|
||||
|
||||
final BufferedImage image =
|
||||
robot.createScreenCapture( mFrame.getBounds() );
|
||||
|
||||
SystemProperties props = SystemProperties.getInstance();
|
||||
|
||||
Path capturePath = props.getApplicationFolder( "screen_captures" );
|
||||
|
||||
if( !Files.exists( capturePath ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
Files.createDirectory( capturePath );
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
mLog.error( "Couldn't create 'screen_captures' "
|
||||
+ "subdirectory in the " +
|
||||
"SDRTrunk application directory", e );
|
||||
}
|
||||
}
|
||||
|
||||
String filename = TimeStamp.getTimeStamp( "_" ) +
|
||||
"_screen_capture.png";
|
||||
|
||||
final Path captureFile = capturePath.resolve( filename );
|
||||
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
ImageIO.write( image, "png",
|
||||
captureFile.toFile() );
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
mLog.error( "Couldn't write screen capture to "
|
||||
+ "file [" + captureFile.toString() + "]", e );
|
||||
}
|
||||
}} );
|
||||
}
|
||||
catch ( AWTException e )
|
||||
{
|
||||
mLog.error( "Exception while taking screen capture", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public abstract class Tap
|
||||
{
|
||||
protected TapType mType;
|
||||
protected String mName;
|
||||
protected int mDelay;
|
||||
|
||||
protected ArrayList<TapListener> mListeners = new ArrayList<TapListener>();
|
||||
|
||||
/**
|
||||
* Instrumentation tap. Provides a tap into a data stream or event stream
|
||||
* within a process, so that registered listeners can be notified every
|
||||
* time a new data sample is availabe, or an event occurrs.
|
||||
*
|
||||
* @param name - displayable name to use for the tap
|
||||
*
|
||||
* @param delay - indicates the number of delay units from when the data
|
||||
* begins the process until this event occurs. When this data or event is
|
||||
* plotted on a flow graph, the delay value will be used to adjust placement
|
||||
* on the display to correctly align events.
|
||||
*/
|
||||
public Tap( TapType type, String name, int delay )
|
||||
{
|
||||
mType = type;
|
||||
mName = name;
|
||||
mDelay = delay;
|
||||
}
|
||||
|
||||
public TapType getType()
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display name for this tap
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delay for this tap
|
||||
*/
|
||||
public int getDelay()
|
||||
{
|
||||
return mDelay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a listener for data or events produced by this tap
|
||||
*/
|
||||
public void addListener( TapListener listener )
|
||||
{
|
||||
if( !mListeners.contains( listener ) )
|
||||
{
|
||||
mListeners.add( listener );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the listener from receiving data or events from this tap
|
||||
*/
|
||||
public void removeListener( TapListener listener )
|
||||
{
|
||||
mListeners.remove( listener );
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of listeners currently registered on this tap
|
||||
*/
|
||||
public int getListenerCount()
|
||||
{
|
||||
return mListeners.size();
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package io.github.dsheirer.instrument.tap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TapGroup
|
||||
{
|
||||
private String mName;
|
||||
private List<Tap> mTaps = new ArrayList<>();
|
||||
|
||||
public TapGroup( String name )
|
||||
{
|
||||
mName = name;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return getName();
|
||||
}
|
||||
|
||||
public List<Tap> getTaps()
|
||||
{
|
||||
return mTaps;
|
||||
}
|
||||
|
||||
public void add( Tap tap )
|
||||
{
|
||||
mTaps.add( tap );
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap;
|
||||
|
||||
public interface TapListener<T>
|
||||
{
|
||||
public void receive( T t );
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap;
|
||||
|
||||
public enum TapType
|
||||
{
|
||||
EVENT_SYNC_DETECT,
|
||||
STREAM_BINARY,
|
||||
STREAM_COMPLEX,
|
||||
STREAM_COMPLEX_SAMPLE,
|
||||
STREAM_DIBIT,
|
||||
STREAM_EYE_DIAGRAM,
|
||||
STREAM_FLOAT,
|
||||
STREAM_QPSK,
|
||||
STREAM_SYMBOL;
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap;
|
||||
|
||||
import io.github.dsheirer.instrument.gui.SampleModel;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Observer;
|
||||
|
||||
public abstract class TapViewPanel extends JPanel implements Observer
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected SampleModel<?> mModel;
|
||||
protected String mLabel;
|
||||
|
||||
protected float mVerticalZoom = 1.0f;
|
||||
|
||||
public TapViewPanel( SampleModel<?> model, String label )
|
||||
{
|
||||
mModel = model;
|
||||
mModel.addObserver( this );
|
||||
|
||||
mLabel = label;
|
||||
|
||||
initGui();
|
||||
}
|
||||
|
||||
private void initGui()
|
||||
{
|
||||
setBackground( Color.WHITE );
|
||||
setForeground( Color.BLUE );
|
||||
|
||||
setSize( new Dimension( 400, 200 ) );
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
mModel.clearSamples();
|
||||
}
|
||||
|
||||
public JMenu getContextMenu()
|
||||
{
|
||||
JMenu menu = new JMenu( mLabel );
|
||||
|
||||
JMenu verticalMenu = new JMenu( "Vertical Zoom" );
|
||||
menu.add( verticalMenu );
|
||||
|
||||
verticalMenu.add( new VerticalZoomItem( this, "8", 8.0f ) );
|
||||
verticalMenu.add( new VerticalZoomItem( this, "4", 4.0f ) );
|
||||
verticalMenu.add( new VerticalZoomItem( this, "2", 2.0f ) );
|
||||
verticalMenu.add( new VerticalZoomItem( this, "1", 1.0f ) );
|
||||
verticalMenu.add( new VerticalZoomItem( this, ".5", 0.5f ) );
|
||||
verticalMenu.add( new VerticalZoomItem( this, ".25", 0.25f ) );
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
public SampleModel<?> getModel()
|
||||
{
|
||||
return mModel;
|
||||
}
|
||||
|
||||
public int getSampleCount()
|
||||
{
|
||||
return getModel().getSampleCount();
|
||||
}
|
||||
|
||||
public void setSampleCount( int sampleCount )
|
||||
{
|
||||
getModel().setSampleCount( sampleCount );
|
||||
}
|
||||
|
||||
public float getVerticalZoom()
|
||||
{
|
||||
return mVerticalZoom;
|
||||
}
|
||||
|
||||
public void setVerticalZoom( float zoom )
|
||||
{
|
||||
mVerticalZoom = zoom;
|
||||
repaint();
|
||||
}
|
||||
|
||||
public class VerticalZoomItem extends JCheckBoxMenuItem
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private TapViewPanel mPanel;
|
||||
private float mZoom;
|
||||
|
||||
public VerticalZoomItem( TapViewPanel panel, String label, float zoom )
|
||||
{
|
||||
super( label );
|
||||
mPanel = panel;
|
||||
mZoom = zoom;
|
||||
|
||||
if( mPanel.getVerticalZoom() == zoom )
|
||||
{
|
||||
setSelected( true );
|
||||
}
|
||||
|
||||
addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
mPanel.setVerticalZoom( mZoom );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap.event;
|
||||
|
||||
import io.github.dsheirer.dsp.symbol.ISyncDetectListener;
|
||||
import io.github.dsheirer.dsp.symbol.SyncDetectProvider;
|
||||
import io.github.dsheirer.instrument.tap.Tap;
|
||||
import io.github.dsheirer.instrument.tap.TapListener;
|
||||
import io.github.dsheirer.instrument.tap.TapType;
|
||||
|
||||
public class SyncDetectTap extends Tap implements ISyncDetectListener, SyncDetectProvider
|
||||
{
|
||||
private ISyncDetectListener mListener;
|
||||
|
||||
/**
|
||||
* Sync detect event tap. Indicates when message sync word has been
|
||||
* detected within a binary stream of data.
|
||||
*/
|
||||
public SyncDetectTap()
|
||||
{
|
||||
super(TapType.EVENT_SYNC_DETECT, "Sync Detected", 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncDetected()
|
||||
{
|
||||
if(mListener != null)
|
||||
{
|
||||
mListener.syncDetected();
|
||||
}
|
||||
|
||||
for(TapListener listener : mListeners)
|
||||
{
|
||||
listener.receive(getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSyncDetectListener(ISyncDetectListener listener)
|
||||
{
|
||||
mListener = listener;
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
|
||||
public class AdditiveFloatTap extends FloatTap
|
||||
{
|
||||
private float mValue;
|
||||
|
||||
public AdditiveFloatTap( String name,
|
||||
int delay,
|
||||
float sampleRateRatio,
|
||||
float addValue )
|
||||
{
|
||||
super( name, delay, sampleRateRatio );
|
||||
|
||||
mValue = addValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( float sample )
|
||||
{
|
||||
super.receive( sample + mValue );
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
import io.github.dsheirer.instrument.tap.TapListener;
|
||||
import io.github.dsheirer.instrument.tap.TapType;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
|
||||
public class BinaryTap extends StreamTap implements Listener<Boolean>
|
||||
|
||||
{
|
||||
private Listener<Boolean> mListener;
|
||||
|
||||
public BinaryTap( String name,
|
||||
int delay,
|
||||
float sampleRateRatio )
|
||||
{
|
||||
super( TapType.STREAM_BINARY, name, delay, sampleRateRatio );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( Boolean bit )
|
||||
{
|
||||
if( mListener != null )
|
||||
{
|
||||
mListener.receive( bit );
|
||||
}
|
||||
|
||||
for( TapListener listener: mListeners )
|
||||
{
|
||||
listener.receive( bit );
|
||||
}
|
||||
}
|
||||
|
||||
public void setListener( Listener<Boolean> listener )
|
||||
{
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
public void removeListener( Listener<Boolean> listener )
|
||||
{
|
||||
mListener = null;
|
||||
}
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
import io.github.dsheirer.instrument.gui.SampleModel;
|
||||
import io.github.dsheirer.instrument.tap.Tap;
|
||||
import io.github.dsheirer.instrument.tap.TapViewPanel;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.List;
|
||||
import java.util.Observable;
|
||||
|
||||
public class BinaryTapViewPanel extends TapViewPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Tap mTap;
|
||||
private List<Boolean> mSamples;
|
||||
private int mSampleCount;
|
||||
|
||||
public BinaryTapViewPanel( BinaryTap tap )
|
||||
{
|
||||
super( new SampleModel<Boolean>(), tap.getName() );
|
||||
|
||||
mTap = tap;
|
||||
mTap.addListener( getModel() );
|
||||
|
||||
getModel().setSampleCount(
|
||||
(int)( getModel().getSampleCount() * tap.getSampleRateRatio() ) );
|
||||
|
||||
getModel().setDelay( tap.getDelay() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update( Observable arg0, Object arg1 )
|
||||
{
|
||||
mSamples = (List<Boolean>)getModel().getSamples();
|
||||
mSampleCount = getModel().getSampleCount();
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void paintComponent( Graphics g )
|
||||
{
|
||||
super.paintComponent( g );
|
||||
|
||||
Graphics2D g2 = (Graphics2D)g;
|
||||
|
||||
int height = getHeight();
|
||||
int width = getWidth();
|
||||
|
||||
g2.setColor( Color.DARK_GRAY );
|
||||
|
||||
float middle = (float)height / 2.0f;
|
||||
|
||||
g2.drawLine( 0, (int)middle, width, (int)middle );
|
||||
|
||||
if( mSamples != null && mSamples.size() > 0 )
|
||||
{
|
||||
g2.setColor( getForeground() );
|
||||
|
||||
g2.drawString( mLabel, 5 , 15 );
|
||||
|
||||
for( int x = 1; x < mSamples.size(); x++ )
|
||||
{
|
||||
paintBit( g, x, mSamples.get( x ) );
|
||||
}
|
||||
}
|
||||
|
||||
g2.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Paints a polyline representing a boolean value with a 0 or 1 label in
|
||||
* the middle of it
|
||||
*
|
||||
* @param graphics object
|
||||
* @param index - index of the sample int the sample buffer
|
||||
* @param value - bit value, 0 or 1
|
||||
*/
|
||||
private void paintBit( Graphics graphics, int index, boolean value )
|
||||
{
|
||||
Graphics2D g2 = (Graphics2D)graphics;
|
||||
|
||||
Path2D.Float polyline =
|
||||
new Path2D.Float( Path2D.Float.WIND_EVEN_ODD, mSamples.size() );
|
||||
|
||||
float middleY = ( (float)getHeight() / 2.0f );
|
||||
|
||||
float indexWidth = (float)( getWidth() ) / (float)mSampleCount;
|
||||
|
||||
float startX = (float)index * indexWidth;
|
||||
float stopX = (float)(index + 1 ) * indexWidth;
|
||||
float fivePercent = indexWidth * .05f;
|
||||
float leftX = startX + fivePercent;
|
||||
float rightX = stopX - fivePercent;
|
||||
|
||||
/* Start */
|
||||
polyline.moveTo( startX, middleY );
|
||||
|
||||
/* Left horizonal segment */
|
||||
polyline.lineTo( leftX, middleY );
|
||||
|
||||
float y = ( value ? ( middleY - ( middleY * 0.5f) ) :
|
||||
( middleY + ( middleY * 0.5f) ) );
|
||||
|
||||
/* Left vertical segment */
|
||||
polyline.lineTo( leftX, y );
|
||||
|
||||
/* Middle horizontal segment */
|
||||
polyline.lineTo( rightX, y );
|
||||
|
||||
/* Right vertical segment */
|
||||
polyline.lineTo( rightX, middleY );
|
||||
|
||||
/* Right horizontal segment */
|
||||
polyline.lineTo( stopX, middleY );
|
||||
|
||||
g2.draw( polyline );
|
||||
|
||||
/* Draw the bit value label */
|
||||
String bit = value ? "1" : "0";
|
||||
|
||||
FontMetrics fontMetrics = graphics.getFontMetrics( this.getFont() );
|
||||
|
||||
Rectangle2D label = fontMetrics.getStringBounds( bit, graphics );
|
||||
|
||||
float offsetX = (float)label.getWidth() / 2.0f;
|
||||
float offsetY = (float)label.getWidth() / 2.0f;
|
||||
|
||||
float middleX = startX + ( indexWidth / 2.0f );
|
||||
|
||||
graphics.drawString( bit,
|
||||
(int)( middleX - offsetX ),
|
||||
(int)( middleY - offsetY ) );
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
import io.github.dsheirer.instrument.tap.TapListener;
|
||||
import io.github.dsheirer.instrument.tap.TapType;
|
||||
import io.github.dsheirer.sample.complex.Complex;
|
||||
import io.github.dsheirer.sample.complex.ComplexSampleListener;
|
||||
|
||||
public class ComplexSampleTap extends StreamTap implements ComplexSampleListener
|
||||
{
|
||||
private ComplexSampleListener mListener;
|
||||
|
||||
public ComplexSampleTap( String name,
|
||||
int delay,
|
||||
float sampleRateRatio )
|
||||
{
|
||||
super( TapType.STREAM_COMPLEX_SAMPLE, name, delay, sampleRateRatio );
|
||||
}
|
||||
|
||||
public ComplexSampleTap( TapType tapType, String name, int delay, float sampleRateRatio )
|
||||
{
|
||||
super( tapType, name, delay, sampleRateRatio );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( float inphase, float quadrature )
|
||||
{
|
||||
if( mListener != null )
|
||||
{
|
||||
mListener.receive( inphase, quadrature );
|
||||
}
|
||||
|
||||
for( TapListener listener: mListeners )
|
||||
{
|
||||
listener.receive( new Complex( inphase, quadrature ) );
|
||||
}
|
||||
}
|
||||
|
||||
public void setListener( ComplexSampleListener listener )
|
||||
{
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
public void removeListener( ComplexSampleListener listener )
|
||||
{
|
||||
mListener = null;
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
import io.github.dsheirer.gui.SDRTrunk;
|
||||
import io.github.dsheirer.instrument.gui.SampleModel;
|
||||
import io.github.dsheirer.instrument.tap.Tap;
|
||||
import io.github.dsheirer.instrument.tap.TapViewPanel;
|
||||
import io.github.dsheirer.sample.complex.Complex;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.util.List;
|
||||
import java.util.Observable;
|
||||
|
||||
public class ComplexSampleTapViewPanel extends TapViewPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final static Logger mLog = LoggerFactory.getLogger( SDRTrunk.class );
|
||||
|
||||
private Tap mTap;
|
||||
private List<Complex> mSamples;
|
||||
private int mSampleCount;
|
||||
|
||||
public ComplexSampleTapViewPanel( ComplexSampleTap tap )
|
||||
{
|
||||
super( new SampleModel<ComplexTap>(), tap.getName() );
|
||||
|
||||
setSize( new Dimension( 400, 400 ) );
|
||||
|
||||
mTap = tap;
|
||||
mTap.addListener( getModel() );
|
||||
|
||||
mSampleCount = (int)( 2000 * tap.getSampleRateRatio() );
|
||||
|
||||
getModel().setSampleCount( mSampleCount );
|
||||
getModel().setDelay( tap.getDelay() );
|
||||
|
||||
mLog.info( "Complex Tap Panel [" + tap.getName() + "] count: " +
|
||||
getModel().getSampleCount() + " delay:" + getModel().getDelay() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update( Observable arg0, Object arg1 )
|
||||
{
|
||||
mSamples = (List<Complex>)getModel().getSamples();
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void paintComponent( Graphics g )
|
||||
{
|
||||
super.paintComponent( g );
|
||||
|
||||
Graphics2D g2 = (Graphics2D)g;
|
||||
|
||||
int height = getHeight();
|
||||
int width = getWidth();
|
||||
|
||||
g2.setColor( Color.DARK_GRAY );
|
||||
|
||||
float middle = (float)height / 4.0f;
|
||||
|
||||
g2.drawLine( 0, (int)middle, width, (int)middle );
|
||||
g2.drawLine( 0, (int)( 3 * middle ), width, (int)( 3 * middle ) );
|
||||
|
||||
if( mSamples != null &&
|
||||
mSamples.size() > 0 )
|
||||
{
|
||||
g2.setColor( getForeground() );
|
||||
|
||||
g2.drawString( mLabel, 5 , 15 );
|
||||
|
||||
Path2D.Float polylineReal =
|
||||
new Path2D.Float( Path2D.Float.WIND_EVEN_ODD, mSamples.size() );
|
||||
Path2D.Float polylineImag =
|
||||
new Path2D.Float( Path2D.Float.WIND_EVEN_ODD, mSamples.size() );
|
||||
|
||||
/* Move to the first point */
|
||||
Point2D.Float firstReal = resolve( 0, mSamples.get( 0 ), Type.REAL );
|
||||
polylineReal.moveTo( firstReal.x, firstReal.y );
|
||||
|
||||
Point2D.Float firstImag = resolve( 0, mSamples.get( 0 ), Type.IMAGINERY );
|
||||
polylineImag.moveTo( firstImag.x, firstImag.y );
|
||||
|
||||
for( int x = 1; x < mSamples.size(); x++ )
|
||||
{
|
||||
Point2D.Float pointReal = resolve( x, mSamples.get( x ), Type.REAL );
|
||||
polylineReal.lineTo( pointReal.x, pointReal.y );
|
||||
|
||||
Point2D.Float pointImag = resolve( x, mSamples.get( x ), Type.IMAGINERY );
|
||||
polylineImag.lineTo( pointImag.x, pointImag.y );
|
||||
|
||||
// mLog.debug( "Imag y:" + pointImag.getY() + " height:" + getHeight() );
|
||||
}
|
||||
|
||||
g2.draw( polylineReal );
|
||||
g2.draw( polylineImag );
|
||||
}
|
||||
|
||||
g2.dispose();
|
||||
}
|
||||
|
||||
|
||||
private Point2D.Float resolve( int index, Complex sample, Type type )
|
||||
{
|
||||
int middle = (int)( getHeight() / 4 );
|
||||
|
||||
float y = middle - ( middle * mVerticalZoom * ( type == Type.REAL ?
|
||||
sample.real() : sample.imaginary()) );
|
||||
|
||||
if( type == Type.IMAGINERY )
|
||||
{
|
||||
y += ( middle * 2 );
|
||||
}
|
||||
|
||||
/* Clip y to zero as necessary */
|
||||
y = ( y < 0 ) ? 0 : y;
|
||||
|
||||
/* Clip y to max height as necessary */
|
||||
y = ( y > getHeight() ) ? getHeight() : y;
|
||||
|
||||
float indexWidth = (float)getWidth() / (float)mSampleCount;
|
||||
|
||||
float x = (float)index * indexWidth;
|
||||
|
||||
Point2D.Float point = new Point2D.Float( x, y );
|
||||
|
||||
return new Point2D.Float( x , y );
|
||||
}
|
||||
|
||||
public enum Type{ REAL,IMAGINERY };
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
import io.github.dsheirer.instrument.tap.TapListener;
|
||||
import io.github.dsheirer.instrument.tap.TapType;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.complex.Complex;
|
||||
|
||||
public class ComplexTap extends StreamTap implements Listener<Complex>
|
||||
{
|
||||
private Listener<Complex> mListener;
|
||||
|
||||
public ComplexTap( String name,
|
||||
int delay,
|
||||
float sampleRateRatio )
|
||||
{
|
||||
super( TapType.STREAM_COMPLEX, name, delay, sampleRateRatio );
|
||||
}
|
||||
|
||||
public ComplexTap( TapType tapType, String name, int delay, float sampleRateRatio )
|
||||
{
|
||||
super( tapType, name, delay, sampleRateRatio );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( Complex sample )
|
||||
{
|
||||
if( mListener != null )
|
||||
{
|
||||
mListener.receive( sample );
|
||||
}
|
||||
|
||||
for( TapListener listener: mListeners )
|
||||
{
|
||||
listener.receive( sample );
|
||||
}
|
||||
}
|
||||
|
||||
public void setListener( Listener<Complex> listener )
|
||||
{
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
public void removeListener( Listener<Complex> listener )
|
||||
{
|
||||
mListener = null;
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
import io.github.dsheirer.gui.SDRTrunk;
|
||||
import io.github.dsheirer.instrument.gui.SampleModel;
|
||||
import io.github.dsheirer.instrument.tap.Tap;
|
||||
import io.github.dsheirer.instrument.tap.TapViewPanel;
|
||||
import io.github.dsheirer.sample.complex.Complex;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.util.List;
|
||||
import java.util.Observable;
|
||||
|
||||
public class ComplexTapViewPanel extends TapViewPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final static Logger mLog = LoggerFactory.getLogger( SDRTrunk.class );
|
||||
|
||||
private Tap mTap;
|
||||
private List<Complex> mSamples;
|
||||
private int mSampleCount;
|
||||
|
||||
public ComplexTapViewPanel( ComplexTap tap )
|
||||
{
|
||||
super( new SampleModel<ComplexTap>(), tap.getName() );
|
||||
|
||||
setSize( new Dimension( 400, 400 ) );
|
||||
|
||||
mTap = tap;
|
||||
mTap.addListener( getModel() );
|
||||
|
||||
mSampleCount = (int)( 2000 * tap.getSampleRateRatio() );
|
||||
|
||||
getModel().setSampleCount( mSampleCount );
|
||||
getModel().setDelay( tap.getDelay() );
|
||||
|
||||
mLog.info( "Complex Tap Panel [" + tap.getName() + "] count: " +
|
||||
getModel().getSampleCount() + " delay:" + getModel().getDelay() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update( Observable arg0, Object arg1 )
|
||||
{
|
||||
mSamples = (List<Complex>)getModel().getSamples();
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void paintComponent( Graphics g )
|
||||
{
|
||||
super.paintComponent( g );
|
||||
|
||||
Graphics2D g2 = (Graphics2D)g;
|
||||
|
||||
int height = getHeight();
|
||||
int width = getWidth();
|
||||
|
||||
g2.setColor( Color.DARK_GRAY );
|
||||
|
||||
float middle = (float)height / 4.0f;
|
||||
|
||||
g2.drawLine( 0, (int)middle, width, (int)middle );
|
||||
g2.drawLine( 0, (int)( 3 * middle ), width, (int)( 3 * middle ) );
|
||||
|
||||
if( mSamples != null &&
|
||||
mSamples.size() > 0 )
|
||||
{
|
||||
g2.setColor( getForeground() );
|
||||
|
||||
g2.drawString( mLabel, 5 , 15 );
|
||||
|
||||
Path2D.Float polylineReal =
|
||||
new Path2D.Float( Path2D.Float.WIND_EVEN_ODD, mSamples.size() );
|
||||
Path2D.Float polylineImag =
|
||||
new Path2D.Float( Path2D.Float.WIND_EVEN_ODD, mSamples.size() );
|
||||
|
||||
/* Move to the first point */
|
||||
Point2D.Float firstReal = resolve( 0, mSamples.get( 0 ), Type.REAL );
|
||||
polylineReal.moveTo( firstReal.x, firstReal.y );
|
||||
|
||||
Point2D.Float firstImag = resolve( 0, mSamples.get( 0 ), Type.IMAGINERY );
|
||||
polylineImag.moveTo( firstImag.x, firstImag.y );
|
||||
|
||||
for( int x = 1; x < mSamples.size(); x++ )
|
||||
{
|
||||
Point2D.Float pointReal = resolve( x, mSamples.get( x ), Type.REAL );
|
||||
polylineReal.lineTo( pointReal.x, pointReal.y );
|
||||
|
||||
Point2D.Float pointImag = resolve( x, mSamples.get( x ), Type.IMAGINERY );
|
||||
polylineImag.lineTo( pointImag.x, pointImag.y );
|
||||
|
||||
// mLog.debug( "Imag y:" + pointImag.getY() + " height:" + getHeight() );
|
||||
}
|
||||
|
||||
g2.draw( polylineReal );
|
||||
g2.draw( polylineImag );
|
||||
}
|
||||
|
||||
g2.dispose();
|
||||
}
|
||||
|
||||
|
||||
private Point2D.Float resolve( int index, Complex sample, Type type )
|
||||
{
|
||||
int middle = (int)( getHeight() / 4 );
|
||||
|
||||
float y = middle - ( middle * mVerticalZoom * ( type == Type.REAL ?
|
||||
sample.real() : sample.imaginary()) );
|
||||
|
||||
if( type == Type.IMAGINERY )
|
||||
{
|
||||
y += ( middle * 2 );
|
||||
}
|
||||
|
||||
/* Clip y to zero as necessary */
|
||||
y = ( y < 0 ) ? 0 : y;
|
||||
|
||||
/* Clip y to max height as necessary */
|
||||
y = ( y > getHeight() ) ? getHeight() : y;
|
||||
|
||||
float indexWidth = (float)getWidth() / (float)mSampleCount;
|
||||
|
||||
float x = (float)index * indexWidth;
|
||||
|
||||
Point2D.Float point = new Point2D.Float( x, y );
|
||||
|
||||
return new Point2D.Float( x , y );
|
||||
}
|
||||
|
||||
public enum Type{ REAL,IMAGINERY };
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
import io.github.dsheirer.dsp.symbol.Dibit;
|
||||
import io.github.dsheirer.instrument.tap.TapListener;
|
||||
import io.github.dsheirer.instrument.tap.TapType;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
|
||||
public class DibitTap extends StreamTap implements Listener<Dibit>
|
||||
|
||||
{
|
||||
private Listener<Dibit> mListener;
|
||||
|
||||
public DibitTap( String name,
|
||||
int delay,
|
||||
float sampleRateRatio )
|
||||
{
|
||||
super( TapType.STREAM_DIBIT, name, delay, sampleRateRatio );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( Dibit dibit )
|
||||
{
|
||||
if( mListener != null )
|
||||
{
|
||||
mListener.receive( dibit );
|
||||
}
|
||||
|
||||
for( TapListener listener: mListeners )
|
||||
{
|
||||
listener.receive( dibit );
|
||||
}
|
||||
}
|
||||
|
||||
public void setListener( Listener<Dibit> listener )
|
||||
{
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
public void removeListener( Listener<Dibit> listener )
|
||||
{
|
||||
mListener = null;
|
||||
}
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
import io.github.dsheirer.dsp.symbol.Dibit;
|
||||
import io.github.dsheirer.instrument.gui.SampleModel;
|
||||
import io.github.dsheirer.instrument.tap.Tap;
|
||||
import io.github.dsheirer.instrument.tap.TapViewPanel;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.List;
|
||||
import java.util.Observable;
|
||||
|
||||
public class DibitTapViewPanel extends TapViewPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Tap mTap;
|
||||
private List<Dibit> mSamples;
|
||||
private int mSampleCount;
|
||||
private int mOffset = 0;
|
||||
|
||||
public DibitTapViewPanel( DibitTap tap )
|
||||
{
|
||||
super( new SampleModel<Dibit>(), tap.getName() );
|
||||
|
||||
mTap = tap;
|
||||
mTap.addListener( getModel() );
|
||||
|
||||
getModel().setSampleCount(
|
||||
(int)( getModel().getSampleCount() * tap.getSampleRateRatio() ) );
|
||||
|
||||
getModel().setDelay( tap.getDelay() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update( Observable arg0, Object arg1 )
|
||||
{
|
||||
mSamples = (List<Dibit>)getModel().getSamples();
|
||||
mSampleCount = getModel().getSampleCount();
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void paintComponent( Graphics g )
|
||||
{
|
||||
super.paintComponent( g );
|
||||
|
||||
Graphics2D g2 = (Graphics2D)g;
|
||||
|
||||
int height = getHeight();
|
||||
int width = getWidth();
|
||||
|
||||
g2.setColor( Color.DARK_GRAY );
|
||||
|
||||
float middle = (float)height / 2.0f;
|
||||
|
||||
g2.drawLine( 0, (int)middle, width, (int)middle );
|
||||
|
||||
if( mSamples != null && mSamples.size() > 0 )
|
||||
{
|
||||
g2.setColor( getForeground() );
|
||||
|
||||
g2.drawString( mLabel, 5 , 15 );
|
||||
|
||||
for( int x = 1; x < mSamples.size(); x++ )
|
||||
{
|
||||
paintDibit( g, x, mSamples.get( x ) );
|
||||
}
|
||||
}
|
||||
|
||||
g2.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Paints a polyline representing a boolean value with a 0 or 1 label in
|
||||
* the middle of it
|
||||
*
|
||||
* @param graphics
|
||||
* @param index - index of the sample int the sample buffer
|
||||
* @param value - bit value, 0 or 1
|
||||
*/
|
||||
private void paintDibit( Graphics graphics, int index, Dibit value )
|
||||
{
|
||||
Graphics2D g2 = (Graphics2D)graphics;
|
||||
|
||||
Path2D.Float polyline =
|
||||
new Path2D.Float( Path2D.Float.WIND_EVEN_ODD, mSamples.size() );
|
||||
|
||||
float middleY = ( (float)getHeight() / 2.0f );
|
||||
|
||||
float indexWidth = (float)( getWidth() ) / (float)mSampleCount;
|
||||
|
||||
float startX = (float)index * indexWidth;
|
||||
float stopX = (float)(index + 1 ) * indexWidth;
|
||||
float fivePercent = indexWidth * .05f;
|
||||
float leftX = startX + fivePercent;
|
||||
float rightX = stopX - fivePercent;
|
||||
|
||||
/* Start */
|
||||
polyline.moveTo( startX, middleY );
|
||||
|
||||
/* Left horizonal segment */
|
||||
polyline.lineTo( leftX, middleY );
|
||||
|
||||
float y = middleY;
|
||||
|
||||
switch( value )
|
||||
{
|
||||
case D01_PLUS_3:
|
||||
y = middleY - ( middleY * 0.75f);
|
||||
break;
|
||||
case D00_PLUS_1:
|
||||
y = middleY - ( middleY * 0.25f);
|
||||
break;
|
||||
case D10_MINUS_1:
|
||||
y = middleY + ( middleY * 0.25f);
|
||||
break;
|
||||
case D11_MINUS_3:
|
||||
y = middleY + ( middleY * 0.75f);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Left vertical segment */
|
||||
polyline.lineTo( leftX, y );
|
||||
|
||||
/* Middle horizontal segment */
|
||||
polyline.lineTo( rightX, y );
|
||||
|
||||
/* Right vertical segment */
|
||||
polyline.lineTo( rightX, middleY );
|
||||
|
||||
/* Right horizontal segment */
|
||||
polyline.lineTo( stopX, middleY );
|
||||
|
||||
g2.draw( polyline );
|
||||
|
||||
/* Draw the bit value label */
|
||||
String bit = null;
|
||||
|
||||
switch( value )
|
||||
{
|
||||
case D00_PLUS_1:
|
||||
bit = "+1";
|
||||
break;
|
||||
case D01_PLUS_3:
|
||||
bit = "+3";
|
||||
break;
|
||||
case D10_MINUS_1:
|
||||
bit = "-1";
|
||||
break;
|
||||
case D11_MINUS_3:
|
||||
bit = "-3";
|
||||
break;
|
||||
}
|
||||
|
||||
FontMetrics fontMetrics = graphics.getFontMetrics( this.getFont() );
|
||||
|
||||
Rectangle2D label = fontMetrics.getStringBounds( bit, graphics );
|
||||
|
||||
float offsetX = (float)label.getWidth() / 2.0f;
|
||||
float offsetY = (float)label.getWidth() / 2.0f;
|
||||
|
||||
float middleX = startX + ( indexWidth / 2.0f );
|
||||
|
||||
graphics.drawString( bit,
|
||||
(int)( middleX - offsetX ),
|
||||
(int)( middleY - offsetY ) );
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
|
||||
public class EyeDiagramData
|
||||
{
|
||||
private float[] mSamplesInphase;
|
||||
private float[] mSamplesQuadrature;
|
||||
private float mLeftPoint;
|
||||
private float mRightPoint;
|
||||
private float mError;
|
||||
|
||||
public EyeDiagramData( float[] samplesInphase, float[] samplesQuadrature,
|
||||
float leftPoint, float rightPoint, float error )
|
||||
{
|
||||
mSamplesInphase = samplesInphase;
|
||||
mSamplesQuadrature = samplesQuadrature;
|
||||
mLeftPoint = leftPoint;
|
||||
mRightPoint = rightPoint;
|
||||
mError = error;
|
||||
}
|
||||
|
||||
public float[] getInphaseSamples()
|
||||
{
|
||||
return mSamplesInphase;
|
||||
}
|
||||
|
||||
public float[] getQuadratureSamples()
|
||||
{
|
||||
return mSamplesQuadrature;
|
||||
}
|
||||
|
||||
public float getLeftPoint()
|
||||
{
|
||||
return mLeftPoint;
|
||||
}
|
||||
|
||||
public float getRightPoint()
|
||||
{
|
||||
return mRightPoint;
|
||||
}
|
||||
|
||||
public float getError()
|
||||
{
|
||||
return mError;
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
import io.github.dsheirer.instrument.tap.TapListener;
|
||||
import io.github.dsheirer.instrument.tap.TapType;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class EyeDiagramDataTap extends StreamTap implements Listener<EyeDiagramData>
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( EyeDiagramDataTap.class );
|
||||
|
||||
private Listener<EyeDiagramData> mListener;
|
||||
|
||||
public EyeDiagramDataTap( String name, int delay, float sampleRate )
|
||||
{
|
||||
super( TapType.STREAM_EYE_DIAGRAM, name, delay, sampleRate );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( EyeDiagramData data )
|
||||
{
|
||||
if( mListener != null )
|
||||
{
|
||||
mListener.receive( data );
|
||||
}
|
||||
|
||||
for( TapListener listener: mListeners )
|
||||
{
|
||||
listener.receive( data );
|
||||
}
|
||||
}
|
||||
|
||||
public void setListener( Listener<EyeDiagramData> listener )
|
||||
{
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
public void removeListener( Listener<EyeDiagramData> listener )
|
||||
{
|
||||
mListener = null;
|
||||
}
|
||||
}
|
||||
@@ -1,221 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
import io.github.dsheirer.instrument.gui.SampleModel;
|
||||
import io.github.dsheirer.instrument.tap.TapViewPanel;
|
||||
import io.github.dsheirer.sample.complex.Complex;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.util.List;
|
||||
import java.util.Observable;
|
||||
|
||||
public class EyeDiagramDataTapPanel extends TapViewPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( EyeDiagramDataTapPanel.class );
|
||||
|
||||
private EyeDiagramDataTap mTap;
|
||||
private List<EyeDiagramData> mSamples;
|
||||
|
||||
public EyeDiagramDataTapPanel( EyeDiagramDataTap tap )
|
||||
{
|
||||
super( new SampleModel<EyeDiagramData>(), tap.getName() );
|
||||
|
||||
mTap = tap;
|
||||
mTap.addListener( getModel() );
|
||||
|
||||
getModel().setSampleCount( 15 );
|
||||
getModel().setDelay( tap.getDelay() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update( Observable arg0, Object arg1 )
|
||||
{
|
||||
mSamples = (List<EyeDiagramData>)getModel().getSamples();
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void paintComponent( Graphics g )
|
||||
{
|
||||
super.paintComponent( g );
|
||||
|
||||
Graphics2D g2 = (Graphics2D)g;
|
||||
|
||||
float third = getWidth() / 3.0f;
|
||||
float two_thirds = 2.0f * third;
|
||||
float halfHeight = getHeight() / 2.0f;
|
||||
|
||||
float xAxisIncrement = third / 20.0f;
|
||||
|
||||
if( mSamples != null && mSamples.size() > 0 )
|
||||
{
|
||||
/* Draw each of the sample sets */
|
||||
for( int z = 0; z < mSamples.size(); z++ )
|
||||
{
|
||||
if( z == mSamples.size() - 1 )
|
||||
{
|
||||
g2.setColor( Color.BLUE );
|
||||
}
|
||||
else if( z > ( mSamples.size() * .75 ) )
|
||||
{
|
||||
g2.setColor( Color.DARK_GRAY );
|
||||
}
|
||||
else
|
||||
{
|
||||
g2.setColor( Color.LIGHT_GRAY );
|
||||
}
|
||||
|
||||
EyeDiagramData data = mSamples.get( z );
|
||||
|
||||
float[] inphaseSamples = data.getInphaseSamples();
|
||||
float[] quadratureSamples = data.getQuadratureSamples();
|
||||
|
||||
/* Draw the sample set containing two symbol periods of data */
|
||||
if( inphaseSamples.length >= 1 )
|
||||
{
|
||||
Path2D.Float iLine = new Path2D.Float( GeneralPath.WIND_EVEN_ODD, 20 );
|
||||
Path2D.Float qLine = new Path2D.Float( GeneralPath.WIND_EVEN_ODD, 20 );
|
||||
Path2D.Float mLine = new Path2D.Float( GeneralPath.WIND_EVEN_ODD, 20 );
|
||||
|
||||
float xAxis = 0;
|
||||
|
||||
iLine.moveTo( xAxis, getSampleHeight( halfHeight, inphaseSamples[ 0 ] ) );
|
||||
qLine.moveTo( xAxis + third, getSampleHeight( halfHeight, quadratureSamples[ 0 ] ) );
|
||||
mLine.moveTo( xAxis + ( two_thirds ), getMagnitudeHeight( Complex.magnitude( inphaseSamples[ 0 ], quadratureSamples[ 0 ] ) ) );
|
||||
|
||||
for( int x = 1; x < inphaseSamples.length; x++ )
|
||||
{
|
||||
xAxis += xAxisIncrement;
|
||||
|
||||
iLine.lineTo( xAxis, getSampleHeight( halfHeight, inphaseSamples[ x ] ) );
|
||||
qLine.lineTo( xAxis + third, getSampleHeight( halfHeight, quadratureSamples[ x ] ) );
|
||||
mLine.lineTo( xAxis + two_thirds, getMagnitudeHeight( Complex.magnitude( inphaseSamples[ x ], quadratureSamples[ x ] ) ) );
|
||||
}
|
||||
|
||||
g2.draw( iLine );
|
||||
g2.draw( qLine );
|
||||
g2.draw( mLine );
|
||||
|
||||
/* Left Sample line */
|
||||
if( z == mSamples.size() - 1 )
|
||||
{
|
||||
g2.setColor( Color.GREEN );
|
||||
}
|
||||
else
|
||||
{
|
||||
g2.setColor( Color.LIGHT_GRAY );
|
||||
}
|
||||
xAxis = xAxisIncrement * data.getLeftPoint();
|
||||
g2.drawLine( (int)xAxis, 5, (int)xAxis, getHeight() - 5 );
|
||||
g2.drawLine( (int)( xAxis + third ), 5, (int)( xAxis + third ), getHeight() - 5 );
|
||||
g2.drawLine( (int)( xAxis + two_thirds ), 5, (int)( xAxis + two_thirds ), getHeight() - 5 );
|
||||
|
||||
/* Right Sample line */
|
||||
if( z == mSamples.size() - 1 )
|
||||
{
|
||||
g2.setColor( Color.GREEN );
|
||||
}
|
||||
else
|
||||
{
|
||||
g2.setColor( Color.LIGHT_GRAY );
|
||||
}
|
||||
xAxis = xAxisIncrement * data.getRightPoint();
|
||||
g2.drawLine( (int)xAxis, 5, (int)xAxis, getHeight() - 5 );
|
||||
g2.drawLine( (int)( xAxis + third ), 5, (int)( xAxis + third ), getHeight() - 5 );
|
||||
g2.drawLine( (int)( xAxis + two_thirds ), 5, (int)( xAxis + two_thirds ), getHeight() - 5 );
|
||||
|
||||
/* Error indicator */
|
||||
float error = data.getError();
|
||||
|
||||
if( z == mSamples.size() - 1 )
|
||||
{
|
||||
g2.setColor( Color.BLACK );
|
||||
|
||||
float xFrom;
|
||||
float xTo;
|
||||
|
||||
if( error < 0.0f )
|
||||
{
|
||||
xFrom = (int)( xAxisIncrement * data.getLeftPoint() );
|
||||
xTo = xFrom - 25.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
xFrom = (int)( xAxisIncrement * data.getRightPoint() );
|
||||
xTo = xFrom + 25.0f;
|
||||
}
|
||||
|
||||
g2.drawLine( (int)xFrom, (int)halfHeight - 15, (int)xTo, (int)halfHeight );
|
||||
g2.drawLine( (int)xFrom, (int)halfHeight + 15, (int)xTo, (int)halfHeight );
|
||||
g2.drawLine( (int)( xFrom + third ), (int)halfHeight - 15, (int)( xTo + third ), (int)halfHeight );
|
||||
g2.drawLine( (int)( xFrom + third ), (int)halfHeight + 15, (int)( xTo + third ), (int)halfHeight );
|
||||
g2.drawLine( (int)( xFrom + two_thirds ), (int)halfHeight - 15, (int)( xTo + two_thirds ), (int)halfHeight );
|
||||
g2.drawLine( (int)( xFrom + two_thirds ), (int)halfHeight + 15, (int)( xTo + two_thirds ), (int)halfHeight );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g2.setColor( Color.BLUE );
|
||||
g2.drawString( "Eye Diagram - I Leg", 5, 15 );
|
||||
g2.drawString( "Eye Diagram - Q Leg", third, 15 );
|
||||
g2.drawString( "Eye Diagram - Magnitude", two_thirds, 15 );
|
||||
|
||||
|
||||
/* Horizontal middle line */
|
||||
g2.setColor( Color.CYAN );
|
||||
g2.drawLine( 0, (int)halfHeight, getWidth(), (int)halfHeight );
|
||||
|
||||
g2.dispose();
|
||||
}
|
||||
|
||||
private float getSampleHeight( float halfHeight, float value )
|
||||
{
|
||||
if( value > 1.0 )
|
||||
{
|
||||
value = 1.0f;
|
||||
}
|
||||
if( value < -1.0 )
|
||||
{
|
||||
value = -1.0f;
|
||||
}
|
||||
|
||||
return halfHeight + ( .95f * ( halfHeight * value ) );
|
||||
}
|
||||
|
||||
private float getMagnitudeHeight( float magnitude )
|
||||
{
|
||||
if( magnitude > 1.0 )
|
||||
{
|
||||
magnitude = 1.0f;
|
||||
}
|
||||
|
||||
return getHeight() - ( getHeight() * magnitude );
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.real.RealBuffer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class FloatBufferTap extends FloatTap implements Listener<RealBuffer>
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( FloatBufferTap.class );
|
||||
|
||||
private Listener<RealBuffer> mRealBufferListener;
|
||||
|
||||
public FloatBufferTap( String name, int delay, float sampleRateRatio )
|
||||
{
|
||||
super( name, delay, sampleRateRatio );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( RealBuffer buffer )
|
||||
{
|
||||
if( mRealBufferListener != null )
|
||||
{
|
||||
mRealBufferListener.receive( buffer );
|
||||
}
|
||||
|
||||
for( float sample: buffer.getSamples() )
|
||||
{
|
||||
super.receive( sample );
|
||||
}
|
||||
}
|
||||
|
||||
public void setListener( Listener<RealBuffer> listener )
|
||||
{
|
||||
mRealBufferListener = listener;
|
||||
}
|
||||
|
||||
public void removeListener( Listener<RealBuffer> listener )
|
||||
{
|
||||
mRealBufferListener = null;
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
import io.github.dsheirer.instrument.tap.TapListener;
|
||||
import io.github.dsheirer.instrument.tap.TapType;
|
||||
import io.github.dsheirer.sample.real.RealSampleListener;
|
||||
|
||||
public class FloatTap extends StreamTap implements RealSampleListener
|
||||
{
|
||||
private RealSampleListener mFloatTapListener;
|
||||
|
||||
public FloatTap( String name,
|
||||
int delay,
|
||||
float sampleRateRatio )
|
||||
{
|
||||
super( TapType.STREAM_FLOAT, name, delay, sampleRateRatio );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( float sample )
|
||||
{
|
||||
if( mFloatTapListener != null )
|
||||
{
|
||||
mFloatTapListener.receive( sample );
|
||||
}
|
||||
|
||||
for( TapListener listener: mListeners )
|
||||
{
|
||||
listener.receive( sample );
|
||||
}
|
||||
}
|
||||
|
||||
public void setListener( RealSampleListener listener )
|
||||
{
|
||||
mFloatTapListener = listener;
|
||||
}
|
||||
|
||||
public void removeListener( RealSampleListener listener )
|
||||
{
|
||||
mFloatTapListener = null;
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
import io.github.dsheirer.instrument.gui.SampleModel;
|
||||
import io.github.dsheirer.instrument.tap.Tap;
|
||||
import io.github.dsheirer.instrument.tap.TapViewPanel;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.util.List;
|
||||
import java.util.Observable;
|
||||
|
||||
public class FloatTapPhaseViewPanel extends TapViewPanel
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( FloatTapPhaseViewPanel.class );
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Tap mTap;
|
||||
private List<Float> mSamples;
|
||||
private int mSampleCount;
|
||||
|
||||
public FloatTapPhaseViewPanel( FloatTap tap )
|
||||
{
|
||||
super( new SampleModel<Float>(), tap.getName() );
|
||||
|
||||
mTap = tap;
|
||||
mTap.addListener( getModel() );
|
||||
|
||||
mSampleCount = (int)( 2000 * tap.getSampleRateRatio() );
|
||||
|
||||
getModel().setSampleCount( mSampleCount );
|
||||
getModel().setDelay( tap.getDelay() );
|
||||
|
||||
mLog.info( "Float Tap Panel [" + tap.getName() + "] count: " +
|
||||
getModel().getSampleCount() + " delay:" + getModel().getDelay() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update( Observable arg0, Object arg1 )
|
||||
{
|
||||
mSamples = (List<Float>)getModel().getSamples();
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void paintComponent( Graphics g )
|
||||
{
|
||||
super.paintComponent( g );
|
||||
|
||||
Graphics2D g2 = (Graphics2D)g;
|
||||
|
||||
int height = getHeight();
|
||||
int width = getWidth();
|
||||
|
||||
g2.setColor( Color.DARK_GRAY );
|
||||
|
||||
float middle = (float)height / 2.0f;
|
||||
|
||||
g2.drawLine( 0, (int)middle, width, (int)middle );
|
||||
|
||||
if( mSamples != null &&
|
||||
mSamples.size() > 0 )
|
||||
{
|
||||
g2.setColor( getForeground() );
|
||||
|
||||
g2.drawString( mLabel, 5 , 15 );
|
||||
|
||||
Path2D.Float polyline =
|
||||
new Path2D.Float( Path2D.Float.WIND_EVEN_ODD, mSamples.size() );
|
||||
|
||||
/* Move to the first point */
|
||||
Point2D.Float first = resolve( 0, mSamples.get( 0 ) );
|
||||
polyline.moveTo( first.x, first.y );
|
||||
|
||||
for( int x = 1; x < mSamples.size(); x++ )
|
||||
{
|
||||
Point2D.Float point = resolve( x, mSamples.get( x ) );
|
||||
|
||||
polyline.lineTo( point.x, point.y );
|
||||
}
|
||||
|
||||
g2.draw(polyline);
|
||||
}
|
||||
|
||||
g2.dispose();
|
||||
}
|
||||
|
||||
private Point2D.Float resolve( int index, float value )
|
||||
{
|
||||
int middle = (int)( getHeight() / 2 );
|
||||
|
||||
double scaledValue = Math.asin( value );
|
||||
|
||||
float y = middle - (float)( middle * scaledValue * mVerticalZoom );
|
||||
|
||||
/* Clip y to zero as necessary */
|
||||
y = ( y < 0 ) ? 0 : y;
|
||||
|
||||
/* Clip y to max height as necessary */
|
||||
y = ( y > getHeight() ) ? getHeight() : y;
|
||||
|
||||
float indexWidth = (float)getWidth() / (float)mSampleCount;
|
||||
|
||||
float x = (float)index * indexWidth;
|
||||
|
||||
Point2D.Float point = new Point2D.Float( x, y );
|
||||
|
||||
return new Point2D.Float( x , y );
|
||||
}
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
import io.github.dsheirer.gui.SDRTrunk;
|
||||
import io.github.dsheirer.instrument.gui.SampleModel;
|
||||
import io.github.dsheirer.instrument.tap.Tap;
|
||||
import io.github.dsheirer.instrument.tap.TapViewPanel;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.util.List;
|
||||
import java.util.Observable;
|
||||
|
||||
public class FloatTapViewPanel extends TapViewPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final static Logger mLog = LoggerFactory.getLogger( SDRTrunk.class );
|
||||
|
||||
private Tap mTap;
|
||||
private List<Float> mSamples;
|
||||
private int mSampleCount;
|
||||
|
||||
public FloatTapViewPanel( FloatTap tap )
|
||||
{
|
||||
super( new SampleModel<Float>(), tap.getName() );
|
||||
|
||||
mTap = tap;
|
||||
mTap.addListener( getModel() );
|
||||
|
||||
mSampleCount = (int)( 2000 * tap.getSampleRateRatio() );
|
||||
|
||||
getModel().setSampleCount( mSampleCount );
|
||||
getModel().setDelay( tap.getDelay() );
|
||||
|
||||
mLog.info( "Float Tap Panel [" + tap.getName() + "] count: " +
|
||||
getModel().getSampleCount() + " delay:" + getModel().getDelay() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update( Observable arg0, Object arg1 )
|
||||
{
|
||||
mSamples = (List<Float>)getModel().getSamples();
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void paintComponent( Graphics g )
|
||||
{
|
||||
super.paintComponent( g );
|
||||
|
||||
Graphics2D g2 = (Graphics2D)g;
|
||||
|
||||
int height = getHeight();
|
||||
int width = getWidth();
|
||||
|
||||
g2.setColor( Color.DARK_GRAY );
|
||||
|
||||
float middle = (float)height / 2.0f;
|
||||
|
||||
g2.drawLine( 0, (int)middle, width, (int)middle );
|
||||
|
||||
if( mSamples != null &&
|
||||
mSamples.size() > 0 )
|
||||
{
|
||||
g2.setColor( getForeground() );
|
||||
|
||||
g2.drawString( mLabel, 5 , 15 );
|
||||
|
||||
Path2D.Float polyline =
|
||||
new Path2D.Float( Path2D.Float.WIND_EVEN_ODD, mSamples.size() );
|
||||
|
||||
/* Move to the first point */
|
||||
Point2D.Float first = resolve( 0, mSamples.get( 0 ) );
|
||||
polyline.moveTo( first.x, first.y );
|
||||
|
||||
for( int x = 1; x < mSamples.size(); x++ )
|
||||
{
|
||||
Point2D.Float point = resolve( x, mSamples.get( x ) );
|
||||
|
||||
polyline.lineTo( point.x, point.y );
|
||||
}
|
||||
|
||||
g2.draw(polyline);
|
||||
}
|
||||
|
||||
g2.dispose();
|
||||
}
|
||||
|
||||
private Point2D.Float resolve( int index, float value )
|
||||
{
|
||||
int middle = (int)( getHeight() / 2 );
|
||||
|
||||
float y = middle - ( middle * value * mVerticalZoom );
|
||||
|
||||
/* Clip y to zero as necessary */
|
||||
y = ( y < 0 ) ? 0 : y;
|
||||
|
||||
/* Clip y to max height as necessary */
|
||||
y = ( y > getHeight() ) ? getHeight() : y;
|
||||
|
||||
float indexWidth = (float)getWidth() / (float)mSampleCount;
|
||||
|
||||
float x = (float)index * indexWidth;
|
||||
|
||||
Point2D.Float point = new Point2D.Float( x, y );
|
||||
|
||||
return new Point2D.Float( x , y );
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
|
||||
public class GainFloatTap extends FloatTap
|
||||
{
|
||||
private float mGain;
|
||||
|
||||
public GainFloatTap( String name,
|
||||
int delay,
|
||||
float sampleRateRatio,
|
||||
float gain )
|
||||
{
|
||||
super( name, delay, sampleRateRatio );
|
||||
|
||||
mGain = gain;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( float sample )
|
||||
{
|
||||
super.receive( sample * mGain );
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
import io.github.dsheirer.instrument.tap.TapType;
|
||||
|
||||
public class QPSKTap extends ComplexTap
|
||||
{
|
||||
public QPSKTap( String name, int delay, float sampleRateRatio )
|
||||
{
|
||||
super( TapType.STREAM_QPSK, name, delay, sampleRateRatio );
|
||||
}
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
import io.github.dsheirer.gui.SDRTrunk;
|
||||
import io.github.dsheirer.instrument.gui.SampleModel;
|
||||
import io.github.dsheirer.instrument.tap.Tap;
|
||||
import io.github.dsheirer.instrument.tap.TapViewPanel;
|
||||
import io.github.dsheirer.sample.complex.Complex;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.util.List;
|
||||
import java.util.Observable;
|
||||
|
||||
public class QPSKTapPanel extends TapViewPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final static Logger mLog = LoggerFactory.getLogger( SDRTrunk.class );
|
||||
|
||||
private Tap mTap;
|
||||
private List<Complex> mSamples;
|
||||
private int mSampleCount;
|
||||
|
||||
public QPSKTapPanel( ComplexTap tap )
|
||||
{
|
||||
super( new SampleModel<ComplexTap>(), tap.getName() );
|
||||
|
||||
mTap = tap;
|
||||
mTap.addListener( getModel() );
|
||||
|
||||
mSampleCount = (int)( 60 * tap.getSampleRateRatio() );
|
||||
|
||||
getModel().setSampleCount( mSampleCount );
|
||||
getModel().setDelay( tap.getDelay() );
|
||||
|
||||
mLog.info( "Complex Tap Panel [" + tap.getName() + "] count: " +
|
||||
getModel().getSampleCount() + " delay:" + getModel().getDelay() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update( Observable arg0, Object arg1 )
|
||||
{
|
||||
mSamples = (List<Complex>)getModel().getSamples();
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void paintComponent( Graphics g )
|
||||
{
|
||||
super.paintComponent( g );
|
||||
|
||||
Graphics2D g2 = (Graphics2D)g;
|
||||
|
||||
int min = ( getHeight() < getWidth() ? getHeight() : getWidth() );
|
||||
|
||||
float middle = (float)min / 2.0f;
|
||||
|
||||
g2.setColor( Color.DARK_GRAY );
|
||||
|
||||
/* Vertical Line */
|
||||
g2.drawLine( getWidth() / 2, 5, getWidth() / 2, getHeight() - 5 );
|
||||
|
||||
/* Horizontal Line */
|
||||
g2.drawLine( getWidth() / 2 - (int)( middle ), getHeight() / 2,
|
||||
getWidth() / 2 + (int)( middle ), getHeight() / 2 );
|
||||
|
||||
g2.setColor( Color.CYAN );
|
||||
|
||||
/* Crossed Lines */
|
||||
g2.drawLine( getWidth() / 2 - (int)( middle ), 5,
|
||||
getWidth() / 2 + (int)( middle ), getHeight() - 5 );
|
||||
g2.drawLine( getWidth() / 2 + (int)( middle ), 5,
|
||||
getWidth() / 2 - (int)( middle ), getHeight() - 5 );
|
||||
|
||||
|
||||
|
||||
if( mSamples != null &&
|
||||
mSamples.size() > 0 )
|
||||
{
|
||||
g2.drawString( mLabel, 5 , 15 );
|
||||
|
||||
/* Set color to light gray for oldest 90% of constellations */
|
||||
g2.setColor( Color.LIGHT_GRAY );
|
||||
|
||||
int counter = 0;
|
||||
|
||||
int threshold = (int)( mSamples.size() * 0.9f );
|
||||
|
||||
for( Complex sample: mSamples )
|
||||
{
|
||||
/* Set color to foreground for newest 10% of constellations */
|
||||
if( counter == threshold )
|
||||
{
|
||||
g2.setColor( getForeground() );
|
||||
}
|
||||
|
||||
// float scale;
|
||||
//
|
||||
// if( sample.real() != 0 && sample.imaginary() != 0 )
|
||||
// {
|
||||
// scale = 1.0f / sample.magnitude();
|
||||
// }
|
||||
// else if( sample.real() == 0 )
|
||||
// {
|
||||
// scale = 1.0f / sample.imaginary();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// scale = 1.0f / sample.real();
|
||||
// }
|
||||
|
||||
// float x = ( getWidth() / 2 ) +
|
||||
// ( scale * sample.real() * middle * 0.75f * mVerticalZoom );
|
||||
float x = ( getWidth() / 2 ) +
|
||||
( sample.real() * middle * 0.75f * mVerticalZoom );
|
||||
|
||||
if( Float.isNaN( x ) )
|
||||
{
|
||||
x = getWidth() / 2;
|
||||
}
|
||||
|
||||
// float y = ( getHeight() / 2 ) +
|
||||
// ( scale * sample.imaginary() * middle * 0.75f * mVerticalZoom );
|
||||
float y = ( getHeight() / 2 ) +
|
||||
( sample.imaginary() * middle * 0.75f * mVerticalZoom );
|
||||
|
||||
if( Float.isNaN( y ) )
|
||||
{
|
||||
y = getHeight() / 2;
|
||||
}
|
||||
|
||||
g2.draw( new Ellipse2D.Float( x, y, 4.0f, 4.0f ) );
|
||||
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
g2.dispose();
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
import io.github.dsheirer.instrument.tap.Tap;
|
||||
import io.github.dsheirer.instrument.tap.TapType;
|
||||
|
||||
public abstract class StreamTap extends Tap
|
||||
{
|
||||
protected float mSampleRateRatio;
|
||||
|
||||
public StreamTap( TapType type,
|
||||
String name,
|
||||
int delay,
|
||||
float sampleRate )
|
||||
{
|
||||
super( type, name, delay );
|
||||
|
||||
mSampleRateRatio = sampleRate;
|
||||
}
|
||||
|
||||
public float getSampleRateRatio()
|
||||
{
|
||||
return mSampleRateRatio;
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
import io.github.dsheirer.dsp.symbol.SymbolEvent;
|
||||
import io.github.dsheirer.instrument.tap.TapListener;
|
||||
import io.github.dsheirer.instrument.tap.TapType;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
|
||||
public class SymbolEventTap extends StreamTap implements Listener<SymbolEvent>
|
||||
{
|
||||
private Listener<SymbolEvent> mListener;
|
||||
|
||||
public SymbolEventTap( String name, int delay, float sampleRate )
|
||||
{
|
||||
super( TapType.STREAM_SYMBOL, name, delay, sampleRate );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( SymbolEvent symbolEvent )
|
||||
{
|
||||
if( mListener != null )
|
||||
{
|
||||
mListener.receive( symbolEvent );
|
||||
}
|
||||
|
||||
for( TapListener listener: mListeners )
|
||||
{
|
||||
listener.receive( symbolEvent );
|
||||
}
|
||||
}
|
||||
|
||||
public void setListener( Listener<SymbolEvent> listener )
|
||||
{
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
public void removeListener( Listener<SymbolEvent> listener )
|
||||
{
|
||||
mListener = null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,187 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.instrument.tap.stream;
|
||||
|
||||
import io.github.dsheirer.dsp.symbol.SymbolEvent;
|
||||
import io.github.dsheirer.instrument.gui.SampleModel;
|
||||
import io.github.dsheirer.instrument.tap.TapViewPanel;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.List;
|
||||
import java.util.Observable;
|
||||
|
||||
public class SymbolEventTapViewPanel extends TapViewPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private SymbolEventTap mTap;
|
||||
private List<SymbolEvent> mSamples;
|
||||
private int mSampleCount;
|
||||
|
||||
public SymbolEventTapViewPanel( SymbolEventTap tap )
|
||||
{
|
||||
super( new SampleModel<SymbolEvent>(), tap.getName() );
|
||||
|
||||
mTap = tap;
|
||||
mTap.addListener( getModel() );
|
||||
|
||||
mSampleCount = (int)( getModel().getSampleCount() * tap.getSampleRateRatio() );
|
||||
|
||||
getModel().setSampleCount( mSampleCount );
|
||||
|
||||
getModel().setDelay( tap.getDelay() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update( Observable arg0, Object arg1 )
|
||||
{
|
||||
mSamples = (List<SymbolEvent>)getModel().getSamples();
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void paintComponent( Graphics g )
|
||||
{
|
||||
super.paintComponent( g );
|
||||
|
||||
Graphics2D g2 = (Graphics2D)g;
|
||||
|
||||
int height = getHeight();
|
||||
int width = getWidth();
|
||||
|
||||
g2.setColor( Color.DARK_GRAY );
|
||||
|
||||
float middle = (float)height / 2.0f;
|
||||
|
||||
g2.drawLine( 0, (int)middle, width, (int)middle );
|
||||
|
||||
if( mSamples != null && mSamples.size() > 0 )
|
||||
{
|
||||
g2.setColor( getForeground() );
|
||||
|
||||
g2.drawString( mLabel, 5 , 15 );
|
||||
|
||||
for( int x = 1; x < mSamples.size(); x++ )
|
||||
{
|
||||
paint( g, x, mSamples.get( x ) );
|
||||
}
|
||||
}
|
||||
|
||||
g2.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Paints a polyline representing a boolean value with a 0 or 1 label in
|
||||
* the middle of it
|
||||
*
|
||||
* @param graphics
|
||||
* @param index - index of the sample int the sample buffer
|
||||
* @param value - bit value, 0 or 1
|
||||
*/
|
||||
private void paint( Graphics graphics, int index, SymbolEvent symbol )
|
||||
{
|
||||
Graphics2D g2 = (Graphics2D)graphics;
|
||||
|
||||
g2.setColor( getForeground() );
|
||||
|
||||
Path2D.Float polyline =
|
||||
new Path2D.Float( Path2D.Float.WIND_EVEN_ODD, mSamples.size() );
|
||||
|
||||
float middleY = ( (float)getHeight() / 2.0f );
|
||||
|
||||
float indexWidth = (float)( getWidth() ) / (float)mSampleCount;
|
||||
|
||||
float startX = (float)index * indexWidth;
|
||||
float stopX = (float)(index + 1 ) * indexWidth;
|
||||
float fivePercent = indexWidth * .05f;
|
||||
float leftX = startX + fivePercent;
|
||||
float rightX = stopX - fivePercent;
|
||||
|
||||
/* Start */
|
||||
polyline.moveTo( startX, middleY );
|
||||
|
||||
/* Left horizonal segment */
|
||||
polyline.lineTo( leftX, middleY );
|
||||
|
||||
float y = ( symbol.getDecision() ? ( middleY - ( middleY * 0.5f) ) :
|
||||
( middleY + ( middleY * 0.5f) ) );
|
||||
|
||||
/* Left vertical segment */
|
||||
polyline.lineTo( leftX, y );
|
||||
|
||||
/* Middle horizontal segment */
|
||||
polyline.lineTo( rightX, y );
|
||||
|
||||
/* Right vertical segment */
|
||||
polyline.lineTo( rightX, middleY );
|
||||
|
||||
/* Right horizontal segment */
|
||||
polyline.lineTo( stopX, middleY );
|
||||
|
||||
g2.draw( polyline );
|
||||
|
||||
/* Draw the bit value label */
|
||||
String bit = symbol.getDecision() ? "1" : "0";
|
||||
|
||||
FontMetrics fontMetrics = graphics.getFontMetrics( this.getFont() );
|
||||
|
||||
Rectangle2D label = fontMetrics.getStringBounds( bit, graphics );
|
||||
|
||||
float offsetX = (float)label.getWidth() / 2.0f;
|
||||
float offsetY = (float)label.getHeight() / 2.0f;
|
||||
|
||||
float middleX = startX + ( indexWidth / 2.0f );
|
||||
|
||||
graphics.drawString( bit,
|
||||
(int)( middleX - offsetX ),
|
||||
(int)( middleY - ( ( middleY < y ) ? offsetY : -( 2.0f * offsetY ) ) ) );
|
||||
|
||||
/* Draw samples */
|
||||
float sampleWidth = ( rightX - leftX ) / (float)( symbol.getSamplesPerSymbol() + 1 );
|
||||
|
||||
g2.setColor( Color.GREEN );
|
||||
|
||||
for( int x = 0; x < symbol.getSamplesPerSymbol(); x++ )
|
||||
{
|
||||
Path2D.Float line =
|
||||
new Path2D.Float( Path2D.Float.WIND_EVEN_ODD, 2 );
|
||||
|
||||
float sampleX = leftX + ( ( x + 1 ) * sampleWidth );
|
||||
|
||||
// line.moveTo( sampleX, middleY );
|
||||
line.moveTo( sampleX, ( symbol.getBitSet().get( x ) ?
|
||||
middleY - ( middleY * .05f ) :
|
||||
middleY + ( middleY * .05f ) ) );
|
||||
|
||||
float sampleY = ( symbol.getBitSet().get( x ) ?
|
||||
( middleY - ( middleY * 0.45f ) ) :
|
||||
( middleY + ( middleY * 0.45f ) ) );
|
||||
|
||||
line.lineTo( sampleX, sampleY );
|
||||
|
||||
g2.draw( line );
|
||||
|
||||
graphics.drawString( symbol.getShift().getLabel(),
|
||||
(int)( middleX - offsetX ),
|
||||
(int)( y - ( ( y < middleY ) ? offsetY : -( 2.0f * offsetY ) ) ) );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
package io.github.dsheirer.module.decode.fleetsync2;
|
||||
|
||||
import io.github.dsheirer.dsp.afsk.AFSK1200DecoderInstrumented;
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.IInstrumentedAFSK1200Decoder;
|
||||
import io.github.dsheirer.instrument.chart.IInstrumentedAFSK1200Decoder;
|
||||
import io.github.dsheirer.sample.buffer.ReusableBuffer;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
package io.github.dsheirer.module.decode.lj1200;
|
||||
|
||||
import io.github.dsheirer.dsp.afsk.AFSK1200DecoderInstrumented;
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.IInstrumentedAFSK1200Decoder;
|
||||
import io.github.dsheirer.instrument.chart.IInstrumentedAFSK1200Decoder;
|
||||
import io.github.dsheirer.sample.buffer.ReusableBuffer;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
package io.github.dsheirer.module.decode.mdc1200;
|
||||
|
||||
import io.github.dsheirer.dsp.afsk.AFSK1200DecoderInstrumented;
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.IInstrumentedAFSK1200Decoder;
|
||||
import io.github.dsheirer.instrument.chart.IInstrumentedAFSK1200Decoder;
|
||||
import io.github.dsheirer.sample.buffer.ReusableBuffer;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
package io.github.dsheirer.module.decode.mpt1327;
|
||||
|
||||
import io.github.dsheirer.dsp.afsk.AFSK1200DecoderInstrumented;
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.IInstrumentedAFSK1200Decoder;
|
||||
import io.github.dsheirer.instrument.chart.IInstrumentedAFSK1200Decoder;
|
||||
import io.github.dsheirer.sample.buffer.ReusableBuffer;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
|
||||
|
||||
@@ -1,253 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.module.decode.mpt1327;
|
||||
|
||||
import io.github.dsheirer.alias.AliasList;
|
||||
import io.github.dsheirer.bits.MessageFramer;
|
||||
import io.github.dsheirer.dsp.filter.FilterFactory;
|
||||
import io.github.dsheirer.dsp.filter.Filters;
|
||||
import io.github.dsheirer.dsp.filter.fir.FIRFilterSpecification;
|
||||
import io.github.dsheirer.dsp.filter.fir.real.RealFIRFilter_RB_RB;
|
||||
import io.github.dsheirer.dsp.filter.halfband.real.HalfBandFilter_RB_RB;
|
||||
import io.github.dsheirer.dsp.fsk.FSK2Decoder;
|
||||
import io.github.dsheirer.instrument.Instrumentable;
|
||||
import io.github.dsheirer.instrument.tap.Tap;
|
||||
import io.github.dsheirer.instrument.tap.TapGroup;
|
||||
import io.github.dsheirer.instrument.tap.stream.BinaryTap;
|
||||
import io.github.dsheirer.instrument.tap.stream.FloatBufferTap;
|
||||
import io.github.dsheirer.instrument.tap.stream.FloatTap;
|
||||
import io.github.dsheirer.module.decode.Decoder;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.sample.Broadcaster;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.real.IFilteredRealBufferListener;
|
||||
import io.github.dsheirer.sample.real.RealBuffer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* MPT1327 Decoder - 1200 baud 2FSK decoder that can process 48k sample rate
|
||||
* complex or floating point samples and output fully framed MPT1327 control and
|
||||
* traffic messages.
|
||||
*/
|
||||
public class MPT1327DecoderLegacy extends Decoder implements IFilteredRealBufferListener, Instrumentable
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(MPT1327DecoderLegacy.class);
|
||||
|
||||
private static final FIRFilterSpecification HIGH_PASS_SPECIFICATION = FIRFilterSpecification.highPassBuilder()
|
||||
.sampleRate( 24000 )
|
||||
.stopBandCutoff( 800 )
|
||||
.stopBandAmplitude( 0.0 )
|
||||
.stopBandRipple( 0.03 )
|
||||
.passBandStart( 1000 )
|
||||
.passBandAmplitude( 1.0 )
|
||||
.passBandRipple( 0.08 )
|
||||
.build();
|
||||
|
||||
private static float[] HIGHPASS_FILTER;
|
||||
|
||||
static
|
||||
{
|
||||
try
|
||||
{
|
||||
HIGHPASS_FILTER = FilterFactory.getTaps(HIGH_PASS_SPECIFICATION);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
mLog.error("Couldn't design MPT1327 highpass filter");
|
||||
}
|
||||
}
|
||||
|
||||
/* Decimated sample rate ( 48,000 / 2 = 24,000 ) feeding the decoder */
|
||||
private static final int sDECIMATED_SAMPLE_RATE = 24000;
|
||||
|
||||
/* Baud or Symbol Rate */
|
||||
private static final int sSYMBOL_RATE = 1200;
|
||||
|
||||
/* Message length -- longest possible message is:
|
||||
* 4xREVS + 16xSYNC + 64xADD1 + 64xDCW1 + 64xDCW2 + 64xDCW3 + 64xDCW4 */
|
||||
private static final int sMESSAGE_LENGTH = 350;
|
||||
|
||||
/* Instrumentation Taps */
|
||||
private static final String INSTRUMENT_HB1_FILTER_TO_HIGH_PASS =
|
||||
"Tap Point: Half-band Decimation Filter > < Low Pass Filter";
|
||||
private static final String INSTRUMENT_HIGH_PASS_TO_DECODER =
|
||||
"Tap Point: Low Pass Filter > < Decoder";
|
||||
private static final String INSTRUMENT_DECODER_TO_FRAMER =
|
||||
"Tap Point: Decoder > < Sync Detect/Message Framer";
|
||||
private List<TapGroup> mAvailableTaps;
|
||||
|
||||
private HalfBandFilter_RB_RB mDecimationFilter;
|
||||
private RealFIRFilter_RB_RB mHighPassFilter;
|
||||
private FSK2Decoder mFSKDecoder;
|
||||
private Broadcaster<Boolean> mSymbolBroadcaster;
|
||||
private MessageFramer mControlMessageFramer;
|
||||
private MessageFramer mTrafficMessageFramer;
|
||||
private MPT1327MessageProcessor mMessageProcessor;
|
||||
|
||||
public MPT1327DecoderLegacy(AliasList aliasList, Sync sync)
|
||||
{
|
||||
/**
|
||||
* Normal: 2FSK Decoder with inverted output
|
||||
* French: 2FSK Decoder with normal output
|
||||
*/
|
||||
if(sync == Sync.NORMAL)
|
||||
{
|
||||
mFSKDecoder = new FSK2Decoder(24000, 1200, FSK2Decoder.Output.INVERTED);
|
||||
}
|
||||
else if(sync == Sync.FRENCH)
|
||||
{
|
||||
mFSKDecoder = new FSK2Decoder(24000, 1200, FSK2Decoder.Output.NORMAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("MPT1327 Decoder - unrecognized Sync type");
|
||||
}
|
||||
|
||||
/* Decimation filter - 48000 / 2 = 24000 output */
|
||||
mDecimationFilter = new HalfBandFilter_RB_RB(Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO.getCoefficients(), 1.0002f, true);
|
||||
|
||||
//High-pass filter the audio to remove any DC component or CTCSS tones. The audio has already been low-pass
|
||||
//filtered by the AudioDemodulation filter cutoff of 3400 Hz.
|
||||
mHighPassFilter = new RealFIRFilter_RB_RB(HIGHPASS_FILTER, 1.0f);
|
||||
mDecimationFilter.setListener(mHighPassFilter);
|
||||
|
||||
mHighPassFilter.setListener(mFSKDecoder);
|
||||
|
||||
mSymbolBroadcaster = new Broadcaster<Boolean>();
|
||||
mFSKDecoder.setListener(mSymbolBroadcaster);
|
||||
|
||||
/* Message framer for control channel messages */
|
||||
mControlMessageFramer = new MessageFramer(sync.getControlSyncPattern().getPattern(), sMESSAGE_LENGTH);
|
||||
mSymbolBroadcaster.addListener(mControlMessageFramer);
|
||||
|
||||
/* Message framer for traffic channel massages */
|
||||
mTrafficMessageFramer = new MessageFramer(sync.getTrafficSyncPattern().getPattern(), sMESSAGE_LENGTH);
|
||||
mSymbolBroadcaster.addListener(mTrafficMessageFramer);
|
||||
|
||||
/* Fully decoded and framed messages processor */
|
||||
mMessageProcessor = new MPT1327MessageProcessor(aliasList);
|
||||
mMessageProcessor.setMessageListener(getMessageListener());
|
||||
mControlMessageFramer.addMessageListener(mMessageProcessor);
|
||||
mTrafficMessageFramer.addMessageListener(mMessageProcessor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<RealBuffer> getFilteredRealBufferListener()
|
||||
{
|
||||
return mDecimationFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecoderType getDecoderType()
|
||||
{
|
||||
return DecoderType.MPT1327;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup method
|
||||
*/
|
||||
public void dispose()
|
||||
{
|
||||
super.dispose();
|
||||
|
||||
mSymbolBroadcaster.dispose();
|
||||
|
||||
mControlMessageFramer.dispose();
|
||||
|
||||
mFSKDecoder.dispose();
|
||||
|
||||
mDecimationFilter.dispose();
|
||||
|
||||
mMessageProcessor.dispose();
|
||||
|
||||
mTrafficMessageFramer.dispose();
|
||||
}
|
||||
|
||||
/* Instrumentation Taps */
|
||||
@Override
|
||||
public List<TapGroup> getTapGroups()
|
||||
{
|
||||
if(mAvailableTaps == null)
|
||||
{
|
||||
mAvailableTaps = new ArrayList<TapGroup>();
|
||||
|
||||
TapGroup group = new TapGroup("MPT-1327 Decoder");
|
||||
|
||||
group.add(new FloatTap(INSTRUMENT_HB1_FILTER_TO_HIGH_PASS, 0, 0.5f));
|
||||
group.add(new FloatTap(INSTRUMENT_HIGH_PASS_TO_DECODER, 0, 0.5f));
|
||||
group.add(new BinaryTap(INSTRUMENT_DECODER_TO_FRAMER, 0, 0.025f));
|
||||
|
||||
mAvailableTaps.add(group);
|
||||
|
||||
/* Add the taps from the FSK decoder */
|
||||
mAvailableTaps.addAll(mFSKDecoder.getTapGroups());
|
||||
}
|
||||
|
||||
return mAvailableTaps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerTap(Tap tap)
|
||||
{
|
||||
/* Send request to decoder */
|
||||
mFSKDecoder.registerTap(tap);
|
||||
|
||||
switch(tap.getName())
|
||||
{
|
||||
case INSTRUMENT_HB1_FILTER_TO_HIGH_PASS:
|
||||
FloatBufferTap hb1Tap = (FloatBufferTap) tap;
|
||||
mDecimationFilter.setListener(hb1Tap);
|
||||
hb1Tap.setListener(mHighPassFilter);
|
||||
break;
|
||||
case INSTRUMENT_HIGH_PASS_TO_DECODER:
|
||||
FloatBufferTap lowTap = (FloatBufferTap) tap;
|
||||
mHighPassFilter.setListener(lowTap);
|
||||
lowTap.setListener(mFSKDecoder);
|
||||
break;
|
||||
case INSTRUMENT_DECODER_TO_FRAMER:
|
||||
BinaryTap decoderTap = (BinaryTap) tap;
|
||||
mFSKDecoder.setListener(decoderTap);
|
||||
decoderTap.setListener(mSymbolBroadcaster);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterTap(Tap tap)
|
||||
{
|
||||
mFSKDecoder.unregisterTap(tap);
|
||||
|
||||
switch(tap.getName())
|
||||
{
|
||||
case INSTRUMENT_HB1_FILTER_TO_HIGH_PASS:
|
||||
mDecimationFilter.setListener(mHighPassFilter);
|
||||
break;
|
||||
case INSTRUMENT_HIGH_PASS_TO_DECODER:
|
||||
mHighPassFilter.setListener(mFSKDecoder);
|
||||
break;
|
||||
case INSTRUMENT_DECODER_TO_FRAMER:
|
||||
mFSKDecoder.setListener(mSymbolBroadcaster);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
package io.github.dsheirer.module.decode.p25;
|
||||
|
||||
import io.github.dsheirer.dsp.gain.DirectGainControl;
|
||||
import io.github.dsheirer.instrument.Instrumentable;
|
||||
import io.github.dsheirer.instrument.tap.Tap;
|
||||
import io.github.dsheirer.instrument.tap.TapGroup;
|
||||
import io.github.dsheirer.instrument.tap.stream.AdditiveFloatTap;
|
||||
import io.github.dsheirer.instrument.tap.stream.FloatTap;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.real.RealBuffer;
|
||||
import io.github.dsheirer.sample.real.RealSampleListener;
|
||||
@@ -13,10 +8,7 @@ import io.github.dsheirer.sample.real.RealSampleProvider;
|
||||
import io.github.dsheirer.source.ISourceEventListener;
|
||||
import io.github.dsheirer.source.SourceEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class C4FMSymbolFilter implements Listener<RealBuffer>, ISourceEventListener, RealSampleProvider, Instrumentable
|
||||
public class C4FMSymbolFilter implements Listener<RealBuffer>, ISourceEventListener, RealSampleProvider
|
||||
{
|
||||
private static final float TAPS[][] =
|
||||
{
|
||||
@@ -151,11 +143,6 @@ public class C4FMSymbolFilter implements Listener<RealBuffer>, ISourceEventListe
|
||||
{0.00000e+00f, 0.00000e+00f, 0.00000e+00f, 1.00000e+00f, 0.00000e+00f, 0.00000e+00f, 0.00000e+00f, 0.00000e+00f}, // 128/128
|
||||
};
|
||||
|
||||
/* Instrumentation Taps */
|
||||
private static final String INSTRUMENT_SYMBOL_SPREAD = "Tap Point: Symbol Spread (Goal=2.0)";
|
||||
private FloatTap mSymbolSpreadTap;
|
||||
private List<TapGroup> mAvailableTaps;
|
||||
|
||||
private static final int NUMBER_FILTER_TAPS = 8;
|
||||
private static final int NUMBER_FILTER_STEPS = 128;
|
||||
|
||||
@@ -379,11 +366,6 @@ public class C4FMSymbolFilter implements Listener<RealBuffer>, ISourceEventListe
|
||||
500 * (mCoarseFrequencyCorrection > 0 ? 1 : -1);
|
||||
}
|
||||
|
||||
if(mSymbolSpreadTap != null)
|
||||
{
|
||||
mSymbolSpreadTap.receive(mSymbolSpread);
|
||||
}
|
||||
|
||||
/* dispatch the interpolated value to the listener */
|
||||
if(mListener != null)
|
||||
{
|
||||
@@ -404,46 +386,6 @@ public class C4FMSymbolFilter implements Listener<RealBuffer>, ISourceEventListe
|
||||
mListener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TapGroup> getTapGroups()
|
||||
{
|
||||
if(mAvailableTaps == null)
|
||||
{
|
||||
mAvailableTaps = new ArrayList<>();
|
||||
|
||||
/*
|
||||
* Since the target is 2.0, we subtract 2.0 from the value so that
|
||||
* a good value is plotted right on the zero center line
|
||||
*/
|
||||
TapGroup group = new TapGroup("C4FM Symbol Filter");
|
||||
|
||||
group.add(
|
||||
new AdditiveFloatTap(INSTRUMENT_SYMBOL_SPREAD, 0, 0.1f, -2.0f));
|
||||
|
||||
mAvailableTaps.add(group);
|
||||
}
|
||||
|
||||
return mAvailableTaps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerTap(Tap tap)
|
||||
{
|
||||
if(tap.getName().contentEquals(INSTRUMENT_SYMBOL_SPREAD))
|
||||
{
|
||||
mSymbolSpreadTap = (FloatTap)tap;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterTap(Tap tap)
|
||||
{
|
||||
if(tap.getName().contentEquals(INSTRUMENT_SYMBOL_SPREAD))
|
||||
{
|
||||
mSymbolSpreadTap = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts a frequency change event to the registered listener
|
||||
*
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
package io.github.dsheirer.module.decode.tait;
|
||||
|
||||
import io.github.dsheirer.dsp.afsk.AFSK1200DecoderInstrumented;
|
||||
import io.github.dsheirer.instrument.gui.viewer.chart.IInstrumentedAFSK1200Decoder;
|
||||
import io.github.dsheirer.instrument.chart.IInstrumentedAFSK1200Decoder;
|
||||
import io.github.dsheirer.sample.buffer.ReusableBuffer;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user