[WIP] Adds locking mechanism to tuner controllers so that the

polyphase channel manager can block users from changing frequency and/or
sample rate when polyphase channels are allocated.
This commit is contained in:
Denny
2018-02-04 06:30:25 -05:00
parent 85691edacb
commit 96d9d6f750
14 changed files with 3271 additions and 3031 deletions

View File

@@ -147,6 +147,7 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
mChannelCalculator.getChannelSampleRate());
mChannelSources.add(channelSource);
mSourceEventBroadcaster.broadcast(SourceEvent.channelCountChange(getTunerChannelCount()));
}
}
catch(IllegalArgumentException iae)
@@ -225,7 +226,6 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
synchronized(mBufferProcessor)
{
mPolyphaseChannelizer.addChannel(channelSource);
mSourceEventBroadcaster.broadcast(SourceEvent.channelCountChange(getTunerChannelCount()));
if(mPolyphaseChannelizer.getRegisteredChannelCount() == 1)
{

View File

@@ -20,7 +20,6 @@ package io.github.dsheirer.gui.control;
import io.github.dsheirer.source.ISourceEventProcessor;
import io.github.dsheirer.source.InvalidFrequencyException;
import io.github.dsheirer.source.SourceEvent;
import io.github.dsheirer.source.SourceEvent.Event;
import io.github.dsheirer.source.SourceException;
import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger;
@@ -32,6 +31,7 @@ import javax.swing.JPanel;
import javax.swing.JTextField;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Image;
import java.awt.Point;
@@ -146,9 +146,38 @@ public class JFrequencyControl extends JPanel implements ISourceEventProcessor
@Override
public void process(SourceEvent event)
{
if(event.getEvent() == Event.NOTIFICATION_FREQUENCY_CHANGE)
switch(event.getEvent())
{
setFrequency(event.getValue().longValue(), false);
case NOTIFICATION_FREQUENCY_CHANGE:
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
setFrequency(event.getValue().longValue(), false);
}
});
break;
case NOTIFICATION_FREQUENCY_AND_SAMPLE_RATE_LOCKED:
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
setEnabled(false);
}
});
break;
case NOTIFICATION_FREQUENCY_AND_SAMPLE_RATE_UNLOCKED:
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
setEnabled(true);
}
});
break;
}
}

View File

