From 96d9d6f750ef264109317fe7b80bf1c0def6b835 Mon Sep 17 00:00:00 2001 From: Denny Date: Sun, 4 Feb 2018 06:30:25 -0500 Subject: [PATCH] [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. --- .../channelizer/PolyphaseChannelManager.java | 2 +- .../gui/control/JFrequencyControl.java | 35 +- .../github/dsheirer/source/SourceEvent.java | 18 + .../source/tuner/TunerController.java | 31 + .../dsheirer/source/tuner/TunerEditor.java | 503 +++--- .../tuner/airspy/AirspyTunerEditor.java | 1471 +++++++++-------- .../TunerConfigurationEditor.java | 49 +- .../tuner/fcd/proV1/FCD1TunerEditor.java | 962 +++++------ .../tuner/fcd/proplusV2/FCD2TunerEditor.java | 489 +++--- .../tuner/frequency/FrequencyController.java | 453 ++--- .../tuner/hackrf/HackRFTunerEditor.java | 346 ++-- .../manager/TunerChannelSourceManager.java | 3 + .../source/tuner/rtl/e4k/E4KTunerEditor.java | 898 +++++----- .../tuner/rtl/r820t/R820TTunerEditor.java | 1042 ++++++------ 14 files changed, 3271 insertions(+), 3031 deletions(-) diff --git a/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelManager.java b/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelManager.java index 028cfb26..5fd66a2e 100644 --- a/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelManager.java +++ b/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelManager.java @@ -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) { diff --git a/src/main/java/io/github/dsheirer/gui/control/JFrequencyControl.java b/src/main/java/io/github/dsheirer/gui/control/JFrequencyControl.java index 4dfef7a2..bd6c4162 100644 --- a/src/main/java/io/github/dsheirer/gui/control/JFrequencyControl.java +++ b/src/main/java/io/github/dsheirer/gui/control/JFrequencyControl.java @@ -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; } } diff --git a/src/main/java/io/github/dsheirer/source/SourceEvent.java b/src/main/java/io/github/dsheirer/source/SourceEvent.java index a5c23087..c8b6996e 100644 --- a/src/main/java/io/github/dsheirer/source/SourceEvent.java +++ b/src/main/java/io/github/dsheirer/source/SourceEvent.java @@ -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 * diff --git a/src/main/java/io/github/dsheirer/source/tuner/TunerController.java b/src/main/java/io/github/dsheirer/source/tuner/TunerController.java index 60394ee6..ebd1c516 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/TunerController.java +++ b/src/main/java/io/github/dsheirer/source/tuner/TunerController.java @@ -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(); diff --git a/src/main/java/io/github/dsheirer/source/tuner/TunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/TunerEditor.java index e9c6a3f3..abb5f418 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/TunerEditor.java +++ b/src/main/java/io/github/dsheirer/source/tuner/TunerEditor.java @@ -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 { - 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 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 mEditor = new EmptyEditor<>( "a tuner" ); - private JideSplitPane mEditorSplitPane = new JideSplitPane(); + private TunerConfigurationModel mTunerConfigurationModel; + private JTable mTunerConfigurationTable; + private TableRowSorter 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 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(); - } + //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(); + } - //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 - { - private TunerType mTunerType; - private String mUniqueID; + public class ConfigurationRowFilter extends RowFilter + { + 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 entry ) - { - TunerConfiguration config = entry.getModel() - .getTunerConfiguration( entry.getIdentifier() ); + @Override + public boolean include(javax.swing.RowFilter.Entry 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); + } + } } \ No newline at end of file diff --git a/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTunerEditor.java index 2d47f9c2..e8ef26c1 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTunerEditor.java +++ b/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTunerEditor.java @@ -1,19 +1,17 @@ /******************************************************************************* - * SDR Trunk - * Copyright (C) 2015-2016 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see + * 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 + * ******************************************************************************/ package io.github.dsheirer.source.tuner.airspy; @@ -45,6 +43,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; @@ -54,713 +53,737 @@ import java.util.List; public class AirspyTunerEditor extends TunerConfigurationEditor { - private static final long serialVersionUID = 1L; - - private final static Logger mLog = - LoggerFactory.getLogger( AirspyTunerEditor.class ); - - private JTextField mConfigurationName; - private JButton mTunerInfo; - - private JComboBox mSampleRateCombo; - private JSpinner mFrequencyCorrection; - - private JComboBox mGainModeCombo; - - private JSlider mMasterGain; - private JLabel mMasterGainValueLabel; - - private JSlider mIFGain; - private JLabel mIFGainValueLabel; - - private JSlider mLNAGain; - private JLabel mLNAGainValueLabel; - - private JSlider mMixerGain; - private JLabel mMixerGainValueLabel; - - private JCheckBox mLNAAGC; - private JCheckBox mMixerAGC; - - private AirspyTunerController mController; - private boolean mLoading; - - public AirspyTunerEditor( TunerConfigurationModel tunerConfigurationModel, - AirspyTuner tuner ) - { - super( tunerConfigurationModel ); - mController = tuner.getController(); - - init(); - } - - private AirspyTunerConfiguration getConfiguration() - { - if( hasItem() ) - { - return (AirspyTunerConfiguration)getItem(); - } - - return null; - } - - private void init() - { - setLayout( new MigLayout( "fill,wrap 4", "[right][grow,fill][right][grow,fill]", - "[][][][][][grow]" ) ); - - add( new JLabel( "Airspy Tuner Configuration" ), "span,align center" ); - - mConfigurationName = new JTextField(); - mConfigurationName.setEnabled( false ); - mConfigurationName.addFocusListener( new FocusListener() - { - @Override - public void focusLost( FocusEvent e ) - { - save(); - } - @Override - public void focusGained( FocusEvent e ) {} - } ); - - add( new JLabel( "Name:" ) ); - add( mConfigurationName, "span 2" ); - - mTunerInfo = new JButton( "Tuner Info" ); - mTunerInfo.setEnabled( false ); - mTunerInfo.addActionListener( new ActionListener() - { - @Override - public void actionPerformed( ActionEvent e ) - { - JOptionPane.showMessageDialog( AirspyTunerEditor.this, getTunerInfo(), - "Tuner Info", JOptionPane.INFORMATION_MESSAGE ); - } - } ); - add( mTunerInfo ); - - /** - * Sample Rate - */ - add( new JLabel( "Sample Rate:" ) ); - - List rates = mController.getSampleRates(); - - mSampleRateCombo = new JComboBox( - new DefaultComboBoxModel( rates.toArray( - new AirspySampleRate[ rates.size() ] ) ) ); - mSampleRateCombo.setEnabled( false ); - mSampleRateCombo.addActionListener( new ActionListener() - { - @Override - public void actionPerformed( ActionEvent e ) - { - AirspySampleRate rate = (AirspySampleRate)mSampleRateCombo.getSelectedItem(); - - try - { - mController.setSampleRate( rate ); - save(); - } - catch ( LibUsbException | UsbException | SourceException e1 ) - { - JOptionPane.showMessageDialog( AirspyTunerEditor.this, - "Couldn't set sample rate to " + rate.getLabel() ); - - mLog.error( "Error setting airspy sample rate", e1 ); - } - } - } ); - - add( mSampleRateCombo ); - - /** - * Frequency Correction - */ - SpinnerModel model = - new SpinnerNumberModel( 0.0, //initial value - -1000.0, //min - 1000.0, //max - 0.1 ); //step - - mFrequencyCorrection = new JSpinner( model ); - mFrequencyCorrection.setEnabled( false ); - - JSpinner.NumberEditor editor = - (JSpinner.NumberEditor)mFrequencyCorrection.getEditor(); - - DecimalFormat format = editor.getFormat(); - format.setMinimumFractionDigits( 1 ); - editor.getTextField().setHorizontalAlignment( SwingConstants.CENTER ); - - mFrequencyCorrection.addChangeListener( new ChangeListener() - { - @Override - public void stateChanged( ChangeEvent e ) - { - final double value = ((SpinnerNumberModel)mFrequencyCorrection - .getModel()).getNumber().doubleValue(); - - try - { - mController.setFrequencyCorrection( value ); - } - catch ( SourceException e1 ) - { - mLog.error( "Error setting frequency correction value", e1 ); - } - - save(); - } - } ); - - add( new JLabel( "PPM:" ) ); - add( mFrequencyCorrection ); - - add( new JSeparator(), "span,growx,push" ); - - /** - * Gain Mode - */ - add( new JLabel( "Gain Mode:" ) ); - mGainModeCombo = new JComboBox( GainMode.values() ); - mGainModeCombo.setEnabled( false ); - mGainModeCombo.addActionListener( new ActionListener() - { - @Override - public void actionPerformed( ActionEvent e ) - { - GainMode mode = (GainMode)mGainModeCombo.getSelectedItem(); - - updateGainComponents( mode ); - - if( hasItem() ) - { - AirspyTunerConfiguration airspy = getConfiguration(); - - Gain gain = airspy.getGain(); - - if( mode == GainMode.CUSTOM ) - { - mIFGain.setValue( airspy.getIFGain() ); - mMixerGain.setValue( airspy.getMixerGain() ); - mMixerAGC.setSelected( airspy.isMixerAGC() ); - mLNAGain.setValue( airspy.getLNAGain() ); - mLNAAGC.setSelected( airspy.isLNAAGC() ); - } - else - { - mMixerAGC.setSelected( false ); - mLNAAGC.setSelected( false ); - mMasterGain.setValue( gain.getValue() ); - mIFGain.setValue( gain.getIF() ); - mMixerGain.setValue( gain.getMixer() ); - mLNAGain.setValue( gain.getLNA() ); - } - } - - save(); - } - } ); - - add( mGainModeCombo, "wrap" ); - - /** - * Gain - */ - add( new JLabel( "Master:" ) ); - - mMasterGain = new JSlider( JSlider.HORIZONTAL, - AirspyTunerController.GAIN_MIN, - AirspyTunerController.GAIN_MAX, - AirspyTunerController.GAIN_MIN ); - mMasterGain.setMajorTickSpacing( 1 ); - mMasterGain.setPaintTicks( true ); - - mMasterGain.addChangeListener( new ChangeListener() - { - @Override - public void stateChanged( ChangeEvent event ) - { - GainMode mode = (GainMode)mGainModeCombo.getSelectedItem(); - int value = mMasterGain.getValue(); - Gain gain = Gain.getGain( mode, value ); - - try - { - mController.setGain( gain ); - save(); - mMasterGainValueLabel.setText( String.valueOf( gain.getValue() ) ); - } - catch ( Exception e ) - { - mLog.error( "Couldn't set airspy gain to:" + gain.name(), e ); - JOptionPane.showMessageDialog( mMasterGain, "Couldn't set gain value to " + - gain.getValue() ); - } - } - } ); - - add( mMasterGain, "span 2" ); - - mMasterGainValueLabel = new JLabel( "0" ); - add( mMasterGainValueLabel ); - - add( new JLabel( "IF:" ) ); - - mIFGain = new JSlider( JSlider.HORIZONTAL, - AirspyTunerController.IF_GAIN_MIN, - AirspyTunerController.IF_GAIN_MAX, - AirspyTunerController.IF_GAIN_MIN ); - - mIFGain.setMajorTickSpacing( 1 ); - mIFGain.setPaintTicks( true ); - - mIFGain.addChangeListener( new ChangeListener() - { - @Override - public void stateChanged( ChangeEvent event ) - { - int gain = mIFGain.getValue(); - - try - { - mController.setIFGain( gain ); - save(); - mIFGainValueLabel.setText( String.valueOf( gain ) ); - } - catch ( Exception e ) - { - mLog.error( "Couldn't set airspy IF gain to:" + gain, e ); - - JOptionPane.showMessageDialog( mIFGain, "Couldn't set IF gain value to " + gain ); - } - } - } ); - - add( mIFGain, "span 2" ); - - mIFGainValueLabel = new JLabel( "0" ); - add( mIFGainValueLabel ); - - /** - * Mixer Gain - */ - add( new JLabel( "Mixer:" ) ); - - mMixerGain = new JSlider( JSlider.HORIZONTAL, - AirspyTunerController.MIXER_GAIN_MIN, - AirspyTunerController.MIXER_GAIN_MAX, - AirspyTunerController.MIXER_GAIN_MIN ); - - mMixerGain.setMajorTickSpacing( 1 ); - mMixerGain.setPaintTicks( true ); - - mMixerGain.addChangeListener( new ChangeListener() - { - @Override - public void stateChanged( ChangeEvent event ) - { - int gain = mMixerGain.getValue(); - - try - { - mController.setMixerGain( gain ); - save(); - mMixerGainValueLabel.setText( String.valueOf( gain ) ); - } - catch ( Exception e ) - { - mLog.error( "Couldn't set airspy Mixer gain to:" + gain, e ); - JOptionPane.showMessageDialog( mIFGain, "Couldn't set Mixer gain value to " + gain ); - } - } - } ); - - add( mMixerGain, "span 2" ); - - mMixerGainValueLabel = new JLabel( "0" ); - add( mMixerGainValueLabel ); - - add( new JLabel( "LNA:" ) ); - - mLNAGain = new JSlider( JSlider.HORIZONTAL, - AirspyTunerController.LNA_GAIN_MIN, - AirspyTunerController.LNA_GAIN_MAX, - AirspyTunerController.LNA_GAIN_MIN ); - - mLNAGain.setMajorTickSpacing( 1 ); - mLNAGain.setPaintTicks( true ); - - mLNAGain.addChangeListener( new ChangeListener() - { - @Override - public void stateChanged( ChangeEvent event ) - { - int gain = mLNAGain.getValue(); - - try - { - mController.setLNAGain( gain ); - save(); - mLNAGainValueLabel.setText( String.valueOf( gain ) ); - } - catch ( Exception e ) - { - mLog.error( "Couldn't set airspy LNA gain to:" + gain, e ); - JOptionPane.showMessageDialog( mIFGain, "Couldn't set LNA gain value to " + gain ); - } - } - } ); - - add( mLNAGain, "span 2" ); - - mLNAGainValueLabel = new JLabel( "0" ); - add( mLNAGainValueLabel ); - - mMixerAGC = new JCheckBox( "Mixer AGC" ); - mMixerAGC.addActionListener( new ActionListener() - { - @Override - public void actionPerformed( ActionEvent e ) - { - try - { - mController.setMixerAGC( mMixerAGC.isSelected() ); - mMixerGain.setEnabled( !mMixerAGC.isSelected() ); - - save(); - } - catch ( Exception e1 ) - { - mLog.error( "Error setting Mixer AGC Enabled" ); - } - } - } ); - - add( mMixerAGC, "span 2,center" ); - - mLNAAGC = new JCheckBox( "LNA AGC" ); - mLNAAGC.addActionListener( new ActionListener() - { - @Override - public void actionPerformed( ActionEvent e ) - { - try - { - mController.setLNAAGC( mLNAAGC.isSelected() ); - mLNAGain.setEnabled( !mLNAAGC.isSelected() ); - - save(); - } - catch ( Exception e1 ) - { - mLog.error( "Error setting LNA AGC Enabled" ); - } - - } - } ); - - add( mLNAAGC, "span 2,center" ); - } - - /** - * Updates the enabled state of each of the gain controls according to the - * specified gain mode. The master gain control is enabled for linearity - * and sensitivity and the individual gain controls are disabled, and - * vice-versa for custom mode. - */ - private void updateGainComponents( GainMode mode ) - { - switch( mode ) - { - case LINEARITY: - if( !mMasterGain.isEnabled() ) - { - mMasterGain.setEnabled( true ); - mMasterGainValueLabel.setEnabled( true ); - } - if( mIFGain.isEnabled() ) - { - mIFGain.setEnabled( false ); - mIFGainValueLabel.setEnabled( false ); - } - if( mLNAGain.isEnabled() ) - { - mLNAAGC.setEnabled( false ); - mLNAGainValueLabel.setEnabled( false ); - mLNAGain.setEnabled( false ); - } - if( mMixerGain.isEnabled() ) - { - mMixerGainValueLabel.setEnabled( false ); - mMixerAGC.setEnabled( false ); - mMixerGain.setEnabled( false ); - } - break; - case SENSITIVITY: - if( !mMasterGain.isEnabled() ) - { - mMasterGain.setEnabled( true ); - mMasterGainValueLabel.setEnabled( true ); - } - if( mIFGain.isEnabled() ) - { - mIFGain.setEnabled( false ); - mIFGainValueLabel.setEnabled( false ); - } - if( mLNAGain.isEnabled() ) - { - mLNAAGC.setEnabled( false ); - mLNAGainValueLabel.setEnabled( false ); - mLNAGain.setEnabled( false ); - } - if( mMixerGain.isEnabled() ) - { - mMixerGainValueLabel.setEnabled( false ); - mMixerAGC.setEnabled( false ); - mMixerGain.setEnabled( false ); - } - break; - case CUSTOM: - if( mMasterGain.isEnabled() ) - { - mMasterGain.setEnabled( false ); - mMasterGainValueLabel.setEnabled( false ); - } - if( !mIFGain.isEnabled() ) - { - mIFGain.setEnabled( true ); - mIFGainValueLabel.setEnabled( true ); - } - if( !mLNAGain.isEnabled() ) - { - mLNAAGC.setEnabled( true ); - mLNAGainValueLabel.setEnabled( true ); - mLNAGain.setEnabled( true ); - } - if( !mMixerGain.isEnabled() ) - { - mMixerGainValueLabel.setEnabled( true ); - mMixerAGC.setEnabled( true ); - mMixerGain.setEnabled( true ); - } - default: - break; - } - } - - @Override - public void save() - { - if( hasItem() && !mLoading ) - { - AirspyTunerConfiguration config = getConfiguration(); - config.setName( mConfigurationName.getText() ); - config.setSampleRate( ((AirspySampleRate)mSampleRateCombo.getSelectedItem()).getRate() ); - - double value = ((SpinnerNumberModel)mFrequencyCorrection.getModel()).getNumber().doubleValue(); - config.setFrequencyCorrection( value ); - - Gain gain = Gain.getGain( (GainMode)mGainModeCombo.getSelectedItem(), mMasterGain.getValue() ); - - config.setGain( gain ); - config.setIFGain( mIFGain.getValue() ); - config.setMixerGain( mMixerGain.getValue() ); - config.setLNAGain( mLNAGain.getValue() ); - config.setMixerAGC( mMixerAGC.isSelected() ); - config.setLNAAGC( mLNAAGC.isSelected() ); - - getTunerConfigurationModel().broadcast( new TunerConfigurationEvent( config, TunerConfigurationEvent.Event.CHANGE ) ); - } - } - - private AirspySampleRate fromValue( int value ) - { - List rates = mController.getSampleRates(); - - for( AirspySampleRate rate: rates ) - { - if( rate.getRate() == value ) - { - return rate; - } - } - - if( rates.size() > 0 ) - { - return rates.get( 0 ); - } - - return null; - } - - /** - * Sets all controls to the argument enabled state - */ - private void setControlsEnabled( boolean enabled ) - { - if( mConfigurationName.isEnabled() != enabled ) - { - mConfigurationName.setEnabled( enabled ); - } - - if( mTunerInfo.isEnabled() != enabled ) - { - mTunerInfo.setEnabled( enabled ); - } - - if( mSampleRateCombo.isEnabled() != enabled ) - { - mSampleRateCombo.setEnabled( enabled ); - } - - if( mFrequencyCorrection.isEnabled() != enabled ) - { - mFrequencyCorrection.setEnabled( enabled ); - } - - if( mGainModeCombo.isEnabled() != enabled ) - { - mGainModeCombo.setEnabled( enabled ); - } - - if( mMasterGain.isEnabled() != enabled ) - { - mMasterGain.setEnabled( enabled ); - } - - if( mIFGain.isEnabled() != enabled ) - { - mIFGain.setEnabled( enabled ); - } - - if( mMixerGain.isEnabled() != enabled ) - { - mMixerGain.setEnabled( enabled ); - } - - if( mMixerAGC.isEnabled() != enabled ) - { - mMixerAGC.setEnabled( enabled ); - } - - if( mLNAGain.isEnabled() != enabled ) - { - mLNAGain.setEnabled( enabled ); - } - - if( mLNAAGC.isEnabled() != enabled ) - { - mLNAAGC.setEnabled( enabled ); - } - } - - /** - * Applies the tuner configuration to the editor. If the configuration is assigned to the - * currently selected tuner, then the settings are applied. - */ - @Override - public void setItem( TunerConfiguration config ) - { - super.setItem( config ); - - mLoading = true; - - if( hasItem() && getItem().isAssigned() ) - { - AirspyTunerConfiguration airspy = getConfiguration(); - - setControlsEnabled( true ); - - mConfigurationName.setText( airspy.getName() ); - - AirspySampleRate rate = fromValue( airspy.getSampleRate() ); - - if( rate != null ) - { - mSampleRateCombo.setSelectedItem( rate ); - } - - mFrequencyCorrection.setValue( airspy.getFrequencyCorrection() ); - - GainMode mode = Gain.getGainMode( airspy.getGain() ); - - //This will set the master, IF, Mixer, LNA and AGC controls - mGainModeCombo.setSelectedItem( mode ); - - if( mode == GainMode.CUSTOM ) - { - mMasterGain.setValue( airspy.getGain().getValue() ); - mIFGain.setValue( airspy.getIFGain() ); - - if( airspy.isMixerAGC() ) - { - mMixerAGC.setSelected( airspy.isMixerAGC() ); - mMixerGain.setEnabled( false ); - } - else - { - mMixerGain.setValue( airspy.getMixerGain() ); - } - - if( airspy.isLNAAGC() ) - { - mLNAAGC.setSelected( airspy.isLNAAGC() ); - mLNAGain.setEnabled( false ); - } - else - { - mLNAGain.setValue( airspy.getLNAGain() ); - } - } - else - { - mMixerAGC.setSelected( false ); - mLNAAGC.setSelected( false ); - - Gain gain = airspy.getGain(); - - mMasterGain.setValue( gain.getValue() ); - mIFGain.setValue( gain.getIF() ); - mMixerGain.setValue( gain.getMixer() ); - mLNAGain.setValue( gain.getLNA() ); - } - } - else - { - setControlsEnabled( false ); - mConfigurationName.setText( hasItem() ? getItem().getName() : "" ); - } - - mLoading = false; - } - - private String getTunerInfo() - { - StringBuilder sb = new StringBuilder(); - - AirspyDeviceInformation info = mController.getDeviceInfo(); - - sb.append( "

