mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-13 00:57:31 -05:00
Initial code check in continued
This commit is contained in:
53
src/instrument/Instrumentable.java
Normal file
53
src/instrument/Instrumentable.java
Normal file
@@ -0,0 +1,53 @@
|
||||
/*******************************************************************************
|
||||
* 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 instrument;
|
||||
|
||||
import instrument.tap.Tap;
|
||||
|
||||
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 points. 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<Tap> getTaps();
|
||||
|
||||
/**
|
||||
* Registers a tap on the instrumentable object.
|
||||
*
|
||||
* @param tap - one of the tap(s) obtained from getTaps() from the
|
||||
* instrumentable source
|
||||
*/
|
||||
public void addTap( 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 removeTap( Tap tap );
|
||||
}
|
||||
152
src/instrument/gui/BinaryTapViewPanel.java
Normal file
152
src/instrument/gui/BinaryTapViewPanel.java
Normal file
@@ -0,0 +1,152 @@
|
||||
/*******************************************************************************
|
||||
* 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 instrument.gui;
|
||||
|
||||
import instrument.tap.Tap;
|
||||
import instrument.tap.stream.BinaryTap;
|
||||
|
||||
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 Tap mTap;
|
||||
private List<Boolean> mSamples;
|
||||
private int mSampleCount;
|
||||
private int mOffset = 0;
|
||||
|
||||
public BinaryTapViewPanel( BinaryTap tap )
|
||||
{
|
||||
super( new SampleModel<Boolean>(), tap.getName() );
|
||||
|
||||
mTap = tap;
|
||||
mTap.addListener( getModel() );
|
||||
|
||||
getModel().setSampleCount(
|
||||
(int)( getModel().getSampleCount() * tap.getSampleRateRatio() ) );
|
||||
}
|
||||
|
||||
@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
|
||||
* @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 ) );
|
||||
}
|
||||
}
|
||||
232
src/instrument/gui/DecoderViewFrame.java
Normal file
232
src/instrument/gui/DecoderViewFrame.java
Normal file
@@ -0,0 +1,232 @@
|
||||
/*******************************************************************************
|
||||
* 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 instrument.gui;
|
||||
|
||||
import instrument.Instrumentable;
|
||||
import instrument.tap.Tap;
|
||||
import instrument.tap.stream.BinaryTap;
|
||||
import instrument.tap.stream.FloatTap;
|
||||
import instrument.tap.stream.SymbolEventTap;
|
||||
|
||||
import java.awt.Dimension;
|
||||
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 javax.swing.JCheckBoxMenuItem;
|
||||
import javax.swing.JInternalFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JSeparator;
|
||||
|
||||
import log.Log;
|
||||
import message.Message;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import sample.Listener;
|
||||
import source.Source.SampleType;
|
||||
import source.wave.FloatWaveSource;
|
||||
import source.wave.WaveSource;
|
||||
import source.wave.WaveSource.PositionListener;
|
||||
import decode.Decoder;
|
||||
|
||||
public class DecoderViewFrame extends JInternalFrame
|
||||
implements PositionListener, Listener<Message>
|
||||
{
|
||||
private Decoder mDecoder;
|
||||
private WaveSource mWaveSource;
|
||||
|
||||
private HashMap<Tap,TapViewPanel> mPanelMap =
|
||||
new HashMap<Tap,TapViewPanel>();
|
||||
|
||||
public DecoderViewFrame( Decoder decoder, WaveSource source )
|
||||
{
|
||||
mDecoder = decoder;
|
||||
mWaveSource = source;
|
||||
|
||||
if( source.getSampleType() == SampleType.COMPLEX )
|
||||
{
|
||||
Log.error( "Hey, we're not wired up yet for complex" );
|
||||
}
|
||||
else if( source.getSampleType() == SampleType.FLOAT )
|
||||
{
|
||||
FloatWaveSource fws = (FloatWaveSource)mWaveSource;
|
||||
fws.setListener( mDecoder.getFloatReceiver() );
|
||||
}
|
||||
|
||||
mDecoder.addMessageListener( this );
|
||||
|
||||
initGui();
|
||||
}
|
||||
|
||||
private void initGui()
|
||||
{
|
||||
setLayout( new MigLayout( "insets 0 0 0 0 ", "[grow,fill]", "[grow,fill]" ) );
|
||||
|
||||
setTitle( "Decoder [" + mDecoder.getType().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();
|
||||
|
||||
if( mDecoder instanceof Instrumentable )
|
||||
{
|
||||
JMenu tapMenu = new JMenu( "Taps" );
|
||||
popup.add( tapMenu );
|
||||
|
||||
Instrumentable i = (Instrumentable)mDecoder;
|
||||
|
||||
for( Tap tap: i.getTaps() )
|
||||
{
|
||||
tapMenu.add( new TapSelectionItem( tap ) );
|
||||
}
|
||||
}
|
||||
|
||||
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 ) {}
|
||||
|
||||
} );
|
||||
}
|
||||
|
||||
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:
|
||||
break;
|
||||
case STREAM_FLOAT:
|
||||
panel = new FloatTapViewPanel( (FloatTap)tap );
|
||||
break;
|
||||
case STREAM_SYMBOL:
|
||||
panel = new SymbolEventTapViewPanel( (SymbolEventTap)tap );
|
||||
break;
|
||||
}
|
||||
|
||||
add( panel, "span" );
|
||||
|
||||
validate();
|
||||
|
||||
mPanelMap.put( tap, panel );
|
||||
|
||||
((Instrumentable)mDecoder).addTap( tap );
|
||||
}
|
||||
|
||||
public void remove( Tap tap )
|
||||
{
|
||||
((Instrumentable)mDecoder).removeTap( tap );
|
||||
|
||||
TapViewPanel panel = mPanelMap.get( tap );
|
||||
|
||||
remove( panel );
|
||||
|
||||
validate();
|
||||
|
||||
mPanelMap.remove( tap );
|
||||
}
|
||||
|
||||
public class TapSelectionItem extends JCheckBoxMenuItem
|
||||
{
|
||||
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 positionUpdated( long position, boolean reset )
|
||||
{
|
||||
if( reset )
|
||||
{
|
||||
for( TapViewPanel panel: mPanelMap.values() )
|
||||
{
|
||||
panel.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( Message message )
|
||||
{
|
||||
Log.info( "Decoder message: " + message.toString() );
|
||||
}
|
||||
}
|
||||
119
src/instrument/gui/FloatTapViewPanel.java
Normal file
119
src/instrument/gui/FloatTapViewPanel.java
Normal file
@@ -0,0 +1,119 @@
|
||||
/*******************************************************************************
|
||||
* 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 instrument.gui;
|
||||
|
||||
import instrument.tap.Tap;
|
||||
import instrument.tap.stream.FloatTap;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.util.List;
|
||||
import java.util.Observable;
|
||||
|
||||
public class FloatTapViewPanel extends TapViewPanel
|
||||
{
|
||||
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() );
|
||||
|
||||
getModel().setSampleCount(
|
||||
(int)( getModel().getSampleCount() * tap.getSampleRateRatio() ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update( Observable arg0, Object arg1 )
|
||||
{
|
||||
mSamples = (List<Float>)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 );
|
||||
|
||||
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 scaledValue = value / (float)Short.MAX_VALUE;
|
||||
|
||||
float y = middle - ( 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 );
|
||||
}
|
||||
}
|
||||
78
src/instrument/gui/SampleModel.java
Normal file
78
src/instrument/gui/SampleModel.java
Normal file
@@ -0,0 +1,78 @@
|
||||
/*******************************************************************************
|
||||
* 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 instrument.gui;
|
||||
|
||||
import instrument.tap.TapListener;
|
||||
|
||||
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 int mSampleCount = 2000;
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( T t )
|
||||
{
|
||||
mSamples.add( t );
|
||||
|
||||
while( mSamples.size() > mSampleCount )
|
||||
{
|
||||
mSamples.remove( 0 );
|
||||
}
|
||||
|
||||
changed();
|
||||
}
|
||||
|
||||
private void changed()
|
||||
{
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
}
|
||||
}
|
||||
186
src/instrument/gui/SymbolEventTapViewPanel.java
Normal file
186
src/instrument/gui/SymbolEventTapViewPanel.java
Normal file
@@ -0,0 +1,186 @@
|
||||
/*******************************************************************************
|
||||
* 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 instrument.gui;
|
||||
|
||||
import instrument.tap.stream.SymbolEventTap;
|
||||
|
||||
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;
|
||||
|
||||
import dsp.fsk.SymbolEvent;
|
||||
|
||||
public class SymbolEventTapViewPanel extends TapViewPanel
|
||||
{
|
||||
private SymbolEventTap mTap;
|
||||
private List<SymbolEvent> mSamples;
|
||||
private int mSampleCount;
|
||||
private int mOffset = 0;
|
||||
|
||||
public SymbolEventTapViewPanel( SymbolEventTap tap )
|
||||
{
|
||||
super( new SampleModel<SymbolEvent>(), tap.getName() );
|
||||
|
||||
mTap = tap;
|
||||
mTap.addListener( getModel() );
|
||||
|
||||
getModel().setSampleCount(
|
||||
(int)( getModel().getSampleCount() * tap.getSampleRateRatio() ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update( Observable arg0, Object arg1 )
|
||||
{
|
||||
mSamples = (List<SymbolEvent>)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++ )
|
||||
{
|
||||
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 ) ) ) );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
129
src/instrument/gui/TapViewPanel.java
Normal file
129
src/instrument/gui/TapViewPanel.java
Normal file
@@ -0,0 +1,129 @@
|
||||
/*******************************************************************************
|
||||
* 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 instrument.gui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Observer;
|
||||
|
||||
import javax.swing.JCheckBoxMenuItem;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
public abstract class TapViewPanel extends JPanel implements Observer
|
||||
{
|
||||
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 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 );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
234
src/instrument/gui/Viewer.java
Normal file
234
src/instrument/gui/Viewer.java
Normal file
@@ -0,0 +1,234 @@
|
||||
/*******************************************************************************
|
||||
* 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 instrument.gui;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.JDesktopPane;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
|
||||
import log.Log;
|
||||
import source.Source;
|
||||
import source.wave.ComplexWaveSource;
|
||||
import source.wave.FloatWaveSource;
|
||||
import source.wave.WaveSource;
|
||||
|
||||
public class Viewer
|
||||
{
|
||||
private JFrame mFrame;
|
||||
private JDesktopPane mDesktop;
|
||||
|
||||
private Source mSource;
|
||||
|
||||
public Viewer()
|
||||
{
|
||||
initGUI();
|
||||
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
mFrame.setVisible( true );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 );
|
||||
|
||||
// JInternalFrame frame =
|
||||
// new JInternalFrame( "New", true, true, true, true );
|
||||
// frame.add( new JLabel( "This is a test" ) );
|
||||
// frame.pack();
|
||||
// mDesktop.add( frame );
|
||||
// frame.setVisible( true );
|
||||
|
||||
/* 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 );
|
||||
|
||||
// JMenuItem windowItem = new JMenuItem( "New Window" );
|
||||
// windowItem.addActionListener( new ActionListener()
|
||||
// {
|
||||
// @Override
|
||||
// public void actionPerformed( ActionEvent arg0 )
|
||||
// {
|
||||
// JInternalFrame frame =
|
||||
// new JInternalFrame( "New", true, true, true, true );
|
||||
//
|
||||
// frame.add( new JLabel( "This is a test" ) );
|
||||
// frame.pack();
|
||||
//
|
||||
// mDesktop.add( frame );
|
||||
//
|
||||
// frame.setVisible( true );
|
||||
// }
|
||||
// } );
|
||||
// menuBar.add( windowItem );
|
||||
}
|
||||
|
||||
private void setSourceFile( File file )
|
||||
{
|
||||
Log.info( "File selected [" + file.getAbsolutePath() + "]");
|
||||
|
||||
WaveSource source = null;
|
||||
|
||||
/* Attempt to open file as a 1-channel float source */
|
||||
try
|
||||
{
|
||||
FloatWaveSource floatSource = new FloatWaveSource( file, false );
|
||||
floatSource.open();
|
||||
|
||||
source = floatSource;
|
||||
|
||||
Log.info( "File opened as float wave file" );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
Log.error( "Couldn't open file as float source - " +
|
||||
e.getLocalizedMessage() );
|
||||
}
|
||||
|
||||
if( source == null )
|
||||
{
|
||||
/* Attempt to open file as a 2-channel complex source */
|
||||
try
|
||||
{
|
||||
ComplexWaveSource complex = new ComplexWaveSource( file, false );
|
||||
complex.open();
|
||||
|
||||
source = complex;
|
||||
|
||||
Log.info( "File opened as complex wave file" );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
Log.error( "Couldn't open file as float source - " +
|
||||
e.getLocalizedMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
if( source != null )
|
||||
{
|
||||
mSource = source;
|
||||
|
||||
WaveSourceFrame sourcePanel =
|
||||
new WaveSourceFrame( source, mDesktop );
|
||||
sourcePanel.setVisible( true );
|
||||
mDesktop.add( sourcePanel );
|
||||
}
|
||||
}
|
||||
|
||||
public static void main( String[] args )
|
||||
{
|
||||
final Viewer viewer = new Viewer();
|
||||
}
|
||||
|
||||
public class SourceFileItem extends JMenuItem
|
||||
{
|
||||
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 );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
242
src/instrument/gui/WaveSourceFrame.java
Normal file
242
src/instrument/gui/WaveSourceFrame.java
Normal file
@@ -0,0 +1,242 @@
|
||||
/*******************************************************************************
|
||||
* 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 instrument.gui;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JDesktopPane;
|
||||
import javax.swing.JInternalFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
import log.Log;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import source.Source.SampleType;
|
||||
import source.wave.WaveSource;
|
||||
import source.wave.WaveSource.PositionListener;
|
||||
import decode.Decoder;
|
||||
import decode.DecoderType;
|
||||
import decode.fleetsync2.Fleetsync2Decoder;
|
||||
import decode.mdc1200.MDCDecoder;
|
||||
import decode.mpt1327.MPT1327Decoder;
|
||||
|
||||
public class WaveSourceFrame extends JInternalFrame implements PositionListener
|
||||
{
|
||||
private WaveSource mSource;
|
||||
private JDesktopPane mDesktop;
|
||||
|
||||
private JLabel mCurrentPosition = new JLabel( "0" );
|
||||
private JComboBox<DecoderType> mComboDecoders;
|
||||
|
||||
public WaveSourceFrame( WaveSource source, JDesktopPane desktop )
|
||||
{
|
||||
mSource = source;
|
||||
mSource.addListener( this );
|
||||
|
||||
mDesktop = desktop;
|
||||
|
||||
initGui();
|
||||
}
|
||||
|
||||
private void initGui()
|
||||
{
|
||||
setTitle( "Wave Source [" + mSource.getSampleType().toString() + "]" );
|
||||
setPreferredSize( new Dimension( 600, 150 ) );
|
||||
setSize( 600, 150 );
|
||||
|
||||
setResizable( true );
|
||||
setClosable( true );
|
||||
setIconifiable( true );
|
||||
setMaximizable( false );
|
||||
|
||||
JPanel panel = new JPanel();
|
||||
panel.setLayout( new MigLayout() );
|
||||
|
||||
JLabel fileLabel = new JLabel( "File: " + mSource.getFile().getName() );
|
||||
fileLabel.setToolTipText( mSource.getFile().getName() );
|
||||
panel.add( fileLabel, "span,wrap" );
|
||||
|
||||
panel.add( new JLabel( "Jump:" ) );
|
||||
panel.add( new JumpToField( mSource ) );
|
||||
panel.add( new NextSampleButton( mSource, ">", 1 ) );
|
||||
panel.add( new NextSampleButton( mSource, "> 100 >", 100 ) );
|
||||
panel.add( new NextSampleButton( mSource, "> 1000 >", 1000 ) );
|
||||
panel.add( new JLabel( "Posn:" ) );
|
||||
panel.add( mCurrentPosition, "wrap" );
|
||||
|
||||
/* ComboBox: Decoders */
|
||||
mComboDecoders = new JComboBox<DecoderType>();
|
||||
|
||||
DefaultComboBoxModel<DecoderType> model =
|
||||
new DefaultComboBoxModel<DecoderType>();
|
||||
|
||||
for( DecoderType type: DecoderType.getInstrumentableDecoders() )
|
||||
{
|
||||
model.addElement( type );
|
||||
}
|
||||
|
||||
mComboDecoders.setModel( model );
|
||||
|
||||
panel.add( new JLabel( "Decoders:" ) );
|
||||
panel.add( mComboDecoders, "span 3,grow" );
|
||||
panel.add( new AddDecoderButton(), "grow" );
|
||||
|
||||
add( panel );
|
||||
}
|
||||
|
||||
public class AddDecoderButton extends JButton
|
||||
{
|
||||
public AddDecoderButton()
|
||||
{
|
||||
super( "Add" );
|
||||
|
||||
addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
DecoderType selected =
|
||||
(DecoderType)mComboDecoders.getSelectedItem();
|
||||
|
||||
Log.info( "Selected:" + selected.getDisplayString() );
|
||||
|
||||
Decoder decoder = null;
|
||||
|
||||
switch( selected )
|
||||
{
|
||||
case FLEETSYNC2:
|
||||
decoder = new Fleetsync2Decoder( null );
|
||||
break;
|
||||
case MDC1200:
|
||||
decoder = new MDCDecoder( null );
|
||||
break;
|
||||
case MPT1327:
|
||||
decoder = new MPT1327Decoder( SampleType.FLOAT, null );
|
||||
break;
|
||||
}
|
||||
|
||||
if( decoder != null )
|
||||
{
|
||||
DecoderViewFrame decoderFrame =
|
||||
new DecoderViewFrame( decoder, mSource );
|
||||
|
||||
decoderFrame.setVisible( true );
|
||||
mDesktop.add( decoderFrame );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
public class NextSampleButton extends JButton
|
||||
{
|
||||
private WaveSource mSource;
|
||||
private int mCount;
|
||||
|
||||
public NextSampleButton( WaveSource source, String label, int count )
|
||||
{
|
||||
super( label );
|
||||
mSource = source;
|
||||
mCount = count;
|
||||
|
||||
addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
try
|
||||
{
|
||||
mSource.next( mCount );
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
Log.error( "Viewer - error trying to fetch next [" +
|
||||
mCount + "] samples - " + e.getLocalizedMessage() );
|
||||
|
||||
JOptionPane.showMessageDialog( WaveSourceFrame.this,
|
||||
"Cannot read " + mCount + " more samples [" +
|
||||
e.getLocalizedMessage() + "]",
|
||||
"Wave File Error",
|
||||
JOptionPane.ERROR_MESSAGE );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
public class JumpToField extends JTextField
|
||||
{
|
||||
private WaveSource mSource;
|
||||
|
||||
public JumpToField( WaveSource 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
|
||||
{
|
||||
long position = Long.parseLong( getText() );
|
||||
mSource.jumpTo( position );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
Log.error( "WaveSourceFrame - exception during jump "
|
||||
+ "to - " + e.getLocalizedMessage() );
|
||||
|
||||
JOptionPane.showMessageDialog( WaveSourceFrame.this,
|
||||
"Can't jump to position [" + getText() + "]",
|
||||
"Error",
|
||||
JOptionPane.ERROR_MESSAGE );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void positionUpdated( long position, boolean reset )
|
||||
{
|
||||
mCurrentPosition.setText( String.valueOf( position ) );
|
||||
|
||||
if( reset )
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
96
src/instrument/tap/Tap.java
Normal file
96
src/instrument/tap/Tap.java
Normal file
@@ -0,0 +1,96 @@
|
||||
/*******************************************************************************
|
||||
* 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 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();
|
||||
}
|
||||
}
|
||||
23
src/instrument/tap/TapListener.java
Normal file
23
src/instrument/tap/TapListener.java
Normal file
@@ -0,0 +1,23 @@
|
||||
/*******************************************************************************
|
||||
* 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 instrument.tap;
|
||||
|
||||
public interface TapListener<T>
|
||||
{
|
||||
public void receive( T t );
|
||||
}
|
||||
27
src/instrument/tap/TapType.java
Normal file
27
src/instrument/tap/TapType.java
Normal file
@@ -0,0 +1,27 @@
|
||||
/*******************************************************************************
|
||||
* 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 instrument.tap;
|
||||
|
||||
public enum TapType
|
||||
{
|
||||
EVENT_SYNC_DETECT,
|
||||
STREAM_BINARY,
|
||||
STREAM_COMPLEX,
|
||||
STREAM_FLOAT,
|
||||
STREAM_SYMBOL;
|
||||
}
|
||||
60
src/instrument/tap/event/SyncDetectTap.java
Normal file
60
src/instrument/tap/event/SyncDetectTap.java
Normal file
@@ -0,0 +1,60 @@
|
||||
/*******************************************************************************
|
||||
* 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 instrument.tap.event;
|
||||
|
||||
import instrument.tap.Tap;
|
||||
import instrument.tap.TapListener;
|
||||
import instrument.tap.TapType;
|
||||
import dsp.SyncDetectListener;
|
||||
import dsp.SyncDetectProvider;
|
||||
|
||||
public class SyncDetectTap extends Tap
|
||||
implements SyncDetectListener,
|
||||
SyncDetectProvider
|
||||
{
|
||||
private SyncDetectListener 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( SyncDetectListener listener )
|
||||
{
|
||||
mListener = listener;
|
||||
}
|
||||
}
|
||||
59
src/instrument/tap/stream/BinaryTap.java
Normal file
59
src/instrument/tap/stream/BinaryTap.java
Normal file
@@ -0,0 +1,59 @@
|
||||
/*******************************************************************************
|
||||
* 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 instrument.tap.stream;
|
||||
|
||||
import instrument.tap.TapListener;
|
||||
import instrument.tap.TapType;
|
||||
import 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;
|
||||
}
|
||||
}
|
||||
60
src/instrument/tap/stream/ComplexTap.java
Normal file
60
src/instrument/tap/stream/ComplexTap.java
Normal file
@@ -0,0 +1,60 @@
|
||||
/*******************************************************************************
|
||||
* 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 instrument.tap.stream;
|
||||
|
||||
import instrument.tap.TapListener;
|
||||
import instrument.tap.TapType;
|
||||
import sample.Listener;
|
||||
import sample.complex.ComplexSample;
|
||||
|
||||
public class ComplexTap extends StreamTap
|
||||
implements Listener<ComplexSample>
|
||||
{
|
||||
private Listener<ComplexSample> mListener;
|
||||
|
||||
public ComplexTap( String name,
|
||||
int delay,
|
||||
float sampleRateRatio )
|
||||
{
|
||||
super( TapType.STREAM_COMPLEX, name, delay, sampleRateRatio );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( ComplexSample t )
|
||||
{
|
||||
if( mListener != null )
|
||||
{
|
||||
mListener.receive( t );
|
||||
}
|
||||
|
||||
for( TapListener listener: mListeners )
|
||||
{
|
||||
listener.receive( t );
|
||||
}
|
||||
}
|
||||
|
||||
public void setListener( Listener<ComplexSample> listener )
|
||||
{
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
public void removeListener( Listener<ComplexSample> listener )
|
||||
{
|
||||
mListener = null;
|
||||
}
|
||||
}
|
||||
58
src/instrument/tap/stream/FloatTap.java
Normal file
58
src/instrument/tap/stream/FloatTap.java
Normal file
@@ -0,0 +1,58 @@
|
||||
/*******************************************************************************
|
||||
* 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 instrument.tap.stream;
|
||||
|
||||
import instrument.tap.TapListener;
|
||||
import instrument.tap.TapType;
|
||||
import sample.Listener;
|
||||
|
||||
public class FloatTap extends StreamTap implements Listener<Float>
|
||||
{
|
||||
private Listener<Float> mListener;
|
||||
|
||||
public FloatTap( String name,
|
||||
int delay,
|
||||
float sampleRateRatio )
|
||||
{
|
||||
super( TapType.STREAM_FLOAT, name, delay, sampleRateRatio );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( Float sample )
|
||||
{
|
||||
if( mListener != null )
|
||||
{
|
||||
mListener.receive( sample );
|
||||
}
|
||||
|
||||
for( TapListener listener: mListeners )
|
||||
{
|
||||
listener.receive( sample );
|
||||
}
|
||||
}
|
||||
|
||||
public void setListener( Listener<Float> listener )
|
||||
{
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
public void removeListener( Listener<Float> listener )
|
||||
{
|
||||
mListener = null;
|
||||
}
|
||||
}
|
||||
41
src/instrument/tap/stream/StreamTap.java
Normal file
41
src/instrument/tap/stream/StreamTap.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*******************************************************************************
|
||||
* 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 instrument.tap.stream;
|
||||
|
||||
import instrument.tap.Tap;
|
||||
import 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;
|
||||
}
|
||||
}
|
||||
58
src/instrument/tap/stream/SymbolEventTap.java
Normal file
58
src/instrument/tap/stream/SymbolEventTap.java
Normal file
@@ -0,0 +1,58 @@
|
||||
/*******************************************************************************
|
||||
* 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 instrument.tap.stream;
|
||||
|
||||
import instrument.tap.TapListener;
|
||||
import instrument.tap.TapType;
|
||||
import sample.Listener;
|
||||
import dsp.fsk.SymbolEvent;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user