@@ -27,6 +27,8 @@ public class SourceEvent
NOTIFICATION_CHANNEL_COUNT_CHANGE,
NOTIFICATION_CHANNEL_FREQUENCY_CORRECTION_CHANGE,
NOTIFICATION_CHANNEL_SAMPLE_RATE_CHANGE,
NOTIFICATION_FREQUENCY_AND_SAMPLE_RATE_LOCKED,
NOTIFICATION_FREQUENCY_AND_SAMPLE_RATE_UNLOCKED,
NOTIFICATION_FREQUENCY_CHANGE,
NOTIFICATION_FREQUENCY_CORRECTION_CHANGE,
NOTIFICATION_SAMPLE_RATE_CHANGE,
@@ -119,6 +121,22 @@ public class SourceEvent
return mSource != null;
}
/**
* Creates a new locked state change event
*/
public static SourceEvent lockedState()
{
return new SourceEvent(Event.NOTIFICATION_FREQUENCY_AND_SAMPLE_RATE_LOCKED, 1);
}
/**
* Creates a new unlocked state change event
*/
public static SourceEvent unlockedState()
{
return new SourceEvent(Event.NOTIFICATION_FREQUENCY_AND_SAMPLE_RATE_UNLOCKED, 0);
}
/**
* Creates a new frequency change event
*

View File

@@ -104,6 +104,37 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
}
}
/**
* Indicates if the frequency and sample rate controls are locked by another process. User interface controls
* should monitor source events and check the locked state via this method to correctly render the enabled state
* of the frequency and sample rate controls.
*
* @return true if the tuner controller is locked.
*/
public boolean isLocked()
{
return mFrequencyController.isLocked();
}
/**
* Sets the frequency and sample rate locked state to the locked argument value. This should only be changed
* by a downstream consumer of samples to prevent users or other processes from modifying the center frequency
* and/or sample rate of the tuner while processing samples.
*
* @param locked true to indicate the tuner controller is in a locked state, otherwise false.
*/
public void setLocked(boolean locked)
{
try
{
mFrequencyController.setLocked(locked);
}
catch(SourceException se)
{
mLog.error("Couldn't set frequency controller locked state to: " + locked);
}
}
public int getBandwidth()
{
return mFrequencyController.getBandwidth();

View File

@@ -1,6 +1,6 @@
/*******************************************************************************
* sdr-trunk
* Copyright (C) 2014-2017 Dennis Sheirer
* Copyright (C) 2014-2018 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
@@ -44,306 +44,305 @@ import java.awt.event.ActionListener;
public class TunerEditor extends Editor<Tuner>
{
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
private final static Logger mLog = LoggerFactory.getLogger( TunerEditor.class );
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();
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 )
{
mTunerConfigurationModel = tunerConfigurationModel;
init();
}
public TunerEditor(TunerConfigurationModel tunerConfigurationModel)
{
mTunerConfigurationModel = tunerConfigurationModel;
init();
}
public void init()
{
setLayout( new MigLayout( "insets 0 0 0 0", "[grow,fill]", "[grow,fill]" ) );
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][]" ) );
JPanel listPanel = new JPanel();
listPanel.setLayout(new MigLayout("fill,wrap 3", "[grow,fill]", "[][][][grow,fill][]"));
listPanel.add( mSelectedTunerType, "span" );
listPanel.add(mSelectedTunerType, "span");
mFrequencyControl.setEnabled( false );
listPanel.add( mFrequencyControl, "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();
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(row >= 0)
{
int modelRow = mTunerConfigurationTable.convertRowIndexToModel(row);
if( modelRow >= 0 )
{
setTunerConfiguration( mTunerConfigurationModel.getTunerConfiguration( modelRow ) );
}
}
}
}
} );
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" );
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();
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() );
String name = mTunerConfigurationModel
.getDistinctName(tuner.getTunerType(), tuner.getUniqueID());
TunerConfiguration config = TunerConfigurationFactory
.getTunerConfiguration( tuner.getTunerType(),
tuner.getUniqueID(), name );
TunerConfiguration config = TunerConfigurationFactory
.getTunerConfiguration(tuner.getTunerType(),
tuner.getUniqueID(), name);
mTunerConfigurationModel.addTunerConfiguration( config );
}
} );
listPanel.add( mNewConfigurationButton );
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 );
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();
if(choice == JOptionPane.YES_OPTION)
{
TunerConfiguration selected = getSelectedTunerConfiguration();
mTunerConfigurationModel.removeTunerConfiguration( selected );
mTunerConfigurationTable.setRowSelectionInterval( 0, 0 );
}
}
} );
listPanel.add( mDeleteConfigurationButton );
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();
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 );
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 ) );
//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 ) );
mEditorScroller = new JScrollPane(mEditor);
mEditorScroller.setPreferredSize(new Dimension(100, 80));
mEditorSplitPane = new JideSplitPane( JideSplitPane.HORIZONTAL_SPLIT );
mEditorSplitPane.add( listScroller );
mEditorSplitPane.add( mEditorScroller );
mEditorSplitPane = new JideSplitPane(JideSplitPane.HORIZONTAL_SPLIT);
mEditorSplitPane.add(listScroller);
mEditorSplitPane.add(mEditorScroller);
add( mEditorSplitPane );
}
add(mEditorSplitPane);
}
private TunerConfiguration getSelectedTunerConfiguration()
{
int tableRow = mTunerConfigurationTable.getSelectedRow();
private TunerConfiguration getSelectedTunerConfiguration()
{
int tableRow = mTunerConfigurationTable.getSelectedRow();
if( tableRow >= 0 )
{
int modelRow = mTunerConfigurationTable.convertRowIndexToModel( tableRow );
if(tableRow >= 0)
{
int modelRow = mTunerConfigurationTable.convertRowIndexToModel(tableRow);
if( modelRow >= 0 )
{
return mTunerConfigurationModel.getTunerConfiguration( modelRow );
}
}
if(modelRow >= 0)
{
return mTunerConfigurationModel.getTunerConfiguration(modelRow);
}
}
return null;
}
return null;
}
@Override
public void save()
{
//Unused
}
@Override
public void save()
{
//Unused
}
@Override
public void setItem( Tuner tuner )
{
//Cleanup previously selected tuner
if( hasItem() )
{
Tuner previous = getItem();
previous.getTunerController().removeListener( mFrequencyControl );
mFrequencyControl.removeListener( previous.getTunerController() );
}
@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 );
super.setItem(tuner);
if( hasItem() )
{
mSelectedTunerType.setText( tuner.getName() );
mFrequencyControl.setEnabled( true );
mTunerConfigurationTable.setEnabled( true );
mNewConfigurationButton.setEnabled( true );
if(hasItem())
{
mSelectedTunerType.setText(tuner.getName());
mTunerConfigurationTable.setEnabled(true);
mNewConfigurationButton.setEnabled(true);
//Change to an editor for this config's tuner type
mEditor = TunerConfigurationFactory.getEditor( getItem(), mTunerConfigurationModel );
//Change to an editor for this config's tuner type
mEditor = TunerConfigurationFactory.getEditor(getItem(), mTunerConfigurationModel);
mRowSorter.setRowFilter( new ConfigurationRowFilter( tuner.getTunerType(),
tuner.getUniqueID() ) );
mRowSorter.setRowFilter(new ConfigurationRowFilter(tuner.getTunerType(),
tuner.getUniqueID()));
TunerConfiguration assigned = mTunerConfigurationModel
.getTunerConfiguration( tuner.getTunerType(), tuner.getUniqueID() );
TunerConfiguration assigned = mTunerConfigurationModel
.getTunerConfiguration(tuner.getTunerType(), tuner.getUniqueID());
int modelIndex = mTunerConfigurationModel.getRowIndex( assigned );
int modelIndex = mTunerConfigurationModel.getRowIndex(assigned);
if( modelIndex >= 0 )
{
int viewIndex = mTunerConfigurationTable
.convertRowIndexToView( modelIndex );
if(modelIndex >= 0)
{
int viewIndex = mTunerConfigurationTable
.convertRowIndexToView(modelIndex);
if( viewIndex >= 0 )
{
mTunerConfigurationTable
.setRowSelectionInterval( viewIndex, viewIndex );
}
}
if(viewIndex >= 0)
{
mTunerConfigurationTable
.setRowSelectionInterval(viewIndex, viewIndex);
}
}
//Link frequency control to the tuner
mFrequencyControl.addListener( tuner.getTunerController() );
//Link frequency control to the tuner and set enabled state
mFrequencyControl.addListener(tuner.getTunerController());
mFrequencyControl.setEnabled(!tuner.getTunerController().isLocked());
//Link tuner to frequency control
tuner.getTunerController().addListener( mFrequencyControl );
//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>();
}
//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 );
}
//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 setTunerConfiguration( TunerConfiguration config )
{
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 );
}
private void setTunerConfiguration(TunerConfiguration config)
{
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(mDeleteConfigurationButton.isEnabled())
{
mDeleteConfigurationButton.setEnabled(false);
}
}
}
else
{
if(mDeleteConfigurationButton.isEnabled())
{
mDeleteConfigurationButton.setEnabled(false);
}
if( mAssignConfigurationButton.isEnabled() )
{
mAssignConfigurationButton.setEnabled( false );
}
}
if(mAssignConfigurationButton.isEnabled())
{
mAssignConfigurationButton.setEnabled(false);
}
}
mEditor.setItem( config );
}
mEditor.setItem(config);
}
public class ConfigurationRowFilter extends RowFilter<TunerConfigurationModel,Integer>
{
private TunerType mTunerType;
private String mUniqueID;
public class ConfigurationRowFilter extends RowFilter<TunerConfigurationModel,Integer>
{
private TunerType mTunerType;
private String mUniqueID;
public ConfigurationRowFilter( TunerType type, String uniqueID )
{
mTunerType = type;
mUniqueID = uniqueID;
}
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() );
@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 );
}
}
return config != null &&
config.getTunerType() == mTunerType &&
config.getUniqueID() != null &&
config.getUniqueID().contentEquals(mUniqueID);
}
}
}

View File

@@ -1,20 +1,43 @@
/*******************************************************************************
* sdr-trunk
* Copyright (C) 2014-2018 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package io.github.dsheirer.source.tuner.configuration;
import io.github.dsheirer.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;
}
private static final long serialVersionUID = 1L;
private TunerConfigurationModel mTunerConfigurationModel;
public TunerConfigurationEditor(TunerConfigurationModel model)
{
mTunerConfigurationModel = model;
}
public TunerConfigurationModel getTunerConfigurationModel()
{
return mTunerConfigurationModel;
}
/**
* Sets the state of the sample rate editor control. When enabled, users are allowed to change the sample rate
* of the tuner. When disabled, user controls should NOT allow sample rate changes.
*
* @param enabled state for the sample rate control
*/
public abstract void setSampleRateControl(boolean enabled);
}