Airspy Tuner

" ); - sb.append( "Serial: " ); - sb.append( info.getSerialNumber() ); - sb.append( "
" ); - - sb.append( "Firmware: " ); - String[] firmware = info.getVersion().split( " " ); - sb.append( firmware.length > 1 ? firmware[ 0 ] : info.getVersion() ); - sb.append( "
" ); - - sb.append( "Part: " ); - sb.append( info.getPartNumber() ); - sb.append( "
" ); - - sb.append( "Board ID: " ); - sb.append( info.getBoardID().getLabel() ); - sb.append( "
" ); - - return sb.toString(); - } + private static final long serialVersionUID = 1L; + + private final static Logger mLog = + LoggerFactory.getLogger(AirspyTunerEditor.class); + + private JTextField mConfigurationName; + private JButton mTunerInfo; + + private JComboBox mSampleRateCombo; + private JSpinner mFrequencyCorrection; + + private JComboBox mGainModeCombo; + + private JSlider mMasterGain; + private JLabel mMasterGainValueLabel; + + private JSlider mIFGain; + private JLabel mIFGainValueLabel; + + private JSlider mLNAGain; + private JLabel mLNAGainValueLabel; + + private JSlider mMixerGain; + private JLabel mMixerGainValueLabel; + + private JCheckBox mLNAAGC; + private JCheckBox mMixerAGC; + + private AirspyTunerController mController; + private boolean mLoading; + + public AirspyTunerEditor(TunerConfigurationModel tunerConfigurationModel, + AirspyTuner tuner) + { + super(tunerConfigurationModel); + mController = tuner.getController(); + + init(); + } + + private AirspyTunerConfiguration getConfiguration() + { + if(hasItem()) + { + return (AirspyTunerConfiguration)getItem(); + } + + return null; + } + + /** + * Updates the enabled state of the sample rate combo control. + * + * @param enabled state for the sample rate control + */ + @Override + public void setSampleRateControl(boolean enabled) + { + EventQueue.invokeLater(new Runnable() + { + @Override + public void run() + { + mSampleRateCombo.setEnabled(enabled); + } + }); + } + + private void init() + { + setLayout(new MigLayout("fill,wrap 4", "[right][grow,fill][right][grow,fill]", + "[][][][][][grow]")); + + add(new JLabel("Airspy Tuner Configuration"), "span,align center"); + + mConfigurationName = new JTextField(); + mConfigurationName.setEnabled(false); + mConfigurationName.addFocusListener(new FocusListener() + { + @Override + public void focusLost(FocusEvent e) + { + save(); + } + + @Override + public void focusGained(FocusEvent e) + { + } + }); + + add(new JLabel("Name:")); + add(mConfigurationName, "span 2"); + + mTunerInfo = new JButton("Tuner Info"); + mTunerInfo.setEnabled(false); + mTunerInfo.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + JOptionPane.showMessageDialog(AirspyTunerEditor.this, getTunerInfo(), + "Tuner Info", JOptionPane.INFORMATION_MESSAGE); + } + }); + add(mTunerInfo); + + /** + * Sample Rate + */ + add(new JLabel("Sample Rate:")); + + List rates = mController.getSampleRates(); + + mSampleRateCombo = new JComboBox( + new DefaultComboBoxModel(rates.toArray( + new AirspySampleRate[rates.size()]))); + mSampleRateCombo.setEnabled(false); + mSampleRateCombo.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + AirspySampleRate rate = (AirspySampleRate)mSampleRateCombo.getSelectedItem(); + + try + { + mController.setSampleRate(rate); + save(); + } + catch(LibUsbException | UsbException | SourceException e1) + { + JOptionPane.showMessageDialog(AirspyTunerEditor.this, + "Couldn't set sample rate to " + rate.getLabel()); + + mLog.error("Error setting airspy sample rate", e1); + } + } + }); + + add(mSampleRateCombo); + + /** + * Frequency Correction + */ + SpinnerModel model = + new SpinnerNumberModel(0.0, //initial value + -1000.0, //min + 1000.0, //max + 0.1); //step + + mFrequencyCorrection = new JSpinner(model); + mFrequencyCorrection.setEnabled(false); + + JSpinner.NumberEditor editor = + (JSpinner.NumberEditor)mFrequencyCorrection.getEditor(); + + DecimalFormat format = editor.getFormat(); + format.setMinimumFractionDigits(1); + editor.getTextField().setHorizontalAlignment(SwingConstants.CENTER); + + mFrequencyCorrection.addChangeListener(new ChangeListener() + { + @Override + public void stateChanged(ChangeEvent e) + { + final double value = ((SpinnerNumberModel)mFrequencyCorrection + .getModel()).getNumber().doubleValue(); + + try + { + mController.setFrequencyCorrection(value); + } + catch(SourceException e1) + { + mLog.error("Error setting frequency correction value", e1); + } + + save(); + } + }); + + add(new JLabel("PPM:")); + add(mFrequencyCorrection); + + add(new JSeparator(), "span,growx,push"); + + /** + * Gain Mode + */ + add(new JLabel("Gain Mode:")); + mGainModeCombo = new JComboBox(GainMode.values()); + mGainModeCombo.setEnabled(false); + mGainModeCombo.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + GainMode mode = (GainMode)mGainModeCombo.getSelectedItem(); + + updateGainComponents(mode); + + if(hasItem()) + { + AirspyTunerConfiguration airspy = getConfiguration(); + + Gain gain = airspy.getGain(); + + if(mode == GainMode.CUSTOM) + { + mIFGain.setValue(airspy.getIFGain()); + mMixerGain.setValue(airspy.getMixerGain()); + mMixerAGC.setSelected(airspy.isMixerAGC()); + mLNAGain.setValue(airspy.getLNAGain()); + mLNAAGC.setSelected(airspy.isLNAAGC()); + } + else + { + mMixerAGC.setSelected(false); + mLNAAGC.setSelected(false); + mMasterGain.setValue(gain.getValue()); + mIFGain.setValue(gain.getIF()); + mMixerGain.setValue(gain.getMixer()); + mLNAGain.setValue(gain.getLNA()); + } + } + + save(); + } + }); + + add(mGainModeCombo, "wrap"); + + /** + * Gain + */ + add(new JLabel("Master:")); + + mMasterGain = new JSlider(JSlider.HORIZONTAL, + AirspyTunerController.GAIN_MIN, + AirspyTunerController.GAIN_MAX, + AirspyTunerController.GAIN_MIN); + mMasterGain.setMajorTickSpacing(1); + mMasterGain.setPaintTicks(true); + + mMasterGain.addChangeListener(new ChangeListener() + { + @Override + public void stateChanged(ChangeEvent event) + { + GainMode mode = (GainMode)mGainModeCombo.getSelectedItem(); + int value = mMasterGain.getValue(); + Gain gain = Gain.getGain(mode, value); + + try + { + mController.setGain(gain); + save(); + mMasterGainValueLabel.setText(String.valueOf(gain.getValue())); + } + catch(Exception e) + { + mLog.error("Couldn't set airspy gain to:" + gain.name(), e); + JOptionPane.showMessageDialog(mMasterGain, "Couldn't set gain value to " + + gain.getValue()); + } + } + }); + + add(mMasterGain, "span 2"); + + mMasterGainValueLabel = new JLabel("0"); + add(mMasterGainValueLabel); + + add(new JLabel("IF:")); + + mIFGain = new JSlider(JSlider.HORIZONTAL, + AirspyTunerController.IF_GAIN_MIN, + AirspyTunerController.IF_GAIN_MAX, + AirspyTunerController.IF_GAIN_MIN); + + mIFGain.setMajorTickSpacing(1); + mIFGain.setPaintTicks(true); + + mIFGain.addChangeListener(new ChangeListener() + { + @Override + public void stateChanged(ChangeEvent event) + { + int gain = mIFGain.getValue(); + + try + { + mController.setIFGain(gain); + save(); + mIFGainValueLabel.setText(String.valueOf(gain)); + } + catch(Exception e) + { + mLog.error("Couldn't set airspy IF gain to:" + gain, e); + + JOptionPane.showMessageDialog(mIFGain, "Couldn't set IF gain value to " + gain); + } + } + }); + + add(mIFGain, "span 2"); + + mIFGainValueLabel = new JLabel("0"); + add(mIFGainValueLabel); + + /** + * Mixer Gain + */ + add(new JLabel("Mixer:")); + + mMixerGain = new JSlider(JSlider.HORIZONTAL, + AirspyTunerController.MIXER_GAIN_MIN, + AirspyTunerController.MIXER_GAIN_MAX, + AirspyTunerController.MIXER_GAIN_MIN); + + mMixerGain.setMajorTickSpacing(1); + mMixerGain.setPaintTicks(true); + + mMixerGain.addChangeListener(new ChangeListener() + { + @Override + public void stateChanged(ChangeEvent event) + { + int gain = mMixerGain.getValue(); + + try + { + mController.setMixerGain(gain); + save(); + mMixerGainValueLabel.setText(String.valueOf(gain)); + } + catch(Exception e) + { + mLog.error("Couldn't set airspy Mixer gain to:" + gain, e); + JOptionPane.showMessageDialog(mIFGain, "Couldn't set Mixer gain value to " + gain); + } + } + }); + + add(mMixerGain, "span 2"); + + mMixerGainValueLabel = new JLabel("0"); + add(mMixerGainValueLabel); + + add(new JLabel("LNA:")); + + mLNAGain = new JSlider(JSlider.HORIZONTAL, + AirspyTunerController.LNA_GAIN_MIN, + AirspyTunerController.LNA_GAIN_MAX, + AirspyTunerController.LNA_GAIN_MIN); + + mLNAGain.setMajorTickSpacing(1); + mLNAGain.setPaintTicks(true); + + mLNAGain.addChangeListener(new ChangeListener() + { + @Override + public void stateChanged(ChangeEvent event) + { + int gain = mLNAGain.getValue(); + + try + { + mController.setLNAGain(gain); + save(); + mLNAGainValueLabel.setText(String.valueOf(gain)); + } + catch(Exception e) + { + mLog.error("Couldn't set airspy LNA gain to:" + gain, e); + JOptionPane.showMessageDialog(mIFGain, "Couldn't set LNA gain value to " + gain); + } + } + }); + + add(mLNAGain, "span 2"); + + mLNAGainValueLabel = new JLabel("0"); + add(mLNAGainValueLabel); + + mMixerAGC = new JCheckBox("Mixer AGC"); + mMixerAGC.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + try + { + mController.setMixerAGC(mMixerAGC.isSelected()); + mMixerGain.setEnabled(!mMixerAGC.isSelected()); + + save(); + } + catch(Exception e1) + { + mLog.error("Error setting Mixer AGC Enabled"); + } + } + }); + + add(mMixerAGC, "span 2,center"); + + mLNAAGC = new JCheckBox("LNA AGC"); + mLNAAGC.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + try + { + mController.setLNAAGC(mLNAAGC.isSelected()); + mLNAGain.setEnabled(!mLNAAGC.isSelected()); + + save(); + } + catch(Exception e1) + { + mLog.error("Error setting LNA AGC Enabled"); + } + + } + }); + + add(mLNAAGC, "span 2,center"); + } + + /** + * Updates the enabled state of each of the gain controls according to the + * specified gain mode. The master gain control is enabled for linearity + * and sensitivity and the individual gain controls are disabled, and + * vice-versa for custom mode. + */ + private void updateGainComponents(GainMode mode) + { + switch(mode) + { + case LINEARITY: + if(!mMasterGain.isEnabled()) + { + mMasterGain.setEnabled(true); + mMasterGainValueLabel.setEnabled(true); + } + if(mIFGain.isEnabled()) + { + mIFGain.setEnabled(false); + mIFGainValueLabel.setEnabled(false); + } + if(mLNAGain.isEnabled()) + { + mLNAAGC.setEnabled(false); + mLNAGainValueLabel.setEnabled(false); + mLNAGain.setEnabled(false); + } + if(mMixerGain.isEnabled()) + { + mMixerGainValueLabel.setEnabled(false); + mMixerAGC.setEnabled(false); + mMixerGain.setEnabled(false); + } + break; + case SENSITIVITY: + if(!mMasterGain.isEnabled()) + { + mMasterGain.setEnabled(true); + mMasterGainValueLabel.setEnabled(true); + } + if(mIFGain.isEnabled()) + { + mIFGain.setEnabled(false); + mIFGainValueLabel.setEnabled(false); + } + if(mLNAGain.isEnabled()) + { + mLNAAGC.setEnabled(false); + mLNAGainValueLabel.setEnabled(false); + mLNAGain.setEnabled(false); + } + if(mMixerGain.isEnabled()) + { + mMixerGainValueLabel.setEnabled(false); + mMixerAGC.setEnabled(false); + mMixerGain.setEnabled(false); + } + break; + case CUSTOM: + if(mMasterGain.isEnabled()) + { + mMasterGain.setEnabled(false); + mMasterGainValueLabel.setEnabled(false); + } + if(!mIFGain.isEnabled()) + { + mIFGain.setEnabled(true); + mIFGainValueLabel.setEnabled(true); + } + if(!mLNAGain.isEnabled()) + { + mLNAAGC.setEnabled(true); + mLNAGainValueLabel.setEnabled(true); + mLNAGain.setEnabled(true); + } + if(!mMixerGain.isEnabled()) + { + mMixerGainValueLabel.setEnabled(true); + mMixerAGC.setEnabled(true); + mMixerGain.setEnabled(true); + } + default: + break; + } + } + + @Override + public void save() + { + if(hasItem() && !mLoading) + { + AirspyTunerConfiguration config = getConfiguration(); + config.setName(mConfigurationName.getText()); + config.setSampleRate(((AirspySampleRate)mSampleRateCombo.getSelectedItem()).getRate()); + + double value = ((SpinnerNumberModel)mFrequencyCorrection.getModel()).getNumber().doubleValue(); + config.setFrequencyCorrection(value); + + Gain gain = Gain.getGain((GainMode)mGainModeCombo.getSelectedItem(), mMasterGain.getValue()); + + config.setGain(gain); + config.setIFGain(mIFGain.getValue()); + config.setMixerGain(mMixerGain.getValue()); + config.setLNAGain(mLNAGain.getValue()); + config.setMixerAGC(mMixerAGC.isSelected()); + config.setLNAAGC(mLNAAGC.isSelected()); + + getTunerConfigurationModel().broadcast(new TunerConfigurationEvent(config, TunerConfigurationEvent.Event.CHANGE)); + } + } + + private AirspySampleRate fromValue(int value) + { + List rates = mController.getSampleRates(); + + for(AirspySampleRate rate : rates) + { + if(rate.getRate() == value) + { + return rate; + } + } + + if(rates.size() > 0) + { + return rates.get(0); + } + + return null; + } + + /** + * Sets all controls to the argument enabled state + */ + private void setControlsEnabled(boolean enabled) + { + if(mConfigurationName.isEnabled() != enabled) + { + mConfigurationName.setEnabled(enabled); + } + + if(mTunerInfo.isEnabled() != enabled) + { + mTunerInfo.setEnabled(enabled); + } + + if(mSampleRateCombo.isEnabled() != enabled) + { + mSampleRateCombo.setEnabled(enabled); + } + + if(mFrequencyCorrection.isEnabled() != enabled) + { + mFrequencyCorrection.setEnabled(enabled); + } + + if(mGainModeCombo.isEnabled() != enabled) + { + mGainModeCombo.setEnabled(enabled); + } + + if(mMasterGain.isEnabled() != enabled) + { + mMasterGain.setEnabled(enabled); + } + + if(mIFGain.isEnabled() != enabled) + { + mIFGain.setEnabled(enabled); + } + + if(mMixerGain.isEnabled() != enabled) + { + mMixerGain.setEnabled(enabled); + } + + if(mMixerAGC.isEnabled() != enabled) + { + mMixerAGC.setEnabled(enabled); + } + + if(mLNAGain.isEnabled() != enabled) + { + mLNAGain.setEnabled(enabled); + } + + if(mLNAAGC.isEnabled() != enabled) + { + mLNAAGC.setEnabled(enabled); + } + } + + /** + * Applies the tuner configuration to the editor. If the configuration is assigned to the + * currently selected tuner, then the settings are applied. + */ + @Override + public void setItem(TunerConfiguration config) + { + super.setItem(config); + + mLoading = true; + + if(hasItem() && getItem().isAssigned()) + { + AirspyTunerConfiguration airspy = getConfiguration(); + + setControlsEnabled(true); + + mConfigurationName.setText(airspy.getName()); + + AirspySampleRate rate = fromValue(airspy.getSampleRate()); + + if(rate != null) + { + mSampleRateCombo.setSelectedItem(rate); + } + + //Update enabled state to reflect when frequency and sample rate controls are locked + mSampleRateCombo.setEnabled(!mController.isLocked()); + + mFrequencyCorrection.setValue(airspy.getFrequencyCorrection()); + + GainMode mode = Gain.getGainMode(airspy.getGain()); + + //This will set the master, IF, Mixer, LNA and AGC controls + mGainModeCombo.setSelectedItem(mode); + + if(mode == GainMode.CUSTOM) + { + mMasterGain.setValue(airspy.getGain().getValue()); + mIFGain.setValue(airspy.getIFGain()); + + if(airspy.isMixerAGC()) + { + mMixerAGC.setSelected(airspy.isMixerAGC()); + mMixerGain.setEnabled(false); + } + else + { + mMixerGain.setValue(airspy.getMixerGain()); + } + + if(airspy.isLNAAGC()) + { + mLNAAGC.setSelected(airspy.isLNAAGC()); + mLNAGain.setEnabled(false); + } + else + { + mLNAGain.setValue(airspy.getLNAGain()); + } + } + else + { + mMixerAGC.setSelected(false); + mLNAAGC.setSelected(false); + + Gain gain = airspy.getGain(); + + mMasterGain.setValue(gain.getValue()); + mIFGain.setValue(gain.getIF()); + mMixerGain.setValue(gain.getMixer()); + mLNAGain.setValue(gain.getLNA()); + } + } + else + { + setControlsEnabled(false); + mConfigurationName.setText(hasItem() ? getItem().getName() : ""); + } + + mLoading = false; + } + + private String getTunerInfo() + { + StringBuilder sb = new StringBuilder(); + + AirspyDeviceInformation info = mController.getDeviceInfo(); + + sb.append("

