mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
Merges #34 Major redesign of Tuner, Channel and Alias management.
Changes to model, view and controller components and updates all gui editors. Removes the configuration panel and tree and replaces with 3 new panels. Updates playlist.xml to a new playlist_v2.xml format.
This commit is contained in:
@@ -6,8 +6,8 @@ import sample.complex.ComplexBuffer;
|
||||
|
||||
public abstract class ComplexSource extends Source implements Provider<ComplexBuffer>
|
||||
{
|
||||
public ComplexSource( String name )
|
||||
public ComplexSource()
|
||||
{
|
||||
super( name, SampleType.COMPLEX );
|
||||
super( SampleType.COMPLEX );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
|
||||
import source.config.SourceConfiguration;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class EmptySourceEditor extends SourceEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public EmptySourceEditor( ResourceManager resourceManager,
|
||||
SourceConfiguration config )
|
||||
{
|
||||
super( resourceManager, config );
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
public void reset() {}
|
||||
|
||||
public void save() {}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
JLabel selectLabel = new JLabel( "Please select a source" );
|
||||
add( selectLabel );
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package source;
|
||||
|
||||
import sample.Provider;
|
||||
import sample.SampleType;
|
||||
|
||||
public abstract class FloatSource extends Source implements Provider<Float>
|
||||
{
|
||||
public FloatSource( String name )
|
||||
{
|
||||
super( name, SampleType.REAL );
|
||||
}
|
||||
}
|
||||
@@ -7,8 +7,8 @@ import sample.real.RealBuffer;
|
||||
|
||||
public abstract class RealSource extends Source implements Provider<RealBuffer>
|
||||
{
|
||||
public RealSource( String name )
|
||||
public RealSource()
|
||||
{
|
||||
super( name, SampleType.REAL );
|
||||
super( SampleType.REAL );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source;
|
||||
|
||||
import sample.SampleType;
|
||||
|
||||
public interface SampleProvider
|
||||
{
|
||||
/**
|
||||
* Real or Complex
|
||||
*/
|
||||
public abstract SampleType getSampleType();
|
||||
}
|
||||
@@ -17,27 +17,21 @@
|
||||
******************************************************************************/
|
||||
package source;
|
||||
|
||||
import module.Module;
|
||||
import sample.SampleType;
|
||||
|
||||
/**
|
||||
* Abstract class to define the minimum functionality of a sample data provider.
|
||||
*/
|
||||
public abstract class Source
|
||||
public abstract class Source extends Module
|
||||
{
|
||||
protected String mName;
|
||||
protected SampleType mSampleType;
|
||||
|
||||
public Source( String name, SampleType sampleType )
|
||||
public Source( SampleType sampleType )
|
||||
{
|
||||
mName = name;
|
||||
mSampleType = sampleType;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
public abstract int getSampleRate() throws SourceException;
|
||||
|
||||
public abstract long getFrequency() throws SourceException;
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source;
|
||||
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import source.config.SourceConfigFactory;
|
||||
import source.config.SourceConfiguration;
|
||||
import controller.channel.AbstractChannelEditor;
|
||||
import controller.channel.ChannelNode;
|
||||
|
||||
public class SourceComponentEditor extends AbstractChannelEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JComboBox<SourceType> mComboSources;
|
||||
private SourceEditor mEditor;
|
||||
|
||||
public SourceComponentEditor( ChannelNode channelNode )
|
||||
{
|
||||
super( channelNode );
|
||||
|
||||
setLayout( new MigLayout( "fill,wrap 2", "[right,grow][grow]", "[][][grow]" ) );
|
||||
|
||||
mComboSources = new JComboBox<SourceType>();
|
||||
mComboSources.setModel( new DefaultComboBoxModel<SourceType>( SourceType.values() ) );
|
||||
mComboSources.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
SourceType selected = mComboSources.getItemAt( mComboSources.getSelectedIndex() );
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
SourceConfiguration config;
|
||||
|
||||
if( selected == mChannelNode.getChannel()
|
||||
.getSourceConfiguration().getSourceType() )
|
||||
{
|
||||
config = mChannelNode.getChannel()
|
||||
.getSourceConfiguration();
|
||||
}
|
||||
else
|
||||
{
|
||||
config = SourceConfigFactory
|
||||
.getSourceConfiguration( selected );
|
||||
}
|
||||
|
||||
//Remove the existing one
|
||||
if( mEditor != null )
|
||||
{
|
||||
remove( mEditor );
|
||||
}
|
||||
|
||||
//Change to the new one
|
||||
mEditor = SourceEditorFactory.getPanel(
|
||||
mChannelNode.getModel().getResourceManager(), config );
|
||||
|
||||
//Add it to the jpanel
|
||||
add( mEditor, "span 2" );
|
||||
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
add( new JLabel( "Source:" ) );
|
||||
add( mComboSources, "wrap" );
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
public SourceEditor getSourceEditor()
|
||||
{
|
||||
return mEditor;
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
javax.swing.SwingUtilities.invokeLater(new Runnable()
|
||||
{
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
mComboSources.setSelectedItem(
|
||||
mChannelNode.getChannel()
|
||||
.getSourceConfiguration().getSourceType() );
|
||||
|
||||
mComboSources.requestFocus();
|
||||
|
||||
mComboSources.requestFocusInWindow();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
mEditor.save();
|
||||
|
||||
//Let the calling save method send the config change event
|
||||
mChannelNode.getChannel()
|
||||
.setSourceConfiguration( mEditor.getConfig(), false );
|
||||
}
|
||||
}
|
||||
137
src/source/SourceConfigurationEditor.java
Normal file
137
src/source/SourceConfigurationEditor.java
Normal file
@@ -0,0 +1,137 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 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 source;
|
||||
|
||||
import gui.editor.Editor;
|
||||
import gui.editor.EmptyEditor;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JComboBox;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import source.config.SourceConfiguration;
|
||||
import source.mixer.MixerSourceEditor;
|
||||
import source.tuner.TunerSourceEditor;
|
||||
import controller.channel.Channel;
|
||||
|
||||
public class SourceConfigurationEditor extends Editor<Channel>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JComboBox<SourceType> mComboSources;
|
||||
private MixerSourceEditor mMixerSourceEditor;
|
||||
private TunerSourceEditor mTunerSourceEditor;
|
||||
private Editor<Channel> mCurrentEditor;
|
||||
|
||||
public SourceConfigurationEditor( SourceManager sourceManager )
|
||||
{
|
||||
mMixerSourceEditor = new MixerSourceEditor( sourceManager );
|
||||
mMixerSourceEditor.setSaveRequestListener( this );
|
||||
|
||||
mTunerSourceEditor = new TunerSourceEditor();
|
||||
mTunerSourceEditor.setSaveRequestListener( this );
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
public SourceConfiguration getSourceConfiguration()
|
||||
{
|
||||
return hasItem() ? getItem().getSourceConfiguration() : null;
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "wrap 2", "[][grow,fill]", "[align top][grow]" ) );
|
||||
|
||||
mComboSources = new JComboBox<SourceType>();
|
||||
mComboSources.setModel( new DefaultComboBoxModel<SourceType>( SourceType.getTypes() ) );
|
||||
mComboSources.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
SourceType selected = (SourceType)mComboSources.getSelectedItem();
|
||||
|
||||
switch( selected )
|
||||
{
|
||||
case MIXER:
|
||||
setEditor( mMixerSourceEditor );
|
||||
break;
|
||||
case TUNER:
|
||||
setEditor( mTunerSourceEditor );
|
||||
break;
|
||||
default:
|
||||
setEditor( new EmptyEditor<Channel>() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
add( mComboSources );
|
||||
|
||||
mCurrentEditor = mTunerSourceEditor;
|
||||
add( mCurrentEditor );
|
||||
}
|
||||
|
||||
private void setEditor( Editor<Channel> editor )
|
||||
{
|
||||
if( mCurrentEditor != editor )
|
||||
{
|
||||
//Set channel to null to force a save prompt as required
|
||||
mCurrentEditor.setItem( null );
|
||||
|
||||
remove( mCurrentEditor );
|
||||
mCurrentEditor = editor;
|
||||
mCurrentEditor.setSaveRequestListener( this );
|
||||
add( mCurrentEditor );
|
||||
|
||||
mCurrentEditor.setItem( getItem() );
|
||||
|
||||
revalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
if( hasItem() )
|
||||
{
|
||||
mCurrentEditor.save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the channel configuration. Note: this method must be invoked from
|
||||
* the swing event dispatch thread.
|
||||
*/
|
||||
@Override
|
||||
public void setItem( Channel channel )
|
||||
{
|
||||
super.setItem( channel );
|
||||
|
||||
if( hasItem() )
|
||||
{
|
||||
mComboSources.setSelectedItem( getItem().getSourceConfiguration().getSourceType() );
|
||||
repaint();
|
||||
mCurrentEditor.setItem( channel );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source;
|
||||
|
||||
import source.config.SourceConfiguration;
|
||||
import controller.Editor;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public abstract class SourceEditor extends Editor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected ResourceManager mResourceManager;
|
||||
protected SourceConfiguration mConfig;
|
||||
|
||||
public SourceEditor( ResourceManager resourceManager, SourceConfiguration config )
|
||||
{
|
||||
mResourceManager = resourceManager;
|
||||
mConfig = config;
|
||||
}
|
||||
|
||||
public SourceConfiguration getConfig()
|
||||
{
|
||||
return mConfig;
|
||||
}
|
||||
|
||||
public ResourceManager getResourceManager()
|
||||
{
|
||||
return mResourceManager;
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source;
|
||||
|
||||
import source.config.SourceConfiguration;
|
||||
import source.mixer.MixerEditor;
|
||||
import source.recording.RecordingEditor;
|
||||
import source.tuner.TunerEditor;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class SourceEditorFactory
|
||||
{
|
||||
public static SourceEditor getPanel( ResourceManager resourceManager,
|
||||
SourceConfiguration config )
|
||||
{
|
||||
SourceEditor configuredPanel;
|
||||
|
||||
switch( config.getSourceType() )
|
||||
{
|
||||
case MIXER:
|
||||
configuredPanel = new MixerEditor( resourceManager, config );
|
||||
break;
|
||||
case TUNER:
|
||||
configuredPanel = new TunerEditor( resourceManager, config );
|
||||
break;
|
||||
case RECORDING:
|
||||
configuredPanel = new RecordingEditor( resourceManager, config );
|
||||
break;
|
||||
case NONE:
|
||||
default:
|
||||
configuredPanel = new EmptySourceEditor( resourceManager, config );
|
||||
break;
|
||||
}
|
||||
|
||||
return configuredPanel;
|
||||
}
|
||||
}
|
||||
@@ -17,27 +17,48 @@
|
||||
******************************************************************************/
|
||||
package source;
|
||||
|
||||
import settings.SettingsManager;
|
||||
import source.config.SourceConfigTuner;
|
||||
import source.config.SourceConfiguration;
|
||||
import source.mixer.MixerManager;
|
||||
import controller.ResourceManager;
|
||||
import source.recording.RecordingSourceManager;
|
||||
import source.tuner.TunerManager;
|
||||
import source.tuner.TunerModel;
|
||||
import controller.ThreadPoolManager;
|
||||
|
||||
public class SourceManager {
|
||||
/**
|
||||
* NOTE: each source will auto-start once a listener registers on it to
|
||||
* receive samples and should auto-stop once a listener de-registers
|
||||
*
|
||||
* Each channel object will handle the starting and stopping of each channel
|
||||
* processing chain.
|
||||
*
|
||||
* Source Manager will reach out to the MixerManager or the TunerManager
|
||||
* to get source objects to pass off to the channel object, as requested.
|
||||
*/
|
||||
|
||||
private ResourceManager mResourceManager;
|
||||
public class SourceManager
|
||||
{
|
||||
private MixerManager mMixerManager;
|
||||
private RecordingSourceManager mRecordingSourceManager;
|
||||
private TunerManager mTunerManager;
|
||||
private TunerModel mTunerModel;
|
||||
|
||||
public SourceManager( ResourceManager resourceManager )
|
||||
public SourceManager( TunerModel tunerModel,
|
||||
SettingsManager settingsManager,
|
||||
ThreadPoolManager threadPoolManager )
|
||||
{
|
||||
mResourceManager = resourceManager;
|
||||
mTunerModel = tunerModel;
|
||||
mMixerManager = new MixerManager();
|
||||
mRecordingSourceManager = new RecordingSourceManager( settingsManager );
|
||||
mTunerManager = new TunerManager( mMixerManager, tunerModel, threadPoolManager );
|
||||
|
||||
//TODO: change mixer & recording managers to be models and hand them
|
||||
//in via the constructor. Perform loading outside of this class.
|
||||
}
|
||||
|
||||
public MixerManager getMixerManager()
|
||||
{
|
||||
return mMixerManager;
|
||||
}
|
||||
|
||||
public RecordingSourceManager getRecordingSourceManager()
|
||||
{
|
||||
return mRecordingSourceManager;
|
||||
}
|
||||
|
||||
public TunerManager getTunerManager()
|
||||
{
|
||||
return mTunerManager;
|
||||
}
|
||||
|
||||
public Source getSource( SourceConfiguration config, int bandwidth )
|
||||
@@ -48,14 +69,13 @@ public class SourceManager {
|
||||
switch( config.getSourceType() )
|
||||
{
|
||||
case MIXER:
|
||||
retVal = MixerManager.getInstance().getSource( config );
|
||||
retVal = mMixerManager.getSource( config );
|
||||
break;
|
||||
case TUNER:
|
||||
retVal = mResourceManager.getTunerManager().getSource( config, bandwidth );
|
||||
retVal = mTunerModel.getSource( (SourceConfigTuner)config, bandwidth );
|
||||
break;
|
||||
case RECORDING:
|
||||
retVal = mResourceManager.getRecordingSourceManager()
|
||||
.getSource( config, bandwidth );
|
||||
retVal = mRecordingSourceManager.getSource( config, bandwidth );
|
||||
case NONE:
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
******************************************************************************/
|
||||
package source;
|
||||
|
||||
|
||||
public enum SourceType
|
||||
{
|
||||
NONE( "No Source" ),
|
||||
MIXER( "Mixer/Sound Card" ),
|
||||
MIXER( "Sound Card" ),
|
||||
TUNER( "Tuner" ),
|
||||
RECORDING( "IQ Recording" );
|
||||
|
||||
@@ -31,6 +32,15 @@ public enum SourceType
|
||||
mDisplayString = displayString;
|
||||
}
|
||||
|
||||
public static SourceType[] getTypes()
|
||||
{
|
||||
SourceType[] types = new SourceType[ 2 ];
|
||||
types[ 0 ] = SourceType.TUNER;
|
||||
types[ 1 ] = SourceType.MIXER;
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
public String getDisplayString()
|
||||
{
|
||||
return mDisplayString;
|
||||
|
||||
@@ -23,24 +23,20 @@ public class SourceConfigFactory
|
||||
{
|
||||
public static SourceConfiguration getDefaultSourceConfiguration()
|
||||
{
|
||||
return getSourceConfiguration( SourceType.NONE );
|
||||
return getSourceConfiguration( SourceType.TUNER );
|
||||
}
|
||||
|
||||
public static SourceConfiguration
|
||||
getSourceConfiguration( SourceType source )
|
||||
public static SourceConfiguration getSourceConfiguration( SourceType source )
|
||||
{
|
||||
SourceConfiguration retVal;
|
||||
|
||||
switch( source )
|
||||
{
|
||||
case MIXER:
|
||||
retVal = new SourceConfigMixer();
|
||||
break;
|
||||
case TUNER:
|
||||
retVal = new SourceConfigTuner();
|
||||
break;
|
||||
case RECORDING:
|
||||
retVal = new SourceConfigRecording();
|
||||
case MIXER:
|
||||
retVal = new SourceConfigMixer();
|
||||
break;
|
||||
case NONE:
|
||||
default:
|
||||
@@ -50,4 +46,39 @@ public class SourceConfigFactory
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of the configuration
|
||||
*/
|
||||
public static SourceConfiguration copy( SourceConfiguration config )
|
||||
{
|
||||
if( config != null )
|
||||
{
|
||||
switch( config.getSourceType() )
|
||||
{
|
||||
case MIXER:
|
||||
SourceConfigMixer originalMixer = (SourceConfigMixer)config;
|
||||
SourceConfigMixer copyMixer = new SourceConfigMixer();
|
||||
copyMixer.setChannel( originalMixer.getChannel() );
|
||||
copyMixer.setMixer( originalMixer.getMixer() );
|
||||
return copyMixer;
|
||||
case RECORDING:
|
||||
SourceConfigRecording originalRec = (SourceConfigRecording)config;
|
||||
SourceConfigRecording copyRec = new SourceConfigRecording();
|
||||
copyRec.setFrequency( originalRec.getFrequency() );
|
||||
copyRec.setRecordingAlias( originalRec.getRecordingAlias() );
|
||||
return copyRec;
|
||||
case TUNER:
|
||||
SourceConfigTuner originalTuner = (SourceConfigTuner)config;
|
||||
SourceConfigTuner copyTuner = new SourceConfigTuner();
|
||||
copyTuner.setFrequency( originalTuner.getFrequency() );
|
||||
return copyTuner;
|
||||
case NONE:
|
||||
default:
|
||||
return new SourceConfigNone();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ public class SourceConfigMixer extends SourceConfiguration
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "Mixer: " );
|
||||
sb.append( mMixer );
|
||||
sb.append( "-" );
|
||||
sb.append( mChannel.toString() );
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
* Copyright (C) 2014-2016 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
|
||||
@@ -30,7 +30,7 @@ public class SourceConfigTuner extends SourceConfiguration
|
||||
private static DecimalFormat sFORMAT = new DecimalFormat( "0.00000" );
|
||||
|
||||
private long mFrequency = 0;
|
||||
private int mBandwidth = 15000;
|
||||
private int mBandwidth = 12500;
|
||||
|
||||
public SourceConfigTuner()
|
||||
{
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.mixer;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
import javax.sound.sampled.Mixer;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
import source.SourceEditor;
|
||||
import source.config.SourceConfigMixer;
|
||||
import source.config.SourceConfiguration;
|
||||
import source.mixer.MixerManager.InputMixerConfiguration;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class MixerEditor extends SourceEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private JComboBox<InputMixerConfiguration> mComboMixers;
|
||||
private JComboBox<MixerChannel>mComboChannels;
|
||||
protected Mixer.Info mSelectedMixer = null;
|
||||
|
||||
|
||||
public MixerEditor( ResourceManager resourceManager,
|
||||
SourceConfiguration config )
|
||||
{
|
||||
super( resourceManager, config );
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
JLabel mixerLabel = new JLabel( "Mixer:" );
|
||||
add( mixerLabel, "align right" );
|
||||
|
||||
mComboMixers = new JComboBox<InputMixerConfiguration>();
|
||||
|
||||
add( mComboMixers, "wrap" );
|
||||
|
||||
resetMixers();
|
||||
|
||||
JLabel channelLabel = new JLabel( "Channel:" );
|
||||
add( channelLabel, "align right" );
|
||||
|
||||
mComboChannels = new JComboBox<MixerChannel>();
|
||||
|
||||
add( mComboChannels, "wrap" );
|
||||
|
||||
resetChannels();
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
resetMixers();
|
||||
resetChannels();
|
||||
}
|
||||
|
||||
public void save()
|
||||
{
|
||||
SourceConfigMixer config = (SourceConfigMixer)mConfig;
|
||||
|
||||
InputMixerConfiguration selectedMixer =
|
||||
mComboMixers.getItemAt( mComboMixers.getSelectedIndex() );
|
||||
|
||||
if( selectedMixer != null )
|
||||
{
|
||||
config.setMixer( selectedMixer.getMixerName() );
|
||||
}
|
||||
|
||||
MixerChannel channel = mComboChannels.getItemAt(
|
||||
mComboChannels.getSelectedIndex() );
|
||||
|
||||
if( channel != null )
|
||||
{
|
||||
if( config.getChannel() != channel )
|
||||
{
|
||||
config.setChannel( channel );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resetMixers()
|
||||
{
|
||||
|
||||
javax.swing.SwingUtilities.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
InputMixerConfiguration[] mixers = MixerManager.getInstance().getInputMixers();
|
||||
|
||||
mComboMixers.setModel(
|
||||
new DefaultComboBoxModel<InputMixerConfiguration>( mixers ) );
|
||||
|
||||
SourceConfigMixer config = (SourceConfigMixer)mConfig;
|
||||
|
||||
String mixer = config.getMixer();
|
||||
|
||||
if( mixer != null )
|
||||
{
|
||||
mComboMixers.setSelectedItem( mixer );
|
||||
}
|
||||
else
|
||||
{
|
||||
//Mixer either hasn't been set yet, or it was set to a
|
||||
//mixer that is no longer available. Set the mixer to the
|
||||
//first item, and then store the value
|
||||
if( mixers.length > 0 )
|
||||
{
|
||||
mComboMixers.setSelectedIndex( 0 );
|
||||
|
||||
InputMixerConfiguration selectedMixer =
|
||||
(InputMixerConfiguration)mComboMixers.getSelectedItem();
|
||||
|
||||
config.setMixer( selectedMixer.getMixerName() );
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void resetChannels()
|
||||
{
|
||||
javax.swing.SwingUtilities.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
EnumSet<MixerChannel> channels = MixerChannel.getTargetChannels();
|
||||
|
||||
mComboChannels.setModel( new DefaultComboBoxModel<MixerChannel>(
|
||||
channels.toArray( new MixerChannel[ channels.size() ] ) ) );
|
||||
|
||||
MixerChannel channel = ((SourceConfigMixer)mConfig).getChannel();
|
||||
|
||||
mComboChannels.setSelectedItem( channel );
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package source.mixer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -49,27 +50,15 @@ public class MixerManager
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( MixerManager.class );
|
||||
|
||||
private static MixerManager sInstance = null;
|
||||
|
||||
private List<InputMixerConfiguration> mInputMixers = new ArrayList<>();
|
||||
private List<MixerChannelConfiguration> mOutputMixers = new ArrayList<>();
|
||||
private HashMap<String,MixerTunerDataLine> mMixerTuners = new HashMap<>();
|
||||
|
||||
private MixerManager()
|
||||
public MixerManager()
|
||||
{
|
||||
loadMixers();
|
||||
}
|
||||
|
||||
public static MixerManager getInstance()
|
||||
{
|
||||
if( sInstance == null )
|
||||
{
|
||||
sInstance = new MixerManager();
|
||||
}
|
||||
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public RealMixerSource getSource( SourceConfiguration config )
|
||||
{
|
||||
RealMixerSource retVal = null;
|
||||
@@ -108,7 +97,6 @@ public class MixerManager
|
||||
{
|
||||
return new RealMixerSource( dataLine,
|
||||
AudioFormats.PCM_SIGNED_48KHZ_16BITS_MONO,
|
||||
mixerName,
|
||||
new ShortAdapter() );
|
||||
}
|
||||
}
|
||||
@@ -137,7 +125,7 @@ public class MixerManager
|
||||
{
|
||||
return new RealMixerSource( dataLine,
|
||||
AudioFormats.PCM_SIGNED_48KHZ_16BITS_STEREO,
|
||||
mixerName, new ChannelShortAdapter(
|
||||
new ChannelShortAdapter(
|
||||
mixerConfig.getChannel() ) );
|
||||
}
|
||||
}
|
||||
@@ -181,7 +169,14 @@ public class MixerManager
|
||||
|
||||
public Collection<MixerTunerDataLine> getMixerTunerDataLines()
|
||||
{
|
||||
return mMixerTuners.values();
|
||||
if( mMixerTuners.isEmpty() )
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
else
|
||||
{
|
||||
return mMixerTuners.values();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadMixers()
|
||||
|
||||
177
src/source/mixer/MixerSourceEditor.java
Normal file
177
src/source/mixer/MixerSourceEditor.java
Normal file
@@ -0,0 +1,177 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 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 source.mixer;
|
||||
|
||||
import gui.editor.Editor;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import source.SourceManager;
|
||||
import source.config.SourceConfigMixer;
|
||||
import source.config.SourceConfiguration;
|
||||
import source.mixer.MixerManager.InputMixerConfiguration;
|
||||
import controller.channel.Channel;
|
||||
|
||||
public class MixerSourceEditor extends Editor<Channel>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private JComboBox<InputMixerConfiguration> mComboMixers;
|
||||
private JComboBox<MixerChannel>mComboChannels;
|
||||
|
||||
private SourceManager mSourceManager;
|
||||
|
||||
public MixerSourceEditor( SourceManager sourceManager )
|
||||
{
|
||||
mSourceManager = sourceManager;
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "insets 0 0 0 0,wrap 4", "[right][grow,fill][right][grow,fill]", "" ) );
|
||||
|
||||
mComboMixers = new JComboBox<InputMixerConfiguration>();
|
||||
InputMixerConfiguration[] inputMixers = mSourceManager.getMixerManager().getInputMixers();
|
||||
mComboMixers.setModel( new DefaultComboBoxModel<InputMixerConfiguration>( inputMixers ) );
|
||||
mComboMixers.setEnabled( false );
|
||||
mComboMixers.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
InputMixerConfiguration selected = (InputMixerConfiguration)mComboMixers.getSelectedItem();
|
||||
|
||||
EnumSet<MixerChannel> channels = selected.getChannels();
|
||||
|
||||
mComboChannels.setModel( new DefaultComboBoxModel<MixerChannel>(
|
||||
channels.toArray( new MixerChannel[ channels.size() ] ) ) );
|
||||
|
||||
repaint();
|
||||
|
||||
setModified( true );
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Mixer:" ) );
|
||||
add( mComboMixers );
|
||||
|
||||
mComboChannels = new JComboBox<MixerChannel>();
|
||||
|
||||
InputMixerConfiguration selected = (InputMixerConfiguration)mComboMixers.getSelectedItem();
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
EnumSet<MixerChannel> channels = selected.getChannels();
|
||||
|
||||
mComboChannels.setModel( new DefaultComboBoxModel<MixerChannel>(
|
||||
channels.toArray( new MixerChannel[ channels.size() ] ) ) );
|
||||
}
|
||||
|
||||
mComboChannels.setEnabled( false );
|
||||
mComboChannels.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
setModified( true );
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Channel:" ) );
|
||||
add( mComboChannels );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem( Channel item )
|
||||
{
|
||||
super.setItem( item );
|
||||
|
||||
if( hasItem() )
|
||||
{
|
||||
mComboMixers.setEnabled( true );
|
||||
mComboChannels.setEnabled( true );
|
||||
|
||||
SourceConfiguration config = item.getSourceConfiguration();
|
||||
|
||||
if( config instanceof SourceConfigMixer )
|
||||
{
|
||||
SourceConfigMixer mixer = (SourceConfigMixer)config;
|
||||
|
||||
for( InputMixerConfiguration inputMixer: mSourceManager.getMixerManager().getInputMixers() )
|
||||
{
|
||||
if( inputMixer.getMixerName().equalsIgnoreCase( mixer.getMixer() ) )
|
||||
{
|
||||
mComboMixers.setSelectedItem( inputMixer );
|
||||
|
||||
for( MixerChannel channel: inputMixer.getChannels() )
|
||||
{
|
||||
if( channel.getLabel() != null && mixer.getChannel() != null )
|
||||
{
|
||||
if( channel.getLabel().equalsIgnoreCase( mixer.getChannel().getLabel() ) )
|
||||
{
|
||||
mComboChannels.setSelectedItem( channel );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
setModified( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
setModified( true );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mComboMixers.setEnabled( false );
|
||||
mComboChannels.setEnabled( false );
|
||||
|
||||
setModified( false );
|
||||
}
|
||||
}
|
||||
|
||||
public void save()
|
||||
{
|
||||
if( hasItem() && isModified() )
|
||||
{
|
||||
SourceConfigMixer config = new SourceConfigMixer();
|
||||
|
||||
InputMixerConfiguration selected =
|
||||
(InputMixerConfiguration)mComboMixers.getSelectedItem();
|
||||
config.setMixer( selected.getMixerName() );
|
||||
|
||||
MixerChannel channel = (MixerChannel)mComboChannels.getSelectedItem();
|
||||
config.setChannel( channel );
|
||||
|
||||
getItem().setSourceConfiguration( config );
|
||||
}
|
||||
|
||||
setModified( false );
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package source.mixer;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
@@ -29,12 +30,12 @@ import javax.sound.sampled.TargetDataLine;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import dsp.gain.AutomaticGainControl;
|
||||
import sample.Listener;
|
||||
import sample.adapter.ISampleAdapter;
|
||||
import sample.real.RealBuffer;
|
||||
import source.RealSource;
|
||||
import source.SourceException;
|
||||
import dsp.gain.AutomaticGainControl;
|
||||
|
||||
public class RealMixerSource extends RealSource
|
||||
{
|
||||
@@ -72,18 +73,30 @@ public class RealMixerSource extends RealSource
|
||||
* the left/right stereo channels are inverted.
|
||||
*/
|
||||
public RealMixerSource( TargetDataLine targetDataLine,
|
||||
AudioFormat format,
|
||||
String name,
|
||||
ISampleAdapter sampleAdapter )
|
||||
AudioFormat format,
|
||||
ISampleAdapter sampleAdapter )
|
||||
{
|
||||
super( name );
|
||||
|
||||
mTargetDataLine = targetDataLine;
|
||||
mAudioFormat = format;
|
||||
mSampleAdapter = sampleAdapter;
|
||||
}
|
||||
|
||||
public void setListener( Listener<RealBuffer> listener )
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
}
|
||||
|
||||
public void setListener( Listener<RealBuffer> listener )
|
||||
{
|
||||
mSampleListeners.add( listener );
|
||||
|
||||
@@ -92,7 +105,7 @@ public class RealMixerSource extends RealSource
|
||||
{
|
||||
Thread thread = new Thread( mBufferReader );
|
||||
thread.setDaemon( true );
|
||||
thread.setName( getName() + " Sample Reader" );
|
||||
thread.setName( "Sample Reader" );
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,32 +4,34 @@ import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import settings.SettingsManager;
|
||||
import source.SourceException;
|
||||
import source.tuner.ITunerChannelProvider;
|
||||
import source.tuner.TunerChannel;
|
||||
import source.tuner.TunerChannelProvider;
|
||||
import source.tuner.TunerChannelSource;
|
||||
import source.tuner.frequency.FrequencyChangeEvent;
|
||||
import source.tuner.frequency.FrequencyChangeListener;
|
||||
import source.tuner.frequency.FrequencyChangeEvent.Event;
|
||||
import controller.ResourceManager;
|
||||
import controller.ThreadPoolManager;
|
||||
import source.tuner.frequency.IFrequencyChangeProcessor;
|
||||
|
||||
public class Recording implements Comparable<Recording>,
|
||||
FrequencyChangeListener,
|
||||
TunerChannelProvider
|
||||
IFrequencyChangeProcessor,
|
||||
ITunerChannelProvider
|
||||
{
|
||||
private ResourceManager mResourceManager;
|
||||
private RecordingConfiguration mConfiguration;
|
||||
|
||||
private ArrayList<TunerChannelSource> mTunerChannels =
|
||||
new ArrayList<TunerChannelSource>();
|
||||
|
||||
@SuppressWarnings( "unused" )
|
||||
private long mCenterFrequency;
|
||||
|
||||
public Recording( ResourceManager resourceManager,
|
||||
@SuppressWarnings( "unused" )
|
||||
private SettingsManager mSettingsManager;
|
||||
|
||||
public Recording( SettingsManager settingsManager,
|
||||
RecordingConfiguration configuration )
|
||||
{
|
||||
mResourceManager = resourceManager;
|
||||
mSettingsManager = settingsManager;
|
||||
mConfiguration = configuration;
|
||||
mCenterFrequency = mConfiguration.getCenterFrequency();
|
||||
}
|
||||
@@ -37,7 +39,7 @@ public class Recording implements Comparable<Recording>,
|
||||
public void setAlias( String alias )
|
||||
{
|
||||
mConfiguration.setAlias( alias );
|
||||
mResourceManager.getSettingsManager().save();
|
||||
// mSettingsManager.save();
|
||||
}
|
||||
|
||||
public void setRecordingFile( File file ) throws SourceException
|
||||
@@ -50,7 +52,7 @@ public class Recording implements Comparable<Recording>,
|
||||
}
|
||||
|
||||
mConfiguration.setFilePath( file.getAbsolutePath() );
|
||||
mResourceManager.getSettingsManager().save();
|
||||
// mSettingsManager.save();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,13 +91,13 @@ public class Recording implements Comparable<Recording>,
|
||||
@Override
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION )
|
||||
if( event.getEvent() == Event.NOTIFICATION_FREQUENCY_CHANGE )
|
||||
{
|
||||
long frequency = event.getValue().longValue();
|
||||
|
||||
mConfiguration.setCenterFrequency( frequency );
|
||||
|
||||
mResourceManager.getSettingsManager().save();
|
||||
// mSettingsManager.save();
|
||||
|
||||
mCenterFrequency = frequency;
|
||||
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.recording;
|
||||
|
||||
import gui.control.JFrequencyControl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import source.SourceEditor;
|
||||
import source.config.SourceConfigRecording;
|
||||
import source.config.SourceConfigTuner;
|
||||
import source.config.SourceConfiguration;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class RecordingEditor extends SourceEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private JComboBox<Recording> mComboRecordings;
|
||||
private JFrequencyControl mFrequencyControl;
|
||||
|
||||
public RecordingEditor( ResourceManager resourceManager,
|
||||
SourceConfiguration config )
|
||||
{
|
||||
super( resourceManager, config );
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
mFrequencyControl.setFrequency(
|
||||
((SourceConfigTuner)mConfig).getFrequency(), false );
|
||||
}
|
||||
|
||||
public void save()
|
||||
{
|
||||
SourceConfigRecording config = (SourceConfigRecording)mConfig;
|
||||
|
||||
Recording selected = (Recording)mComboRecordings.getSelectedItem();
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
config.setRecordingAlias( selected
|
||||
.getRecordingConfiguration().getAlias() );
|
||||
}
|
||||
|
||||
config.setFrequency( mFrequencyControl.getFrequency() );
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
add( new JLabel( "Recording" ) );
|
||||
|
||||
mComboRecordings = new JComboBox<Recording>();
|
||||
|
||||
add( mComboRecordings, "wrap" );
|
||||
|
||||
mFrequencyControl = new JFrequencyControl();
|
||||
|
||||
mFrequencyControl.setFrequency(
|
||||
((SourceConfigRecording)mConfig).getFrequency(), false );
|
||||
|
||||
add( mFrequencyControl, "span" );
|
||||
|
||||
resetRecordings();
|
||||
}
|
||||
|
||||
private void resetRecordings()
|
||||
{
|
||||
SwingUtilities.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
List<Recording> recordings = getResourceManager()
|
||||
.getRecordingSourceManager().getRecordings();
|
||||
|
||||
mComboRecordings.setModel(
|
||||
new DefaultComboBoxModel<Recording>(
|
||||
recordings.toArray( new Recording[ recordings.size()] ) ) );
|
||||
|
||||
SourceConfigRecording config = (SourceConfigRecording)mConfig;
|
||||
|
||||
String recordingAlias = config.getRecordingAlias();
|
||||
|
||||
if( recordingAlias != null )
|
||||
{
|
||||
Recording selected = mResourceManager
|
||||
.getRecordingSourceManager()
|
||||
.getRecordingFromAlias( recordingAlias );
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
mComboRecordings.setSelectedItem( selected );
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
package source.recording;
|
||||
|
||||
import gui.control.JFrequencyControl;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
public class RecordingEditorPanel extends JPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private RecordingNode mRecordingNode;
|
||||
|
||||
private JTextField mRecordingAlias;
|
||||
private JLabel mFilePathLabel;
|
||||
|
||||
public RecordingEditorPanel( RecordingNode recordingNode )
|
||||
{
|
||||
mRecordingNode = recordingNode;
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 2", "[right,grow][grow]", "[][][][][][grow]" ) );
|
||||
|
||||
add( new JLabel( "I/Q Recording" ), "span,align left" );
|
||||
|
||||
add( new JLabel( "Alias:" ) );
|
||||
|
||||
mRecordingAlias = new JTextField( mRecordingNode.getRecording()
|
||||
.getRecordingConfiguration().getAlias() );
|
||||
|
||||
mRecordingAlias.addFocusListener( new FocusListener()
|
||||
{
|
||||
@Override
|
||||
public void focusLost( FocusEvent arg0 )
|
||||
{
|
||||
String alias = mRecordingAlias.getText();
|
||||
|
||||
if( alias != null )
|
||||
{
|
||||
mRecordingNode.getRecording().setAlias( alias );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusGained( FocusEvent arg0 ) {}
|
||||
} );
|
||||
|
||||
add( mRecordingAlias, "wrap" );
|
||||
|
||||
JButton mFileSelectionButton = new JButton( "File ..." );
|
||||
mFileSelectionButton.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
if( mRecordingNode.getRecording().hasChannels() )
|
||||
{
|
||||
JOptionPane.showMessageDialog( RecordingEditorPanel.this,
|
||||
"This recording is currently in replay. Please "
|
||||
+ "disable any channels that are using this "
|
||||
+ "recording before changing the recording file." );
|
||||
}
|
||||
else
|
||||
{
|
||||
final JFileChooser fc = new JFileChooser();
|
||||
|
||||
int returnVal = fc.showOpenDialog( RecordingEditorPanel.this );
|
||||
|
||||
if ( returnVal == JFileChooser.APPROVE_OPTION )
|
||||
{
|
||||
File file = fc.getSelectedFile();
|
||||
|
||||
if( file != null && file.exists() )
|
||||
{
|
||||
mRecordingNode.getRecording()
|
||||
.getRecordingConfiguration()
|
||||
.setFilePath( file.getAbsolutePath() );
|
||||
|
||||
if( mFilePathLabel != null )
|
||||
{
|
||||
mFilePathLabel.setText( file.getName() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
add( mFileSelectionButton );
|
||||
|
||||
String filePath = mRecordingNode.getRecording()
|
||||
.getRecordingConfiguration().getFilePath();
|
||||
|
||||
if( filePath != null )
|
||||
{
|
||||
mFilePathLabel = new JLabel( filePath );
|
||||
}
|
||||
else
|
||||
{
|
||||
mFilePathLabel = new JLabel( "Please select a recording" );
|
||||
}
|
||||
|
||||
add( mFilePathLabel, "wrap" );
|
||||
|
||||
add( new JLabel( "Center Frequency:" ), "span,align left" );
|
||||
|
||||
JFrequencyControl frequencyControl = new JFrequencyControl(
|
||||
mRecordingNode.getRecording().getRecordingConfiguration()
|
||||
.getCenterFrequency() );
|
||||
|
||||
frequencyControl.addListener( mRecordingNode.getRecording() );
|
||||
|
||||
add( frequencyControl, "span,align left" );
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.recording;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPopupMenu;
|
||||
|
||||
import controller.BaseNode;
|
||||
|
||||
public class RecordingGroupNode extends BaseNode
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public RecordingGroupNode()
|
||||
{
|
||||
super( null );
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "Recordings [" + this.getChildCount() + "]";
|
||||
}
|
||||
|
||||
public JPopupMenu getContextMenu()
|
||||
{
|
||||
JPopupMenu menu = new JPopupMenu();
|
||||
|
||||
JMenuItem addRecordingItem = new JMenuItem( "Add Recording" );
|
||||
|
||||
addRecordingItem.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
RecordingConfiguration config = new RecordingConfiguration();
|
||||
|
||||
getModel().getResourceManager().getSettingsManager()
|
||||
.addRecordingConfiguration( config );
|
||||
|
||||
Recording recording = getModel().getResourceManager()
|
||||
.getRecordingSourceManager().addRecording( config );
|
||||
|
||||
RecordingNode node = new RecordingNode( recording );
|
||||
|
||||
getModel().addNode( node, RecordingGroupNode.this, 0 );
|
||||
|
||||
sort();
|
||||
|
||||
node.show();
|
||||
}
|
||||
} );
|
||||
|
||||
menu.add( addRecordingItem );
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
public void loadRecordings()
|
||||
{
|
||||
List<Recording> recordings = getModel().getResourceManager()
|
||||
.getRecordingSourceManager().getRecordings();
|
||||
|
||||
for( Recording recording: recordings )
|
||||
{
|
||||
RecordingNode node = new RecordingNode( recording );
|
||||
|
||||
getModel().addNode( node, this, 0 );
|
||||
}
|
||||
|
||||
sort();
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
package source.recording;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
|
||||
import controller.BaseNode;
|
||||
|
||||
public class RecordingNode extends BaseNode
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JPanel mEditor;
|
||||
|
||||
public RecordingNode( Recording recording )
|
||||
{
|
||||
super( recording );
|
||||
}
|
||||
|
||||
public Recording getRecording()
|
||||
{
|
||||
return (Recording)getUserObject();
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return getRecording().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JPanel getEditor()
|
||||
{
|
||||
if( mEditor == null )
|
||||
{
|
||||
mEditor = new RecordingEditorPanel( this );
|
||||
}
|
||||
|
||||
return mEditor;
|
||||
}
|
||||
|
||||
public JPopupMenu getContextMenu()
|
||||
{
|
||||
JPopupMenu menu = new JPopupMenu();
|
||||
|
||||
JMenuItem deleteItem = new JMenuItem( "Delete" );
|
||||
|
||||
deleteItem.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
if( getRecording().hasChannels() )
|
||||
{
|
||||
JOptionPane.showMessageDialog( getModel().getTree(),
|
||||
"Can't delete recording - currently in use. Please"
|
||||
+ " disable any channel(s) that are using this "
|
||||
+ "recording before deleting it",
|
||||
"Can't delete recording",
|
||||
JOptionPane.ERROR_MESSAGE );
|
||||
}
|
||||
else
|
||||
{
|
||||
getModel().getResourceManager().getRecordingSourceManager()
|
||||
.removeRecording( getRecording() );
|
||||
|
||||
getModel().removeNodeFromParent( RecordingNode.this );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
menu.add( deleteItem );
|
||||
|
||||
return menu;
|
||||
}
|
||||
}
|
||||
@@ -31,21 +31,19 @@ import source.config.SourceConfigRecording;
|
||||
import source.config.SourceConfiguration;
|
||||
import source.tuner.TunerChannel;
|
||||
import source.tuner.TunerChannelSource;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class RecordingSourceManager
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( RecordingSourceManager.class );
|
||||
|
||||
private ResourceManager mResourceManager;
|
||||
|
||||
private ArrayList<Recording> mRecordings = new ArrayList<Recording>();
|
||||
|
||||
public RecordingSourceManager( ResourceManager resourceManager )
|
||||
private SettingsManager mSettingsManager;
|
||||
|
||||
public RecordingSourceManager( SettingsManager settingsManager )
|
||||
{
|
||||
mResourceManager = resourceManager;
|
||||
|
||||
mSettingsManager = settingsManager;
|
||||
loadRecordings();
|
||||
}
|
||||
|
||||
@@ -114,7 +112,7 @@ public class RecordingSourceManager
|
||||
|
||||
public Recording addRecording( RecordingConfiguration config )
|
||||
{
|
||||
Recording recording = new Recording( mResourceManager, config );
|
||||
Recording recording = new Recording( mSettingsManager, config );
|
||||
|
||||
mRecordings.add( recording );
|
||||
|
||||
@@ -124,7 +122,7 @@ public class RecordingSourceManager
|
||||
public void removeRecording( Recording recording )
|
||||
{
|
||||
/* Remove the config from the settings manager */
|
||||
mResourceManager.getSettingsManager().removeRecordingConfiguration(
|
||||
mSettingsManager.removeRecordingConfiguration(
|
||||
recording.getRecordingConfiguration() );
|
||||
|
||||
mRecordings.remove( recording );
|
||||
@@ -132,24 +130,17 @@ public class RecordingSourceManager
|
||||
|
||||
private void loadRecordings()
|
||||
{
|
||||
if( mResourceManager != null )
|
||||
{
|
||||
SettingsManager settingsManager = mResourceManager.getSettingsManager();
|
||||
|
||||
if( settingsManager != null )
|
||||
{
|
||||
ArrayList<RecordingConfiguration> recordingConfigurations =
|
||||
settingsManager.getRecordingConfigurations();
|
||||
List<RecordingConfiguration> recordingConfigurations =
|
||||
mSettingsManager.getRecordingConfigurations();
|
||||
|
||||
mLog.info( "discovered [" + recordingConfigurations.size() + "] recording configurations" );
|
||||
|
||||
for( RecordingConfiguration config: recordingConfigurations )
|
||||
{
|
||||
Recording recording = new Recording( mResourceManager, config );
|
||||
|
||||
mRecordings.add( recording );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mLog.info( "RecordingSourceManager - discovered [" +
|
||||
recordingConfigurations.size() + "] recording configurations" );
|
||||
|
||||
for( RecordingConfiguration config: recordingConfigurations )
|
||||
{
|
||||
Recording recording = new Recording( mSettingsManager, config );
|
||||
|
||||
mRecordings.add( recording );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
* Copyright (C) 2014-2016 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
|
||||
@@ -17,19 +17,28 @@
|
||||
******************************************************************************/
|
||||
package source.tuner;
|
||||
|
||||
import controller.BaseNode;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
public class TunerGroupNode extends BaseNode
|
||||
import source.SourceException;
|
||||
|
||||
public interface ITunerChannelProvider
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* Returns a tuner frequency channel source, tuned to the correct frequency
|
||||
*
|
||||
* @param frequency - desired frequency
|
||||
*
|
||||
* @return - source for 48k sample rate
|
||||
*/
|
||||
public abstract TunerChannelSource getChannel( TunerChannel channel )
|
||||
throws RejectedExecutionException, SourceException;
|
||||
|
||||
public TunerGroupNode()
|
||||
{
|
||||
super( null );
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "Tuners [" + this.getChildCount() + "]";
|
||||
}
|
||||
/**
|
||||
* Releases the tuned channel resources
|
||||
*
|
||||
* @param channel - previously obtained tuner channel
|
||||
*/
|
||||
public abstract void releaseChannel( TunerChannelSource source );
|
||||
|
||||
|
||||
}
|
||||
@@ -46,11 +46,12 @@ public abstract class MixerTuner extends Tuner implements Listener<ComplexBuffer
|
||||
* to support tuning.
|
||||
*/
|
||||
public MixerTuner( String name,
|
||||
TunerController tunerController,
|
||||
MixerTunerType mixerTunerType,
|
||||
TargetDataLine targetDataLine,
|
||||
ISampleAdapter sampleAdapter )
|
||||
{
|
||||
super( name );
|
||||
super( name, tunerController );
|
||||
|
||||
mMixerTunerType = mixerTunerType;
|
||||
|
||||
@@ -61,11 +62,13 @@ public abstract class MixerTuner extends Tuner implements Listener<ComplexBuffer
|
||||
(Listener<ComplexBuffer>)this );
|
||||
}
|
||||
|
||||
public MixerTuner( String name,
|
||||
public MixerTuner( String name,
|
||||
TunerController tunerController,
|
||||
MixerTunerDataLine mixerTuner,
|
||||
ISampleAdapter sampleAdapter )
|
||||
{
|
||||
this( name,
|
||||
tunerController,
|
||||
mixerTuner.getMixerTunerType(),
|
||||
mixerTuner.getTargetDataLine(),
|
||||
sampleAdapter );
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
* Copyright (C) 2014-2016 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
|
||||
@@ -17,47 +17,70 @@
|
||||
******************************************************************************/
|
||||
package source.tuner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.Listener;
|
||||
import sample.complex.ComplexBuffer;
|
||||
import source.SourceException;
|
||||
import source.tuner.frequency.FrequencyChangeBroadcaster;
|
||||
import source.tuner.frequency.FrequencyChangeEvent;
|
||||
import source.tuner.frequency.FrequencyChangeEvent.Event;
|
||||
import source.tuner.frequency.FrequencyChangeListener;
|
||||
import controller.ResourceManager;
|
||||
import source.tuner.frequency.IFrequencyChangeProcessor;
|
||||
|
||||
/**
|
||||
* Tuner - provides tuner channel sources, representing a channel frequency
|
||||
*/
|
||||
public abstract class Tuner implements FrequencyChangeBroadcaster,
|
||||
FrequencyChangeListener,
|
||||
TunerChannelProvider
|
||||
public abstract class Tuner implements ITunerChannelProvider
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( Tuner.class );
|
||||
|
||||
private String mName;
|
||||
|
||||
private TunerController mTunerController;
|
||||
/**
|
||||
* Sample Listeners - these will typically be the DFT processor for spectral
|
||||
* display, or it will be one or more tuner channel sources
|
||||
*/
|
||||
protected CopyOnWriteArrayList<Listener<ComplexBuffer>>
|
||||
mSampleListeners = new CopyOnWriteArrayList<Listener<ComplexBuffer>>();
|
||||
protected List<Listener<ComplexBuffer>> mSampleListeners =
|
||||
new CopyOnWriteArrayList<>();
|
||||
|
||||
protected CopyOnWriteArrayList<FrequencyChangeListener>
|
||||
mFrequencyChangeListeners = new CopyOnWriteArrayList<FrequencyChangeListener>();
|
||||
|
||||
public Tuner( String name )
|
||||
protected List<Listener<TunerEvent>> mTunerChangeListeners =
|
||||
new ArrayList<>();
|
||||
|
||||
public Tuner( String name, TunerController tunerController )
|
||||
{
|
||||
mName = name;
|
||||
mTunerController = tunerController;
|
||||
|
||||
//Rebroadcast frequency and sample rate change events as tuner events
|
||||
mTunerController.addListener( new IFrequencyChangeProcessor()
|
||||
{
|
||||
@Override
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
switch( event.getEvent() )
|
||||
{
|
||||
case NOTIFICATION_FREQUENCY_CHANGE:
|
||||
broadcast( new TunerEvent( Tuner.this,
|
||||
source.tuner.TunerEvent.Event.FREQUENCY ));
|
||||
break;
|
||||
case NOTIFICATION_SAMPLE_RATE_CHANGE:
|
||||
broadcast( new TunerEvent( Tuner.this,
|
||||
source.tuner.TunerEvent.Event.SAMPLE_RATE ));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
public TunerController getTunerController()
|
||||
{
|
||||
return mTunerController;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
@@ -68,7 +91,6 @@ public abstract class Tuner implements FrequencyChangeBroadcaster,
|
||||
public void dispose()
|
||||
{
|
||||
mSampleListeners.clear();
|
||||
mFrequencyChangeListeners.clear();
|
||||
}
|
||||
|
||||
public void setName( String name )
|
||||
@@ -76,18 +98,6 @@ public abstract class Tuner implements FrequencyChangeBroadcaster,
|
||||
mName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an editor panel for the tuner
|
||||
*/
|
||||
public abstract JPanel getEditor( ResourceManager resourceManager );
|
||||
|
||||
|
||||
/**
|
||||
* Applies the settings from a saved tuner configuration setting object
|
||||
*/
|
||||
public abstract void apply( TunerConfiguration config )
|
||||
throws SourceException;
|
||||
|
||||
/**
|
||||
* Unique identifier for this tuner, used to lookup a tuner configuration
|
||||
* from the settings manager.
|
||||
@@ -118,23 +128,11 @@ public abstract class Tuner implements FrequencyChangeBroadcaster,
|
||||
return mName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sample rate of complex data coming from the Tuner
|
||||
* @return
|
||||
*/
|
||||
public abstract int getSampleRate();
|
||||
|
||||
/**
|
||||
* Sample size in bits
|
||||
*/
|
||||
public abstract double getSampleSize();
|
||||
|
||||
/**
|
||||
* Tuner Local Oscillator Frequency
|
||||
* @return - frequency in Hertz
|
||||
*/
|
||||
public abstract long getFrequency() throws SourceException;
|
||||
|
||||
/**
|
||||
* Returns a tuner frequency channel source, tuned to the correct frequency
|
||||
*
|
||||
@@ -186,67 +184,30 @@ public abstract class Tuner implements FrequencyChangeBroadcaster,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the frequency change listener to receive frequency and/or bandwidth
|
||||
* change events
|
||||
*/
|
||||
public void addListener( FrequencyChangeListener listener )
|
||||
{
|
||||
mFrequencyChangeListeners.add( listener );
|
||||
}
|
||||
/**
|
||||
* Registers the listener
|
||||
*/
|
||||
public void addTunerChangeListener( Listener<TunerEvent> listener )
|
||||
{
|
||||
mTunerChangeListeners.add( listener );
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the frequency change listener
|
||||
* Removes the registered listener
|
||||
*/
|
||||
public void removeListener( FrequencyChangeListener listener )
|
||||
public void removeTunerChangeListener( Listener<TunerEvent> listener )
|
||||
{
|
||||
mFrequencyChangeListeners.remove( listener );
|
||||
mTunerChangeListeners.remove( listener );
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts a frequency change event to all registered listeners
|
||||
* Broadcasts the tuner change event
|
||||
*/
|
||||
public void broadcastFrequencyChange( long frequency )
|
||||
public void broadcast( TunerEvent event )
|
||||
{
|
||||
broadcastFrequencyChangeEvent(
|
||||
new FrequencyChangeEvent( Event.FREQUENCY_CHANGE_NOTIFICATION, frequency ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts a sample rate change event to all registered listeners
|
||||
*/
|
||||
public void broadcastSampleRateChange( int sampleRate )
|
||||
{
|
||||
broadcastFrequencyChangeEvent(
|
||||
new FrequencyChangeEvent( Event.SAMPLE_RATE_CHANGE_NOTIFICATION, sampleRate ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts actual sample rate change event to all registered listeners
|
||||
*/
|
||||
public void broadcastActualSampleRateChange( int actualSampleRate )
|
||||
{
|
||||
broadcastFrequencyChangeEvent(
|
||||
new FrequencyChangeEvent( Event.SAMPLE_RATE_CHANGE_NOTIFICATION, actualSampleRate ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts a frequency change event to all registered listeners
|
||||
*/
|
||||
public void broadcastFrequencyChangeEvent( FrequencyChangeEvent event )
|
||||
{
|
||||
for( FrequencyChangeListener listener: mFrequencyChangeListeners )
|
||||
for( Listener<TunerEvent> listener: mTunerChangeListeners )
|
||||
{
|
||||
listener.frequencyChanged( event );
|
||||
listener.receive( event );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Frequency change listener method. We receive change events from the
|
||||
* controller and rebroadcast them to all registered listeners.
|
||||
*/
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
broadcastFrequencyChangeEvent( event );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,13 +97,13 @@ public class TunerChannel implements Comparable<TunerChannel>
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo( TunerChannel otherTunerChannel )
|
||||
public int compareTo( TunerChannel otherLock )
|
||||
{
|
||||
if( this.equals( otherTunerChannel ) )
|
||||
if( this.equals( otherLock ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if( mFrequency < otherTunerChannel.getFrequency() )
|
||||
else if( mFrequency < otherLock.getFrequency() )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package source.tuner;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import source.SourceException;
|
||||
import controller.ThreadPoolManager;
|
||||
|
||||
public interface TunerChannelProvider
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014,2015 Dennis Sheirer
|
||||
* Copyright (C) 2014-2016 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
|
||||
@@ -37,15 +37,14 @@ import source.ComplexSource;
|
||||
import source.SourceException;
|
||||
import source.tuner.frequency.FrequencyChangeEvent;
|
||||
import source.tuner.frequency.FrequencyChangeEvent.Event;
|
||||
import source.tuner.frequency.FrequencyChangeListener;
|
||||
import source.tuner.frequency.IFrequencyChangeProcessor;
|
||||
import dsp.filter.FilterFactory;
|
||||
import dsp.filter.Window.WindowType;
|
||||
import dsp.filter.cic.ComplexPrimeCICDecimate;
|
||||
import dsp.mixer.Oscillator;
|
||||
|
||||
public class TunerChannelSource extends ComplexSource
|
||||
implements FrequencyChangeListener,
|
||||
Listener<ComplexBuffer>
|
||||
implements IFrequencyChangeProcessor, Listener<ComplexBuffer>
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( TunerChannelSource.class );
|
||||
@@ -60,7 +59,7 @@ public class TunerChannelSource extends ComplexSource
|
||||
private Oscillator mMixer;
|
||||
private ComplexPrimeCICDecimate mDecimationFilter;
|
||||
private Listener<ComplexBuffer> mListener;
|
||||
private FrequencyChangeListener mFrequencyChangeListener;
|
||||
private IFrequencyChangeProcessor mFrequencyChangeProcessor;
|
||||
private ScheduledFuture<?> mTaskHandle;
|
||||
|
||||
private long mTunerFrequency = 0;
|
||||
@@ -69,82 +68,122 @@ public class TunerChannelSource extends ComplexSource
|
||||
|
||||
private DecimationProcessor mDecimationProcessor = new DecimationProcessor();
|
||||
|
||||
private AtomicBoolean mRunning = new AtomicBoolean();
|
||||
private boolean mExpended = false;
|
||||
|
||||
/**
|
||||
* Provides a Digital Drop Channel (DDC) to decimate the IQ output from a
|
||||
* tuner down to a 48 kHz IQ channel rate.
|
||||
*
|
||||
* Note: this class can only be used once (started and stopped) and a new
|
||||
* tuner channel source must be requested from the tuner once this object
|
||||
* has been stopped. This is because channels are managed dynamically and
|
||||
* center tuned frequency may have changed since this source was obtained
|
||||
* and thus the tuner might no longer be able to source this channel once it
|
||||
* has been stopped.
|
||||
*
|
||||
* @param threadPoolManager to use for decimation processing task
|
||||
* @param tuner to obtain wideband IQ samples from
|
||||
* @param tunerChannel specifying the center frequency for the DDC
|
||||
* @throws RejectedExecutionException if the thread pool manager cannot
|
||||
* accept the decimation processing task
|
||||
* @throws SourceException if the tuner has an issue providing IQ samples
|
||||
*/
|
||||
public TunerChannelSource( Tuner tuner, TunerChannel tunerChannel )
|
||||
throws RejectedExecutionException, SourceException
|
||||
throws RejectedExecutionException, SourceException
|
||||
{
|
||||
super( "Tuner Channel Source" );
|
||||
|
||||
mTuner = tuner;
|
||||
mTuner.addListener( (FrequencyChangeListener)this );
|
||||
mTuner.getTunerController().addListener( (IFrequencyChangeProcessor)this );
|
||||
|
||||
mTunerChannel = tunerChannel;
|
||||
|
||||
mTunerFrequency = mTuner.getFrequency();
|
||||
mTunerFrequency = mTuner.getTunerController().getFrequency();
|
||||
|
||||
/* Setup the frequency translator to the current source frequency */
|
||||
long frequencyOffset = mTunerFrequency - mTunerChannel.getFrequency();
|
||||
|
||||
mMixer = new Oscillator( frequencyOffset, mTuner.getSampleRate() );
|
||||
mMixer = new Oscillator( frequencyOffset,
|
||||
mTuner.getTunerController().getSampleRate() );
|
||||
|
||||
/* Fire a sample rate change event to setup the decimation chain */
|
||||
frequencyChanged( new FrequencyChangeEvent(
|
||||
Event.SAMPLE_RATE_CHANGE_NOTIFICATION, mTuner.getSampleRate() ) );
|
||||
Event.NOTIFICATION_SAMPLE_RATE_CHANGE,
|
||||
mTuner.getTunerController().getSampleRate() ) );
|
||||
}
|
||||
|
||||
public void start( ScheduledExecutorService scheduledExecutorService )
|
||||
{
|
||||
/* Schedule the decimation task to run every 10 ms (100 iterations/second) */
|
||||
mTaskHandle = scheduledExecutorService.scheduleAtFixedRate(
|
||||
mDecimationProcessor, 0, 10, TimeUnit.MILLISECONDS );
|
||||
|
||||
/* Finally, register to receive samples from the tuner */
|
||||
mTuner.addListener( (Listener<ComplexBuffer>)this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
if( mExpended )
|
||||
{
|
||||
throw new IllegalStateException( "Attempt to re-start an expended "
|
||||
+ "tuner channel source. TunerChannelSource objects can only "
|
||||
+ "be used once. " );
|
||||
}
|
||||
|
||||
if( mRunning.compareAndSet( false, true ))
|
||||
{
|
||||
/* Schedule the decimation task to run every 10 ms (100 iterations/second) */
|
||||
mTaskHandle = executor.scheduleAtFixedRate( mDecimationProcessor,
|
||||
0, 10, TimeUnit.MILLISECONDS );
|
||||
|
||||
/* Finally, register to receive samples from the tuner */
|
||||
mTuner.addListener( (Listener<ComplexBuffer>)this );
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.warn( "Attempt to start() and already running tuner channel source was ignored" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
if( mRunning.compareAndSet( true, false ))
|
||||
{
|
||||
mTuner.releaseChannel( this );
|
||||
mDecimationProcessor.shutdown();
|
||||
|
||||
if( mTaskHandle != null )
|
||||
{
|
||||
mTaskHandle.cancel( true );
|
||||
mTaskHandle = null;
|
||||
}
|
||||
|
||||
mBuffer.clear();
|
||||
|
||||
mExpended = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.warn( "Attempt to stop() and already stopped tuner channel source was ignored" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void dispose()
|
||||
{
|
||||
/* Tell the tuner to release/unregister our resources */
|
||||
mTuner.removeListener( (FrequencyChangeListener)this );
|
||||
mTuner.releaseChannel( this );
|
||||
mTuner = null;
|
||||
mTunerChannel = null;
|
||||
|
||||
/* Flag the decimation processor to shutdown */
|
||||
if( mDecimationProcessor != null )
|
||||
{
|
||||
mDecimationProcessor.dispose();
|
||||
}
|
||||
|
||||
if( !mRunning.get() )
|
||||
{
|
||||
/* Tell the tuner to release/unregister our resources */
|
||||
mTuner.getTunerController().removeListener( this );
|
||||
mTuner = null;
|
||||
mTunerChannel = null;
|
||||
mBuffer = null;
|
||||
mFrequencyChangeProcessor = null;
|
||||
mListener = null;
|
||||
mMixer = null;
|
||||
mDecimationFilter.dispose();
|
||||
mDecimationFilter = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup method to allow the decimation processor to perform final cleanup
|
||||
* once it gracefully shuts itself down
|
||||
*/
|
||||
private void cleanup()
|
||||
{
|
||||
if( mTaskHandle != null )
|
||||
{
|
||||
mTaskHandle.cancel( true );
|
||||
mTaskHandle = null;
|
||||
}
|
||||
|
||||
synchronized( mBuffer )
|
||||
{
|
||||
mBuffer.clear();
|
||||
mBuffer = null;
|
||||
}
|
||||
|
||||
mFrequencyChangeListener = null;
|
||||
mListener = null;
|
||||
|
||||
mMixer = null;
|
||||
|
||||
mDecimationFilter.dispose();
|
||||
mDecimationFilter = null;
|
||||
}
|
||||
|
||||
public Tuner getTuner()
|
||||
{
|
||||
return mTuner;
|
||||
@@ -158,24 +197,21 @@ public class TunerChannelSource extends ComplexSource
|
||||
@Override
|
||||
public void receive( ComplexBuffer buffer )
|
||||
{
|
||||
synchronized( mBuffer )
|
||||
if( mRunning.get() )
|
||||
{
|
||||
if( mBuffer != null )
|
||||
{
|
||||
mBuffer.add( buffer );
|
||||
}
|
||||
mBuffer.add( buffer );
|
||||
}
|
||||
}
|
||||
|
||||
public void setFrequencyChangeListener( FrequencyChangeListener listener )
|
||||
public void setFrequencyChangeListener( IFrequencyChangeProcessor processor )
|
||||
{
|
||||
mFrequencyChangeListener = listener;
|
||||
mFrequencyChangeProcessor = processor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListener( Listener<ComplexBuffer> listener )
|
||||
{
|
||||
/* Get a pointer to the listener so that if we have to change the
|
||||
/* Save a pointer to the listener so that if we have to change the
|
||||
* decimation filter, we can re-add the listener */
|
||||
mListener = listener;
|
||||
|
||||
@@ -196,31 +232,31 @@ public class TunerChannelSource extends ComplexSource
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
// Echo the event to the registered event listener
|
||||
if( mFrequencyChangeListener != null )
|
||||
if( mFrequencyChangeProcessor != null )
|
||||
{
|
||||
mFrequencyChangeListener.frequencyChanged( event );
|
||||
mFrequencyChangeProcessor.frequencyChanged( event );
|
||||
}
|
||||
|
||||
switch( event.getEvent() )
|
||||
{
|
||||
case FREQUENCY_CHANGE_NOTIFICATION:
|
||||
case NOTIFICATION_FREQUENCY_CHANGE:
|
||||
mTunerFrequency = event.getValue().longValue();
|
||||
updateMixerFrequencyOffset();
|
||||
break;
|
||||
case CHANNEL_FREQUENCY_CORRECTION_CHANGE_REQUEST:
|
||||
case REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE:
|
||||
mChannelFrequencyCorrection = event.getValue().intValue();
|
||||
|
||||
updateMixerFrequencyOffset();
|
||||
|
||||
if( mFrequencyChangeListener != null )
|
||||
if( mFrequencyChangeProcessor != null )
|
||||
{
|
||||
mFrequencyChangeListener.frequencyChanged(
|
||||
mFrequencyChangeProcessor.frequencyChanged(
|
||||
new FrequencyChangeEvent(
|
||||
Event.CHANNEL_FREQUENCY_CORRECTION_CHANGE_NOTIFICATION,
|
||||
Event.NOTIFICATION_CHANNEL_FREQUENCY_CORRECTION_CHANGE,
|
||||
mChannelFrequencyCorrection ) );
|
||||
}
|
||||
break;
|
||||
case SAMPLE_RATE_CHANGE_NOTIFICATION:
|
||||
case NOTIFICATION_SAMPLE_RATE_CHANGE:
|
||||
int sampleRate = event.getValue().intValue();
|
||||
|
||||
if( mTunerSampleRate != sampleRate )
|
||||
@@ -276,12 +312,12 @@ public class TunerChannelSource extends ComplexSource
|
||||
*/
|
||||
public class DecimationProcessor implements Runnable
|
||||
{
|
||||
private AtomicBoolean mDispose = new AtomicBoolean( false );
|
||||
private boolean mProcessing = true;
|
||||
private List<ComplexBuffer> mSampleBuffers = new ArrayList<ComplexBuffer>();
|
||||
|
||||
public void dispose()
|
||||
public void shutdown()
|
||||
{
|
||||
mDispose.set( true );
|
||||
mProcessing = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -292,64 +328,69 @@ public class TunerChannelSource extends ComplexSource
|
||||
* run the program out of memory */
|
||||
try
|
||||
{
|
||||
if( mBuffer != null )
|
||||
if( mProcessing )
|
||||
{
|
||||
mBuffer.drainTo( mSampleBuffers, 8 );
|
||||
|
||||
for( Buffer buffer: mSampleBuffers )
|
||||
{
|
||||
/* Check to see if we've been shutdown */
|
||||
if( mDispose.get() )
|
||||
// long start = System.currentTimeMillis();
|
||||
|
||||
mBuffer.drainTo( mSampleBuffers, 8 );
|
||||
|
||||
for( Buffer buffer: mSampleBuffers )
|
||||
{
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
float[] samples = buffer.getSamples();
|
||||
|
||||
/* We make a copy of the buffer so that we don't affect
|
||||
* anyone else that is using the same buffer, like other
|
||||
* channels or the spectral display */
|
||||
float[] translated = new float[ samples.length ];
|
||||
|
||||
/* Perform frequency translation */
|
||||
for( int x = 0; x < samples.length; x += 2 )
|
||||
/* Check to see if we've been shutdown */
|
||||
if( !mProcessing )
|
||||
{
|
||||
mMixer.rotate();
|
||||
mBuffer.clear();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
float[] samples = buffer.getSamples();
|
||||
|
||||
/* We make a copy of the buffer so that we don't affect
|
||||
* anyone else that is using the same buffer, like other
|
||||
* channels or the spectral display */
|
||||
float[] translated = new float[ samples.length ];
|
||||
|
||||
translated[ x ] = Complex.multiplyInphase(
|
||||
samples[ x ], samples[ x + 1 ], mMixer.inphase(), mMixer.quadrature() );
|
||||
|
||||
translated[ x + 1 ] = Complex.multiplyQuadrature(
|
||||
/* Perform frequency translation */
|
||||
for( int x = 0; x < samples.length; x += 2 )
|
||||
{
|
||||
mMixer.rotate();
|
||||
|
||||
translated[ x ] = Complex.multiplyInphase(
|
||||
samples[ x ], samples[ x + 1 ], mMixer.inphase(), mMixer.quadrature() );
|
||||
}
|
||||
|
||||
if( mDecimationFilter != null )
|
||||
{
|
||||
mDecimationFilter.receive( new ComplexBuffer( translated ) );
|
||||
|
||||
translated[ x + 1 ] = Complex.multiplyQuadrature(
|
||||
samples[ x ], samples[ x + 1 ], mMixer.inphase(), mMixer.quadrature() );
|
||||
}
|
||||
|
||||
if( mProcessing && mDecimationFilter != null )
|
||||
{
|
||||
mDecimationFilter.receive( new ComplexBuffer( translated ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mLog.debug( "Processed [" + mSampleBuffers.size() + "] in " + ( System.currentTimeMillis() - start ) );
|
||||
|
||||
mSampleBuffers.clear();
|
||||
}
|
||||
|
||||
mSampleBuffers.clear();
|
||||
}
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
/* Only log the stack trace if we've haven't been shutdown and
|
||||
* this is a true error */
|
||||
if( !mDispose.get() )
|
||||
/* Only log the stack trace if we're still processing */
|
||||
if( mProcessing )
|
||||
{
|
||||
mLog.error( "Error encountered during decimation process", e );
|
||||
}
|
||||
}
|
||||
|
||||
/* Check to see if we've been shutdown */
|
||||
if( mDispose.get() )
|
||||
if( !mProcessing )
|
||||
{
|
||||
mBuffer.clear();
|
||||
mSampleBuffers.clear();
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import javax.usb.UsbDeviceDescriptor;
|
||||
|
||||
public enum TunerClass
|
||||
{
|
||||
AIRSPY( TunerType.AIRSPY_R820T, "1D50", "60A1", "Airspy.com", "Airspy" ),
|
||||
AIRSPY( TunerType.AIRSPY_R820T, "1D50", "60A1", "Airspy", "Airspy" ),
|
||||
GENERIC_2832( TunerType.RTL2832_VARIOUS, "0BDA", "2832", "RTL2832", "SDR" ),
|
||||
GENERIC_2838( TunerType.RTL2832_VARIOUS, "0BDA", "2838", "RTL2832", "SDR" ),
|
||||
COMPRO_VIDEOMATE_U620F( TunerType.ELONICS_E4000, "185B", "0620", "Compro", "Videomate U620F" ),
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.tuner;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
|
||||
public class TunerConfigurationAssignment
|
||||
{
|
||||
private TunerType mTunerType;
|
||||
private String mUniqueID;
|
||||
private String mTunerConfigurationName;
|
||||
|
||||
public TunerConfigurationAssignment()
|
||||
{
|
||||
}
|
||||
|
||||
@XmlAttribute( name = "type" )
|
||||
public TunerType getTunerType()
|
||||
{
|
||||
return mTunerType;
|
||||
}
|
||||
|
||||
public void setTunerType( TunerType tunerType )
|
||||
{
|
||||
mTunerType = tunerType;
|
||||
}
|
||||
|
||||
@XmlAttribute( name = "id" )
|
||||
public String getUniqueID()
|
||||
{
|
||||
return mUniqueID;
|
||||
}
|
||||
|
||||
public void setUniqueID( String uniqueID )
|
||||
{
|
||||
mUniqueID = uniqueID;
|
||||
}
|
||||
|
||||
@XmlAttribute( name = "configuration_name" )
|
||||
public String getTunerConfigurationName()
|
||||
{
|
||||
return mTunerConfigurationName;
|
||||
}
|
||||
|
||||
public void setTunerConfigurationName( String tunerConfigurationName )
|
||||
{
|
||||
mTunerConfigurationName = tunerConfigurationName;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014,2015 Dennis Sheirer
|
||||
* Copyright (C) 2014-2016 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
|
||||
@@ -25,12 +25,14 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.frequency.FrequencyChangeListener;
|
||||
import source.tuner.configuration.TunerConfiguration;
|
||||
import source.tuner.frequency.FrequencyChangeEvent;
|
||||
import source.tuner.frequency.FrequencyChangeEvent.Event;
|
||||
import source.tuner.frequency.FrequencyController;
|
||||
import source.tuner.frequency.FrequencyController.Tunable;
|
||||
import controller.ThreadPoolManager;
|
||||
import source.tuner.frequency.IFrequencyChangeProcessor;
|
||||
|
||||
public abstract class TunerController implements Tunable
|
||||
public abstract class TunerController implements Tunable, IFrequencyChangeProcessor
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( TunerController.class );
|
||||
@@ -72,8 +74,27 @@ public abstract class TunerController implements Tunable
|
||||
*/
|
||||
public abstract void apply( TunerConfiguration config )
|
||||
throws SourceException;
|
||||
|
||||
public int getBandwidth()
|
||||
|
||||
/**
|
||||
* Responds to requests to set the frequency
|
||||
*/
|
||||
@Override
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
if( event.getEvent() == Event.REQUEST_FREQUENCY_CHANGE )
|
||||
{
|
||||
try
|
||||
{
|
||||
setFrequency( event.getValue().longValue() );
|
||||
}
|
||||
catch ( SourceException e )
|
||||
{
|
||||
mLog.error( "Error setting frequency from external controller", e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getBandwidth()
|
||||
{
|
||||
return mFrequencyController.getBandwidth();
|
||||
}
|
||||
@@ -98,6 +119,11 @@ public abstract class TunerController implements Tunable
|
||||
{
|
||||
return mFrequencyController.getFrequency();
|
||||
}
|
||||
|
||||
public int getSampleRate()
|
||||
{
|
||||
return mFrequencyController.getBandwidth();
|
||||
}
|
||||
|
||||
public double getFrequencyCorrection()
|
||||
{
|
||||
@@ -221,6 +247,11 @@ public abstract class TunerController implements Tunable
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
public int getChannelCount()
|
||||
{
|
||||
return mTunedChannels.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the tuner's LO frequency must be updated in order to
|
||||
@@ -358,16 +389,16 @@ public abstract class TunerController implements Tunable
|
||||
* Note: this is normally used by the Tuner. Any additional listeners can
|
||||
* be registered on the tuner.
|
||||
*/
|
||||
public void addListener( FrequencyChangeListener listener )
|
||||
public void addListener( IFrequencyChangeProcessor processor )
|
||||
{
|
||||
mFrequencyController.addListener( listener );
|
||||
mFrequencyController.addListener( processor );
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the frequency change listener
|
||||
*/
|
||||
public void removeListener( FrequencyChangeListener listener )
|
||||
public void removeListener( IFrequencyChangeProcessor processor )
|
||||
{
|
||||
mFrequencyController.removeListener( listener );
|
||||
mFrequencyController.removeFrequencyChangeProcessor( processor );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
* Copyright (C) 2014-2016 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
|
||||
@@ -15,45 +15,342 @@
|
||||
* 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 source.tuner;
|
||||
|
||||
import gui.control.JFrequencyControl;
|
||||
import source.SourceEditor;
|
||||
import source.config.SourceConfigTuner;
|
||||
import source.config.SourceConfiguration;
|
||||
import controller.ResourceManager;
|
||||
import gui.editor.Editor;
|
||||
import gui.editor.EmptyEditor;
|
||||
|
||||
public class TunerEditor extends SourceEditor
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.RowFilter;
|
||||
import javax.swing.ScrollPaneConstants;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import javax.swing.table.TableRowSorter;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.tuner.configuration.TunerConfiguration;
|
||||
import source.tuner.configuration.TunerConfigurationFactory;
|
||||
import source.tuner.configuration.TunerConfigurationModel;
|
||||
|
||||
import com.jidesoft.swing.JideSplitPane;
|
||||
|
||||
public class TunerEditor extends Editor<Tuner>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private JFrequencyControl mFrequencyControl;
|
||||
|
||||
public TunerEditor( ResourceManager resourceManager,
|
||||
SourceConfiguration config )
|
||||
{
|
||||
super( resourceManager, config );
|
||||
|
||||
initGUI();
|
||||
}
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public void reset()
|
||||
private final static Logger mLog = LoggerFactory.getLogger( TunerEditor.class );
|
||||
|
||||
private TunerConfigurationModel mTunerConfigurationModel;
|
||||
private JTable mTunerConfigurationTable;
|
||||
private TableRowSorter<TunerConfigurationModel> mRowSorter;
|
||||
private JFrequencyControl mFrequencyControl = new JFrequencyControl();
|
||||
private JLabel mSelectedTunerType = new JLabel( "No Tuner Selected" );
|
||||
private JButton mNewConfigurationButton = new JButton( "New" );
|
||||
private JButton mDeleteConfigurationButton = new JButton( "Delete" );
|
||||
private JButton mAssignConfigurationButton = new JButton( "Assign" );
|
||||
private JScrollPane mEditorScroller;
|
||||
private Editor<TunerConfiguration> mEditor = new EmptyEditor<>( "a tuner" );
|
||||
private JideSplitPane mEditorSplitPane = new JideSplitPane();
|
||||
|
||||
public TunerEditor( TunerConfigurationModel tunerConfigurationModel )
|
||||
{
|
||||
mFrequencyControl.setFrequency(
|
||||
((SourceConfigTuner)mConfig).getFrequency(), false );
|
||||
mTunerConfigurationModel = tunerConfigurationModel;
|
||||
init();
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
setLayout( new MigLayout( "insets 0 0 0 0", "[grow,fill]", "[grow,fill]" ) );
|
||||
|
||||
JPanel listPanel = new JPanel();
|
||||
listPanel.setLayout( new MigLayout( "fill,wrap 3", "[grow,fill]", "[][][][grow,fill][]" ) );
|
||||
|
||||
listPanel.add( mSelectedTunerType, "span" );
|
||||
|
||||
mFrequencyControl.setEnabled( false );
|
||||
listPanel.add( mFrequencyControl, "span" );
|
||||
|
||||
mRowSorter = new TableRowSorter<>( mTunerConfigurationModel );
|
||||
mTunerConfigurationTable = new JTable( mTunerConfigurationModel );
|
||||
mTunerConfigurationTable.setRowSorter( mRowSorter );
|
||||
mTunerConfigurationTable.setEnabled( false );
|
||||
mTunerConfigurationTable.getSelectionModel().addListSelectionListener( new ListSelectionListener()
|
||||
{
|
||||
@Override
|
||||
public void valueChanged( ListSelectionEvent event )
|
||||
{
|
||||
if( !event.getValueIsAdjusting() )
|
||||
{
|
||||
int row = mTunerConfigurationTable.getSelectedRow();
|
||||
|
||||
if( row >= 0 )
|
||||
{
|
||||
int modelRow = mTunerConfigurationTable.convertRowIndexToModel( row );
|
||||
|
||||
if( modelRow >= 0 )
|
||||
{
|
||||
setTunerConfiguration( mTunerConfigurationModel.getTunerConfiguration( modelRow ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
JScrollPane tableScroller = new JScrollPane( mTunerConfigurationTable );
|
||||
tableScroller.setHorizontalScrollBarPolicy(
|
||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER );
|
||||
listPanel.add( new JLabel( "Tuner Configurations" ), "span" );
|
||||
listPanel.add( tableScroller, "span" );
|
||||
|
||||
mNewConfigurationButton.setEnabled( false );
|
||||
mNewConfigurationButton.setToolTipText( "Create a new configuration for the currently selected tuner" );
|
||||
mNewConfigurationButton.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
Tuner tuner = getItem();
|
||||
|
||||
String name = mTunerConfigurationModel
|
||||
.getDistinctName( tuner.getTunerType(), tuner.getUniqueID() );
|
||||
|
||||
TunerConfiguration config = TunerConfigurationFactory
|
||||
.getTunerConfiguration( tuner.getTunerType(),
|
||||
tuner.getUniqueID(), name );
|
||||
|
||||
mTunerConfigurationModel.addTunerConfiguration( config );
|
||||
}
|
||||
} );
|
||||
listPanel.add( mNewConfigurationButton );
|
||||
|
||||
mDeleteConfigurationButton.setEnabled( false );
|
||||
mDeleteConfigurationButton.setToolTipText( "Deletes the currently selected tuner" );
|
||||
mDeleteConfigurationButton.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
int choice = JOptionPane.showConfirmDialog( TunerEditor.this,
|
||||
"Do you want to delete this tuner configuration?",
|
||||
"Delete Tuner Configuration?", JOptionPane.YES_NO_OPTION );
|
||||
|
||||
if( choice == JOptionPane.YES_OPTION )
|
||||
{
|
||||
TunerConfiguration selected = getSelectedTunerConfiguration();
|
||||
|
||||
mTunerConfigurationModel.removeTunerConfiguration( selected );
|
||||
mTunerConfigurationTable.setRowSelectionInterval( 0, 0 );
|
||||
}
|
||||
}
|
||||
} );
|
||||
listPanel.add( mDeleteConfigurationButton );
|
||||
|
||||
mAssignConfigurationButton.setEnabled( false );
|
||||
mAssignConfigurationButton.setToolTipText( "Assigns to the currently selected tuner configuration to the selected tuner" );
|
||||
mAssignConfigurationButton.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
TunerConfiguration selected = getSelectedTunerConfiguration();
|
||||
|
||||
mTunerConfigurationModel.assignTunerConfiguration( selected );
|
||||
setTunerConfiguration( getSelectedTunerConfiguration() );
|
||||
}
|
||||
} );
|
||||
listPanel.add( mAssignConfigurationButton );
|
||||
|
||||
//Set preferred size on both scrollers to same width, so they split the space
|
||||
listPanel.setPreferredSize( new Dimension( 100, 80 ) );
|
||||
JScrollPane listScroller = new JScrollPane( listPanel );
|
||||
listScroller.setPreferredSize( new Dimension( 100, 80 ) );
|
||||
|
||||
mEditorScroller = new JScrollPane( mEditor );
|
||||
mEditorScroller.setPreferredSize( new Dimension( 100, 80 ) );
|
||||
|
||||
mEditorSplitPane = new JideSplitPane( JideSplitPane.HORIZONTAL_SPLIT );
|
||||
mEditorSplitPane.add( listScroller );
|
||||
mEditorSplitPane.add( mEditorScroller );
|
||||
|
||||
add( mEditorSplitPane );
|
||||
}
|
||||
|
||||
private TunerConfiguration getSelectedTunerConfiguration()
|
||||
{
|
||||
int tableRow = mTunerConfigurationTable.getSelectedRow();
|
||||
|
||||
if( tableRow >= 0 )
|
||||
{
|
||||
int modelRow = mTunerConfigurationTable.convertRowIndexToModel( tableRow );
|
||||
|
||||
if( modelRow >= 0 )
|
||||
{
|
||||
return mTunerConfigurationModel.getTunerConfiguration( modelRow );
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
((SourceConfigTuner)mConfig).setFrequency( mFrequencyControl.getFrequency() );
|
||||
//Unused
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem( Tuner tuner )
|
||||
{
|
||||
//Cleanup previously selected tuner
|
||||
if( hasItem() )
|
||||
{
|
||||
Tuner previous = getItem();
|
||||
previous.getTunerController().removeListener( mFrequencyControl );
|
||||
mFrequencyControl.removeListener( previous.getTunerController() );
|
||||
}
|
||||
|
||||
super.setItem( tuner );
|
||||
|
||||
if( hasItem() )
|
||||
{
|
||||
mSelectedTunerType.setText( tuner.getName() );
|
||||
mFrequencyControl.setEnabled( true );
|
||||
mTunerConfigurationTable.setEnabled( true );
|
||||
mNewConfigurationButton.setEnabled( true );
|
||||
|
||||
//Change to an editor for this config's tuner type
|
||||
mEditor = TunerConfigurationFactory.getEditor( getItem(), mTunerConfigurationModel );
|
||||
|
||||
mRowSorter.setRowFilter( new ConfigurationRowFilter( tuner.getTunerType(),
|
||||
tuner.getUniqueID() ) );
|
||||
|
||||
TunerConfiguration assigned = mTunerConfigurationModel
|
||||
.getTunerConfiguration( tuner.getTunerType(), tuner.getUniqueID() );
|
||||
|
||||
int modelIndex = mTunerConfigurationModel.getRowIndex( assigned );
|
||||
|
||||
if( modelIndex >= 0 )
|
||||
{
|
||||
int viewIndex = mTunerConfigurationTable
|
||||
.convertRowIndexToView( modelIndex );
|
||||
|
||||
if( viewIndex >= 0 )
|
||||
{
|
||||
mTunerConfigurationTable
|
||||
.setRowSelectionInterval( viewIndex, viewIndex );
|
||||
}
|
||||
}
|
||||
|
||||
//Link frequency control to the tuner
|
||||
mFrequencyControl.addListener( tuner.getTunerController() );
|
||||
|
||||
//Link tuner to frequency control
|
||||
tuner.getTunerController().addListener( mFrequencyControl );
|
||||
|
||||
//Set the displayed frequency without adjusting the tuner's frequency
|
||||
mFrequencyControl.setFrequency(
|
||||
tuner.getTunerController().getFrequency(), false );
|
||||
}
|
||||
else
|
||||
{
|
||||
mSelectedTunerType.setText( "No Tuner Selected" );
|
||||
mFrequencyControl.setEnabled( false );
|
||||
mTunerConfigurationTable.setEnabled( false );
|
||||
mNewConfigurationButton.setEnabled( false );
|
||||
mRowSorter.setRowFilter( null );
|
||||
mEditor = new EmptyEditor<TunerConfiguration>();
|
||||
}
|
||||
|
||||
//Swap out the editor
|
||||
int split = mEditorSplitPane.getDividerLocation( 0 );
|
||||
mEditorSplitPane.remove( mEditorScroller );
|
||||
mEditorScroller = new JScrollPane( mEditor );
|
||||
mEditorSplitPane.add( mEditorScroller );
|
||||
mEditorSplitPane.setDividerLocation( 0, split );
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
private void setTunerConfiguration( TunerConfiguration config )
|
||||
{
|
||||
mFrequencyControl = new JFrequencyControl();
|
||||
if( config != null )
|
||||
{
|
||||
if( !config.isAssigned() )
|
||||
{
|
||||
if( !mAssignConfigurationButton.isEnabled() )
|
||||
{
|
||||
mAssignConfigurationButton.setEnabled( true );
|
||||
}
|
||||
if( !mDeleteConfigurationButton.isEnabled() )
|
||||
{
|
||||
mDeleteConfigurationButton.setEnabled( true );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( mAssignConfigurationButton.isEnabled() )
|
||||
{
|
||||
mAssignConfigurationButton.setEnabled( false );
|
||||
}
|
||||
|
||||
if( mDeleteConfigurationButton.isEnabled() )
|
||||
{
|
||||
mDeleteConfigurationButton.setEnabled( false );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( mDeleteConfigurationButton.isEnabled() )
|
||||
{
|
||||
mDeleteConfigurationButton.setEnabled( false );
|
||||
}
|
||||
|
||||
if( mAssignConfigurationButton.isEnabled() )
|
||||
{
|
||||
mAssignConfigurationButton.setEnabled( false );
|
||||
}
|
||||
}
|
||||
|
||||
mFrequencyControl.setFrequency(
|
||||
((SourceConfigTuner)mConfig).getFrequency(), false );
|
||||
|
||||
add( mFrequencyControl );
|
||||
mEditor.setItem( config );
|
||||
}
|
||||
|
||||
public class ConfigurationRowFilter extends RowFilter<TunerConfigurationModel,Integer>
|
||||
{
|
||||
private TunerType mTunerType;
|
||||
private String mUniqueID;
|
||||
|
||||
public ConfigurationRowFilter( TunerType type, String uniqueID )
|
||||
{
|
||||
mTunerType = type;
|
||||
mUniqueID = uniqueID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean include( javax.swing.RowFilter.Entry<? extends TunerConfigurationModel,
|
||||
? extends Integer> entry )
|
||||
{
|
||||
TunerConfiguration config = entry.getModel()
|
||||
.getTunerConfiguration( entry.getIdentifier() );
|
||||
|
||||
return config != null &&
|
||||
config.getTunerType() == mTunerType &&
|
||||
config.getUniqueID() != null &&
|
||||
config.getUniqueID().contentEquals( mUniqueID );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
34
src/source/tuner/TunerEvent.java
Normal file
34
src/source/tuner/TunerEvent.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package source.tuner;
|
||||
|
||||
public class TunerEvent
|
||||
{
|
||||
private Tuner mTuner;
|
||||
private Event mEvent;
|
||||
|
||||
public TunerEvent( Tuner tuner, Event event )
|
||||
{
|
||||
mTuner = tuner;
|
||||
mEvent = event;
|
||||
}
|
||||
|
||||
public Tuner getTuner()
|
||||
{
|
||||
return mTuner;
|
||||
}
|
||||
|
||||
public Event getEvent()
|
||||
{
|
||||
return mEvent;
|
||||
}
|
||||
|
||||
public enum Event
|
||||
{
|
||||
ADD,
|
||||
REMOVE,
|
||||
CHANNEL_COUNT,
|
||||
FREQUENCY,
|
||||
SAMPLE_RATE,
|
||||
REQUEST_MAIN_SPECTRAL_DISPLAY,
|
||||
REQUEST_NEW_SPECTRAL_DISPLAY;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014,2015 Dennis Sheirer
|
||||
* Copyright (C) 2014-2016 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
|
||||
@@ -17,11 +17,7 @@
|
||||
******************************************************************************/
|
||||
package source.tuner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -30,10 +26,7 @@ import org.usb4java.DeviceDescriptor;
|
||||
import org.usb4java.DeviceList;
|
||||
import org.usb4java.LibUsb;
|
||||
|
||||
import source.Source;
|
||||
import source.SourceException;
|
||||
import source.config.SourceConfigTuner;
|
||||
import source.config.SourceConfiguration;
|
||||
import source.mixer.MixerManager;
|
||||
import source.tuner.airspy.AirspyTuner;
|
||||
import source.tuner.airspy.AirspyTunerController;
|
||||
@@ -46,22 +39,24 @@ import source.tuner.rtl.RTL2832Tuner;
|
||||
import source.tuner.rtl.RTL2832TunerController;
|
||||
import source.tuner.rtl.e4k.E4KTunerController;
|
||||
import source.tuner.rtl.r820t.R820TTunerController;
|
||||
import controller.ResourceManager;
|
||||
import controller.ThreadPoolManager;
|
||||
|
||||
public class TunerManager
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( TunerManager.class );
|
||||
|
||||
private ResourceManager mResourceManager;
|
||||
private ArrayList<Tuner> mTuners = new ArrayList<Tuner>();
|
||||
private MixerManager mMixerManager;
|
||||
private TunerModel mTunerModel;
|
||||
private ThreadPoolManager mThreadPoolManager;
|
||||
|
||||
public TunerManager( ResourceManager resourceManager )
|
||||
public TunerManager( MixerManager mixerManager,
|
||||
TunerModel tunerModel,
|
||||
ThreadPoolManager threadPoolManager )
|
||||
{
|
||||
mResourceManager = resourceManager;
|
||||
|
||||
/* initialize mixers */
|
||||
MixerManager.getInstance();
|
||||
mMixerManager = mixerManager;
|
||||
mTunerModel = tunerModel;
|
||||
mThreadPoolManager = threadPoolManager;
|
||||
|
||||
initTuners();
|
||||
}
|
||||
@@ -74,57 +69,6 @@ public class TunerManager
|
||||
LibUsb.exit( null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates current tuners to get a tuner channel source for the frequency
|
||||
* specified in the channel config's source config object
|
||||
*/
|
||||
public Source getSource( SourceConfiguration config, int bandwidth )
|
||||
{
|
||||
TunerChannelSource retVal = null;
|
||||
|
||||
if( config instanceof SourceConfigTuner )
|
||||
{
|
||||
SourceConfigTuner tunerConfig = (SourceConfigTuner)config;
|
||||
|
||||
TunerChannel tunerChannel = tunerConfig.getTunerChannel();
|
||||
|
||||
tunerChannel.setBandwidth( bandwidth );
|
||||
|
||||
Iterator<Tuner> it = mTuners.iterator();
|
||||
|
||||
Tuner tuner;
|
||||
|
||||
while( it.hasNext() && retVal == null )
|
||||
{
|
||||
tuner = it.next();
|
||||
|
||||
try
|
||||
{
|
||||
retVal = tuner.getChannel( tunerChannel );
|
||||
}
|
||||
catch ( RejectedExecutionException ree )
|
||||
{
|
||||
mLog.error( "couldn't provide tuner channel source", ree );
|
||||
}
|
||||
catch ( SourceException e )
|
||||
{
|
||||
mLog.error( "error obtaining channel from tuner [" +
|
||||
tuner.getName() + "]", e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of current tuners
|
||||
*/
|
||||
public List<Tuner> getTuners()
|
||||
{
|
||||
return mTuners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all USB tuners and USB/Mixer tuner devices
|
||||
*/
|
||||
@@ -182,9 +126,19 @@ public class TunerManager
|
||||
if( status.isLoaded() )
|
||||
{
|
||||
Tuner tuner = status.getTuner();
|
||||
sb.append( "] LOADED: " );
|
||||
sb.append( tuner.toString() );
|
||||
mTuners.add( tuner );
|
||||
|
||||
try
|
||||
{
|
||||
mTunerModel.addTuner( tuner );
|
||||
sb.append( "] LOADED: " );
|
||||
sb.append( tuner.toString() );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
sb.append( "] NOT LOADED: " );
|
||||
sb.append( status.getInfo() );
|
||||
sb.append( " Error:" + e.getMessage() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -261,19 +215,12 @@ public class TunerManager
|
||||
try
|
||||
{
|
||||
AirspyTunerController airspyController =
|
||||
new AirspyTunerController( device, mResourceManager.getThreadPoolManager() );
|
||||
new AirspyTunerController( device, mThreadPoolManager );
|
||||
|
||||
airspyController.init();
|
||||
|
||||
AirspyTuner tuner = new AirspyTuner( airspyController );
|
||||
|
||||
TunerConfiguration config = getTunerConfiguration( tuner );
|
||||
|
||||
if( config != null )
|
||||
{
|
||||
tuner.apply( config );
|
||||
}
|
||||
|
||||
return new TunerInitStatus( tuner, "LOADED" );
|
||||
}
|
||||
catch( SourceException se )
|
||||
@@ -292,11 +239,6 @@ public class TunerManager
|
||||
{
|
||||
return new TunerInitStatus( null, "Ettus B100 tuner not currently "
|
||||
+ "supported" );
|
||||
// case ETTUS_USRP_B100:
|
||||
// mTuners.add( new B100Tuner( device ) );
|
||||
// status = sLOADED;
|
||||
// reason = null;
|
||||
// break;
|
||||
}
|
||||
|
||||
private TunerInitStatus initFuncubeProTuner( Device device,
|
||||
@@ -319,13 +261,6 @@ public class TunerManager
|
||||
FCDTuner tuner =
|
||||
new FCDTuner( dataline, controller );
|
||||
|
||||
TunerConfiguration config = getTunerConfiguration( tuner );
|
||||
|
||||
if( config != null )
|
||||
{
|
||||
tuner.apply( config );
|
||||
}
|
||||
|
||||
return new TunerInitStatus( tuner, "LOADED" );
|
||||
}
|
||||
catch ( SourceException e )
|
||||
@@ -364,13 +299,6 @@ public class TunerManager
|
||||
FCDTuner tuner =
|
||||
new FCDTuner( dataline, controller );
|
||||
|
||||
TunerConfiguration config = getTunerConfiguration( tuner );
|
||||
|
||||
if( config != null )
|
||||
{
|
||||
tuner.apply( config );
|
||||
}
|
||||
|
||||
return new TunerInitStatus( tuner, "LOADED" );
|
||||
}
|
||||
catch ( SourceException e )
|
||||
@@ -397,19 +325,12 @@ public class TunerManager
|
||||
{
|
||||
HackRFTunerController hackRFController =
|
||||
new HackRFTunerController( device, descriptor,
|
||||
mResourceManager.getThreadPoolManager() );
|
||||
mThreadPoolManager );
|
||||
|
||||
hackRFController.init();
|
||||
|
||||
HackRFTuner tuner = new HackRFTuner( hackRFController );
|
||||
|
||||
TunerConfiguration config = getTunerConfiguration( tuner );
|
||||
|
||||
if( config != null )
|
||||
{
|
||||
tuner.apply( config );
|
||||
}
|
||||
|
||||
return new TunerInitStatus( tuner, "LOADED" );
|
||||
}
|
||||
catch( SourceException se )
|
||||
@@ -449,21 +370,13 @@ public class TunerManager
|
||||
{
|
||||
E4KTunerController controller =
|
||||
new E4KTunerController( device, deviceDescriptor,
|
||||
mResourceManager.getThreadPoolManager() );
|
||||
mThreadPoolManager );
|
||||
|
||||
controller.init();
|
||||
|
||||
RTL2832Tuner rtlTuner =
|
||||
new RTL2832Tuner( tunerClass, controller );
|
||||
|
||||
TunerConfiguration config =
|
||||
getTunerConfiguration( rtlTuner );
|
||||
|
||||
if( config != null )
|
||||
{
|
||||
rtlTuner.apply( config );
|
||||
}
|
||||
|
||||
return new TunerInitStatus( rtlTuner, "LOADED" );
|
||||
}
|
||||
catch( SourceException se )
|
||||
@@ -476,21 +389,13 @@ public class TunerManager
|
||||
{
|
||||
R820TTunerController controller =
|
||||
new R820TTunerController( device, deviceDescriptor,
|
||||
mResourceManager.getThreadPoolManager() );
|
||||
mThreadPoolManager );
|
||||
|
||||
controller.init();
|
||||
|
||||
RTL2832Tuner rtlTuner =
|
||||
new RTL2832Tuner( tunerClass, controller );
|
||||
|
||||
TunerConfiguration config =
|
||||
getTunerConfiguration( rtlTuner );
|
||||
|
||||
if( config != null )
|
||||
{
|
||||
rtlTuner.apply( config );
|
||||
}
|
||||
|
||||
return new TunerInitStatus( rtlTuner, "LOADED" );
|
||||
}
|
||||
catch( SourceException se )
|
||||
@@ -513,55 +418,6 @@ public class TunerManager
|
||||
|
||||
return new TunerInitStatus( null, reason );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a stored tuner configuration or create a default tuner configuration
|
||||
* for the tuner type, connected at the address.
|
||||
*
|
||||
* Note: a named tuner configuration will be stored for for each tuner type
|
||||
* and address combination.
|
||||
* @param type - tuner type
|
||||
* @param address - current usb address/port
|
||||
* @return - stored tuner configuration or default configuration
|
||||
*/
|
||||
private TunerConfiguration getTunerConfiguration( Tuner tuner )
|
||||
{
|
||||
TunerConfigurationAssignment selected = mResourceManager
|
||||
.getSettingsManager().getSelectedTunerConfiguration(
|
||||
tuner.getTunerType(), tuner.getUniqueID() );
|
||||
|
||||
ArrayList<TunerConfiguration> configs = mResourceManager
|
||||
.getSettingsManager().getTunerConfigurations( tuner.getTunerType() );
|
||||
|
||||
TunerConfiguration config = null;
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
for( TunerConfiguration tunerConfig: configs )
|
||||
{
|
||||
if( tunerConfig.getName().contentEquals( selected.getTunerConfigurationName() ) )
|
||||
{
|
||||
config = tunerConfig;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//If we're still null at this point, create a default config
|
||||
if( config == null )
|
||||
{
|
||||
String name = "Default-" + tuner.getUniqueID();
|
||||
|
||||
config = mResourceManager.getSettingsManager()
|
||||
.addNewTunerConfiguration( tuner.getTunerType(), name );
|
||||
}
|
||||
|
||||
//Persist the config as the selected tuner configuration. The method
|
||||
//auto-saves the setting
|
||||
mResourceManager.getSettingsManager().setSelectedTunerConfiguration(
|
||||
tuner.getTunerType(), tuner.getUniqueID(), config );
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the first tuner mixer dataline that corresponds to the tuner class.
|
||||
@@ -577,7 +433,7 @@ public class TunerManager
|
||||
private MixerTunerDataLine getMixerTunerDataLine( TunerType tunerClass )
|
||||
{
|
||||
Collection<MixerTunerDataLine> datalines =
|
||||
MixerManager.getInstance().getMixerTunerDataLines();
|
||||
mMixerManager.getMixerTunerDataLines();
|
||||
|
||||
for( MixerTunerDataLine mixerTDL: datalines )
|
||||
{
|
||||
|
||||
297
src/source/tuner/TunerModel.java
Normal file
297
src/source/tuner/TunerModel.java
Normal file
@@ -0,0 +1,297 @@
|
||||
package source.tuner;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.Listener;
|
||||
import source.Source;
|
||||
import source.SourceException;
|
||||
import source.config.SourceConfigTuner;
|
||||
import source.tuner.TunerEvent.Event;
|
||||
import source.tuner.configuration.TunerConfiguration;
|
||||
import source.tuner.configuration.TunerConfigurationModel;
|
||||
|
||||
public class TunerModel extends AbstractTableModel implements Listener<TunerEvent>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final static Logger mLog = LoggerFactory.getLogger( TunerModel.class );
|
||||
|
||||
public static final int TUNER_TYPE = 0;
|
||||
public static final int TUNER_ID = 1;
|
||||
public static final int SAMPLE_RATE = 2;
|
||||
public static final int FREQUENCY = 3;
|
||||
public static final int CHANNEL_COUNT = 4;
|
||||
public static final int SPECTRAL_DISPLAY_MAIN = 5;
|
||||
public static final int SPECTRAL_DISPLAY_NEW = 6;
|
||||
|
||||
private static final String MHZ = " MHz";
|
||||
private static final String[] COLUMNS =
|
||||
{ "Tuner", "ID", "Sample Rate", "Frequency", "Channels", "Spectral", "Display" };
|
||||
|
||||
private List<Tuner> mTuners = new ArrayList<>();
|
||||
private List<Listener<TunerEvent>> mTunerEventListeners = new ArrayList<>();
|
||||
private DecimalFormat mFrequencyFormat = new DecimalFormat( "0.00000" );
|
||||
private DecimalFormat mSampleRateFormat = new DecimalFormat( "0.000" );
|
||||
|
||||
private TunerConfigurationModel mTunerConfigurationModel;
|
||||
|
||||
public TunerModel( TunerConfigurationModel tunerConfigurationModel )
|
||||
{
|
||||
mTunerConfigurationModel = tunerConfigurationModel;
|
||||
}
|
||||
|
||||
public TunerConfigurationModel getTunerConfigurationModel()
|
||||
{
|
||||
return mTunerConfigurationModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of Tuners currently in the model
|
||||
*/
|
||||
public List<Tuner> getTuners()
|
||||
{
|
||||
return mTuners;
|
||||
}
|
||||
|
||||
public Tuner getTuner( int index )
|
||||
{
|
||||
if( index < mTuners.size() )
|
||||
{
|
||||
return mTuners.get( index );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addTuners( List<Tuner> Tuners )
|
||||
{
|
||||
for( Tuner tuner: Tuners )
|
||||
{
|
||||
addTuner( tuner );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the Tuner to this model
|
||||
*/
|
||||
public void addTuner( Tuner tuner )
|
||||
{
|
||||
if( !mTuners.contains( tuner ) )
|
||||
{
|
||||
//Get the tuner configuration and apply it to the tuner - this
|
||||
//call should always produce a tuner configuration
|
||||
TunerConfiguration config = mTunerConfigurationModel
|
||||
.getTunerConfiguration( tuner.getTunerType(), tuner.getUniqueID() );
|
||||
|
||||
try
|
||||
{
|
||||
tuner.getTunerController().apply( config );
|
||||
|
||||
mTuners.add( tuner );
|
||||
|
||||
int index = mTuners.indexOf( tuner );
|
||||
|
||||
fireTableRowsInserted( index, index );
|
||||
|
||||
tuner.addTunerChangeListener( this );
|
||||
}
|
||||
catch( SourceException se )
|
||||
{
|
||||
mLog.error( "Couldn't apply tuner configuration to tuner - ["
|
||||
+ tuner.getTunerType().name() + "] with id ["
|
||||
+ tuner.getUniqueID() + "] - tuner will not be included" );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the Tuner from this model
|
||||
*/
|
||||
public void removeTuner( Tuner tuner )
|
||||
{
|
||||
if( mTuners.contains( tuner ) )
|
||||
{
|
||||
tuner.removeTunerChangeListener( this );
|
||||
|
||||
int index = mTuners.indexOf( tuner );
|
||||
|
||||
mTuners.remove( tuner );
|
||||
|
||||
fireTableRowsDeleted( index, index );
|
||||
}
|
||||
}
|
||||
|
||||
public void addListener( Listener<TunerEvent> listener )
|
||||
{
|
||||
mTunerEventListeners.add( listener );
|
||||
}
|
||||
|
||||
public void removeListener( Listener<TunerEvent> listener )
|
||||
{
|
||||
mTunerEventListeners.remove( listener );
|
||||
}
|
||||
|
||||
public void broadcast( TunerEvent event )
|
||||
{
|
||||
for( Listener<TunerEvent> listener: mTunerEventListeners )
|
||||
{
|
||||
listener.receive( event );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests to display the first tuner in this model. Invoke this method
|
||||
* after all listeners have registered and tuners have been added to this
|
||||
* model, in order to inform the primary display to use the first tuner.
|
||||
*/
|
||||
public void requestFirstTunerDisplay()
|
||||
{
|
||||
if( mTuners.size() > 0 )
|
||||
{
|
||||
broadcast( new TunerEvent( mTuners.get( 0 ),
|
||||
Event.REQUEST_MAIN_SPECTRAL_DISPLAY ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( TunerEvent event )
|
||||
{
|
||||
if( event.getTuner() != null )
|
||||
{
|
||||
int index = mTuners.indexOf( event.getTuner() );
|
||||
|
||||
if( index >= 0 )
|
||||
{
|
||||
switch( event.getEvent() )
|
||||
{
|
||||
case CHANNEL_COUNT:
|
||||
fireTableCellUpdated( index, CHANNEL_COUNT );
|
||||
break;
|
||||
case FREQUENCY:
|
||||
fireTableCellUpdated( index, FREQUENCY );
|
||||
break;
|
||||
case SAMPLE_RATE:
|
||||
fireTableCellUpdated( index, SAMPLE_RATE );
|
||||
break;
|
||||
case REQUEST_MAIN_SPECTRAL_DISPLAY:
|
||||
fireTableCellUpdated( index, SPECTRAL_DISPLAY_MAIN );
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
broadcast( event );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowCount()
|
||||
{
|
||||
return mTuners.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount()
|
||||
{
|
||||
return COLUMNS.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValueAt( int rowIndex, int columnIndex )
|
||||
{
|
||||
if( rowIndex < mTuners.size() )
|
||||
{
|
||||
Tuner tuner = mTuners.get( rowIndex );
|
||||
|
||||
switch( columnIndex )
|
||||
{
|
||||
case TUNER_TYPE:
|
||||
return tuner.getTunerType().getLabel();
|
||||
case TUNER_ID:
|
||||
return tuner.getUniqueID();
|
||||
case SAMPLE_RATE:
|
||||
int sampleRate = tuner.getTunerController().getSampleRate();
|
||||
|
||||
return mSampleRateFormat.format( sampleRate / 1E6D ) + MHZ;
|
||||
case FREQUENCY:
|
||||
try
|
||||
{
|
||||
long frequency = tuner.getTunerController().getFrequency();
|
||||
|
||||
return mFrequencyFormat.format( frequency / 1E6D ) + MHZ;
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
case CHANNEL_COUNT:
|
||||
return tuner.getTunerController().getChannelCount();
|
||||
case SPECTRAL_DISPLAY_MAIN:
|
||||
return "Main";
|
||||
case SPECTRAL_DISPLAY_NEW:
|
||||
return "New";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnName( int columnIndex )
|
||||
{
|
||||
return COLUMNS[ columnIndex ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates current tuners to get a tuner channel source for the frequency
|
||||
* specified in the channel config's source config object.
|
||||
*
|
||||
* Returns null if no tuner can source the channel
|
||||
*/
|
||||
public Source getSource( SourceConfigTuner config, int bandwidth )
|
||||
{
|
||||
TunerChannelSource retVal = null;
|
||||
|
||||
TunerChannel tunerChannel = config.getTunerChannel();
|
||||
|
||||
tunerChannel.setBandwidth( bandwidth );
|
||||
|
||||
Iterator<Tuner> it = mTuners.iterator();
|
||||
|
||||
Tuner tuner;
|
||||
|
||||
while( it.hasNext() && retVal == null )
|
||||
{
|
||||
tuner = it.next();
|
||||
|
||||
try
|
||||
{
|
||||
retVal = tuner.getChannel( tunerChannel );
|
||||
}
|
||||
catch ( RejectedExecutionException ree )
|
||||
{
|
||||
mLog.error( "couldn't provide tuner channel source", ree );
|
||||
}
|
||||
catch ( SourceException e )
|
||||
{
|
||||
mLog.error( "error obtaining channel from tuner [" +
|
||||
tuner.getName() + "]", e );
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.tuner;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.frequency.FrequencyChangeEvent;
|
||||
import source.tuner.frequency.FrequencyChangeListener;
|
||||
import spectrum.SpectrumFrame;
|
||||
import controller.BaseNode;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class TunerNode extends BaseNode implements FrequencyChangeListener
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( TunerNode.class );
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static DecimalFormat FREQUENCY_FORMAT = new DecimalFormat( "0.00000" );
|
||||
private static DecimalFormat SAMPLE_RATE_FORMAT = new DecimalFormat( "0.000" );
|
||||
|
||||
private long mFrequency;
|
||||
private int mSampleRate;
|
||||
|
||||
public TunerNode( Tuner tuner )
|
||||
{
|
||||
super( tuner ); //does this make it a super tuner?
|
||||
|
||||
tuner.addListener( this );
|
||||
|
||||
try
|
||||
{
|
||||
mFrequency = tuner.getFrequency();
|
||||
mSampleRate = tuner.getSampleRate();
|
||||
}
|
||||
catch ( SourceException e )
|
||||
{
|
||||
mLog.error( "TunerNode - error reading frequency and sample rate "
|
||||
+ "from tuner", e );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JPanel getEditor()
|
||||
{
|
||||
return getTuner().getEditor( getModel().getResourceManager() );
|
||||
}
|
||||
|
||||
public Tuner getTuner()
|
||||
{
|
||||
return (Tuner)getUserObject();
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getTuner().getName() );
|
||||
|
||||
sb.append( " " );
|
||||
sb.append( FREQUENCY_FORMAT.format( (double)mFrequency / 1E6d ) );
|
||||
sb.append( " [" );
|
||||
sb.append( SAMPLE_RATE_FORMAT.format( (double)mSampleRate / 1E6d ) );
|
||||
sb.append( "] MHz" );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public JPopupMenu getContextMenu()
|
||||
{
|
||||
JPopupMenu retVal = new JPopupMenu();
|
||||
|
||||
JMenuItem showSpectrumItem = new JMenuItem( "Show in Main Spectrum" );
|
||||
showSpectrumItem.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
getModel().fireTunerSelectedEvent( getTuner() );
|
||||
}
|
||||
} );
|
||||
|
||||
retVal.add( showSpectrumItem );
|
||||
|
||||
JMenuItem newSpectrumItem = new JMenuItem( "New Spectrum Window" );
|
||||
newSpectrumItem.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
ResourceManager rm = getModel().getResourceManager();
|
||||
|
||||
SpectrumFrame frame = new SpectrumFrame( rm.getChannelManager(),
|
||||
rm.getController(), rm.getPlaylistManager(),
|
||||
rm.getSettingsManager(), getTuner() );
|
||||
}
|
||||
} );
|
||||
|
||||
retVal.add( newSpectrumItem );
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
switch( event.getEvent() )
|
||||
{
|
||||
case FREQUENCY_CHANGE_NOTIFICATION:
|
||||
long frequency = event.getValue().longValue();
|
||||
|
||||
if( mFrequency != frequency )
|
||||
{
|
||||
mFrequency = frequency;
|
||||
getModel().nodeChanged( TunerNode.this );
|
||||
}
|
||||
break;
|
||||
case SAMPLE_RATE_CHANGE_NOTIFICATION:
|
||||
int sampleRate = event.getValue().intValue();
|
||||
|
||||
if( mSampleRate != sampleRate )
|
||||
{
|
||||
mSampleRate = sampleRate;
|
||||
getModel().nodeChanged( TunerNode.this );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.tuner;
|
||||
|
||||
public interface TunerSelectionListener
|
||||
{
|
||||
public void tunerSelected( Tuner tuner );
|
||||
}
|
||||
95
src/source/tuner/TunerSourceEditor.java
Normal file
95
src/source/tuner/TunerSourceEditor.java
Normal file
@@ -0,0 +1,95 @@
|
||||
/*******************************************************************************
|
||||
* 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 source.tuner;
|
||||
|
||||
import gui.control.JFrequencyControl;
|
||||
import gui.editor.Editor;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import source.config.SourceConfigTuner;
|
||||
import source.config.SourceConfiguration;
|
||||
import source.tuner.frequency.FrequencyChangeEvent;
|
||||
import source.tuner.frequency.IFrequencyChangeProcessor;
|
||||
import controller.channel.Channel;
|
||||
|
||||
public class TunerSourceEditor extends Editor<Channel>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private JFrequencyControl mFrequencyControl;
|
||||
|
||||
public TunerSourceEditor()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "insets 0 0 0 0", "[left]", "" ) );
|
||||
mFrequencyControl = new JFrequencyControl();
|
||||
mFrequencyControl.setEnabled( false );
|
||||
mFrequencyControl.addListener( new IFrequencyChangeProcessor()
|
||||
{
|
||||
@Override
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
setModified( true );
|
||||
}
|
||||
} );
|
||||
add( mFrequencyControl );
|
||||
}
|
||||
|
||||
public void save()
|
||||
{
|
||||
if( hasItem() && isModified() )
|
||||
{
|
||||
SourceConfigTuner config = new SourceConfigTuner();
|
||||
config.setFrequency( mFrequencyControl.getFrequency() );
|
||||
getItem().setSourceConfiguration( config );
|
||||
}
|
||||
|
||||
setModified( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem( Channel item )
|
||||
{
|
||||
super.setItem( item );
|
||||
|
||||
if( hasItem() )
|
||||
{
|
||||
SourceConfiguration config = getItem().getSourceConfiguration();
|
||||
|
||||
mFrequencyControl.setEnabled( true );
|
||||
|
||||
if( config instanceof SourceConfigTuner )
|
||||
{
|
||||
mFrequencyControl.setFrequency( ((SourceConfigTuner)config).getFrequency(), false );
|
||||
setModified( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
mFrequencyControl.setFrequency( 101000000, false );
|
||||
setModified( true );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mFrequencyControl.setEnabled( false );
|
||||
setModified( false );
|
||||
}
|
||||
}
|
||||
}
|
||||
55
src/source/tuner/TunerSpectralDisplayManager.java
Normal file
55
src/source/tuner/TunerSpectralDisplayManager.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package source.tuner;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
|
||||
import sample.Listener;
|
||||
import settings.SettingsManager;
|
||||
import spectrum.SpectralDisplayPanel;
|
||||
import spectrum.SpectrumFrame;
|
||||
import controller.channel.ChannelModel;
|
||||
import controller.channel.ChannelProcessingManager;
|
||||
|
||||
public class TunerSpectralDisplayManager implements Listener<TunerEvent>
|
||||
{
|
||||
private SpectralDisplayPanel mSpectralDisplayPanel;
|
||||
private ChannelModel mChannelModel;
|
||||
private ChannelProcessingManager mChannelProcessingManager;
|
||||
private SettingsManager mSettingsManager;
|
||||
|
||||
public TunerSpectralDisplayManager( SpectralDisplayPanel panel,
|
||||
ChannelModel channelModel,
|
||||
ChannelProcessingManager channelProcessingManager,
|
||||
SettingsManager settingsManager )
|
||||
{
|
||||
mSpectralDisplayPanel = panel;
|
||||
mChannelModel = channelModel;
|
||||
mChannelProcessingManager = channelProcessingManager;
|
||||
mSettingsManager = settingsManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( TunerEvent event )
|
||||
{
|
||||
switch( event.getEvent() )
|
||||
{
|
||||
case REQUEST_MAIN_SPECTRAL_DISPLAY:
|
||||
mSpectralDisplayPanel.showTuner( event.getTuner() );
|
||||
break;
|
||||
case REQUEST_NEW_SPECTRAL_DISPLAY:
|
||||
final SpectrumFrame frame = new SpectrumFrame( mChannelModel,
|
||||
mChannelProcessingManager, mSettingsManager, event.getTuner() );
|
||||
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
frame.setVisible( true );
|
||||
}
|
||||
} );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ package source.tuner;
|
||||
|
||||
public enum TunerType
|
||||
{
|
||||
AIRSPY_R820T( "R820T" ),
|
||||
AIRSPY_R820T( "Airspy R820T" ),
|
||||
ELONICS_E4000( "E4000" ),
|
||||
ETTUS_WBX( "WBX" ),
|
||||
ETTUS_VARIOUS( "Ettus Tuner" ),
|
||||
|
||||
178
src/source/tuner/TunerViewPanel.java
Normal file
178
src/source/tuner/TunerViewPanel.java
Normal file
@@ -0,0 +1,178 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 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 source.tuner;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.RowSorter;
|
||||
import javax.swing.SortOrder;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import javax.swing.table.TableRowSorter;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.tuner.TunerEvent.Event;
|
||||
|
||||
import com.jidesoft.swing.JideSplitPane;
|
||||
|
||||
public class TunerViewPanel extends JPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final static Logger mLog = LoggerFactory.getLogger( TunerViewPanel.class );
|
||||
|
||||
private TunerModel mTunerModel;
|
||||
private JTable mTunerTable;
|
||||
private TableRowSorter<TunerModel> mRowSorter;
|
||||
private JideSplitPane mSplitPane;
|
||||
private TunerEditor mTunerEditor;
|
||||
|
||||
public TunerViewPanel( TunerModel tunerModel )
|
||||
{
|
||||
mTunerModel = tunerModel;
|
||||
mTunerEditor = new TunerEditor( mTunerModel.getTunerConfigurationModel() );
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "insets 0 0 0 0", "[fill,grow]", "[fill,grow]" ) );
|
||||
|
||||
mRowSorter = new TableRowSorter<>( mTunerModel );
|
||||
List<RowSorter.SortKey> sortKeys = new ArrayList<>();
|
||||
sortKeys.add( new RowSorter.SortKey( TunerModel.TUNER_TYPE, SortOrder.ASCENDING ) );
|
||||
sortKeys.add( new RowSorter.SortKey( TunerModel.TUNER_ID, SortOrder.ASCENDING ) );
|
||||
mRowSorter.setSortKeys( sortKeys );
|
||||
|
||||
mTunerTable = new JTable( mTunerModel );
|
||||
mTunerTable.setRowSorter( mRowSorter );
|
||||
mTunerTable.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
|
||||
mTunerTable.getSelectionModel().addListSelectionListener( new ListSelectionListener()
|
||||
{
|
||||
@Override
|
||||
public void valueChanged( ListSelectionEvent event )
|
||||
{
|
||||
if( !event.getValueIsAdjusting() )
|
||||
{
|
||||
int row = mTunerTable.getSelectedRow();
|
||||
int modelRow = mTunerTable.convertRowIndexToModel( row );
|
||||
|
||||
mTunerEditor.setItem( mTunerModel.getTuner( modelRow ) );
|
||||
}
|
||||
}
|
||||
} );
|
||||
mTunerTable.addMouseListener( new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked( MouseEvent e )
|
||||
{
|
||||
int column = mTunerTable.columnAtPoint( e.getPoint() );
|
||||
|
||||
if( column == TunerModel.SPECTRAL_DISPLAY_MAIN )
|
||||
{
|
||||
int tableRow = mTunerTable.rowAtPoint( e.getPoint() );
|
||||
int modelRow = mTunerTable.convertRowIndexToModel( tableRow );
|
||||
|
||||
Tuner tuner = mTunerModel.getTuner( modelRow );
|
||||
|
||||
if( tuner != null )
|
||||
{
|
||||
mTunerModel.broadcast( new TunerEvent( tuner,
|
||||
Event.REQUEST_MAIN_SPECTRAL_DISPLAY ) );
|
||||
}
|
||||
}
|
||||
else if( column == TunerModel.SPECTRAL_DISPLAY_NEW )
|
||||
{
|
||||
int tableRow = mTunerTable.rowAtPoint( e.getPoint() );
|
||||
int modelRow = mTunerTable.convertRowIndexToModel( tableRow );
|
||||
|
||||
Tuner tuner = mTunerModel.getTuner( modelRow );
|
||||
|
||||
if( tuner != null )
|
||||
{
|
||||
mTunerModel.broadcast( new TunerEvent( tuner,
|
||||
Event.REQUEST_NEW_SPECTRAL_DISPLAY ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
TableCellRenderer renderer = new LinkCellRenderer();
|
||||
|
||||
mTunerTable.getColumnModel().getColumn( 5 ).setCellRenderer( renderer );
|
||||
mTunerTable.getColumnModel().getColumn( 6 ).setCellRenderer( renderer );
|
||||
|
||||
JScrollPane listScroller = new JScrollPane( mTunerTable );
|
||||
listScroller.setPreferredSize( new Dimension( 400, 20 ) );
|
||||
|
||||
JScrollPane editorScroller = new JScrollPane( mTunerEditor );
|
||||
editorScroller.setPreferredSize( new Dimension( 400, 80 ) );
|
||||
|
||||
mSplitPane = new JideSplitPane();
|
||||
mSplitPane.setOrientation( JideSplitPane.VERTICAL_SPLIT );
|
||||
mSplitPane.add( listScroller );
|
||||
mSplitPane.add( editorScroller );
|
||||
|
||||
add( mSplitPane );
|
||||
}
|
||||
|
||||
public class LinkCellRenderer extends DefaultTableCellRenderer
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent( JTable table,
|
||||
Object value, boolean isSelected, boolean hasFocus, int row,
|
||||
int column )
|
||||
{
|
||||
JLabel label = (JLabel)super.getTableCellRendererComponent( table,
|
||||
value, isSelected, hasFocus, row, column );
|
||||
|
||||
label.setForeground( Color.BLUE.brighter() );
|
||||
|
||||
if( column == TunerModel.SPECTRAL_DISPLAY_MAIN )
|
||||
{
|
||||
label.setToolTipText( "Show this tuner in the main spectral display" );
|
||||
}
|
||||
else if( column == TunerModel.SPECTRAL_DISPLAY_NEW )
|
||||
{
|
||||
label.setToolTipText( "Show this tuner in a new spectral display" );
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
package source.tuner.airspy;
|
||||
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2015 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
public class AirspyInformationPanel extends JPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private AirspyTunerController mController;
|
||||
|
||||
/**
|
||||
* Displays Airspy firmware, serial number and part identifier
|
||||
*/
|
||||
public AirspyInformationPanel( AirspyTunerController controller )
|
||||
{
|
||||
mController = controller;
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 2",
|
||||
"[right,grow][grow]",
|
||||
"[][][][][grow]" ) );
|
||||
|
||||
AirspyDeviceInformation info = mController.getDeviceInfo();
|
||||
|
||||
add( new JLabel( "Serial:" ) );
|
||||
add( new JLabel( info.getSerialNumber() ) );
|
||||
add( new JLabel( "Firmware:" ) );
|
||||
|
||||
//Split the firmware on spaces and use first value -- expose full
|
||||
//string in a tool tip
|
||||
String[] firmware = info.getVersion().split( " " );
|
||||
|
||||
JLabel firmwareLabel;
|
||||
|
||||
if( firmware.length > 1 )
|
||||
{
|
||||
firmwareLabel = new JLabel( firmware[ 0 ] );
|
||||
}
|
||||
else
|
||||
{
|
||||
firmwareLabel = new JLabel( info.getVersion() );
|
||||
}
|
||||
|
||||
firmwareLabel.setToolTipText( info.getVersion() );
|
||||
|
||||
add( firmwareLabel );
|
||||
add( new JLabel( "Part:" ) );
|
||||
add( new JLabel( info.getPartNumber() ) );
|
||||
add( new JLabel( "Board ID:" ) );
|
||||
add( new JLabel( info.getBoardID().getLabel() ) );
|
||||
}
|
||||
}
|
||||
@@ -18,15 +18,10 @@ package source.tuner.airspy;
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.adapter.ISampleAdapter;
|
||||
|
||||
public class AirspySampleAdapter implements ISampleAdapter
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( AirspySampleAdapter.class );
|
||||
|
||||
private static final float SCALE_SIGNED_12_BIT_TO_FLOAT = 1.0f / 2048.0f;
|
||||
|
||||
private boolean mSamplePacking = false;
|
||||
|
||||
@@ -19,8 +19,6 @@ package source.tuner.airspy;
|
||||
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -31,44 +29,22 @@ import source.tuner.Tuner;
|
||||
import source.tuner.TunerChannel;
|
||||
import source.tuner.TunerChannelSource;
|
||||
import source.tuner.TunerClass;
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerEvent;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.airspy.AirspyTunerController.BoardID;
|
||||
import controller.ResourceManager;
|
||||
import controller.ThreadPoolManager;
|
||||
|
||||
public class AirspyTuner extends Tuner
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( AirspyTuner.class );
|
||||
|
||||
AirspyTunerController mController;
|
||||
|
||||
public AirspyTuner( AirspyTunerController controller )
|
||||
{
|
||||
super( "Airspy" );
|
||||
|
||||
mController = controller;
|
||||
|
||||
/* Register for frequency/sample rate changes so that we can rebroadcast
|
||||
* to any registered listeners */
|
||||
mController.addListener( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public JPanel getEditor( ResourceManager resourceManager )
|
||||
{
|
||||
return new AirspyTunerEditorPanel( this, resourceManager );
|
||||
super( "Airspy " + controller.getDeviceInfo().getSerialNumber(), controller );
|
||||
}
|
||||
|
||||
public AirspyTunerController getController()
|
||||
{
|
||||
return mController;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply( TunerConfiguration config ) throws SourceException
|
||||
{
|
||||
mController.apply( config );
|
||||
return (AirspyTunerController)getTunerController();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -76,11 +52,11 @@ public class AirspyTuner extends Tuner
|
||||
{
|
||||
try
|
||||
{
|
||||
return mController.getDeviceInfo().getSerialNumber();
|
||||
return getController().getDeviceInfo().getSerialNumber();
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
mLog.error( "error gettting serial number", e );
|
||||
mLog.error( "error getting serial number", e );
|
||||
}
|
||||
|
||||
return BoardID.AIRSPY.getLabel();
|
||||
@@ -98,35 +74,12 @@ public class AirspyTuner extends Tuner
|
||||
return TunerType.AIRSPY_R820T;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSampleRate()
|
||||
{
|
||||
int rate = 0;
|
||||
|
||||
try
|
||||
{
|
||||
rate = mController.getCurrentSampleRate();
|
||||
}
|
||||
catch ( SourceException e )
|
||||
{
|
||||
mLog.error( "Error while getting sample rate from controller", e );
|
||||
}
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getSampleSize()
|
||||
{
|
||||
return 13.0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFrequency() throws SourceException
|
||||
{
|
||||
return mController.getFrequency();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TunerChannelSource getChannel( TunerChannel channel )
|
||||
throws RejectedExecutionException, SourceException
|
||||
@@ -138,9 +91,16 @@ public class AirspyTuner extends Tuner
|
||||
//Consider implementing a fractional resampler to get a correct 48 kHz
|
||||
//output sample rate
|
||||
|
||||
return mController.getChannel( this, channel );
|
||||
}
|
||||
TunerChannelSource source = getController().getChannel( this, channel );
|
||||
|
||||
if( source != null )
|
||||
{
|
||||
broadcast( new TunerEvent( this, TunerEvent.Event.CHANNEL_COUNT ) );
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseChannel( TunerChannelSource source )
|
||||
{
|
||||
@@ -150,19 +110,19 @@ public class AirspyTuner extends Tuner
|
||||
/* Tell the controller to release the channel and cleanup */
|
||||
if( source != null )
|
||||
{
|
||||
mController.releaseChannel( source );
|
||||
getController().releaseChannel( source );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener( Listener<ComplexBuffer> listener )
|
||||
{
|
||||
mController.addListener( listener );
|
||||
getController().addListener( listener );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener( Listener<ComplexBuffer> listener )
|
||||
{
|
||||
mController.removeListener( listener );
|
||||
getController().removeListener( listener );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,9 @@ package source.tuner.airspy;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.airspy.AirspyTunerController.Gain;
|
||||
import source.tuner.configuration.TunerConfiguration;
|
||||
|
||||
public class AirspyTunerConfiguration extends TunerConfiguration
|
||||
{
|
||||
@@ -30,6 +30,7 @@ public class AirspyTunerConfiguration extends TunerConfiguration
|
||||
private int mIFGain = AirspyTunerController.IF_GAIN_DEFAULT;
|
||||
private int mMixerGain = AirspyTunerController.MIXER_GAIN_DEFAULT;
|
||||
private int mLNAGain = AirspyTunerController.LNA_GAIN_DEFAULT;
|
||||
private double mFrequencyCorrection = 0.0d;
|
||||
|
||||
private boolean mMixerAGC = false;
|
||||
private boolean mLNAAGC = false;
|
||||
@@ -39,12 +40,11 @@ public class AirspyTunerConfiguration extends TunerConfiguration
|
||||
*/
|
||||
public AirspyTunerConfiguration()
|
||||
{
|
||||
this( "Default" );
|
||||
}
|
||||
|
||||
public AirspyTunerConfiguration( String name )
|
||||
public AirspyTunerConfiguration( String uniqueID, String name )
|
||||
{
|
||||
super( name );
|
||||
super( uniqueID, name );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -129,4 +129,16 @@ public class AirspyTunerConfiguration extends TunerConfiguration
|
||||
{
|
||||
mLNAAGC = enabled;
|
||||
}
|
||||
|
||||
@XmlAttribute( name = "frequency_correction" )
|
||||
public double getFrequencyCorrection()
|
||||
{
|
||||
return mFrequencyCorrection;
|
||||
}
|
||||
|
||||
public void setFrequencyCorrection( double value )
|
||||
{
|
||||
mFrequencyCorrection = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,705 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.tuner.airspy;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.ComboBoxModel;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.JSlider;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.usb.UsbException;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.usb4java.LibUsbException;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerConfigurationAssignment;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.airspy.AirspyTunerController.Gain;
|
||||
import source.tuner.airspy.AirspyTunerController.GainMode;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class AirspyTunerConfigurationPanel extends JPanel
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( AirspyTunerConfigurationPanel.class );
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private ResourceManager mResourceManager;
|
||||
private AirspyTunerController mController;
|
||||
private AirspyTunerConfiguration mSelectedConfig;
|
||||
|
||||
private JButton mNewConfiguration;
|
||||
private JButton mDeleteConfiguration;
|
||||
private JComboBox<AirspyTunerConfiguration> mComboConfigurations;
|
||||
|
||||
private JTextField mName;
|
||||
|
||||
private JComboBox<AirspySampleRate> mSampleRateCombo;
|
||||
|
||||
private JComboBox<GainMode> mGainModeCombo;
|
||||
private JLabel mGainLabel;
|
||||
private JLabel mGainFillerLabel;
|
||||
private JLabel mGainValueLabel;
|
||||
private JSlider mGain;
|
||||
|
||||
private JLabel mIFGainLabel;
|
||||
private JLabel mIFGainFillerLabel;
|
||||
private JLabel mIFGainValueLabel;
|
||||
private JSlider mIFGain;
|
||||
|
||||
private JLabel mLNAGainLabel;
|
||||
private JCheckBox mLNAAGC;
|
||||
private JLabel mLNAGainValueLabel;
|
||||
private JSlider mLNAGain;
|
||||
|
||||
private JLabel mMixerGainValueLabel;
|
||||
private JCheckBox mMixerAGC;
|
||||
private JLabel mMixerGainLabel;
|
||||
private JSlider mMixerGain;
|
||||
|
||||
|
||||
public AirspyTunerConfigurationPanel( ResourceManager resourceManager,
|
||||
AirspyTunerController controller )
|
||||
{
|
||||
mResourceManager = resourceManager;
|
||||
mController = controller;
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the gui components
|
||||
*/
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 4", "[left][grow][grow][right]",
|
||||
"[][][][][][][grow]" ) );
|
||||
|
||||
/**
|
||||
* Tuner configuration selector
|
||||
*/
|
||||
mComboConfigurations = new JComboBox<AirspyTunerConfiguration>();
|
||||
|
||||
mComboConfigurations.setModel( getModel() );
|
||||
|
||||
/* Determine which tuner configuration should be selected/displayed */
|
||||
TunerConfigurationAssignment savedConfig = null;
|
||||
String serial = null;
|
||||
|
||||
serial = mController.getDeviceInfo().getSerialNumber();
|
||||
|
||||
if( serial != null )
|
||||
{
|
||||
savedConfig = mResourceManager
|
||||
.getSettingsManager().getSelectedTunerConfiguration(
|
||||
TunerType.AIRSPY_R820T, serial );
|
||||
}
|
||||
|
||||
if( savedConfig != null )
|
||||
{
|
||||
mSelectedConfig = getNamedConfiguration(
|
||||
savedConfig.getTunerConfigurationName() );
|
||||
}
|
||||
|
||||
/* If we couldn't determine the saved/selected config, use the first one */
|
||||
if( mSelectedConfig == null )
|
||||
{
|
||||
mSelectedConfig = mComboConfigurations.getItemAt( 0 );
|
||||
|
||||
//Store this config as the default for this tuner at this address
|
||||
|
||||
if( serial != null )
|
||||
{
|
||||
mResourceManager.getSettingsManager()
|
||||
.setSelectedTunerConfiguration( TunerType.AIRSPY_R820T,
|
||||
serial, mSelectedConfig );
|
||||
}
|
||||
}
|
||||
|
||||
mComboConfigurations.setSelectedItem( mSelectedConfig );
|
||||
|
||||
mComboConfigurations.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
AirspyTunerConfiguration selected =
|
||||
(AirspyTunerConfiguration)mComboConfigurations
|
||||
.getItemAt( mComboConfigurations.getSelectedIndex() );
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
update( selected );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
add( new JLabel( "Config:" ) );
|
||||
add( mComboConfigurations, "span,growx,push" );
|
||||
|
||||
add( new JSeparator(), "span,growx,push" );
|
||||
|
||||
|
||||
/**
|
||||
* Tuner Configuration Name
|
||||
*/
|
||||
mName = new JTextField();
|
||||
mName.setText( mSelectedConfig.getName() );
|
||||
|
||||
mName.addFocusListener( new FocusListener()
|
||||
{
|
||||
@Override
|
||||
public void focusLost( FocusEvent e )
|
||||
{
|
||||
mSelectedConfig.setName( mName.getText() );
|
||||
save();
|
||||
}
|
||||
@Override
|
||||
public void focusGained( FocusEvent e ) {}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Name:" ) );
|
||||
add( mName, "span,growx,push" );
|
||||
|
||||
/**
|
||||
* Sample Rate
|
||||
*/
|
||||
add( new JLabel( "Sample Rate:" ) );
|
||||
|
||||
List<AirspySampleRate> rates = mController.getSampleRates();
|
||||
|
||||
mSampleRateCombo = new JComboBox<AirspySampleRate>(
|
||||
new DefaultComboBoxModel<AirspySampleRate>( rates.toArray(
|
||||
new AirspySampleRate[ rates.size() ] ) ) );
|
||||
|
||||
mSampleRateCombo.setSelectedItem( mController.getSampleRate() );
|
||||
|
||||
mSampleRateCombo.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
AirspySampleRate rate = (AirspySampleRate)mSampleRateCombo.getSelectedItem();
|
||||
|
||||
try
|
||||
{
|
||||
mController.setSampleRate( rate );
|
||||
mSelectedConfig.setSampleRate( rate.getRate() );
|
||||
save();
|
||||
}
|
||||
catch ( LibUsbException | UsbException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog( AirspyTunerConfigurationPanel.this,
|
||||
"Couldn't set sample rate to " + rate.getLabel() );
|
||||
|
||||
mLog.error( "Error setting airspy sample rate", e1 );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mSampleRateCombo, "span 3,growx" );
|
||||
|
||||
add( new JSeparator(), "span,growx,push" );
|
||||
|
||||
/**
|
||||
* Gain Mode
|
||||
*/
|
||||
add( new JLabel( "Gain Mode:" ) );
|
||||
mGainModeCombo = new JComboBox<AirspyTunerController.GainMode>( GainMode.values() );
|
||||
mGainModeCombo.setSelectedItem( Gain.getGainMode( mSelectedConfig.getGain() ) );
|
||||
mGainModeCombo.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
GainMode mode = (GainMode)mGainModeCombo.getSelectedItem();
|
||||
updateGainComponents( mode );
|
||||
|
||||
switch( mode )
|
||||
{
|
||||
case LINEARITY:
|
||||
mGain.setValue( AirspyTunerController.LINEARITY_GAIN_DEFAULT.getValue() );
|
||||
mSelectedConfig.setGain( AirspyTunerController.LINEARITY_GAIN_DEFAULT );
|
||||
break;
|
||||
case SENSITIVITY:
|
||||
mGain.setValue( AirspyTunerController.SENSITIVITY_GAIN_DEFAULT.getValue() );
|
||||
mSelectedConfig.setGain( AirspyTunerController.SENSITIVITY_GAIN_DEFAULT );
|
||||
break;
|
||||
case CUSTOM:
|
||||
default:
|
||||
mLNAGain.setValue( mSelectedConfig.getLNAGain() );
|
||||
mMixerGain.setValue( mSelectedConfig.getMixerGain() );
|
||||
mIFGain.setValue( mSelectedConfig.getIFGain() );
|
||||
mSelectedConfig.setGain( Gain.CUSTOM );
|
||||
break;
|
||||
}
|
||||
|
||||
save();
|
||||
}
|
||||
} );
|
||||
|
||||
add( mGainModeCombo, "wrap" );
|
||||
|
||||
/**
|
||||
* Gain
|
||||
*/
|
||||
mGainLabel = new JLabel( "Gain" );
|
||||
add( mGainLabel );
|
||||
mGainFillerLabel = new JLabel( "" );
|
||||
add( mGainFillerLabel, "span 2" );
|
||||
mGainValueLabel = new JLabel( String.valueOf( mSelectedConfig.getGain().getValue() ) );
|
||||
add( mGainValueLabel, "wrap" );
|
||||
mGain = new JSlider( JSlider.HORIZONTAL,
|
||||
AirspyTunerController.GAIN_MIN,
|
||||
AirspyTunerController.GAIN_MAX,
|
||||
mSelectedConfig.getGain().getValue() );
|
||||
mGain.setMajorTickSpacing( 1 );
|
||||
mGain.setPaintTicks( true );
|
||||
|
||||
mGain.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent event )
|
||||
{
|
||||
GainMode mode = (GainMode)mGainModeCombo.getSelectedItem();
|
||||
int value = mGain.getValue();
|
||||
Gain gain = Gain.getGain( mode, value );
|
||||
|
||||
try
|
||||
{
|
||||
mController.setGain( gain );
|
||||
mSelectedConfig.setGain( gain );
|
||||
save();
|
||||
mGainValueLabel.setText( String.valueOf( gain.getValue() ) );
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
mLog.error( "Couldn't set airspy gain to:" + gain.name(), e );
|
||||
|
||||
JOptionPane.showMessageDialog( mGain,
|
||||
"Couldn't set gain value to " + gain.getValue() );
|
||||
|
||||
mGain.setValue( mSelectedConfig.getGain().getValue() );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mGain, "span,grow" );
|
||||
|
||||
/**
|
||||
* IF/VGA Gain
|
||||
*/
|
||||
mIFGainLabel = new JLabel( "IF Gain" );
|
||||
add( mIFGainLabel );
|
||||
mIFGainFillerLabel = new JLabel( "" );
|
||||
add( mIFGainFillerLabel, "span 2" );
|
||||
mIFGainValueLabel = new JLabel( String.valueOf( mSelectedConfig.getIFGain() ) );
|
||||
add( mIFGainValueLabel, "wrap" );
|
||||
|
||||
mIFGain = new JSlider( JSlider.HORIZONTAL,
|
||||
AirspyTunerController.IF_GAIN_MIN,
|
||||
AirspyTunerController.IF_GAIN_MAX,
|
||||
mSelectedConfig.getIFGain() );
|
||||
|
||||
mIFGain.setMajorTickSpacing( 1 );
|
||||
mIFGain.setPaintTicks( true );
|
||||
|
||||
mIFGain.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent event )
|
||||
{
|
||||
int gain = mIFGain.getValue();
|
||||
|
||||
try
|
||||
{
|
||||
mController.setIFGain( gain );
|
||||
mSelectedConfig.setIFGain( gain );
|
||||
save();
|
||||
mIFGainValueLabel.setText( String.valueOf( gain ) );
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
mLog.error( "Couldn't set airspy IF gain to:" + gain, e );
|
||||
|
||||
JOptionPane.showMessageDialog( mIFGain,
|
||||
"Couldn't set IF gain value to " + gain );
|
||||
|
||||
mIFGain.setValue( mSelectedConfig.getIFGain() );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mIFGain, "span,grow" );
|
||||
|
||||
/**
|
||||
* Mixer Gain
|
||||
*/
|
||||
mMixerGainLabel = new JLabel( "Mixer Gain" );
|
||||
add( mMixerGainLabel );
|
||||
|
||||
mMixerAGC = new JCheckBox( "AGC" );
|
||||
mMixerAGC.setSelected( mSelectedConfig.isMixerAGC() );
|
||||
mMixerAGC.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
try
|
||||
{
|
||||
mController.setMixerAGC( !mSelectedConfig.isMixerAGC() );
|
||||
mSelectedConfig.setMixerAGC( !mSelectedConfig.isMixerAGC() );
|
||||
save();
|
||||
}
|
||||
catch ( Exception e1 )
|
||||
{
|
||||
mLog.error( "Error setting Mixer AGC Enabled:" + !mSelectedConfig.isMixerAGC() );
|
||||
mMixerAGC.setSelected( mSelectedConfig.isMixerAGC() );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
|
||||
add( mMixerAGC, "span 2,center" );
|
||||
|
||||
mMixerGainValueLabel = new JLabel( String.valueOf( mSelectedConfig.getMixerGain() ) );
|
||||
add( mMixerGainValueLabel, "wrap" );
|
||||
|
||||
mMixerGain = new JSlider( JSlider.HORIZONTAL,
|
||||
AirspyTunerController.MIXER_GAIN_MIN,
|
||||
AirspyTunerController.MIXER_GAIN_MAX,
|
||||
mSelectedConfig.getMixerGain() );
|
||||
|
||||
mMixerGain.setMajorTickSpacing( 1 );
|
||||
mMixerGain.setPaintTicks( true );
|
||||
|
||||
mMixerGain.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent event )
|
||||
{
|
||||
int gain = mMixerGain.getValue();
|
||||
|
||||
try
|
||||
{
|
||||
mController.setMixerGain( gain );
|
||||
mSelectedConfig.setMixerGain( gain );
|
||||
save();
|
||||
mMixerGainValueLabel.setText( String.valueOf( gain ) );
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
mLog.error( "Couldn't set airspy Mixer gain to:" + gain, e );
|
||||
|
||||
JOptionPane.showMessageDialog( mIFGain, "Couldn't set Mixer gain value to " + gain );
|
||||
|
||||
mMixerGain.setValue( mSelectedConfig.getMixerGain() );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mMixerGain, "span,grow" );
|
||||
|
||||
/**
|
||||
* LNA Gain
|
||||
*/
|
||||
mLNAGainLabel = new JLabel( "LNA Gain" );
|
||||
add( mLNAGainLabel );
|
||||
|
||||
mLNAAGC = new JCheckBox( "AGC" );
|
||||
mLNAAGC.setSelected( mSelectedConfig.isLNAAGC() );
|
||||
mLNAAGC.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
try
|
||||
{
|
||||
mController.setLNAAGC( !mSelectedConfig.isLNAAGC() );
|
||||
mSelectedConfig.setLNAAGC( !mSelectedConfig.isLNAAGC() );
|
||||
save();
|
||||
}
|
||||
catch ( Exception e1 )
|
||||
{
|
||||
mLog.error( "Error setting LNA AGC Enabled:" + !mSelectedConfig.isLNAAGC() );
|
||||
mLNAAGC.setSelected( mSelectedConfig.isLNAAGC() );
|
||||
}
|
||||
|
||||
}
|
||||
} );
|
||||
|
||||
add( mLNAAGC, "span 2,center" );
|
||||
|
||||
mLNAGainValueLabel = new JLabel( String.valueOf( mSelectedConfig.getLNAGain() ) );
|
||||
add( mLNAGainValueLabel, "wrap" );
|
||||
|
||||
mLNAGain = new JSlider( JSlider.HORIZONTAL,
|
||||
AirspyTunerController.LNA_GAIN_MIN,
|
||||
AirspyTunerController.LNA_GAIN_MAX,
|
||||
mSelectedConfig.getLNAGain() );
|
||||
|
||||
mLNAGain.setMajorTickSpacing( 1 );
|
||||
mLNAGain.setPaintTicks( true );
|
||||
|
||||
mLNAGain.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent event )
|
||||
{
|
||||
int gain = mLNAGain.getValue();
|
||||
|
||||
try
|
||||
{
|
||||
mController.setLNAGain( gain );
|
||||
mSelectedConfig.setLNAGain( gain );
|
||||
save();
|
||||
mLNAGainValueLabel.setText( String.valueOf( gain ) );
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
mLog.error( "Couldn't set airspy LNA gain to:" + gain, e );
|
||||
|
||||
JOptionPane.showMessageDialog( mIFGain, "Couldn't set LNA gain value to " + gain );
|
||||
|
||||
mLNAGain.setValue( mSelectedConfig.getLNAGain() );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mLNAGain, "span,grow" );
|
||||
|
||||
//Set the enabled state of each of the gain controls
|
||||
updateGainComponents( (GainMode)mGainModeCombo.getSelectedItem() );
|
||||
|
||||
/**
|
||||
* Create a new configuration
|
||||
*/
|
||||
mNewConfiguration = new JButton( "New" );
|
||||
|
||||
mNewConfiguration.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
TunerConfiguration config =
|
||||
mResourceManager.getSettingsManager()
|
||||
.addNewTunerConfiguration(
|
||||
TunerType.AIRSPY_R820T,
|
||||
"New Configuration" );
|
||||
|
||||
mComboConfigurations.setModel( getModel() );
|
||||
|
||||
mComboConfigurations.setSelectedItem( config );
|
||||
|
||||
repaint();
|
||||
}
|
||||
} );
|
||||
|
||||
add( mNewConfiguration, "span 2,growx,push" );
|
||||
|
||||
/**
|
||||
* Delete the currently selected configuration
|
||||
*/
|
||||
mDeleteConfiguration = new JButton( "Delete" );
|
||||
|
||||
mDeleteConfiguration.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
AirspyTunerConfiguration selected =
|
||||
(AirspyTunerConfiguration)mComboConfigurations
|
||||
.getItemAt( mComboConfigurations.getSelectedIndex() );
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
int n = JOptionPane.showConfirmDialog(
|
||||
AirspyTunerConfigurationPanel.this,
|
||||
"Are you sure you want to delete '"
|
||||
+ selected.getName() + "'?",
|
||||
"Are you sure?",
|
||||
JOptionPane.YES_NO_OPTION );
|
||||
|
||||
if( n == JOptionPane.YES_OPTION )
|
||||
{
|
||||
mResourceManager.getSettingsManager()
|
||||
.deleteTunerConfiguration( selected );
|
||||
|
||||
mComboConfigurations.setModel( getModel() );
|
||||
|
||||
mComboConfigurations.setSelectedIndex( 0 );
|
||||
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mDeleteConfiguration, "span 2,growx,push" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the enabled state of each of the gain controls according to the
|
||||
* specified gain mode. The overall gain controls are enabled for linearity
|
||||
* and sensitivity and the individual gain controls are disabled, and
|
||||
* vice-versa for custom mode.
|
||||
*/
|
||||
private void updateGainComponents( GainMode mode )
|
||||
{
|
||||
boolean isCustom = ( mode == GainMode.CUSTOM );
|
||||
|
||||
mGainLabel.setEnabled( !isCustom );
|
||||
mGainFillerLabel.setEnabled( !isCustom );
|
||||
mGainValueLabel.setEnabled( !isCustom );
|
||||
mGain.setEnabled( !isCustom );
|
||||
mIFGainLabel.setEnabled( isCustom );
|
||||
mIFGainFillerLabel.setEnabled( isCustom );
|
||||
mIFGainValueLabel.setEnabled( isCustom );
|
||||
mIFGain.setEnabled( isCustom );
|
||||
mLNAGainLabel.setEnabled( isCustom );
|
||||
mLNAAGC.setEnabled( isCustom );
|
||||
mLNAGainValueLabel.setEnabled( isCustom );
|
||||
mLNAGain.setEnabled( isCustom );
|
||||
mMixerGainValueLabel.setEnabled( isCustom );
|
||||
mMixerAGC.setEnabled( isCustom );
|
||||
mMixerGainLabel.setEnabled( isCustom );
|
||||
mMixerGain.setEnabled( isCustom );
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates gui controls with the values from the tuner configuration
|
||||
* @param config - tuner configuration
|
||||
*/
|
||||
private void update( AirspyTunerConfiguration config )
|
||||
{
|
||||
mSelectedConfig = config;
|
||||
|
||||
try
|
||||
{
|
||||
mController.apply( config );
|
||||
|
||||
mName.setText( config.getName() );
|
||||
|
||||
AirspySampleRate rate = mController.getSampleRate(
|
||||
mSelectedConfig.getSampleRate() );
|
||||
|
||||
if( rate != null )
|
||||
{
|
||||
mSampleRateCombo.setSelectedItem( rate );
|
||||
}
|
||||
|
||||
mIFGain.setValue( mSelectedConfig.getIFGain() );
|
||||
mMixerGain.setValue( mSelectedConfig.getMixerGain() );
|
||||
mLNAGain.setValue( mSelectedConfig.getLNAGain() );
|
||||
|
||||
mMixerAGC.setSelected( mSelectedConfig.isMixerAGC() );
|
||||
mLNAAGC.setSelected( mSelectedConfig.isLNAAGC() );
|
||||
|
||||
Gain gain = mSelectedConfig.getGain();
|
||||
mGainModeCombo.setSelectedItem( Gain.getGainMode( gain ) );
|
||||
mGain.setValue( gain.getValue() );
|
||||
|
||||
mResourceManager.getSettingsManager().setSelectedTunerConfiguration(
|
||||
TunerType.AIRSPY_R820T, mController.getDeviceInfo().getSerialNumber(), config );
|
||||
|
||||
save();
|
||||
}
|
||||
catch ( /*UsbException |*/ SourceException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
AirspyTunerConfigurationPanel.this,
|
||||
"Airspy Tuner Controller - couldn't "
|
||||
+ "apply the tuner configuration settings - " +
|
||||
e1.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "Airspy Tuner Controller - couldn't apply "
|
||||
+ "config [" + config.getName() + "]", e1 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a combo box model for the tuner configuration combo component
|
||||
* by assembling a list of the tuner configurations appropriate for this
|
||||
* specific tuner
|
||||
*/
|
||||
private ComboBoxModel<AirspyTunerConfiguration> getModel()
|
||||
{
|
||||
ArrayList<TunerConfiguration> configs =
|
||||
mResourceManager.getSettingsManager()
|
||||
.getTunerConfigurations( TunerType.AIRSPY_R820T );
|
||||
|
||||
DefaultComboBoxModel<AirspyTunerConfiguration> model =
|
||||
new DefaultComboBoxModel<AirspyTunerConfiguration>();
|
||||
|
||||
for( TunerConfiguration config: configs )
|
||||
{
|
||||
model.addElement( (AirspyTunerConfiguration)config );
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a specific (named) tuner configuration
|
||||
*/
|
||||
private AirspyTunerConfiguration getNamedConfiguration( String name )
|
||||
{
|
||||
ArrayList<TunerConfiguration> configs =
|
||||
mResourceManager.getSettingsManager()
|
||||
.getTunerConfigurations( TunerType.AIRSPY_R820T );
|
||||
|
||||
for( TunerConfiguration config: configs )
|
||||
{
|
||||
if( config.getName().contentEquals( name ) )
|
||||
{
|
||||
return (AirspyTunerConfiguration)config;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves current tuner configuration settings
|
||||
*/
|
||||
private void save()
|
||||
{
|
||||
mResourceManager.getSettingsManager().save();
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.LinkedTransferQueue;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -28,8 +27,8 @@ import sample.Broadcaster;
|
||||
import sample.Listener;
|
||||
import sample.complex.ComplexBuffer;
|
||||
import source.SourceException;
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerController;
|
||||
import source.tuner.configuration.TunerConfiguration;
|
||||
import controller.ThreadPoolManager;
|
||||
import controller.ThreadPoolManager.ThreadType;
|
||||
import dsp.filter.dc.DCRemovalFilter_RB;
|
||||
@@ -262,30 +261,31 @@ public class AirspyTunerController extends TunerController
|
||||
}
|
||||
}
|
||||
|
||||
public static String getTransferStatus( int status )
|
||||
{
|
||||
switch( status )
|
||||
{
|
||||
case 0:
|
||||
return "TRANSFER COMPLETED (0)";
|
||||
case 1:
|
||||
return "TRANSFER ERROR (1)";
|
||||
case 2:
|
||||
return "TRANSFER TIMED OUT (2)";
|
||||
case 3:
|
||||
return "TRANSFER CANCELLED (3)";
|
||||
case 4:
|
||||
return "TRANSFER STALL (4)";
|
||||
case 5:
|
||||
return "TRANSFER NO DEVICE (5)";
|
||||
case 6:
|
||||
return "TRANSFER OVERFLOW (6)";
|
||||
default:
|
||||
return "UNKNOWN TRANSFER STATUS (" + status + ")";
|
||||
}
|
||||
}
|
||||
public static String getTransferStatus( int status )
|
||||
{
|
||||
switch( status )
|
||||
{
|
||||
case 0:
|
||||
return "TRANSFER COMPLETED (0)";
|
||||
case 1:
|
||||
return "TRANSFER ERROR (1)";
|
||||
case 2:
|
||||
return "TRANSFER TIMED OUT (2)";
|
||||
case 3:
|
||||
return "TRANSFER CANCELLED (3)";
|
||||
case 4:
|
||||
return "TRANSFER STALL (4)";
|
||||
case 5:
|
||||
return "TRANSFER NO DEVICE (5)";
|
||||
case 6:
|
||||
return "TRANSFER OVERFLOW (6)";
|
||||
default:
|
||||
return "UNKNOWN TRANSFER STATUS (" + status + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@Override
|
||||
public void apply( TunerConfiguration config ) throws SourceException
|
||||
{
|
||||
if( config instanceof AirspyTunerConfiguration )
|
||||
@@ -426,7 +426,7 @@ public class AirspyTunerController extends TunerController
|
||||
/**
|
||||
* Airspy sample rate object that matches the current sample rate setting.
|
||||
*/
|
||||
public AirspySampleRate getSampleRate()
|
||||
public AirspySampleRate getAirspySampleRate()
|
||||
{
|
||||
return getSampleRate( mSampleRate );
|
||||
}
|
||||
@@ -1215,8 +1215,8 @@ public class AirspyTunerController extends TunerController
|
||||
*/
|
||||
public void addListener( Listener<ComplexBuffer> listener )
|
||||
{
|
||||
synchronized( mComplexBufferBroadcaster )
|
||||
{
|
||||
synchronized ( mComplexBufferBroadcaster )
|
||||
{
|
||||
mComplexBufferBroadcaster.addListener( listener );
|
||||
|
||||
if( mBufferProcessor == null || !mBufferProcessor.isRunning() )
|
||||
@@ -1229,7 +1229,7 @@ public class AirspyTunerController extends TunerController
|
||||
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1238,15 +1238,15 @@ public class AirspyTunerController extends TunerController
|
||||
*/
|
||||
public void removeListener( Listener<ComplexBuffer> listener )
|
||||
{
|
||||
synchronized( mComplexBufferBroadcaster )
|
||||
{
|
||||
synchronized ( mComplexBufferBroadcaster )
|
||||
{
|
||||
mComplexBufferBroadcaster.removeListener( listener );
|
||||
|
||||
if( !mComplexBufferBroadcaster.hasListeners() )
|
||||
{
|
||||
mBufferProcessor.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1273,31 +1273,31 @@ public class AirspyTunerController extends TunerController
|
||||
ThreadType.SOURCE_SAMPLE_PROCESSING, new BufferDispatcher(),
|
||||
20, TimeUnit.MILLISECONDS );
|
||||
|
||||
mLibUsbHandlerStatus = ByteBuffer.allocateDirect( 4 );
|
||||
|
||||
mLibUsbHandlerStatus = ByteBuffer.allocateDirect( 4 );
|
||||
|
||||
List<Transfer> transfers = new ArrayList<>();
|
||||
|
||||
mCancel = false;
|
||||
|
||||
while( mRunning.get() )
|
||||
while( mRunning.get() )
|
||||
{
|
||||
mAvailableTransfers.drainTo( transfers );
|
||||
|
||||
for( Transfer transfer: transfers )
|
||||
{
|
||||
int result = LibUsb.submitTransfer( transfer );
|
||||
|
||||
if( result == LibUsb.SUCCESS )
|
||||
{
|
||||
mTransfersInProgress.add( transfer );
|
||||
}
|
||||
mAvailableTransfers.drainTo( transfers );
|
||||
|
||||
for( Transfer transfer: transfers )
|
||||
{
|
||||
int result = LibUsb.submitTransfer( transfer );
|
||||
|
||||
if( result == LibUsb.SUCCESS )
|
||||
{
|
||||
mTransfersInProgress.add( transfer );
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.error( "error submitting transfer [" +
|
||||
LibUsb.errorName( result ) + "]" );
|
||||
}
|
||||
}
|
||||
|
||||
mLog.error( "error submitting transfer [" +
|
||||
LibUsb.errorName( result ) + "]" );
|
||||
}
|
||||
}
|
||||
|
||||
int result = LibUsb.handleEventsTimeoutCompleted(
|
||||
null, USB_TIMEOUT_MS, mLibUsbHandlerStatus.asIntBuffer() );
|
||||
|
||||
@@ -1310,20 +1310,20 @@ public class AirspyTunerController extends TunerController
|
||||
|
||||
mLibUsbHandlerStatus.rewind();
|
||||
}
|
||||
|
||||
if( mCancel )
|
||||
{
|
||||
for( Transfer transfer: mTransfersInProgress )
|
||||
{
|
||||
LibUsb.cancelTransfer( transfer );
|
||||
}
|
||||
|
||||
int result = LibUsb.handleEventsTimeoutCompleted( null,
|
||||
USB_TIMEOUT_MS, mLibUsbHandlerStatus.asIntBuffer() );
|
||||
|
||||
if( mCancel )
|
||||
{
|
||||
for( Transfer transfer: mTransfersInProgress )
|
||||
{
|
||||
LibUsb.cancelTransfer( transfer );
|
||||
}
|
||||
|
||||
int result = LibUsb.handleEventsTimeoutCompleted( null,
|
||||
USB_TIMEOUT_MS, mLibUsbHandlerStatus.asIntBuffer() );
|
||||
|
||||
if( result != LibUsb.SUCCESS )
|
||||
{
|
||||
mLog.error( "error handling events for libusb" );
|
||||
mLog.error( "error handling events for libusb during cancel" );
|
||||
}
|
||||
|
||||
mLibUsbHandlerStatus.rewind();
|
||||
|
||||
770
src/source/tuner/airspy/AirspyTunerEditor.java
Normal file
770
src/source/tuner/airspy/AirspyTunerEditor.java
Normal file
@@ -0,0 +1,770 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2015-2016 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 source.tuner.airspy;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.JSlider;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SpinnerModel;
|
||||
import javax.swing.SpinnerNumberModel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.usb.UsbException;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.usb4java.LibUsbException;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.airspy.AirspyTunerController.Gain;
|
||||
import source.tuner.airspy.AirspyTunerController.GainMode;
|
||||
import source.tuner.configuration.TunerConfiguration;
|
||||
import source.tuner.configuration.TunerConfigurationEditor;
|
||||
import source.tuner.configuration.TunerConfigurationEvent;
|
||||
import source.tuner.configuration.TunerConfigurationModel;
|
||||
import source.tuner.configuration.TunerConfigurationEvent.Event;
|
||||
|
||||
public class AirspyTunerEditor extends TunerConfigurationEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( AirspyTunerEditor.class );
|
||||
|
||||
private JTextField mConfigurationName;
|
||||
private JButton mTunerInfo;
|
||||
|
||||
private JComboBox<AirspySampleRate> mSampleRateCombo;
|
||||
private JSpinner mFrequencyCorrection;
|
||||
|
||||
private JComboBox<GainMode> mGainModeCombo;
|
||||
|
||||
private JSlider mMasterGain;
|
||||
private JLabel mMasterGainValueLabel;
|
||||
|
||||
private JSlider mIFGain;
|
||||
private JLabel mIFGainValueLabel;
|
||||
|
||||
private JSlider mLNAGain;
|
||||
private JLabel mLNAGainValueLabel;
|
||||
|
||||
private JSlider mMixerGain;
|
||||
private JLabel mMixerGainValueLabel;
|
||||
|
||||
private JCheckBox mLNAAGC;
|
||||
private JCheckBox mMixerAGC;
|
||||
|
||||
private AirspyTunerController mController;
|
||||
private boolean mLoading;
|
||||
|
||||
public AirspyTunerEditor( TunerConfigurationModel tunerConfigurationModel,
|
||||
AirspyTuner tuner )
|
||||
{
|
||||
super( tunerConfigurationModel );
|
||||
mController = tuner.getController();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
private AirspyTunerConfiguration getConfiguration()
|
||||
{
|
||||
if( hasItem() )
|
||||
{
|
||||
return (AirspyTunerConfiguration)getItem();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 4", "[right][grow,fill][right][grow,fill]",
|
||||
"[][][][][][grow]" ) );
|
||||
|
||||
add( new JLabel( "Airspy Tuner Configuration" ), "span,align center" );
|
||||
|
||||
mConfigurationName = new JTextField();
|
||||
mConfigurationName.setEnabled( false );
|
||||
mConfigurationName.addFocusListener( new FocusListener()
|
||||
{
|
||||
@Override
|
||||
public void focusLost( FocusEvent e )
|
||||
{
|
||||
save();
|
||||
}
|
||||
@Override
|
||||
public void focusGained( FocusEvent e ) {}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Name:" ) );
|
||||
add( mConfigurationName, "span 2" );
|
||||
|
||||
mTunerInfo = new JButton( "Tuner Info" );
|
||||
mTunerInfo.setEnabled( false );
|
||||
mTunerInfo.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
JOptionPane.showMessageDialog( AirspyTunerEditor.this, getTunerInfo(),
|
||||
"Tuner Info", JOptionPane.INFORMATION_MESSAGE );
|
||||
}
|
||||
} );
|
||||
add( mTunerInfo );
|
||||
|
||||
/**
|
||||
* Sample Rate
|
||||
*/
|
||||
add( new JLabel( "Sample Rate:" ) );
|
||||
|
||||
List<AirspySampleRate> rates = mController.getSampleRates();
|
||||
|
||||
mSampleRateCombo = new JComboBox<AirspySampleRate>(
|
||||
new DefaultComboBoxModel<AirspySampleRate>( rates.toArray(
|
||||
new AirspySampleRate[ rates.size() ] ) ) );
|
||||
mSampleRateCombo.setEnabled( false );
|
||||
mSampleRateCombo.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
AirspySampleRate rate = (AirspySampleRate)mSampleRateCombo.getSelectedItem();
|
||||
|
||||
try
|
||||
{
|
||||
mController.setSampleRate( rate );
|
||||
save();
|
||||
}
|
||||
catch ( LibUsbException | UsbException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog( AirspyTunerEditor.this,
|
||||
"Couldn't set sample rate to " + rate.getLabel() );
|
||||
|
||||
mLog.error( "Error setting airspy sample rate", e1 );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mSampleRateCombo );
|
||||
|
||||
/**
|
||||
* Frequency Correction
|
||||
*/
|
||||
SpinnerModel model =
|
||||
new SpinnerNumberModel( 0.0, //initial value
|
||||
-1000.0, //min
|
||||
1000.0, //max
|
||||
0.1 ); //step
|
||||
|
||||
mFrequencyCorrection = new JSpinner( model );
|
||||
mFrequencyCorrection.setEnabled( false );
|
||||
|
||||
JSpinner.NumberEditor editor =
|
||||
(JSpinner.NumberEditor)mFrequencyCorrection.getEditor();
|
||||
|
||||
DecimalFormat format = editor.getFormat();
|
||||
format.setMinimumFractionDigits( 1 );
|
||||
editor.getTextField().setHorizontalAlignment( SwingConstants.CENTER );
|
||||
|
||||
mFrequencyCorrection.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
final double value = ((SpinnerNumberModel)mFrequencyCorrection
|
||||
.getModel()).getNumber().doubleValue();
|
||||
|
||||
try
|
||||
{
|
||||
mController.setFrequencyCorrection( value );
|
||||
}
|
||||
catch ( SourceException e1 )
|
||||
{
|
||||
mLog.error( "Error setting frequency correction value", e1 );
|
||||
}
|
||||
|
||||
save();
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "PPM:" ) );
|
||||
add( mFrequencyCorrection );
|
||||
|
||||
add( new JSeparator(), "span,growx,push" );
|
||||
|
||||
/**
|
||||
* Gain Mode
|
||||
*/
|
||||
add( new JLabel( "Gain Mode:" ) );
|
||||
mGainModeCombo = new JComboBox<AirspyTunerController.GainMode>( GainMode.values() );
|
||||
mGainModeCombo.setEnabled( false );
|
||||
mGainModeCombo.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
GainMode mode = (GainMode)mGainModeCombo.getSelectedItem();
|
||||
|
||||
updateGainComponents( mode );
|
||||
|
||||
if( hasItem() )
|
||||
{
|
||||
AirspyTunerConfiguration airspy = getConfiguration();
|
||||
|
||||
Gain gain = airspy.getGain();
|
||||
|
||||
if( mode == GainMode.CUSTOM )
|
||||
{
|
||||
mIFGain.setValue( airspy.getIFGain() );
|
||||
mMixerGain.setValue( airspy.getMixerGain() );
|
||||
mMixerAGC.setSelected( airspy.isMixerAGC() );
|
||||
mLNAGain.setValue( airspy.getLNAGain() );
|
||||
mLNAAGC.setSelected( airspy.isLNAAGC() );
|
||||
}
|
||||
else
|
||||
{
|
||||
mMixerAGC.setSelected( false );
|
||||
mLNAAGC.setSelected( false );
|
||||
mMasterGain.setValue( gain.getValue() );
|
||||
mIFGain.setValue( gain.getIF() );
|
||||
mMixerGain.setValue( gain.getMixer() );
|
||||
mLNAGain.setValue( gain.getLNA() );
|
||||
}
|
||||
}
|
||||
|
||||
save();
|
||||
}
|
||||
} );
|
||||
|
||||
add( mGainModeCombo, "wrap" );
|
||||
|
||||
/**
|
||||
* Gain
|
||||
*/
|
||||
add( new JLabel( "Master:" ) );
|
||||
|
||||
mMasterGain = new JSlider( JSlider.HORIZONTAL,
|
||||
AirspyTunerController.GAIN_MIN,
|
||||
AirspyTunerController.GAIN_MAX,
|
||||
AirspyTunerController.GAIN_MIN );
|
||||
mMasterGain.setMajorTickSpacing( 1 );
|
||||
mMasterGain.setPaintTicks( true );
|
||||
|
||||
mMasterGain.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent event )
|
||||
{
|
||||
GainMode mode = (GainMode)mGainModeCombo.getSelectedItem();
|
||||
int value = mMasterGain.getValue();
|
||||
Gain gain = Gain.getGain( mode, value );
|
||||
|
||||
try
|
||||
{
|
||||
mController.setGain( gain );
|
||||
save();
|
||||
mMasterGainValueLabel.setText( String.valueOf( gain.getValue() ) );
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
mLog.error( "Couldn't set airspy gain to:" + gain.name(), e );
|
||||
JOptionPane.showMessageDialog( mMasterGain, "Couldn't set gain value to " +
|
||||
gain.getValue() );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mMasterGain, "span 2" );
|
||||
|
||||
mMasterGainValueLabel = new JLabel( "0" );
|
||||
add( mMasterGainValueLabel );
|
||||
|
||||
add( new JLabel( "IF:" ) );
|
||||
|
||||
mIFGain = new JSlider( JSlider.HORIZONTAL,
|
||||
AirspyTunerController.IF_GAIN_MIN,
|
||||
AirspyTunerController.IF_GAIN_MAX,
|
||||
AirspyTunerController.IF_GAIN_MIN );
|
||||
|
||||
mIFGain.setMajorTickSpacing( 1 );
|
||||
mIFGain.setPaintTicks( true );
|
||||
|
||||
mIFGain.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent event )
|
||||
{
|
||||
int gain = mIFGain.getValue();
|
||||
|
||||
try
|
||||
{
|
||||
mController.setIFGain( gain );
|
||||
save();
|
||||
mIFGainValueLabel.setText( String.valueOf( gain ) );
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
mLog.error( "Couldn't set airspy IF gain to:" + gain, e );
|
||||
|
||||
JOptionPane.showMessageDialog( mIFGain, "Couldn't set IF gain value to " + gain );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mIFGain, "span 2" );
|
||||
|
||||
mIFGainValueLabel = new JLabel( "0" );
|
||||
add( mIFGainValueLabel );
|
||||
|
||||
/**
|
||||
* Mixer Gain
|
||||
*/
|
||||
add( new JLabel( "Mixer:" ) );
|
||||
|
||||
mMixerGain = new JSlider( JSlider.HORIZONTAL,
|
||||
AirspyTunerController.MIXER_GAIN_MIN,
|
||||
AirspyTunerController.MIXER_GAIN_MAX,
|
||||
AirspyTunerController.MIXER_GAIN_MIN );
|
||||
|
||||
mMixerGain.setMajorTickSpacing( 1 );
|
||||
mMixerGain.setPaintTicks( true );
|
||||
|
||||
mMixerGain.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent event )
|
||||
{
|
||||
int gain = mMixerGain.getValue();
|
||||
|
||||
try
|
||||
{
|
||||
mController.setMixerGain( gain );
|
||||
save();
|
||||
mMixerGainValueLabel.setText( String.valueOf( gain ) );
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
mLog.error( "Couldn't set airspy Mixer gain to:" + gain, e );
|
||||
JOptionPane.showMessageDialog( mIFGain, "Couldn't set Mixer gain value to " + gain );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mMixerGain, "span 2" );
|
||||
|
||||
mMixerGainValueLabel = new JLabel( "0" );
|
||||
add( mMixerGainValueLabel );
|
||||
|
||||
add( new JLabel( "LNA:" ) );
|
||||
|
||||
mLNAGain = new JSlider( JSlider.HORIZONTAL,
|
||||
AirspyTunerController.LNA_GAIN_MIN,
|
||||
AirspyTunerController.LNA_GAIN_MAX,
|
||||
AirspyTunerController.LNA_GAIN_MIN );
|
||||
|
||||
mLNAGain.setMajorTickSpacing( 1 );
|
||||
mLNAGain.setPaintTicks( true );
|
||||
|
||||
mLNAGain.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent event )
|
||||
{
|
||||
int gain = mLNAGain.getValue();
|
||||
|
||||
try
|
||||
{
|
||||
mController.setLNAGain( gain );
|
||||
save();
|
||||
mLNAGainValueLabel.setText( String.valueOf( gain ) );
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
mLog.error( "Couldn't set airspy LNA gain to:" + gain, e );
|
||||
JOptionPane.showMessageDialog( mIFGain, "Couldn't set LNA gain value to " + gain );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mLNAGain, "span 2" );
|
||||
|
||||
mLNAGainValueLabel = new JLabel( "0" );
|
||||
add( mLNAGainValueLabel );
|
||||
|
||||
mMixerAGC = new JCheckBox( "Mixer AGC" );
|
||||
mMixerAGC.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
try
|
||||
{
|
||||
mController.setMixerAGC( mMixerAGC.isSelected() );
|
||||
mMixerGain.setEnabled( !mMixerAGC.isSelected() );
|
||||
|
||||
save();
|
||||
}
|
||||
catch ( Exception e1 )
|
||||
{
|
||||
mLog.error( "Error setting Mixer AGC Enabled" );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mMixerAGC, "span 2,center" );
|
||||
|
||||
mLNAAGC = new JCheckBox( "LNA AGC" );
|
||||
mLNAAGC.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
try
|
||||
{
|
||||
mController.setLNAAGC( mLNAAGC.isSelected() );
|
||||
mLNAGain.setEnabled( !mLNAAGC.isSelected() );
|
||||
|
||||
save();
|
||||
}
|
||||
catch ( Exception e1 )
|
||||
{
|
||||
mLog.error( "Error setting LNA AGC Enabled" );
|
||||
}
|
||||
|
||||
}
|
||||
} );
|
||||
|
||||
add( mLNAAGC, "span 2,center" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the enabled state of each of the gain controls according to the
|
||||
* specified gain mode. The master gain control is enabled for linearity
|
||||
* and sensitivity and the individual gain controls are disabled, and
|
||||
* vice-versa for custom mode.
|
||||
*/
|
||||
private void updateGainComponents( GainMode mode )
|
||||
{
|
||||
switch( mode )
|
||||
{
|
||||
case LINEARITY:
|
||||
if( !mMasterGain.isEnabled() )
|
||||
{
|
||||
mMasterGain.setEnabled( true );
|
||||
mMasterGainValueLabel.setEnabled( true );
|
||||
}
|
||||
if( mIFGain.isEnabled() )
|
||||
{
|
||||
mIFGain.setEnabled( false );
|
||||
mIFGainValueLabel.setEnabled( false );
|
||||
}
|
||||
if( mLNAGain.isEnabled() )
|
||||
{
|
||||
mLNAAGC.setEnabled( false );
|
||||
mLNAGainValueLabel.setEnabled( false );
|
||||
mLNAGain.setEnabled( false );
|
||||
}
|
||||
if( mMixerGain.isEnabled() )
|
||||
{
|
||||
mMixerGainValueLabel.setEnabled( false );
|
||||
mMixerAGC.setEnabled( false );
|
||||
mMixerGain.setEnabled( false );
|
||||
}
|
||||
break;
|
||||
case SENSITIVITY:
|
||||
if( !mMasterGain.isEnabled() )
|
||||
{
|
||||
mMasterGain.setEnabled( true );
|
||||
mMasterGainValueLabel.setEnabled( true );
|
||||
}
|
||||
if( mIFGain.isEnabled() )
|
||||
{
|
||||
mIFGain.setEnabled( false );
|
||||
mIFGainValueLabel.setEnabled( false );
|
||||
}
|
||||
if( mLNAGain.isEnabled() )
|
||||
{
|
||||
mLNAAGC.setEnabled( false );
|
||||
mLNAGainValueLabel.setEnabled( false );
|
||||
mLNAGain.setEnabled( false );
|
||||
}
|
||||
if( mMixerGain.isEnabled() )
|
||||
{
|
||||
mMixerGainValueLabel.setEnabled( false );
|
||||
mMixerAGC.setEnabled( false );
|
||||
mMixerGain.setEnabled( false );
|
||||
}
|
||||
break;
|
||||
case CUSTOM:
|
||||
if( mMasterGain.isEnabled() )
|
||||
{
|
||||
mMasterGain.setEnabled( false );
|
||||
mMasterGainValueLabel.setEnabled( false );
|
||||
}
|
||||
if( !mIFGain.isEnabled() )
|
||||
{
|
||||
mIFGain.setEnabled( true );
|
||||
mIFGainValueLabel.setEnabled( true );
|
||||
}
|
||||
if( !mLNAGain.isEnabled() )
|
||||
{
|
||||
mLNAAGC.setEnabled( true );
|
||||
mLNAGainValueLabel.setEnabled( true );
|
||||
mLNAGain.setEnabled( true );
|
||||
}
|
||||
if( !mMixerGain.isEnabled() )
|
||||
{
|
||||
mMixerGainValueLabel.setEnabled( true );
|
||||
mMixerAGC.setEnabled( true );
|
||||
mMixerGain.setEnabled( true );
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
if( hasItem() && !mLoading )
|
||||
{
|
||||
AirspyTunerConfiguration config = getConfiguration();
|
||||
config.setName( mConfigurationName.getText() );
|
||||
config.setSampleRate( ((AirspySampleRate)mSampleRateCombo.getSelectedItem()).getRate() );
|
||||
|
||||
double value = ((SpinnerNumberModel)mFrequencyCorrection.getModel()).getNumber().doubleValue();
|
||||
config.setFrequencyCorrection( value );
|
||||
|
||||
Gain gain = Gain.getGain( (GainMode)mGainModeCombo.getSelectedItem(), mMasterGain.getValue() );
|
||||
|
||||
config.setGain( gain );
|
||||
config.setIFGain( mIFGain.getValue() );
|
||||
config.setMixerGain( mMixerGain.getValue() );
|
||||
config.setLNAGain( mLNAGain.getValue() );
|
||||
config.setMixerAGC( mMixerAGC.isSelected() );
|
||||
config.setLNAAGC( mLNAAGC.isSelected() );
|
||||
|
||||
getTunerConfigurationModel().broadcast( new TunerConfigurationEvent( config, Event.CHANGE ) );
|
||||
}
|
||||
}
|
||||
|
||||
private AirspySampleRate fromValue( int value )
|
||||
{
|
||||
List<AirspySampleRate> rates = mController.getSampleRates();
|
||||
|
||||
for( AirspySampleRate rate: rates )
|
||||
{
|
||||
if( rate.getRate() == value )
|
||||
{
|
||||
return rate;
|
||||
}
|
||||
}
|
||||
|
||||
if( rates.size() > 0 )
|
||||
{
|
||||
return rates.get( 0 );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all controls to the argument enabled state
|
||||
*/
|
||||
private void setControlsEnabled( boolean enabled )
|
||||
{
|
||||
if( mConfigurationName.isEnabled() != enabled )
|
||||
{
|
||||
mConfigurationName.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mTunerInfo.isEnabled() != enabled )
|
||||
{
|
||||
mTunerInfo.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mSampleRateCombo.isEnabled() != enabled )
|
||||
{
|
||||
mSampleRateCombo.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mFrequencyCorrection.isEnabled() != enabled )
|
||||
{
|
||||
mFrequencyCorrection.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mGainModeCombo.isEnabled() != enabled )
|
||||
{
|
||||
mGainModeCombo.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mMasterGain.isEnabled() != enabled )
|
||||
{
|
||||
mMasterGain.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mIFGain.isEnabled() != enabled )
|
||||
{
|
||||
mIFGain.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mMixerGain.isEnabled() != enabled )
|
||||
{
|
||||
mMixerGain.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mMixerAGC.isEnabled() != enabled )
|
||||
{
|
||||
mMixerAGC.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mLNAGain.isEnabled() != enabled )
|
||||
{
|
||||
mLNAGain.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mLNAAGC.isEnabled() != enabled )
|
||||
{
|
||||
mLNAAGC.setEnabled( enabled );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the tuner configuration to the editor. If the configuration is assigned to the
|
||||
* currently selected tuner, then the settings are applied.
|
||||
*/
|
||||
@Override
|
||||
public void setItem( TunerConfiguration config )
|
||||
{
|
||||
super.setItem( config );
|
||||
|
||||
mLoading = true;
|
||||
|
||||
if( hasItem() && getItem().isAssigned() )
|
||||
{
|
||||
AirspyTunerConfiguration airspy = getConfiguration();
|
||||
|
||||
setControlsEnabled( true );
|
||||
|
||||
mConfigurationName.setText( airspy.getName() );
|
||||
|
||||
AirspySampleRate rate = fromValue( airspy.getSampleRate() );
|
||||
|
||||
if( rate != null )
|
||||
{
|
||||
mSampleRateCombo.setSelectedItem( rate );
|
||||
}
|
||||
|
||||
mFrequencyCorrection.setValue( airspy.getFrequencyCorrection() );
|
||||
|
||||
GainMode mode = Gain.getGainMode( airspy.getGain() );
|
||||
|
||||
//This will set the master, IF, Mixer, LNA and AGC controls
|
||||
mGainModeCombo.setSelectedItem( mode );
|
||||
|
||||
if( mode == GainMode.CUSTOM )
|
||||
{
|
||||
mMasterGain.setValue( airspy.getGain().getValue() );
|
||||
mIFGain.setValue( airspy.getIFGain() );
|
||||
|
||||
if( airspy.isMixerAGC() )
|
||||
{
|
||||
mMixerAGC.setSelected( airspy.isMixerAGC() );
|
||||
mMixerGain.setEnabled( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
mMixerGain.setValue( airspy.getMixerGain() );
|
||||
}
|
||||
|
||||
if( airspy.isLNAAGC() )
|
||||
{
|
||||
mLNAAGC.setSelected( airspy.isLNAAGC() );
|
||||
mLNAGain.setEnabled( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
mLNAGain.setValue( airspy.getLNAGain() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mMixerAGC.setSelected( false );
|
||||
mLNAAGC.setSelected( false );
|
||||
|
||||
Gain gain = airspy.getGain();
|
||||
|
||||
mMasterGain.setValue( gain.getValue() );
|
||||
mIFGain.setValue( gain.getIF() );
|
||||
mMixerGain.setValue( gain.getMixer() );
|
||||
mLNAGain.setValue( gain.getLNA() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setControlsEnabled( false );
|
||||
mConfigurationName.setText( hasItem() ? getItem().getName() : "" );
|
||||
}
|
||||
|
||||
mLoading = false;
|
||||
}
|
||||
|
||||
private String getTunerInfo()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
AirspyDeviceInformation info = mController.getDeviceInfo();
|
||||
|
||||
sb.append( "<html><h3>Airspy Tuner</h3>" );
|
||||
sb.append( "<b>Serial: </b>" );
|
||||
sb.append( info.getSerialNumber() );
|
||||
sb.append( "<br>" );
|
||||
|
||||
sb.append( "<b>Firmware: </b>" );
|
||||
String[] firmware = info.getVersion().split( " " );
|
||||
sb.append( firmware.length > 1 ? firmware[ 0 ] : info.getVersion() );
|
||||
sb.append( "<br>" );
|
||||
|
||||
sb.append( "<b>Part: </b>" );
|
||||
sb.append( info.getPartNumber() );
|
||||
sb.append( "<br>" );
|
||||
|
||||
sb.append( "<b>Board ID: </b>" );
|
||||
sb.append( info.getBoardID().getLabel() );
|
||||
sb.append( "<br>" );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2015 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.tuner.airspy;
|
||||
|
||||
import gui.control.JFrequencyControl;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.frequency.FrequencyChangeEvent;
|
||||
import source.tuner.frequency.FrequencyChangeEvent.Event;
|
||||
import source.tuner.frequency.FrequencyChangeListener;
|
||||
|
||||
import com.jidesoft.swing.JideTabbedPane;
|
||||
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class AirspyTunerEditorPanel extends JPanel
|
||||
implements FrequencyChangeListener
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( AirspyTunerEditorPanel.class );
|
||||
|
||||
private JFrequencyControl mFrequencyControl;
|
||||
|
||||
private AirspyTuner mTuner;
|
||||
private AirspyTunerController mController;
|
||||
private ResourceManager mResourceManager;
|
||||
|
||||
public AirspyTunerEditorPanel( AirspyTuner tuner,
|
||||
ResourceManager resourceManager )
|
||||
{
|
||||
mTuner = tuner;
|
||||
mController = mTuner.getController();
|
||||
mResourceManager = resourceManager;
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 2",
|
||||
"[right,grow][grow]",
|
||||
"[][][][][][grow]" ) );
|
||||
|
||||
add( new JLabel( "Airspy Tuner" ), "span,align center" );
|
||||
|
||||
mFrequencyControl = new JFrequencyControl();
|
||||
|
||||
mFrequencyControl.addListener( this );
|
||||
|
||||
/* Add frequency control as frequency change listener. This creates a
|
||||
* feedback loop, so the control does not rebroadcast the event */
|
||||
mTuner.addListener( mFrequencyControl );
|
||||
|
||||
mFrequencyControl.setFrequency( mController.getFrequency(), false );
|
||||
|
||||
add( mFrequencyControl, "span,align center" );
|
||||
|
||||
JideTabbedPane tabs = new JideTabbedPane();
|
||||
tabs.setFont( this.getFont() );
|
||||
tabs.setForeground( Color.BLACK );
|
||||
|
||||
add( tabs, "span,grow,push" );
|
||||
|
||||
tabs.add( "Config", new AirspyTunerConfigurationPanel(
|
||||
mResourceManager, mTuner.getController() ) );
|
||||
|
||||
tabs.add( "Info", new AirspyInformationPanel( mTuner.getController() ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION )
|
||||
{
|
||||
try
|
||||
{
|
||||
mController.setFrequency( event.getValue().longValue() );
|
||||
}
|
||||
catch ( SourceException e )
|
||||
{
|
||||
mLog.error( "error setting frequency [" +
|
||||
event.getValue().longValue() + "]", e );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,11 +15,13 @@
|
||||
* 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 source.tuner;
|
||||
package source.tuner.configuration;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
import source.tuner.TunerType;
|
||||
|
||||
/**
|
||||
* Abstract class to hold a named configuration for a specific type of tuner
|
||||
*/
|
||||
@@ -27,13 +29,23 @@ import javax.xml.bind.annotation.XmlType;
|
||||
public abstract class TunerConfiguration
|
||||
{
|
||||
protected String mName;
|
||||
protected String mUniqueID;
|
||||
protected boolean mAssigned;
|
||||
|
||||
/**
|
||||
* Default constructor to support JAXB
|
||||
*/
|
||||
public TunerConfiguration()
|
||||
{
|
||||
this( "Unknown" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Normal constructor
|
||||
*/
|
||||
public TunerConfiguration( String uniqueID, String name )
|
||||
{
|
||||
mUniqueID = uniqueID;
|
||||
mName = name;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
@@ -41,14 +53,6 @@ public abstract class TunerConfiguration
|
||||
return mName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normal constructor
|
||||
*/
|
||||
public TunerConfiguration( String name )
|
||||
{
|
||||
mName = name;
|
||||
}
|
||||
|
||||
@XmlAttribute( name = "name" )
|
||||
public String getName()
|
||||
{
|
||||
@@ -59,6 +63,28 @@ public abstract class TunerConfiguration
|
||||
{
|
||||
mName = name;
|
||||
}
|
||||
|
||||
@XmlAttribute( name = "unique_id" )
|
||||
public String getUniqueID()
|
||||
{
|
||||
return mUniqueID;
|
||||
}
|
||||
|
||||
public void setUniqueID( String id )
|
||||
{
|
||||
mUniqueID = id;;
|
||||
}
|
||||
|
||||
@XmlAttribute( name = "assigned" )
|
||||
public boolean isAssigned()
|
||||
{
|
||||
return mAssigned;
|
||||
}
|
||||
|
||||
public void setAssigned( boolean assigned )
|
||||
{
|
||||
mAssigned = assigned;
|
||||
}
|
||||
|
||||
@XmlAttribute( name = "tuner_type" )
|
||||
public abstract TunerType getTunerType();
|
||||
20
src/source/tuner/configuration/TunerConfigurationEditor.java
Normal file
20
src/source/tuner/configuration/TunerConfigurationEditor.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package source.tuner.configuration;
|
||||
|
||||
import gui.editor.Editor;
|
||||
|
||||
public abstract class TunerConfigurationEditor extends Editor<TunerConfiguration>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private TunerConfigurationModel mTunerConfigurationModel;
|
||||
|
||||
public TunerConfigurationEditor( TunerConfigurationModel model )
|
||||
{
|
||||
mTunerConfigurationModel = model;
|
||||
}
|
||||
|
||||
public TunerConfigurationModel getTunerConfigurationModel()
|
||||
{
|
||||
return mTunerConfigurationModel;
|
||||
}
|
||||
}
|
||||
30
src/source/tuner/configuration/TunerConfigurationEvent.java
Normal file
30
src/source/tuner/configuration/TunerConfigurationEvent.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package source.tuner.configuration;
|
||||
|
||||
public class TunerConfigurationEvent
|
||||
{
|
||||
private TunerConfiguration mTunerConfiguration;
|
||||
private Event mEvent;
|
||||
|
||||
public TunerConfigurationEvent( TunerConfiguration configuration, Event event )
|
||||
{
|
||||
mTunerConfiguration = configuration;
|
||||
mEvent = event;
|
||||
}
|
||||
|
||||
public TunerConfiguration getConfiguration()
|
||||
{
|
||||
return mTunerConfiguration;
|
||||
}
|
||||
|
||||
public Event getEvent()
|
||||
{
|
||||
return mEvent;
|
||||
}
|
||||
|
||||
public enum Event
|
||||
{
|
||||
ADD,
|
||||
REMOVE,
|
||||
CHANGE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 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 source.tuner.configuration;
|
||||
|
||||
import gui.editor.Editor;
|
||||
import source.tuner.Tuner;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.airspy.AirspyTuner;
|
||||
import source.tuner.airspy.AirspyTunerConfiguration;
|
||||
import source.tuner.airspy.AirspyTunerEditor;
|
||||
import source.tuner.fcd.FCDTuner;
|
||||
import source.tuner.fcd.proV1.FCD1TunerConfiguration;
|
||||
import source.tuner.fcd.proV1.FCD1TunerEditor;
|
||||
import source.tuner.fcd.proplusV2.FCD2TunerConfiguration;
|
||||
import source.tuner.fcd.proplusV2.FCD2TunerEditor;
|
||||
import source.tuner.hackrf.HackRFTuner;
|
||||
import source.tuner.hackrf.HackRFTunerConfiguration;
|
||||
import source.tuner.hackrf.HackRFTunerEditor;
|
||||
import source.tuner.rtl.RTL2832Tuner;
|
||||
import source.tuner.rtl.e4k.E4KTunerConfiguration;
|
||||
import source.tuner.rtl.e4k.E4KTunerEditor;
|
||||
import source.tuner.rtl.r820t.R820TTunerConfiguration;
|
||||
import source.tuner.rtl.r820t.R820TTunerEditor;
|
||||
|
||||
public class TunerConfigurationFactory
|
||||
{
|
||||
/**
|
||||
* Creates a tuner configuration for the specified tuner type, unique ID and name
|
||||
*/
|
||||
public static TunerConfiguration getTunerConfiguration( TunerType type, String uniqueID,
|
||||
String name )
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
case AIRSPY_R820T:
|
||||
return new AirspyTunerConfiguration( uniqueID, name );
|
||||
case ELONICS_E4000:
|
||||
return new E4KTunerConfiguration( uniqueID, name );
|
||||
case FUNCUBE_DONGLE_PRO:
|
||||
return new FCD1TunerConfiguration( uniqueID, name );
|
||||
case FUNCUBE_DONGLE_PRO_PLUS:
|
||||
return new FCD2TunerConfiguration( uniqueID, name );
|
||||
case HACKRF:
|
||||
return new HackRFTunerConfiguration( uniqueID, name );
|
||||
case RAFAELMICRO_R820T:
|
||||
return new R820TTunerConfiguration( uniqueID, name );
|
||||
default:
|
||||
throw new IllegalArgumentException( "Unrecognized tuner type ["
|
||||
+ type.name() + "] - can't create named [" + name + "] tuner"
|
||||
+ " configuration" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a tuner editor gui for the specified tuner
|
||||
*/
|
||||
public static Editor<TunerConfiguration> getEditor( Tuner tuner, TunerConfigurationModel model )
|
||||
{
|
||||
switch( tuner.getTunerType() )
|
||||
{
|
||||
case AIRSPY_R820T:
|
||||
return new AirspyTunerEditor( model, (AirspyTuner)tuner );
|
||||
case ELONICS_E4000:
|
||||
return new E4KTunerEditor( model, (RTL2832Tuner)tuner );
|
||||
case FUNCUBE_DONGLE_PRO:
|
||||
return new FCD1TunerEditor( model, (FCDTuner)tuner );
|
||||
case FUNCUBE_DONGLE_PRO_PLUS:
|
||||
return new FCD2TunerEditor( model, (FCDTuner)tuner );
|
||||
case HACKRF:
|
||||
return new HackRFTunerEditor( model, (HackRFTuner)tuner );
|
||||
case RAFAELMICRO_R820T:
|
||||
return new R820TTunerEditor( model, (RTL2832Tuner)tuner );
|
||||
case UNKNOWN:
|
||||
default:
|
||||
throw new IllegalArgumentException( "Unrecognized Tuner: " + tuner.getName() );
|
||||
}
|
||||
}
|
||||
}
|
||||
371
src/source/tuner/configuration/TunerConfigurationModel.java
Normal file
371
src/source/tuner/configuration/TunerConfigurationModel.java
Normal file
@@ -0,0 +1,371 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 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 source.tuner.configuration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.Listener;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.configuration.TunerConfigurationEvent.Event;
|
||||
|
||||
public class TunerConfigurationModel extends AbstractTableModel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( TunerConfigurationModel.class );
|
||||
|
||||
public static final int TUNER_TYPE = 0;
|
||||
public static final int CONFIGURATION_NAME = 1;
|
||||
public static final int ASSIGNED = 2;
|
||||
private static final String[] COLUMN_HEADERS = { "Tuner Type", "Name", "Assigned" };
|
||||
|
||||
private List<Listener<TunerConfigurationEvent>> mConfigurationChangeListeners =
|
||||
new ArrayList<>();
|
||||
private List<TunerConfiguration> mTunerConfigurations = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Table model for managing tuner configurations. Provides tuner configuration events to
|
||||
* registered listeners
|
||||
*/
|
||||
public TunerConfigurationModel()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the list of tuner configurations to the model
|
||||
*/
|
||||
public void addTunerConfigurations( List<TunerConfiguration> configs )
|
||||
{
|
||||
for( TunerConfiguration config: configs )
|
||||
{
|
||||
addTunerConfiguration( config );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns of list of tuner configurations from the model
|
||||
*/
|
||||
public List<TunerConfiguration> getTunerConfigurations()
|
||||
{
|
||||
return mTunerConfigurations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the tuner configuration to the model firing a table model row add
|
||||
* event and broadcasting a tuner configuration event.
|
||||
*/
|
||||
public void addTunerConfiguration( TunerConfiguration config )
|
||||
{
|
||||
if( !mTunerConfigurations.contains( config ) &&
|
||||
config.getUniqueID() != null &&
|
||||
config.getName() != null )
|
||||
{
|
||||
mTunerConfigurations.add( config );
|
||||
|
||||
int index = mTunerConfigurations.indexOf( config );
|
||||
|
||||
fireTableRowsInserted( index, index );
|
||||
|
||||
broadcast( new TunerConfigurationEvent( config, Event.ADD ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the tuner configuration from the model firing a table model row
|
||||
* delete event and broadcasting a tuner configuration event.
|
||||
*/
|
||||
public void removeTunerConfiguration( TunerConfiguration config )
|
||||
{
|
||||
if( mTunerConfigurations.contains( config ) )
|
||||
{
|
||||
int index = mTunerConfigurations.indexOf( config );
|
||||
|
||||
mTunerConfigurations.remove( config );
|
||||
|
||||
fireTableRowsDeleted( index, index );
|
||||
|
||||
broadcast( new TunerConfigurationEvent( config, Event.REMOVE ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all tuner configurations and assignments from the model and
|
||||
* fires a table clear event and broadcasts a tuner configuration event for
|
||||
* each row removed.
|
||||
*/
|
||||
public void clear()
|
||||
{
|
||||
for( TunerConfiguration config: mTunerConfigurations )
|
||||
{
|
||||
broadcast( new TunerConfigurationEvent( config, Event.REMOVE ) );
|
||||
}
|
||||
|
||||
int size = mTunerConfigurations.size();
|
||||
|
||||
mTunerConfigurations.clear();
|
||||
|
||||
fireTableRowsDeleted( 0, size - 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a tuner configuration event listener
|
||||
*/
|
||||
public void addListener( Listener<TunerConfigurationEvent> listener )
|
||||
{
|
||||
mConfigurationChangeListeners.add( listener );
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the tuner configuration event listener
|
||||
*/
|
||||
public void removeListener( Listener<TunerConfigurationEvent> listener )
|
||||
{
|
||||
mConfigurationChangeListeners.remove( listener );
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts a tuner configuration event
|
||||
*/
|
||||
public void broadcast( TunerConfigurationEvent event )
|
||||
{
|
||||
for( Listener<TunerConfigurationEvent> listener: mConfigurationChangeListeners )
|
||||
{
|
||||
listener.receive( event );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Designates the configuration argument as the currently assigned configuration and unassigns
|
||||
* any other configurations with the same tuner type and unique ID.
|
||||
*/
|
||||
public void assignTunerConfiguration( TunerConfiguration configToAssign )
|
||||
{
|
||||
if( configToAssign != null )
|
||||
{
|
||||
List<TunerConfiguration> configs =
|
||||
getTunerConfigurations( configToAssign.getTunerType(), configToAssign.getUniqueID() );
|
||||
|
||||
for( TunerConfiguration config: configs )
|
||||
{
|
||||
if( config.isAssigned() )
|
||||
{
|
||||
config.setAssigned( false );
|
||||
|
||||
int index = mTunerConfigurations.indexOf( config );
|
||||
fireTableCellUpdated( index, ASSIGNED );
|
||||
broadcast( new TunerConfigurationEvent( config, Event.CHANGE ) );
|
||||
}
|
||||
}
|
||||
|
||||
configToAssign.setAssigned( true );
|
||||
int index = mTunerConfigurations.indexOf( configToAssign );
|
||||
fireTableCellUpdated( index, ASSIGNED );
|
||||
broadcast( new TunerConfigurationEvent( configToAssign, Event.CHANGE ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tuner configuration that is assigned to the tuner with the
|
||||
* tuner type and uniqueID, or selects the first existing configuration that
|
||||
* matches the tuner type and unique ID and assigns it, or creates a new
|
||||
* tuner configuration and assigns it to the tuner.
|
||||
*
|
||||
* This method will always return a tuner configuration that is assigned to
|
||||
* the tuner type and unique ID.
|
||||
*/
|
||||
public TunerConfiguration getTunerConfiguration( TunerType type, String uniqueID )
|
||||
{
|
||||
List<TunerConfiguration> configs = getTunerConfigurations( type, uniqueID );
|
||||
|
||||
for( TunerConfiguration config: configs )
|
||||
{
|
||||
if( config.isAssigned() &&
|
||||
config.getUniqueID() != null &&
|
||||
config.getUniqueID().contentEquals( uniqueID ) )
|
||||
{
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
//Reuse an existing configuration to assign
|
||||
if( !configs.isEmpty() )
|
||||
{
|
||||
configs.get( 0 ).setAssigned( true );
|
||||
return configs.get( 0 );
|
||||
}
|
||||
|
||||
String name = getDistinctName( type, uniqueID );
|
||||
|
||||
//We didn't find the config so create a new one and assign it
|
||||
TunerConfiguration config = TunerConfigurationFactory
|
||||
.getTunerConfiguration( type, uniqueID, name );
|
||||
|
||||
config.setAssigned( true );
|
||||
|
||||
addTunerConfiguration( config );
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if a configuration exists in this model matching the tuner type
|
||||
* and unique ID and name.
|
||||
*/
|
||||
public boolean hasTunerConfiguration( TunerType type, String uniqueID, String name )
|
||||
{
|
||||
for( TunerConfiguration config: mTunerConfigurations )
|
||||
{
|
||||
if( config.getTunerType() == type &&
|
||||
config.getUniqueID() != null &&
|
||||
config.getUniqueID().contentEquals( uniqueID ) &&
|
||||
config.getName() != null &&
|
||||
config.getName().contentEquals( name ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a configuration name for the tuner configuration that is distinct
|
||||
* among the existing tuner configurations of the same type and uniqueID
|
||||
*/
|
||||
public String getDistinctName( TunerType type, String uniqueID )
|
||||
{
|
||||
int counter = 0;
|
||||
|
||||
String name = "New";
|
||||
|
||||
while( hasTunerConfiguration( type, uniqueID, name ) )
|
||||
{
|
||||
counter++;
|
||||
|
||||
name = "New (" + counter + ")";
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all tuner configurations for the specified tuner type
|
||||
*/
|
||||
public List<TunerConfiguration> getTunerConfigurations( TunerType type, String uniqueID )
|
||||
{
|
||||
List<TunerConfiguration> configs = new ArrayList<>();
|
||||
|
||||
for( TunerConfiguration config: mTunerConfigurations )
|
||||
{
|
||||
if( config.getTunerType() == type &&
|
||||
config.getUniqueID() != null &&
|
||||
config.getUniqueID().contentEquals( uniqueID ) )
|
||||
{
|
||||
configs.add( config );
|
||||
}
|
||||
}
|
||||
|
||||
return configs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Column names for the table model
|
||||
*/
|
||||
@Override
|
||||
public String getColumnName( int column )
|
||||
{
|
||||
return COLUMN_HEADERS[ column ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tuner configuration model row count
|
||||
*/
|
||||
@Override
|
||||
public int getRowCount()
|
||||
{
|
||||
return mTunerConfigurations.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tuner configuration model column count
|
||||
*/
|
||||
@Override
|
||||
public int getColumnCount()
|
||||
{
|
||||
return COLUMN_HEADERS.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the row index for the specified configuration or -1
|
||||
*/
|
||||
public int getRowIndex( TunerConfiguration configuration )
|
||||
{
|
||||
if( mTunerConfigurations.contains( configuration ) )
|
||||
{
|
||||
return mTunerConfigurations.indexOf( configuration );
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configuration at the specified index or null
|
||||
*/
|
||||
public TunerConfiguration getTunerConfiguration( int index )
|
||||
{
|
||||
if( index >= 0 && index < mTunerConfigurations.size() )
|
||||
{
|
||||
return mTunerConfigurations.get( index );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value at the indicated table cell
|
||||
*/
|
||||
@Override
|
||||
public Object getValueAt( int row, int column )
|
||||
{
|
||||
if( row >= 0 && row < mTunerConfigurations.size() )
|
||||
{
|
||||
TunerConfiguration config = mTunerConfigurations.get( row );
|
||||
|
||||
switch( column )
|
||||
{
|
||||
case TUNER_TYPE:
|
||||
return config.getTunerType().getLabel();
|
||||
case CONFIGURATION_NAME:
|
||||
return config.getName();
|
||||
case ASSIGNED:
|
||||
return config.isAssigned() ? "*" : null;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -19,36 +19,22 @@ package source.tuner.ettus;
|
||||
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.Tuner;
|
||||
import source.tuner.TunerChannel;
|
||||
import source.tuner.TunerChannelSource;
|
||||
import source.tuner.TunerClass;
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.usb.USBTunerDevice;
|
||||
import controller.ResourceManager;
|
||||
import controller.ThreadPoolManager;
|
||||
|
||||
public class B100Tuner extends Tuner
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( B100Tuner.class );
|
||||
|
||||
private USBTunerDevice mDevice;
|
||||
|
||||
public B100Tuner( USBTunerDevice device )
|
||||
{
|
||||
//TODO: this should extend a USBTuner class, so that we can push the
|
||||
//complex sample listener and the frequency change listener up to that class
|
||||
|
||||
super( "Ettus B100 with WBX Tuner" );
|
||||
|
||||
mDevice = device;
|
||||
super( "Ettus B100 with WBX Tuner", null );
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
@@ -68,36 +54,12 @@ public class B100Tuner extends Tuner
|
||||
return TunerType.ETTUS_WBX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JPanel getEditor( ResourceManager resourceManager )
|
||||
{
|
||||
return new B100TunerEditorPanel( this, resourceManager );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply( TunerConfiguration config ) throws SourceException
|
||||
{
|
||||
mLog.error( "B100 Tuner - can't apply tuner configuration" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSampleRate()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getSampleSize()
|
||||
{
|
||||
return 16.0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFrequency() throws SourceException
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TunerChannelSource getChannel( TunerChannel channel )
|
||||
throws RejectedExecutionException, SourceException
|
||||
@@ -105,7 +67,7 @@ public class B100Tuner extends Tuner
|
||||
//TODO: pass this call to the tuner controller
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void releaseChannel( TunerChannelSource source )
|
||||
{
|
||||
|
||||
@@ -22,20 +22,14 @@ import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import controller.ResourceManager;
|
||||
import settings.SettingsManager;
|
||||
|
||||
public class B100TunerEditorPanel extends JPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private B100Tuner mTuner;
|
||||
private ResourceManager mResourceManager;
|
||||
|
||||
public B100TunerEditorPanel( B100Tuner tuner, ResourceManager resourceManager )
|
||||
public B100TunerEditorPanel( B100Tuner tuner, SettingsManager settingsManager )
|
||||
{
|
||||
mTuner = tuner;
|
||||
mResourceManager = resourceManager;
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,8 +19,6 @@ package source.tuner.fcd;
|
||||
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import sample.Listener;
|
||||
import sample.adapter.ShortAdapter;
|
||||
import sample.complex.ComplexBuffer;
|
||||
@@ -30,75 +28,50 @@ import source.tuner.MixerTunerDataLine;
|
||||
import source.tuner.TunerChannel;
|
||||
import source.tuner.TunerChannelSource;
|
||||
import source.tuner.TunerClass;
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerEvent;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.frequency.FrequencyChangeListener;
|
||||
import controller.ResourceManager;
|
||||
import controller.ThreadPoolManager;
|
||||
|
||||
public class FCDTuner extends MixerTuner
|
||||
{
|
||||
private FCDTunerController mController;
|
||||
|
||||
public FCDTuner( MixerTunerDataLine mixerTDL,
|
||||
FCDTunerController controller )
|
||||
{
|
||||
super( controller.getConfiguration().toString(),
|
||||
super( controller.getConfiguration().toString(),
|
||||
controller,
|
||||
mixerTDL,
|
||||
new ShortAdapter() );
|
||||
|
||||
mController = controller;
|
||||
mController.addListener( (FrequencyChangeListener)this );
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
//TODO: release the mixer tuner data line as well
|
||||
|
||||
mController.dispose();
|
||||
getController().dispose();
|
||||
}
|
||||
|
||||
public FCDTunerController getController()
|
||||
{
|
||||
return mController;
|
||||
return (FCDTunerController)getTunerController();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TunerClass getTunerClass()
|
||||
{
|
||||
return mController.getTunerClass();
|
||||
return getController().getTunerClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TunerType getTunerType()
|
||||
{
|
||||
return mController.getTunerType();
|
||||
return getController().getTunerType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueID()
|
||||
{
|
||||
return mController.getUSBAddress();
|
||||
return getController().getUSBAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JPanel getEditor( ResourceManager resourceManager )
|
||||
{
|
||||
return mController.getEditor( this, resourceManager );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply( TunerConfiguration config )throws SourceException
|
||||
{
|
||||
mController.apply( config );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSampleRate()
|
||||
{
|
||||
return (int)mMixerTunerType.getAudioFormat().getSampleRate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getSampleSize()
|
||||
{
|
||||
@@ -106,16 +79,17 @@ public class FCDTuner extends MixerTuner
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFrequency() throws SourceException
|
||||
{
|
||||
return mController.getFrequency();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TunerChannelSource getChannel( TunerChannel tunerChannel )
|
||||
public TunerChannelSource getChannel( TunerChannel tunerChannel )
|
||||
throws RejectedExecutionException, SourceException
|
||||
{
|
||||
return mController.getChannel( this, tunerChannel );
|
||||
TunerChannelSource source = getController().getChannel( this, tunerChannel );
|
||||
|
||||
if( source != null )
|
||||
{
|
||||
broadcast( new TunerEvent( this, TunerEvent.Event.CHANNEL_COUNT ) );
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,7 +106,7 @@ public class FCDTuner extends MixerTuner
|
||||
|
||||
/* Tell the controller to release the channel and cleanup */
|
||||
/* This will release the channel as a frequency change listener */
|
||||
mController.releaseChannel( source );
|
||||
getController().releaseChannel( source );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.usb.UsbClaimException;
|
||||
import javax.usb.UsbException;
|
||||
|
||||
@@ -35,11 +34,10 @@ import org.usb4java.LibUsbException;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.TunerClass;
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerController;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.configuration.TunerConfiguration;
|
||||
import source.tuner.fcd.proV1.FCD1TunerController.Block;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public abstract class FCDTunerController extends TunerController
|
||||
{
|
||||
@@ -70,6 +68,7 @@ public abstract class FCDTunerController extends TunerController
|
||||
*/
|
||||
public FCDTunerController( Device device,
|
||||
DeviceDescriptor descriptor,
|
||||
int sampleRate,
|
||||
int minTunableFrequency,
|
||||
int maxTunableFrequency )
|
||||
{
|
||||
@@ -77,7 +76,7 @@ public abstract class FCDTunerController extends TunerController
|
||||
maxTunableFrequency,
|
||||
DC_SPIKE_AVOID_BUFFER,
|
||||
USABLE_BANDWIDTH_PERCENT );
|
||||
|
||||
mFrequencyController.setSampleRate( sampleRate );
|
||||
mDevice = device;
|
||||
mDeviceDescriptor = descriptor;
|
||||
}
|
||||
@@ -146,23 +145,10 @@ public abstract class FCDTunerController extends TunerController
|
||||
*/
|
||||
public abstract TunerType getTunerType();
|
||||
|
||||
/**
|
||||
* Editor panel (GUI) component.
|
||||
*/
|
||||
public abstract JPanel getEditor( FCDTuner tuner,
|
||||
ResourceManager resourceManager );
|
||||
|
||||
/**
|
||||
* Applies the settings in the tuner configuration
|
||||
*/
|
||||
public abstract void apply( TunerConfiguration config )
|
||||
throws SourceException;
|
||||
|
||||
/**
|
||||
* Returns the currently applied tuner configuration or null if one hasn't
|
||||
* yet been applied
|
||||
*/
|
||||
public abstract TunerConfiguration getTunerConfiguration();
|
||||
public abstract void apply( TunerConfiguration config ) throws SourceException;
|
||||
|
||||
/**
|
||||
* USB address (bus/port)
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.tuner.fcd;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
public class FCDTunerDetailsPanel extends JPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public FCDTunerDetailsPanel( FCDTunerController controller )
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][][][][][grow]" ) );
|
||||
|
||||
add( new JLabel( "USB ID:" ) );
|
||||
add( new JLabel( controller.getUSBID() ) );
|
||||
|
||||
add( new JLabel( "USB Address:" ) );
|
||||
add( new JLabel( controller.getUSBAddress() ) );
|
||||
|
||||
add( new JLabel( "USB Speed:" ) );
|
||||
add( new JLabel( controller.getUSBSpeed() ) );
|
||||
|
||||
add( new JLabel( "Cellular Band:" ) );
|
||||
add( new JLabel( controller.getConfiguration().getBandBlocking()
|
||||
.getLabel() ) );
|
||||
|
||||
add( new JLabel( "Firmware:" ) );
|
||||
add( new JLabel( controller.getConfiguration().getFirmware() ) );
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,8 @@ package source.tuner.fcd.proV1;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.configuration.TunerConfiguration;
|
||||
import source.tuner.fcd.proV1.FCD1TunerController.LNAEnhance;
|
||||
import source.tuner.fcd.proV1.FCD1TunerController.LNAGain;
|
||||
import source.tuner.fcd.proV1.FCD1TunerController.MixerGain;
|
||||
@@ -42,12 +42,11 @@ public class FCD1TunerConfiguration extends TunerConfiguration
|
||||
*/
|
||||
public FCD1TunerConfiguration()
|
||||
{
|
||||
this( "Default" );
|
||||
}
|
||||
|
||||
public FCD1TunerConfiguration( String name )
|
||||
public FCD1TunerConfiguration( String uniqueID, String name )
|
||||
{
|
||||
super( name );
|
||||
super( uniqueID, name );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -56,6 +55,7 @@ public class FCD1TunerConfiguration extends TunerConfiguration
|
||||
return TunerType.FUNCUBE_DONGLE_PRO;
|
||||
}
|
||||
|
||||
@XmlAttribute( name = "lna_gain" )
|
||||
public LNAGain getLNAGain()
|
||||
{
|
||||
return mLNAGain;
|
||||
@@ -66,12 +66,12 @@ public class FCD1TunerConfiguration extends TunerConfiguration
|
||||
mLNAGain = gain;
|
||||
}
|
||||
|
||||
@XmlAttribute( name = "lna_gain" )
|
||||
public LNAEnhance getLNAEnhance()
|
||||
{
|
||||
return mLNAEnhance;
|
||||
}
|
||||
|
||||
@XmlAttribute( name = "lna_enhance" )
|
||||
public void setLNAEnhance( LNAEnhance enhance )
|
||||
{
|
||||
mLNAEnhance = enhance;
|
||||
|
||||
@@ -1,663 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.tuner.fcd.proV1;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.ComboBoxModel;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SpinnerModel;
|
||||
import javax.swing.SpinnerNumberModel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.usb.UsbClaimException;
|
||||
import javax.usb.UsbException;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.fcd.proV1.FCD1TunerController.LNAEnhance;
|
||||
import source.tuner.fcd.proV1.FCD1TunerController.LNAGain;
|
||||
import source.tuner.fcd.proV1.FCD1TunerController.MixerGain;
|
||||
|
||||
import com.jidesoft.swing.JideTabbedPane;
|
||||
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class FCD1TunerConfigurationPanel extends JPanel
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( FCD1TunerConfigurationPanel.class );
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private ResourceManager mResourceManager;
|
||||
private FCD1TunerController mController;
|
||||
|
||||
private FCD1TunerConfiguration mSelectedConfig;
|
||||
private JButton mNewConfiguration;
|
||||
private JButton mDeleteConfiguration;
|
||||
private JComboBox<FCD1TunerConfiguration> mComboConfigurations;
|
||||
private JComboBox<LNAGain> mComboLNAGain;
|
||||
private JComboBox<LNAEnhance> mComboLNAEnhance;
|
||||
private JComboBox<MixerGain> mComboMixerGain;
|
||||
private JTextField mName;
|
||||
private JSpinner mCorrectionFrequency;
|
||||
private CorrectionSpinner mCorrectionDCI;
|
||||
private CorrectionSpinner mCorrectionDCQ;
|
||||
private CorrectionSpinner mCorrectionGain;
|
||||
private CorrectionSpinner mCorrectionPhase;
|
||||
|
||||
public FCD1TunerConfigurationPanel( ResourceManager resourceManager,
|
||||
FCD1TunerController controller )
|
||||
{
|
||||
mResourceManager = resourceManager;
|
||||
mController = controller;
|
||||
mSelectedConfig = controller.getTunerConfiguration();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][][][][grow]" ) );
|
||||
|
||||
/**
|
||||
* Tuner configurations combo
|
||||
*/
|
||||
mComboConfigurations = new JComboBox<FCD1TunerConfiguration>();
|
||||
mComboConfigurations.setToolTipText( "Select a tuner configuration. "
|
||||
+ "Create a separate tuner configuration for each of your "
|
||||
+ "funcube dongles by using the NEW button and typing a "
|
||||
+ "descriptive name" );
|
||||
|
||||
mComboConfigurations.setModel( getModel() );
|
||||
|
||||
mComboConfigurations.setSelectedItem( mSelectedConfig );
|
||||
|
||||
mComboConfigurations.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
FCD1TunerConfiguration selected =
|
||||
(FCD1TunerConfiguration)mComboConfigurations
|
||||
.getItemAt( mComboConfigurations.getSelectedIndex() );
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
update( selected );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
add( new JLabel( "Config:" ) );
|
||||
add( mComboConfigurations, "growx,push" );
|
||||
|
||||
/**
|
||||
* Tuner Configuration - Name
|
||||
*/
|
||||
mName = new JTextField( mSelectedConfig.getName() );
|
||||
mName.setToolTipText( "Name for the selected tuner configuration" );
|
||||
|
||||
mName.addFocusListener( new FocusListener()
|
||||
{
|
||||
@Override
|
||||
public void focusLost( FocusEvent e )
|
||||
{
|
||||
mSelectedConfig.setName( mName.getText() );
|
||||
save();
|
||||
}
|
||||
@Override
|
||||
public void focusGained( FocusEvent e ) {}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Name:" ) );
|
||||
add( mName, "growx,push" );
|
||||
|
||||
JideTabbedPane tabs = new JideTabbedPane();
|
||||
tabs.setFont( this.getFont() );
|
||||
tabs.setForeground( Color.BLACK );
|
||||
add( tabs, "span,grow,push" );
|
||||
|
||||
JPanel gainPanel = new JPanel();
|
||||
gainPanel.setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][][][grow]" ) );
|
||||
|
||||
/**
|
||||
* LNA Gain
|
||||
*/
|
||||
mComboLNAGain = new JComboBox<LNAGain>( LNAGain.values() );
|
||||
|
||||
mComboLNAGain.setToolTipText( "Adjust the low noise amplifier gain "
|
||||
+ "setting. Default value is 20db" );
|
||||
|
||||
mComboLNAGain.setSelectedItem( mSelectedConfig.getLNAGain() );
|
||||
|
||||
mComboLNAGain.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
LNAGain gain = (LNAGain)mComboLNAGain.getSelectedItem();
|
||||
|
||||
mSelectedConfig.setLNAGain( gain );
|
||||
|
||||
try
|
||||
{
|
||||
mController.setLNAGain( gain );
|
||||
}
|
||||
catch ( UsbClaimException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
FCD1TunerConfigurationPanel.this,
|
||||
"FCD Pro Tuner Controller - cannot claim FCD "
|
||||
+ "Controller to apply LNA gain [" + gain.toString() + "]" );
|
||||
|
||||
mLog.error( "FuncubeDonglePro Controller - usb claim "
|
||||
+ "exception while applying LNA gain value [" +
|
||||
gain.toString() + "]", e1 );
|
||||
}
|
||||
catch ( UsbException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
FCD1TunerConfigurationPanel.this,
|
||||
"FCD Pro Tuner Controller - FCD Controller "
|
||||
+ "cannot apply LNA gain [" + gain.toString() + "]" );
|
||||
|
||||
mLog.error( "FuncubeDonglePro Controller - "
|
||||
+ "exception while applying LNA gain value [" +
|
||||
gain.toString() + "]", e1 );
|
||||
}
|
||||
|
||||
save();
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
gainPanel.add( new JLabel( "LNA:" ) );
|
||||
gainPanel.add( mComboLNAGain, "growx,push" );
|
||||
|
||||
/**
|
||||
* LNA Enhance
|
||||
*/
|
||||
mComboLNAEnhance = new JComboBox<LNAEnhance>( LNAEnhance.values() );
|
||||
mComboLNAEnhance.setToolTipText( "Adjust the LNA enhance setting. "
|
||||
+ "Default value is OFF" );
|
||||
|
||||
mComboLNAEnhance.setSelectedItem( mSelectedConfig.getLNAEnhance() );
|
||||
|
||||
mComboLNAEnhance.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
LNAEnhance enhance = (LNAEnhance)mComboLNAEnhance.getSelectedItem();
|
||||
|
||||
mSelectedConfig.setLNAEnhance( enhance );
|
||||
|
||||
try
|
||||
{
|
||||
mController.setLNAEnhance( enhance );
|
||||
}
|
||||
catch ( UsbClaimException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
FCD1TunerConfigurationPanel.this,
|
||||
"FCD Pro Tuner Controller - cannot claim FCD "
|
||||
+ "Controller to apply LNA enhance [" + enhance.toString() + "]" );
|
||||
|
||||
mLog.error( "FuncubeDonglePro Controller - usb claim "
|
||||
+ "exception while applying LNA enhance value [" +
|
||||
enhance.toString() + "]", e1 );
|
||||
}
|
||||
catch ( UsbException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
FCD1TunerConfigurationPanel.this,
|
||||
"FCD Pro Tuner Controller - FCD Controller "
|
||||
+ "cannot apply LNA enhance [" + enhance.toString() + "]" );
|
||||
|
||||
mLog.error( "FuncubeDonglePro Controller - "
|
||||
+ "exception while applying LNA enhance value [" +
|
||||
enhance.toString() + "]", e1 );
|
||||
}
|
||||
|
||||
save();
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
gainPanel.add( new JLabel( "LNA Enhance:" ) );
|
||||
gainPanel.add( mComboLNAEnhance, "growx,push" );
|
||||
|
||||
/**
|
||||
* Mixer Gain
|
||||
*/
|
||||
mComboMixerGain = new JComboBox<MixerGain>( MixerGain.values() );
|
||||
mComboMixerGain.setToolTipText( "Adjust mixer gain setting" );
|
||||
|
||||
mComboMixerGain.setSelectedItem( mSelectedConfig.getMixerGain() );
|
||||
|
||||
mComboMixerGain.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
MixerGain gain = (MixerGain)mComboMixerGain.getSelectedItem();
|
||||
|
||||
mSelectedConfig.setMixerGain( gain );
|
||||
|
||||
try
|
||||
{
|
||||
mController.setMixerGain( gain );
|
||||
}
|
||||
catch ( UsbClaimException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
FCD1TunerConfigurationPanel.this,
|
||||
"FCD Pro Tuner Controller - cannot claim FCD "
|
||||
+ "Controller to apply Mixer gain [" + gain.toString() + "]" );
|
||||
|
||||
mLog.error( "FuncubeDonglePro Controller - usb claim "
|
||||
+ "exception while applying Mixer gain value [" +
|
||||
gain.toString() + "]", e1 );
|
||||
}
|
||||
catch ( UsbException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
FCD1TunerConfigurationPanel.this,
|
||||
"FCD Pro Tuner Controller - FCD Controller "
|
||||
+ "cannot apply Mixer gain [" + gain.toString() + "]" );
|
||||
|
||||
mLog.error( "FuncubeDonglePro Controller - "
|
||||
+ "exception while applying Mixer gain value [" +
|
||||
gain.toString() + "]", e1 );
|
||||
}
|
||||
|
||||
save();
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
gainPanel.add( new JLabel( "Mixer:" ) );
|
||||
gainPanel.add( mComboMixerGain, "growx,push" );
|
||||
|
||||
tabs.add( "Gain", gainPanel );
|
||||
|
||||
JPanel correctionPanel = new JPanel();
|
||||
correctionPanel.setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][][][][][grow]" ) );
|
||||
|
||||
/**
|
||||
* Frequency Correction
|
||||
*/
|
||||
SpinnerModel model =
|
||||
new SpinnerNumberModel( 0.0, -1000.0, 1000.0, 0.1 ); //initial,min,max,step
|
||||
|
||||
mCorrectionFrequency = new JSpinner( model );
|
||||
|
||||
mCorrectionFrequency.setToolTipText( "Frequency Correction: adjust "
|
||||
+ "value +/- to align the displayed frequency label with the "
|
||||
+ "actual signals" );
|
||||
|
||||
JSpinner.NumberEditor editor =
|
||||
(JSpinner.NumberEditor)mCorrectionFrequency.getEditor();
|
||||
|
||||
DecimalFormat format = editor.getFormat();
|
||||
format.setMinimumFractionDigits( 1 );
|
||||
editor.getTextField().setHorizontalAlignment( SwingConstants.CENTER );
|
||||
|
||||
mCorrectionFrequency.setValue( mSelectedConfig.getFrequencyCorrection() );
|
||||
|
||||
mCorrectionFrequency.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
double value = ((SpinnerNumberModel)mCorrectionFrequency
|
||||
.getModel()).getNumber().doubleValue();
|
||||
|
||||
try
|
||||
{
|
||||
mSelectedConfig.setFrequencyCorrection( value );
|
||||
mController.setFrequencyCorrection( value );
|
||||
save();
|
||||
}
|
||||
catch ( SourceException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
FCD1TunerConfigurationPanel.this,
|
||||
"FCD Pro Tuner Controller - couldn't "
|
||||
+ "apply frequency correction value: " + value +
|
||||
e1.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "FuncubeDonglePro Controller - couldn't apply "
|
||||
+ "frequency correction value: " + value, e1 );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
correctionPanel.add( new JLabel( "Frequency PPM:" ) );
|
||||
correctionPanel.add( mCorrectionFrequency, "growx,push" );
|
||||
|
||||
/**
|
||||
* Inphase DC Correction
|
||||
*/
|
||||
mCorrectionDCI = new CorrectionSpinner( Correction.DC_INPHASE,
|
||||
mSelectedConfig.getInphaseDCCorrection(), 0.00001, 5 );
|
||||
mCorrectionDCI.setToolTipText( "DC Bias Correction/Inphase "
|
||||
+ "Component: valid values are -1.0 to 1.0 (default: 0.0)" );
|
||||
correctionPanel.add( new JLabel( "DC Inphase:" ) );
|
||||
correctionPanel.add( mCorrectionDCI, "growx,push" );
|
||||
|
||||
/**
|
||||
* Quadrature DC Correction
|
||||
*/
|
||||
mCorrectionDCQ = new CorrectionSpinner( Correction.DC_QUADRATURE,
|
||||
mSelectedConfig.getQuadratureDCCorrection(), 0.00001, 5 );
|
||||
mCorrectionDCQ.setToolTipText( "DC Bias Correction/Quadrature "
|
||||
+ "Component: valid values are -1.0 to 1.0 (default: 0.0)" );
|
||||
correctionPanel.add( new JLabel( "DC Quadrature:" ) );
|
||||
correctionPanel.add( mCorrectionDCQ, "growx,push" );
|
||||
|
||||
/**
|
||||
* Gain Correction
|
||||
*/
|
||||
mCorrectionGain = new CorrectionSpinner( Correction.GAIN,
|
||||
mSelectedConfig.getGainCorrection(), 0.00001, 5 );
|
||||
mCorrectionGain.setToolTipText( "Gain Correction: valid values are "
|
||||
+ "-1.0 to 1.0 (default: 0.0)" );
|
||||
correctionPanel.add( new JLabel( "Gain:" ) );
|
||||
correctionPanel.add( mCorrectionGain, "growx,push" );
|
||||
|
||||
/**
|
||||
* Phase Correction
|
||||
*/
|
||||
mCorrectionPhase = new CorrectionSpinner( Correction.PHASE,
|
||||
mSelectedConfig.getPhaseCorrection(), 0.00001, 5 );
|
||||
mCorrectionPhase.setToolTipText( "Phase Correction: valid values are "
|
||||
+ "-1.0 to 1.0 (default: 0.0)" );
|
||||
correctionPanel.add( new JLabel( "Phase:" ) );
|
||||
correctionPanel.add( mCorrectionPhase, "growx,push" );
|
||||
|
||||
tabs.add( "Correction", correctionPanel );
|
||||
|
||||
/**
|
||||
* Create a new configuration
|
||||
*/
|
||||
mNewConfiguration = new JButton( "New" );
|
||||
mNewConfiguration.setToolTipText( "Create a new tuner configuration "
|
||||
+ "for each of your dongles to keep track of the specific "
|
||||
+ "settings for each dongle" );
|
||||
|
||||
mNewConfiguration.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
TunerConfiguration config =
|
||||
mResourceManager.getSettingsManager()
|
||||
.addNewTunerConfiguration(
|
||||
TunerType.FUNCUBE_DONGLE_PRO,
|
||||
"New Configuration" );
|
||||
|
||||
mComboConfigurations.setModel( getModel() );
|
||||
|
||||
mComboConfigurations.setSelectedItem( config );
|
||||
|
||||
repaint();
|
||||
}
|
||||
} );
|
||||
|
||||
add( mNewConfiguration, "growx,push" );
|
||||
|
||||
/**
|
||||
* Delete the currently selected configuration
|
||||
*/
|
||||
mDeleteConfiguration = new JButton( "Delete" );
|
||||
mDeleteConfiguration.setToolTipText( "Deletes the currently selected "
|
||||
+ "tuner configuration. Note: the DEFAULT tuner "
|
||||
+ "configuration will be recreated if you delete it, "
|
||||
+ "after you restart the application" );
|
||||
|
||||
mDeleteConfiguration.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
FCD1TunerConfiguration selected =
|
||||
(FCD1TunerConfiguration)mComboConfigurations
|
||||
.getItemAt( mComboConfigurations.getSelectedIndex() );
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
int n = JOptionPane.showConfirmDialog(
|
||||
FCD1TunerConfigurationPanel.this,
|
||||
"Are you sure you want to delete '"
|
||||
+ selected.getName() + "'?",
|
||||
"Are you sure?",
|
||||
JOptionPane.YES_NO_OPTION );
|
||||
|
||||
if( n == JOptionPane.YES_OPTION )
|
||||
{
|
||||
mResourceManager.getSettingsManager()
|
||||
.deleteTunerConfiguration( selected );
|
||||
|
||||
mComboConfigurations.setModel( getModel() );
|
||||
|
||||
mComboConfigurations.setSelectedIndex( 0 );
|
||||
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mDeleteConfiguration, "growx,push" );
|
||||
}
|
||||
|
||||
private void update( FCD1TunerConfiguration config )
|
||||
{
|
||||
mSelectedConfig = config;
|
||||
|
||||
try
|
||||
{
|
||||
mController.apply( config );
|
||||
|
||||
mName.setText( config.getName() );
|
||||
|
||||
mComboLNAGain.setSelectedItem( mSelectedConfig.getLNAGain() );
|
||||
mComboLNAEnhance.setSelectedItem( mSelectedConfig.getLNAEnhance() );
|
||||
mComboMixerGain.setSelectedItem( mSelectedConfig.getMixerGain() );
|
||||
|
||||
mCorrectionFrequency.setValue( config.getFrequencyCorrection() );
|
||||
mCorrectionDCI.setValue( config.getInphaseDCCorrection() );
|
||||
mCorrectionDCQ.setValue( config.getQuadratureDCCorrection() );
|
||||
mCorrectionGain.setValue( config.getGainCorrection() );
|
||||
mCorrectionPhase.setValue( config.getPhaseCorrection() );
|
||||
|
||||
mResourceManager.getSettingsManager()
|
||||
.setSelectedTunerConfiguration(
|
||||
TunerType.FUNCUBE_DONGLE_PRO,
|
||||
mController.getUSBAddress(), config );
|
||||
}
|
||||
catch ( SourceException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
FCD1TunerConfigurationPanel.this,
|
||||
"FCD Pro Tuner Controller - couldn't "
|
||||
+ "apply the tuner configuration settings - " +
|
||||
e1.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "FuncubeDonglePro Controller - couldn't apply "
|
||||
+ "config [" + config.getName() + "]", e1 );
|
||||
}
|
||||
}
|
||||
|
||||
private ComboBoxModel<FCD1TunerConfiguration> getModel()
|
||||
{
|
||||
ArrayList<TunerConfiguration> configs =
|
||||
mResourceManager.getSettingsManager()
|
||||
.getTunerConfigurations( TunerType.FUNCUBE_DONGLE_PRO );
|
||||
|
||||
DefaultComboBoxModel<FCD1TunerConfiguration> model =
|
||||
new DefaultComboBoxModel<FCD1TunerConfiguration>();
|
||||
|
||||
for( TunerConfiguration config: configs )
|
||||
{
|
||||
model.addElement( (FCD1TunerConfiguration)config );
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
@SuppressWarnings( "unused" )
|
||||
private FCD1TunerConfiguration getNamedConfiguration( String name )
|
||||
{
|
||||
ArrayList<TunerConfiguration> configs =
|
||||
mResourceManager.getSettingsManager()
|
||||
.getTunerConfigurations( TunerType.FUNCUBE_DONGLE_PRO );
|
||||
|
||||
for( TunerConfiguration config: configs )
|
||||
{
|
||||
if( config.getName().contentEquals( name ) )
|
||||
{
|
||||
return (FCD1TunerConfiguration)config;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void save()
|
||||
{
|
||||
mResourceManager.getSettingsManager().save();
|
||||
}
|
||||
|
||||
public enum Correction { GAIN, PHASE, DC_INPHASE, DC_QUADRATURE };
|
||||
|
||||
public class CorrectionSpinner extends JSpinner
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final double sMIN_VALUE = -1.0d;
|
||||
private static final double sMAX_VALUE = 1.0d;
|
||||
|
||||
private Correction mCorrectionComponent;
|
||||
|
||||
public CorrectionSpinner( Correction component,
|
||||
double initialValue,
|
||||
double step,
|
||||
int decimalPlaces )
|
||||
{
|
||||
mCorrectionComponent = component;
|
||||
|
||||
SpinnerModel model = new SpinnerNumberModel( initialValue,
|
||||
sMIN_VALUE, sMAX_VALUE, step );
|
||||
|
||||
setModel( model );
|
||||
|
||||
JSpinner.NumberEditor editor = (JSpinner.NumberEditor)getEditor();
|
||||
|
||||
DecimalFormat format = editor.getFormat();
|
||||
format.setMinimumFractionDigits( decimalPlaces );
|
||||
|
||||
editor.getTextField().setHorizontalAlignment( SwingConstants.CENTER );
|
||||
|
||||
addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
double value =
|
||||
((SpinnerNumberModel)getModel()).getNumber().doubleValue();
|
||||
|
||||
try
|
||||
{
|
||||
switch( mCorrectionComponent )
|
||||
{
|
||||
case DC_INPHASE:
|
||||
mSelectedConfig.setInphaseDCCorrection( value );
|
||||
mController.setDCCorrectionInPhase( value );
|
||||
break;
|
||||
case DC_QUADRATURE:
|
||||
mSelectedConfig.setQuadratureDCCorrection( value );
|
||||
mController.setDCCorrectionQuadrature( value );
|
||||
break;
|
||||
case GAIN:
|
||||
mSelectedConfig.setGainCorrection( value );
|
||||
mController.setGainCorrection( value );
|
||||
break;
|
||||
case PHASE:
|
||||
mSelectedConfig.setPhaseCorrection( value );
|
||||
mController.setPhaseCorrection( value );
|
||||
break;
|
||||
}
|
||||
|
||||
//Save the change(s) to the selected tuner config
|
||||
save();
|
||||
}
|
||||
catch ( UsbClaimException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
FCD1TunerConfigurationPanel.this,
|
||||
"FCD Pro Tuner Controller - cannot claim FCD "
|
||||
+ "Controller to apply "
|
||||
+ mCorrectionComponent.toString() +
|
||||
" correction value [" + value + "]" );
|
||||
|
||||
mLog.error( "FuncubeDonglePro Controller - usb claim "
|
||||
+ "exception while applying "
|
||||
+ mCorrectionComponent.toString()
|
||||
+ " correction value [" + value + "]", e1 );
|
||||
}
|
||||
catch ( UsbException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
FCD1TunerConfigurationPanel.this,
|
||||
"FCD Pro Tuner Controller - USB error from FCD "
|
||||
+ "Controller while applying "
|
||||
+ mCorrectionComponent.toString() +
|
||||
" correction value [" + value + "]" );
|
||||
|
||||
mLog.error( "FuncubeDonglePro Controller - usb "
|
||||
+ "exception while applying "
|
||||
+ mCorrectionComponent.toString()
|
||||
+ " correction value [" + value + "]", e1 );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ package source.tuner.fcd.proV1;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.usb.UsbClaimException;
|
||||
import javax.usb.UsbException;
|
||||
|
||||
@@ -30,13 +29,12 @@ import org.usb4java.Device;
|
||||
import org.usb4java.DeviceDescriptor;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.MixerTunerType;
|
||||
import source.tuner.TunerClass;
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.configuration.TunerConfiguration;
|
||||
import source.tuner.fcd.FCDCommand;
|
||||
import source.tuner.fcd.FCDTuner;
|
||||
import source.tuner.fcd.FCDTunerController;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class FCD1TunerController extends FCDTunerController
|
||||
{
|
||||
@@ -55,12 +53,13 @@ public class FCD1TunerController extends FCDTunerController
|
||||
private LNAEnhance mLNAEnhance;
|
||||
private MixerGain mMixerGain;
|
||||
private FCD1TunerConfiguration mTunerConfiguration;
|
||||
private FCD1TunerEditorPanel mEditor;
|
||||
private FCD1TunerEditor mEditor;
|
||||
|
||||
public FCD1TunerController( Device device, DeviceDescriptor descriptor )
|
||||
{
|
||||
super( device,
|
||||
descriptor,
|
||||
descriptor,
|
||||
(int)MixerTunerType.FUNCUBE_DONGLE_PRO.getAudioFormat().getSampleRate(),
|
||||
sMINIMUM_TUNABLE_FREQUENCY,
|
||||
sMAXIMUM_TUNABLE_FREQUENCY );
|
||||
}
|
||||
@@ -147,17 +146,6 @@ public class FCD1TunerController extends FCDTunerController
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JPanel getEditor( FCDTuner tuner, ResourceManager resourceManager )
|
||||
{
|
||||
if( mEditor == null )
|
||||
{
|
||||
mEditor = new FCD1TunerEditorPanel( tuner, resourceManager );
|
||||
}
|
||||
|
||||
return mEditor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current LNA Gain value from the controller and stores it
|
||||
*/
|
||||
|
||||
528
src/source/tuner/fcd/proV1/FCD1TunerEditor.java
Normal file
528
src/source/tuner/fcd/proV1/FCD1TunerEditor.java
Normal file
@@ -0,0 +1,528 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 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 source.tuner.fcd.proV1;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SpinnerModel;
|
||||
import javax.swing.SpinnerNumberModel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.configuration.TunerConfiguration;
|
||||
import source.tuner.configuration.TunerConfigurationEditor;
|
||||
import source.tuner.configuration.TunerConfigurationEvent;
|
||||
import source.tuner.configuration.TunerConfigurationEvent.Event;
|
||||
import source.tuner.configuration.TunerConfigurationModel;
|
||||
import source.tuner.fcd.FCDTuner;
|
||||
import source.tuner.fcd.proV1.FCD1TunerController.LNAEnhance;
|
||||
import source.tuner.fcd.proV1.FCD1TunerController.LNAGain;
|
||||
import source.tuner.fcd.proV1.FCD1TunerController.MixerGain;
|
||||
|
||||
public class FCD1TunerEditor extends TunerConfigurationEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final static Logger mLog = LoggerFactory.getLogger( FCD1TunerEditor.class );
|
||||
|
||||
private JTextField mConfigurationName;
|
||||
private JButton mTunerInfo;
|
||||
private JSpinner mFrequencyCorrection;
|
||||
private JComboBox<LNAGain> mComboLNAGain;
|
||||
private JComboBox<LNAEnhance> mComboLNAEnhance;
|
||||
private JComboBox<MixerGain> mComboMixerGain;
|
||||
private CorrectionSpinner mCorrectionDCI;
|
||||
private CorrectionSpinner mCorrectionDCQ;
|
||||
private CorrectionSpinner mCorrectionGain;
|
||||
private CorrectionSpinner mCorrectionPhase;
|
||||
private boolean mLoading;
|
||||
|
||||
private FCD1TunerController mController;
|
||||
|
||||
public FCD1TunerEditor( TunerConfigurationModel tunerConfigurationModel, FCDTuner tuner )
|
||||
{
|
||||
super( tunerConfigurationModel );
|
||||
mController = (FCD1TunerController)tuner.getController();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
private FCD1TunerConfiguration getConfiguration()
|
||||
{
|
||||
if( hasItem() )
|
||||
{
|
||||
return (FCD1TunerConfiguration)getItem();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 4", "[right][grow,fill][right][grow,fill]",
|
||||
"[][][][][][][][][][][][grow]" ) );
|
||||
|
||||
add( new JLabel( "FCD Pro Tuner Configuration" ), "span,align center" );
|
||||
|
||||
mConfigurationName = new JTextField();
|
||||
mConfigurationName.setEnabled( false );
|
||||
mConfigurationName.addFocusListener( new FocusListener()
|
||||
{
|
||||
@Override
|
||||
public void focusLost( FocusEvent e )
|
||||
{
|
||||
save();
|
||||
}
|
||||
@Override
|
||||
public void focusGained( FocusEvent e ) {}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Name:" ) );
|
||||
add( mConfigurationName, "span 2" );
|
||||
|
||||
mTunerInfo = new JButton( "Tuner Info" );
|
||||
mTunerInfo.setEnabled( false );
|
||||
mTunerInfo.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
JOptionPane.showMessageDialog( FCD1TunerEditor.this, getTunerInfo(),
|
||||
"Tuner Info", JOptionPane.INFORMATION_MESSAGE );
|
||||
}
|
||||
} );
|
||||
add( mTunerInfo );
|
||||
|
||||
SpinnerModel model = new SpinnerNumberModel( 0.0, //initial value
|
||||
-1000.0, //min
|
||||
1000.0, //max
|
||||
0.1 ); //step
|
||||
|
||||
mFrequencyCorrection = new JSpinner( model );
|
||||
mFrequencyCorrection.setEnabled( false );
|
||||
JSpinner.NumberEditor editor =
|
||||
(JSpinner.NumberEditor)mFrequencyCorrection.getEditor();
|
||||
|
||||
DecimalFormat format = editor.getFormat();
|
||||
format.setMinimumFractionDigits( 1 );
|
||||
editor.getTextField().setHorizontalAlignment( SwingConstants.CENTER );
|
||||
|
||||
mFrequencyCorrection.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
double value = ((SpinnerNumberModel)mFrequencyCorrection
|
||||
.getModel()).getNumber().doubleValue();
|
||||
|
||||
try
|
||||
{
|
||||
mController.setFrequencyCorrection( value );
|
||||
save();
|
||||
}
|
||||
catch ( SourceException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog( FCD1TunerEditor.this, "FCD Pro Tuner "
|
||||
+ "Controller - couldn't apply frequency correction value: " + value +
|
||||
e1.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "FuncubeDonglePro Controller - couldn't apply "
|
||||
+ "frequency correction value: " + value, e1 );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "PPM:" ) );
|
||||
add( mFrequencyCorrection, "wrap" );
|
||||
|
||||
add( new JSeparator( JSeparator.HORIZONTAL ), "span,grow" );
|
||||
add( new JLabel( "Gain" ), "span,align center" );
|
||||
|
||||
mComboLNAGain = new JComboBox<LNAGain>( LNAGain.values() );
|
||||
mComboLNAGain.setEnabled( false );
|
||||
mComboLNAGain.setToolTipText( "Adjust the low noise amplifier gain setting." );
|
||||
mComboLNAGain.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
LNAGain gain = (LNAGain)mComboLNAGain.getSelectedItem();
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
mController.setLNAGain( gain );
|
||||
save();
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
JOptionPane.showMessageDialog( FCD1TunerEditor.this, "FCD Pro Tuner Controller"
|
||||
+ " - error setting LNA gain [" + gain.toString() + "]" );
|
||||
|
||||
mLog.error( "FuncubeDonglePro Controller - error setting gain [" + gain.toString() + "]", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "LNA:" ) );
|
||||
add( mComboLNAGain );
|
||||
|
||||
/**
|
||||
* LNA Enhance
|
||||
*/
|
||||
mComboLNAEnhance = new JComboBox<LNAEnhance>( LNAEnhance.values() );
|
||||
mComboLNAEnhance.setToolTipText( "Adjust the LNA enhance setting. Default value is OFF" );
|
||||
|
||||
mComboLNAEnhance.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
LNAEnhance enhance = (LNAEnhance)mComboLNAEnhance.getSelectedItem();
|
||||
|
||||
try
|
||||
{
|
||||
mController.setLNAEnhance( enhance );
|
||||
save();
|
||||
}
|
||||
catch ( Exception e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog( FCD1TunerEditor.this, "FCD Pro Tuner"
|
||||
+ " error setting LNA enhance gain [" + enhance.toString() + "]" );
|
||||
|
||||
mLog.error( "FCDPro - error setting LNA enhance [" + enhance.toString() + "]", e1 );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Enhance:" ) );
|
||||
add( mComboLNAEnhance );
|
||||
|
||||
/**
|
||||
* Mixer Gain
|
||||
*/
|
||||
mComboMixerGain = new JComboBox<MixerGain>( MixerGain.values() );
|
||||
mComboMixerGain.setToolTipText( "Adjust mixer gain setting" );
|
||||
|
||||
|
||||
mComboMixerGain.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
MixerGain gain = (MixerGain)mComboMixerGain.getSelectedItem();
|
||||
|
||||
try
|
||||
{
|
||||
mController.setMixerGain( gain );
|
||||
save();
|
||||
}
|
||||
catch ( Exception e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog( FCD1TunerEditor.this, "FCDPro - error setting"
|
||||
+ " mixer gain [" + gain.toString() + "]" );
|
||||
|
||||
mLog.error( "FCDPro - error setting mixer gain [" + gain.toString() + "]", e1 );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Mixer:" ) );
|
||||
add( mComboMixerGain, "wrap" );
|
||||
|
||||
add( new JSeparator( JSeparator.HORIZONTAL ), "span,grow" );
|
||||
add( new JLabel( "Correction" ), "span,align center" );
|
||||
|
||||
/**
|
||||
* Inphase DC Correction
|
||||
*/
|
||||
mCorrectionDCI = new CorrectionSpinner( Correction.DC_INPHASE, 0.0, 0.00001, 5 );
|
||||
mCorrectionDCI.setEnabled( false );
|
||||
mCorrectionDCI.setToolTipText( "DC Bias Correction/Inphase "
|
||||
+ "Component: valid values are -1.0 to 1.0 (default: 0.0)" );
|
||||
add( new JLabel( "DC Inphase:" ) );
|
||||
add( mCorrectionDCI );
|
||||
|
||||
/**
|
||||
* Quadrature DC Correction
|
||||
*/
|
||||
mCorrectionDCQ = new CorrectionSpinner( Correction.DC_QUADRATURE, 0.0, 0.00001, 5 );
|
||||
mCorrectionDCQ.setToolTipText( "DC Bias Correction/Quadrature "
|
||||
+ "Component: valid values are -1.0 to 1.0 (default: 0.0)" );
|
||||
add( new JLabel( "DC Quadrature:" ) );
|
||||
add( mCorrectionDCQ );
|
||||
|
||||
/**
|
||||
* Gain Correction
|
||||
*/
|
||||
mCorrectionGain = new CorrectionSpinner( Correction.GAIN, 0.0, 0.00001, 5 );
|
||||
mCorrectionGain.setToolTipText( "Gain Correction: valid values are "
|
||||
+ "-1.0 to 1.0 (default: 0.0)" );
|
||||
add( new JLabel( "Gain:" ) );
|
||||
add( mCorrectionGain );
|
||||
|
||||
/**
|
||||
* Phase Correction
|
||||
*/
|
||||
mCorrectionPhase = new CorrectionSpinner( Correction.PHASE, 0.0, 0.00001, 5 );
|
||||
mCorrectionPhase.setToolTipText( "Phase Correction: valid values are "
|
||||
+ "-1.0 to 1.0 (default: 0.0)" );
|
||||
add( new JLabel( "Phase:" ) );
|
||||
add( mCorrectionPhase );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets each of the tuner configuration controls to the enabled argument state
|
||||
*/
|
||||
private void setControlsEnabled( boolean enabled )
|
||||
{
|
||||
if( mConfigurationName.isEnabled() != enabled )
|
||||
{
|
||||
mConfigurationName.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mTunerInfo.isEnabled() != enabled )
|
||||
{
|
||||
mTunerInfo.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mFrequencyCorrection.isEnabled() != enabled )
|
||||
{
|
||||
mFrequencyCorrection.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mComboLNAEnhance.isEnabled() != enabled )
|
||||
{
|
||||
mComboLNAEnhance.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mComboLNAGain.isEnabled() != enabled )
|
||||
{
|
||||
mComboLNAGain.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mComboMixerGain.isEnabled() != enabled )
|
||||
{
|
||||
mComboMixerGain.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mCorrectionDCI.isEnabled() != enabled )
|
||||
{
|
||||
mCorrectionDCI.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mCorrectionDCQ.isEnabled() != enabled )
|
||||
{
|
||||
mCorrectionDCQ.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mCorrectionGain.isEnabled() != enabled )
|
||||
{
|
||||
mCorrectionGain.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mCorrectionPhase.isEnabled() != enabled )
|
||||
{
|
||||
mCorrectionPhase.setEnabled( enabled );
|
||||
}
|
||||
}
|
||||
|
||||
private String getTunerInfo()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "<html><h3>Funcube Dongle Pro Tuner</h3>" );
|
||||
|
||||
sb.append( "<b>USB ID: </b>" );
|
||||
sb.append( mController.getUSBID() );
|
||||
sb.append( "<br>" );
|
||||
|
||||
sb.append( "<b>USB Address: </b>" );
|
||||
sb.append( mController.getUSBAddress() );
|
||||
sb.append( "<br>" );
|
||||
|
||||
sb.append( "<b>USB Speed: </b>" );
|
||||
sb.append( mController.getUSBSpeed() );
|
||||
sb.append( "<br>" );
|
||||
|
||||
sb.append( "<b>Cellular Band: </b>" );
|
||||
sb.append( mController.getConfiguration().getBandBlocking() );
|
||||
sb.append( "<br>" );
|
||||
|
||||
sb.append( "<b>Firmware: </b>" );
|
||||
sb.append( mController.getConfiguration().getFirmware() );
|
||||
sb.append( "<br>" );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
if( hasItem() && !mLoading )
|
||||
{
|
||||
FCD1TunerConfiguration config = getConfiguration();
|
||||
|
||||
config.setName( mConfigurationName.getText() );
|
||||
|
||||
double value = ((SpinnerNumberModel)mFrequencyCorrection
|
||||
.getModel()).getNumber().doubleValue();
|
||||
config.setFrequencyCorrection( value );
|
||||
config.setLNAEnhance( (LNAEnhance)mComboLNAEnhance.getSelectedItem() );
|
||||
config.setLNAGain( (LNAGain)mComboLNAGain.getSelectedItem() );
|
||||
config.setMixerGain( (MixerGain)mComboMixerGain.getSelectedItem() );
|
||||
|
||||
double dci = ((SpinnerNumberModel)mCorrectionDCI.getModel()).getNumber().doubleValue();
|
||||
config.setInphaseDCCorrection( dci );
|
||||
|
||||
double dcq = ((SpinnerNumberModel)mCorrectionDCQ.getModel()).getNumber().doubleValue();
|
||||
config.setQuadratureDCCorrection( dcq );
|
||||
|
||||
double gain = ((SpinnerNumberModel)mCorrectionGain.getModel()).getNumber().doubleValue();
|
||||
config.setGainCorrection( gain );
|
||||
|
||||
double phase = ((SpinnerNumberModel)mCorrectionPhase.getModel()).getNumber().doubleValue();
|
||||
config.setPhaseCorrection( phase );
|
||||
|
||||
getTunerConfigurationModel().broadcast( new TunerConfigurationEvent( getConfiguration(), Event.CHANGE ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem( TunerConfiguration tunerConfiguration )
|
||||
{
|
||||
super.setItem( tunerConfiguration );
|
||||
|
||||
//Toggle loading so that we don't fire a change event and schedule a settings file save
|
||||
mLoading = true;
|
||||
|
||||
if( hasItem() )
|
||||
{
|
||||
FCD1TunerConfiguration config = getConfiguration();
|
||||
|
||||
if( tunerConfiguration.isAssigned() )
|
||||
{
|
||||
setControlsEnabled( true );
|
||||
mConfigurationName.setText( config.getName() );
|
||||
mFrequencyCorrection.setValue( config.getFrequencyCorrection() );
|
||||
mComboLNAEnhance.setSelectedItem( config.getLNAEnhance() );
|
||||
mComboLNAGain.setSelectedItem( config.getLNAGain() );
|
||||
mComboMixerGain.setSelectedItem( config.getMixerGain() );
|
||||
mCorrectionDCI.setValue( config.getInphaseDCCorrection() );
|
||||
mCorrectionDCQ.setValue( config.getQuadratureDCCorrection() );
|
||||
mCorrectionGain.setValue( config.getGainCorrection() );
|
||||
mCorrectionPhase.setValue( config.getPhaseCorrection() );
|
||||
}
|
||||
else
|
||||
{
|
||||
setControlsEnabled( false );
|
||||
mConfigurationName.setText( config.getName() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setControlsEnabled( false );
|
||||
mConfigurationName.setText( "" );
|
||||
}
|
||||
|
||||
mLoading = false;
|
||||
}
|
||||
|
||||
public enum Correction { GAIN, PHASE, DC_INPHASE, DC_QUADRATURE };
|
||||
|
||||
public class CorrectionSpinner extends JSpinner
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final double MIN_VALUE = -1.0d;
|
||||
private static final double MAX_VALUE = 1.0d;
|
||||
|
||||
private Correction mCorrectionComponent;
|
||||
|
||||
public CorrectionSpinner( Correction component, double initialValue, double step, int decimalPlaces )
|
||||
{
|
||||
mCorrectionComponent = component;
|
||||
|
||||
SpinnerModel model = new SpinnerNumberModel( initialValue, MIN_VALUE, MAX_VALUE, step );
|
||||
setModel( model );
|
||||
|
||||
JSpinner.NumberEditor editor = (JSpinner.NumberEditor)getEditor();
|
||||
|
||||
DecimalFormat format = editor.getFormat();
|
||||
format.setMinimumFractionDigits( decimalPlaces );
|
||||
|
||||
editor.getTextField().setHorizontalAlignment( SwingConstants.CENTER );
|
||||
|
||||
addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
double value =
|
||||
((SpinnerNumberModel)getModel()).getNumber().doubleValue();
|
||||
|
||||
try
|
||||
{
|
||||
switch( mCorrectionComponent )
|
||||
{
|
||||
case DC_INPHASE:
|
||||
mController.setDCCorrectionInPhase( value );
|
||||
break;
|
||||
case DC_QUADRATURE:
|
||||
mController.setDCCorrectionQuadrature( value );
|
||||
break;
|
||||
case GAIN:
|
||||
mController.setGainCorrection( value );
|
||||
break;
|
||||
case PHASE:
|
||||
mController.setPhaseCorrection( value );
|
||||
break;
|
||||
}
|
||||
|
||||
save();
|
||||
}
|
||||
catch ( Exception e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog( FCD1TunerEditor.this, "FCDPro - error "
|
||||
+ "applying " + mCorrectionComponent.toString() + " correction value ["
|
||||
+ value + "]" );
|
||||
|
||||
mLog.error( "FCDPro - error applying "+ mCorrectionComponent.toString()
|
||||
+ " correction value [" + value + "]", e1 );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.tuner.fcd.proV1;
|
||||
|
||||
import gui.control.JFrequencyControl;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.fcd.FCDTuner;
|
||||
import source.tuner.fcd.FCDTunerDetailsPanel;
|
||||
import source.tuner.frequency.FrequencyChangeEvent;
|
||||
import source.tuner.frequency.FrequencyChangeListener;
|
||||
import source.tuner.frequency.FrequencyChangeEvent.Event;
|
||||
|
||||
import com.jidesoft.swing.JideTabbedPane;
|
||||
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class FCD1TunerEditorPanel extends JPanel implements FrequencyChangeListener
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( FCD1TunerEditorPanel.class );
|
||||
|
||||
private FCDTuner mTuner;
|
||||
private FCD1TunerController mController;
|
||||
private ResourceManager mResourceManager;
|
||||
|
||||
private JFrequencyControl mFrequencyControl;
|
||||
|
||||
public FCD1TunerEditorPanel( FCDTuner tuner, ResourceManager resourceManager )
|
||||
{
|
||||
mTuner = tuner;
|
||||
mController = (FCD1TunerController)mTuner.getController();
|
||||
mResourceManager = resourceManager;
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 2", "[grow,right][grow]", "[][][grow]" ) );
|
||||
|
||||
add( new JLabel( "Funcube Dongle Pro Tuner" ), "span, align center" );
|
||||
|
||||
mFrequencyControl = new JFrequencyControl();
|
||||
|
||||
mFrequencyControl.addListener( this );
|
||||
|
||||
/* Add frequency control as listener to tuner to get frequency changes
|
||||
* that are invoked elsewhere, to keep the control in sync with the
|
||||
* frequency */
|
||||
mTuner.addListener( mFrequencyControl );
|
||||
|
||||
mFrequencyControl.setFrequency( mController.getFrequency(), false );
|
||||
|
||||
add( mFrequencyControl, "span,align center" );
|
||||
|
||||
JideTabbedPane tabs = new JideTabbedPane();
|
||||
tabs.setFont( this.getFont() );
|
||||
tabs.setForeground( Color.BLACK );
|
||||
|
||||
tabs.add( "Configuration", new FCD1TunerConfigurationPanel(
|
||||
mResourceManager, mController ) );
|
||||
|
||||
tabs.add( "Info", new FCDTunerDetailsPanel( mController ) );
|
||||
|
||||
add( tabs, "span,push,grow" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION )
|
||||
{
|
||||
try
|
||||
{
|
||||
mController.setFrequency( event.getValue().longValue() );
|
||||
}
|
||||
catch ( SourceException e )
|
||||
{
|
||||
mLog.error( "FCTProController - error setting frequency [" +
|
||||
event.getValue().longValue() + "]", e );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,8 @@ package source.tuner.fcd.proplusV2;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.configuration.TunerConfiguration;
|
||||
|
||||
public class FCD2TunerConfiguration extends TunerConfiguration
|
||||
{
|
||||
@@ -33,12 +33,11 @@ public class FCD2TunerConfiguration extends TunerConfiguration
|
||||
*/
|
||||
public FCD2TunerConfiguration()
|
||||
{
|
||||
this( "Default" );
|
||||
}
|
||||
|
||||
public FCD2TunerConfiguration( String name )
|
||||
public FCD2TunerConfiguration( String uniqueID, String name )
|
||||
{
|
||||
super( name );
|
||||
super( uniqueID, name );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,380 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.tuner.fcd.proplusV2;
|
||||
|
||||
import java.awt.ComponentOrientation;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.ComboBoxModel;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SpinnerModel;
|
||||
import javax.swing.SpinnerNumberModel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerConfigurationAssignment;
|
||||
import source.tuner.TunerType;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class FCD2TunerConfigurationPanel extends JPanel
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( FCD2TunerConfigurationPanel.class );
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private ResourceManager mResourceManager;
|
||||
private FCD2TunerController mController;
|
||||
private FCD2TunerConfiguration mSelectedConfig;
|
||||
private JButton mNewConfiguration;
|
||||
private JButton mDeleteConfiguration;
|
||||
private JComboBox<FCD2TunerConfiguration> mComboConfigurations;
|
||||
private JTextField mName;
|
||||
private JCheckBox mLNAGain;
|
||||
private JCheckBox mMixerGain;
|
||||
private JSpinner mFrequencyCorrection;
|
||||
|
||||
public FCD2TunerConfigurationPanel( ResourceManager resourceManager,
|
||||
FCD2TunerController controller )
|
||||
{
|
||||
mResourceManager = resourceManager;
|
||||
mController = controller;
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][][][][][grow]" ) );
|
||||
|
||||
mComboConfigurations = new JComboBox<FCD2TunerConfiguration>();
|
||||
|
||||
mComboConfigurations.setModel( getModel() );
|
||||
|
||||
mComboConfigurations.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
FCD2TunerConfiguration selected =
|
||||
(FCD2TunerConfiguration)mComboConfigurations
|
||||
.getItemAt( mComboConfigurations.getSelectedIndex() );
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
update( selected );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
add( new JLabel( "Config:" ) );
|
||||
add( mComboConfigurations, "growx,push" );
|
||||
|
||||
mName = new JTextField();
|
||||
|
||||
mName.addFocusListener( new FocusListener()
|
||||
{
|
||||
@Override
|
||||
public void focusLost( FocusEvent e )
|
||||
{
|
||||
mSelectedConfig.setName( mName.getText() );
|
||||
save();
|
||||
}
|
||||
@Override
|
||||
public void focusGained( FocusEvent e ) {}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Name" ) );
|
||||
add( mName, "growx,push" );
|
||||
|
||||
/**
|
||||
* Frequency Correction
|
||||
*/
|
||||
|
||||
SpinnerModel model =
|
||||
new SpinnerNumberModel( 0.0, //initial value
|
||||
-1000.0, //min
|
||||
1000.0, //max
|
||||
0.1 ); //step
|
||||
|
||||
mFrequencyCorrection = new JSpinner( model );
|
||||
|
||||
JSpinner.NumberEditor editor =
|
||||
(JSpinner.NumberEditor)mFrequencyCorrection.getEditor();
|
||||
|
||||
DecimalFormat format = editor.getFormat();
|
||||
format.setMinimumFractionDigits( 1 );
|
||||
editor.getTextField().setHorizontalAlignment( SwingConstants.CENTER );
|
||||
|
||||
mFrequencyCorrection.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
double value = ((SpinnerNumberModel)mFrequencyCorrection
|
||||
.getModel()).getNumber().doubleValue();
|
||||
|
||||
try
|
||||
{
|
||||
mController.setFrequencyCorrection( value );
|
||||
mSelectedConfig.setFrequencyCorrection( value );
|
||||
save();
|
||||
}
|
||||
catch ( SourceException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
FCD2TunerConfigurationPanel.this,
|
||||
"FCD Pro Plus Tuner Controller - couldn't "
|
||||
+ "apply frequency correction value: " + value +
|
||||
e1.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "FuncubeDongleProPlus Controller - couldn't apply "
|
||||
+ "frequency correction value: " + value, e1 );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Correction PPM:" ) );
|
||||
add( mFrequencyCorrection, "growx,push" );
|
||||
|
||||
/**
|
||||
* LNA Gain
|
||||
*/
|
||||
mLNAGain = new JCheckBox( "LNA Gain:" );
|
||||
mLNAGain.setComponentOrientation( ComponentOrientation.RIGHT_TO_LEFT );
|
||||
|
||||
mLNAGain.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
mSelectedConfig.setGainLNA( mLNAGain.isSelected() );
|
||||
|
||||
save();
|
||||
|
||||
update( mSelectedConfig );
|
||||
}
|
||||
} );
|
||||
|
||||
add( mLNAGain );
|
||||
|
||||
/**
|
||||
* Mixer Gain
|
||||
*/
|
||||
mMixerGain = new JCheckBox( "Mixer Gain:" );
|
||||
mMixerGain.setComponentOrientation( ComponentOrientation.RIGHT_TO_LEFT );
|
||||
|
||||
mMixerGain.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
mSelectedConfig.setGainMixer( mMixerGain.isSelected() );
|
||||
|
||||
save();
|
||||
|
||||
update( mSelectedConfig );
|
||||
}
|
||||
} );
|
||||
|
||||
add( mMixerGain );
|
||||
|
||||
/**
|
||||
* Lookup the save config and apply that config to update all of the
|
||||
* controls
|
||||
*/
|
||||
TunerConfigurationAssignment savedConfig = mResourceManager
|
||||
.getSettingsManager().getSelectedTunerConfiguration(
|
||||
TunerType.FUNCUBE_DONGLE_PRO_PLUS,
|
||||
mController.getUSBAddress() );
|
||||
|
||||
if( savedConfig != null )
|
||||
{
|
||||
mSelectedConfig = getNamedConfiguration(
|
||||
savedConfig.getTunerConfigurationName() );
|
||||
}
|
||||
|
||||
if( mSelectedConfig == null )
|
||||
{
|
||||
mSelectedConfig = mComboConfigurations.getItemAt( 0 );
|
||||
|
||||
//Store this config as the default for this tuner at this address
|
||||
mResourceManager.getSettingsManager()
|
||||
.setSelectedTunerConfiguration(
|
||||
TunerType.FUNCUBE_DONGLE_PRO_PLUS,
|
||||
mController.getUSBAddress(), mSelectedConfig );
|
||||
}
|
||||
|
||||
mComboConfigurations.setSelectedItem( mSelectedConfig );
|
||||
|
||||
/**
|
||||
* Create a new configuration
|
||||
*/
|
||||
mNewConfiguration = new JButton( "New" );
|
||||
|
||||
mNewConfiguration.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
TunerConfiguration config =
|
||||
mResourceManager.getSettingsManager()
|
||||
.addNewTunerConfiguration(
|
||||
TunerType.FUNCUBE_DONGLE_PRO_PLUS,
|
||||
"New Configuration" );
|
||||
|
||||
mComboConfigurations.setModel( getModel() );
|
||||
|
||||
mComboConfigurations.setSelectedItem( config );
|
||||
|
||||
repaint();
|
||||
}
|
||||
} );
|
||||
|
||||
add( mNewConfiguration, "growx,push" );
|
||||
|
||||
/**
|
||||
* Delete the currently selected configuration
|
||||
*/
|
||||
mDeleteConfiguration = new JButton( "Delete" );
|
||||
|
||||
mDeleteConfiguration.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
FCD2TunerConfiguration selected =
|
||||
(FCD2TunerConfiguration)mComboConfigurations
|
||||
.getItemAt( mComboConfigurations.getSelectedIndex() );
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
int n = JOptionPane.showConfirmDialog(
|
||||
FCD2TunerConfigurationPanel.this,
|
||||
"Are you sure you want to delete '"
|
||||
+ selected.getName() + "'?",
|
||||
"Are you sure?",
|
||||
JOptionPane.YES_NO_OPTION );
|
||||
|
||||
if( n == JOptionPane.YES_OPTION )
|
||||
{
|
||||
mResourceManager.getSettingsManager()
|
||||
.deleteTunerConfiguration( selected );
|
||||
|
||||
mComboConfigurations.setModel( getModel() );
|
||||
|
||||
mComboConfigurations.setSelectedIndex( 0 );
|
||||
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mDeleteConfiguration, "growx,push" );
|
||||
}
|
||||
|
||||
private void update( FCD2TunerConfiguration config )
|
||||
{
|
||||
mSelectedConfig = config;
|
||||
|
||||
try
|
||||
{
|
||||
mController.apply( config );
|
||||
|
||||
mName.setText( config.getName() );
|
||||
mLNAGain.setSelected( config.getGainLNA() );
|
||||
mMixerGain.setSelected( config.getGainMixer() );
|
||||
mFrequencyCorrection.setValue( config.getFrequencyCorrection() );
|
||||
|
||||
mResourceManager.getSettingsManager().setSelectedTunerConfiguration(
|
||||
TunerType.FUNCUBE_DONGLE_PRO_PLUS,
|
||||
mController.getUSBAddress(), config );
|
||||
}
|
||||
catch ( SourceException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
FCD2TunerConfigurationPanel.this,
|
||||
"FCD Pro Plus Tuner Controller - couldn't "
|
||||
+ "apply the tuner configuration settings - " +
|
||||
e1.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "FuncubeDongleProPlus Controller - couldn't apply "
|
||||
+ "config [" + config.getName() + "]", e1 );
|
||||
}
|
||||
}
|
||||
|
||||
private ComboBoxModel<FCD2TunerConfiguration> getModel()
|
||||
{
|
||||
ArrayList<TunerConfiguration> configs =
|
||||
mResourceManager.getSettingsManager()
|
||||
.getTunerConfigurations( TunerType.FUNCUBE_DONGLE_PRO_PLUS );
|
||||
|
||||
DefaultComboBoxModel<FCD2TunerConfiguration> model =
|
||||
new DefaultComboBoxModel<FCD2TunerConfiguration>();
|
||||
|
||||
for( TunerConfiguration config: configs )
|
||||
{
|
||||
model.addElement( (FCD2TunerConfiguration)config );
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
private FCD2TunerConfiguration getNamedConfiguration( String name )
|
||||
{
|
||||
ArrayList<TunerConfiguration> configs =
|
||||
mResourceManager.getSettingsManager()
|
||||
.getTunerConfigurations( TunerType.FUNCUBE_DONGLE_PRO_PLUS );
|
||||
|
||||
for( TunerConfiguration config: configs )
|
||||
{
|
||||
if( config.getName().contentEquals( name ) )
|
||||
{
|
||||
return (FCD2TunerConfiguration)config;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void save()
|
||||
{
|
||||
mResourceManager.getSettingsManager().save();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
* Copyright (C) 2014-2016 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
|
||||
@@ -20,47 +20,39 @@ package source.tuner.fcd.proplusV2;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.usb4java.Device;
|
||||
import org.usb4java.DeviceDescriptor;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.MixerTunerType;
|
||||
import source.tuner.TunerClass;
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.configuration.TunerConfiguration;
|
||||
import source.tuner.fcd.FCDCommand;
|
||||
import source.tuner.fcd.FCDTuner;
|
||||
import source.tuner.fcd.FCDTunerController;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class FCD2TunerController extends FCDTunerController
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( FCD2TunerController.class );
|
||||
private final static Logger mLog = LoggerFactory.getLogger( FCD2TunerController.class );
|
||||
|
||||
public static final int sMINIMUM_TUNABLE_FREQUENCY = 150000;
|
||||
public static final int sMAXIMUM_TUNABLE_FREQUENCY = 2050000000;
|
||||
public static final int sSAMPLE_RATE = 192000;
|
||||
|
||||
private FCD2TunerConfiguration mTunerConfiguration;
|
||||
private FCD2TunerEditorPanel mEditor;
|
||||
public static final int MINIMUM_TUNABLE_FREQUENCY = 150000;
|
||||
public static final int MAXIMUM_TUNABLE_FREQUENCY = 2050000000;
|
||||
public static final int SAMPLE_RATE = 192000;
|
||||
|
||||
public FCD2TunerController( Device device, DeviceDescriptor descriptor )
|
||||
{
|
||||
super( device,
|
||||
descriptor,
|
||||
sMINIMUM_TUNABLE_FREQUENCY,
|
||||
sMAXIMUM_TUNABLE_FREQUENCY );
|
||||
super( device, descriptor,
|
||||
(int)MixerTunerType.FUNCUBE_DONGLE_PRO_PLUS.getAudioFormat().getSampleRate(),
|
||||
MINIMUM_TUNABLE_FREQUENCY, MAXIMUM_TUNABLE_FREQUENCY );
|
||||
}
|
||||
|
||||
public void init() throws SourceException
|
||||
{
|
||||
super.init();
|
||||
|
||||
mFrequencyController.setSampleRate( sSAMPLE_RATE );
|
||||
mFrequencyController.setSampleRate( SAMPLE_RATE );
|
||||
|
||||
try
|
||||
{
|
||||
@@ -74,7 +66,7 @@ public class FCD2TunerController extends FCDTunerController
|
||||
|
||||
public int getCurrentSampleRate()
|
||||
{
|
||||
return sSAMPLE_RATE;
|
||||
return SAMPLE_RATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -88,71 +80,44 @@ public class FCD2TunerController extends FCDTunerController
|
||||
{
|
||||
return TunerType.FUNCUBE_DONGLE_PRO_PLUS;
|
||||
}
|
||||
|
||||
public JPanel getEditor( FCDTuner tuner, ResourceManager resourceManager )
|
||||
{
|
||||
if( mEditor == null )
|
||||
{
|
||||
mEditor = new FCD2TunerEditorPanel( tuner, resourceManager );
|
||||
}
|
||||
|
||||
return mEditor;
|
||||
}
|
||||
|
||||
public void setLNAGain( boolean enabled ) throws SourceException
|
||||
{
|
||||
try
|
||||
{
|
||||
send( FCDCommand.APP_SET_LNA_GAIN, enabled ? 1 : 0 );
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
throw new SourceException( "error while setting LNA Gain", e );
|
||||
}
|
||||
}
|
||||
|
||||
public void setMixerGain( boolean enabled ) throws SourceException
|
||||
{
|
||||
try
|
||||
{
|
||||
send( FCDCommand.APP_SET_MIXER_GAIN, enabled ? 1 : 0 );
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
throw new SourceException( "error while setting Mixer Gain", e );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply( TunerConfiguration config ) throws SourceException
|
||||
{
|
||||
if( config instanceof FCD2TunerConfiguration )
|
||||
{
|
||||
FCD2TunerConfiguration plusConfig =
|
||||
(FCD2TunerConfiguration)config;
|
||||
FCD2TunerConfiguration fcd2 = (FCD2TunerConfiguration)config;
|
||||
|
||||
setFrequencyCorrection( plusConfig.getFrequencyCorrection() );
|
||||
|
||||
try
|
||||
{
|
||||
if( plusConfig.getGainLNA() )
|
||||
{
|
||||
send( FCDCommand.APP_SET_LNA_GAIN, 1 );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
send( FCDCommand.APP_SET_LNA_GAIN, 0 );
|
||||
}
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
throw new SourceException( "error while setting LNA Gain", e );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if( plusConfig.getGainMixer() )
|
||||
{
|
||||
send( FCDCommand.APP_SET_MIXER_GAIN, 1 );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
send( FCDCommand.APP_SET_MIXER_GAIN, 0 );
|
||||
}
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
throw new SourceException( "error while setting Mixer Gain", e );
|
||||
}
|
||||
|
||||
mTunerConfiguration = plusConfig;
|
||||
setFrequencyCorrection( fcd2.getFrequencyCorrection() );
|
||||
setLNAGain( fcd2.getGainLNA() );
|
||||
setMixerGain( fcd2.getGainMixer() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TunerConfiguration getTunerConfiguration()
|
||||
{
|
||||
return mTunerConfiguration;
|
||||
}
|
||||
|
||||
public int getDCCorrection()
|
||||
{
|
||||
int dcCorrection = -999;
|
||||
|
||||
328
src/source/tuner/fcd/proplusV2/FCD2TunerEditor.java
Normal file
328
src/source/tuner/fcd/proplusV2/FCD2TunerEditor.java
Normal file
@@ -0,0 +1,328 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 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 source.tuner.fcd.proplusV2;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SpinnerModel;
|
||||
import javax.swing.SpinnerNumberModel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.configuration.TunerConfiguration;
|
||||
import source.tuner.configuration.TunerConfigurationEditor;
|
||||
import source.tuner.configuration.TunerConfigurationEvent;
|
||||
import source.tuner.configuration.TunerConfigurationEvent.Event;
|
||||
import source.tuner.configuration.TunerConfigurationModel;
|
||||
import source.tuner.fcd.FCDTuner;
|
||||
|
||||
public class FCD2TunerEditor extends TunerConfigurationEditor
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( FCD2TunerEditor.class );
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JTextField mConfigurationName;
|
||||
private JButton mTunerInfo;
|
||||
private JSpinner mFrequencyCorrection;
|
||||
private JCheckBox mLNAGain;
|
||||
private JCheckBox mMixerGain;
|
||||
private boolean mLoading;
|
||||
|
||||
private FCD2TunerController mController;
|
||||
|
||||
public FCD2TunerEditor( TunerConfigurationModel tunerConfigurationModel, FCDTuner tuner )
|
||||
{
|
||||
super( tunerConfigurationModel );
|
||||
mController = (FCD2TunerController)tuner.getController();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
private FCD2TunerConfiguration getConfiguration()
|
||||
{
|
||||
if( hasItem() )
|
||||
{
|
||||
return (FCD2TunerConfiguration)getItem();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 4", "[right][grow,fill][right][grow,fill]",
|
||||
"[][][][][][grow]" ) );
|
||||
|
||||
add( new JLabel( "FCD Pro+ Tuner Configuration" ), "span,align center" );
|
||||
|
||||
mConfigurationName = new JTextField();
|
||||
mConfigurationName.setEnabled( false );
|
||||
mConfigurationName.addFocusListener( new FocusListener()
|
||||
{
|
||||
@Override
|
||||
public void focusLost( FocusEvent e )
|
||||
{
|
||||
save();
|
||||
}
|
||||
@Override
|
||||
public void focusGained( FocusEvent e ) {}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Name:" ) );
|
||||
add( mConfigurationName, "span 2" );
|
||||
|
||||
mTunerInfo = new JButton( "Tuner Info" );
|
||||
mTunerInfo.setEnabled( false );
|
||||
mTunerInfo.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
JOptionPane.showMessageDialog( FCD2TunerEditor.this, getTunerInfo(),
|
||||
"Tuner Info", JOptionPane.INFORMATION_MESSAGE );
|
||||
}
|
||||
} );
|
||||
add( mTunerInfo );
|
||||
|
||||
SpinnerModel model = new SpinnerNumberModel( 0.0, //initial value
|
||||
-1000.0, //min
|
||||
1000.0, //max
|
||||
0.1 ); //step
|
||||
|
||||
mFrequencyCorrection = new JSpinner( model );
|
||||
mFrequencyCorrection.setEnabled( false );
|
||||
JSpinner.NumberEditor editor =
|
||||
(JSpinner.NumberEditor)mFrequencyCorrection.getEditor();
|
||||
|
||||
DecimalFormat format = editor.getFormat();
|
||||
format.setMinimumFractionDigits( 1 );
|
||||
editor.getTextField().setHorizontalAlignment( SwingConstants.CENTER );
|
||||
|
||||
mFrequencyCorrection.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
double value = ((SpinnerNumberModel)mFrequencyCorrection
|
||||
.getModel()).getNumber().doubleValue();
|
||||
|
||||
try
|
||||
{
|
||||
mController.setFrequencyCorrection( value );
|
||||
save();
|
||||
}
|
||||
catch ( SourceException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog( FCD2TunerEditor.this, "FCD Pro Plus Tuner "
|
||||
+ "Controller - couldn't apply frequency correction value: " + value +
|
||||
e1.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "FuncubeDongleProPlus Controller - couldn't apply "
|
||||
+ "frequency correction value: " + value, e1 );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "PPM:" ) );
|
||||
add( mFrequencyCorrection, "wrap" );
|
||||
|
||||
add( new JSeparator( JSeparator.HORIZONTAL ), "span,grow" );
|
||||
|
||||
mLNAGain = new JCheckBox( "LNA Gain" );
|
||||
mLNAGain.setEnabled( false );
|
||||
mLNAGain.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent event )
|
||||
{
|
||||
try
|
||||
{
|
||||
mController.setLNAGain( mLNAGain.isSelected() );
|
||||
save();
|
||||
}
|
||||
catch( SourceException e )
|
||||
{
|
||||
mLog.error( "Couldn't set LNA gain for FCD2", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "" ) );
|
||||
add( mLNAGain );
|
||||
|
||||
/**
|
||||
* Mixer Gain
|
||||
*/
|
||||
mMixerGain = new JCheckBox( "Mixer Gain" );
|
||||
|
||||
mMixerGain.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent event )
|
||||
{
|
||||
try
|
||||
{
|
||||
mController.setMixerGain( mMixerGain.isSelected() );
|
||||
save();
|
||||
}
|
||||
catch( SourceException e )
|
||||
{
|
||||
mLog.error( "Couldn't set mixer gain for FCD2", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "" ) );
|
||||
add( mMixerGain );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets each of the tuner configuration controls to the enabled argument state
|
||||
*/
|
||||
private void setControlsEnabled( boolean enabled )
|
||||
{
|
||||
if( mConfigurationName.isEnabled() != enabled )
|
||||
{
|
||||
mConfigurationName.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mTunerInfo.isEnabled() != enabled )
|
||||
{
|
||||
mTunerInfo.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mFrequencyCorrection.isEnabled() != enabled )
|
||||
{
|
||||
mFrequencyCorrection.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mLNAGain.isEnabled() != enabled )
|
||||
{
|
||||
mLNAGain.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mMixerGain.isEnabled() != enabled )
|
||||
{
|
||||
mMixerGain.setEnabled( enabled );
|
||||
}
|
||||
}
|
||||
|
||||
private String getTunerInfo()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "<html><h3>Funcube Dongle Pro Plus Tuner</h3>" );
|
||||
|
||||
sb.append( "<b>USB ID: </b>" );
|
||||
sb.append( mController.getUSBID() );
|
||||
sb.append( "<br>" );
|
||||
|
||||
sb.append( "<b>USB Address: </b>" );
|
||||
sb.append( mController.getUSBAddress() );
|
||||
sb.append( "<br>" );
|
||||
|
||||
sb.append( "<b>USB Speed: </b>" );
|
||||
sb.append( mController.getUSBSpeed() );
|
||||
sb.append( "<br>" );
|
||||
|
||||
sb.append( "<b>Cellular Band: </b>" );
|
||||
sb.append( mController.getConfiguration().getBandBlocking() );
|
||||
sb.append( "<br>" );
|
||||
|
||||
sb.append( "<b>Firmware: </b>" );
|
||||
sb.append( mController.getConfiguration().getFirmware() );
|
||||
sb.append( "<br>" );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
if( hasItem() && !mLoading )
|
||||
{
|
||||
FCD2TunerConfiguration config = getConfiguration();
|
||||
|
||||
config.setName( mConfigurationName.getText() );
|
||||
|
||||
double value = ((SpinnerNumberModel)mFrequencyCorrection
|
||||
.getModel()).getNumber().doubleValue();
|
||||
config.setFrequencyCorrection( value );
|
||||
|
||||
config.setGainLNA( mLNAGain.isSelected() );
|
||||
config.setGainMixer( mMixerGain.isSelected() );
|
||||
|
||||
getTunerConfigurationModel().broadcast(
|
||||
new TunerConfigurationEvent( getConfiguration(), Event.CHANGE ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem( TunerConfiguration tunerConfiguration )
|
||||
{
|
||||
super.setItem( tunerConfiguration );
|
||||
|
||||
//Toggle loading so that we don't fire a change event and schedule a settings file save
|
||||
mLoading = true;
|
||||
|
||||
if( hasItem() )
|
||||
{
|
||||
FCD2TunerConfiguration config = getConfiguration();
|
||||
|
||||
|
||||
if( tunerConfiguration.isAssigned() )
|
||||
{
|
||||
setControlsEnabled( true );
|
||||
mConfigurationName.setText( config.getName() );
|
||||
mFrequencyCorrection.setValue( config.getFrequencyCorrection() );
|
||||
mLNAGain.setSelected( config.getGainLNA() );
|
||||
mMixerGain.setSelected( config.getGainMixer() );
|
||||
}
|
||||
else
|
||||
{
|
||||
setControlsEnabled( false );
|
||||
mConfigurationName.setText( config.getName() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setControlsEnabled( false );
|
||||
mConfigurationName.setText( "" );
|
||||
}
|
||||
|
||||
mLoading = false;
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.tuner.fcd.proplusV2;
|
||||
|
||||
import gui.control.JFrequencyControl;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.fcd.FCDTuner;
|
||||
import source.tuner.fcd.FCDTunerDetailsPanel;
|
||||
import source.tuner.frequency.FrequencyChangeEvent;
|
||||
import source.tuner.frequency.FrequencyChangeListener;
|
||||
import source.tuner.frequency.FrequencyChangeEvent.Event;
|
||||
|
||||
import com.jidesoft.swing.JideTabbedPane;
|
||||
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class FCD2TunerEditorPanel extends JPanel implements FrequencyChangeListener
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( FCD2TunerEditorPanel.class );
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private FCDTuner mTuner;
|
||||
private FCD2TunerController mController;
|
||||
private ResourceManager mResourceManager;
|
||||
|
||||
private JFrequencyControl mFrequencyControl;
|
||||
|
||||
public FCD2TunerEditorPanel( FCDTuner tuner, ResourceManager resourceManager )
|
||||
{
|
||||
mTuner = tuner;
|
||||
mController = (FCD2TunerController)mTuner.getController();
|
||||
mResourceManager = resourceManager;
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 2", "[right,grow][grow]", "[][][grow]" ) );
|
||||
|
||||
add( new JLabel( "Funcube Dongle Pro Plus Tuner" ), "span,align center" );
|
||||
|
||||
mFrequencyControl = new JFrequencyControl();
|
||||
|
||||
mFrequencyControl.addListener( this );
|
||||
|
||||
/* Add frequency control as frequency change listener. This creates a
|
||||
* feedback loop, so the control does not rebroadcast the event */
|
||||
mTuner.addListener( mFrequencyControl );
|
||||
|
||||
mFrequencyControl.setFrequency( mController.getFrequency(), false );
|
||||
|
||||
add( mFrequencyControl, "span,align center" );
|
||||
|
||||
JideTabbedPane tabs = new JideTabbedPane();
|
||||
tabs.setFont( this.getFont() );
|
||||
tabs.setForeground( Color.BLACK );
|
||||
|
||||
tabs.add( "Configuration", new FCD2TunerConfigurationPanel(
|
||||
mResourceManager, mController ) );
|
||||
|
||||
tabs.add( "Info", new FCDTunerDetailsPanel( mController ) );
|
||||
|
||||
add( tabs, "span,grow,push" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION )
|
||||
{
|
||||
//Disregard the bandwidth, which shouldn't be changing
|
||||
try
|
||||
{
|
||||
mController.setFrequency( event.getValue().longValue() );
|
||||
}
|
||||
catch ( SourceException e )
|
||||
{
|
||||
mLog.error( "FCDProController - error setting frequency [" +
|
||||
event.getValue().longValue() + "]", e );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
package source.tuner.frequency;
|
||||
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2015 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.real.RealSampleListener;
|
||||
import source.tuner.frequency.FrequencyChangeEvent.Event;
|
||||
import buffer.FloatAveragingBuffer;
|
||||
|
||||
public class AutomaticFrequencyControl_R extends FrequencyCorrectionControl
|
||||
implements RealSampleListener
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( AutomaticFrequencyControl_R.class );
|
||||
|
||||
private static float LARGE_ERROR = 0.300f;
|
||||
private static float MEDIUM_ERROR = 0.150f;
|
||||
private static float SMALL_ERROR = 0.030f;
|
||||
private static float FINE_ERROR = 0.015f;
|
||||
|
||||
private static int LARGE_FREQUENCY_CORRECTION = 1500; //Hertz
|
||||
private static int MEDIUM_FREQUENCY_CORRECTION = 500;
|
||||
private static int SMALL_FREQUENCY_CORRECTION = 100;
|
||||
private static int FINE_FREQUENCY_CORRECTION = 50;
|
||||
|
||||
private static int SAMPLE_THRESHOLD = 15000;
|
||||
private Mode mMode = Mode.FAST;
|
||||
|
||||
private FloatAveragingBuffer mBuffer =
|
||||
new FloatAveragingBuffer( SAMPLE_THRESHOLD );
|
||||
|
||||
private int mSampleCounter = 0;
|
||||
private int mSkipCounter = 0;
|
||||
private int mSkipThreshold = 4;
|
||||
private int mErrorCorrection = 0;
|
||||
|
||||
public enum Mode
|
||||
{
|
||||
NORMAL,FAST;
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatic Frequency Control. Monitors DC bias present in an FM
|
||||
* demodulated audio stream and issues automatic frequency corrections to
|
||||
* maintain the DC bias close to zero.
|
||||
*
|
||||
* @param maximum - maximum allowable (+/-) frequency correction value.
|
||||
*/
|
||||
public AutomaticFrequencyControl_R( int maximum )
|
||||
{
|
||||
super( maximum );
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
super.dispose();
|
||||
|
||||
mBuffer = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the error correction value to zero and broadcasts a change event
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
mErrorCorrection = 0;
|
||||
mMode = Mode.FAST;
|
||||
dispatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts a frequency correction change event to the registered listener
|
||||
*/
|
||||
private void dispatch()
|
||||
{
|
||||
if( mListener != null )
|
||||
{
|
||||
mListener.frequencyChanged(
|
||||
new FrequencyChangeEvent( Event.CHANNEL_FREQUENCY_CORRECTION_CHANGE_NOTIFICATION,
|
||||
mErrorCorrection ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( float sample )
|
||||
{
|
||||
if( mMode == Mode.FAST )
|
||||
{
|
||||
float average = mBuffer.get( sample );
|
||||
|
||||
mSampleCounter++;
|
||||
|
||||
if( mSampleCounter >= SAMPLE_THRESHOLD )
|
||||
{
|
||||
mSampleCounter = 0;
|
||||
|
||||
update( average );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mSkipCounter++;
|
||||
|
||||
if( mSkipCounter >= mSkipThreshold )
|
||||
{
|
||||
mSkipCounter = 0;
|
||||
|
||||
float average = mBuffer.get( sample );
|
||||
|
||||
mSampleCounter++;
|
||||
|
||||
if( mSampleCounter >= SAMPLE_THRESHOLD )
|
||||
{
|
||||
mSampleCounter = 0;
|
||||
|
||||
update( average );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void update( float average )
|
||||
{
|
||||
mMode = Mode.NORMAL;
|
||||
|
||||
if( average > LARGE_ERROR )
|
||||
{
|
||||
adjust( -LARGE_FREQUENCY_CORRECTION );
|
||||
mMode = Mode.FAST;
|
||||
}
|
||||
else if( average > MEDIUM_ERROR )
|
||||
{
|
||||
adjust( -MEDIUM_FREQUENCY_CORRECTION );
|
||||
mMode = Mode.FAST;
|
||||
}
|
||||
else if( average > SMALL_ERROR )
|
||||
{
|
||||
adjust( -SMALL_FREQUENCY_CORRECTION );
|
||||
}
|
||||
else if( average > FINE_ERROR )
|
||||
{
|
||||
adjust( -FINE_FREQUENCY_CORRECTION );
|
||||
}
|
||||
else if( average < -LARGE_ERROR )
|
||||
{
|
||||
adjust( LARGE_FREQUENCY_CORRECTION );
|
||||
mMode = Mode.FAST;
|
||||
}
|
||||
else if( average < -MEDIUM_ERROR )
|
||||
{
|
||||
adjust( MEDIUM_FREQUENCY_CORRECTION );
|
||||
mMode = Mode.FAST;
|
||||
}
|
||||
else if( average < -SMALL_ERROR )
|
||||
{
|
||||
adjust( SMALL_FREQUENCY_CORRECTION );
|
||||
}
|
||||
else if( average < -FINE_ERROR )
|
||||
{
|
||||
adjust( FINE_FREQUENCY_CORRECTION );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,197 +0,0 @@
|
||||
package source.tuner.frequency;
|
||||
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2015 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.Listener;
|
||||
import sample.real.RealBuffer;
|
||||
import source.tuner.frequency.FrequencyChangeEvent.Event;
|
||||
import buffer.FloatAveragingBuffer;
|
||||
|
||||
public class AutomaticFrequencyControl_RB extends FrequencyCorrectionControl
|
||||
implements Listener<RealBuffer>
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( AutomaticFrequencyControl_RB.class );
|
||||
|
||||
private static float LARGE_ERROR = 0.300f;
|
||||
private static float MEDIUM_ERROR = 0.150f;
|
||||
private static float SMALL_ERROR = 0.030f;
|
||||
private static float FINE_ERROR = 0.015f;
|
||||
|
||||
private static int LARGE_FREQUENCY_CORRECTION = 1500; //Hertz
|
||||
private static int MEDIUM_FREQUENCY_CORRECTION = 500;
|
||||
private static int SMALL_FREQUENCY_CORRECTION = 100;
|
||||
private static int FINE_FREQUENCY_CORRECTION = 50;
|
||||
|
||||
private static int SAMPLE_THRESHOLD = 15000;
|
||||
private Mode mMode = Mode.FAST;
|
||||
|
||||
private FloatAveragingBuffer mBuffer =
|
||||
new FloatAveragingBuffer( SAMPLE_THRESHOLD );
|
||||
|
||||
private int mSampleCounter = 0;
|
||||
private int mSkipCounter = 0;
|
||||
private int mSkipThreshold = 4;
|
||||
private int mErrorCorrection = 0;
|
||||
|
||||
public enum Mode
|
||||
{
|
||||
NORMAL,FAST;
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatic Frequency Control. Monitors DC bias present in an FM
|
||||
* demodulated audio stream and issues automatic frequency corrections to
|
||||
* maintain the DC bias close to zero.
|
||||
*
|
||||
* @param maximum - maximum allowable (+/-) frequency correction value.
|
||||
*/
|
||||
public AutomaticFrequencyControl_RB( int maximum )
|
||||
{
|
||||
super( maximum );
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
super.dispose();
|
||||
|
||||
mBuffer = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the error correction value to zero and broadcasts a change event
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
super.reset();
|
||||
|
||||
mMode = Mode.FAST;
|
||||
dispatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts a frequency correction change event to the registered listener
|
||||
*/
|
||||
private void dispatch()
|
||||
{
|
||||
if( mListener != null )
|
||||
{
|
||||
mListener.frequencyChanged(
|
||||
new FrequencyChangeEvent( Event.CHANNEL_FREQUENCY_CORRECTION_CHANGE_NOTIFICATION,
|
||||
mErrorCorrection ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( RealBuffer t )
|
||||
{
|
||||
float average = 0.0f;
|
||||
|
||||
for( float sample: t.getSamples() )
|
||||
{
|
||||
average = mBuffer.get( sample );
|
||||
}
|
||||
|
||||
//TODO: fix this
|
||||
|
||||
// update( average );
|
||||
}
|
||||
|
||||
public void receive( float sample )
|
||||
{
|
||||
if( mMode == Mode.FAST )
|
||||
{
|
||||
float average = mBuffer.get( sample );
|
||||
|
||||
mSampleCounter++;
|
||||
|
||||
if( mSampleCounter >= SAMPLE_THRESHOLD )
|
||||
{
|
||||
mSampleCounter = 0;
|
||||
|
||||
update( average );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mSkipCounter++;
|
||||
|
||||
if( mSkipCounter >= mSkipThreshold )
|
||||
{
|
||||
mSkipCounter = 0;
|
||||
|
||||
float average = mBuffer.get( sample );
|
||||
|
||||
mSampleCounter++;
|
||||
|
||||
if( mSampleCounter >= SAMPLE_THRESHOLD )
|
||||
{
|
||||
mSampleCounter = 0;
|
||||
|
||||
update( average );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void update( float average )
|
||||
{
|
||||
mMode = Mode.NORMAL;
|
||||
|
||||
if( average > LARGE_ERROR )
|
||||
{
|
||||
adjust( -LARGE_FREQUENCY_CORRECTION );
|
||||
mMode = Mode.FAST;
|
||||
}
|
||||
else if( average > MEDIUM_ERROR )
|
||||
{
|
||||
adjust( -MEDIUM_FREQUENCY_CORRECTION );
|
||||
mMode = Mode.FAST;
|
||||
}
|
||||
else if( average > SMALL_ERROR )
|
||||
{
|
||||
adjust( -SMALL_FREQUENCY_CORRECTION );
|
||||
}
|
||||
else if( average > FINE_ERROR )
|
||||
{
|
||||
adjust( -FINE_FREQUENCY_CORRECTION );
|
||||
}
|
||||
else if( average < -LARGE_ERROR )
|
||||
{
|
||||
adjust( LARGE_FREQUENCY_CORRECTION );
|
||||
mMode = Mode.FAST;
|
||||
}
|
||||
else if( average < -MEDIUM_ERROR )
|
||||
{
|
||||
adjust( MEDIUM_FREQUENCY_CORRECTION );
|
||||
mMode = Mode.FAST;
|
||||
}
|
||||
else if( average < -SMALL_ERROR )
|
||||
{
|
||||
adjust( SMALL_FREQUENCY_CORRECTION );
|
||||
}
|
||||
else if( average < -FINE_ERROR )
|
||||
{
|
||||
adjust( FINE_FREQUENCY_CORRECTION );
|
||||
}
|
||||
}
|
||||
}
|
||||
128
src/source/tuner/frequency/DCTrackingFrequencyControl.java
Normal file
128
src/source/tuner/frequency/DCTrackingFrequencyControl.java
Normal file
@@ -0,0 +1,128 @@
|
||||
package source.tuner.frequency;
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2016 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/>
|
||||
******************************************************************************/
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import module.Module;
|
||||
import sample.Listener;
|
||||
import sample.real.RealBuffer;
|
||||
import source.tuner.frequency.FrequencyChangeEvent.Event;
|
||||
|
||||
public class DCTrackingFrequencyControl extends Module
|
||||
implements Listener<RealBuffer>, IFrequencyChangeProvider
|
||||
{
|
||||
private static float COARSE_THRESHOLD = 0.1f;
|
||||
private static float LOOP_GAIN = 0.1f;
|
||||
private static float COARSE_GAIN = 1000.0f;
|
||||
private static float FINE_GAIN = 100.0f;
|
||||
private int mErrorCorrection = 0;
|
||||
private int mMaximumFrequencyCorrection = 0;
|
||||
private Listener<FrequencyChangeEvent> mListener;
|
||||
|
||||
/**
|
||||
* DC offset Automatic Frequency Control. Monitors DC bias present in an FM
|
||||
* demodulated audio stream and issues automatic frequency corrections to
|
||||
* maintain the DC bias close to zero.
|
||||
*
|
||||
* @param maximum - maximum allowable (+/-) frequency correction value.
|
||||
*/
|
||||
public DCTrackingFrequencyControl( int maximum )
|
||||
{
|
||||
mMaximumFrequencyCorrection = maximum;
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
mListener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( RealBuffer buffer )
|
||||
{
|
||||
double sum = 0.0d;
|
||||
|
||||
for( float sample: buffer.getSamples() )
|
||||
{
|
||||
sum += sample;
|
||||
}
|
||||
|
||||
float mean = (float)( sum / (double)buffer.getSamples().length );
|
||||
|
||||
float adjustment = 0.0f;
|
||||
|
||||
if( mean > COARSE_THRESHOLD || mean < - COARSE_THRESHOLD )
|
||||
{
|
||||
adjustment = mean * COARSE_GAIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
adjustment = mean * FINE_GAIN;
|
||||
}
|
||||
|
||||
setErrorCorrection( mErrorCorrection + (int)( (float)adjustment * LOOP_GAIN ) );
|
||||
}
|
||||
|
||||
private void setErrorCorrection( int correction )
|
||||
{
|
||||
if( mListener != null )
|
||||
{
|
||||
if( correction > mMaximumFrequencyCorrection )
|
||||
{
|
||||
correction = mMaximumFrequencyCorrection;
|
||||
}
|
||||
else if( correction < -mMaximumFrequencyCorrection )
|
||||
{
|
||||
correction = -mMaximumFrequencyCorrection;
|
||||
}
|
||||
|
||||
if( correction != mErrorCorrection )
|
||||
{
|
||||
mListener.receive( new FrequencyChangeEvent(
|
||||
Event.REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE, correction ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFrequencyChangeListener( Listener<FrequencyChangeEvent> listener )
|
||||
{
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFrequencyChangeListener()
|
||||
{
|
||||
mListener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start( ScheduledExecutorService executor )
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
setErrorCorrection( 0 );
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.tuner.frequency;
|
||||
|
||||
|
||||
public interface FrequencyChangeBroadcaster
|
||||
{
|
||||
public abstract void addListener( FrequencyChangeListener listener );
|
||||
|
||||
public abstract void removeListener( FrequencyChangeListener listener );
|
||||
}
|
||||
@@ -4,11 +4,13 @@ public class FrequencyChangeEvent
|
||||
{
|
||||
public enum Event
|
||||
{
|
||||
FREQUENCY_CHANGE_NOTIFICATION,
|
||||
FREQUENCY_CORRECTION_CHANGE_NOTIFICATION,
|
||||
CHANNEL_FREQUENCY_CORRECTION_CHANGE_NOTIFICATION,
|
||||
CHANNEL_FREQUENCY_CORRECTION_CHANGE_REQUEST,
|
||||
SAMPLE_RATE_CHANGE_NOTIFICATION;
|
||||
NOTIFICATION_FREQUENCY_CHANGE,
|
||||
NOTIFICATION_FREQUENCY_CORRECTION_CHANGE,
|
||||
NOTIFICATION_CHANNEL_FREQUENCY_CORRECTION_CHANGE,
|
||||
NOTIFICATION_SAMPLE_RATE_CHANGE,
|
||||
|
||||
REQUEST_FREQUENCY_CHANGE,
|
||||
REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE;
|
||||
}
|
||||
|
||||
private Event mEvent;
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package source.tuner.frequency;
|
||||
|
||||
import sample.Listener;
|
||||
|
||||
public class FrequencyChangeProcessorWrapper
|
||||
implements IFrequencyChangeListener, Listener<FrequencyChangeEvent>
|
||||
{
|
||||
private IFrequencyChangeProcessor mProcessor;
|
||||
|
||||
/**
|
||||
* Provides IFrequencyChangeListener wrapper for an IFrequencyChangeProcessor
|
||||
*/
|
||||
public FrequencyChangeProcessorWrapper( IFrequencyChangeProcessor handler )
|
||||
{
|
||||
mProcessor = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<FrequencyChangeEvent> getFrequencyChangeListener()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( FrequencyChangeEvent event )
|
||||
{
|
||||
if( mProcessor != null )
|
||||
{
|
||||
mProcessor.frequencyChanged( event );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,8 +37,7 @@ public class FrequencyController
|
||||
private double mFrequencyCorrection = 0d;
|
||||
private int mSampleRate = 0;
|
||||
|
||||
private ArrayList<FrequencyChangeListener> mListeners =
|
||||
new ArrayList<FrequencyChangeListener>();
|
||||
private ArrayList<IFrequencyChangeProcessor> mProcessors = new ArrayList<>();
|
||||
|
||||
public FrequencyController( Tunable tunable,
|
||||
long minFrequency,
|
||||
@@ -181,20 +180,21 @@ public class FrequencyController
|
||||
/**
|
||||
* Adds listener to receive frequency change events
|
||||
*/
|
||||
public void addListener( FrequencyChangeListener listener )
|
||||
//TODO: rename this to addFrequencyChangeProcessor()
|
||||
public void addListener( IFrequencyChangeProcessor processor )
|
||||
{
|
||||
if( !mListeners.contains( listener ) )
|
||||
if( !mProcessors.contains( processor ) )
|
||||
{
|
||||
mListeners.add( listener );
|
||||
mProcessors.add( processor );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes listener from receiving frequency change events
|
||||
*/
|
||||
public void removeListener( FrequencyChangeListener listener )
|
||||
public void removeFrequencyChangeProcessor( IFrequencyChangeProcessor processor )
|
||||
{
|
||||
mListeners.remove( listener );
|
||||
mProcessors.remove( processor );
|
||||
}
|
||||
|
||||
|
||||
@@ -205,7 +205,7 @@ public class FrequencyController
|
||||
protected void broadcastFrequencyChange()
|
||||
{
|
||||
broadcastFrequencyChangeEvent(
|
||||
new FrequencyChangeEvent( Event.FREQUENCY_CHANGE_NOTIFICATION, mFrequency ) );
|
||||
new FrequencyChangeEvent( Event.NOTIFICATION_FREQUENCY_CHANGE, mFrequency ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,7 +214,7 @@ public class FrequencyController
|
||||
protected void broadcastFrequencyErrorChange()
|
||||
{
|
||||
broadcastFrequencyChangeEvent(
|
||||
new FrequencyChangeEvent( Event.FREQUENCY_CORRECTION_CHANGE_NOTIFICATION, mFrequencyCorrection ) );
|
||||
new FrequencyChangeEvent( Event.NOTIFICATION_FREQUENCY_CORRECTION_CHANGE, mFrequencyCorrection ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -223,14 +223,14 @@ public class FrequencyController
|
||||
protected void broadcastSampleRateChange()
|
||||
{
|
||||
broadcastFrequencyChangeEvent(
|
||||
new FrequencyChangeEvent( Event.SAMPLE_RATE_CHANGE_NOTIFICATION, mSampleRate ) );
|
||||
new FrequencyChangeEvent( Event.NOTIFICATION_SAMPLE_RATE_CHANGE, mSampleRate ) );
|
||||
}
|
||||
|
||||
public void broadcastFrequencyChangeEvent( FrequencyChangeEvent event )
|
||||
{
|
||||
for( FrequencyChangeListener listener: mListeners )
|
||||
for( IFrequencyChangeProcessor processor: mProcessors )
|
||||
{
|
||||
listener.frequencyChanged( event );
|
||||
processor.frequencyChanged( event );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
package source.tuner.frequency;
|
||||
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2015 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.tuner.frequency.FrequencyChangeEvent.Event;
|
||||
|
||||
/**
|
||||
* Frequency control for providing frequency error correction to a tuned channel
|
||||
*/
|
||||
public class FrequencyCorrectionControl implements FrequencyChangeListener
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( FrequencyCorrectionControl.class );
|
||||
|
||||
protected FrequencyChangeListener mListener;
|
||||
protected FrequencyCorrectionResetListener mResetListener;
|
||||
|
||||
protected int mChannelFrequencyCorrection = 0;
|
||||
private int mMaximumCorrection = 3000;
|
||||
|
||||
/**
|
||||
* Frequency correction controller.
|
||||
*
|
||||
* @param maximum - defines the maximum +/- allowable frequency correction
|
||||
* value
|
||||
*/
|
||||
public FrequencyCorrectionControl( int maximum )
|
||||
{
|
||||
mMaximumCorrection = maximum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup
|
||||
*/
|
||||
public void dispose()
|
||||
{
|
||||
mListener = null;
|
||||
mResetListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a listener to receive frequency correction events
|
||||
*/
|
||||
public void setFrequencyChangeListener( FrequencyChangeListener listener )
|
||||
{
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a listener to receive frequency correction resets
|
||||
*/
|
||||
public void setListener( FrequencyCorrectionResetListener listener )
|
||||
{
|
||||
mResetListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for source frequency or frequency offset value changes to
|
||||
* reset this frequency controller value to zero.
|
||||
*/
|
||||
@Override
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
Event attribute = event.getEvent();
|
||||
|
||||
switch( attribute )
|
||||
{
|
||||
//Direct the listener to reset when frequency correction (PPM) or
|
||||
//sample rate changes
|
||||
case FREQUENCY_CORRECTION_CHANGE_NOTIFICATION:
|
||||
case SAMPLE_RATE_CHANGE_NOTIFICATION:
|
||||
reset();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets frequency correction value to zero and notifies any reset
|
||||
* listeners
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
if( mResetListener != null )
|
||||
{
|
||||
mResetListener.resetFrequencyCorrection();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets frequency correction to the specified value and broadcasts a change
|
||||
* request
|
||||
*/
|
||||
public void setFrequencyCorrection( int correction )
|
||||
{
|
||||
mChannelFrequencyCorrection = correction;
|
||||
|
||||
/* Limit frequency correction to +/- max correction value */
|
||||
if( mChannelFrequencyCorrection > mMaximumCorrection )
|
||||
{
|
||||
mChannelFrequencyCorrection = mMaximumCorrection;
|
||||
}
|
||||
else if( mChannelFrequencyCorrection < -mMaximumCorrection )
|
||||
{
|
||||
mChannelFrequencyCorrection = -mMaximumCorrection;
|
||||
}
|
||||
|
||||
/* Broadcast a change request */
|
||||
if( mListener != null )
|
||||
{
|
||||
mListener.frequencyChanged( new FrequencyChangeEvent(
|
||||
Event.CHANNEL_FREQUENCY_CORRECTION_CHANGE_REQUEST,
|
||||
mChannelFrequencyCorrection ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the frequency error correction value by the specified adjustment
|
||||
*/
|
||||
public void adjust( int adjustment )
|
||||
{
|
||||
setFrequencyCorrection( getErrorCorrection() + adjustment );
|
||||
}
|
||||
|
||||
/**
|
||||
* Current frequency error correction value
|
||||
* @return
|
||||
*/
|
||||
public int getErrorCorrection()
|
||||
{
|
||||
return mChannelFrequencyCorrection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener interface to be notified when this control is reset to a zero
|
||||
* frequency correction value
|
||||
*/
|
||||
public interface FrequencyCorrectionResetListener
|
||||
{
|
||||
public void resetFrequencyCorrection();
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,8 @@
|
||||
******************************************************************************/
|
||||
package source.tuner.frequency;
|
||||
|
||||
import sample.Listener;
|
||||
|
||||
|
||||
/**
|
||||
* Interface for broadcasting changes to frequency, bandwidth, sample rate,
|
||||
@@ -26,7 +28,7 @@ package source.tuner.frequency;
|
||||
* frequency value. All frequency correction aspects should be handled within
|
||||
* the device that implements the tuning of the frequency.
|
||||
*/
|
||||
public interface FrequencyChangeListener
|
||||
public interface IFrequencyChangeListener
|
||||
{
|
||||
public void frequencyChanged( FrequencyChangeEvent event );
|
||||
public Listener<FrequencyChangeEvent> getFrequencyChangeListener();
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package source.tuner.frequency;
|
||||
|
||||
public interface IFrequencyChangeProcessor
|
||||
{
|
||||
public void frequencyChanged( FrequencyChangeEvent event );
|
||||
}
|
||||
9
src/source/tuner/frequency/IFrequencyChangeProvider.java
Normal file
9
src/source/tuner/frequency/IFrequencyChangeProvider.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package source.tuner.frequency;
|
||||
|
||||
import sample.Listener;
|
||||
|
||||
public interface IFrequencyChangeProvider
|
||||
{
|
||||
public void setFrequencyChangeListener( Listener<FrequencyChangeEvent> listener );
|
||||
public void removeFrequencyChangeListener();
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package source.tuner.frequency;
|
||||
|
||||
|
||||
public interface IFrequencyCorrectionController
|
||||
{
|
||||
public boolean hasFrequencyCorrectionControl();
|
||||
public FrequencyCorrectionControl getFrequencyCorrectionControl();
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
package source.tuner.hackrf;
|
||||
|
||||
/*******************************************************************************
|
||||
* 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/>
|
||||
******************************************************************************/
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.tuner.hackrf.HackRFTunerController.Serial;
|
||||
|
||||
public class HackRFInformationPanel extends JPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( HackRFInformationPanel.class );
|
||||
|
||||
private HackRFTunerController mController;
|
||||
|
||||
/**
|
||||
* Displays HackRF firmware, serial number and part identifier
|
||||
*/
|
||||
public HackRFInformationPanel( HackRFTunerController controller )
|
||||
{
|
||||
mController = controller;
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 2",
|
||||
"[right,grow][grow]",
|
||||
"[][][][grow]" ) );
|
||||
|
||||
Serial serial = null;
|
||||
|
||||
try
|
||||
{
|
||||
serial = mController.getSerial();
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
mLog.error( "couldn't read HackRF serial number", e );
|
||||
}
|
||||
|
||||
if( serial != null )
|
||||
{
|
||||
add( new JLabel( "Serial:" ) );
|
||||
add( new JLabel( serial.getSerialNumber() ) );
|
||||
add( new JLabel( "Part:" ) );
|
||||
add( new JLabel( serial.getPartID() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
add( new JLabel( "Serial:" ) );
|
||||
add( new JLabel( "Unknown" ) );
|
||||
add( new JLabel( "Part:" ) );
|
||||
add( new JLabel( "Unknown" ) );
|
||||
}
|
||||
|
||||
String firmware = null;
|
||||
|
||||
try
|
||||
{
|
||||
firmware = mController.getFirmwareVersion();
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
mLog.error( "couldn't read HackRF firmware version", e );
|
||||
}
|
||||
|
||||
add( new JLabel( "Firmware:" ) );
|
||||
|
||||
if( firmware != null )
|
||||
{
|
||||
add( new JLabel( firmware ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
add( new JLabel( "Unknown" ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,8 +19,6 @@ package source.tuner.hackrf;
|
||||
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -31,26 +29,22 @@ import source.tuner.Tuner;
|
||||
import source.tuner.TunerChannel;
|
||||
import source.tuner.TunerChannelSource;
|
||||
import source.tuner.TunerClass;
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerEvent;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.hackrf.HackRFTunerController.BoardID;
|
||||
import controller.ResourceManager;
|
||||
import controller.ThreadPoolManager;
|
||||
|
||||
public class HackRFTuner extends Tuner
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( HackRFTuner.class );
|
||||
|
||||
private HackRFTunerController mController;
|
||||
|
||||
public HackRFTuner( HackRFTunerController controller ) throws SourceException
|
||||
{
|
||||
super( "HackRF" );
|
||||
|
||||
mController = controller;
|
||||
|
||||
/* Register for frequency/sample rate changes */
|
||||
mController.addListener( this );
|
||||
super( "HackRF", controller );
|
||||
}
|
||||
|
||||
public HackRFTunerController getController()
|
||||
{
|
||||
return (HackRFTunerController)getTunerController();
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
@@ -58,11 +52,6 @@ public class HackRFTuner extends Tuner
|
||||
//TODO: dispose of something here
|
||||
}
|
||||
|
||||
public HackRFTunerController getController()
|
||||
{
|
||||
return mController;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TunerClass getTunerClass()
|
||||
{
|
||||
@@ -75,41 +64,24 @@ public class HackRFTuner extends Tuner
|
||||
return TunerType.HACKRF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JPanel getEditor( ResourceManager resourceManager )
|
||||
{
|
||||
return new HackRFTunerEditorPanel( this, resourceManager );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply( TunerConfiguration config ) throws SourceException
|
||||
{
|
||||
mController.apply( config );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSampleRate()
|
||||
{
|
||||
return mController.getSampleRate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getSampleSize()
|
||||
{
|
||||
return 11.0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFrequency() throws SourceException
|
||||
{
|
||||
return mController.getFrequency();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TunerChannelSource getChannel( TunerChannel channel )
|
||||
throws RejectedExecutionException, SourceException
|
||||
{
|
||||
return mController.getChannel( this, channel );
|
||||
TunerChannelSource source = getController().getChannel( this, channel );
|
||||
|
||||
if( source != null )
|
||||
{
|
||||
broadcast( new TunerEvent( this, TunerEvent.Event.CHANNEL_COUNT ) );
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -121,7 +93,7 @@ public class HackRFTuner extends Tuner
|
||||
/* Tell the controller to release the channel and cleanup */
|
||||
if( source != null )
|
||||
{
|
||||
mController.releaseChannel( source );
|
||||
getController().releaseChannel( source );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +102,7 @@ public class HackRFTuner extends Tuner
|
||||
{
|
||||
try
|
||||
{
|
||||
return mController.getSerial().getSerialNumber();
|
||||
return getController().getSerial().getSerialNumber();
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
@@ -143,12 +115,12 @@ public class HackRFTuner extends Tuner
|
||||
@Override
|
||||
public void addListener( Listener<ComplexBuffer> listener )
|
||||
{
|
||||
mController.addListener( listener );
|
||||
getController().addListener( listener );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener( Listener<ComplexBuffer> listener )
|
||||
{
|
||||
mController.removeListener( listener );
|
||||
getController().removeListener( listener );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ package source.tuner.hackrf;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.configuration.TunerConfiguration;
|
||||
import source.tuner.hackrf.HackRFTunerController.HackRFLNAGain;
|
||||
import source.tuner.hackrf.HackRFTunerController.HackRFSampleRate;
|
||||
import source.tuner.hackrf.HackRFTunerController.HackRFVGAGain;
|
||||
@@ -39,12 +39,11 @@ public class HackRFTunerConfiguration extends TunerConfiguration
|
||||
*/
|
||||
public HackRFTunerConfiguration()
|
||||
{
|
||||
this( "Default" );
|
||||
}
|
||||
|
||||
public HackRFTunerConfiguration( String name )
|
||||
public HackRFTunerConfiguration( String uniqueID, String name )
|
||||
{
|
||||
super( name );
|
||||
super( uniqueID, name );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,562 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.tuner.hackrf;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.ComboBoxModel;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.JToggleButton;
|
||||
import javax.swing.SpinnerModel;
|
||||
import javax.swing.SpinnerNumberModel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.usb.UsbException;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerConfigurationAssignment;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.hackrf.HackRFTunerController.HackRFLNAGain;
|
||||
import source.tuner.hackrf.HackRFTunerController.HackRFSampleRate;
|
||||
import source.tuner.hackrf.HackRFTunerController.HackRFVGAGain;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class HackRFTunerConfigurationPanel extends JPanel
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( HackRFTunerConfigurationPanel.class );
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private ResourceManager mResourceManager;
|
||||
private HackRFTunerController mController;
|
||||
private HackRFTunerConfiguration mSelectedConfig;
|
||||
|
||||
private JButton mNewConfiguration;
|
||||
private JButton mDeleteConfiguration;
|
||||
private JComboBox<HackRFTunerConfiguration> mComboConfigurations;
|
||||
|
||||
private JTextField mName;
|
||||
|
||||
private JSpinner mFrequencyCorrection;
|
||||
private JToggleButton mAmplifier;
|
||||
private JComboBox<HackRFLNAGain> mComboLNAGain;
|
||||
private JComboBox<HackRFVGAGain> mComboVGAGain;
|
||||
|
||||
private JComboBox<HackRFSampleRate> mComboSampleRate;
|
||||
|
||||
public HackRFTunerConfigurationPanel( ResourceManager resourceManager,
|
||||
HackRFTunerController controller )
|
||||
{
|
||||
mResourceManager = resourceManager;
|
||||
mController = controller;
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the gui components
|
||||
*/
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 2", "[grow,right][grow]", "[][][][][][][grow]" ) );
|
||||
|
||||
/**
|
||||
* Tuner configuration selector
|
||||
*/
|
||||
mComboConfigurations = new JComboBox<HackRFTunerConfiguration>();
|
||||
|
||||
mComboConfigurations.setModel( getModel() );
|
||||
|
||||
/* Determine which tuner configuration should be selected/displayed */
|
||||
TunerConfigurationAssignment savedConfig = null;
|
||||
String serial = null;
|
||||
|
||||
try
|
||||
{
|
||||
serial = mController.getSerial().getSerialNumber();
|
||||
}
|
||||
catch ( UsbException e2 )
|
||||
{
|
||||
mLog.error( "couldn't read hackrf serial number", e2 );
|
||||
}
|
||||
|
||||
if( serial != null )
|
||||
{
|
||||
savedConfig = mResourceManager
|
||||
.getSettingsManager().getSelectedTunerConfiguration(
|
||||
TunerType.HACKRF, serial );
|
||||
}
|
||||
|
||||
if( savedConfig != null )
|
||||
{
|
||||
mSelectedConfig = getNamedConfiguration(
|
||||
savedConfig.getTunerConfigurationName() );
|
||||
}
|
||||
|
||||
/* If we couldn't determine the saved/selected config, use the first one */
|
||||
if( mSelectedConfig == null )
|
||||
{
|
||||
mSelectedConfig = mComboConfigurations.getItemAt( 0 );
|
||||
|
||||
//Store this config as the default for this tuner at this address
|
||||
|
||||
if( serial != null )
|
||||
{
|
||||
mResourceManager.getSettingsManager()
|
||||
.setSelectedTunerConfiguration( TunerType.HACKRF,
|
||||
serial, mSelectedConfig );
|
||||
}
|
||||
}
|
||||
|
||||
mComboConfigurations.setSelectedItem( mSelectedConfig );
|
||||
|
||||
mComboConfigurations.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
HackRFTunerConfiguration selected =
|
||||
(HackRFTunerConfiguration)mComboConfigurations
|
||||
.getItemAt( mComboConfigurations.getSelectedIndex() );
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
update( selected );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
add( new JLabel( "Config:" ) );
|
||||
add( mComboConfigurations, "growx,push" );
|
||||
|
||||
|
||||
/**
|
||||
* Tuner Configuration Name
|
||||
*/
|
||||
mName = new JTextField();
|
||||
mName.setText( mSelectedConfig.getName() );
|
||||
|
||||
mName.addFocusListener( new FocusListener()
|
||||
{
|
||||
@Override
|
||||
public void focusLost( FocusEvent e )
|
||||
{
|
||||
mSelectedConfig.setName( mName.getText() );
|
||||
save();
|
||||
}
|
||||
@Override
|
||||
public void focusGained( FocusEvent e ) {}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Name:" ) );
|
||||
add( mName, "growx,push" );
|
||||
|
||||
/**
|
||||
* Frequency Correction
|
||||
*/
|
||||
SpinnerModel model =
|
||||
new SpinnerNumberModel( 0.0, //initial value
|
||||
-1000.0, //min
|
||||
1000.0, //max
|
||||
0.1 ); //step
|
||||
|
||||
mFrequencyCorrection = new JSpinner( model );
|
||||
|
||||
JSpinner.NumberEditor editor =
|
||||
(JSpinner.NumberEditor)mFrequencyCorrection.getEditor();
|
||||
|
||||
DecimalFormat format = editor.getFormat();
|
||||
format.setMinimumFractionDigits( 1 );
|
||||
editor.getTextField().setHorizontalAlignment( SwingConstants.CENTER );
|
||||
|
||||
mFrequencyCorrection.setValue( mSelectedConfig.getFrequencyCorrection() );
|
||||
|
||||
mFrequencyCorrection.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
final double value = ((SpinnerNumberModel)mFrequencyCorrection
|
||||
.getModel()).getNumber().doubleValue();
|
||||
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
mController.setFrequencyCorrection( value );
|
||||
mSelectedConfig.setFrequencyCorrection( value );
|
||||
save();
|
||||
}
|
||||
catch ( SourceException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
HackRFTunerConfigurationPanel.this,
|
||||
"HackRF Tuner Controller - couldn't apply "
|
||||
+ "frequency correction value: " + value +
|
||||
e1.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "HackRF Tuner Controller - couldn't apply "
|
||||
+ "frequency correction value: " + value, e1 );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Correction PPM:" ) );
|
||||
add( mFrequencyCorrection, "growx,push" );
|
||||
|
||||
/**
|
||||
* Sample Rate
|
||||
*/
|
||||
mComboSampleRate = new JComboBox<>( HackRFSampleRate.values() );
|
||||
mComboSampleRate.setSelectedItem( mSelectedConfig.getSampleRate() );
|
||||
mComboSampleRate.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
HackRFSampleRate sampleRate =
|
||||
(HackRFSampleRate)mComboSampleRate.getSelectedItem();
|
||||
try
|
||||
{
|
||||
|
||||
mController.setSampleRate( sampleRate );
|
||||
|
||||
mSelectedConfig.setSampleRate( sampleRate );
|
||||
save();
|
||||
}
|
||||
catch ( UsbException e2 )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
HackRFTunerConfigurationPanel.this,
|
||||
"HackRF Tuner Controller - couldn't apply the sample "
|
||||
+ "rate setting [" + sampleRate.getLabel() + "] " +
|
||||
e2.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "HackRF Tuner Controller - couldn't apply sample "
|
||||
+ "rate setting [" + sampleRate.getLabel() + "]", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
add( new JLabel( "Sample Rate:" ) );
|
||||
add( mComboSampleRate, "growx,push" );
|
||||
|
||||
/**
|
||||
* Gain Controls
|
||||
*/
|
||||
JPanel gainPanel = new JPanel();
|
||||
gainPanel.setLayout( new MigLayout( "",
|
||||
"[][right][grow,fill][right][grow,fill]", "[grow,fill]" ) );
|
||||
gainPanel.setBorder( BorderFactory.createTitledBorder( "Gain" ) );
|
||||
|
||||
/* Amplifier */
|
||||
mAmplifier = new JToggleButton( "Amp" );
|
||||
mAmplifier.setSelected( mSelectedConfig.getAmplifierEnabled() );
|
||||
mAmplifier.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
try
|
||||
{
|
||||
mController.setAmplifierEnabled( mAmplifier.isSelected() );
|
||||
mSelectedConfig.setAmplifierEnabled( mAmplifier.isSelected() );
|
||||
save();
|
||||
}
|
||||
catch ( UsbException e )
|
||||
{
|
||||
mLog.error( "couldn't enable/disable amplifier", e );
|
||||
mAmplifier.setEnabled( !mAmplifier.isSelected() );
|
||||
|
||||
JOptionPane.showMessageDialog(
|
||||
HackRFTunerConfigurationPanel.this,
|
||||
"Couldn't change amplifier setting",
|
||||
"Error changing amplifier setting",
|
||||
JOptionPane.ERROR_MESSAGE );
|
||||
}
|
||||
}
|
||||
} );
|
||||
gainPanel.add( mAmplifier );
|
||||
|
||||
/* LNA Gain Control */
|
||||
mComboLNAGain = new JComboBox<HackRFLNAGain>( HackRFLNAGain.values() );
|
||||
mComboLNAGain.setSelectedItem( mSelectedConfig.getLNAGain() );
|
||||
mComboLNAGain.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
try
|
||||
{
|
||||
HackRFLNAGain lnaGain =
|
||||
(HackRFLNAGain)mComboLNAGain.getSelectedItem();
|
||||
|
||||
if ( lnaGain == null )
|
||||
{
|
||||
lnaGain = HackRFLNAGain.GAIN_0;
|
||||
}
|
||||
|
||||
if( mComboLNAGain.isEnabled() )
|
||||
{
|
||||
mController.setLNAGain( lnaGain );
|
||||
}
|
||||
|
||||
mSelectedConfig.setLNAGain( lnaGain );
|
||||
|
||||
save();
|
||||
}
|
||||
catch ( UsbException e )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
HackRFTunerConfigurationPanel.this,
|
||||
"HackRF Tuner Controller - couldn't apply the LNA "
|
||||
+ "gain setting - " + e.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "HackRF Tuner Controller - couldn't apply LNA "
|
||||
+ "gain setting - ", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
mComboLNAGain.setToolTipText( "<html>LNA Gain. Adjust to set "
|
||||
+ "the IF gain</html>" );
|
||||
gainPanel.add( new JLabel( "LNA" ) );
|
||||
gainPanel.add( mComboLNAGain );
|
||||
|
||||
/* VGA Gain Control */
|
||||
mComboVGAGain = new JComboBox<HackRFVGAGain>( HackRFVGAGain.values() );
|
||||
mComboVGAGain.setSelectedItem( mSelectedConfig.getVGAGain() );
|
||||
mComboVGAGain.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
try
|
||||
{
|
||||
HackRFVGAGain vgaGain = (HackRFVGAGain)mComboVGAGain.getSelectedItem();
|
||||
|
||||
if( vgaGain == null )
|
||||
{
|
||||
vgaGain = HackRFVGAGain.GAIN_4;
|
||||
}
|
||||
|
||||
if( mComboVGAGain.isEnabled() )
|
||||
{
|
||||
mController.setVGAGain( vgaGain );
|
||||
}
|
||||
|
||||
mSelectedConfig.setVGAGain( vgaGain );
|
||||
save();
|
||||
}
|
||||
catch ( UsbException e )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
HackRFTunerConfigurationPanel.this,
|
||||
"HackRF Tuner Controller - couldn't apply the VGA "
|
||||
+ "gain setting - " + e.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "HackRF Tuner Controller - couldn't apply VGA "
|
||||
+ "gain setting", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
mComboVGAGain.setToolTipText( "<html>VGA Gain. Adjust to set the "
|
||||
+ "baseband gain</html>" );
|
||||
gainPanel.add( new JLabel( "VGA" ) );
|
||||
gainPanel.add( mComboVGAGain, "wrap" );
|
||||
|
||||
add( gainPanel, "span,growx" );
|
||||
|
||||
/**
|
||||
* Create a new configuration
|
||||
*/
|
||||
mNewConfiguration = new JButton( "New" );
|
||||
|
||||
mNewConfiguration.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
TunerConfiguration config =
|
||||
mResourceManager.getSettingsManager()
|
||||
.addNewTunerConfiguration(
|
||||
TunerType.HACKRF,
|
||||
"New Configuration" );
|
||||
|
||||
mComboConfigurations.setModel( getModel() );
|
||||
|
||||
mComboConfigurations.setSelectedItem( config );
|
||||
|
||||
repaint();
|
||||
}
|
||||
} );
|
||||
|
||||
add( mNewConfiguration, "growx,push" );
|
||||
|
||||
/**
|
||||
* Delete the currently selected configuration
|
||||
*/
|
||||
mDeleteConfiguration = new JButton( "Delete" );
|
||||
|
||||
mDeleteConfiguration.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
HackRFTunerConfiguration selected =
|
||||
(HackRFTunerConfiguration)mComboConfigurations
|
||||
.getItemAt( mComboConfigurations.getSelectedIndex() );
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
int n = JOptionPane.showConfirmDialog(
|
||||
HackRFTunerConfigurationPanel.this,
|
||||
"Are you sure you want to delete '"
|
||||
+ selected.getName() + "'?",
|
||||
"Are you sure?",
|
||||
JOptionPane.YES_NO_OPTION );
|
||||
|
||||
if( n == JOptionPane.YES_OPTION )
|
||||
{
|
||||
mResourceManager.getSettingsManager()
|
||||
.deleteTunerConfiguration( selected );
|
||||
|
||||
mComboConfigurations.setModel( getModel() );
|
||||
|
||||
mComboConfigurations.setSelectedIndex( 0 );
|
||||
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mDeleteConfiguration, "growx,push,wrap" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates gui controls with the values from the tuner configuration
|
||||
* @param config - tuner configuration
|
||||
*/
|
||||
private void update( HackRFTunerConfiguration config )
|
||||
{
|
||||
mSelectedConfig = config;
|
||||
|
||||
try
|
||||
{
|
||||
mController.apply( config );
|
||||
|
||||
mName.setText( config.getName() );
|
||||
mFrequencyCorrection.setValue( config.getFrequencyCorrection() );
|
||||
|
||||
mComboLNAGain.setSelectedItem( mSelectedConfig.getLNAGain() );
|
||||
mComboVGAGain.setSelectedItem( mSelectedConfig.getVGAGain() );
|
||||
|
||||
mComboSampleRate.setSelectedItem( mSelectedConfig.getSampleRate() );
|
||||
|
||||
mResourceManager.getSettingsManager().setSelectedTunerConfiguration(
|
||||
TunerType.HACKRF, mController.getSerial().getSerialNumber(), config );
|
||||
}
|
||||
catch ( UsbException | SourceException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
HackRFTunerConfigurationPanel.this,
|
||||
"HackRF Tuner Controller - couldn't "
|
||||
+ "apply the tuner configuration settings - " +
|
||||
e1.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "HackRF Tuner Controller - couldn't apply "
|
||||
+ "config [" + config.getName() + "]", e1 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a combo box model for the tuner configuration combo component
|
||||
* by assembling a list of the tuner configurations appropriate for this
|
||||
* specific tuner
|
||||
*/
|
||||
private ComboBoxModel<HackRFTunerConfiguration> getModel()
|
||||
{
|
||||
ArrayList<TunerConfiguration> configs =
|
||||
mResourceManager.getSettingsManager()
|
||||
.getTunerConfigurations( TunerType.HACKRF );
|
||||
|
||||
DefaultComboBoxModel<HackRFTunerConfiguration> model =
|
||||
new DefaultComboBoxModel<HackRFTunerConfiguration>();
|
||||
|
||||
for( TunerConfiguration config: configs )
|
||||
{
|
||||
model.addElement( (HackRFTunerConfiguration)config );
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a specific (named) tuner configuration
|
||||
*/
|
||||
private HackRFTunerConfiguration getNamedConfiguration( String name )
|
||||
{
|
||||
ArrayList<TunerConfiguration> configs =
|
||||
mResourceManager.getSettingsManager()
|
||||
.getTunerConfigurations( TunerType.HACKRF );
|
||||
|
||||
for( TunerConfiguration config: configs )
|
||||
{
|
||||
if( config.getName().contentEquals( name ) )
|
||||
{
|
||||
return (HackRFTunerConfiguration)config;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves current tuner configuration settings
|
||||
*/
|
||||
private void save()
|
||||
{
|
||||
mResourceManager.getSettingsManager().save();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
package source.tuner.hackrf;
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
@@ -52,12 +51,13 @@ package source.tuner.hackrf;
|
||||
* 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 source.tuner.hackrf;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.LinkedTransferQueue;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -81,8 +81,8 @@ import sample.Listener;
|
||||
import sample.adapter.ByteSampleAdapter;
|
||||
import sample.complex.ComplexBuffer;
|
||||
import source.SourceException;
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerController;
|
||||
import source.tuner.configuration.TunerConfiguration;
|
||||
import controller.ThreadPoolManager;
|
||||
import controller.ThreadPoolManager.ThreadType;
|
||||
|
||||
@@ -92,7 +92,7 @@ public class HackRFTunerController extends TunerController
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( HackRFTunerController.class );
|
||||
|
||||
public final static long USB_TIMEOUT_MS = 1000000l; //uSeconds
|
||||
public final static long USB_TIMEOUT_US = 1000000l; //uSeconds
|
||||
public static final byte USB_ENDPOINT = (byte)0x81;
|
||||
public static final byte USB_INTERFACE = (byte)0x0;
|
||||
|
||||
@@ -395,7 +395,7 @@ public class HackRFTunerController extends TunerController
|
||||
(short)value,
|
||||
(short)index,
|
||||
buffer,
|
||||
USB_TIMEOUT_MS );
|
||||
USB_TIMEOUT_US );
|
||||
|
||||
if( transferred < 0 )
|
||||
{
|
||||
@@ -468,7 +468,7 @@ public class HackRFTunerController extends TunerController
|
||||
(short)value,
|
||||
(short)index,
|
||||
buffer,
|
||||
USB_TIMEOUT_MS );
|
||||
USB_TIMEOUT_US );
|
||||
|
||||
if( transferred < 0 )
|
||||
{
|
||||
@@ -887,8 +887,8 @@ public class HackRFTunerController extends TunerController
|
||||
*/
|
||||
public void addListener( Listener<ComplexBuffer> listener )
|
||||
{
|
||||
synchronized( mComplexBufferBroadcaster )
|
||||
{
|
||||
synchronized ( mComplexBufferBroadcaster )
|
||||
{
|
||||
mComplexBufferBroadcaster.addListener( listener );
|
||||
|
||||
if( mBufferProcessor == null || !mBufferProcessor.isRunning() )
|
||||
@@ -901,7 +901,7 @@ public class HackRFTunerController extends TunerController
|
||||
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -910,15 +910,15 @@ public class HackRFTunerController extends TunerController
|
||||
*/
|
||||
public void removeListener( Listener<ComplexBuffer> listener )
|
||||
{
|
||||
synchronized( mComplexBufferBroadcaster )
|
||||
{
|
||||
synchronized ( mComplexBufferBroadcaster )
|
||||
{
|
||||
mComplexBufferBroadcaster.removeListener( listener );
|
||||
|
||||
if( !mComplexBufferBroadcaster.hasListeners() )
|
||||
{
|
||||
mBufferProcessor.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -928,12 +928,12 @@ public class HackRFTunerController extends TunerController
|
||||
public class BufferProcessor implements Runnable, TransferCallback
|
||||
{
|
||||
private ScheduledFuture<?> mSampleDispatcherTask;
|
||||
private AtomicBoolean mRunning = new AtomicBoolean();
|
||||
private LinkedTransferQueue<Transfer> mAvailableTransfers;
|
||||
private LinkedTransferQueue<Transfer> mTransfersInProgress = new LinkedTransferQueue<>();
|
||||
private AtomicBoolean mRunning = new AtomicBoolean();
|
||||
private ByteBuffer mLibUsbHandlerStatus;
|
||||
private boolean mCancel = false;
|
||||
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
@@ -955,23 +955,23 @@ public class HackRFTunerController extends TunerController
|
||||
{
|
||||
mAvailableTransfers.drainTo( transfers );
|
||||
|
||||
for( Transfer transfer: transfers )
|
||||
{
|
||||
int result = LibUsb.submitTransfer( transfer );
|
||||
|
||||
if( result == LibUsb.SUCCESS )
|
||||
{
|
||||
mTransfersInProgress.add( transfer );
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.error( "error submitting transfer [" +
|
||||
LibUsb.errorName( result ) + "]" );
|
||||
}
|
||||
}
|
||||
for( Transfer transfer: transfers )
|
||||
{
|
||||
int result = LibUsb.submitTransfer( transfer );
|
||||
|
||||
if( result == LibUsb.SUCCESS )
|
||||
{
|
||||
mTransfersInProgress.add( transfer );
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.error( "error submitting transfer [" +
|
||||
LibUsb.errorName( result ) + "]" );
|
||||
}
|
||||
}
|
||||
|
||||
int result = LibUsb.handleEventsTimeoutCompleted(
|
||||
null, USB_TIMEOUT_MS, mLibUsbHandlerStatus.asIntBuffer() );
|
||||
null, USB_TIMEOUT_US, mLibUsbHandlerStatus.asIntBuffer() );
|
||||
|
||||
if( result != LibUsb.SUCCESS )
|
||||
{
|
||||
@@ -990,16 +990,16 @@ public class HackRFTunerController extends TunerController
|
||||
LibUsb.cancelTransfer( transfer );
|
||||
}
|
||||
|
||||
int result = LibUsb.handleEventsTimeoutCompleted(
|
||||
null, USB_TIMEOUT_MS, mLibUsbHandlerStatus.asIntBuffer() );
|
||||
int result = LibUsb.handleEventsTimeoutCompleted( null,
|
||||
USB_TIMEOUT_US, mLibUsbHandlerStatus.asIntBuffer() );
|
||||
|
||||
if( result != LibUsb.SUCCESS )
|
||||
{
|
||||
mLog.error( "error cancelling transfers in progress" );
|
||||
}
|
||||
|
||||
mLibUsbHandlerStatus.rewind();
|
||||
}
|
||||
{
|
||||
mLog.error( "error cancelling transfers in progress" );
|
||||
}
|
||||
|
||||
mLibUsbHandlerStatus.rewind();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1089,7 +1089,7 @@ public class HackRFTunerController extends TunerController
|
||||
ByteBuffer.allocateDirect( mBufferSize );
|
||||
|
||||
LibUsb.fillBulkTransfer( transfer, mDeviceHandle,USB_ENDPOINT,
|
||||
buffer, BufferProcessor.this, "Buffer", USB_TIMEOUT_MS );
|
||||
buffer, BufferProcessor.this, "Buffer", USB_TIMEOUT_US );
|
||||
|
||||
mAvailableTransfers.add( transfer );
|
||||
}
|
||||
|
||||
464
src/source/tuner/hackrf/HackRFTunerEditor.java
Normal file
464
src/source/tuner/hackrf/HackRFTunerEditor.java
Normal file
@@ -0,0 +1,464 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 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 source.tuner.hackrf;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.JToggleButton;
|
||||
import javax.swing.SpinnerModel;
|
||||
import javax.swing.SpinnerNumberModel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.usb.UsbException;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.configuration.TunerConfiguration;
|
||||
import source.tuner.configuration.TunerConfigurationEditor;
|
||||
import source.tuner.configuration.TunerConfigurationEvent;
|
||||
import source.tuner.configuration.TunerConfigurationEvent.Event;
|
||||
import source.tuner.configuration.TunerConfigurationModel;
|
||||
import source.tuner.hackrf.HackRFTunerController.BoardID;
|
||||
import source.tuner.hackrf.HackRFTunerController.HackRFLNAGain;
|
||||
import source.tuner.hackrf.HackRFTunerController.HackRFSampleRate;
|
||||
import source.tuner.hackrf.HackRFTunerController.HackRFVGAGain;
|
||||
import source.tuner.hackrf.HackRFTunerController.Serial;
|
||||
|
||||
public class HackRFTunerEditor extends TunerConfigurationEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final static Logger mLog = LoggerFactory.getLogger( HackRFTunerEditor.class );
|
||||
|
||||
private JTextField mConfigurationName;
|
||||
private JButton mTunerInfo;
|
||||
private JComboBox<HackRFSampleRate> mComboSampleRate;
|
||||
private JSpinner mFrequencyCorrection;
|
||||
private JToggleButton mAmplifier;
|
||||
private JComboBox<HackRFLNAGain> mComboLNAGain;
|
||||
private JComboBox<HackRFVGAGain> mComboVGAGain;
|
||||
private boolean mLoading;
|
||||
|
||||
private HackRFTunerController mController;
|
||||
|
||||
public HackRFTunerEditor( TunerConfigurationModel tunerConfigurationModel, HackRFTuner tuner )
|
||||
{
|
||||
super( tunerConfigurationModel );
|
||||
|
||||
mController = tuner.getController();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
private HackRFTunerConfiguration getConfiguration()
|
||||
{
|
||||
if( hasItem() )
|
||||
{
|
||||
return (HackRFTunerConfiguration)getItem();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 4", "[right][grow,fill][right][grow,fill]",
|
||||
"[][][][][][][grow]" ) );
|
||||
|
||||
add( new JLabel( "HackRF Tuner Configuration" ), "span,align center" );
|
||||
|
||||
mConfigurationName = new JTextField();
|
||||
mConfigurationName.setEnabled( false );
|
||||
mConfigurationName.addFocusListener( new FocusListener()
|
||||
{
|
||||
@Override
|
||||
public void focusLost( FocusEvent e )
|
||||
{
|
||||
save();
|
||||
}
|
||||
@Override
|
||||
public void focusGained( FocusEvent e ) {}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Name:" ) );
|
||||
add( mConfigurationName, "span 2" );
|
||||
|
||||
mTunerInfo = new JButton( "Tuner Info" );
|
||||
mTunerInfo.setEnabled( false );
|
||||
mTunerInfo.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
JOptionPane.showMessageDialog( HackRFTunerEditor.this, getTunerInfo(),
|
||||
"Tuner Info", JOptionPane.INFORMATION_MESSAGE );
|
||||
}
|
||||
} );
|
||||
add( mTunerInfo );
|
||||
|
||||
mComboSampleRate = new JComboBox<>( HackRFSampleRate.values() );
|
||||
mComboSampleRate.setEnabled( false );
|
||||
mComboSampleRate.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
HackRFSampleRate sampleRate =
|
||||
(HackRFSampleRate)mComboSampleRate.getSelectedItem();
|
||||
try
|
||||
{
|
||||
|
||||
mController.setSampleRate( sampleRate );
|
||||
save();
|
||||
}
|
||||
catch ( UsbException e2 )
|
||||
{
|
||||
JOptionPane.showMessageDialog( HackRFTunerEditor.this, "HackRF Tuner Controller"
|
||||
+ " - couldn't apply the sample rate setting [" + sampleRate.getLabel() +
|
||||
"] " + e2.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "HackRF Tuner Controller - couldn't apply sample rate setting [" +
|
||||
sampleRate.getLabel() + "]", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
add( new JLabel( "Sample Rate:" ) );
|
||||
add( mComboSampleRate );
|
||||
|
||||
SpinnerModel model = new SpinnerNumberModel( 0.0, //initial value
|
||||
-1000.0, //min
|
||||
1000.0, //max
|
||||
0.1 ); //step
|
||||
|
||||
mFrequencyCorrection = new JSpinner( model );
|
||||
mFrequencyCorrection.setEnabled( false );
|
||||
JSpinner.NumberEditor editor = (JSpinner.NumberEditor)mFrequencyCorrection.getEditor();
|
||||
|
||||
DecimalFormat format = editor.getFormat();
|
||||
format.setMinimumFractionDigits( 1 );
|
||||
editor.getTextField().setHorizontalAlignment( SwingConstants.CENTER );
|
||||
|
||||
mFrequencyCorrection.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
final double value = ((SpinnerNumberModel)mFrequencyCorrection
|
||||
.getModel()).getNumber().doubleValue();
|
||||
|
||||
try
|
||||
{
|
||||
mController.setFrequencyCorrection( value );
|
||||
save();
|
||||
}
|
||||
catch ( SourceException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog( HackRFTunerEditor.this, "HackRF Tuner Controller"
|
||||
+ " - couldn't apply frequency correction value: " + value +
|
||||
e1.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "HackRF Tuner Controller - couldn't apply frequency correction "
|
||||
+ "value: " + value, e1 );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "PPM:" ) );
|
||||
add( mFrequencyCorrection );
|
||||
|
||||
add( new JSeparator( JSeparator.HORIZONTAL ), "span,grow" );
|
||||
add( new JLabel( "Gain" ) );
|
||||
add( new JLabel( "" ), "span 2" ); //filler
|
||||
|
||||
mAmplifier = new JToggleButton( "Amplifier" );
|
||||
mAmplifier.setEnabled( false );
|
||||
mAmplifier.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
try
|
||||
{
|
||||
mController.setAmplifierEnabled( mAmplifier.isSelected() );
|
||||
save();
|
||||
}
|
||||
catch ( UsbException e )
|
||||
{
|
||||
mLog.error( "couldn't enable/disable amplifier", e );
|
||||
|
||||
JOptionPane.showMessageDialog( HackRFTunerEditor.this, "Couldn't change amplifier setting",
|
||||
"Error changing amplifier setting", JOptionPane.ERROR_MESSAGE );
|
||||
}
|
||||
}
|
||||
} );
|
||||
add( mAmplifier );
|
||||
|
||||
mComboLNAGain = new JComboBox<HackRFLNAGain>( HackRFLNAGain.values() );
|
||||
mComboLNAGain.setEnabled( false );
|
||||
mComboLNAGain.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
try
|
||||
{
|
||||
HackRFLNAGain lnaGain = (HackRFLNAGain)mComboLNAGain.getSelectedItem();
|
||||
|
||||
if ( lnaGain == null )
|
||||
{
|
||||
lnaGain = HackRFLNAGain.GAIN_0;
|
||||
}
|
||||
|
||||
mController.setLNAGain( lnaGain );
|
||||
save();
|
||||
}
|
||||
catch ( UsbException e )
|
||||
{
|
||||
JOptionPane.showMessageDialog( HackRFTunerEditor.this, "HackRF Tuner Controller"
|
||||
+ " - couldn't apply the LNA gain setting - " + e.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "HackRF Tuner Controller - couldn't apply LNA gain setting - ", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
mComboLNAGain.setToolTipText( "<html>LNA Gain. Adjust to set the IF gain</html>" );
|
||||
add( new JLabel( "LNA:" ) );
|
||||
add( mComboLNAGain );
|
||||
|
||||
mComboVGAGain = new JComboBox<HackRFVGAGain>( HackRFVGAGain.values() );
|
||||
mComboVGAGain.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
try
|
||||
{
|
||||
HackRFVGAGain vgaGain = (HackRFVGAGain)mComboVGAGain.getSelectedItem();
|
||||
|
||||
if( vgaGain == null )
|
||||
{
|
||||
vgaGain = HackRFVGAGain.GAIN_4;
|
||||
}
|
||||
|
||||
mController.setVGAGain( vgaGain );
|
||||
save();
|
||||
}
|
||||
catch ( UsbException e )
|
||||
{
|
||||
JOptionPane.showMessageDialog( HackRFTunerEditor.this, "HackRF Tuner Controller"
|
||||
+ " - couldn't apply the VGA gain setting - " + e.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "HackRF Tuner Controller - couldn't apply VGA gain setting", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
mComboVGAGain.setToolTipText( "<html>VGA Gain. Adjust to set the baseband gain</html>" );
|
||||
add( new JLabel( "VGA:" ) );
|
||||
add( mComboVGAGain );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets each of the tuner configuration controls to the enabled argument state
|
||||
*/
|
||||
private void setControlsEnabled( boolean enabled )
|
||||
{
|
||||
if( mConfigurationName.isEnabled() != enabled )
|
||||
{
|
||||
mConfigurationName.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mTunerInfo.isEnabled() != enabled )
|
||||
{
|
||||
mTunerInfo.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mFrequencyCorrection.isEnabled() != enabled )
|
||||
{
|
||||
mFrequencyCorrection.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mComboSampleRate.isEnabled() != enabled )
|
||||
{
|
||||
mComboSampleRate.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mAmplifier.isEnabled() != enabled )
|
||||
{
|
||||
mAmplifier.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mComboLNAGain.isEnabled() != enabled )
|
||||
{
|
||||
mComboLNAGain.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mComboVGAGain.isEnabled() != enabled )
|
||||
{
|
||||
mComboVGAGain.setEnabled( enabled );
|
||||
}
|
||||
}
|
||||
|
||||
private String getTunerInfo()
|
||||
{
|
||||
BoardID board = BoardID.INVALID;
|
||||
|
||||
try
|
||||
{
|
||||
board = mController.getBoardID();
|
||||
}
|
||||
catch ( UsbException e )
|
||||
{
|
||||
mLog.error( "couldn't read HackRF board identifier", e );
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "<html><h3>HackRF Tuner</h3>" );
|
||||
|
||||
sb.append( "<b>Board: </b>" );
|
||||
sb.append( board.getLabel() );
|
||||
sb.append( "<br>" );
|
||||
|
||||
Serial serial = null;
|
||||
|
||||
try
|
||||
{
|
||||
serial = mController.getSerial();
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
mLog.error( "couldn't read HackRF serial number", e );
|
||||
}
|
||||
|
||||
if( serial != null )
|
||||
{
|
||||
sb.append( "<b>Serial: </b>" );
|
||||
sb.append( serial.getSerialNumber() );
|
||||
sb.append( "<br>" );
|
||||
|
||||
sb.append( "<b>Part: </b>" );
|
||||
sb.append( serial.getPartID() );
|
||||
sb.append( "<br>" );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "<b>Serial: Unknown</b><br>" );
|
||||
sb.append( "<b>Part: Unknown</b><br>" );
|
||||
}
|
||||
|
||||
String firmware = null;
|
||||
|
||||
try
|
||||
{
|
||||
firmware = mController.getFirmwareVersion();
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
mLog.error( "couldn't read HackRF firmware version", e );
|
||||
}
|
||||
|
||||
if( firmware != null )
|
||||
{
|
||||
sb.append( "<b>Firmware: </b>" );
|
||||
sb.append( firmware );
|
||||
sb.append( "<br>" );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "<b>Firmware: Unknown</b><br>" );
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem( TunerConfiguration tunerConfiguration )
|
||||
{
|
||||
super.setItem( tunerConfiguration );
|
||||
|
||||
//Toggle loading so that we don't fire a change event and schedule a settings file save
|
||||
mLoading = true;
|
||||
|
||||
if( hasItem() )
|
||||
{
|
||||
HackRFTunerConfiguration config = getConfiguration();
|
||||
|
||||
if( tunerConfiguration.isAssigned() )
|
||||
{
|
||||
setControlsEnabled( true );
|
||||
|
||||
mConfigurationName.setText( config.getName() );
|
||||
mComboSampleRate.setSelectedItem( config.getSampleRate() );
|
||||
mFrequencyCorrection.setValue( config.getFrequencyCorrection() );
|
||||
mAmplifier.setSelected( config.getAmplifierEnabled() );
|
||||
mComboLNAGain.setSelectedItem( config.getLNAGain() );
|
||||
mComboVGAGain.setSelectedItem( config.getVGAGain() );
|
||||
}
|
||||
else
|
||||
{
|
||||
setControlsEnabled( false );
|
||||
mConfigurationName.setText( config.getName() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setControlsEnabled( false );
|
||||
mConfigurationName.setText( "" );
|
||||
}
|
||||
|
||||
mLoading = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
if( hasItem() && !mLoading )
|
||||
{
|
||||
HackRFTunerConfiguration config = getConfiguration();
|
||||
|
||||
config.setName( mConfigurationName.getText() );
|
||||
|
||||
double value = ((SpinnerNumberModel)mFrequencyCorrection
|
||||
.getModel()).getNumber().doubleValue();
|
||||
config.setFrequencyCorrection( value );
|
||||
config.setSampleRate( (HackRFSampleRate)mComboSampleRate.getSelectedItem() );
|
||||
config.setAmplifierEnabled( mAmplifier.isSelected() );
|
||||
config.setLNAGain( (HackRFLNAGain)mComboLNAGain.getSelectedItem() );
|
||||
config.setVGAGain( (HackRFVGAGain)mComboVGAGain.getSelectedItem() );
|
||||
|
||||
getTunerConfigurationModel().broadcast(
|
||||
new TunerConfigurationEvent( getConfiguration(), Event.CHANGE ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.tuner.hackrf;
|
||||
|
||||
import gui.control.JFrequencyControl;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.usb.UsbException;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.frequency.FrequencyChangeEvent;
|
||||
import source.tuner.frequency.FrequencyChangeListener;
|
||||
import source.tuner.frequency.FrequencyChangeEvent.Event;
|
||||
import source.tuner.hackrf.HackRFTunerController.BoardID;
|
||||
|
||||
import com.jidesoft.swing.JideTabbedPane;
|
||||
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class HackRFTunerEditorPanel extends JPanel
|
||||
implements FrequencyChangeListener
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( HackRFTunerEditorPanel.class );
|
||||
|
||||
private JFrequencyControl mFrequencyControl;
|
||||
|
||||
private HackRFTuner mTuner;
|
||||
private HackRFTunerController mController;
|
||||
private ResourceManager mResourceManager;
|
||||
|
||||
public HackRFTunerEditorPanel( HackRFTuner tuner,
|
||||
ResourceManager resourceManager )
|
||||
{
|
||||
mTuner = tuner;
|
||||
mController = mTuner.getController();
|
||||
mResourceManager = resourceManager;
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 2",
|
||||
"[right,grow][grow]",
|
||||
"[][][][][][grow]" ) );
|
||||
|
||||
BoardID board = BoardID.INVALID;
|
||||
|
||||
try
|
||||
{
|
||||
board = mTuner.getController().getBoardID();
|
||||
}
|
||||
catch ( UsbException e )
|
||||
{
|
||||
mLog.error( "couldn't read HackRF board identifier", e );
|
||||
}
|
||||
|
||||
add( new JLabel( board.getLabel() ), "span,align center" );
|
||||
|
||||
mFrequencyControl = new JFrequencyControl();
|
||||
|
||||
mFrequencyControl.addListener( this );
|
||||
|
||||
/* Add frequency control as frequency change listener. This creates a
|
||||
* feedback loop, so the control does not rebroadcast the event */
|
||||
mTuner.addListener( mFrequencyControl );
|
||||
|
||||
mFrequencyControl.setFrequency( mController.getFrequency(), false );
|
||||
|
||||
add( mFrequencyControl, "span,align center" );
|
||||
|
||||
JideTabbedPane tabs = new JideTabbedPane();
|
||||
tabs.setFont( this.getFont() );
|
||||
tabs.setForeground( Color.BLACK );
|
||||
|
||||
add( tabs, "span,grow,push" );
|
||||
|
||||
tabs.add( "Config", new HackRFTunerConfigurationPanel(
|
||||
mResourceManager, mTuner.getController() ) );
|
||||
|
||||
tabs.add( "Info", new HackRFInformationPanel( mTuner.getController() ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION )
|
||||
{
|
||||
try
|
||||
{
|
||||
mController.setFrequency( event.getValue().longValue() );
|
||||
}
|
||||
catch ( SourceException e )
|
||||
{
|
||||
mLog.error( "error setting frequency [" + event.getValue().longValue() + "]", e );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.tuner.rtl;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import source.tuner.rtl.RTL2832TunerController.Descriptor;
|
||||
|
||||
public class RTL2832InfoPanel extends JPanel
|
||||
{
|
||||
RTL2832TunerController mController;
|
||||
|
||||
public RTL2832InfoPanel( RTL2832TunerController controller )
|
||||
{
|
||||
mController = controller;
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
mController = null;
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][][][][][][][grow]" ) );
|
||||
|
||||
Descriptor descriptor = mController.getDescriptor();
|
||||
|
||||
add( new JLabel( "RTL-2832 EEPROM Descriptor" ), "span,align center" );
|
||||
|
||||
if( descriptor == null )
|
||||
{
|
||||
add( new JLabel( "No descriptor" ), "wrap" ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
add( new JLabel( "USB ID:" ) ) ;
|
||||
add( new JLabel( descriptor.getVendorID() + ":" +
|
||||
descriptor.getProductID() ), "wrap" ) ;
|
||||
|
||||
add( new JLabel( "Vendor:" ) ) ;
|
||||
add( new JLabel( descriptor.getVendorLabel() ), "wrap" ) ;
|
||||
|
||||
add( new JLabel( "Product:" ) ) ;
|
||||
add( new JLabel( descriptor.getProductLabel() ), "wrap" ) ;
|
||||
|
||||
add( new JLabel( "Serial:" ) ) ;
|
||||
add( new JLabel( descriptor.getSerial() ), "wrap" ) ;
|
||||
|
||||
add( new JLabel( "IR Enabled:" ) ) ;
|
||||
add( new JLabel( ( descriptor.irEnabled() ? "Yes" : "No" ) ), "wrap" ) ;
|
||||
|
||||
add( new JLabel( "Remote Wake:" ) ) ;
|
||||
add( new JLabel( ( descriptor.remoteWakeupEnabled() ? "Yes" : "No" ) ), "wrap" ) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,8 +19,6 @@ package source.tuner.rtl;
|
||||
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.usb4java.LibUsbException;
|
||||
@@ -32,11 +30,9 @@ import source.tuner.Tuner;
|
||||
import source.tuner.TunerChannel;
|
||||
import source.tuner.TunerChannelSource;
|
||||
import source.tuner.TunerClass;
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerEvent;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.frequency.FrequencyChangeListener;
|
||||
import source.tuner.rtl.RTL2832TunerController.SampleRate;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class RTL2832Tuner extends Tuner
|
||||
{
|
||||
@@ -44,19 +40,16 @@ public class RTL2832Tuner extends Tuner
|
||||
LoggerFactory.getLogger( RTL2832Tuner.class );
|
||||
|
||||
private TunerClass mTunerClass;
|
||||
protected RTL2832TunerController mController;
|
||||
|
||||
public RTL2832Tuner( TunerClass tunerClass,
|
||||
RTL2832TunerController controller )
|
||||
throws SourceException
|
||||
{
|
||||
super( tunerClass.getVendorDeviceLabel() + "/" +
|
||||
controller.getTunerType().getLabel() + " #" +
|
||||
controller.getUniqueID() );
|
||||
controller.getTunerType().getLabel() + " " +
|
||||
controller.getUniqueID(), controller );
|
||||
|
||||
mTunerClass = tunerClass;
|
||||
mController = controller;
|
||||
mController.addListener( (FrequencyChangeListener)this );
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
@@ -66,13 +59,13 @@ public class RTL2832Tuner extends Tuner
|
||||
|
||||
public RTL2832TunerController getController()
|
||||
{
|
||||
return mController;
|
||||
return (RTL2832TunerController)getTunerController();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueID()
|
||||
{
|
||||
return mController.getUniqueID();
|
||||
return getController().getUniqueID();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -84,41 +77,14 @@ public class RTL2832Tuner extends Tuner
|
||||
@Override
|
||||
public TunerType getTunerType()
|
||||
{
|
||||
return mController.getTunerType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JPanel getEditor( ResourceManager resourceManager )
|
||||
{
|
||||
return mController.getEditor( resourceManager );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply( TunerConfiguration config ) throws SourceException
|
||||
{
|
||||
mController.apply( config );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSampleRate()
|
||||
{
|
||||
try
|
||||
{
|
||||
return mController.getCurrentSampleRate();
|
||||
}
|
||||
catch( SourceException e )
|
||||
{
|
||||
mLog.error( "RTL2832 Tuner - couldn't get sample rate", e );
|
||||
}
|
||||
|
||||
return 0;
|
||||
return getController().getTunerType();
|
||||
}
|
||||
|
||||
public void setSampleRate( SampleRate sampleRate ) throws SourceException
|
||||
{
|
||||
try
|
||||
{
|
||||
mController.setSampleRate( sampleRate );
|
||||
getController().setSampleRate( sampleRate );
|
||||
}
|
||||
catch( LibUsbException e )
|
||||
{
|
||||
@@ -135,26 +101,26 @@ public class RTL2832Tuner extends Tuner
|
||||
return 11.0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFrequency() throws SourceException
|
||||
{
|
||||
return mController.getFrequency();
|
||||
}
|
||||
|
||||
public void setFrequency( int frequency ) throws SourceException
|
||||
{
|
||||
mController.setFrequency( frequency );
|
||||
getController().setFrequency( frequency );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TunerChannelSource getChannel( TunerChannel channel )
|
||||
throws RejectedExecutionException, SourceException
|
||||
throws RejectedExecutionException,
|
||||
SourceException
|
||||
{
|
||||
TunerChannelSource source = null;
|
||||
|
||||
try
|
||||
{
|
||||
source = mController.getChannel( this, channel );
|
||||
source = getController().getChannel( this, channel );
|
||||
|
||||
if( source != null )
|
||||
{
|
||||
broadcast( new TunerEvent( this, TunerEvent.Event.CHANNEL_COUNT ) );
|
||||
}
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
@@ -163,6 +129,7 @@ public class RTL2832Tuner extends Tuner
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the tuned channel so that the tuner controller can tune to
|
||||
* other frequencies as needed.
|
||||
@@ -176,19 +143,19 @@ public class RTL2832Tuner extends Tuner
|
||||
/* Tell the controller to release the channel and cleanup */
|
||||
if( source != null )
|
||||
{
|
||||
mController.releaseChannel( source );
|
||||
getController().releaseChannel( source );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener( Listener<ComplexBuffer> listener )
|
||||
{
|
||||
mController.addListener( listener );
|
||||
getController().addListener( listener );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener( Listener<ComplexBuffer> listener )
|
||||
{
|
||||
mController.removeListener( listener );
|
||||
getController().removeListener( listener );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.usb.UsbDisconnectedException;
|
||||
import javax.usb.UsbException;
|
||||
|
||||
@@ -56,7 +55,6 @@ import source.SourceException;
|
||||
import source.tuner.TunerController;
|
||||
import source.tuner.TunerType;
|
||||
import buffer.FloatAveragingBuffer;
|
||||
import controller.ResourceManager;
|
||||
import controller.ThreadPoolManager;
|
||||
import controller.ThreadPoolManager.ThreadType;
|
||||
|
||||
@@ -113,8 +111,6 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
|
||||
private SampleRateMonitor mSampleRateMonitor;
|
||||
private AtomicInteger mSampleCounter = new AtomicInteger();
|
||||
private double mSampleRateAverageSum;
|
||||
private int mSampleRateAverageCount;
|
||||
private static final DecimalFormat mDecimalFormatter =
|
||||
new DecimalFormat( "###,###,###.0" );
|
||||
private static final DecimalFormat mPercentFormatter =
|
||||
@@ -149,6 +145,7 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
mDevice = device;
|
||||
mDeviceDescriptor = deviceDescriptor;
|
||||
}
|
||||
|
||||
|
||||
public void init() throws SourceException
|
||||
{
|
||||
@@ -362,8 +359,6 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
}
|
||||
}
|
||||
|
||||
public abstract JPanel getEditor( ResourceManager resourceManager );
|
||||
|
||||
public abstract void setSampleRateFilters( int sampleRate )
|
||||
throws SourceException;
|
||||
|
||||
@@ -977,7 +972,7 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
return mSampleRate.getRate();
|
||||
}
|
||||
|
||||
public int getSampleRate() throws SourceException
|
||||
public int getSampleRateFromTuner() throws SourceException
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -1426,17 +1421,17 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
{
|
||||
mLog.error( "NPE! = tpm null: " + ( mThreadPoolManager == null ), npe );
|
||||
}
|
||||
|
||||
|
||||
mLibUsbHandlerStatus = ByteBuffer.allocateDirect( 4 );
|
||||
|
||||
List<Transfer> transfers = new ArrayList<>();
|
||||
|
||||
|
||||
mCancel = false;
|
||||
|
||||
while( mRunning.get() )
|
||||
while( mRunning.get() )
|
||||
{
|
||||
mAvailableTransfers.drainTo( transfers );
|
||||
|
||||
|
||||
for( Transfer transfer: transfers )
|
||||
{
|
||||
int result = LibUsb.submitTransfer( transfer );
|
||||
@@ -1453,7 +1448,7 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
}
|
||||
|
||||
int result = LibUsb.handleEventsTimeoutCompleted(
|
||||
null, TIMEOUT_US, mLibUsbHandlerStatus.asIntBuffer() );
|
||||
null, TIMEOUT_US, mLibUsbHandlerStatus.asIntBuffer() );
|
||||
|
||||
if( result != LibUsb.SUCCESS )
|
||||
{
|
||||
@@ -1472,21 +1467,17 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
LibUsb.cancelTransfer( transfer );
|
||||
}
|
||||
|
||||
int result = LibUsb.handleEventsTimeoutCompleted(
|
||||
null, TIMEOUT_US, mLibUsbHandlerStatus.asIntBuffer() );
|
||||
|
||||
if( result != LibUsb.SUCCESS )
|
||||
{
|
||||
mLog.error( "error handling events for libusb" );
|
||||
}
|
||||
|
||||
mLibUsbHandlerStatus.rewind();
|
||||
int result = LibUsb.handleEventsTimeoutCompleted( null,
|
||||
TIMEOUT_US, mLibUsbHandlerStatus.asIntBuffer() );
|
||||
|
||||
if( result != LibUsb.SUCCESS )
|
||||
{
|
||||
mLog.error( "error handling events for libusb during cancel" );
|
||||
}
|
||||
|
||||
mLibUsbHandlerStatus.rewind();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.error( "Couldn't start buffer processor - already running!" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1516,7 +1507,7 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processTransfer( Transfer transfer )
|
||||
public void processTransfer( Transfer transfer )
|
||||
{
|
||||
mTransfersInProgress.remove( transfer );
|
||||
|
||||
@@ -1636,6 +1627,79 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class USBEventHandlingThread implements Runnable
|
||||
{
|
||||
/** If thread should abort. */
|
||||
private volatile boolean mAbort;
|
||||
|
||||
/**
|
||||
* Aborts the event handling thread.
|
||||
*/
|
||||
public void abort()
|
||||
{
|
||||
mAbort = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
while ( !mAbort )
|
||||
{
|
||||
int result = LibUsb.handleEventsTimeout( null, 1000 );
|
||||
|
||||
if ( result != LibUsb.SUCCESS )
|
||||
{
|
||||
mAbort = true;
|
||||
|
||||
mLog.error( "error handling usb events [" +
|
||||
LibUsb.errorName( result ) + "]" );
|
||||
|
||||
throw new LibUsbException("Unable to handle USB "
|
||||
+ "events", result );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum TunerTypeCheck
|
||||
{
|
||||
E4K( 0xC8, 0x02, 0x40 ),
|
||||
FC0012( 0xC6, 0x00, 0xA1 ),
|
||||
FC0013( 0xC6, 0x00, 0xA3 ),
|
||||
FC2580( 0xAC, 0x01, 0x56 ),
|
||||
R820T( 0x34, 0x00, 0x69 ),
|
||||
R828D( 0x74, 0x00, 0x69 );
|
||||
|
||||
private int mI2CAddress;
|
||||
private int mCheckAddress;
|
||||
private int mCheckValue;
|
||||
|
||||
private TunerTypeCheck( int i2c, int address, int value )
|
||||
{
|
||||
mI2CAddress = i2c;
|
||||
mCheckAddress = address;
|
||||
mCheckValue = value;
|
||||
}
|
||||
|
||||
public byte getI2CAddress()
|
||||
{
|
||||
return (byte)mI2CAddress;
|
||||
}
|
||||
|
||||
public byte getCheckAddress()
|
||||
{
|
||||
return (byte)mCheckAddress;
|
||||
}
|
||||
|
||||
public byte getCheckValue()
|
||||
{
|
||||
return (byte)mCheckValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Averages the sample rate over a 10-second period. The count is for the
|
||||
* number of bytes received from the tuner. There are two bytes for each
|
||||
@@ -1730,7 +1794,6 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RTL2832 EEPROM byte array descriptor parsing class
|
||||
*/
|
||||
@@ -1901,74 +1964,4 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
}
|
||||
}
|
||||
|
||||
public class USBEventHandlingThread implements Runnable
|
||||
{
|
||||
/** If thread should abort. */
|
||||
private volatile boolean mAbort;
|
||||
|
||||
/**
|
||||
* Aborts the event handling thread.
|
||||
*/
|
||||
public void abort()
|
||||
{
|
||||
mAbort = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
while ( !mAbort )
|
||||
{
|
||||
int result = LibUsb.handleEventsTimeout( null, 1000 );
|
||||
|
||||
if ( result != LibUsb.SUCCESS )
|
||||
{
|
||||
mAbort = true;
|
||||
|
||||
mLog.error( "error handling usb events [" +
|
||||
LibUsb.errorName( result ) + "]" );
|
||||
|
||||
throw new LibUsbException("Unable to handle USB "
|
||||
+ "events", result );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum TunerTypeCheck
|
||||
{
|
||||
E4K( 0xC8, 0x02, 0x40 ),
|
||||
FC0012( 0xC6, 0x00, 0xA1 ),
|
||||
FC0013( 0xC6, 0x00, 0xA3 ),
|
||||
FC2580( 0xAC, 0x01, 0x56 ),
|
||||
R820T( 0x34, 0x00, 0x69 ),
|
||||
R828D( 0x74, 0x00, 0x69 );
|
||||
|
||||
private int mI2CAddress;
|
||||
private int mCheckAddress;
|
||||
private int mCheckValue;
|
||||
|
||||
private TunerTypeCheck( int i2c, int address, int value )
|
||||
{
|
||||
mI2CAddress = i2c;
|
||||
mCheckAddress = address;
|
||||
mCheckValue = value;
|
||||
}
|
||||
|
||||
public byte getI2CAddress()
|
||||
{
|
||||
return (byte)mI2CAddress;
|
||||
}
|
||||
|
||||
public byte getCheckAddress()
|
||||
{
|
||||
return (byte)mCheckAddress;
|
||||
}
|
||||
|
||||
public byte getCheckValue()
|
||||
{
|
||||
return (byte)mCheckValue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.tuner.rtl;
|
||||
|
||||
public enum RTL2832TunerType
|
||||
{
|
||||
E4000,
|
||||
FC0012,
|
||||
FC0013,
|
||||
R820T,
|
||||
R828D,
|
||||
UNKNOWN;
|
||||
}
|
||||
@@ -19,8 +19,8 @@ package source.tuner.rtl.e4k;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.configuration.TunerConfiguration;
|
||||
import source.tuner.rtl.RTL2832TunerController.SampleRate;
|
||||
import source.tuner.rtl.e4k.E4KTunerController.E4KEnhanceGain;
|
||||
import source.tuner.rtl.e4k.E4KTunerController.E4KGain;
|
||||
@@ -29,24 +29,23 @@ import source.tuner.rtl.e4k.E4KTunerController.E4KMixerGain;
|
||||
|
||||
public class E4KTunerConfiguration extends TunerConfiguration
|
||||
{
|
||||
private E4KGain mMasterGain = E4KGain.AUTOMATIC;
|
||||
private E4KMixerGain mMixerGain = E4KMixerGain.AUTOMATIC;
|
||||
private E4KLNAGain mLNAGain = E4KLNAGain.AUTOMATIC;
|
||||
private E4KEnhanceGain mEnhanceGain = E4KEnhanceGain.AUTOMATIC;
|
||||
private double mFrequencyCorrection = 8.9d;
|
||||
private SampleRate mSampleRate = SampleRate.RATE_1_920MHZ;
|
||||
private E4KGain mMasterGain = E4KGain.MANUAL;
|
||||
private E4KMixerGain mMixerGain = E4KMixerGain.GAIN_4;
|
||||
private E4KLNAGain mLNAGain = E4KLNAGain.GAIN_PLUS_200;
|
||||
private E4KEnhanceGain mEnhanceGain = E4KEnhanceGain.GAIN_3;
|
||||
private double mFrequencyCorrection = 0.0d;
|
||||
private SampleRate mSampleRate = SampleRate.RATE_2_400MHZ;
|
||||
|
||||
/**
|
||||
* Default constructor for JAXB
|
||||
*/
|
||||
public E4KTunerConfiguration()
|
||||
{
|
||||
this( "Default" );
|
||||
}
|
||||
|
||||
public E4KTunerConfiguration( String name )
|
||||
public E4KTunerConfiguration( String uniqueID, String name )
|
||||
{
|
||||
super( name );
|
||||
super( uniqueID, name );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,691 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.tuner.rtl.e4k;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.ComboBoxModel;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SpinnerModel;
|
||||
import javax.swing.SpinnerNumberModel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.usb.UsbException;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.usb4java.LibUsbException;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerConfigurationAssignment;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.rtl.RTL2832TunerController.SampleRate;
|
||||
import source.tuner.rtl.e4k.E4KTunerController.E4KEnhanceGain;
|
||||
import source.tuner.rtl.e4k.E4KTunerController.E4KGain;
|
||||
import source.tuner.rtl.e4k.E4KTunerController.E4KLNAGain;
|
||||
import source.tuner.rtl.e4k.E4KTunerController.E4KMixerGain;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class E4KTunerConfigurationPanel extends JPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( E4KTunerConfigurationPanel.class );
|
||||
|
||||
private ResourceManager mResourceManager;
|
||||
private E4KTunerController mController;
|
||||
private E4KTunerConfiguration mSelectedConfig;
|
||||
|
||||
private JButton mNewConfiguration;
|
||||
private JButton mDeleteConfiguration;
|
||||
private JComboBox<E4KTunerConfiguration> mComboConfigurations;
|
||||
|
||||
private JTextField mName;
|
||||
|
||||
private JSpinner mFrequencyCorrection;
|
||||
private JSpinner mSampleRateCorrection;
|
||||
private JComboBox<E4KGain> mComboMasterGain;
|
||||
private JComboBox<E4KMixerGain> mComboMixerGain;
|
||||
private JComboBox<E4KLNAGain> mComboLNAGain;
|
||||
private JComboBox<E4KEnhanceGain> mComboEnhanceGain;
|
||||
|
||||
private JComboBox<SampleRate> mComboSampleRate;
|
||||
|
||||
public E4KTunerConfigurationPanel( ResourceManager resourceManager,
|
||||
E4KTunerController controller )
|
||||
{
|
||||
mResourceManager = resourceManager;
|
||||
mController = controller;
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the gui components
|
||||
*/
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 2", "[grow,right][grow]", "[][][][][][][grow]" ) );
|
||||
|
||||
/**
|
||||
* Tuner configuration selector
|
||||
*/
|
||||
mComboConfigurations = new JComboBox<E4KTunerConfiguration>();
|
||||
|
||||
mComboConfigurations.setModel( getModel() );
|
||||
|
||||
/* Determine which tuner configuration should be selected/displayed */
|
||||
TunerConfigurationAssignment savedConfig = mResourceManager
|
||||
.getSettingsManager().getSelectedTunerConfiguration(
|
||||
TunerType.ELONICS_E4000, mController.getUniqueID() );
|
||||
|
||||
if( savedConfig != null )
|
||||
{
|
||||
mSelectedConfig = getNamedConfiguration(
|
||||
savedConfig.getTunerConfigurationName() );
|
||||
}
|
||||
|
||||
/* If we couldn't determine the saved/selected config, use the first one */
|
||||
if( mSelectedConfig == null )
|
||||
{
|
||||
mSelectedConfig = mComboConfigurations.getItemAt( 0 );
|
||||
|
||||
//Store this config as the default for this tuner at this address
|
||||
mResourceManager.getSettingsManager()
|
||||
.setSelectedTunerConfiguration(
|
||||
TunerType.ELONICS_E4000,
|
||||
mController.getUniqueID(), mSelectedConfig );
|
||||
}
|
||||
|
||||
mComboConfigurations.setSelectedItem( mSelectedConfig );
|
||||
|
||||
mComboConfigurations.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
E4KTunerConfiguration selected =
|
||||
(E4KTunerConfiguration)mComboConfigurations
|
||||
.getItemAt( mComboConfigurations.getSelectedIndex() );
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
update( selected );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
add( new JLabel( "Config:" ) );
|
||||
add( mComboConfigurations, "growx,push" );
|
||||
|
||||
/**
|
||||
* Tuner Configuration Name
|
||||
*/
|
||||
add( new JLabel( "Name:" ) );
|
||||
mName = new JTextField();
|
||||
mName.setText( mSelectedConfig.getName() );
|
||||
|
||||
mName.addFocusListener( new FocusListener()
|
||||
{
|
||||
@Override
|
||||
public void focusLost( FocusEvent e )
|
||||
{
|
||||
/* Update the config name */
|
||||
mSelectedConfig.setName( mName.getText() );
|
||||
|
||||
/* Reset this named config as the assigned config for this
|
||||
* tuner */
|
||||
mResourceManager.getSettingsManager()
|
||||
.setSelectedTunerConfiguration(
|
||||
TunerType.ELONICS_E4000,
|
||||
mController.getUniqueID(), mSelectedConfig );
|
||||
|
||||
save();
|
||||
}
|
||||
@Override
|
||||
public void focusGained( FocusEvent e ) {}
|
||||
} );
|
||||
|
||||
add( mName, "growx,push" );
|
||||
|
||||
/**
|
||||
* Frequency Correction
|
||||
*/
|
||||
SpinnerModel model =
|
||||
new SpinnerNumberModel( 0.0, //initial value
|
||||
-1000.0, //min
|
||||
1000.0, //max
|
||||
0.1 ); //step
|
||||
|
||||
mFrequencyCorrection = new JSpinner( model );
|
||||
|
||||
JSpinner.NumberEditor editor =
|
||||
(JSpinner.NumberEditor)mFrequencyCorrection.getEditor();
|
||||
|
||||
DecimalFormat format = editor.getFormat();
|
||||
format.setMinimumFractionDigits( 1 );
|
||||
editor.getTextField().setHorizontalAlignment( SwingConstants.CENTER );
|
||||
|
||||
mFrequencyCorrection.setValue( mSelectedConfig.getFrequencyCorrection() );
|
||||
|
||||
mFrequencyCorrection.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
final double value = ((SpinnerNumberModel)mFrequencyCorrection
|
||||
.getModel()).getNumber().doubleValue();
|
||||
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
mController.setFrequencyCorrection( value );
|
||||
mSelectedConfig.setFrequencyCorrection( value );
|
||||
save();
|
||||
}
|
||||
catch ( SourceException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
E4KTunerConfigurationPanel.this,
|
||||
"E4K Tuner Controller - couldn't apply "
|
||||
+ "frequency correction value: " + value +
|
||||
e1.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "E4K Tuner Controller - couldn't apply "
|
||||
+ "frequency correction value: " + value, e1 );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "Correction PPM:" ) );
|
||||
add( mFrequencyCorrection, "growx,push" );
|
||||
|
||||
/**
|
||||
* Sample Rate
|
||||
*/
|
||||
mComboSampleRate = new JComboBox<>( SampleRate.values() );
|
||||
mComboSampleRate.setSelectedItem( mSelectedConfig.getSampleRate() );
|
||||
mComboSampleRate.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
SampleRate sampleRate =
|
||||
(SampleRate)mComboSampleRate.getSelectedItem();
|
||||
try
|
||||
{
|
||||
|
||||
mController.setSampleRate( sampleRate );
|
||||
|
||||
mSelectedConfig.setSampleRate( sampleRate );
|
||||
save();
|
||||
}
|
||||
catch ( SourceException | LibUsbException eSampleRate )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
E4KTunerConfigurationPanel.this,
|
||||
"E4K Tuner Controller - couldn't apply the sample "
|
||||
+ "rate setting [" + sampleRate.getLabel() + "] " +
|
||||
eSampleRate.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "E4K Tuner Controller - couldn't apply sample "
|
||||
+ "rate setting [" + sampleRate.getLabel() + "]",
|
||||
eSampleRate );
|
||||
}
|
||||
}
|
||||
} );
|
||||
add( new JLabel( "Sample Rate:" ) );
|
||||
add( mComboSampleRate, "growx,push" );
|
||||
|
||||
// /**
|
||||
// * Sample Rate Correction
|
||||
// */
|
||||
// SpinnerModel sampleRateCorrectionModel =
|
||||
// new SpinnerNumberModel( 0, //initial value
|
||||
// -32768, //min
|
||||
// 32767, //max
|
||||
// 1 ); //step
|
||||
//
|
||||
// mSampleRateCorrection = new JSpinner( sampleRateCorrectionModel );
|
||||
//
|
||||
// JSpinner.NumberEditor sampleRateCorrectionEditor =
|
||||
// (JSpinner.NumberEditor)mSampleRateCorrection.getEditor();
|
||||
//
|
||||
// DecimalFormat sampleRateCorrectionFormat =
|
||||
// sampleRateCorrectionEditor.getFormat();
|
||||
//
|
||||
// sampleRateCorrectionFormat.setMinimumFractionDigits( 0 );
|
||||
//
|
||||
// sampleRateCorrectionEditor.getTextField()
|
||||
// .setHorizontalAlignment( SwingConstants.CENTER );
|
||||
//
|
||||
// mSampleRateCorrection.addChangeListener( new ChangeListener()
|
||||
// {
|
||||
// @Override
|
||||
// public void stateChanged( ChangeEvent e )
|
||||
// {
|
||||
// final int value = ((SpinnerNumberModel)mSampleRateCorrection
|
||||
// .getModel()).getNumber().intValue();
|
||||
//
|
||||
// EventQueue.invokeLater( new Runnable()
|
||||
// {
|
||||
// @Override
|
||||
// public void run()
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// mController.setSampleRateFrequencyCorrection( value );
|
||||
// }
|
||||
// catch ( SourceException | UsbException e1 )
|
||||
// {
|
||||
// JOptionPane.showMessageDialog(
|
||||
// E4KTunerConfigurationPanel.this,
|
||||
// "E4K Tuner Controller - couldn't apply "
|
||||
// + "sample rate correction value: " + value +
|
||||
// e1.getLocalizedMessage() );
|
||||
//
|
||||
// Log.error( "E4K Tuner Controller - couldn't apply "
|
||||
// + "sample rate correction value: " + value +
|
||||
// e1.getLocalizedMessage() );
|
||||
// }
|
||||
// }
|
||||
// } );
|
||||
// }
|
||||
// } );
|
||||
//
|
||||
// add( mSampleRateCorrection );
|
||||
// add( new JLabel( "Sample Rate Correction (ppm)" ), "wrap" );
|
||||
|
||||
/**
|
||||
* Gain Controls
|
||||
*/
|
||||
JPanel gainPanel = new JPanel();
|
||||
gainPanel.setLayout( new MigLayout( "fill", "[right][left][right][left]", "" ) );
|
||||
gainPanel.setBorder( BorderFactory.createTitledBorder( "Gain" ) );
|
||||
|
||||
/* Master Gain Control */
|
||||
mComboMasterGain = new JComboBox<E4KGain>( E4KGain.values() );
|
||||
mComboMasterGain.setSelectedItem( mSelectedConfig.getMasterGain() );
|
||||
|
||||
mComboMasterGain.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
try
|
||||
{
|
||||
E4KGain gain = (E4KGain)mComboMasterGain.getSelectedItem();
|
||||
|
||||
mController.setGain( (E4KGain)mComboMasterGain.getSelectedItem(), true );
|
||||
|
||||
if( gain == E4KGain.MANUAL )
|
||||
{
|
||||
mComboMixerGain.setSelectedItem(
|
||||
mController.getMixerGain( true ) );
|
||||
mComboMixerGain.setEnabled( true );
|
||||
|
||||
mComboLNAGain.setSelectedItem(
|
||||
mController.getLNAGain( true ) );
|
||||
mComboLNAGain.setEnabled( true );
|
||||
|
||||
mComboEnhanceGain.setEnabled( true );
|
||||
mComboEnhanceGain.setSelectedItem(
|
||||
mController.getEnhanceGain( true ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
mComboMixerGain.setEnabled( false );
|
||||
mComboMixerGain.setSelectedItem( gain.getMixerGain() );
|
||||
|
||||
mComboLNAGain.setEnabled( false );
|
||||
mComboLNAGain.setSelectedItem( gain.getLNAGain() );
|
||||
|
||||
mComboEnhanceGain.setEnabled( false );
|
||||
mComboEnhanceGain.setSelectedItem( gain.getEnhanceGain() );
|
||||
}
|
||||
|
||||
mSelectedConfig.setMasterGain( gain );
|
||||
save();
|
||||
}
|
||||
catch ( UsbException e )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
E4KTunerConfigurationPanel.this,
|
||||
"E4K Tuner Controller - couldn't apply the gain "
|
||||
+ "setting - " + e.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "E4K Tuner Controller - couldn't apply "
|
||||
+ "gain setting", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
mComboMasterGain.setToolTipText( "<html>Select <b>AUTOMATIC</b> for auto "
|
||||
+ "gain, <b>MANUAL</b> to enable<br> independent control of "
|
||||
+ "<i>Mixer</i>, <i>LNA</i> and <i>Enhance</i> gain<br>"
|
||||
+ "settings, or one of the individual gain settings for<br>"
|
||||
+ "semi-manual gain control</html>" );
|
||||
gainPanel.add( new JLabel( "Master" ) );
|
||||
gainPanel.add( mComboMasterGain );
|
||||
|
||||
/* Mixer Gain Control */
|
||||
mComboMixerGain = new JComboBox<E4KMixerGain>( E4KMixerGain.values() );
|
||||
mComboMixerGain.setSelectedItem( mSelectedConfig.getMixerGain() );
|
||||
mComboMixerGain.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
E4KMixerGain mixerGain =
|
||||
(E4KMixerGain)mComboMixerGain.getSelectedItem();
|
||||
|
||||
if( mComboMixerGain.isEnabled() )
|
||||
{
|
||||
mController.setMixerGain( mixerGain, true );
|
||||
}
|
||||
|
||||
mSelectedConfig.setMixerGain( mixerGain );
|
||||
save();
|
||||
}
|
||||
catch ( UsbException e )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
E4KTunerConfigurationPanel.this,
|
||||
"E4K Tuner Controller - couldn't apply the mixer "
|
||||
+ "gain setting - " + e.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "E4K Tuner Controller - couldn't apply mixer "
|
||||
+ "gain setting", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
} );
|
||||
mComboMixerGain.setToolTipText( "<html>Mixer Gain. Set master gain "
|
||||
+ "to <b>MASTER</b> to enable adjustment</html>" );
|
||||
mComboMixerGain.setEnabled( false );
|
||||
gainPanel.add( new JLabel( "Mixer" ) );
|
||||
gainPanel.add( mComboMixerGain, "wrap" );
|
||||
|
||||
/* LNA Gain Control */
|
||||
mComboLNAGain = new JComboBox<E4KLNAGain>( E4KLNAGain.values() );
|
||||
mComboLNAGain.setSelectedItem( mSelectedConfig.getLNAGain() );
|
||||
mComboLNAGain.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
try
|
||||
{
|
||||
E4KLNAGain lnaGain = (E4KLNAGain)mComboLNAGain.getSelectedItem();
|
||||
|
||||
if( mComboLNAGain.isEnabled() )
|
||||
{
|
||||
mController.setLNAGain( lnaGain, true );
|
||||
}
|
||||
|
||||
mSelectedConfig.setLNAGain( lnaGain );
|
||||
save();
|
||||
}
|
||||
catch ( UsbException e )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
E4KTunerConfigurationPanel.this,
|
||||
"E4K Tuner Controller - couldn't apply the LNA "
|
||||
+ "gain setting - " + e.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "E4K Tuner Controller - couldn't apply LNA "
|
||||
+ "gain setting - ", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
mComboLNAGain.setToolTipText( "<html>LNA Gain. Set master gain "
|
||||
+ "to <b>MANUAL</b> to enable adjustment</html>" );
|
||||
mComboLNAGain.setEnabled( false );
|
||||
gainPanel.add( new JLabel( "LNA" ) );
|
||||
gainPanel.add( mComboLNAGain );
|
||||
|
||||
/* Enhance Gain Control */
|
||||
mComboEnhanceGain = new JComboBox<E4KEnhanceGain>( E4KEnhanceGain.values() );
|
||||
mComboEnhanceGain.setSelectedItem( mSelectedConfig.getEnhanceGain() );
|
||||
mComboEnhanceGain.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
try
|
||||
{
|
||||
E4KEnhanceGain enhanceGain =
|
||||
(E4KEnhanceGain)mComboEnhanceGain.getSelectedItem();
|
||||
|
||||
if( mComboEnhanceGain.isEnabled() )
|
||||
{
|
||||
mController.setEnhanceGain( enhanceGain, true );
|
||||
}
|
||||
|
||||
mSelectedConfig.setEnhanceGain( enhanceGain );
|
||||
save();
|
||||
}
|
||||
catch ( UsbException e )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
E4KTunerConfigurationPanel.this,
|
||||
"E4K Tuner Controller - couldn't apply the enhance "
|
||||
+ "gain setting - " + e.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "E4K Tuner Controller - couldn't apply enhance "
|
||||
+ "gain setting", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
mComboEnhanceGain.setToolTipText( "<html>Enhance Gain. Set master gain "
|
||||
+ "to <b>MANUAL</b> to enable adjustment</html>" );
|
||||
mComboEnhanceGain.setEnabled( false );
|
||||
gainPanel.add( new JLabel( "Enhance" ) );
|
||||
gainPanel.add( mComboEnhanceGain, "wrap" );
|
||||
|
||||
add( gainPanel, "span,grow,push" );
|
||||
|
||||
/**
|
||||
* Create a new configuration
|
||||
*/
|
||||
mNewConfiguration = new JButton( "New" );
|
||||
|
||||
mNewConfiguration.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
TunerConfiguration config =
|
||||
mResourceManager.getSettingsManager()
|
||||
.addNewTunerConfiguration(
|
||||
TunerType.ELONICS_E4000,
|
||||
"New Configuration" );
|
||||
|
||||
mComboConfigurations.setModel( getModel() );
|
||||
|
||||
mComboConfigurations.setSelectedItem( config );
|
||||
|
||||
repaint();
|
||||
}
|
||||
} );
|
||||
|
||||
add( mNewConfiguration, "growx,push" );
|
||||
|
||||
/**
|
||||
* Delete the currently selected configuration
|
||||
*/
|
||||
mDeleteConfiguration = new JButton( "Delete" );
|
||||
|
||||
mDeleteConfiguration.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
E4KTunerConfiguration selected =
|
||||
(E4KTunerConfiguration)mComboConfigurations
|
||||
.getItemAt( mComboConfigurations.getSelectedIndex() );
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
int n = JOptionPane.showConfirmDialog(
|
||||
E4KTunerConfigurationPanel.this,
|
||||
"Are you sure you want to delete '"
|
||||
+ selected.getName() + "'?",
|
||||
"Are you sure?",
|
||||
JOptionPane.YES_NO_OPTION );
|
||||
|
||||
if( n == JOptionPane.YES_OPTION )
|
||||
{
|
||||
mResourceManager.getSettingsManager()
|
||||
.deleteTunerConfiguration( selected );
|
||||
|
||||
mComboConfigurations.setModel( getModel() );
|
||||
|
||||
mComboConfigurations.setSelectedIndex( 0 );
|
||||
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( mDeleteConfiguration, "growx,push,wrap" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates gui controls with the values from the tuner configuration
|
||||
* @param config - tuner configuration
|
||||
*/
|
||||
private void update( E4KTunerConfiguration config )
|
||||
{
|
||||
mSelectedConfig = config;
|
||||
|
||||
try
|
||||
{
|
||||
mController.apply( config );
|
||||
|
||||
mName.setText( config.getName() );
|
||||
mFrequencyCorrection.setValue( config.getFrequencyCorrection() );
|
||||
|
||||
mComboMixerGain.setSelectedItem( mSelectedConfig.getMixerGain() );
|
||||
mComboLNAGain.setSelectedItem( mSelectedConfig.getLNAGain() );
|
||||
mComboEnhanceGain.setSelectedItem( mSelectedConfig.getEnhanceGain() );
|
||||
|
||||
/* Apply master gain last so that the Mixer, LNA, and Enhance gain
|
||||
* settings are updated with the master setting where necessary */
|
||||
mComboMasterGain.setSelectedItem( mSelectedConfig.getMasterGain() );
|
||||
|
||||
mComboSampleRate.setSelectedItem( mSelectedConfig.getSampleRate() );
|
||||
|
||||
mResourceManager.getSettingsManager().setSelectedTunerConfiguration(
|
||||
TunerType.ELONICS_E4000, mController.getUniqueID(), config );
|
||||
}
|
||||
catch ( SourceException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
E4KTunerConfigurationPanel.this,
|
||||
"E4K Tuner Controller - couldn't "
|
||||
+ "apply the tuner configuration settings - " +
|
||||
e1.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "E4K Tuner Controller - couldn't apply "
|
||||
+ "config [" + config.getName() + "]", e1 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a combo box model for the tuner configuration combo component
|
||||
* by assembling a list of the tuner configurations appropriate for this
|
||||
* specific tuner
|
||||
*/
|
||||
private ComboBoxModel<E4KTunerConfiguration> getModel()
|
||||
{
|
||||
ArrayList<TunerConfiguration> configs =
|
||||
mResourceManager.getSettingsManager()
|
||||
.getTunerConfigurations( TunerType.ELONICS_E4000 );
|
||||
|
||||
DefaultComboBoxModel<E4KTunerConfiguration> model =
|
||||
new DefaultComboBoxModel<E4KTunerConfiguration>();
|
||||
|
||||
for( TunerConfiguration config: configs )
|
||||
{
|
||||
model.addElement( (E4KTunerConfiguration)config );
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a specific (named) tuner configuration
|
||||
*/
|
||||
private E4KTunerConfiguration getNamedConfiguration( String name )
|
||||
{
|
||||
ArrayList<TunerConfiguration> configs =
|
||||
mResourceManager.getSettingsManager()
|
||||
.getTunerConfigurations( TunerType.ELONICS_E4000 );
|
||||
|
||||
for( TunerConfiguration config: configs )
|
||||
{
|
||||
if( config.getName().contentEquals( name ) )
|
||||
{
|
||||
return (E4KTunerConfiguration)config;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves current tuner configuration settings
|
||||
*/
|
||||
private void save()
|
||||
{
|
||||
mResourceManager.getSettingsManager().save();
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ package source.tuner.rtl.e4k;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.usb.UsbException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -31,10 +30,9 @@ import org.usb4java.LibUsb;
|
||||
import org.usb4java.LibUsbException;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.configuration.TunerConfiguration;
|
||||
import source.tuner.rtl.RTL2832TunerController;
|
||||
import controller.ResourceManager;
|
||||
import controller.ThreadPoolManager;
|
||||
|
||||
public class E4KTunerController extends RTL2832TunerController
|
||||
@@ -110,8 +108,6 @@ public class E4KTunerController extends RTL2832TunerController
|
||||
|
||||
public static final byte CHFCALIB_CMD = (byte)0x01;
|
||||
|
||||
private E4KTunerEditorPanel mEditor;
|
||||
|
||||
public E4KTunerController( Device device,
|
||||
DeviceDescriptor deviceDescriptor,
|
||||
ThreadPoolManager threadPoolManager )
|
||||
@@ -252,16 +248,6 @@ public class E4KTunerController extends RTL2832TunerController
|
||||
}
|
||||
}
|
||||
|
||||
public JPanel getEditor( ResourceManager resourceManager )
|
||||
{
|
||||
if( mEditor == null )
|
||||
{
|
||||
mEditor = new E4KTunerEditorPanel( this, resourceManager );
|
||||
}
|
||||
|
||||
return mEditor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the IF filters (mixer, channel and RC) to the correct filter setting
|
||||
* for the selected bandwidth/sample rate
|
||||
@@ -1070,7 +1056,7 @@ public class E4KTunerController extends RTL2832TunerController
|
||||
(byte)( ( temp & ~mask ) | ( value & mask ) ),
|
||||
controlI2CRepeater );
|
||||
|
||||
int temp2 = readE4KRegister( register, controlI2CRepeater );
|
||||
readE4KRegister( register, controlI2CRepeater );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
499
src/source/tuner/rtl/e4k/E4KTunerEditor.java
Normal file
499
src/source/tuner/rtl/e4k/E4KTunerEditor.java
Normal file
@@ -0,0 +1,499 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 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 source.tuner.rtl.e4k;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SpinnerModel;
|
||||
import javax.swing.SpinnerNumberModel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.usb.UsbException;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.usb4java.LibUsbException;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.configuration.TunerConfiguration;
|
||||
import source.tuner.configuration.TunerConfigurationEditor;
|
||||
import source.tuner.configuration.TunerConfigurationEvent;
|
||||
import source.tuner.configuration.TunerConfigurationModel;
|
||||
import source.tuner.rtl.RTL2832Tuner;
|
||||
import source.tuner.rtl.RTL2832TunerController.Descriptor;
|
||||
import source.tuner.rtl.RTL2832TunerController.SampleRate;
|
||||
import source.tuner.rtl.e4k.E4KTunerController.E4KEnhanceGain;
|
||||
import source.tuner.rtl.e4k.E4KTunerController.E4KGain;
|
||||
import source.tuner.rtl.e4k.E4KTunerController.E4KLNAGain;
|
||||
import source.tuner.rtl.e4k.E4KTunerController.E4KMixerGain;
|
||||
|
||||
public class E4KTunerEditor extends TunerConfigurationEditor
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( E4KTunerEditor.class );
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JTextField mConfigurationName;
|
||||
private JButton mTunerInfo;
|
||||
private JComboBox<SampleRate> mComboSampleRate;
|
||||
private JSpinner mFrequencyCorrection;
|
||||
private JComboBox<E4KGain> mComboMasterGain;
|
||||
private JComboBox<E4KMixerGain> mComboMixerGain;
|
||||
private JComboBox<E4KLNAGain> mComboLNAGain;
|
||||
private JComboBox<E4KEnhanceGain> mComboEnhanceGain;
|
||||
|
||||
private E4KTunerController mController;
|
||||
private boolean mLoading;
|
||||
|
||||
public E4KTunerEditor( TunerConfigurationModel tunerConfigurationModel, RTL2832Tuner tuner )
|
||||
{
|
||||
super( tunerConfigurationModel );
|
||||
mController = (E4KTunerController)tuner.getController();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
private E4KTunerConfiguration getConfiguration()
|
||||
{
|
||||
if( hasItem() )
|
||||
{
|
||||
return (E4KTunerConfiguration)getItem();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 4", "[right][grow,fill][right][grow,fill]",
|
||||
"[][][][][][][][grow]" ) );
|
||||
|
||||
add( new JLabel( "E4000 Tuner Configuration" ), "span,align center" );
|
||||
|
||||
/**
|
||||
* Tuner Configuration Name
|
||||
*/
|
||||
add( new JLabel( "Name:" ) );
|
||||
mConfigurationName = new JTextField();
|
||||
mConfigurationName.setEnabled( false );
|
||||
mConfigurationName.addFocusListener( new FocusListener()
|
||||
{
|
||||
@Override
|
||||
public void focusLost( FocusEvent e )
|
||||
{
|
||||
save();
|
||||
}
|
||||
@Override
|
||||
public void focusGained( FocusEvent e ) {}
|
||||
} );
|
||||
|
||||
add( mConfigurationName, "span 2" );
|
||||
|
||||
mTunerInfo = new JButton( "Tuner Info" );
|
||||
mTunerInfo.setEnabled( false );
|
||||
mTunerInfo.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
JOptionPane.showMessageDialog( E4KTunerEditor.this, getTunerInfo(),
|
||||
"Tuner Info", JOptionPane.INFORMATION_MESSAGE );
|
||||
}
|
||||
} );
|
||||
add( mTunerInfo );
|
||||
|
||||
mComboSampleRate = new JComboBox<>( SampleRate.values() );
|
||||
mComboSampleRate.setEnabled( false );
|
||||
mComboSampleRate.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
SampleRate sampleRate = (SampleRate)mComboSampleRate.getSelectedItem();
|
||||
|
||||
try
|
||||
{
|
||||
mController.setSampleRate( sampleRate );
|
||||
save();
|
||||
}
|
||||
catch ( SourceException | LibUsbException eSampleRate )
|
||||
{
|
||||
JOptionPane.showMessageDialog( E4KTunerEditor.this,
|
||||
"E4K Tuner Controller - couldn't apply the sample rate setting [" +
|
||||
sampleRate.getLabel() + "] " + eSampleRate.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "E4K Tuner Controller - couldn't apply sample rate setting [" +
|
||||
sampleRate.getLabel() + "]", eSampleRate );
|
||||
}
|
||||
}
|
||||
} );
|
||||
add( new JLabel( "Sample Rate:" ) );
|
||||
add( mComboSampleRate );
|
||||
|
||||
SpinnerModel model = new SpinnerNumberModel( 0.0, //initial value
|
||||
-1000.0, //min
|
||||
1000.0, //max
|
||||
0.1 ); //step
|
||||
|
||||
mFrequencyCorrection = new JSpinner( model );
|
||||
mFrequencyCorrection.setEnabled( false );
|
||||
|
||||
JSpinner.NumberEditor editor =
|
||||
(JSpinner.NumberEditor)mFrequencyCorrection.getEditor();
|
||||
|
||||
DecimalFormat format = editor.getFormat();
|
||||
format.setMinimumFractionDigits( 1 );
|
||||
editor.getTextField().setHorizontalAlignment( SwingConstants.CENTER );
|
||||
|
||||
mFrequencyCorrection.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
final double value = ((SpinnerNumberModel)mFrequencyCorrection
|
||||
.getModel()).getNumber().doubleValue();
|
||||
|
||||
try
|
||||
{
|
||||
mController.setFrequencyCorrection( value );
|
||||
save();
|
||||
}
|
||||
catch ( SourceException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog( E4KTunerEditor.this, "E4K Tuner Controller - "
|
||||
+ "couldn't apply frequency correction value: " + value + e1.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "E4K Tuner Controller - couldn't apply frequency correction value:"
|
||||
+ value, e1 );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
add( new JLabel( "PPM:" ) );
|
||||
add( mFrequencyCorrection );
|
||||
|
||||
add( new JSeparator( JSeparator.HORIZONTAL ), "span,grow" );
|
||||
add( new JLabel( "Gain" ), "wrap" );
|
||||
|
||||
mComboMasterGain = new JComboBox<E4KGain>( E4KGain.values() );
|
||||
mComboMasterGain.setEnabled( false );
|
||||
mComboMasterGain.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
try
|
||||
{
|
||||
E4KGain gain = (E4KGain)mComboMasterGain.getSelectedItem();
|
||||
|
||||
mController.setGain( (E4KGain)mComboMasterGain.getSelectedItem(), true );
|
||||
|
||||
if( gain == E4KGain.MANUAL )
|
||||
{
|
||||
mComboMixerGain.setSelectedItem( mController.getMixerGain( true ) );
|
||||
mComboMixerGain.setEnabled( true );
|
||||
|
||||
mComboLNAGain.setSelectedItem( mController.getLNAGain( true ) );
|
||||
mComboLNAGain.setEnabled( true );
|
||||
|
||||
mComboEnhanceGain.setSelectedItem( mController.getEnhanceGain( true ) );
|
||||
mComboEnhanceGain.setEnabled( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
mComboMixerGain.setEnabled( false );
|
||||
mComboMixerGain.setSelectedItem( gain.getMixerGain() );
|
||||
|
||||
mComboLNAGain.setEnabled( false );
|
||||
mComboLNAGain.setSelectedItem( gain.getLNAGain() );
|
||||
|
||||
mComboEnhanceGain.setEnabled( false );
|
||||
mComboEnhanceGain.setSelectedItem( gain.getEnhanceGain() );
|
||||
}
|
||||
|
||||
save();
|
||||
}
|
||||
catch ( UsbException e )
|
||||
{
|
||||
JOptionPane.showMessageDialog( E4KTunerEditor.this, "E4K Tuner Controller - "
|
||||
+ "couldn't apply the gain setting - " + e.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "E4K Tuner Controller - couldn't apply gain setting", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
mComboMasterGain.setToolTipText( "<html>Select <b>AUTOMATIC</b> for auto "
|
||||
+ "gain, <b>MANUAL</b> to enable<br> independent control of "
|
||||
+ "<i>Mixer</i>, <i>LNA</i> and <i>Enhance</i> gain<br>"
|
||||
+ "settings, or one of the individual gain settings for<br>"
|
||||
+ "semi-manual gain control</html>" );
|
||||
add( new JLabel( "Master:" ) );
|
||||
add( mComboMasterGain );
|
||||
|
||||
mComboMixerGain = new JComboBox<E4KMixerGain>( E4KMixerGain.values() );
|
||||
mComboMixerGain.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
try
|
||||
{
|
||||
E4KMixerGain mixerGain = (E4KMixerGain)mComboMixerGain.getSelectedItem();
|
||||
mController.setMixerGain( mixerGain, true );
|
||||
save();
|
||||
}
|
||||
catch ( UsbException e )
|
||||
{
|
||||
JOptionPane.showMessageDialog( E4KTunerEditor.this, "E4K Tuner Controller - "
|
||||
+ "couldn't apply the mixer gain setting - " + e.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "E4K Tuner Controller - couldn't apply mixer gain setting", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
mComboMixerGain.setToolTipText( "<html>Mixer Gain. Set master gain "
|
||||
+ "to <b>MASTER</b> to enable adjustment</html>" );
|
||||
mComboMixerGain.setEnabled( false );
|
||||
add( new JLabel( "Mixer:" ) );
|
||||
add( mComboMixerGain );
|
||||
|
||||
mComboLNAGain = new JComboBox<E4KLNAGain>( E4KLNAGain.values() );
|
||||
mComboLNAGain.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
try
|
||||
{
|
||||
E4KLNAGain lnaGain = (E4KLNAGain)mComboLNAGain.getSelectedItem();
|
||||
mController.setLNAGain( lnaGain, true );
|
||||
save();
|
||||
}
|
||||
catch ( UsbException e )
|
||||
{
|
||||
JOptionPane.showMessageDialog( E4KTunerEditor.this, "E4K Tuner Controller - "
|
||||
+ "couldn't apply the LNA gain setting - " + e.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "E4K Tuner Controller - couldn't apply LNA gain setting - ", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
mComboLNAGain.setToolTipText( "<html>LNA Gain. Set master gain "
|
||||
+ "to <b>MANUAL</b> to enable adjustment</html>" );
|
||||
mComboLNAGain.setEnabled( false );
|
||||
add( new JLabel( "LNA:" ) );
|
||||
add( mComboLNAGain );
|
||||
|
||||
mComboEnhanceGain = new JComboBox<E4KEnhanceGain>( E4KEnhanceGain.values() );
|
||||
mComboEnhanceGain.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
try
|
||||
{
|
||||
E4KEnhanceGain enhance = (E4KEnhanceGain)mComboEnhanceGain.getSelectedItem();
|
||||
mController.setEnhanceGain( enhance, true );
|
||||
save();
|
||||
}
|
||||
catch ( UsbException e )
|
||||
{
|
||||
JOptionPane.showMessageDialog( E4KTunerEditor.this, "E4K Tuner Controller - "
|
||||
+ "couldn't apply the enhance gain setting - " + e.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "E4K Tuner Controller - couldn't apply enhance gain setting", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
mComboEnhanceGain.setToolTipText( "<html>Enhance Gain. Set master gain "
|
||||
+ "to <b>MANUAL</b> to enable adjustment</html>" );
|
||||
mComboEnhanceGain.setEnabled( false );
|
||||
add( new JLabel( "Enhance:" ) );
|
||||
add( mComboEnhanceGain );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets each of the tuner configuration controls to the enabled argument state
|
||||
*/
|
||||
private void setControlsEnabled( boolean enabled )
|
||||
{
|
||||
if( mConfigurationName.isEnabled() != enabled )
|
||||
{
|
||||
mConfigurationName.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mTunerInfo.isEnabled() != enabled )
|
||||
{
|
||||
mTunerInfo.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mFrequencyCorrection.isEnabled() != enabled )
|
||||
{
|
||||
mFrequencyCorrection.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mComboSampleRate.isEnabled() != enabled )
|
||||
{
|
||||
mComboSampleRate.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mComboMasterGain.isEnabled() != enabled )
|
||||
{
|
||||
mComboMasterGain.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mComboMixerGain.isEnabled() != enabled )
|
||||
{
|
||||
mComboMixerGain.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mComboLNAGain.isEnabled() != enabled )
|
||||
{
|
||||
mComboLNAGain.setEnabled( enabled );
|
||||
}
|
||||
|
||||
if( mComboEnhanceGain.isEnabled() != enabled )
|
||||
{
|
||||
mComboEnhanceGain.setEnabled( enabled );
|
||||
}
|
||||
}
|
||||
|
||||
private String getTunerInfo()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
Descriptor descriptor = mController.getDescriptor();
|
||||
|
||||
sb.append( "<html><h3>RTL-2832 with E4000 Tuner</h3>" );
|
||||
|
||||
if( descriptor == null )
|
||||
{
|
||||
sb.append( "No EEPROM Descriptor Available" );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "<b>USB ID: </b>" );
|
||||
sb.append( descriptor.getVendorID() );
|
||||
sb.append( ":" );
|
||||
sb.append( descriptor.getProductID() );
|
||||
sb.append( "<br>" );
|
||||
|
||||
sb.append( "<b>Vendor: </b>" );
|
||||
sb.append( descriptor.getVendorLabel() );
|
||||
sb.append( "<br>" );
|
||||
|
||||
sb.append( "<b>Product: </b>" );
|
||||
sb.append( descriptor.getProductLabel() );
|
||||
sb.append( "<br>" );
|
||||
|
||||
sb.append( "<b>Serial: </b>" );
|
||||
sb.append( descriptor.getSerial() );
|
||||
sb.append( "<br>" );
|
||||
|
||||
sb.append( "<b>IR Enabled: </b>" );
|
||||
sb.append( descriptor.irEnabled() );
|
||||
sb.append( "<br>" );
|
||||
|
||||
sb.append( "<b>Remote Wake: </b>" );
|
||||
sb.append( descriptor.remoteWakeupEnabled() );
|
||||
sb.append( "<br>" );
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
if( hasItem() && !mLoading )
|
||||
{
|
||||
E4KTunerConfiguration config = getConfiguration();
|
||||
|
||||
config.setName( mConfigurationName.getText() );
|
||||
|
||||
config.setSampleRate( (SampleRate)mComboSampleRate.getSelectedItem() );
|
||||
|
||||
double value = ((SpinnerNumberModel)mFrequencyCorrection
|
||||
.getModel()).getNumber().doubleValue();
|
||||
config.setFrequencyCorrection( value );
|
||||
|
||||
config.setMasterGain( (E4KGain)mComboMasterGain.getSelectedItem() );
|
||||
config.setMixerGain( (E4KMixerGain)mComboMixerGain.getSelectedItem() );
|
||||
config.setLNAGain( (E4KLNAGain)mComboLNAGain.getSelectedItem() );
|
||||
config.setEnhanceGain( (E4KEnhanceGain)mComboEnhanceGain.getSelectedItem() );
|
||||
|
||||
getTunerConfigurationModel().broadcast( new TunerConfigurationEvent(
|
||||
getConfiguration(), TunerConfigurationEvent.Event.CHANGE ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem( TunerConfiguration tunerConfiguration )
|
||||
{
|
||||
super.setItem( tunerConfiguration );
|
||||
|
||||
//Toggle loading so that we don't fire a change event and schedule a settings file save
|
||||
mLoading = true;
|
||||
|
||||
if( hasItem() )
|
||||
{
|
||||
E4KTunerConfiguration config = getConfiguration();
|
||||
|
||||
if( tunerConfiguration.isAssigned() )
|
||||
{
|
||||
setControlsEnabled( true );
|
||||
|
||||
mConfigurationName.setText( config.getName() );
|
||||
mFrequencyCorrection.setValue( config.getFrequencyCorrection() );
|
||||
mComboSampleRate.setSelectedItem( config.getSampleRate() );
|
||||
mComboMasterGain.setSelectedItem( config.getMasterGain() );
|
||||
mComboMixerGain.setSelectedItem( config.getMixerGain() );
|
||||
mComboLNAGain.setSelectedItem( config.getLNAGain() );
|
||||
mComboEnhanceGain.setSelectedItem( config.getEnhanceGain() );
|
||||
}
|
||||
else
|
||||
{
|
||||
setControlsEnabled( false );
|
||||
mConfigurationName.setText( config.getName() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setControlsEnabled( false );
|
||||
mConfigurationName.setText( "" );
|
||||
}
|
||||
|
||||
mLoading = false;
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.tuner.rtl.e4k;
|
||||
|
||||
import gui.control.JFrequencyControl;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.EventQueue;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.frequency.FrequencyChangeEvent;
|
||||
import source.tuner.frequency.FrequencyChangeListener;
|
||||
import source.tuner.frequency.FrequencyChangeEvent.Event;
|
||||
import source.tuner.rtl.RTL2832InfoPanel;
|
||||
|
||||
import com.jidesoft.swing.JideTabbedPane;
|
||||
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class E4KTunerEditorPanel extends JPanel implements FrequencyChangeListener
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( E4KTunerEditorPanel.class );
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private E4KTunerController mController;
|
||||
private ResourceManager mResourceManager;
|
||||
|
||||
private JFrequencyControl mFrequencyControl;
|
||||
|
||||
public E4KTunerEditorPanel( E4KTunerController controller,
|
||||
ResourceManager resourceManager )
|
||||
{
|
||||
mController = controller;
|
||||
mResourceManager = resourceManager;
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 2", "[right][grow]", "[][][grow]" ) );
|
||||
|
||||
add( new JLabel( "RTL2832 with E4000 Tuner" ), "span 2, align center, wrap" );
|
||||
|
||||
mFrequencyControl = new JFrequencyControl();
|
||||
|
||||
mFrequencyControl.addListener( this );
|
||||
|
||||
/* Add frequency control as listener on the controller, to maintain
|
||||
* sync with the tuned frequency value */
|
||||
mController.addListener( mFrequencyControl );
|
||||
|
||||
mFrequencyControl.setFrequency( mController.getFrequency(), false );
|
||||
|
||||
add( mFrequencyControl, "span 2, align center, wrap" );
|
||||
|
||||
JideTabbedPane tabs = new JideTabbedPane();
|
||||
tabs.setFont( this.getFont() );
|
||||
tabs.setForeground( Color.BLACK );
|
||||
|
||||
tabs.addTab( "Configuration",
|
||||
new E4KTunerConfigurationPanel( mResourceManager, mController ) );
|
||||
|
||||
tabs.addTab( "Info", new RTL2832InfoPanel( mController ) );
|
||||
|
||||
add( tabs, "grow,push,span" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Frequency change listener for the frequency control gui component to
|
||||
* apply end-user requested frequency changes against the tuner
|
||||
*/
|
||||
@Override
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION )
|
||||
{
|
||||
final long frequency = event.getValue().longValue();
|
||||
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
mController.setFrequency( frequency );
|
||||
}
|
||||
catch ( SourceException e )
|
||||
{
|
||||
mLog.error( "E4KTunerController - error setting frequency [" +
|
||||
frequency + "]", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user