View File

@@ -1,17 +1,17 @@
/*******************************************************************************
* 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/>
******************************************************************************/
@@ -51,475 +51,489 @@ import java.text.DecimalFormat;
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 );
}
}
} );
}
}
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;
}
@Override
public void setSampleRateControl(boolean enabled)
{
//no-op
}
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);
}
}
});
}
}
}

View File

@@ -1,19 +1,17 @@
/*******************************************************************************
* 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/>
* sdr-trunk
* Copyright (C) 2014-2018 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package io.github.dsheirer.source.tuner.fcd.proplusV2;
@@ -48,278 +46,287 @@ import java.text.DecimalFormat;
public class FCD2TunerEditor extends TunerConfigurationEditor
{
private final static Logger mLog = LoggerFactory.getLogger( FCD2TunerEditor.class );
private static final long serialVersionUID = 1L;
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 JTextField mConfigurationName;
private JButton mTunerInfo;
private JSpinner mFrequencyCorrection;
private JCheckBox mLNAGain;
private JCheckBox mMixerGain;
private boolean mLoading;
private FCD2TunerController mController;
private FCD2TunerController mController;
public FCD2TunerEditor( TunerConfigurationModel tunerConfigurationModel, FCDTuner tuner )
{
super( tunerConfigurationModel );
mController = (FCD2TunerController)tuner.getController();
public FCD2TunerEditor(TunerConfigurationModel tunerConfigurationModel, FCDTuner tuner)
{
super(tunerConfigurationModel);
mController = (FCD2TunerController)tuner.getController();
init();
}
init();
}
private FCD2TunerConfiguration getConfiguration()
{
if( hasItem() )
{
return (FCD2TunerConfiguration)getItem();
}
private FCD2TunerConfiguration getConfiguration()
{
if(hasItem())
{
return (FCD2TunerConfiguration)getItem();
}
return null;
}
return null;
}
private void init()
{
setLayout( new MigLayout( "fill,wrap 4", "[right][grow,fill][right][grow,fill]",
"[][][][][][grow]" ) );
@Override
public void setSampleRateControl(boolean enabled)
{
//no-op
}
add( new JLabel( "FCD Pro+ Tuner Configuration" ), "span,align center" );
private void init()
{
setLayout(new MigLayout("fill,wrap 4", "[right][grow,fill][right][grow,fill]",
"[][][][][][grow]"));
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("FCD Pro+ Tuner Configuration"), "span,align center");
add( new JLabel( "Name:" ) );
add( mConfigurationName, "span 2" );
mConfigurationName = new JTextField();
mConfigurationName.setEnabled(false);
mConfigurationName.addFocusListener(new FocusListener()
{
@Override
public void focusLost(FocusEvent e)
{
save();
}
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 );
@Override
public void focusGained(FocusEvent e)
{
}
});
SpinnerModel model = new SpinnerNumberModel( 0.0, //initial value
-1000.0, //min
1000.0, //max
0.1 ); //step
add(new JLabel("Name:"));
add(mConfigurationName, "span 2");
mFrequencyCorrection = new JSpinner( model );
mFrequencyCorrection.setEnabled( false );
JSpinner.NumberEditor editor =
(JSpinner.NumberEditor)mFrequencyCorrection.getEditor();
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);
DecimalFormat format = editor.getFormat();
format.setMinimumFractionDigits( 1 );
editor.getTextField().setHorizontalAlignment( SwingConstants.CENTER );
SpinnerModel model = new SpinnerNumberModel(0.0, //initial value
-1000.0, //min
1000.0, //max
0.1); //step
mFrequencyCorrection.addChangeListener( new ChangeListener()
{
@Override
public void stateChanged( ChangeEvent e )
{
double value = ((SpinnerNumberModel)mFrequencyCorrection
.getModel()).getNumber().doubleValue();
mFrequencyCorrection = new JSpinner(model);
mFrequencyCorrection.setEnabled(false);
JSpinner.NumberEditor editor =
(JSpinner.NumberEditor)mFrequencyCorrection.getEditor();
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() );
DecimalFormat format = editor.getFormat();
format.setMinimumFractionDigits(1);
editor.getTextField().setHorizontalAlignment(SwingConstants.CENTER);
mLog.error( "FuncubeDongleProPlus Controller - couldn't apply "
+ "frequency correction value: " + value, e1 );
}
}
} );
mFrequencyCorrection.addChangeListener(new ChangeListener()
{
@Override
public void stateChanged(ChangeEvent e)
{
double value = ((SpinnerNumberModel)mFrequencyCorrection
.getModel()).getNumber().doubleValue();
add( new JLabel( "PPM:" ) );
add( mFrequencyCorrection, "wrap" );
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());
add( new JSeparator( JSeparator.HORIZONTAL ), "span,grow" );
mLog.error("FuncubeDongleProPlus Controller - couldn't apply "
+ "frequency correction value: " + value, e1);
}
}
});
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("PPM:"));
add(mFrequencyCorrection, "wrap");
add( new JLabel( "" ) );
add( mLNAGain );
add(new JSeparator(JSeparator.HORIZONTAL), "span,grow");
/**
* Mixer Gain
*/
mMixerGain = new JCheckBox( "Mixer Gain" );
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);
}
}
});
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(mLNAGain);
add( new JLabel( "" ) );
add( mMixerGain );
}
/**
* Mixer Gain
*/
mMixerGain = new JCheckBox("Mixer Gain");
/**
* Sets each of the tuner configuration controls to the enabled argument state
*/
private void setControlsEnabled( boolean enabled )
{
if( mConfigurationName.isEnabled() != enabled )
{
mConfigurationName.setEnabled( enabled );
}
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);
}
}
});
if( mTunerInfo.isEnabled() != enabled )
{
mTunerInfo.setEnabled( enabled );
}
add(new JLabel(""));
add(mMixerGain);
}
if( mFrequencyCorrection.isEnabled() != enabled )
{
mFrequencyCorrection.setEnabled( enabled );
}
/**
* 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( mLNAGain.isEnabled() != enabled )
{
mLNAGain.setEnabled( enabled );
}
if(mTunerInfo.isEnabled() != enabled)
{
mTunerInfo.setEnabled(enabled);
}
if( mMixerGain.isEnabled() != enabled )
{
mMixerGain.setEnabled( enabled );
}
}
if(mFrequencyCorrection.isEnabled() != enabled)
{
mFrequencyCorrection.setEnabled(enabled);
}
private String getTunerInfo()
{
StringBuilder sb = new StringBuilder();
if(mLNAGain.isEnabled() != enabled)
{
mLNAGain.setEnabled(enabled);
}
sb.append( "<html><h3>Funcube Dongle Pro Plus Tuner</h3>" );
if(mMixerGain.isEnabled() != enabled)
{
mMixerGain.setEnabled(enabled);
}
}
sb.append( "<b>USB ID: </b>" );
sb.append( mController.getUSBID() );
sb.append( "<br>" );
private String getTunerInfo()
{
StringBuilder sb = new StringBuilder();
sb.append( "<b>USB Address: </b>" );
sb.append( mController.getUSBAddress() );
sb.append( "<br>" );
sb.append("<html><h3>Funcube Dongle Pro Plus Tuner</h3>");
sb.append( "<b>USB Speed: </b>" );
sb.append( mController.getUSBSpeed() );
sb.append( "<br>" );
sb.append("<b>USB ID: </b>");
sb.append(mController.getUSBID());
sb.append("<br>");
sb.append( "<b>Cellular Band: </b>" );
sb.append( mController.getConfiguration().getBandBlocking() );
sb.append( "<br>" );
sb.append("<b>USB Address: </b>");
sb.append(mController.getUSBAddress());
sb.append("<br>");
sb.append( "<b>Firmware: </b>" );
sb.append( mController.getConfiguration().getFirmware() );
sb.append( "<br>" );
sb.append("<b>USB Speed: </b>");
sb.append(mController.getUSBSpeed());
sb.append("<br>");
return sb.toString();
}
sb.append("<b>Cellular Band: </b>");
sb.append(mController.getConfiguration().getBandBlocking());
sb.append("<br>");
@Override
public void save()
{
if( hasItem() && !mLoading )
{
FCD2TunerConfiguration config = getConfiguration();
sb.append("<b>Firmware: </b>");
sb.append(mController.getConfiguration().getFirmware());
sb.append("<br>");
config.setName( mConfigurationName.getText() );
return sb.toString();
}
double value = ((SpinnerNumberModel)mFrequencyCorrection
.getModel()).getNumber().doubleValue();
config.setFrequencyCorrection( value );
@Override
public void save()
{
if(hasItem() && !mLoading)
{
FCD2TunerConfiguration config = getConfiguration();
config.setGainLNA( mLNAGain.isSelected() );
config.setGainMixer( mMixerGain.isSelected() );
config.setName(mConfigurationName.getText());
getTunerConfigurationModel().broadcast(
new TunerConfigurationEvent( getConfiguration(), Event.CHANGE ) );
}
}
double value = ((SpinnerNumberModel)mFrequencyCorrection
.getModel()).getNumber().doubleValue();
config.setFrequencyCorrection(value);
@Override
public void setItem( TunerConfiguration tunerConfiguration )
{
super.setItem( tunerConfiguration );
config.setGainLNA(mLNAGain.isSelected());
config.setGainMixer(mMixerGain.isSelected());
//Toggle loading so that we don't fire a change event and schedule a settings file save
mLoading = true;
getTunerConfigurationModel().broadcast(
new TunerConfigurationEvent(getConfiguration(), Event.CHANGE));
}
}
if( hasItem() )
{
FCD2TunerConfiguration config = getConfiguration();
@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( "" );
}
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;
}
mLoading = false;
}
}

View File

@@ -1,7 +1,6 @@
/*******************************************************************************
* *********************************************************************************************************************
* sdr-trunk
* Copyright (C) 2014-2017 Dennis Sheirer
* Copyright (C) 2014-2018 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
@@ -12,7 +11,7 @@
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <http://www.gnu.org/licenses/>
* *********************************************************************************************************************
*
******************************************************************************/
package io.github.dsheirer.source.tuner.frequency;
@@ -28,248 +27,284 @@ import java.util.List;
public class FrequencyController
{
private final static Logger mLog = LoggerFactory.getLogger(FrequencyController.class);
private final static Logger mLog = LoggerFactory.getLogger(FrequencyController.class);
private Tunable mTunable;
private long mFrequency = 101100000;
private long mTunedFrequency = 101100000;
private long mMinimumFrequency;
private long mMaximumFrequency;
private double mFrequencyCorrection = 0.0d;
private double mSampleRate = 0.0d;
private Tunable mTunable;
private long mFrequency = 101100000;
private long mTunedFrequency = 101100000;
private long mMinimumFrequency;
private long mMaximumFrequency;
private double mFrequencyCorrection = 0.0d;
private double mSampleRate = 0.0d;
private boolean mLocked = false;
private List<ISourceEventProcessor> mProcessors = new ArrayList<>();
private List<ISourceEventProcessor> mProcessors = new ArrayList<>();
public FrequencyController(Tunable tunable, long minFrequency, long maxFrequency, double frequencyCorrection)
{
mTunable = tunable;
mMinimumFrequency = minFrequency;
mMaximumFrequency = maxFrequency;
mFrequencyCorrection = frequencyCorrection;
}
public FrequencyController(Tunable tunable, long minFrequency, long maxFrequency, double frequencyCorrection)
{
mTunable = tunable;
mMinimumFrequency = minFrequency;
mMaximumFrequency = maxFrequency;
mFrequencyCorrection = frequencyCorrection;
}
/**
* Get bandwidth in hertz
*/
public int getBandwidth()
{
return (int)mSampleRate;
}
/**
* Indicates if this frequency controller is locked by a remote process. A locked state indicates that neither
* the frequency nor the sample rate should be changed. The remote process will typically be a downstream
* consumer of the data produced by the device being controlled (ie polyphase channelizer) that does not want
* the sample rate or frequency to be changed while processing is ongoing.
*
* @return true if locked or false if not locked.
*/
public boolean isLocked()
{
return mLocked;
}
/**
* Set sample rate in hertz
*/
public void setSampleRate(int sampleRate) throws SourceException
{
mSampleRate = sampleRate;
/**
* Sets the lock state for this frequency controller. Set to true when a consumer process requires that the
* frequency and sample rate controls be locked so that only the singular consumer process makes changes. This
* is primarily to lock down user interface controls when the polyphase channelizer is producing channels.
*
* @param locked state
*/
public void setLocked(boolean locked) throws SourceException
{
mLocked = locked;
broadcastSampleRateChange();
}
if(mLocked)
{
broadcast(SourceEvent.lockedState());
}
else
{
broadcast(SourceEvent.unlockedState());
}
}
/**
* Get sample rate in hertz
*/
public double getSampleRate()
{
return mSampleRate;
}
/**
* Get bandwidth in hertz
*/
public int getBandwidth()
{
return (int)mSampleRate;
}
/**
* Get frequency in hertz
*/
public long getFrequency()
{
return mFrequency;
}
/**
* Set sample rate in hertz
*/
public void setSampleRate(int sampleRate) throws SourceException
{
mSampleRate = sampleRate;
/**
* Set frequency
*
* @param frequency in hertz
* @throws SourceException if tunable doesn't support tuning a corrected
* version of the requested frequency
*/
public void setFrequency(long frequency) throws SourceException
{
setFrequency(frequency, true);
}
broadcastSampleRateChange();
}
/**
* Indicates if the specified frequency can be tuned (ie is within min/max frequency) by this controller.
* @param frequency to evaluate
* @return true if the frequency falls within the tuning range of this controller
*/
public boolean canTune(long frequency)
{
return getMinimumFrequency() <= frequency && frequency <= getMaximumFrequency();
}
/**
* Get sample rate in hertz
*/
public double getSampleRate()
{
return mSampleRate;
}
/**
* Set frequency with optional broadcast of frequency change event. This
* method supports changing the frequency correction value without
* broadcasting a frequency change event.
*/
private void setFrequency(long frequency, boolean broadcastChange) throws SourceException
{
long tunedFrequency = getTunedFrequency(frequency);
/**
* Get frequency in hertz
*/
public long getFrequency()
{
return mFrequency;
}
if(tunedFrequency < mMinimumFrequency)
{
throw new InvalidFrequencyException("Requested frequency not valid", frequency, mMinimumFrequency);
}
/**
* Set frequency
*
* @param frequency in hertz
* @throws SourceException if tunable doesn't support tuning a corrected
* version of the requested frequency
*/
public void setFrequency(long frequency) throws SourceException
{
setFrequency(frequency, true);
}
if(tunedFrequency > mMaximumFrequency)
{
throw new InvalidFrequencyException("Requested frequency not valid", frequency, mMaximumFrequency);
}
/**
* Indicates if the specified frequency can be tuned (ie is within min/max frequency) by this controller.
*
* @param frequency to evaluate
* @return true if the frequency falls within the tuning range of this controller
*/
public boolean canTune(long frequency)
{
return getMinimumFrequency() <= frequency && frequency <= getMaximumFrequency();
}
mFrequency = frequency;
/**
* Set frequency with optional broadcast of frequency change event. This
* method supports changing the frequency correction value without
* broadcasting a frequency change event.
*/
private void setFrequency(long frequency, boolean broadcastChange) throws SourceException
{
long tunedFrequency = getTunedFrequency(frequency);
mTunedFrequency = tunedFrequency;
if(tunedFrequency < mMinimumFrequency)
{
throw new InvalidFrequencyException("Requested frequency not valid", frequency, mMinimumFrequency);
}
if(mTunable != null)
{
mTunable.setTunedFrequency(mTunedFrequency);
}
if(tunedFrequency > mMaximumFrequency)
{
throw new InvalidFrequencyException("Requested frequency not valid", frequency, mMaximumFrequency);
}
/* Broadcast to all listeners that the frequency has changed */
if(broadcastChange)
{
broadcastFrequencyChange();
}
}
mFrequency = frequency;
public long getTunedFrequency()
{
return mTunedFrequency;
}
mTunedFrequency = tunedFrequency;
public long getMinimumFrequency()
{
return mMinimumFrequency;
}
if(mTunable != null)
{
mTunable.setTunedFrequency(mTunedFrequency);
}
public long getMaximumFrequency()
{
return mMaximumFrequency;
}
/* Broadcast to all listeners that the frequency has changed */
if(broadcastChange)
{
broadcastFrequencyChange();
}
}
/**
* Calculate the tuned frequency by adding frequency correction to the
* corrected frequency.
*
* @param correctedFrequency
*/
private long getTunedFrequency(long correctedFrequency)
{
return (long)((double)correctedFrequency /
(1.0 + (mFrequencyCorrection / 1000000.0)));
}
public long getTunedFrequency()
{
return mTunedFrequency;
}
/**
* Calculate the corrected frequency by subtracting frequency correction
* from the tuned frequency.
*
* @param tunedFrequency
*/
@SuppressWarnings("unused")
private long getCorrectedFrequency(long tunedFrequency)
{
return (long)((double)tunedFrequency /
(1.0 - (mFrequencyCorrection / 1000000.0)));
}
public long getMinimumFrequency()
{
return mMinimumFrequency;
}
public double getFrequencyCorrection()
{
return mFrequencyCorrection;
}
public long getMaximumFrequency()
{
return mMaximumFrequency;
}
public void setFrequencyCorrection(double correction) throws SourceException
{
mFrequencyCorrection = correction;
/**
* Calculate the tuned frequency by adding frequency correction to the
* corrected frequency.
*
* @param correctedFrequency
*/
private long getTunedFrequency(long correctedFrequency)
{
return (long)((double)correctedFrequency /
(1.0 + (mFrequencyCorrection / 1000000.0)));
}
if(mFrequency > 0)
{
setFrequency(mFrequency, true);
}
/**
* Calculate the corrected frequency by subtracting frequency correction
* from the tuned frequency.
*
* @param tunedFrequency
*/
@SuppressWarnings("unused")
private long getCorrectedFrequency(long tunedFrequency)
{
return (long)((double)tunedFrequency /
(1.0 - (mFrequencyCorrection / 1000000.0)));
}
broadcastFrequencyCorrectionChange();
}
public double getFrequencyCorrection()
{
return mFrequencyCorrection;
}
/**
* Adds listener to receive frequency change events
*/
public void addListener(ISourceEventProcessor processor)
{
if(!mProcessors.contains(processor))
{
mProcessors.add(processor);
}
}
public void setFrequencyCorrection(double correction) throws SourceException
{
mFrequencyCorrection = correction;
/**
* Removes listener from receiving frequency change events
*/
public void removeFrequencyChangeProcessor(ISourceEventProcessor processor)
{
mProcessors.remove(processor);
}
if(mFrequency > 0)
{
setFrequency(mFrequency, true);
}
broadcastFrequencyCorrectionChange();
}
/**
* Adds listener to receive frequency change events
*/
public void addListener(ISourceEventProcessor processor)
{
if(!mProcessors.contains(processor))
{
mProcessors.add(processor);
}
}
/**
* Removes listener from receiving frequency change events
*/
public void removeFrequencyChangeProcessor(ISourceEventProcessor processor)
{
mProcessors.remove(processor);
}
/**
* Broadcasts a change/update to the current (uncorrected) frequency or the
* bandwidth/sample rate value.
*/
protected void broadcastFrequencyChange() throws SourceException
{
broadcast(SourceEvent.frequencyChange(mFrequency));
}
/**
* Broadcasts a change/update to the current (uncorrected) frequency or the
* bandwidth/sample rate value.
*/
protected void broadcastFrequencyChange() throws SourceException
{
broadcast(SourceEvent.frequencyChange(mFrequency));
}
/**
* Broadcast a frequency error/correction value change
*/
protected void broadcastFrequencyCorrectionChange() throws SourceException
{
broadcast(SourceEvent.frequencyCorrectionChange((int)mFrequencyCorrection));
}
/**
* Broadcast a frequency error/correction value change
*/
protected void broadcastFrequencyCorrectionChange() throws SourceException
{
broadcast(SourceEvent.frequencyCorrectionChange((int)mFrequencyCorrection));
}
/**
* Broadcasts a sample rate change
*/
protected void broadcastSampleRateChange() throws SourceException
{
broadcast(SourceEvent.sampleRateChange(mSampleRate));
}
/**
* Broadcasts a sample rate change
*/
protected void broadcastSampleRateChange() throws SourceException
{
broadcast(SourceEvent.sampleRateChange(mSampleRate));
}
public void broadcast(SourceEvent event) throws SourceException
{
for(ISourceEventProcessor processor : mProcessors)
{
processor.process(event);
}
}
public void broadcast(SourceEvent event) throws SourceException
{
for(ISourceEventProcessor processor : mProcessors)
{
processor.process(event);
}
}
public interface Tunable
{
/**
* Gets the tuned frequency of the device
*/
public long getTunedFrequency() throws SourceException;
public interface Tunable
{
/**
* Gets the tuned frequency of the device
*/
public long getTunedFrequency() throws SourceException;
/**
* Sets the tuned frequency of the device
*/
public void setTunedFrequency(long frequency) throws SourceException;
/**
* Sets the tuned frequency of the device
*/
public void setTunedFrequency(long frequency) throws SourceException;
/**
* Gets the current bandwidth setting of the device
*/
public double getCurrentSampleRate() throws SourceException;
/**
* Gets the current bandwidth setting of the device
*/
public double getCurrentSampleRate() throws SourceException;
/**
* Indicates if this tunable can tune the frequency
*/
public boolean canTune(long frequency);
}
/**
* Indicates if this tunable can tune the frequency
*/
public boolean canTune(long frequency);
}
}