Airspy Tuner

"); + sb.append("Serial: "); + sb.append(info.getSerialNumber()); + sb.append("
"); + + sb.append("Firmware: "); + String[] firmware = info.getVersion().split(" "); + sb.append(firmware.length > 1 ? firmware[0] : info.getVersion()); + sb.append("
"); + + sb.append("Part: "); + sb.append(info.getPartNumber()); + sb.append("
"); + + sb.append("Board ID: "); + sb.append(info.getBoardID().getLabel()); + sb.append("
"); + + return sb.toString(); + } } \ No newline at end of file diff --git a/src/main/java/io/github/dsheirer/source/tuner/configuration/TunerConfigurationEditor.java b/src/main/java/io/github/dsheirer/source/tuner/configuration/TunerConfigurationEditor.java index 6c8af503..c328c3af 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/configuration/TunerConfigurationEditor.java +++ b/src/main/java/io/github/dsheirer/source/tuner/configuration/TunerConfigurationEditor.java @@ -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 + * + ******************************************************************************/ package io.github.dsheirer.source.tuner.configuration; import io.github.dsheirer.gui.editor.Editor; public abstract class TunerConfigurationEditor extends Editor { - 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); } diff --git a/src/main/java/io/github/dsheirer/source/tuner/fcd/proV1/FCD1TunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/fcd/proV1/FCD1TunerEditor.java index eb8ac835..9839526b 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/fcd/proV1/FCD1TunerEditor.java +++ b/src/main/java/io/github/dsheirer/source/tuner/fcd/proV1/FCD1TunerEditor.java @@ -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 ******************************************************************************/ @@ -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 mComboLNAGain; - private JComboBox mComboLNAEnhance; - private JComboBox 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.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.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.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( "

