Initial code check in continued

This commit is contained in:
dennis.sheirer
2014-04-26 19:48:24 +00:00
parent 960a6f9952
commit 3dfedcf8d1
474 changed files with 76613 additions and 0 deletions

View 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 );
}

View 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 ) );
}
}

View 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() );
}
}

View 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 );
}
}

View 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();
}
}

View 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 ) ) ) );
}
}
}

View 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 );
}
} );
}
}
}

View 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 );
}
} );
}
}
} );
}
}
}

View 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 )
{
}
}
}

View 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();
}
}

View 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 );
}

View 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;
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}