View File

@@ -1,6 +1,6 @@
/*******************************************************************************
* sdr-trunk
* Copyright (C) 2014-2017 Dennis Sheirer
* Copyright (C) 2014-2018 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
@@ -41,6 +41,7 @@ import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.usb.UsbException;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
@@ -51,7 +52,7 @@ public class HackRFTunerEditor extends TunerConfigurationEditor
{
private static final long serialVersionUID = 1L;
private final static Logger mLog = LoggerFactory.getLogger( HackRFTunerEditor.class );
private final static Logger mLog = LoggerFactory.getLogger(HackRFTunerEditor.class);
private JTextField mConfigurationName;
private JButton mTunerInfo;
@@ -64,9 +65,9 @@ public class HackRFTunerEditor extends TunerConfigurationEditor
private HackRFTunerController mController;
public HackRFTunerEditor( TunerConfigurationModel tunerConfigurationModel, HackRFTuner tuner )
public HackRFTunerEditor(TunerConfigurationModel tunerConfigurationModel, HackRFTuner tuner)
{
super( tunerConfigurationModel );
super(tunerConfigurationModel);
mController = tuner.getController();
@@ -75,7 +76,7 @@ public class HackRFTunerEditor extends TunerConfigurationEditor
private HackRFTunerConfiguration getConfiguration()
{
if( hasItem() )
if(hasItem())
{
return (HackRFTunerConfiguration)getItem();
}
@@ -83,241 +84,257 @@ public class HackRFTunerEditor extends TunerConfigurationEditor
return null;
}
private void init()
@Override
public void setSampleRateControl(boolean enabled)
{
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()
EventQueue.invokeLater(new Runnable()
{
@Override
public void focusLost( FocusEvent e )
public void run()
{
mComboSampleRate.setEnabled(enabled);
}
});
}
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 )
public void focusGained(FocusEvent 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()
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 )
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 );
mController.setSampleRate(sampleRate);
save();
}
catch ( SourceException|UsbException e2 )
catch(SourceException | UsbException e2)
{
JOptionPane.showMessageDialog( HackRFTunerEditor.this, "HackRF Tuner Controller"
JOptionPane.showMessageDialog(HackRFTunerEditor.this, "HackRF Tuner Controller"
+ " - couldn't apply the sample rate setting [" + sampleRate.getLabel() +
"] " + e2.getLocalizedMessage() );
"] " + e2.getLocalizedMessage());
mLog.error( "HackRF Tuner Controller - couldn't apply sample rate setting [" +
sampleRate.getLabel() + "]", e );
mLog.error("HackRF Tuner Controller - couldn't apply sample rate setting [" +
sampleRate.getLabel() + "]", e);
}
}
} );
add( new JLabel( "Sample Rate:" ) );
add( mComboSampleRate );
});
add(new JLabel("Sample Rate:"));
add(mComboSampleRate);
SpinnerModel model = new SpinnerNumberModel( 0.0, //initial value
SpinnerModel model = new SpinnerNumberModel(0.0, //initial value
-1000.0, //min
1000.0, //max
0.1 ); //step
0.1); //step
mFrequencyCorrection = new JSpinner( model );
mFrequencyCorrection.setEnabled( false );
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 );
format.setMinimumFractionDigits(1);
editor.getTextField().setHorizontalAlignment(SwingConstants.CENTER);
mFrequencyCorrection.addChangeListener( new ChangeListener()
mFrequencyCorrection.addChangeListener(new ChangeListener()
{
@Override
public void stateChanged( ChangeEvent e )
public void stateChanged(ChangeEvent e)
{
final double value = ((SpinnerNumberModel)mFrequencyCorrection
.getModel()).getNumber().doubleValue();
try
{
mController.setFrequencyCorrection( value );
mController.setFrequencyCorrection(value);
save();
}
catch ( SourceException e1 )
catch(SourceException e1)
{
JOptionPane.showMessageDialog( HackRFTunerEditor.this, "HackRF Tuner Controller"
JOptionPane.showMessageDialog(HackRFTunerEditor.this, "HackRF Tuner Controller"
+ " - couldn't apply frequency correction value: " + value +
e1.getLocalizedMessage() );
e1.getLocalizedMessage());
mLog.error( "HackRF Tuner Controller - couldn't apply frequency correction "
+ "value: " + value, e1 );
mLog.error("HackRF Tuner Controller - couldn't apply frequency correction "
+ "value: " + value, e1);
}
}
} );
});
add( new JLabel( "PPM:" ) );
add( mFrequencyCorrection );
add(new JLabel("PPM:"));
add(mFrequencyCorrection);
add( new JSeparator( JSeparator.HORIZONTAL ), "span,grow" );
add( new JLabel( "Gain" ) );
add( new JLabel( "" ), "span 2" ); //filler
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()
mAmplifier = new JToggleButton("Amplifier");
mAmplifier.setEnabled(false);
mAmplifier.addActionListener(new ActionListener()
{
@Override
public void actionPerformed( ActionEvent arg0 )
public void actionPerformed(ActionEvent arg0)
{
try
{
mController.setAmplifierEnabled( mAmplifier.isSelected() );
mController.setAmplifierEnabled(mAmplifier.isSelected());
save();
}
catch ( UsbException e )
catch(UsbException e)
{
mLog.error( "couldn't enable/disable amplifier", 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 );
JOptionPane.showMessageDialog(HackRFTunerEditor.this, "Couldn't change amplifier setting",
"Error changing amplifier setting", JOptionPane.ERROR_MESSAGE);
}
}
} );
add( mAmplifier );
});
add(mAmplifier);
mComboLNAGain = new JComboBox<HackRFLNAGain>( HackRFLNAGain.values() );
mComboLNAGain.setEnabled( false );
mComboLNAGain.addActionListener( new ActionListener()
mComboLNAGain = new JComboBox<HackRFLNAGain>(HackRFLNAGain.values());
mComboLNAGain.setEnabled(false);
mComboLNAGain.addActionListener(new ActionListener()
{
@Override
public void actionPerformed( ActionEvent arg0 )
public void actionPerformed(ActionEvent arg0)
{
try
{
HackRFLNAGain lnaGain = (HackRFLNAGain)mComboLNAGain.getSelectedItem();
if ( lnaGain == null )
if(lnaGain == null)
{
lnaGain = HackRFLNAGain.GAIN_0;
}
mController.setLNAGain( lnaGain );
mController.setLNAGain(lnaGain);
save();
}
catch ( UsbException e )
catch(UsbException e)
{
JOptionPane.showMessageDialog( HackRFTunerEditor.this, "HackRF Tuner Controller"
+ " - couldn't apply the LNA gain setting - " + e.getLocalizedMessage() );
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 );
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 );
});
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()
mComboVGAGain = new JComboBox<HackRFVGAGain>(HackRFVGAGain.values());
mComboVGAGain.addActionListener(new ActionListener()
{
@Override
public void actionPerformed( ActionEvent arg0 )
public void actionPerformed(ActionEvent arg0)
{
try
{
HackRFVGAGain vgaGain = (HackRFVGAGain)mComboVGAGain.getSelectedItem();
if( vgaGain == null )
if(vgaGain == null)
{
vgaGain = HackRFVGAGain.GAIN_4;
}
mController.setVGAGain( vgaGain );
mController.setVGAGain(vgaGain);
save();
}
catch ( UsbException e )
catch(UsbException e)
{
JOptionPane.showMessageDialog( HackRFTunerEditor.this, "HackRF Tuner Controller"
+ " - couldn't apply the VGA gain setting - " + e.getLocalizedMessage() );
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 );
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 );
});
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 )
private void setControlsEnabled(boolean enabled)
{
if( mConfigurationName.isEnabled() != enabled )
if(mConfigurationName.isEnabled() != enabled)
{
mConfigurationName.setEnabled( enabled );
mConfigurationName.setEnabled(enabled);
}
if( mTunerInfo.isEnabled() != enabled )
if(mTunerInfo.isEnabled() != enabled)
{
mTunerInfo.setEnabled( enabled );
mTunerInfo.setEnabled(enabled);
}
if( mFrequencyCorrection.isEnabled() != enabled )
if(mFrequencyCorrection.isEnabled() != enabled)
{
mFrequencyCorrection.setEnabled( enabled );
mFrequencyCorrection.setEnabled(enabled);
}
if( mComboSampleRate.isEnabled() != enabled )
if(mComboSampleRate.isEnabled() != enabled)
{
mComboSampleRate.setEnabled( enabled );
mComboSampleRate.setEnabled(enabled);
}
if( mAmplifier.isEnabled() != enabled )
if(mAmplifier.isEnabled() != enabled)
{
mAmplifier.setEnabled( enabled );
mAmplifier.setEnabled(enabled);
}
if( mComboLNAGain.isEnabled() != enabled )
if(mComboLNAGain.isEnabled() != enabled)
{
mComboLNAGain.setEnabled( enabled );
mComboLNAGain.setEnabled(enabled);
}
if( mComboVGAGain.isEnabled() != enabled )
if(mComboVGAGain.isEnabled() != enabled)
{
mComboVGAGain.setEnabled( enabled );
mComboVGAGain.setEnabled(enabled);
}
}
@@ -329,18 +346,18 @@ public class HackRFTunerEditor extends TunerConfigurationEditor
{
board = mController.getBoardID();
}
catch ( UsbException e )
catch(UsbException e)
{
mLog.error( "couldn't read HackRF board identifier", e );
mLog.error("couldn't read HackRF board identifier", e);
}
StringBuilder sb = new StringBuilder();
sb.append( "<html><h3>HackRF Tuner</h3>" );
sb.append("<html><h3>HackRF Tuner</h3>");
sb.append( "<b>Board: </b>" );
sb.append( board.getLabel() );
sb.append( "<br>" );
sb.append("<b>Board: </b>");
sb.append(board.getLabel());
sb.append("<br>");
HackRFTunerController.Serial serial = null;
@@ -348,25 +365,25 @@ public class HackRFTunerEditor extends TunerConfigurationEditor
{
serial = mController.getSerial();
}
catch( Exception e )
catch(Exception e)
{
mLog.error( "couldn't read HackRF serial number", e );
mLog.error("couldn't read HackRF serial number", e);
}
if( serial != null )
if(serial != null)
{
sb.append( "<b>Serial: </b>" );
sb.append( serial.getSerialNumber() );
sb.append( "<br>" );
sb.append("<b>Serial: </b>");
sb.append(serial.getSerialNumber());
sb.append("<br>");
sb.append( "<b>Part: </b>" );
sb.append( serial.getPartID() );
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>" );
sb.append("<b>Serial: Unknown</b><br>");
sb.append("<b>Part: Unknown</b><br>");
}
String firmware = null;
@@ -375,58 +392,61 @@ public class HackRFTunerEditor extends TunerConfigurationEditor
{
firmware = mController.getFirmwareVersion();
}
catch( Exception e )
catch(Exception e)
{
mLog.error( "couldn't read HackRF firmware version", e );
mLog.error("couldn't read HackRF firmware version", e);
}
if( firmware != null )
if(firmware != null)
{
sb.append( "<b>Firmware: </b>" );
sb.append( firmware );
sb.append( "<br>" );
sb.append("<b>Firmware: </b>");
sb.append(firmware);
sb.append("<br>");
}
else
{
sb.append( "<b>Firmware: Unknown</b><br>" );
sb.append("<b>Firmware: Unknown</b><br>");
}
return sb.toString();
}
@Override
public void setItem( TunerConfiguration tunerConfiguration )
public void setItem(TunerConfiguration tunerConfiguration)
{
super.setItem( 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() )
if(hasItem())
{
HackRFTunerConfiguration config = getConfiguration();
if( tunerConfiguration.isAssigned() )
if(tunerConfiguration.isAssigned())
{
setControlsEnabled( true );
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() );
mConfigurationName.setText(config.getName());
mComboSampleRate.setSelectedItem(config.getSampleRate());
mFrequencyCorrection.setValue(config.getFrequencyCorrection());
mAmplifier.setSelected(config.getAmplifierEnabled());
mComboLNAGain.setSelectedItem(config.getLNAGain());
mComboVGAGain.setSelectedItem(config.getVGAGain());
//Update enabled state to reflect when frequency and sample rate controls are locked
mComboSampleRate.setEnabled(!mController.isLocked());
}
else
{
setControlsEnabled( false );
mConfigurationName.setText( config.getName() );
setControlsEnabled(false);
mConfigurationName.setText(config.getName());
}
}
else
{
setControlsEnabled( false );
mConfigurationName.setText( "" );
setControlsEnabled(false);
mConfigurationName.setText("");
}
mLoading = false;
@@ -435,22 +455,22 @@ public class HackRFTunerEditor extends TunerConfigurationEditor
@Override
public void save()
{
if( hasItem() && !mLoading )
if(hasItem() && !mLoading)
{
HackRFTunerConfiguration config = getConfiguration();
config.setName( mConfigurationName.getText() );
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() );
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(), TunerConfigurationEvent.Event.CHANGE ) );
new TunerConfigurationEvent(getConfiguration(), TunerConfigurationEvent.Event.CHANGE));
}
}
}

View File

@@ -433,6 +433,9 @@ public class TunerChannelSourceManager extends ChannelSourceManager
case NOTIFICATION_CHANNEL_COUNT_CHANGE:
//Rebroadcast this event to any registered listeners (ie tuner and tuner controller)
broadcast(sourceEvent);
//Lock the frequency and sample rate controls on the tuner controller so users can't change them
//when the polyphase manager has channels allocated
mTunerController.setLocked(getTunerChannelCount() > 0);
break;
default:
mLog.info("Unrecognized source event: " + sourceEvent);

View File

@@ -1,6 +1,6 @@
/*******************************************************************************
* sdr-trunk
* Copyright (C) 2014-2017 Dennis Sheirer
* Copyright (C) 2014-2018 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
@@ -45,6 +45,7 @@ import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.usb.UsbException;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
@@ -53,442 +54,461 @@ import java.text.DecimalFormat;
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();
RTL2832TunerController.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;
}
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;
}
@Override
public void setSampleRateControl(boolean enabled)
{
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
mComboSampleRate.setEnabled(enabled);
}
});
}
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();
RTL2832TunerController.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());
//Update enabled state to reflect when frequency and sample rate controls are locked
mComboSampleRate.setEnabled(!mController.isLocked());
}
else
{
setControlsEnabled(false);
mConfigurationName.setText(config.getName());
}
}
else
{
setControlsEnabled(false);
mConfigurationName.setText("");
}
mLoading = false;
}
}