Funcube Dongle Pro Tuner

" ); - - sb.append( "USB ID: " ); - sb.append( mController.getUSBID() ); - sb.append( "
" ); - - sb.append( "USB Address: " ); - sb.append( mController.getUSBAddress() ); - sb.append( "
" ); - - sb.append( "USB Speed: " ); - sb.append( mController.getUSBSpeed() ); - sb.append( "
" ); - - sb.append( "Cellular Band: " ); - sb.append( mController.getConfiguration().getBandBlocking() ); - sb.append( "
" ); - - sb.append( "Firmware: " ); - sb.append( mController.getConfiguration().getFirmware() ); - sb.append( "
" ); - - 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 mComboLNAGain; + private JComboBox mComboLNAEnhance; + private JComboBox 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.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.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.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("

Funcube Dongle Pro Tuner

"); + + sb.append("USB ID: "); + sb.append(mController.getUSBID()); + sb.append("
"); + + sb.append("USB Address: "); + sb.append(mController.getUSBAddress()); + sb.append("
"); + + sb.append("USB Speed: "); + sb.append(mController.getUSBSpeed()); + sb.append("
"); + + sb.append("Cellular Band: "); + sb.append(mController.getConfiguration().getBandBlocking()); + sb.append("
"); + + sb.append("Firmware: "); + sb.append(mController.getConfiguration().getFirmware()); + sb.append("
"); + + 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); + } + } + }); + } + } } \ No newline at end of file diff --git a/src/main/java/io/github/dsheirer/source/tuner/fcd/proplusV2/FCD2TunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/fcd/proplusV2/FCD2TunerEditor.java index ce8d6fb7..a9d854e8 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/fcd/proplusV2/FCD2TunerEditor.java +++ b/src/main/java/io/github/dsheirer/source/tuner/fcd/proplusV2/FCD2TunerEditor.java @@ -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 + * 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 + * ******************************************************************************/ 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( "

Funcube Dongle Pro Plus Tuner

" ); + if(mMixerGain.isEnabled() != enabled) + { + mMixerGain.setEnabled(enabled); + } + } - sb.append( "USB ID: " ); - sb.append( mController.getUSBID() ); - sb.append( "
" ); + private String getTunerInfo() + { + StringBuilder sb = new StringBuilder(); - sb.append( "USB Address: " ); - sb.append( mController.getUSBAddress() ); - sb.append( "
" ); + sb.append("

Funcube Dongle Pro Plus Tuner

"); - sb.append( "USB Speed: " ); - sb.append( mController.getUSBSpeed() ); - sb.append( "
" ); + sb.append("USB ID: "); + sb.append(mController.getUSBID()); + sb.append("
"); - sb.append( "Cellular Band: " ); - sb.append( mController.getConfiguration().getBandBlocking() ); - sb.append( "
" ); + sb.append("USB Address: "); + sb.append(mController.getUSBAddress()); + sb.append("
"); - sb.append( "Firmware: " ); - sb.append( mController.getConfiguration().getFirmware() ); - sb.append( "
" ); + sb.append("USB Speed: "); + sb.append(mController.getUSBSpeed()); + sb.append("
"); - return sb.toString(); - } + sb.append("Cellular Band: "); + sb.append(mController.getConfiguration().getBandBlocking()); + sb.append("
"); - @Override - public void save() - { - if( hasItem() && !mLoading ) - { - FCD2TunerConfiguration config = getConfiguration(); + sb.append("Firmware: "); + sb.append(mController.getConfiguration().getFirmware()); + sb.append("
"); - 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; + } } \ No newline at end of file diff --git a/src/main/java/io/github/dsheirer/source/tuner/frequency/FrequencyController.java b/src/main/java/io/github/dsheirer/source/tuner/frequency/FrequencyController.java index 74d36f8f..aa8b98aa 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/frequency/FrequencyController.java +++ b/src/main/java/io/github/dsheirer/source/tuner/frequency/FrequencyController.java @@ -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 - * ********************************************************************************************************************* + * ******************************************************************************/ 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 mProcessors = new ArrayList<>(); + private List 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); + } } \ No newline at end of file diff --git a/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerEditor.java index 9aea1db3..a2f78262 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerEditor.java +++ b/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerEditor.java @@ -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.values() ); - mComboLNAGain.setEnabled( false ); - mComboLNAGain.addActionListener( new ActionListener() + mComboLNAGain = new JComboBox(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( "LNA Gain. Adjust to set the IF gain" ); - add( new JLabel( "LNA:" ) ); - add( mComboLNAGain ); + }); + mComboLNAGain.setToolTipText("LNA Gain. Adjust to set the IF gain"); + add(new JLabel("LNA:")); + add(mComboLNAGain); - mComboVGAGain = new JComboBox( HackRFVGAGain.values() ); - mComboVGAGain.addActionListener( new ActionListener() + mComboVGAGain = new JComboBox(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( "VGA Gain. Adjust to set the baseband gain" ); - add( new JLabel( "VGA:" ) ); - add( mComboVGAGain ); + }); + mComboVGAGain.setToolTipText("VGA Gain. Adjust to set the baseband gain"); + 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( "

HackRF Tuner

" ); + sb.append("

HackRF Tuner

"); - sb.append( "Board: " ); - sb.append( board.getLabel() ); - sb.append( "
" ); + sb.append("Board: "); + sb.append(board.getLabel()); + sb.append("
"); 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( "Serial: " ); - sb.append( serial.getSerialNumber() ); - sb.append( "
" ); + sb.append("Serial: "); + sb.append(serial.getSerialNumber()); + sb.append("
"); - sb.append( "Part: " ); - sb.append( serial.getPartID() ); - sb.append( "
" ); + sb.append("Part: "); + sb.append(serial.getPartID()); + sb.append("
"); } else { - sb.append( "Serial: Unknown
" ); - sb.append( "Part: Unknown
" ); + sb.append("Serial: Unknown
"); + sb.append("Part: Unknown
"); } 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( "Firmware: " ); - sb.append( firmware ); - sb.append( "
" ); + sb.append("Firmware: "); + sb.append(firmware); + sb.append("
"); } else { - sb.append( "Firmware: Unknown
" ); + sb.append("Firmware: Unknown
"); } 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)); } } } \ No newline at end of file diff --git a/src/main/java/io/github/dsheirer/source/tuner/manager/TunerChannelSourceManager.java b/src/main/java/io/github/dsheirer/source/tuner/manager/TunerChannelSourceManager.java index 7e46be1b..64733a83 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/manager/TunerChannelSourceManager.java +++ b/src/main/java/io/github/dsheirer/source/tuner/manager/TunerChannelSourceManager.java @@ -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); diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/e4k/E4KTunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/e4k/E4KTunerEditor.java index 394d785d..5bfa9382 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/rtl/e4k/E4KTunerEditor.java +++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/e4k/E4KTunerEditor.java @@ -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 mComboSampleRate; - private JSpinner mFrequencyCorrection; - private JComboBox mComboMasterGain; - private JComboBox mComboMixerGain; - private JComboBox mComboLNAGain; - private JComboBox 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.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( "Select AUTOMATIC for auto " - + "gain, MANUAL to enable
independent control of " - + "Mixer, LNA and Enhance gain
" - + "settings, or one of the individual gain settings for
" - + "semi-manual gain control" ); - add( new JLabel( "Master:" ) ); - add( mComboMasterGain ); - - mComboMixerGain = new JComboBox( 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( "Mixer Gain. Set master gain " - + "to MASTER to enable adjustment" ); - mComboMixerGain.setEnabled( false ); - add( new JLabel( "Mixer:" ) ); - add( mComboMixerGain ); - - mComboLNAGain = new JComboBox( 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( "LNA Gain. Set master gain " - + "to MANUAL to enable adjustment" ); - mComboLNAGain.setEnabled( false ); - add( new JLabel( "LNA:" ) ); - add( mComboLNAGain ); - - mComboEnhanceGain = new JComboBox( 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( "Enhance Gain. Set master gain " - + "to MANUAL to enable adjustment" ); - 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( "

RTL-2832 with E4000 Tuner

" ); - - if( descriptor == null ) - { - sb.append( "No EEPROM Descriptor Available" ); - } - else - { - sb.append( "USB ID: " ); - sb.append( descriptor.getVendorID() ); - sb.append( ":" ); - sb.append( descriptor.getProductID() ); - sb.append( "
" ); - - sb.append( "Vendor: " ); - sb.append( descriptor.getVendorLabel() ); - sb.append( "
" ); - - sb.append( "Product: " ); - sb.append( descriptor.getProductLabel() ); - sb.append( "
" ); - - sb.append( "Serial: " ); - sb.append( descriptor.getSerial() ); - sb.append( "
" ); - - sb.append( "IR Enabled: " ); - sb.append( descriptor.irEnabled() ); - sb.append( "
" ); - - sb.append( "Remote Wake: " ); - sb.append( descriptor.remoteWakeupEnabled() ); - sb.append( "
" ); - } - - 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 mComboSampleRate; + private JSpinner mFrequencyCorrection; + private JComboBox mComboMasterGain; + private JComboBox mComboMixerGain; + private JComboBox mComboLNAGain; + private JComboBox 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.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("Select AUTOMATIC for auto " + + "gain, MANUAL to enable
independent control of " + + "Mixer, LNA and Enhance gain
" + + "settings, or one of the individual gain settings for
" + + "semi-manual gain control"); + add(new JLabel("Master:")); + add(mComboMasterGain); + + mComboMixerGain = new JComboBox(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("Mixer Gain. Set master gain " + + "to MASTER to enable adjustment"); + mComboMixerGain.setEnabled(false); + add(new JLabel("Mixer:")); + add(mComboMixerGain); + + mComboLNAGain = new JComboBox(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("LNA Gain. Set master gain " + + "to MANUAL to enable adjustment"); + mComboLNAGain.setEnabled(false); + add(new JLabel("LNA:")); + add(mComboLNAGain); + + mComboEnhanceGain = new JComboBox(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("Enhance Gain. Set master gain " + + "to MANUAL to enable adjustment"); + 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("

RTL-2832 with E4000 Tuner

"); + + if(descriptor == null) + { + sb.append("No EEPROM Descriptor Available"); + } + else + { + sb.append("USB ID: "); + sb.append(descriptor.getVendorID()); + sb.append(":"); + sb.append(descriptor.getProductID()); + sb.append("
"); + + sb.append("Vendor: "); + sb.append(descriptor.getVendorLabel()); + sb.append("
"); + + sb.append("Product: "); + sb.append(descriptor.getProductLabel()); + sb.append("
"); + + sb.append("Serial: "); + sb.append(descriptor.getSerial()); + sb.append("
"); + + sb.append("IR Enabled: "); + sb.append(descriptor.irEnabled()); + sb.append("
"); + + sb.append("Remote Wake: "); + sb.append(descriptor.remoteWakeupEnabled()); + sb.append("
"); + } + + 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; + } } \ No newline at end of file diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/r820t/R820TTunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/r820t/R820TTunerEditor.java index 43fa49d2..1105ffba 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/rtl/r820t/R820TTunerEditor.java +++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/r820t/R820TTunerEditor.java @@ -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 + * 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 + * ******************************************************************************/ package io.github.dsheirer.source.tuner.rtl.r820t; @@ -47,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; @@ -55,501 +54,520 @@ import java.text.DecimalFormat; public class R820TTunerEditor extends TunerConfigurationEditor { - private final static Logger mLog = LoggerFactory.getLogger( R820TTunerEditor.class ); - - private static final long serialVersionUID = 1L; - private static final R820TGain DEFAULT_GAIN = R820TGain.GAIN_279; - - private R820TTunerController mController; - - private JTextField mConfigurationName; - private JButton mTunerInfo; - private JComboBox mComboSampleRate; - private JSpinner mFrequencyCorrection; - private JComboBox mComboMasterGain; - private JComboBox mComboMixerGain; - private JComboBox mComboLNAGain; - private JComboBox mComboVGAGain; - private boolean mLoading; - - public R820TTunerEditor( TunerConfigurationModel tunerConfigurationModel, RTL2832Tuner tuner ) - { - super( tunerConfigurationModel ); - mController = (R820TTunerController)tuner.getController(); - - init(); - } - - private R820TTunerConfiguration getConfiguration() - { - if( hasItem() ) - { - return (R820TTunerConfiguration)getItem(); - } - - return null; - } - - private void init() - { - setLayout( new MigLayout( "fill,wrap 4", "[right][grow,fill][right][grow,fill]", - "[][][][][][][][grow]" ) ); - - add( new JLabel( "R820T 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( R820TTunerEditor.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( - R820TTunerEditor.this, - "R820T Tuner Controller - couldn't apply the sample " - + "rate setting [" + sampleRate.getLabel() + "] " + - eSampleRate.getLocalizedMessage() ); - - mLog.error( "R820T Tuner Controller - couldn't apply sample " - + "rate setting [" + sampleRate.getLabel() + "]", - eSampleRate ); - } - } - } ); - add( new JLabel( "Sample Rate:" ) ); - add( mComboSampleRate ); - - /** - * Frequency Correction - */ - SpinnerModel model = - new SpinnerNumberModel( 0.0, //initial value - -1000.0, //min - 1000.0, //max - 0.1 ); //step - - mFrequencyCorrection = new JSpinner( model ); - mFrequencyCorrection.setEnabled( false ); - - JSpinner.NumberEditor editor = - (JSpinner.NumberEditor)mFrequencyCorrection.getEditor(); - - DecimalFormat format = editor.getFormat(); - format.setMinimumFractionDigits( 1 ); - editor.getTextField().setHorizontalAlignment( SwingConstants.CENTER ); - - mFrequencyCorrection.addChangeListener( new ChangeListener() - { - @Override - public void stateChanged( ChangeEvent e ) - { - final double value = ((SpinnerNumberModel)mFrequencyCorrection - .getModel()).getNumber().doubleValue(); - - try - { - mController.setFrequencyCorrection( value ); - } - catch ( SourceException e1 ) - { - mLog.error( "Error setting frequency correction value", e1 ); - } - - save(); - } - } ); - - add( new JLabel( "PPM:" ) ); - add( mFrequencyCorrection ); - - add( new JSeparator( JSeparator.HORIZONTAL ), "span,grow" ); - - /** - * Gain Controls - */ - add( new JLabel( "Gain" ), "wrap" ); - - /* Master Gain Control */ - mComboMasterGain = new JComboBox( R820TGain.values() ); - mComboMasterGain.setEnabled( false ); - mComboMasterGain.addActionListener( new ActionListener() - { - @Override - public void actionPerformed( ActionEvent arg0 ) - { - try - { - R820TGain gain = (R820TGain)mComboMasterGain.getSelectedItem(); - - mController.setGain( (R820TGain)mComboMasterGain.getSelectedItem(), true ); - - if( gain == R820TGain.MANUAL ) - { - mComboMixerGain.setSelectedItem( gain.getMixerGain() ); - mComboMixerGain.setEnabled( true ); - - mComboLNAGain.setSelectedItem( gain.getLNAGain() ); - mComboLNAGain.setEnabled( true ); - - mComboVGAGain.setSelectedItem( gain.getVGAGain() ); - mComboVGAGain.setEnabled( true ); - } - else - { - mComboMixerGain.setEnabled( false ); - mComboMixerGain.setSelectedItem( gain.getMixerGain() ); - - mComboLNAGain.setEnabled( false ); - mComboLNAGain.setSelectedItem( gain.getLNAGain() ); - - mComboVGAGain.setEnabled( false ); - mComboVGAGain.setSelectedItem( gain.getVGAGain() ); - } - - save(); - } - catch ( UsbException e ) - { - JOptionPane.showMessageDialog( - R820TTunerEditor.this, - "R820T Tuner Controller - couldn't apply the gain " - + "setting - " + e.getLocalizedMessage() ); - - mLog.error( "R820T Tuner Controller - couldn't apply " - + "gain setting - ", e ); - } - } - } ); - mComboMasterGain.setToolTipText( "Select AUTOMATIC for auto " - + "gain, MANUAL to enable
independent control of " - + "Mixer, LNA and Enhance gain
" - + "settings, or one of the individual gain settings for
" - + "semi-manual gain control" ); - add( new JLabel( "Master:" ) ); - add( mComboMasterGain ); - - /* Mixer Gain Control */ - mComboMixerGain = new JComboBox( R820TMixerGain.values() ); - mComboMixerGain.setEnabled( false ); - mComboMixerGain.addActionListener( new ActionListener() - { - @Override - public void actionPerformed( ActionEvent arg0 ) - { - try - { - R820TMixerGain mixerGain = - (R820TMixerGain)mComboMixerGain.getSelectedItem(); - - if( mixerGain == null ) - { - mixerGain = DEFAULT_GAIN.getMixerGain(); - } - - if( mComboMixerGain.isEnabled() ) - { - mController.setMixerGain( mixerGain, true ); - } - - save(); - } - catch ( UsbException e ) - { - JOptionPane.showMessageDialog( R820TTunerEditor.this, - "R820T Tuner Controller - couldn't apply the mixer " - + "gain setting - " + e.getLocalizedMessage() ); - - mLog.error( "R820T Tuner Controller - couldn't apply mixer " - + "gain setting - ", e ); - } - } - } ); - mComboMixerGain.setToolTipText( "Mixer Gain. Set master gain " - + "to MANUAL to enable adjustment" ); - - add( new JLabel( "Mixer:" ) ); - add( mComboMixerGain ); - - /* LNA Gain Control */ - mComboLNAGain = new JComboBox( R820TLNAGain.values() ); - mComboLNAGain.setEnabled( false ); - mComboLNAGain.addActionListener( new ActionListener() - { - @Override - public void actionPerformed( ActionEvent arg0 ) - { - try - { - R820TLNAGain lnaGain = - (R820TLNAGain)mComboLNAGain.getSelectedItem(); - - if ( lnaGain == null ) - { - lnaGain = DEFAULT_GAIN.getLNAGain(); - } - - if( mComboLNAGain.isEnabled() ) - { - mController.setLNAGain( lnaGain, true ); - } - - save(); - } - catch ( UsbException e ) - { - JOptionPane.showMessageDialog( R820TTunerEditor.this, - "R820T Tuner Controller - couldn't apply the LNA " - + "gain setting - " + e.getLocalizedMessage() ); - - mLog.error( "R820T Tuner Controller - couldn't apply LNA " - + "gain setting - ", e ); - } - } - } ); - mComboLNAGain.setToolTipText( "LNA Gain. Set master gain " - + "to MANUAL to enable adjustment" ); - - add( new JLabel( "LNA:" ) ); - add( mComboLNAGain ); - - /* VGA Gain Control */ - mComboVGAGain = new JComboBox( R820TVGAGain.values() ); - mComboVGAGain.setEnabled( false ); - mComboVGAGain.addActionListener( new ActionListener() - { - @Override - public void actionPerformed( ActionEvent arg0 ) - { - try - { - R820TVGAGain vgaGain = - (R820TVGAGain)mComboVGAGain.getSelectedItem(); - - if( vgaGain == null ) - { - vgaGain = DEFAULT_GAIN.getVGAGain(); - } - - if( mComboVGAGain.isEnabled() ) - { - mController.setVGAGain( vgaGain, true ); - } - - save(); - } - catch ( UsbException e ) - { - JOptionPane.showMessageDialog( R820TTunerEditor.this, - "R820T Tuner Controller - couldn't apply the VGA " - + "gain setting - " + e.getLocalizedMessage() ); - - mLog.error( "R820T Tuner Controller - couldn't apply VGA " - + "gain setting", e ); - } - } - } ); - mComboVGAGain.setToolTipText( "VGA Gain. Set master gain " - + "to MANUAL to enable adjustment" ); - add( new JLabel( "VGA:" ) ); - add( mComboVGAGain ); - } - - /** - * Sets each of the tuner configuration controls to the enabled argument state - */ - private void setControlsEnabled( boolean enabled ) - { - if( mConfigurationName.isEnabled() != enabled ) - { - mConfigurationName.setEnabled( enabled ); - } - - if( mTunerInfo.isEnabled() != enabled ) - { - mTunerInfo.setEnabled( enabled ); - } - - if( mFrequencyCorrection.isEnabled() != enabled ) - { - mFrequencyCorrection.setEnabled( enabled ); - } - - if( mComboSampleRate.isEnabled() != enabled ) - { - mComboSampleRate.setEnabled( enabled ); - } - - if( mComboMasterGain.isEnabled() != enabled ) - { - mComboMasterGain.setEnabled( enabled ); - } - - if( mComboMixerGain.isEnabled() != enabled ) - { - mComboMixerGain.setEnabled( enabled ); - } - - if( mComboLNAGain.isEnabled() != enabled ) - { - mComboLNAGain.setEnabled( enabled ); - } - - if( mComboVGAGain.isEnabled() != enabled ) - { - mComboVGAGain.setEnabled( enabled ); - } - } - - private String getTunerInfo() - { - StringBuilder sb = new StringBuilder(); - - RTL2832TunerController.Descriptor descriptor = mController.getDescriptor(); - - sb.append( "

RTL-2832 with R820T Tuner

" ); - - if( descriptor == null ) - { - sb.append( "No EEPROM Descriptor Available" ); - } - else - { - sb.append( "USB ID: " ); - sb.append( descriptor.getVendorID() ); - sb.append( ":" ); - sb.append( descriptor.getProductID() ); - sb.append( "
" ); - - sb.append( "Vendor: " ); - sb.append( descriptor.getVendorLabel() ); - sb.append( "
" ); - - sb.append( "Product: " ); - sb.append( descriptor.getProductLabel() ); - sb.append( "
" ); - - sb.append( "Serial: " ); - sb.append( descriptor.getSerial() ); - sb.append( "
" ); - - sb.append( "IR Enabled: " ); - sb.append( descriptor.irEnabled() ); - sb.append( "
" ); - - sb.append( "Remote Wake: " ); - sb.append( descriptor.remoteWakeupEnabled() ); - sb.append( "
" ); - } - - return sb.toString(); - } - - @Override - public void save() - { - if( hasItem() && !mLoading ) - { - R820TTunerConfiguration config = getConfiguration(); - - config.setName( mConfigurationName.getText() ); - - double value = ((SpinnerNumberModel)mFrequencyCorrection - .getModel()).getNumber().doubleValue(); - config.setFrequencyCorrection( value ); - - config.setSampleRate( (SampleRate)mComboSampleRate.getSelectedItem() ); - - R820TGain gain = (R820TGain)mComboMasterGain.getSelectedItem(); - config.setMasterGain( gain ); - - R820TMixerGain mixerGain = (R820TMixerGain)mComboMixerGain.getSelectedItem(); - config.setMixerGain( mixerGain ); - - R820TLNAGain lnaGain = (R820TLNAGain)mComboLNAGain.getSelectedItem(); - config.setLNAGain( lnaGain ); - - R820TVGAGain vgaGain = (R820TVGAGain)mComboVGAGain.getSelectedItem(); - config.setVGAGain( vgaGain ); - - 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() ) - { - R820TTunerConfiguration 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() ); - mComboVGAGain.setSelectedItem( config.getVGAGain() ); - } - else - { - setControlsEnabled( false ); - mConfigurationName.setText( config.getName() ); - } - } - else - { - setControlsEnabled( false ); - mConfigurationName.setText( "" ); - } - - mLoading = false; - } + private final static Logger mLog = LoggerFactory.getLogger(R820TTunerEditor.class); + + private static final long serialVersionUID = 1L; + private static final R820TGain DEFAULT_GAIN = R820TGain.GAIN_279; + + private R820TTunerController mController; + + private JTextField mConfigurationName; + private JButton mTunerInfo; + private JComboBox mComboSampleRate; + private JSpinner mFrequencyCorrection; + private JComboBox mComboMasterGain; + private JComboBox mComboMixerGain; + private JComboBox mComboLNAGain; + private JComboBox mComboVGAGain; + private boolean mLoading; + + public R820TTunerEditor(TunerConfigurationModel tunerConfigurationModel, RTL2832Tuner tuner) + { + super(tunerConfigurationModel); + mController = (R820TTunerController)tuner.getController(); + + init(); + } + + private R820TTunerConfiguration getConfiguration() + { + if(hasItem()) + { + return (R820TTunerConfiguration)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("R820T 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(R820TTunerEditor.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( + R820TTunerEditor.this, + "R820T Tuner Controller - couldn't apply the sample " + + "rate setting [" + sampleRate.getLabel() + "] " + + eSampleRate.getLocalizedMessage()); + + mLog.error("R820T Tuner Controller - couldn't apply sample " + + "rate setting [" + sampleRate.getLabel() + "]", + eSampleRate); + } + } + }); + add(new JLabel("Sample Rate:")); + add(mComboSampleRate); + + /** + * Frequency Correction + */ + SpinnerModel model = + new SpinnerNumberModel(0.0, //initial value + -1000.0, //min + 1000.0, //max + 0.1); //step + + mFrequencyCorrection = new JSpinner(model); + mFrequencyCorrection.setEnabled(false); + + JSpinner.NumberEditor editor = + (JSpinner.NumberEditor)mFrequencyCorrection.getEditor(); + + DecimalFormat format = editor.getFormat(); + format.setMinimumFractionDigits(1); + editor.getTextField().setHorizontalAlignment(SwingConstants.CENTER); + + mFrequencyCorrection.addChangeListener(new ChangeListener() + { + @Override + public void stateChanged(ChangeEvent e) + { + final double value = ((SpinnerNumberModel)mFrequencyCorrection + .getModel()).getNumber().doubleValue(); + + try + { + mController.setFrequencyCorrection(value); + } + catch(SourceException e1) + { + mLog.error("Error setting frequency correction value", e1); + } + + save(); + } + }); + + add(new JLabel("PPM:")); + add(mFrequencyCorrection); + + add(new JSeparator(JSeparator.HORIZONTAL), "span,grow"); + + /** + * Gain Controls + */ + add(new JLabel("Gain"), "wrap"); + + /* Master Gain Control */ + mComboMasterGain = new JComboBox(R820TGain.values()); + mComboMasterGain.setEnabled(false); + mComboMasterGain.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent arg0) + { + try + { + R820TGain gain = (R820TGain)mComboMasterGain.getSelectedItem(); + + mController.setGain((R820TGain)mComboMasterGain.getSelectedItem(), true); + + if(gain == R820TGain.MANUAL) + { + mComboMixerGain.setSelectedItem(gain.getMixerGain()); + mComboMixerGain.setEnabled(true); + + mComboLNAGain.setSelectedItem(gain.getLNAGain()); + mComboLNAGain.setEnabled(true); + + mComboVGAGain.setSelectedItem(gain.getVGAGain()); + mComboVGAGain.setEnabled(true); + } + else + { + mComboMixerGain.setEnabled(false); + mComboMixerGain.setSelectedItem(gain.getMixerGain()); + + mComboLNAGain.setEnabled(false); + mComboLNAGain.setSelectedItem(gain.getLNAGain()); + + mComboVGAGain.setEnabled(false); + mComboVGAGain.setSelectedItem(gain.getVGAGain()); + } + + save(); + } + catch(UsbException e) + { + JOptionPane.showMessageDialog( + R820TTunerEditor.this, + "R820T Tuner Controller - couldn't apply the gain " + + "setting - " + e.getLocalizedMessage()); + + mLog.error("R820T Tuner Controller - couldn't apply " + + "gain setting - ", e); + } + } + }); + mComboMasterGain.setToolTipText("Select AUTOMATIC for auto " + + "gain, MANUAL to enable
independent control of " + + "Mixer, LNA and Enhance gain
" + + "settings, or one of the individual gain settings for
" + + "semi-manual gain control"); + add(new JLabel("Master:")); + add(mComboMasterGain); + + /* Mixer Gain Control */ + mComboMixerGain = new JComboBox(R820TMixerGain.values()); + mComboMixerGain.setEnabled(false); + mComboMixerGain.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent arg0) + { + try + { + R820TMixerGain mixerGain = + (R820TMixerGain)mComboMixerGain.getSelectedItem(); + + if(mixerGain == null) + { + mixerGain = DEFAULT_GAIN.getMixerGain(); + } + + if(mComboMixerGain.isEnabled()) + { + mController.setMixerGain(mixerGain, true); + } + + save(); + } + catch(UsbException e) + { + JOptionPane.showMessageDialog(R820TTunerEditor.this, + "R820T Tuner Controller - couldn't apply the mixer " + + "gain setting - " + e.getLocalizedMessage()); + + mLog.error("R820T Tuner Controller - couldn't apply mixer " + + "gain setting - ", e); + } + } + }); + mComboMixerGain.setToolTipText("Mixer Gain. Set master gain " + + "to MANUAL to enable adjustment"); + + add(new JLabel("Mixer:")); + add(mComboMixerGain); + + /* LNA Gain Control */ + mComboLNAGain = new JComboBox(R820TLNAGain.values()); + mComboLNAGain.setEnabled(false); + mComboLNAGain.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent arg0) + { + try + { + R820TLNAGain lnaGain = + (R820TLNAGain)mComboLNAGain.getSelectedItem(); + + if(lnaGain == null) + { + lnaGain = DEFAULT_GAIN.getLNAGain(); + } + + if(mComboLNAGain.isEnabled()) + { + mController.setLNAGain(lnaGain, true); + } + + save(); + } + catch(UsbException e) + { + JOptionPane.showMessageDialog(R820TTunerEditor.this, + "R820T Tuner Controller - couldn't apply the LNA " + + "gain setting - " + e.getLocalizedMessage()); + + mLog.error("R820T Tuner Controller - couldn't apply LNA " + + "gain setting - ", e); + } + } + }); + mComboLNAGain.setToolTipText("LNA Gain. Set master gain " + + "to MANUAL to enable adjustment"); + + add(new JLabel("LNA:")); + add(mComboLNAGain); + + /* VGA Gain Control */ + mComboVGAGain = new JComboBox(R820TVGAGain.values()); + mComboVGAGain.setEnabled(false); + mComboVGAGain.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent arg0) + { + try + { + R820TVGAGain vgaGain = + (R820TVGAGain)mComboVGAGain.getSelectedItem(); + + if(vgaGain == null) + { + vgaGain = DEFAULT_GAIN.getVGAGain(); + } + + if(mComboVGAGain.isEnabled()) + { + mController.setVGAGain(vgaGain, true); + } + + save(); + } + catch(UsbException e) + { + JOptionPane.showMessageDialog(R820TTunerEditor.this, + "R820T Tuner Controller - couldn't apply the VGA " + + "gain setting - " + e.getLocalizedMessage()); + + mLog.error("R820T Tuner Controller - couldn't apply VGA " + + "gain setting", e); + } + } + }); + mComboVGAGain.setToolTipText("VGA Gain. Set master gain " + + "to MANUAL to enable adjustment"); + add(new JLabel("VGA:")); + add(mComboVGAGain); + } + + /** + * Sets each of the tuner configuration controls to the enabled argument state + */ + private void setControlsEnabled(boolean enabled) + { + if(mConfigurationName.isEnabled() != enabled) + { + mConfigurationName.setEnabled(enabled); + } + + if(mTunerInfo.isEnabled() != enabled) + { + mTunerInfo.setEnabled(enabled); + } + + if(mFrequencyCorrection.isEnabled() != enabled) + { + mFrequencyCorrection.setEnabled(enabled); + } + + if(mComboSampleRate.isEnabled() != enabled) + { + mComboSampleRate.setEnabled(enabled); + } + + if(mComboMasterGain.isEnabled() != enabled) + { + mComboMasterGain.setEnabled(enabled); + } + + if(mComboMixerGain.isEnabled() != enabled) + { + mComboMixerGain.setEnabled(enabled); + } + + if(mComboLNAGain.isEnabled() != enabled) + { + mComboLNAGain.setEnabled(enabled); + } + + if(mComboVGAGain.isEnabled() != enabled) + { + mComboVGAGain.setEnabled(enabled); + } + } + + private String getTunerInfo() + { + StringBuilder sb = new StringBuilder(); + + RTL2832TunerController.Descriptor descriptor = mController.getDescriptor(); + + sb.append("

RTL-2832 with R820T Tuner

"); + + if(descriptor == null) + { + sb.append("No EEPROM Descriptor Available"); + } + else + { + sb.append("USB ID: "); + sb.append(descriptor.getVendorID()); + sb.append(":"); + sb.append(descriptor.getProductID()); + sb.append("
"); + + sb.append("Vendor: "); + sb.append(descriptor.getVendorLabel()); + sb.append("
"); + + sb.append("Product: "); + sb.append(descriptor.getProductLabel()); + sb.append("
"); + + sb.append("Serial: "); + sb.append(descriptor.getSerial()); + sb.append("
"); + + sb.append("IR Enabled: "); + sb.append(descriptor.irEnabled()); + sb.append("
"); + + sb.append("Remote Wake: "); + sb.append(descriptor.remoteWakeupEnabled()); + sb.append("
"); + } + + return sb.toString(); + } + + @Override + public void save() + { + if(hasItem() && !mLoading) + { + R820TTunerConfiguration config = getConfiguration(); + + config.setName(mConfigurationName.getText()); + + double value = ((SpinnerNumberModel)mFrequencyCorrection + .getModel()).getNumber().doubleValue(); + config.setFrequencyCorrection(value); + + config.setSampleRate((SampleRate)mComboSampleRate.getSelectedItem()); + + R820TGain gain = (R820TGain)mComboMasterGain.getSelectedItem(); + config.setMasterGain(gain); + + R820TMixerGain mixerGain = (R820TMixerGain)mComboMixerGain.getSelectedItem(); + config.setMixerGain(mixerGain); + + R820TLNAGain lnaGain = (R820TLNAGain)mComboLNAGain.getSelectedItem(); + config.setLNAGain(lnaGain); + + R820TVGAGain vgaGain = (R820TVGAGain)mComboVGAGain.getSelectedItem(); + config.setVGAGain(vgaGain); + + 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()) + { + R820TTunerConfiguration 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()); + 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()); + } + } + else + { + setControlsEnabled(false); + mConfigurationName.setText(""); + } + + mLoading = false; + } } \ No newline at end of file