actions = alias.getAction();
+
+ for(AliasAction action : actions)
+ {
+ /* Provide access to the thread pool manager in case the
* action needs to setup a timer, and provide the original
* message to be used as part of the action (e.g. sending
* the message as a text message to a cell phone */
- action.execute( mThreadPoolManager, alias, message );
- }
- }
- }
- }
- }
- }
+ action.execute(ThreadPool.SCHEDULED, alias, message);
+ }
+ }
+ }
+ }
+ }
+ }
}
diff --git a/src/alias/action/RecurringAction.java b/src/alias/action/RecurringAction.java
index 8d6298c2..c8e54d62 100644
--- a/src/alias/action/RecurringAction.java
+++ b/src/alias/action/RecurringAction.java
@@ -1,188 +1,181 @@
package alias.action;
-import java.awt.EventQueue;
+import alias.Alias;
+import message.Message;
+
+import javax.swing.*;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlTransient;
+import java.awt.*;
+import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
-import javax.swing.JOptionPane;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlTransient;
-
-import message.Message;
-import alias.Alias;
-import controller.ThreadPoolManager;
-import controller.ThreadPoolManager.ThreadType;
-
public abstract class RecurringAction extends AliasAction
{
- @XmlTransient
- protected AtomicBoolean mRunning = new AtomicBoolean( false );
- @XmlTransient
- private ScheduledFuture> mPerpetualAction;
-
- protected Interval mInterval = Interval.ONCE;
- protected int mPeriod = 5;
-
- protected ThreadPoolManager mThreadPoolManager;
-
- public abstract void performAction( Alias alias, Message message );
+ @XmlTransient
+ protected AtomicBoolean mRunning = new AtomicBoolean(false);
+ @XmlTransient
+ private ScheduledFuture> mPerpetualAction;
+ @XmlTransient
+ protected ScheduledExecutorService mScheduledExecutorService;
- @Override
- public void execute( ThreadPoolManager threadPoolManager,
- Alias alias,
- Message message )
- {
- mThreadPoolManager = threadPoolManager;
+ protected Interval mInterval = Interval.ONCE;
+ protected int mPeriod = 5;
- if( mRunning.compareAndSet( false, true ) )
- {
- switch( mInterval )
- {
- case ONCE:
- performThreadedAction( alias, message );
- /* Don't reset */
- break;
- case DELAYED_RESET:
- performThreadedAction( alias, message );
- mThreadPoolManager.scheduleOnce( new ResetTask(),
- mPeriod, TimeUnit.SECONDS );
- break;
- case UNTIL_DISMISSED:
- mPerpetualAction = mThreadPoolManager
- .scheduleFixedRate( ThreadType.DECODER,
- new PerformActionTask( alias, message ),
- mPeriod, TimeUnit.SECONDS );
+ public abstract void performAction(Alias alias, Message message);
- StringBuilder sb = new StringBuilder();
- sb.append( "Alias [" );
- sb.append( alias.getName() );
- sb.append( "] is active in message [" );
- sb.append( message.toString() );
- sb.append( "]
" );
-
- final String text = sb.toString();
-
- EventQueue.invokeLater( new Runnable()
- {
- @Override
- public void run()
- {
- JOptionPane.showMessageDialog( null, text,
- "Alias Alert", JOptionPane.INFORMATION_MESSAGE );
-
- dismiss( false );
-
- mThreadPoolManager.scheduleOnce( new ResetTask(),
- 15, TimeUnit.SECONDS );
- }
- } );
- break;
- default:
- }
- }
- }
+ @Override
+ public void execute(ScheduledExecutorService scheduledExecutorService, Alias alias, Message message)
+ {
+ mScheduledExecutorService = scheduledExecutorService;
- /**
- * Spawns the performAction() event into a new thread so that it doesn't
- * delay any decoder actions.
- */
- private void performThreadedAction( final Alias alias, final Message message )
- {
- mThreadPoolManager.scheduleOnce( new Runnable() {
+ if(mRunning.compareAndSet(false, true))
+ {
+ switch(mInterval)
+ {
+ case ONCE:
+ performThreadedAction(alias, message);
+ /* Don't reset */
+ break;
+ case DELAYED_RESET:
+ performThreadedAction(alias, message);
+ mScheduledExecutorService.schedule(new ResetTask(), mPeriod, TimeUnit.SECONDS);
+ break;
+ case UNTIL_DISMISSED:
+ mPerpetualAction = mScheduledExecutorService.scheduleAtFixedRate(
+ new PerformActionTask(alias, message), mPeriod, mPeriod, TimeUnit.SECONDS);
- @Override
- public void run()
- {
- performAction( alias, message );
- }}, 0, TimeUnit.SECONDS );
- }
-
- @Override
- public void dismiss( boolean reset )
- {
- if( mPerpetualAction != null )
- {
- mPerpetualAction.cancel( true );
-
- mPerpetualAction = null;
- }
-
- if( reset )
- {
- mRunning.set( false );
- }
- }
-
- @XmlAttribute
- public int getPeriod()
- {
- return mPeriod;
- }
-
- public void setPeriod( int period )
- {
- mPeriod = period;
- }
-
- @XmlAttribute
- public Interval getInterval()
- {
- return mInterval;
- }
-
- public void setInterval( Interval interval )
- {
- mInterval = interval;
-
- mRunning.set( false );
- }
-
- public enum Interval
- {
- ONCE( "Once" ),
- DELAYED_RESET( "Once, Reset After Delay" ),
- UNTIL_DISMISSED( "Until Dismissed" );
-
- private String mLabel;
-
- private Interval( String label )
- {
- mLabel = label;
- }
-
- public String toString()
- {
- return mLabel;
- }
- }
-
- public class PerformActionTask implements Runnable
- {
- private Alias mAlias;
- private Message mMessage;
+ StringBuilder sb = new StringBuilder();
+ sb.append("Alias [");
+ sb.append(alias.getName());
+ sb.append("] is active in message [");
+ sb.append(message.toString());
+ sb.append("]
");
- public PerformActionTask( Alias alias, Message message )
- {
- mAlias = alias;
- mMessage = message;
- }
-
- @Override
- public void run()
- {
+ final String text = sb.toString();
+
+ EventQueue.invokeLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ JOptionPane.showMessageDialog(null, text,
+ "Alias Alert", JOptionPane.INFORMATION_MESSAGE);
+
+ dismiss(false);
+
+ mScheduledExecutorService.schedule(new ResetTask(), 15, TimeUnit.SECONDS);
+ }
+ });
+ break;
+ default:
+ }
+ }
+ }
+
+ /**
+ * Spawns the performAction() event into a new thread so that it doesn't
+ * delay any decoder actions.
+ */
+ private void performThreadedAction(final Alias alias, final Message message)
+ {
+ mScheduledExecutorService.schedule(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ performAction(alias, message);
+ }
+ }, 0, TimeUnit.SECONDS);
+ }
+
+ @Override
+ public void dismiss(boolean reset)
+ {
+ if(mPerpetualAction != null)
+ {
+ mPerpetualAction.cancel(true);
+
+ mPerpetualAction = null;
+ }
+
+ if(reset)
+ {
+ mRunning.set(false);
+ }
+ }
+
+ @XmlAttribute
+ public int getPeriod()
+ {
+ return mPeriod;
+ }
+
+ public void setPeriod(int period)
+ {
+ mPeriod = period;
+ }
+
+ @XmlAttribute
+ public Interval getInterval()
+ {
+ return mInterval;
+ }
+
+ public void setInterval(Interval interval)
+ {
+ mInterval = interval;
+
+ mRunning.set(false);
+ }
+
+ public enum Interval
+ {
+ ONCE("Once"),
+ DELAYED_RESET("Once, Reset After Delay"),
+ UNTIL_DISMISSED("Until Dismissed");
+
+ private String mLabel;
+
+ private Interval(String label)
+ {
+ mLabel = label;
+ }
+
+ public String toString()
+ {
+ return mLabel;
+ }
+ }
+
+ public class PerformActionTask implements Runnable
+ {
+ private Alias mAlias;
+ private Message mMessage;
+
+ public PerformActionTask(Alias alias, Message message)
+ {
+ mAlias = alias;
+ mMessage = message;
+ }
+
+ @Override
+ public void run()
+ {
/* Don't use the performThreadedAction() method, since this is
* already running in a separate thread */
- performAction( mAlias, mMessage );
- }
- }
-
- public class ResetTask implements Runnable
- {
- @Override
- public void run()
- {
- mRunning.set( false );
- }
- }
+ performAction(mAlias, mMessage);
+ }
+ }
+
+ public class ResetTask implements Runnable
+ {
+ @Override
+ public void run()
+ {
+ mRunning.set(false);
+ }
+ }
}
diff --git a/src/audio/AudioManager.java b/src/audio/AudioManager.java
index 02578da0..2cab2400 100644
--- a/src/audio/AudioManager.java
+++ b/src/audio/AudioManager.java
@@ -22,8 +22,6 @@ import audio.AudioEvent.Type;
import audio.output.AudioOutput;
import audio.output.MonoAudioOutput;
import audio.output.StereoAudioOutput;
-import controller.ThreadPoolManager;
-import controller.ThreadPoolManager.ThreadType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import properties.SystemProperties;
@@ -32,6 +30,7 @@ import sample.Listener;
import source.mixer.MixerChannel;
import source.mixer.MixerChannelConfiguration;
import source.mixer.MixerManager;
+import util.ThreadPool;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Mixer;
@@ -70,7 +69,6 @@ public class AudioManager implements Listener, IAudioController
private Broadcaster mControllerBroadcaster = new Broadcaster<>();
- private ThreadPoolManager mThreadPoolManager;
private ScheduledFuture> mProcessingTask;
private MixerManager mMixerManager;
private MixerChannelConfiguration mMixerChannelConfiguration;
@@ -81,9 +79,8 @@ public class AudioManager implements Listener, IAudioController
* packets to any combination of outputs based on any alias audio routing
* options specified by the user.
*/
- public AudioManager(ThreadPoolManager manager, MixerManager mixerManager)
+ public AudioManager(MixerManager mixerManager)
{
- mThreadPoolManager = manager;
mMixerManager = mixerManager;
loadSettings();
@@ -145,14 +142,13 @@ public class AudioManager implements Listener, IAudioController
public void dispose()
{
- if(mThreadPoolManager != null && mProcessingTask != null)
+ if(mProcessingTask != null)
{
- mThreadPoolManager.cancel(mProcessingTask);
+ mProcessingTask.cancel(true);
}
mAudioPacketQueue.clear();
- mThreadPoolManager = null;
mProcessingTask = null;
mChannelConnectionMap.clear();
@@ -224,9 +220,9 @@ public class AudioManager implements Listener, IAudioController
{
mControllerBroadcaster.broadcast(CONFIGURATION_CHANGE_STARTED);
- if(mThreadPoolManager != null && mProcessingTask != null)
+ if(mProcessingTask != null)
{
- mThreadPoolManager.cancel(mProcessingTask);
+ mProcessingTask.cancel(true);
}
disposeCurrentConfiguration();
@@ -234,19 +230,18 @@ public class AudioManager implements Listener, IAudioController
switch(entry.getMixerChannel())
{
case MONO:
- AudioOutput mono = new MonoAudioOutput(mThreadPoolManager,
- entry.getMixer());
+ AudioOutput mono = new MonoAudioOutput(entry.getMixer());
mAudioOutputConnections.add(new AudioOutputConnection(mono));
mAvailableConnectionCount++;
mAudioOutputMap.put(mono.getChannelName(), mono);
break;
case STEREO:
- AudioOutput left = new StereoAudioOutput(mThreadPoolManager, entry.getMixer(), MixerChannel.LEFT);
+ AudioOutput left = new StereoAudioOutput(entry.getMixer(), MixerChannel.LEFT);
mAudioOutputConnections.add(new AudioOutputConnection(left));
mAvailableConnectionCount++;
mAudioOutputMap.put(left.getChannelName(), left);
- AudioOutput right = new StereoAudioOutput(mThreadPoolManager, entry.getMixer(), MixerChannel.RIGHT);
+ AudioOutput right = new StereoAudioOutput(entry.getMixer(), MixerChannel.RIGHT);
mAudioOutputConnections.add(new AudioOutputConnection(right));
mAvailableConnectionCount++;
mAudioOutputMap.put(right.getChannelName(), right);
@@ -256,9 +251,8 @@ public class AudioManager implements Listener, IAudioController
+ "configuration: " + entry.getMixerChannel());
}
- mProcessingTask = mThreadPoolManager.scheduleFixedRate(
- ThreadType.AUDIO_PROCESSING, new AudioPacketProcessor(), 15,
- TimeUnit.MILLISECONDS);
+ mProcessingTask = ThreadPool.SCHEDULED.scheduleAtFixedRate(new AudioPacketProcessor(),
+ 0, 15, TimeUnit.MILLISECONDS);
mControllerBroadcaster.broadcast(CONFIGURATION_CHANGE_COMPLETE);
diff --git a/src/audio/broadcast/AudioBroadcaster.java b/src/audio/broadcast/AudioBroadcaster.java
index 8644e4da..050168c8 100644
--- a/src/audio/broadcast/AudioBroadcaster.java
+++ b/src/audio/broadcast/AudioBroadcaster.java
@@ -20,10 +20,10 @@ package audio.broadcast;
import audio.convert.ISilenceGenerator;
import channel.metadata.Metadata;
-import controller.ThreadPoolManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sample.Listener;
+import util.ThreadPool;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -40,7 +40,6 @@ public abstract class AudioBroadcaster implements Listener
public static final int PROCESSOR_RUN_INTERVAL_MS = 1000;
- private ThreadPoolManager mThreadPoolManager;
private ScheduledFuture mScheduledTask;
private RecordingQueueProcessor mRecordingQueueProcessor = new RecordingQueueProcessor();
@@ -77,19 +76,13 @@ public abstract class AudioBroadcaster implements Listener
* The last audio packet's metadata is automatically attached to the closed audio recording when it is enqueued for
* broadcast. That metadata will be updated on the remote server once the audio recording is opened for streaming.
*/
- public AudioBroadcaster(ThreadPoolManager threadPoolManager, BroadcastConfiguration broadcastConfiguration)
+ public AudioBroadcaster(BroadcastConfiguration broadcastConfiguration)
{
- mThreadPoolManager = threadPoolManager;
mBroadcastConfiguration = broadcastConfiguration;
mDelay = mBroadcastConfiguration.getDelay();
mSilenceGenerator = BroadcastFactory.getSilenceGenerator(broadcastConfiguration.getBroadcastFormat());
}
- protected ThreadPoolManager getThreadPoolManager()
- {
- return mThreadPoolManager;
- }
-
/**
* Broadcast binary audio data frames or sequences.
*/
@@ -129,11 +122,8 @@ public abstract class AudioBroadcaster implements Listener
{
if(mScheduledTask == null)
{
- if(mThreadPoolManager != null)
- {
- mScheduledTask = mThreadPoolManager.scheduleFixedRate(ThreadPoolManager.ThreadType.AUDIO_PROCESSING,
- mRecordingQueueProcessor, PROCESSOR_RUN_INTERVAL_MS, TimeUnit.MILLISECONDS);
- }
+ ThreadPool.SCHEDULED.scheduleAtFixedRate(mRecordingQueueProcessor, 0,
+ PROCESSOR_RUN_INTERVAL_MS, TimeUnit.MILLISECONDS);
}
}
}
@@ -145,9 +135,9 @@ public abstract class AudioBroadcaster implements Listener
{
if(mStreaming.compareAndSet(true, false))
{
- if(mThreadPoolManager != null && mScheduledTask != null)
+ if(mScheduledTask != null)
{
- mThreadPoolManager.cancel(mScheduledTask);
+ mScheduledTask.cancel(true);
}
disconnect();
diff --git a/src/audio/broadcast/BroadcastFactory.java b/src/audio/broadcast/BroadcastFactory.java
index 745be778..75caef3b 100644
--- a/src/audio/broadcast/BroadcastFactory.java
+++ b/src/audio/broadcast/BroadcastFactory.java
@@ -37,7 +37,6 @@ import audio.convert.IAudioConverter;
import audio.convert.ISilenceGenerator;
import audio.convert.MP3AudioConverter;
import audio.convert.MP3SilenceGenerator;
-import controller.ThreadPoolManager;
import gui.editor.Editor;
import gui.editor.EmptyEditor;
import icon.IconManager;
@@ -45,25 +44,23 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import record.AudioRecorder;
import record.mp3.MP3Recorder;
-import settings.SettingsManager;
import java.nio.file.Path;
public class BroadcastFactory
{
- private final static Logger mLog = LoggerFactory.getLogger( BroadcastFactory.class );
+ private final static Logger mLog = LoggerFactory.getLogger(BroadcastFactory.class);
public static final int MP3_MONO_16_KHZ_BITRATE = 16;
public static final boolean MP3_CONSTANT_BITRATE = false;
/**
* Creates an audio streaming broadcaster for the configuration
- * @param threadPoolManager for creating an audio broadcasting connection thread
+ *
* @param configuration describing the server and audio types
* @return configured broadcaster or null
*/
- public static AudioBroadcaster getBroadcaster(ThreadPoolManager threadPoolManager,
- BroadcastConfiguration configuration)
+ public static AudioBroadcaster getBroadcaster(BroadcastConfiguration configuration)
{
if(configuration != null)
{
@@ -74,20 +71,15 @@ public class BroadcastFactory
switch(configuration.getBroadcastServerType())
{
case BROADCASTIFY:
- return new IcecastTCPAudioBroadcaster(threadPoolManager,
- (BroadcastifyConfiguration)configuration);
+ return new IcecastTCPAudioBroadcaster((BroadcastifyConfiguration) configuration);
case ICECAST_TCP:
- return new IcecastTCPAudioBroadcaster(threadPoolManager,
- (IcecastTCPConfiguration)configuration);
+ return new IcecastTCPAudioBroadcaster((IcecastTCPConfiguration) configuration);
case ICECAST_HTTP:
- return new IcecastHTTPAudioBroadcaster(threadPoolManager,
- (IcecastHTTPConfiguration)configuration);
+ return new IcecastHTTPAudioBroadcaster((IcecastHTTPConfiguration) configuration);
case SHOUTCAST_V1:
- return new ShoutcastV1AudioBroadcaster(threadPoolManager,
- (ShoutcastV1Configuration)configuration);
+ return new ShoutcastV1AudioBroadcaster((ShoutcastV1Configuration) configuration);
case SHOUTCAST_V2:
- return new ShoutcastV2AudioBroadcaster(threadPoolManager,
- (ShoutcastV2Configuration)configuration);
+ return new ShoutcastV2AudioBroadcaster((ShoutcastV2Configuration) configuration);
case UNKNOWN:
default:
mLog.info("Unrecognized broadcastAudio configuration: " + configuration.getBroadcastFormat().name());
@@ -101,6 +93,7 @@ public class BroadcastFactory
/**
* Creates an audio convert to convert from 8 kHz PCM audio to the specified format
+ *
* @param configuration containing the requested output audio format
* @return audio convert or null
*/
@@ -149,6 +142,7 @@ public class BroadcastFactory
/**
* Constructs an editor for the specified broadcastAudio configuration
+ *
* @param configuration to modify or view
* @param broadcastModel model for broadcastAudio configurations
* @return an editor for the specified broadcastAudio configuration
@@ -160,10 +154,10 @@ public class BroadcastFactory
{
Editor editor;
- switch (configuration.getBroadcastServerType())
+ switch(configuration.getBroadcastServerType())
{
case BROADCASTIFY:
- editor = new BroadcastifyConfigurationEditor(broadcastModel, aliasModel, iconManager);
+ editor = new BroadcastifyConfigurationEditor(broadcastModel, aliasModel, iconManager);
break;
case ICECAST_TCP:
editor = new IcecastTCPConfigurationEditor(broadcastModel, aliasModel, iconManager);
@@ -192,7 +186,7 @@ public class BroadcastFactory
*/
public static AudioRecorder getAudioRecorder(Path path, BroadcastFormat broadcastFormat)
{
- switch (broadcastFormat)
+ switch(broadcastFormat)
{
case MP3:
return new MP3Recorder(path);
@@ -204,7 +198,7 @@ public class BroadcastFactory
public static ISilenceGenerator getSilenceGenerator(BroadcastFormat format)
{
- switch (format)
+ switch(format)
{
case MP3:
return new MP3SilenceGenerator();
diff --git a/src/audio/broadcast/BroadcastModel.java b/src/audio/broadcast/BroadcastModel.java
index ad79cf9a..d4b449bf 100644
--- a/src/audio/broadcast/BroadcastModel.java
+++ b/src/audio/broadcast/BroadcastModel.java
@@ -21,13 +21,13 @@ package audio.broadcast;
import alias.id.broadcast.BroadcastChannel;
import audio.AudioPacket;
import channel.metadata.Metadata;
-import controller.ThreadPoolManager;
import icon.IconManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import properties.SystemProperties;
import sample.Broadcaster;
import sample.Listener;
+import util.ThreadPool;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
@@ -66,7 +66,6 @@ public class BroadcastModel extends AbstractTableModel implements Listener mBroadcastConfigurationMap = new HashMap<>();
private Map mBroadcasterMap = new HashMap<>();
- private ThreadPoolManager mThreadPoolManager;
private IconManager mIconManager;
private StreamManager mStreamManager;
private Broadcaster mBroadcastEventBroadcaster = new Broadcaster<>();
@@ -74,17 +73,16 @@ public class BroadcastModel extends AbstractTableModel implements Listener
private static AtomicInteger sNextRecordingNumber = new AtomicInteger();
- private ThreadPoolManager mThreadPoolManager;
private Listener mAudioRecordingListener;
private BroadcastFormat mBroadcastFormat;
private Path mTempDirectory;
@@ -61,17 +60,13 @@ public class StreamManager implements Listener
*
* Completed streamable audio recordings are nominated to the output listener (for broadcast) upon completion
*
- * @param threadPoolManager for scheduling runnables
* @param listener to receive completed audio recordings
* @param tempDirectory where to store temporary audio recordings
*/
- public StreamManager(ThreadPoolManager threadPoolManager, Listener listener,
- BroadcastFormat broadcastFormat, Path tempDirectory)
+ public StreamManager(Listener listener, BroadcastFormat broadcastFormat, Path tempDirectory)
{
assert (tempDirectory != null && Files.isDirectory(tempDirectory));
- assert (mThreadPoolManager != null);
- mThreadPoolManager = threadPoolManager;
mAudioRecordingListener = listener;
mBroadcastFormat = broadcastFormat;
mTempDirectory = tempDirectory;
@@ -90,8 +85,8 @@ public class StreamManager implements Listener
mRecorderMonitor = new RecorderMonitor();
}
- mRecorderMonitorFuture = mThreadPoolManager.scheduleFixedRate(ThreadPoolManager.ThreadType.AUDIO_PROCESSING,
- mRecorderMonitor, 2, TimeUnit.SECONDS);
+ mRecorderMonitorFuture = ThreadPool.SCHEDULED.scheduleAtFixedRate(mRecorderMonitor,
+ 0,2, TimeUnit.SECONDS);
}
}
@@ -145,7 +140,7 @@ public class StreamManager implements Listener
{
AudioRecorder recorder = BroadcastFactory.getAudioRecorder(getTemporaryRecordingPath(),
mBroadcastFormat);
- recorder.start(mThreadPoolManager.getScheduledExecutorService());
+ recorder.start(ThreadPool.SCHEDULED);
recorder.receive(audioPacket);
mStreamRecorders.put(channelMetadataID, recorder);
}
diff --git a/src/audio/broadcast/icecast/IcecastAudioBroadcaster.java b/src/audio/broadcast/icecast/IcecastAudioBroadcaster.java
index e7d7ed85..60b6f1b2 100644
--- a/src/audio/broadcast/icecast/IcecastAudioBroadcaster.java
+++ b/src/audio/broadcast/icecast/IcecastAudioBroadcaster.java
@@ -21,15 +21,14 @@ package audio.broadcast.icecast;
import audio.broadcast.AudioBroadcaster;
import audio.broadcast.BroadcastConfiguration;
import audio.broadcast.IBroadcastMetadataUpdater;
-import controller.ThreadPoolManager;
public abstract class IcecastAudioBroadcaster extends AudioBroadcaster
{
private IBroadcastMetadataUpdater mMetadataUpdater;
- public IcecastAudioBroadcaster(ThreadPoolManager threadPoolManager, BroadcastConfiguration broadcastConfiguration)
+ public IcecastAudioBroadcaster(BroadcastConfiguration broadcastConfiguration)
{
- super(threadPoolManager, broadcastConfiguration);
+ super(broadcastConfiguration);
}
/**
@@ -37,7 +36,7 @@ public abstract class IcecastAudioBroadcaster extends AudioBroadcaster
*/
protected IcecastConfiguration getConfiguration()
{
- return (IcecastConfiguration)getBroadcastConfiguration();
+ return (IcecastConfiguration) getBroadcastConfiguration();
}
@Override
@@ -45,7 +44,7 @@ public abstract class IcecastAudioBroadcaster extends AudioBroadcaster
{
if(mMetadataUpdater == null)
{
- mMetadataUpdater = new IcecastBroadcastMetadataUpdater(getThreadPoolManager(), getConfiguration());
+ mMetadataUpdater = new IcecastBroadcastMetadataUpdater(getConfiguration());
}
return mMetadataUpdater;
diff --git a/src/audio/broadcast/icecast/IcecastBroadcastMetadataUpdater.java b/src/audio/broadcast/icecast/IcecastBroadcastMetadataUpdater.java
index dafde211..e7e7c2f4 100644
--- a/src/audio/broadcast/icecast/IcecastBroadcastMetadataUpdater.java
+++ b/src/audio/broadcast/icecast/IcecastBroadcastMetadataUpdater.java
@@ -20,7 +20,6 @@ package audio.broadcast.icecast;
import audio.broadcast.IBroadcastMetadataUpdater;
import channel.metadata.Metadata;
-import controller.ThreadPoolManager;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
@@ -33,6 +32,7 @@ import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import properties.SystemProperties;
+import util.ThreadPool;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
@@ -50,7 +50,6 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
private final static Logger mLog = LoggerFactory.getLogger(IcecastBroadcastMetadataUpdater.class);
private final static String UTF8 = "UTF-8";
- private ThreadPoolManager mThreadPoolManager;
private IcecastConfiguration mIcecastConfiguration;
private NioSocketConnector mSocketConnector;
@@ -65,9 +64,8 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
* broadcaster. When multiple metadata updates are received prior to completion of the current ongoing update
* sequence, those updates will be queued and processed in the order received.
*/
- public IcecastBroadcastMetadataUpdater(ThreadPoolManager threadPoolManager, IcecastConfiguration icecastConfiguration)
+ public IcecastBroadcastMetadataUpdater(IcecastConfiguration icecastConfiguration)
{
- mThreadPoolManager = threadPoolManager;
mIcecastConfiguration = icecastConfiguration;
}
@@ -128,7 +126,7 @@ public class IcecastBroadcastMetadataUpdater implements IBroadcastMetadataUpdate
if(updateRequest != null)
{
- mThreadPoolManager.scheduleOnce(new Runnable()
+ ThreadPool.SCHEDULED.schedule(new Runnable()
{
@Override
public void run()
diff --git a/src/audio/broadcast/icecast/IcecastHTTPAudioBroadcaster.java b/src/audio/broadcast/icecast/IcecastHTTPAudioBroadcaster.java
index d40f9e32..2825395f 100644
--- a/src/audio/broadcast/icecast/IcecastHTTPAudioBroadcaster.java
+++ b/src/audio/broadcast/icecast/IcecastHTTPAudioBroadcaster.java
@@ -20,7 +20,6 @@ package audio.broadcast.icecast;
import audio.broadcast.BroadcastState;
import audio.convert.MP3AudioConverter;
-import controller.ThreadPoolManager;
import org.apache.mina.core.RuntimeIoException;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.future.ConnectFuture;
@@ -38,6 +37,7 @@ import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import properties.SystemProperties;
+import util.ThreadPool;
import java.net.ConnectException;
import java.net.InetSocketAddress;
@@ -48,12 +48,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
{
- private static final Logger mLog = LoggerFactory.getLogger( IcecastHTTPAudioBroadcaster.class );
+ private static final Logger mLog = LoggerFactory.getLogger(IcecastHTTPAudioBroadcaster.class);
private static final long RECONNECT_INTERVAL_MILLISECONDS = 30000; //30 seconds
private NioSocketConnector mSocketConnector;
private IoSession mStreamingSession = null;
- private Map mHTTPHeaders;
+ private Map mHTTPHeaders;
private long mLastConnectionAttempt = 0;
private AtomicBoolean mConnecting = new AtomicBoolean();
@@ -69,9 +69,9 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
*
* @param configuration for the Icecast stream
*/
- public IcecastHTTPAudioBroadcaster(ThreadPoolManager threadPoolManager, IcecastHTTPConfiguration configuration)
+ public IcecastHTTPAudioBroadcaster(IcecastHTTPConfiguration configuration)
{
- super(threadPoolManager, configuration);
+ super(configuration);
}
/**
@@ -101,7 +101,7 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
private boolean connect()
{
if(!connected() && canConnect() &&
- (mLastConnectionAttempt + RECONNECT_INTERVAL_MILLISECONDS < System.currentTimeMillis()) &&
+ (mLastConnectionAttempt + RECONNECT_INTERVAL_MILLISECONDS < System.currentTimeMillis()) &&
mConnecting.compareAndSet(false, true))
{
mLastConnectionAttempt = System.currentTimeMillis();
@@ -159,7 +159,7 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
}
};
- getThreadPoolManager().scheduleOnce(runnable, 0l, TimeUnit.SECONDS);
+ ThreadPool.SCHEDULED.schedule(runnable, 0l, TimeUnit.SECONDS);
}
@@ -264,10 +264,10 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
{
if(throwable instanceof ProtocolDecoderException)
{
- Throwable cause = ((ProtocolDecoderException)throwable).getCause();
+ Throwable cause = ((ProtocolDecoderException) throwable).getCause();
if(cause instanceof HttpException &&
- ((HttpException)cause).getStatusCode() == HttpStatus.CLIENT_ERROR_LENGTH_REQUIRED.code())
+ ((HttpException) cause).getStatusCode() == HttpStatus.CLIENT_ERROR_LENGTH_REQUIRED.code())
{
//Ignore - Icecast 2.4 sometimes doesn't send any headers with their HTTP responses. Mina expects a
//content-length for HTTP responses.
@@ -294,7 +294,7 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
{
if(object instanceof DefaultHttpResponse)
{
- DefaultHttpResponse response = (DefaultHttpResponse)object;
+ DefaultHttpResponse response = (DefaultHttpResponse) object;
switch(response.getStatus())
{
@@ -322,7 +322,7 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
else
{
mLog.error("Icecast HTTP broadcaster - unrecognized message [ " + object.getClass() +
- "] received:" + object.toString());
+ "] received:" + object.toString());
}
}
}
diff --git a/src/audio/broadcast/icecast/IcecastTCPAudioBroadcaster.java b/src/audio/broadcast/icecast/IcecastTCPAudioBroadcaster.java
index 693ad674..f6d7c783 100644
--- a/src/audio/broadcast/icecast/IcecastTCPAudioBroadcaster.java
+++ b/src/audio/broadcast/icecast/IcecastTCPAudioBroadcaster.java
@@ -21,7 +21,6 @@ package audio.broadcast.icecast;
import audio.broadcast.BroadcastState;
import audio.broadcast.icecast.codec.IcecastCodecFactory;
import audio.convert.MP3AudioConverter;
-import controller.ThreadPoolManager;
import org.apache.mina.core.RuntimeIoException;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoHandlerAdapter;
@@ -31,6 +30,7 @@ import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import properties.SystemProperties;
+import util.ThreadPool;
import java.io.IOException;
import java.net.ConnectException;
@@ -40,7 +40,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
{
- private final static Logger mLog = LoggerFactory.getLogger( IcecastTCPAudioBroadcaster.class );
+ private final static Logger mLog = LoggerFactory.getLogger(IcecastTCPAudioBroadcaster.class);
private final static String TERMINATOR = "\r\n";
private final static String SEPARATOR = ":";
private static final long RECONNECT_INTERVAL_MILLISECONDS = 30000; //30 seconds
@@ -62,9 +62,9 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
*
* @param configuration for the Icecast stream
*/
- public IcecastTCPAudioBroadcaster(ThreadPoolManager threadPoolManager, IcecastTCPConfiguration configuration)
+ public IcecastTCPAudioBroadcaster(IcecastTCPConfiguration configuration)
{
- super(threadPoolManager, configuration);
+ super(configuration);
}
/**
@@ -90,7 +90,7 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
private boolean connect()
{
if(!connected() && canConnect() &&
- (mLastConnectionAttempt + RECONNECT_INTERVAL_MILLISECONDS < System.currentTimeMillis()) &&
+ (mLastConnectionAttempt + RECONNECT_INTERVAL_MILLISECONDS < System.currentTimeMillis()) &&
mConnecting.compareAndSet(false, true))
{
mLastConnectionAttempt = System.currentTimeMillis();
@@ -149,8 +149,7 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
}
};
- getThreadPoolManager().scheduleOnce(runnable, 0l, TimeUnit.SECONDS);
-
+ ThreadPool.SCHEDULED.schedule(runnable, 0l, TimeUnit.SECONDS);
}
return connected();
@@ -241,9 +240,9 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
@Override
public void exceptionCaught(IoSession session, Throwable cause) throws Exception
{
- if(cause instanceof IOException && ((IOException)cause).getMessage().startsWith("Connection reset"))
+ if(cause instanceof IOException && ((IOException) cause).getMessage().startsWith("Connection reset"))
{
- IOException ioe = (IOException)cause;
+ IOException ioe = (IOException) cause;
if(ioe.getMessage() != null && ioe.getMessage().startsWith("Connection reset"))
{
@@ -271,7 +270,7 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
{
if(object instanceof String)
{
- String message = (String)object;
+ String message = (String) object;
if(message != null && !message.trim().isEmpty())
{
diff --git a/src/audio/broadcast/shoutcast/v1/ShoutcastV1AudioBroadcaster.java b/src/audio/broadcast/shoutcast/v1/ShoutcastV1AudioBroadcaster.java
index 8c031150..637a721e 100644
--- a/src/audio/broadcast/shoutcast/v1/ShoutcastV1AudioBroadcaster.java
+++ b/src/audio/broadcast/shoutcast/v1/ShoutcastV1AudioBroadcaster.java
@@ -21,7 +21,6 @@ package audio.broadcast.shoutcast.v1;
import audio.broadcast.AudioBroadcaster;
import audio.broadcast.BroadcastState;
import audio.broadcast.IBroadcastMetadataUpdater;
-import controller.ThreadPoolManager;
import org.apache.mina.core.RuntimeIoException;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.future.ConnectFuture;
@@ -32,6 +31,7 @@ import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import util.ThreadPool;
import java.io.IOException;
import java.net.ConnectException;
@@ -41,7 +41,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
{
- private final static Logger mLog = LoggerFactory.getLogger( ShoutcastV1AudioBroadcaster.class );
+ private final static Logger mLog = LoggerFactory.getLogger(ShoutcastV1AudioBroadcaster.class);
private static final long RECONNECT_INTERVAL_MILLISECONDS = 30000; //30 seconds
private NioSocketConnector mSocketConnector;
@@ -61,9 +61,9 @@ public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
*
* @param configuration for the Shoutcast stream
*/
- public ShoutcastV1AudioBroadcaster(ThreadPoolManager threadPoolManager, ShoutcastV1Configuration configuration)
+ public ShoutcastV1AudioBroadcaster(ShoutcastV1Configuration configuration)
{
- super(threadPoolManager, configuration);
+ super(configuration);
}
/**
@@ -71,7 +71,7 @@ public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
*/
private ShoutcastV1Configuration getConfiguration()
{
- return (ShoutcastV1Configuration)getBroadcastConfiguration();
+ return (ShoutcastV1Configuration) getBroadcastConfiguration();
}
@Override
@@ -79,7 +79,7 @@ public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
{
if(mMetadataUpdater == null)
{
- mMetadataUpdater = new ShoutcastV1BroadcastMetadataUpdater(getThreadPoolManager(), getConfiguration());
+ mMetadataUpdater = new ShoutcastV1BroadcastMetadataUpdater(getConfiguration());
}
return mMetadataUpdater;
@@ -111,7 +111,7 @@ public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
private boolean connect()
{
if(!connected() && canConnect() &&
- (mLastConnectionAttempt + RECONNECT_INTERVAL_MILLISECONDS < System.currentTimeMillis()) &&
+ (mLastConnectionAttempt + RECONNECT_INTERVAL_MILLISECONDS < System.currentTimeMillis()) &&
mConnecting.compareAndSet(false, true))
{
mLastConnectionAttempt = System.currentTimeMillis();
@@ -171,8 +171,7 @@ public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
}
};
- getThreadPoolManager().scheduleOnce(runnable, 0l, TimeUnit.SECONDS);
-
+ ThreadPool.SCHEDULED.schedule(runnable, 0l, TimeUnit.SECONDS);
}
return connected();
@@ -242,9 +241,9 @@ public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
@Override
public void exceptionCaught(IoSession session, Throwable cause) throws Exception
{
- if(cause instanceof IOException && ((IOException)cause).getMessage().startsWith("Connection reset"))
+ if(cause instanceof IOException && ((IOException) cause).getMessage().startsWith("Connection reset"))
{
- IOException ioe = (IOException)cause;
+ IOException ioe = (IOException) cause;
if(ioe.getMessage() != null && ioe.getMessage().startsWith("Connection reset"))
{
@@ -272,7 +271,7 @@ public class ShoutcastV1AudioBroadcaster extends AudioBroadcaster
{
if(object instanceof String)
{
- String message = (String)object;
+ String message = (String) object;
if(message != null && !message.trim().isEmpty())
{
diff --git a/src/audio/broadcast/shoutcast/v1/ShoutcastV1BroadcastMetadataUpdater.java b/src/audio/broadcast/shoutcast/v1/ShoutcastV1BroadcastMetadataUpdater.java
index 4c1de743..6ef77c33 100644
--- a/src/audio/broadcast/shoutcast/v1/ShoutcastV1BroadcastMetadataUpdater.java
+++ b/src/audio/broadcast/shoutcast/v1/ShoutcastV1BroadcastMetadataUpdater.java
@@ -20,7 +20,6 @@ package audio.broadcast.shoutcast.v1;
import audio.broadcast.IBroadcastMetadataUpdater;
import channel.metadata.Metadata;
-import controller.ThreadPoolManager;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
@@ -32,6 +31,7 @@ import org.apache.mina.http.api.HttpVersion;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import util.ThreadPool;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
@@ -49,7 +49,6 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
private final static Logger mLog = LoggerFactory.getLogger(ShoutcastV1BroadcastMetadataUpdater.class);
private final static String UTF8 = "UTF-8";
- private ThreadPoolManager mThreadPoolManager;
private ShoutcastV1Configuration mShoutcastV1Configuration;
private NioSocketConnector mSocketConnector;
@@ -63,9 +62,8 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
* broadcaster. When multiple metadata updates are received prior to completion of the current ongoing update
* sequence, those updates will be queued and processed in the order received.
*/
- public ShoutcastV1BroadcastMetadataUpdater(ThreadPoolManager threadPoolManager, ShoutcastV1Configuration shoutcastV1Configuration)
+ public ShoutcastV1BroadcastMetadataUpdater(ShoutcastV1Configuration shoutcastV1Configuration)
{
- mThreadPoolManager = threadPoolManager;
mShoutcastV1Configuration = shoutcastV1Configuration;
}
@@ -127,7 +125,7 @@ public class ShoutcastV1BroadcastMetadataUpdater implements IBroadcastMetadataUp
if(updateRequest != null)
{
- mThreadPoolManager.scheduleOnce(new Runnable()
+ ThreadPool.SCHEDULED.schedule(new Runnable()
{
@Override
public void run()
diff --git a/src/audio/broadcast/shoutcast/v2/ShoutcastV2AudioBroadcaster.java b/src/audio/broadcast/shoutcast/v2/ShoutcastV2AudioBroadcaster.java
index 85add863..95e2c6c1 100644
--- a/src/audio/broadcast/shoutcast/v2/ShoutcastV2AudioBroadcaster.java
+++ b/src/audio/broadcast/shoutcast/v2/ShoutcastV2AudioBroadcaster.java
@@ -38,7 +38,6 @@ import audio.broadcast.shoutcast.v2.ultravox.UltravoxMessageType;
import audio.broadcast.shoutcast.v2.ultravox.UltravoxMetadata;
import audio.broadcast.shoutcast.v2.ultravox.UltravoxProtocolFactory;
import channel.metadata.Metadata;
-import controller.ThreadPoolManager;
import org.apache.mina.core.RuntimeIoException;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoHandlerAdapter;
@@ -48,6 +47,7 @@ import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import properties.SystemProperties;
+import util.ThreadPool;
import java.io.IOException;
import java.net.ConnectException;
@@ -81,12 +81,11 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
* This broadcaster uses the Apache Mina library for the streaming socket connection. The
* ShoutcastV2IOHandler manages all interaction with the Shoutcast server and manages the overall broadcast state.
*
- * @param threadPoolManager for thread pool access
* @param configuration for the Shoutcast V2 stream
*/
- public ShoutcastV2AudioBroadcaster(ThreadPoolManager threadPoolManager, ShoutcastV2Configuration configuration)
+ public ShoutcastV2AudioBroadcaster(ShoutcastV2Configuration configuration)
{
- super(threadPoolManager, configuration);
+ super(configuration);
}
public ShoutcastV2Configuration getConfiguration()
@@ -207,8 +206,7 @@ public class ShoutcastV2AudioBroadcaster extends AudioBroadcaster implements IBr
}
};
- getThreadPoolManager().scheduleOnce(runnable, 0l, TimeUnit.SECONDS);
-
+ ThreadPool.SCHEDULED.schedule(runnable, 0l, TimeUnit.SECONDS);
}
return connected();
diff --git a/src/audio/output/AudioOutput.java b/src/audio/output/AudioOutput.java
index 896fbd50..f27dd8b3 100644
--- a/src/audio/output/AudioOutput.java
+++ b/src/audio/output/AudioOutput.java
@@ -22,13 +22,12 @@ import audio.AudioEvent;
import audio.AudioPacket;
import audio.AudioPacket.Type;
import channel.metadata.Metadata;
-import controller.ThreadPoolManager;
-import controller.ThreadPoolManager.ThreadType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sample.Broadcaster;
import sample.Listener;
import source.mixer.MixerChannel;
+import util.ThreadPool;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.BooleanControl;
@@ -59,7 +58,6 @@ public abstract class AudioOutput implements Listener, LineListener
private Listener mMetadataListener;
private Broadcaster mAudioEventBroadcaster = new Broadcaster<>();
- private ThreadPoolManager mThreadPoolManager;
private ScheduledFuture> mProcessorTask;
private SourceDataLine mOutput;
@@ -82,21 +80,18 @@ public abstract class AudioOutput implements Listener, LineListener
* Maintains an internal non-blocking audio packet queue and processes this
* queue 25 times a second (every 40 ms).
*
- * @param threadPoolManager for assigning buffer processing schedule task
* @param mixer to obtain source data line
* @param mixerChannel either mono or left/right stereo
* @param audioFormat to use during playback
* @param lineInfo to use when obtaining the source data line
* @param requestedBufferSize of approximately 1 second of audio
*/
- public AudioOutput(ThreadPoolManager threadPoolManager,
- Mixer mixer,
+ public AudioOutput(Mixer mixer,
MixerChannel mixerChannel,
AudioFormat audioFormat,
Line.Info lineInfo,
int requestedBufferSize)
{
- mThreadPoolManager = threadPoolManager;
mMixer = mixer;
mMixerChannel = mixerChannel;
@@ -141,9 +136,8 @@ public abstract class AudioOutput implements Listener, LineListener
}
/* Run the queue processor task every 40 milliseconds or 25 times a second */
- mProcessorTask = mThreadPoolManager.scheduleFixedRate(
- ThreadType.AUDIO_PROCESSING, new BufferProcessor(),
- 40, TimeUnit.MILLISECONDS);
+ mProcessorTask = ThreadPool.SCHEDULED.scheduleAtFixedRate(new BufferProcessor(),
+ 0, 40, TimeUnit.MILLISECONDS);
}
mAudioStartEvent = new AudioEvent(AudioEvent.Type.AUDIO_STARTED,
@@ -170,12 +164,11 @@ public abstract class AudioOutput implements Listener, LineListener
{
mCanProcessAudio = false;
- if(mProcessorTask != null && mThreadPoolManager != null)
+ if(mProcessorTask != null)
{
- mThreadPoolManager.cancel(mProcessorTask);
+ mProcessorTask.cancel(true);
}
- mThreadPoolManager = null;
mProcessorTask = null;
mBuffer.clear();
diff --git a/src/audio/output/MonoAudioOutput.java b/src/audio/output/MonoAudioOutput.java
index a217c192..c8c7c267 100644
--- a/src/audio/output/MonoAudioOutput.java
+++ b/src/audio/output/MonoAudioOutput.java
@@ -1,74 +1,67 @@
/*******************************************************************************
- * 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
+ * sdrtrunk
+ * Copyright (C) 2014-2017 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 audio.output;
+import audio.AudioFormats;
+import audio.AudioPacket;
+import source.mixer.MixerChannel;
+
+import javax.sound.sampled.Mixer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
-import javax.sound.sampled.Mixer;
-
-import source.mixer.MixerChannel;
-import audio.AudioFormats;
-import audio.AudioPacket;
-import controller.ThreadPoolManager;
-
/**
* Mono Audio output implementation
*/
public class MonoAudioOutput extends AudioOutput
{
- private final static int BUFFER_SIZE = 8000;
-
- public MonoAudioOutput( ThreadPoolManager threadPoolManager, Mixer mixer )
- {
- super( threadPoolManager,
- mixer,
- MixerChannel.MONO,
- AudioFormats.PCM_SIGNED_8KHZ_16BITS_MONO,
- AudioFormats.MONO_SOURCE_DATALINE_INFO,
- BUFFER_SIZE );
- }
+ private final static int BUFFER_SIZE = 8000;
+
+ public MonoAudioOutput(Mixer mixer)
+ {
+ super(mixer, MixerChannel.MONO, AudioFormats.PCM_SIGNED_8KHZ_16BITS_MONO,
+ AudioFormats.MONO_SOURCE_DATALINE_INFO, BUFFER_SIZE);
+ }
+
+ /**
+ * Converts the audio packet data into mono audio frames.
+ */
+ protected ByteBuffer convert(AudioPacket packet)
+ {
+ if(packet.hasAudioBuffer())
+ {
+ float[] samples = packet.getAudioBuffer().getSamples();
- /**
- * Converts the audio packet data into mono audio frames.
- */
- protected ByteBuffer convert( AudioPacket packet )
- {
- if( packet.hasAudioBuffer() )
- {
- float[] samples = packet.getAudioBuffer().getSamples();
-
/* Little-endian byte buffer */
- ByteBuffer buffer =
- ByteBuffer.allocate( samples.length * 2 )
- .order( ByteOrder.LITTLE_ENDIAN );
+ ByteBuffer buffer = ByteBuffer.allocate(samples.length * 2).order(ByteOrder.LITTLE_ENDIAN);
- ShortBuffer shortBuffer = buffer.asShortBuffer();
+ ShortBuffer shortBuffer = buffer.asShortBuffer();
- for( float sample: samples )
- {
- shortBuffer.put( (short)( sample * Short.MAX_VALUE ) );
- }
-
- return buffer;
- }
-
- return null;
- }
+ for(float sample : samples)
+ {
+ shortBuffer.put((short) (sample * Short.MAX_VALUE));
+ }
+
+ return buffer;
+ }
+
+ return null;
+ }
}
diff --git a/src/audio/output/StereoAudioOutput.java b/src/audio/output/StereoAudioOutput.java
index 098112ec..54c90150 100644
--- a/src/audio/output/StereoAudioOutput.java
+++ b/src/audio/output/StereoAudioOutput.java
@@ -1,88 +1,82 @@
/*******************************************************************************
- * 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
+ * sdrtrunk
+ * Copyright (C) 2014-2017 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 audio.output;
+import audio.AudioFormats;
+import audio.AudioPacket;
+import source.mixer.MixerChannel;
+
+import javax.sound.sampled.Mixer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
-import javax.sound.sampled.Mixer;
-
-import source.mixer.MixerChannel;
-import audio.AudioFormats;
-import audio.AudioPacket;
-import controller.ThreadPoolManager;
-
/**
- * Stereo audio output implementation.
+ * Stereo audio output implementation.
*/
public class StereoAudioOutput extends AudioOutput
{
- private final static int BUFFER_SIZE = 16000;
-
- public StereoAudioOutput( ThreadPoolManager threadPoolManager,
- Mixer mixer, MixerChannel channel )
- {
- super( threadPoolManager,
- mixer,
- channel,
- AudioFormats.PCM_SIGNED_8KHZ_16BITS_STEREO,
- AudioFormats.STEREO_SOURCE_DATALINE_INFO,
- BUFFER_SIZE );
- }
+ private final static int BUFFER_SIZE = 16000;
+
+ public StereoAudioOutput(Mixer mixer, MixerChannel channel)
+ {
+ super(mixer, channel, AudioFormats.PCM_SIGNED_8KHZ_16BITS_STEREO, AudioFormats.STEREO_SOURCE_DATALINE_INFO,
+ BUFFER_SIZE);
+ }
+
+ /**
+ * Converts the audio packet data into stereo audio frames with the mixer
+ * channel containing the audio and the other channel containing zero
+ * valued (silent) samples.
+ */
+ protected ByteBuffer convert(AudioPacket packet)
+ {
+ if(packet.hasAudioBuffer())
+ {
+ float[] samples = packet.getAudioBuffer().getSamples();
- /**
- * Converts the audio packet data into stereo audio frames with the mixer
- * channel containing the audio and the other channel containing zero
- * valued (silent) samples.
- */
- protected ByteBuffer convert( AudioPacket packet )
- {
- if( packet.hasAudioBuffer() )
- {
- float[] samples = packet.getAudioBuffer().getSamples();
-
/* Little-endian byte buffer */
- ByteBuffer buffer = ByteBuffer.allocate( samples.length * 4 )
- .order( ByteOrder.LITTLE_ENDIAN );
-
- ShortBuffer shortBuffer = buffer.asShortBuffer();
+ ByteBuffer buffer = ByteBuffer.allocate(samples.length * 4)
+ .order(ByteOrder.LITTLE_ENDIAN);
- if( getMixerChannel() == MixerChannel.LEFT )
- {
- for( float sample: samples )
- {
- shortBuffer.put( (short)( sample * Short.MAX_VALUE ) );
- shortBuffer.put( (short)0 );
- }
- }
- else
- {
- for( float sample: samples )
- {
- shortBuffer.put( (short)0 );
- shortBuffer.put( (short)( sample * Short.MAX_VALUE ) );
- }
- }
-
- return buffer;
- }
-
- return null;
- }
+ ShortBuffer shortBuffer = buffer.asShortBuffer();
+
+ if(getMixerChannel() == MixerChannel.LEFT)
+ {
+ for(float sample : samples)
+ {
+ shortBuffer.put((short) (sample * Short.MAX_VALUE));
+ shortBuffer.put((short) 0);
+ }
+ }
+ else
+ {
+ for(float sample : samples)
+ {
+ shortBuffer.put((short) 0);
+ shortBuffer.put((short) (sample * Short.MAX_VALUE));
+ }
+ }
+
+ return buffer;
+ }
+
+ return null;
+ }
}
diff --git a/src/channel/metadata/ChannelMetadataPanel.java b/src/channel/metadata/ChannelMetadataPanel.java
index c3a07090..d16161de 100644
--- a/src/channel/metadata/ChannelMetadataPanel.java
+++ b/src/channel/metadata/ChannelMetadataPanel.java
@@ -20,7 +20,6 @@ package channel.metadata;
import alias.Alias;
import channel.state.State;
-import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory;
import controller.channel.Channel;
import controller.channel.ChannelProcessingManager;
import icon.IconManager;
diff --git a/src/controller/ThreadPoolManager.java b/src/controller/ThreadPoolManager.java
deleted file mode 100644
index d96cf9c6..00000000
--- a/src/controller/ThreadPoolManager.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014 Dennis Sheirer
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- ******************************************************************************/
-package controller;
-
-import java.util.HashMap;
-import java.util.concurrent.Executors;
-import java.util.concurrent.RejectedExecutionException;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ThreadPoolManager
-{
- private final static Logger mLog = LoggerFactory.getLogger( ThreadPoolManager.class );
-
- private int THREAD_POOL_SIZE = 2;
-
- private HashMap,ThreadType> mTasks =
- new HashMap,ThreadType>();
-
- private ScheduledExecutorService mExecutor;
-
- public ThreadPoolManager()
- {
- }
-
- public ScheduledExecutorService getScheduledExecutorService()
- {
- if( mExecutor == null )
- {
- mExecutor = Executors.newScheduledThreadPool( THREAD_POOL_SIZE,
- new NamingThreadFactory( "sdrtrunk" ) );
- }
-
- return mExecutor;
- }
-
- public ScheduledFuture> scheduleFixedRate( ThreadType type,
- Runnable command,
- long period,
- TimeUnit unit )
- throws RejectedExecutionException
- {
- ScheduledExecutorService executorService = getScheduledExecutorService();
-
- ScheduledFuture> task =
- executorService.scheduleAtFixedRate( command, 0, period, unit );
-
- mTasks.put( task, type );
-
- return task;
- }
-
- public void scheduleOnce( Runnable command, long delay, TimeUnit unit )
- throws RejectedExecutionException
- {
- ScheduledExecutorService executorService = getScheduledExecutorService();
-
- executorService.schedule( command, delay, unit );
- }
-
- public boolean cancel( ScheduledFuture> task )
- {
- boolean success = task.cancel( true );
-
- mTasks.remove( task );
-
- return success;
- }
-
- public int getTaskCount( ThreadType type )
- {
- int count = 0;
-
- for( ThreadType current: mTasks.values() )
- {
- if( current == type )
- {
- count++;
- }
- }
-
- return count;
- }
-
- public enum ThreadType
- {
- AUDIO_PROCESSING,
- AUDIO_RECORDING,
- BASEBAND_RECORDING,
- SOURCE_SAMPLE_PROCESSING,
- DECIMATION,
- DECODER;
- }
-}
diff --git a/src/gui/SDRTrunk.java b/src/gui/SDRTrunk.java
index 720a7faa..401067f6 100644
--- a/src/gui/SDRTrunk.java
+++ b/src/gui/SDRTrunk.java
@@ -1,19 +1,20 @@
/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014-2016 Dennis Sheirer
+ * sdrtrunk
+ * Copyright (C) 2014-2017 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 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.
+ * 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
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
******************************************************************************/
package gui;
@@ -24,9 +25,6 @@ import audio.broadcast.BroadcastModel;
import audio.broadcast.BroadcastStatusPanel;
import com.jidesoft.swing.JideSplitPane;
import controller.ControllerPanel;
-import controller.ThreadPoolManager;
-import controller.ThreadPoolManager.ThreadType;
-import controller.channel.ChannelEventListener;
import controller.channel.ChannelModel;
import controller.channel.ChannelProcessingManager;
import controller.channel.ChannelSelectionManager;
@@ -48,6 +46,7 @@ import source.tuner.TunerModel;
import source.tuner.TunerSpectralDisplayManager;
import source.tuner.configuration.TunerConfigurationModel;
import spectrum.SpectralDisplayPanel;
+import util.ThreadPool;
import util.TimeStamp;
import javax.imageio.ImageIO;
@@ -61,7 +60,6 @@ import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.concurrent.TimeUnit;
public class SDRTrunk implements Listener
{
@@ -80,26 +78,28 @@ public class SDRTrunk implements Listener
private String mTitle;
- private boolean mLogChannelAndMemoryUsage = false;
-
public SDRTrunk()
{
- mLog.info("");
mLog.info("");
mLog.info("*******************************************************************");
mLog.info("**** sdrtrunk: a trunked radio and digital decoding application ***");
mLog.info("**** website: https://github.com/dsheirer/sdrtrunk ***");
mLog.info("*******************************************************************");
mLog.info("");
- mLog.info("");
+ mLog.info("Host CPU Cores: " + Runtime.getRuntime().availableProcessors());
+ mLog.info("Host Memory Total: " + Runtime.getRuntime().totalMemory());
+ mLog.info("Host Memory Max: " + Runtime.getRuntime().maxMemory());
+ mLog.info("Host Memory Free: " + Runtime.getRuntime().freeMemory());
//Setup the application home directory
Path home = getHomePath();
+ ThreadPool.logSettings();
+
mLog.info("Home path: " + home.toString());
//Load properties file
- if (home != null)
+ if(home != null)
{
loadProperties(home);
}
@@ -110,11 +110,9 @@ public class SDRTrunk implements Listener
TunerConfigurationModel tunerConfigurationModel = new TunerConfigurationModel();
TunerModel tunerModel = new TunerModel(tunerConfigurationModel);
- ThreadPoolManager threadPoolManager = new ThreadPoolManager();
+ mIconManager = new IconManager();
- mIconManager = new IconManager(threadPoolManager);
-
- mSettingsManager = new SettingsManager(threadPoolManager, tunerConfigurationModel);
+ mSettingsManager = new SettingsManager(tunerConfigurationModel);
AliasModel aliasModel = new AliasModel();
@@ -124,28 +122,27 @@ public class SDRTrunk implements Listener
EventLogManager eventLogManager = new EventLogManager();
- RecorderManager recorderManager = new RecorderManager(threadPoolManager);
+ RecorderManager recorderManager = new RecorderManager();
- SourceManager sourceManager = new SourceManager(tunerModel,
- mSettingsManager, threadPoolManager);
+ SourceManager sourceManager = new SourceManager(tunerModel, mSettingsManager);
ChannelProcessingManager channelProcessingManager = new ChannelProcessingManager(
- channelModel, channelMapModel, aliasModel, eventLogManager, recorderManager, sourceManager);
+ channelModel, channelMapModel, aliasModel, eventLogManager, recorderManager, sourceManager);
channelProcessingManager.addAudioPacketListener(recorderManager);
channelModel.addListener(channelProcessingManager);
ChannelSelectionManager channelSelectionManager =
- new ChannelSelectionManager(channelModel);
+ new ChannelSelectionManager(channelModel);
channelModel.addListener(channelSelectionManager);
- AliasActionManager aliasActionManager = new AliasActionManager(threadPoolManager);
+ AliasActionManager aliasActionManager = new AliasActionManager();
channelProcessingManager.addMessageListener(aliasActionManager);
- AudioManager audioManager = new AudioManager(threadPoolManager, sourceManager.getMixerManager());
+ AudioManager audioManager = new AudioManager(sourceManager.getMixerManager());
channelProcessingManager.addAudioPacketListener(audioManager);
- mBroadcastModel = new BroadcastModel(threadPoolManager, mIconManager);
+ mBroadcastModel = new BroadcastModel(mIconManager);
channelProcessingManager.addAudioPacketListener(mBroadcastModel);
@@ -153,31 +150,23 @@ public class SDRTrunk implements Listener
channelProcessingManager.addMessageListener(mapService);
mControllerPanel = new ControllerPanel(audioManager, aliasModel, mBroadcastModel,
- channelModel, channelMapModel, channelProcessingManager, mIconManager,
- mapService, mSettingsManager, sourceManager, tunerModel);
+ channelModel, channelMapModel, channelProcessingManager, mIconManager,
+ mapService, mSettingsManager, sourceManager, tunerModel);
mSpectralPanel = new SpectralDisplayPanel(channelModel,
- channelProcessingManager, mSettingsManager);
+ channelProcessingManager, mSettingsManager);
TunerSpectralDisplayManager tunerSpectralDisplayManager =
- new TunerSpectralDisplayManager(mSpectralPanel,
- channelModel, channelProcessingManager, mSettingsManager);
+ new TunerSpectralDisplayManager(mSpectralPanel,
+ channelModel, channelProcessingManager, mSettingsManager);
tunerModel.addListener(tunerSpectralDisplayManager);
tunerModel.addListener(this);
- PlaylistManager playlistManager = new PlaylistManager(threadPoolManager,
- aliasModel, mBroadcastModel, channelModel, channelMapModel);
+ PlaylistManager playlistManager = new PlaylistManager(aliasModel, mBroadcastModel, channelModel,
+ channelMapModel);
playlistManager.init();
- if (mLogChannelAndMemoryUsage)
- {
- Runnable cml = new ChannelMemoryLogger();
- channelModel.addListener((ChannelEventListener) cml);
- threadPoolManager.scheduleFixedRate(
- ThreadType.DECODER, cml, 5, TimeUnit.SECONDS);
- }
-
mLog.info("starting main application gui");
//Initialize the GUI
@@ -194,7 +183,7 @@ public class SDRTrunk implements Listener
{
mMainGui.setVisible(true);
}
- catch (Exception e)
+ catch(Exception e)
{
e.printStackTrace();
}
@@ -263,15 +252,15 @@ public class SDRTrunk implements Listener
{
Desktop.getDesktop().open(getHomePath().toFile());
}
- catch (Exception e)
+ catch(Exception e)
{
mLog.error("Couldn't open file explorer");
JOptionPane.showMessageDialog(mMainGui,
- "Can't launch file explorer - files are located at: " +
- getHomePath().toString(),
- "Can't launch file explorer",
- JOptionPane.ERROR_MESSAGE);
+ "Can't launch file explorer - files are located at: " +
+ getHomePath().toString(),
+ "Can't launch file explorer",
+ JOptionPane.ERROR_MESSAGE);
}
}
});
@@ -292,13 +281,13 @@ public class SDRTrunk implements Listener
JMenuItem exitMenu = new JMenuItem("Exit");
exitMenu.addActionListener(
- new ActionListener()
+ new ActionListener()
+ {
+ public void actionPerformed(ActionEvent event)
{
- public void actionPerformed(ActionEvent event)
- {
- System.exit(0);
- }
+ System.exit(0);
}
+ }
);
fileMenu.add(exitMenu);
@@ -313,7 +302,7 @@ public class SDRTrunk implements Listener
screenCaptureItem.setMnemonic(KeyEvent.VK_C);
screenCaptureItem.setAccelerator(
- KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.ALT_MASK));
+ KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.ALT_MASK));
screenCaptureItem.addActionListener(new ActionListener()
{
@@ -325,28 +314,28 @@ public class SDRTrunk implements Listener
Robot robot = new Robot();
final BufferedImage image =
- robot.createScreenCapture(mMainGui.getBounds());
+ robot.createScreenCapture(mMainGui.getBounds());
SystemProperties props = SystemProperties.getInstance();
Path capturePath = props.getApplicationFolder("screen_captures");
- if (!Files.exists(capturePath))
+ if(!Files.exists(capturePath))
{
try
{
Files.createDirectory(capturePath);
}
- catch (IOException e)
+ catch(IOException e)
{
mLog.error("Couldn't create 'screen_captures' "
- + "subdirectory in the " +
- "SDRTrunk application directory", e);
+ + "subdirectory in the " +
+ "SDRTrunk application directory", e);
}
}
String filename = TimeStamp.getTimeStamp("_") +
- "_screen_capture.png";
+ "_screen_capture.png";
final Path captureFile = capturePath.resolve(filename);
@@ -358,17 +347,17 @@ public class SDRTrunk implements Listener
try
{
ImageIO.write(image, "png",
- captureFile.toFile());
+ captureFile.toFile());
}
- catch (IOException e)
+ catch(IOException e)
{
mLog.error("Couldn't write screen capture to "
- + "file [" + captureFile.toString() + "]", e);
+ + "file [" + captureFile.toString() + "]", e);
}
}
});
}
- catch (AWTException e)
+ catch(AWTException e)
{
mLog.error("Exception while taking screen capture", e);
}
@@ -430,30 +419,30 @@ public class SDRTrunk implements Listener
{
Path propsPath = homePath.resolve("SDRTrunk.properties");
- if (!Files.exists(propsPath))
+ if(!Files.exists(propsPath))
{
try
{
mLog.info("SDRTrunk - creating application properties file [" +
- propsPath.toAbsolutePath() + "]");
+ propsPath.toAbsolutePath() + "]");
Files.createFile(propsPath);
}
- catch (IOException e)
+ catch(IOException e)
{
mLog.error("SDRTrunk - couldn't create application properties "
- + "file [" + propsPath.toAbsolutePath(), e);
+ + "file [" + propsPath.toAbsolutePath(), e);
}
}
- if (Files.exists(propsPath))
+ if(Files.exists(propsPath))
{
SystemProperties.getInstance().load(propsPath);
}
else
{
mLog.error("SDRTrunk - couldn't find or recreate the SDRTrunk " +
- "application properties file");
+ "application properties file");
}
}
@@ -466,23 +455,23 @@ public class SDRTrunk implements Listener
private Path getHomePath()
{
Path homePath = FileSystems.getDefault()
- .getPath(System.getProperty("user.home"), "SDRTrunk");
+ .getPath(System.getProperty("user.home"), "SDRTrunk");
- if (!Files.exists(homePath))
+ if(!Files.exists(homePath))
{
try
{
Files.createDirectory(homePath);
mLog.info("SDRTrunk - created application home directory [" +
- homePath.toString() + "]");
+ homePath.toString() + "]");
}
- catch (Exception e)
+ catch(Exception e)
{
homePath = null;
mLog.error("SDRTrunk: exception while creating SDRTrunk home " +
- "directory in the user's home directory", e);
+ "directory in the user's home directory", e);
}
}
@@ -492,7 +481,7 @@ public class SDRTrunk implements Listener
@Override
public void receive(TunerEvent event)
{
- if (event.getEvent() == TunerEvent.Event.REQUEST_MAIN_SPECTRAL_DISPLAY)
+ if(event.getEvent() == TunerEvent.Event.REQUEST_MAIN_SPECTRAL_DISPLAY)
{
mMainGui.setTitle(mTitle + " - " + event.getTuner().getName());
}
diff --git a/src/icon/IconManager.java b/src/icon/IconManager.java
index 5d61c1ac..ea29ee56 100644
--- a/src/icon/IconManager.java
+++ b/src/icon/IconManager.java
@@ -18,14 +18,12 @@
******************************************************************************/
package icon;
-import controller.ThreadPoolManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import properties.SystemProperties;
+import util.ThreadPool;
import javax.swing.*;
-import javax.swing.event.ListDataEvent;
-import javax.swing.event.ListDataListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.xml.bind.JAXBContext;
@@ -54,16 +52,14 @@ public class IconManager
private Path mIconBackupFilePath;
private Path mIconLockFilePath;
- private ThreadPoolManager mThreadPoolManager;
private IconEditor mIconEditor;
private IconTableModel mIconTableModel;
private AtomicBoolean mSavingIcons = new AtomicBoolean();
- private Map mResizedIcons = new HashMap<>();
+ private Map mResizedIcons = new HashMap<>();
- public IconManager(ThreadPoolManager threadPoolManager)
+ public IconManager()
{
- mThreadPoolManager = threadPoolManager;
}
/**
@@ -412,7 +408,7 @@ public class IconManager
{
if(mSavingIcons.compareAndSet(false, true))
{
- mThreadPoolManager.scheduleOnce(new IconSaveTask(), 2, TimeUnit.SECONDS);
+ ThreadPool.SCHEDULED.schedule(new IconSaveTask(), 2, TimeUnit.SECONDS);
}
}
diff --git a/src/instrument/gui/DecoderSelectionFrame.java b/src/instrument/gui/DecoderSelectionFrame.java
index 23239335..c79ad61c 100644
--- a/src/instrument/gui/DecoderSelectionFrame.java
+++ b/src/instrument/gui/DecoderSelectionFrame.java
@@ -1,83 +1,77 @@
package instrument.gui;
-import java.awt.Dimension;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-
-import javax.swing.JButton;
-import javax.swing.JDesktopPane;
-import javax.swing.JInternalFrame;
-
+import alias.AliasModel;
import audio.broadcast.BroadcastModel;
+import controller.channel.ChannelModel;
+import controller.channel.map.ChannelMapModel;
import module.decode.DecodeConfigurationEditor;
import net.miginfocom.swing.MigLayout;
import playlist.PlaylistManager;
import source.IControllableFileSource;
-import alias.AliasModel;
-import controller.ThreadPoolManager;
-import controller.channel.ChannelModel;
-import controller.channel.map.ChannelMapModel;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
public class DecoderSelectionFrame extends JInternalFrame
{
- private static final long serialVersionUID = 1L;
+ private static final long serialVersionUID = 1L;
- private DecodeConfigurationEditor mDecodeEditor = new DecodeConfigurationEditor( null );
- private PlaylistManager mPlaylistManager;
-
- private IControllableFileSource mSource;
- private JDesktopPane mDesktop;
-
- public DecoderSelectionFrame( JDesktopPane desktop,
- IControllableFileSource source )
- {
- ThreadPoolManager tpm = new ThreadPoolManager();
+ private DecodeConfigurationEditor mDecodeEditor = new DecodeConfigurationEditor(null);
+ private PlaylistManager mPlaylistManager;
- AliasModel aliasModel = new AliasModel();
- BroadcastModel broadcastModel = new BroadcastModel(tpm, null);
- ChannelModel channelModel = new ChannelModel();
- ChannelMapModel channelMapModel = new ChannelMapModel();
+ private IControllableFileSource mSource;
+ private JDesktopPane mDesktop;
- mPlaylistManager = new PlaylistManager( tpm, aliasModel, broadcastModel, channelModel, channelMapModel );
+ public DecoderSelectionFrame(JDesktopPane desktop,
+ IControllableFileSource source)
+ {
+ AliasModel aliasModel = new AliasModel();
+ BroadcastModel broadcastModel = new BroadcastModel(null);
+ ChannelModel channelModel = new ChannelModel();
+ ChannelMapModel channelMapModel = new ChannelMapModel();
- mDesktop = desktop;
- mSource = source;
-
- initGUI();
- }
-
- private void initGUI()
- {
- setLayout( new MigLayout( "", "[grow,fill]", "[][][grow,fill]" ) );
+ mPlaylistManager = new PlaylistManager(aliasModel, broadcastModel, channelModel, channelMapModel);
- setTitle( "Decoders" );
- setPreferredSize( new Dimension( 700, 450 ) );
- setSize( 700, 450 );
+ mDesktop = desktop;
+ mSource = source;
- setResizable( true );
- setClosable( true );
- setIconifiable( true );
- setMaximizable( false );
+ initGUI();
+ }
- add( mDecodeEditor, "wrap" );
-
- add( new AddDecoderButton(), "span" );
-
- }
-
- public class AddDecoderButton extends JButton
- {
- private static final long serialVersionUID = 1L;
+ private void initGUI()
+ {
+ setLayout(new MigLayout("", "[grow,fill]", "[][][grow,fill]"));
- public AddDecoderButton()
- {
- super( "Add" );
-
- addActionListener( new ActionListener()
- {
- @Override
- public void actionPerformed( ActionEvent arg0 )
- {
+ setTitle("Decoders");
+ setPreferredSize(new Dimension(700, 450));
+ setSize(700, 450);
+
+ setResizable(true);
+ setClosable(true);
+ setIconifiable(true);
+ setMaximizable(false);
+
+ add(mDecodeEditor, "wrap");
+
+ add(new AddDecoderButton(), "span");
+
+ }
+
+ public class AddDecoderButton extends JButton
+ {
+ private static final long serialVersionUID = 1L;
+
+ public AddDecoderButton()
+ {
+ super("Add");
+
+ addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent arg0)
+ {
// DecodeConfiguration config = mDecodeEditor.getDecodeConfig();
//
// if( config != null )
@@ -89,9 +83,9 @@ public class DecoderSelectionFrame extends JInternalFrame
//
// mDesktop.add( decoderFrame );
// }
- }
- } );
- }
- }
-
+ }
+ });
+ }
+ }
+
}
diff --git a/src/map/MapService.java b/src/map/MapService.java
index 38991881..a2150731 100644
--- a/src/map/MapService.java
+++ b/src/map/MapService.java
@@ -19,7 +19,6 @@
package map;
import alias.Alias;
-import controller.NamingThreadFactory;
import icon.IconManager;
import message.Message;
import sample.Listener;
@@ -28,9 +27,8 @@ import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Set;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
public class MapService implements Listener
{
@@ -39,12 +37,7 @@ public class MapService implements Listener
private static final Color sDEFAULT_COLOR = Color.BLACK;
- private final ScheduledExecutorService scheduler =
- Executors.newScheduledThreadPool(1,
- new NamingThreadFactory("map tile fetcher"));
-
- private ArrayList mListeners =
- new ArrayList();
+ private List mListeners = new ArrayList();
private HashMap mEntities =
new HashMap();
diff --git a/src/module/ProcessingChain.java b/src/module/ProcessingChain.java
index 2adc84f6..d8a13e9a 100644
--- a/src/module/ProcessingChain.java
+++ b/src/module/ProcessingChain.java
@@ -34,7 +34,6 @@ import channel.state.DecoderStateEvent.Event;
import channel.state.IDecoderStateEventListener;
import channel.state.IDecoderStateEventProvider;
import channel.state.State;
-import controller.NamingThreadFactory;
import controller.channel.Channel.ChannelType;
import controller.channel.ChannelEvent;
import controller.channel.IChannelEventListener;
@@ -69,11 +68,10 @@ import source.tuner.TunerChannelSource;
import source.tuner.frequency.FrequencyChangeEvent;
import source.tuner.frequency.IFrequencyChangeListener;
import source.tuner.frequency.IFrequencyChangeProvider;
+import util.ThreadPool;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -110,7 +108,6 @@ public class ProcessingChain implements IChannelEventListener
private Broadcaster mUnFilteredRealBufferBroadcaster = new Broadcaster<>();
private Broadcaster mSquelchStateBroadcaster = new Broadcaster<>();
- private ScheduledExecutorService mScheduledExecutorService;
private String mName;
private AtomicBoolean mRunning = new AtomicBoolean();
@@ -170,9 +167,6 @@ public class ProcessingChain implements IChannelEventListener
mModules.clear();
- mScheduledExecutorService.shutdownNow();
- mScheduledExecutorService = null;
-
mAudioPacketBroadcaster.dispose();
mCallEventBroadcaster.dispose();
mChannelEventBroadcaster.dispose();
@@ -180,11 +174,6 @@ public class ProcessingChain implements IChannelEventListener
mMessageBroadcaster.dispose();
mFilteredRealBufferBroadcaster.dispose();
mSquelchStateBroadcaster.dispose();
-
- if(mScheduledExecutorService != null)
- {
- mScheduledExecutorService.shutdownNow();
- }
}
/**
@@ -584,18 +573,12 @@ public class ProcessingChain implements IChannelEventListener
}
}
- if(mScheduledExecutorService == null)
- {
- mScheduledExecutorService = Executors.newScheduledThreadPool(
- 1, new NamingThreadFactory("channel " + mName));
- }
-
/* Start each of the modules */
for(Module module : mModules)
{
try
{
- module.start(mScheduledExecutorService);
+ module.start(ThreadPool.SCHEDULED);
}
catch(Exception e)
{
@@ -603,7 +586,7 @@ public class ProcessingChain implements IChannelEventListener
}
}
- mSource.start(mScheduledExecutorService);
+ mSource.start(ThreadPool.SCHEDULED);
}
else
{
diff --git a/src/playlist/PlaylistManager.java b/src/playlist/PlaylistManager.java
index e04cc477..0b3f50b0 100644
--- a/src/playlist/PlaylistManager.java
+++ b/src/playlist/PlaylistManager.java
@@ -21,7 +21,6 @@ import alias.AliasEvent;
import alias.AliasModel;
import audio.broadcast.BroadcastEvent;
import audio.broadcast.BroadcastModel;
-import controller.ThreadPoolManager;
import controller.channel.Channel.ChannelType;
import controller.channel.ChannelEvent;
import controller.channel.ChannelEventListener;
@@ -33,6 +32,7 @@ import org.slf4j.LoggerFactory;
import playlist.version1.PlaylistConverterV1ToV2;
import properties.SystemProperties;
import sample.Listener;
+import util.ThreadPool;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
@@ -51,7 +51,6 @@ public class PlaylistManager implements ChannelEventListener
{
private final static Logger mLog = LoggerFactory.getLogger(PlaylistManager.class);
- private ThreadPoolManager mThreadPoolManager;
private AliasModel mAliasModel;
private BroadcastModel mBroadcastModel;
private ChannelModel mChannelModel;
@@ -72,16 +71,10 @@ public class PlaylistManager implements ChannelEventListener
* Monitors playlist changes to automatically save configuration changes
* after they occur.
*
- * @param threadPoolManager
* @param channelModel
*/
- public PlaylistManager(ThreadPoolManager threadPoolManager,
- AliasModel aliasModel,
- BroadcastModel broadcastModel,
- ChannelModel channelModel,
- ChannelMapModel channelMapModel)
+ public PlaylistManager(AliasModel aliasModel, BroadcastModel broadcastModel, ChannelModel channelModel, ChannelMapModel channelMapModel)
{
- mThreadPoolManager = threadPoolManager;
mAliasModel = aliasModel;
mBroadcastModel = broadcastModel;
mChannelModel = channelModel;
@@ -421,7 +414,7 @@ public class PlaylistManager implements ChannelEventListener
{
if(mPlaylistSavePending.compareAndSet(false, true))
{
- mThreadPoolManager.scheduleOnce(new PlaylistSaveTask(), 2, TimeUnit.SECONDS);
+ ThreadPool.SCHEDULED.schedule(new PlaylistSaveTask(), 2, TimeUnit.SECONDS);
}
}
}
diff --git a/src/properties/SystemProperties.java b/src/properties/SystemProperties.java
index aea40331..c34d2a0d 100644
--- a/src/properties/SystemProperties.java
+++ b/src/properties/SystemProperties.java
@@ -20,11 +20,11 @@ package properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import util.ThreadPool;
import java.awt.*;
import java.io.BufferedReader;
import java.io.FileInputStream;
-import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -34,8 +34,6 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Properties;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -54,7 +52,6 @@ public class SystemProperties
private Path mPropertiesPath;
private String mApplicationName;
private AtomicBoolean mSavePending = new AtomicBoolean();
- private ScheduledExecutorService mScheduledExecutorService;
private SystemProperties()
{
@@ -83,12 +80,7 @@ public class SystemProperties
{
if(mSavePending.compareAndSet(false, true))
{
- if(mScheduledExecutorService == null)
- {
- mScheduledExecutorService = Executors.newScheduledThreadPool(1);
- }
-
- mScheduledExecutorService.schedule(new SavePropertiesTask(), 2, TimeUnit.SECONDS);
+ ThreadPool.SCHEDULED.schedule(new SavePropertiesTask(), 2, TimeUnit.SECONDS);
}
}
diff --git a/src/record/RecorderManager.java b/src/record/RecorderManager.java
index c42019bb..871fe914 100644
--- a/src/record/RecorderManager.java
+++ b/src/record/RecorderManager.java
@@ -19,13 +19,13 @@ package record;
import audio.AudioPacket;
import channel.metadata.Metadata;
-import controller.ThreadPoolManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import properties.SystemProperties;
import record.wave.ComplexBufferWaveRecorder;
import record.wave.RealBufferWaveRecorder;
import sample.Listener;
+import util.ThreadPool;
import java.io.File;
import java.util.HashMap;
@@ -39,22 +39,18 @@ public class RecorderManager implements Listener
private Map mRecorders = new HashMap<>();
- private ThreadPoolManager mThreadPoolManager;
-
private boolean mCanStartNewRecorders = true;
/**
* Manages all audio recording for all processing channels. Reconstructs audio streams and distributes channel
* audio to each of the recorders, starting and stopping the recorders as needed.
*/
- public RecorderManager(ThreadPoolManager threadPoolManager)
+ public RecorderManager()
{
- mThreadPoolManager = threadPoolManager;
}
public void dispose()
{
- mThreadPoolManager = null;
}
@Override
@@ -91,7 +87,7 @@ public class RecorderManager implements Listener
{
recorder = new RealBufferWaveRecorder(AUDIO_SAMPLE_RATE, filePrefix);
- recorder.start(mThreadPoolManager.getScheduledExecutorService());
+ recorder.start(ThreadPool.SCHEDULED);
recorder.receive(audioPacket.getAudioBuffer());
mRecorders.put(identifier, recorder);
diff --git a/src/record/mp3/MP3Recorder.java b/src/record/mp3/MP3Recorder.java
index 747496ce..cc9dc7e8 100644
--- a/src/record/mp3/MP3Recorder.java
+++ b/src/record/mp3/MP3Recorder.java
@@ -19,37 +19,15 @@
package record.mp3;
import audio.AudioPacket;
-import audio.IAudioPacketListener;
-import audio.broadcast.BroadcastModel;
import audio.convert.MP3AudioConverter;
-import module.Module;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import properties.SystemProperties;
import record.AudioRecorder;
-import record.wave.AudioPacketMonoWaveReader;
-import sample.Listener;
-import util.TimeStamp;
-import java.io.ByteArrayInputStream;
-import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.InputStream;
import java.io.OutputStream;
-import java.nio.file.DirectoryStream;
-import java.nio.file.Files;
import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
-import java.util.concurrent.Executors;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Consumer;
/**
* MP3 recorder for converting 8 kHz PCM audio packets to MP3 and writing to .mp3 file.
diff --git a/src/settings/SettingsManager.java b/src/settings/SettingsManager.java
index 3906504b..87d65bce 100644
--- a/src/settings/SettingsManager.java
+++ b/src/settings/SettingsManager.java
@@ -17,7 +17,6 @@
******************************************************************************/
package settings;
-import controller.ThreadPoolManager;
import org.jdesktop.swingx.mapviewer.GeoPosition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -27,6 +26,7 @@ import settings.ColorSetting.ColorSettingName;
import source.recording.RecordingConfiguration;
import source.tuner.configuration.TunerConfigurationEvent;
import source.tuner.configuration.TunerConfigurationModel;
+import util.ThreadPool;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
@@ -54,18 +54,15 @@ public class SettingsManager implements Listener
private Settings mSettings = new Settings();
private List mListeners = new ArrayList<>();
private TunerConfigurationModel mTunerConfigurationModel;
- private ThreadPoolManager mThreadPoolManager;
private boolean mLoadingSettings = false;
private AtomicBoolean mSettingsSavePending = new AtomicBoolean();
- public SettingsManager(ThreadPoolManager threadPoolManager,
- TunerConfigurationModel tunerConfigurationModel)
+ public SettingsManager(TunerConfigurationModel tunerConfigurationModel)
{
//TODO: move settings into a SettingsModel
//and update this class to only provide loading, saving, and model
//change detection producing a save.
- mThreadPoolManager = threadPoolManager;
mTunerConfigurationModel = tunerConfigurationModel;
//Register for tuner config events so that we can save the settings
@@ -481,8 +478,7 @@ public class SettingsManager implements Listener
{
if(mSettingsSavePending.compareAndSet(false, true))
{
- mThreadPoolManager.scheduleOnce(new SettingsSaveTask(),
- 2, TimeUnit.SECONDS);
+ ThreadPool.SCHEDULED.schedule(new SettingsSaveTask(), 2, TimeUnit.SECONDS);
}
}
}
diff --git a/src/source/SourceManager.java b/src/source/SourceManager.java
index cc010d06..182bbeb2 100644
--- a/src/source/SourceManager.java
+++ b/src/source/SourceManager.java
@@ -1,19 +1,20 @@
/*******************************************************************************
- * SDR Trunk
- * Copyright (C) 2014 Dennis Sheirer
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
+ * sdrtrunk
+ * Copyright (C) 2014-2017 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 source;
@@ -24,63 +25,60 @@ import source.mixer.MixerManager;
import source.recording.RecordingSourceManager;
import source.tuner.TunerManager;
import source.tuner.TunerModel;
-import controller.ThreadPoolManager;
-public class SourceManager
+public class SourceManager
{
- private MixerManager mMixerManager;
- private RecordingSourceManager mRecordingSourceManager;
- private TunerManager mTunerManager;
- private TunerModel mTunerModel;
+ private MixerManager mMixerManager;
+ private RecordingSourceManager mRecordingSourceManager;
+ private TunerManager mTunerManager;
+ private TunerModel mTunerModel;
- public SourceManager( TunerModel tunerModel,
- SettingsManager settingsManager,
- ThreadPoolManager threadPoolManager )
- {
- mTunerModel = tunerModel;
- mMixerManager = new MixerManager();
- mRecordingSourceManager = new RecordingSourceManager( settingsManager );
- mTunerManager = new TunerManager( mMixerManager, tunerModel, threadPoolManager );
-
- //TODO: change mixer & recording managers to be models and hand them
- //in via the constructor. Perform loading outside of this class.
- }
-
- public MixerManager getMixerManager()
- {
- return mMixerManager;
- }
+ public SourceManager(TunerModel tunerModel, SettingsManager settingsManager)
+ {
+ mTunerModel = tunerModel;
+ mMixerManager = new MixerManager();
+ mRecordingSourceManager = new RecordingSourceManager(settingsManager);
+ mTunerManager = new TunerManager(mMixerManager, tunerModel);
- public RecordingSourceManager getRecordingSourceManager()
- {
- return mRecordingSourceManager;
- }
-
- public TunerManager getTunerManager()
- {
- return mTunerManager;
- }
-
- public Source getSource( SourceConfiguration config, int bandwidth )
- throws SourceException
- {
- Source retVal = null;
+ //TODO: change mixer & recording managers to be models and hand them
+ //in via the constructor. Perform loading outside of this class.
+ }
- switch( config.getSourceType() )
- {
- case MIXER:
- retVal = mMixerManager.getSource( config );
- break;
- case TUNER:
- retVal = mTunerModel.getSource( (SourceConfigTuner)config, bandwidth );
- break;
- case RECORDING:
- retVal = mRecordingSourceManager.getSource( config, bandwidth );
- case NONE:
- default:
- break;
- }
-
- return retVal;
- }
+ public MixerManager getMixerManager()
+ {
+ return mMixerManager;
+ }
+
+ public RecordingSourceManager getRecordingSourceManager()
+ {
+ return mRecordingSourceManager;
+ }
+
+ public TunerManager getTunerManager()
+ {
+ return mTunerManager;
+ }
+
+ public Source getSource(SourceConfiguration config, int bandwidth)
+ throws SourceException
+ {
+ Source retVal = null;
+
+ switch(config.getSourceType())
+ {
+ case MIXER:
+ retVal = mMixerManager.getSource(config);
+ break;
+ case TUNER:
+ retVal = mTunerModel.getSource((SourceConfigTuner) config, bandwidth);
+ break;
+ case RECORDING:
+ retVal = mRecordingSourceManager.getSource(config, bandwidth);
+ case NONE:
+ default:
+ break;
+ }
+
+ return retVal;
+ }
}
diff --git a/src/source/tuner/TunerChannelSource.java b/src/source/tuner/TunerChannelSource.java
index 1e89e1b4..4a00107e 100644
--- a/src/source/tuner/TunerChannelSource.java
+++ b/src/source/tuner/TunerChannelSource.java
@@ -1,22 +1,38 @@
/*******************************************************************************
* 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
******************************************************************************/
package source.tuner;
+import dsp.filter.FilterFactory;
+import dsp.filter.Window.WindowType;
+import dsp.filter.cic.ComplexPrimeCICDecimate;
+import dsp.mixer.Oscillator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import sample.Buffer;
+import sample.Listener;
+import sample.complex.Complex;
+import sample.complex.ComplexBuffer;
+import source.ComplexSource;
+import source.SourceException;
+import source.tuner.frequency.FrequencyChangeEvent;
+import source.tuner.frequency.FrequencyChangeEvent.Event;
+import source.tuner.frequency.IFrequencyChangeProcessor;
+
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedTransferQueue;
@@ -26,371 +42,351 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import sample.Buffer;
-import sample.Listener;
-import sample.complex.Complex;
-import sample.complex.ComplexBuffer;
-import source.ComplexSource;
-import source.SourceException;
-import source.tuner.frequency.FrequencyChangeEvent;
-import source.tuner.frequency.FrequencyChangeEvent.Event;
-import source.tuner.frequency.IFrequencyChangeProcessor;
-import dsp.filter.FilterFactory;
-import dsp.filter.Window.WindowType;
-import dsp.filter.cic.ComplexPrimeCICDecimate;
-import dsp.mixer.Oscillator;
-
public class TunerChannelSource extends ComplexSource
- implements IFrequencyChangeProcessor, Listener
+ implements IFrequencyChangeProcessor, Listener
{
- private final static Logger mLog =
- LoggerFactory.getLogger( TunerChannelSource.class );
-
- private static int CHANNEL_RATE = 48000;
- private static int CHANNEL_PASS_FREQUENCY = 12000;
-
- private LinkedTransferQueue mBuffer =
- new LinkedTransferQueue();
- private Tuner mTuner;
- private TunerChannel mTunerChannel;
- private Oscillator mMixer;
- private ComplexPrimeCICDecimate mDecimationFilter;
- private Listener mListener;
- private IFrequencyChangeProcessor mFrequencyChangeProcessor;
- private ScheduledFuture> mTaskHandle;
+ private final static Logger mLog =
+ LoggerFactory.getLogger(TunerChannelSource.class);
- private long mTunerFrequency = 0;
- private int mTunerSampleRate;
- private int mChannelFrequencyCorrection = 0;
-
- private DecimationProcessor mDecimationProcessor = new DecimationProcessor();
-
- private AtomicBoolean mRunning = new AtomicBoolean();
- private boolean mExpended = false;
-
- /**
- * Provides a Digital Drop Channel (DDC) to decimate the IQ output from a
- * tuner down to a 48 kHz IQ channel rate.
- *
- * Note: this class can only be used once (started and stopped) and a new
- * tuner channel source must be requested from the tuner once this object
- * has been stopped. This is because channels are managed dynamically and
- * center tuned frequency may have changed since this source was obtained
- * and thus the tuner might no longer be able to source this channel once it
- * has been stopped.
- *
- * @param tuner to obtain wideband IQ samples from
- * @param tunerChannel specifying the center frequency for the DDC
- * @throws RejectedExecutionException if the thread pool manager cannot
- * accept the decimation processing task
- * @throws SourceException if the tuner has an issue providing IQ samples
- */
- public TunerChannelSource( Tuner tuner, TunerChannel tunerChannel )
- throws RejectedExecutionException, SourceException
+ private static int CHANNEL_RATE = 48000;
+ private static int CHANNEL_PASS_FREQUENCY = 12000;
+
+ private LinkedTransferQueue mBuffer =
+ new LinkedTransferQueue();
+ private Tuner mTuner;
+ private TunerChannel mTunerChannel;
+ private Oscillator mMixer;
+ private ComplexPrimeCICDecimate mDecimationFilter;
+ private Listener mListener;
+ private IFrequencyChangeProcessor mFrequencyChangeProcessor;
+ private ScheduledFuture> mTaskHandle;
+
+ private long mTunerFrequency = 0;
+ private int mTunerSampleRate;
+ private int mChannelFrequencyCorrection = 0;
+
+ private DecimationProcessor mDecimationProcessor = new DecimationProcessor();
+
+ private AtomicBoolean mRunning = new AtomicBoolean();
+ private boolean mExpended = false;
+
+ /**
+ * Provides a Digital Drop Channel (DDC) to decimate the IQ output from a
+ * tuner down to a 48 kHz IQ channel rate.
+ *
+ * Note: this class can only be used once (started and stopped) and a new
+ * tuner channel source must be requested from the tuner once this object
+ * has been stopped. This is because channels are managed dynamically and
+ * center tuned frequency may have changed since this source was obtained
+ * and thus the tuner might no longer be able to source this channel once it
+ * has been stopped.
+ *
+ * @param tuner to obtain wideband IQ samples from
+ * @param tunerChannel specifying the center frequency for the DDC
+ * @throws RejectedExecutionException if the thread pool manager cannot
+ * accept the decimation processing task
+ * @throws SourceException if the tuner has an issue providing IQ samples
+ */
+ public TunerChannelSource(Tuner tuner, TunerChannel tunerChannel)
+ throws RejectedExecutionException, SourceException
{
- mTuner = tuner;
- mTuner.getTunerController().addListener( (IFrequencyChangeProcessor)this );
-
- mTunerChannel = tunerChannel;
+ mTuner = tuner;
+ mTuner.getTunerController().addListener((IFrequencyChangeProcessor) this);
+
+ mTunerChannel = tunerChannel;
+
+ mTunerFrequency = mTuner.getTunerController().getFrequency();
- mTunerFrequency = mTuner.getTunerController().getFrequency();
-
/* Setup the frequency translator to the current source frequency */
- long frequencyOffset = mTunerFrequency - mTunerChannel.getFrequency();
-
- mMixer = new Oscillator( frequencyOffset,
- mTuner.getTunerController().getSampleRate() );
+ long frequencyOffset = mTunerFrequency - mTunerChannel.getFrequency();
+
+ mMixer = new Oscillator(frequencyOffset,
+ mTuner.getTunerController().getSampleRate());
/* Fire a sample rate change event to setup the decimation chain */
- frequencyChanged( new FrequencyChangeEvent(
- Event.NOTIFICATION_SAMPLE_RATE_CHANGE,
- mTuner.getTunerController().getSampleRate() ) );
+ frequencyChanged(new FrequencyChangeEvent(
+ Event.NOTIFICATION_SAMPLE_RATE_CHANGE,
+ mTuner.getTunerController().getSampleRate()));
}
-
-
- public void start( ScheduledExecutorService executor )
- {
- if( mExpended )
- {
- throw new IllegalStateException( "Attempt to re-start an expended "
- + "tuner channel source. TunerChannelSource objects can only "
- + "be used once. " );
- }
-
- if( mRunning.compareAndSet( false, true ))
- {
+
+
+ public void start(ScheduledExecutorService executor)
+ {
+ if(mExpended)
+ {
+ throw new IllegalStateException("Attempt to re-start an expended "
+ + "tuner channel source. TunerChannelSource objects can only "
+ + "be used once. ");
+ }
+
+ if(mRunning.compareAndSet(false, true))
+ {
/* Schedule the decimation task to run every 10 ms (100 iterations/second) */
- mTaskHandle = executor.scheduleAtFixedRate( mDecimationProcessor,
- 0, 10, TimeUnit.MILLISECONDS );
+ mTaskHandle = executor.scheduleAtFixedRate(mDecimationProcessor,
+ 0, 10, TimeUnit.MILLISECONDS);
/* Finally, register to receive samples from the tuner */
- mTuner.addListener( (Listener)this );
- }
- else
- {
- mLog.warn( "Attempt to start() and already running tuner channel source was ignored" );
- }
- }
+ mTuner.addListener((Listener) this);
+ }
+ else
+ {
+ mLog.warn("Attempt to start() and already running tuner channel source was ignored");
+ }
+ }
- @Override
- public void reset()
- {
- }
+ @Override
+ public void reset()
+ {
+ }
- @Override
- public void stop()
- {
- if( mRunning.compareAndSet( true, false ))
- {
- mTuner.releaseChannel( this );
- mDecimationProcessor.shutdown();
-
- if( mTaskHandle != null )
- {
- mTaskHandle.cancel( true );
- mTaskHandle = null;
- }
-
- mBuffer.clear();
-
- mExpended = true;
- }
- else
- {
- mLog.warn( "Attempt to stop() and already stopped tuner channel source was ignored" );
- }
- }
+ @Override
+ public void stop()
+ {
+ if(mRunning.compareAndSet(true, false))
+ {
+ mTuner.releaseChannel(this);
+ mDecimationProcessor.shutdown();
+
+ if(mTaskHandle != null)
+ {
+ mTaskHandle.cancel(true);
+ mTaskHandle = null;
+ }
+
+ mBuffer.clear();
+
+ mExpended = true;
+ }
+ else
+ {
+ mLog.warn("Attempt to stop() and already stopped tuner channel source was ignored");
+ }
+ }
- @Override
+ @Override
public void dispose()
{
- if( !mRunning.get() )
- {
+ if(!mRunning.get())
+ {
/* Tell the tuner to release/unregister our resources */
- mTuner.getTunerController().removeListener( this );
- mTuner = null;
- mTunerChannel = null;
- mBuffer = null;
- mFrequencyChangeProcessor = null;
- mListener = null;
- mMixer = null;
- mDecimationFilter.dispose();
- mDecimationFilter = null;
- }
- }
-
- public Tuner getTuner()
- {
- return mTuner;
- }
-
- public TunerChannel getTunerChannel()
- {
- return mTunerChannel;
- }
-
- @Override
- public void receive( ComplexBuffer buffer )
- {
- if( mRunning.get() )
- {
- mBuffer.add( buffer );
- }
+ mTuner.getTunerController().removeListener(this);
+// mTuner = null;
+// mTunerChannel = null;
+// mBuffer = null;
+// mFrequencyChangeProcessor = null;
+// mListener = null;
+// mMixer = null;
+// mDecimationFilter.dispose();
+// mDecimationFilter = null;
+ }
}
- public void setFrequencyChangeListener( IFrequencyChangeProcessor processor )
+ public Tuner getTuner()
{
- mFrequencyChangeProcessor = processor;
+ return mTuner;
}
- @Override
- public void setListener( Listener listener )
- {
+ public TunerChannel getTunerChannel()
+ {
+ return mTunerChannel;
+ }
+
+ @Override
+ public void receive(ComplexBuffer buffer)
+ {
+ if(mRunning.get())
+ {
+ mBuffer.add(buffer);
+ }
+ }
+
+ public void setFrequencyChangeListener(IFrequencyChangeProcessor processor)
+ {
+ mFrequencyChangeProcessor = processor;
+ }
+
+ @Override
+ public void setListener(Listener listener)
+ {
/* Save a pointer to the listener so that if we have to change the
* decimation filter, we can re-add the listener */
- mListener = listener;
-
- mDecimationFilter.setListener( listener );
- }
+ mListener = listener;
- @Override
- public void removeListener( Listener listener )
- {
- mDecimationFilter.removeListener();
- }
-
- /**
- * Handler for frequency change events received from the tuner and channel
- * frequency correction events received from the channel consumer/listener
- */
- @Override
- public void frequencyChanged( FrequencyChangeEvent event ) throws SourceException
- {
- // Echo the event to the registered event listener
- if( mFrequencyChangeProcessor != null )
- {
- mFrequencyChangeProcessor.frequencyChanged( event );
- }
-
- switch( event.getEvent() )
- {
- case NOTIFICATION_FREQUENCY_CHANGE:
- mTunerFrequency = event.getValue().longValue();
- updateMixerFrequencyOffset();
- break;
- case REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE:
- mChannelFrequencyCorrection = event.getValue().intValue();
-
- updateMixerFrequencyOffset();
-
- if( mFrequencyChangeProcessor != null )
- {
- mFrequencyChangeProcessor.frequencyChanged(
- new FrequencyChangeEvent(
- Event.NOTIFICATION_CHANNEL_FREQUENCY_CORRECTION_CHANGE,
- mChannelFrequencyCorrection ) );
- }
- break;
- case NOTIFICATION_SAMPLE_RATE_CHANGE:
- int sampleRate = event.getValue().intValue();
-
- if( mTunerSampleRate != sampleRate )
- {
- mMixer.setSampleRate( sampleRate );
-
- /* Get new decimation filter */
- mDecimationFilter = FilterFactory
- .getDecimationFilter( sampleRate,
- CHANNEL_RATE,
- 1, //Order
- CHANNEL_PASS_FREQUENCY,
- 60, //dB attenuation
- WindowType.HAMMING );
-
- /* re-add the original output listener */
- mDecimationFilter.setListener( mListener );
-
- mTunerSampleRate = sampleRate;
- }
- break;
- default:
- break;
- }
+ mDecimationFilter.setListener(listener);
}
- /**
- * Calculates the local mixer frequency offset from the tuned frequency,
- * channel's requested frequency, and channel frequency correction.
- */
- private void updateMixerFrequencyOffset()
- {
- long offset = mTunerFrequency -
- mTunerChannel.getFrequency() -
- mChannelFrequencyCorrection;
+ @Override
+ public void removeListener(Listener listener)
+ {
+ mDecimationFilter.removeListener();
+ }
- mMixer.setFrequency( offset );
- }
+ /**
+ * Handler for frequency change events received from the tuner and channel
+ * frequency correction events received from the channel consumer/listener
+ */
+ @Override
+ public void frequencyChanged(FrequencyChangeEvent event) throws SourceException
+ {
+ // Echo the event to the registered event listener
+ if(mFrequencyChangeProcessor != null)
+ {
+ mFrequencyChangeProcessor.frequencyChanged(event);
+ }
+
+ switch(event.getEvent())
+ {
+ case NOTIFICATION_FREQUENCY_CHANGE:
+ mTunerFrequency = event.getValue().longValue();
+ updateMixerFrequencyOffset();
+ break;
+ case REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE:
+ mChannelFrequencyCorrection = event.getValue().intValue();
+
+ updateMixerFrequencyOffset();
+
+ if(mFrequencyChangeProcessor != null)
+ {
+ mFrequencyChangeProcessor.frequencyChanged(
+ new FrequencyChangeEvent(
+ Event.NOTIFICATION_CHANNEL_FREQUENCY_CORRECTION_CHANGE,
+ mChannelFrequencyCorrection));
+ }
+ break;
+ case NOTIFICATION_SAMPLE_RATE_CHANGE:
+ int sampleRate = event.getValue().intValue();
+
+ if(mTunerSampleRate != sampleRate)
+ {
+ mMixer.setSampleRate(sampleRate);
+
+ /* Get new decimation filter */
+ mDecimationFilter = FilterFactory
+ .getDecimationFilter(sampleRate,
+ CHANNEL_RATE,
+ 1, //Order
+ CHANNEL_PASS_FREQUENCY,
+ 60, //dB attenuation
+ WindowType.HAMMING);
+
+ /* re-add the original output listener */
+ mDecimationFilter.setListener(mListener);
+
+ mTunerSampleRate = sampleRate;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Calculates the local mixer frequency offset from the tuned frequency,
+ * channel's requested frequency, and channel frequency correction.
+ */
+ private void updateMixerFrequencyOffset()
+ {
+ long offset = mTunerFrequency -
+ mTunerChannel.getFrequency() -
+ mChannelFrequencyCorrection;
+
+ mMixer.setFrequency(offset);
+ }
public int getSampleRate() throws SourceException
{
- return CHANNEL_RATE;
+ return CHANNEL_RATE;
}
public long getFrequency() throws SourceException
{
- return mTunerChannel.getFrequency();
+ return mTunerChannel.getFrequency();
}
-
+
/**
* Decimates an inbound buffer of I/Q samples from the source down to the
* standard 48000 channel sample rate
*/
- public class DecimationProcessor implements Runnable
- {
- private boolean mProcessing = true;
- private List mSampleBuffers = new ArrayList();
+ public class DecimationProcessor implements Runnable
+ {
+ private boolean mProcessing = true;
+ private List mSampleBuffers = new ArrayList();
- public void shutdown()
- {
- mProcessing = false;
- }
-
- @Override
+ public void shutdown()
+ {
+ mProcessing = false;
+ }
+
+ @Override
public void run()
{
/* General exception handler so that any errors won't kill the
* decimation thread and cause the input buffers to fill up and
* run the program out of memory */
- try
- {
- if( mProcessing )
- {
- {
-// long start = System.currentTimeMillis();
-
- mBuffer.drainTo( mSampleBuffers, 8 );
-
- for( Buffer buffer: mSampleBuffers )
- {
+ try
+ {
+ if(mProcessing)
+ {
+ {
+ mBuffer.drainTo(mSampleBuffers, 8);
+
+ for(Buffer buffer : mSampleBuffers)
+ {
/* Check to see if we've been shutdown */
- if( !mProcessing )
- {
- mBuffer.clear();
- return;
- }
- else
- {
- float[] samples = buffer.getSamples();
+ if(!mProcessing)
+ {
+ mBuffer.clear();
+ return;
+ }
+ else
+ {
+ float[] samples = buffer.getSamples();
/* We make a copy of the buffer so that we don't affect
* anyone else that is using the same buffer, like other
* channels or the spectral display */
- float[] translated = new float[ samples.length ];
+ float[] translated = new float[samples.length];
/* Perform frequency translation */
- for( int x = 0; x < samples.length; x += 2 )
- {
- mMixer.rotate();
-
- translated[ x ] = Complex.multiplyInphase(
- samples[ x ], samples[ x + 1 ], mMixer.inphase(), mMixer.quadrature() );
+ for(int x = 0; x < samples.length; x += 2)
+ {
+ mMixer.rotate();
- translated[ x + 1 ] = Complex.multiplyQuadrature(
- samples[ x ], samples[ x + 1 ], mMixer.inphase(), mMixer.quadrature() );
- }
-
- if( mProcessing && mDecimationFilter != null )
- {
- mDecimationFilter.receive( new ComplexBuffer( translated ) );
- }
- }
- }
-
-// mLog.debug( "Processed [" + mSampleBuffers.size() + "] in " + ( System.currentTimeMillis() - start ) );
-
- mSampleBuffers.clear();
- }
- }
- }
- catch( Exception e )
- {
+ translated[x] = Complex.multiplyInphase(
+ samples[x], samples[x + 1], mMixer.inphase(), mMixer.quadrature());
+
+ translated[x + 1] = Complex.multiplyQuadrature(
+ samples[x], samples[x + 1], mMixer.inphase(), mMixer.quadrature());
+ }
+
+ if(mProcessing)
+ {
+ final ComplexPrimeCICDecimate filter = mDecimationFilter;
+ filter.receive(new ComplexBuffer(translated));
+ }
+ }
+ }
+
+ mSampleBuffers.clear();
+ }
+ }
+ }
+ catch(Exception e)
+ {
/* Only log the stack trace if we're still processing */
- if( mProcessing )
- {
- mLog.error( "Error encountered during decimation process", e );
- }
- }
+ if(mProcessing)
+ {
+ mLog.error("Error encountered during decimation process", e);
+ }
+ }
/* Check to see if we've been shutdown */
- if( !mProcessing )
- {
- mBuffer.clear();
- mSampleBuffers.clear();
- }
+ if(!mProcessing)
+ {
+ mBuffer.clear();
+ mSampleBuffers.clear();
+ }
}
- }
+ }
}
diff --git a/src/source/tuner/TunerManager.java b/src/source/tuner/TunerManager.java
index 2cc230f0..0c82b839 100644
--- a/src/source/tuner/TunerManager.java
+++ b/src/source/tuner/TunerManager.java
@@ -1,31 +1,29 @@
/*******************************************************************************
- * 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
+ * sdrtrunk
+ * Copyright (C) 2014-2017 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 source.tuner;
-import java.util.Collection;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.usb4java.Device;
import org.usb4java.DeviceDescriptor;
import org.usb4java.DeviceList;
import org.usb4java.LibUsb;
-
import source.SourceException;
import source.mixer.MixerManager;
import source.tuner.airspy.AirspyTuner;
@@ -39,437 +37,424 @@ import source.tuner.rtl.RTL2832Tuner;
import source.tuner.rtl.RTL2832TunerController;
import source.tuner.rtl.e4k.E4KTunerController;
import source.tuner.rtl.r820t.R820TTunerController;
-import controller.ThreadPoolManager;
+
+import java.util.Collection;
public class TunerManager
{
- private final static Logger mLog =
- LoggerFactory.getLogger( TunerManager.class );
+ private final static Logger mLog =
+ LoggerFactory.getLogger(TunerManager.class);
+
+ private MixerManager mMixerManager;
+ private TunerModel mTunerModel;
+
+ public TunerManager(MixerManager mixerManager, TunerModel tunerModel)
+ {
+ mMixerManager = mixerManager;
+ mTunerModel = tunerModel;
+
+ initTuners();
+ }
- private MixerManager mMixerManager;
- private TunerModel mTunerModel;
- private ThreadPoolManager mThreadPoolManager;
-
- public TunerManager( MixerManager mixerManager,
- TunerModel tunerModel,
- ThreadPoolManager threadPoolManager )
- {
- mMixerManager = mixerManager;
- mTunerModel = tunerModel;
- mThreadPoolManager = threadPoolManager;
-
- initTuners();
- }
-
/**
* Performs cleanup of USB related issues
*/
public void dispose()
{
- LibUsb.exit( null );
+ LibUsb.exit(null);
}
/**
* Loads all USB tuners and USB/Mixer tuner devices
*/
- private void initTuners()
- {
- DeviceList deviceList = new DeviceList();
+ private void initTuners()
+ {
+ DeviceList deviceList = new DeviceList();
- int result = LibUsb.init( null );
+ int result = LibUsb.init(null);
- if( result != LibUsb.SUCCESS )
- {
- mLog.error( "unable to initialize libusb [" +
- LibUsb.errorName( result ) + "]" );
- }
- else
- {
- mLog.info( "LibUSB API Version: " + LibUsb.getApiVersion() );
- mLog.info( "LibUSB Version: " + LibUsb.getVersion() );
-
- result = LibUsb.getDeviceList( null, deviceList );
-
- if( result < 0 )
- {
- mLog.error( "unable to get device list from libusb [" + result + " / " +
- LibUsb.errorName( result ) + "]" );
- }
- else
- {
- mLog.info( "discovered [" + result + "] attached USB devices" );
- }
- }
+ if(result != LibUsb.SUCCESS)
+ {
+ mLog.error("unable to initialize libusb [" +
+ LibUsb.errorName(result) + "]");
+ }
+ else
+ {
+ mLog.info("LibUSB API Version: " + LibUsb.getApiVersion());
+ mLog.info("LibUSB Version: " + LibUsb.getVersion());
- for( Device device: deviceList )
- {
- DeviceDescriptor descriptor = new DeviceDescriptor();
-
- result = LibUsb.getDeviceDescriptor( device, descriptor );
-
- if( result != LibUsb.SUCCESS )
- {
- mLog.error( "unable to read device descriptor [" +
- LibUsb.errorName( result ) + "]" );
- }
- else
- {
- TunerInitStatus status = initTuner( device, descriptor );
+ result = LibUsb.getDeviceList(null, deviceList);
- StringBuilder sb = new StringBuilder();
-
- sb.append( "usb device [" );
- sb.append( String.format( "%04X", descriptor.idVendor() ) );
- sb.append( ":" );
- sb.append( String.format( "%04X", descriptor.idProduct() ) );
-
- if( status.isLoaded() )
- {
- Tuner tuner = status.getTuner();
-
- try
- {
- mTunerModel.addTuner( tuner );
- sb.append( "] LOADED: " );
- sb.append( tuner.toString() );
- }
- catch( Exception e )
- {
- sb.append( "] NOT LOADED: " );
- sb.append( status.getInfo() );
- sb.append( " Error:" + e.getMessage() );
- }
- }
- else
- {
- sb.append( "] NOT LOADED: " );
- sb.append( status.getInfo() );
- }
-
- mLog.info( sb.toString() );
- }
- }
-
- LibUsb.freeDeviceList( deviceList, true );
- }
-
- private TunerInitStatus initTuner( Device device,
- DeviceDescriptor descriptor )
- {
- if( device != null && descriptor != null )
- {
- TunerClass tunerClass = TunerClass.valueOf( descriptor.idVendor(),
- descriptor.idProduct() );
-
- switch( tunerClass )
- {
- case AIRSPY:
- return initAirspyTuner( device, descriptor );
- case ETTUS_USRP_B100:
- return initEttusB100Tuner( device, descriptor );
- case FUNCUBE_DONGLE_PRO:
- return initFuncubeProTuner( device, descriptor );
- case FUNCUBE_DONGLE_PRO_PLUS:
- return initFuncubeProPlusTuner( device, descriptor );
- case HACKRF_ONE:
- case RAD1O:
- return initHackRFTuner( device, descriptor );
- case COMPRO_VIDEOMATE_U620F:
- case COMPRO_VIDEOMATE_U650F:
- case COMPRO_VIDEOMATE_U680F:
- case GENERIC_2832:
- case GENERIC_2838:
- case DEXATEK_5217_DVBT:
- case DEXATEK_DIGIVOX_MINI_II_REV3:
- case DEXATEK_LOGILINK_VG002A:
- case GIGABYTE_GTU7300:
- case GTEK_T803:
- case LIFEVIEW_LV5T_DELUXE:
- case MYGICA_TD312:
- case PEAK_102569AGPK:
- case PROLECTRIX_DV107669:
- case SVEON_STV20:
- case TERRATEC_CINERGY_T_REV1:
- case TERRATEC_CINERGY_T_REV3:
- case TERRATEC_NOXON_REV1_B3:
- case TERRATEC_NOXON_REV1_B4:
- case TERRATEC_NOXON_REV1_B7:
- case TERRATEC_NOXON_REV1_C6:
- case TERRATEC_NOXON_REV2:
- case TERRATEC_T_STICK_PLUS:
- case TWINTECH_UT40:
- case ZAAPA_ZTMINDVBZP:
- return initRTL2832Tuner( tunerClass, device, descriptor );
- case UNKNOWN:
- default:
- break;
- }
- }
-
- return new TunerInitStatus( null, "Unknown Device" );
- }
-
- private TunerInitStatus initAirspyTuner( Device device,
- DeviceDescriptor descriptor )
- {
- try
- {
- AirspyTunerController airspyController =
- new AirspyTunerController( device, mThreadPoolManager );
-
- airspyController.init();
-
- AirspyTuner tuner = new AirspyTuner( airspyController );
-
- return new TunerInitStatus( tuner, "LOADED" );
- }
- catch( SourceException se )
- {
- mLog.error( "couldn't construct Airspy controller/tuner", se );
-
- return new TunerInitStatus( null,
- "error constructing Airspy tuner controller" );
- }
- }
-
-
-
- private TunerInitStatus initEttusB100Tuner( Device device,
- DeviceDescriptor descriptor )
- {
- return new TunerInitStatus( null, "Ettus B100 tuner not currently "
- + "supported" );
- }
-
- private TunerInitStatus initFuncubeProTuner( Device device,
- DeviceDescriptor descriptor )
- {
- String reason = "NOT LOADED";
-
- MixerTunerDataLine dataline = getMixerTunerDataLine(
- TunerClass.FUNCUBE_DONGLE_PRO.getTunerType() );
-
- if( dataline != null )
- {
- FCD1TunerController controller =
- new FCD1TunerController( device, descriptor );
-
- try
+ if(result < 0)
{
- controller.init();
-
- FCDTuner tuner =
- new FCDTuner( dataline, controller );
-
- return new TunerInitStatus( tuner, "LOADED" );
+ mLog.error("unable to get device list from libusb [" + result + " / " +
+ LibUsb.errorName(result) + "]");
}
- catch ( SourceException e )
+ else
{
- mLog.error( "couldn't load funcube dongle pro tuner", e );
-
- reason = "error during initialization - " + e.getLocalizedMessage();
+ mLog.info("discovered [" + result + "] attached USB devices");
}
- }
- else
- {
- reason = "couldn't find matching mixer dataline";
- }
+ }
- return new TunerInitStatus( null, "Funcube Dongle Pro tuner not "
- + "loaded - " + reason );
- }
+ for(Device device : deviceList)
+ {
+ DeviceDescriptor descriptor = new DeviceDescriptor();
- private TunerInitStatus initFuncubeProPlusTuner( Device device,
- DeviceDescriptor descriptor )
- {
- String reason = "NOT LOADED";
-
- MixerTunerDataLine dataline = getMixerTunerDataLine(
- TunerClass.FUNCUBE_DONGLE_PRO_PLUS.getTunerType() );
-
- if( dataline != null )
- {
- FCD2TunerController controller =
- new FCD2TunerController( device, descriptor );
+ result = LibUsb.getDeviceDescriptor(device, descriptor);
- try
+ if(result != LibUsb.SUCCESS)
{
- controller.init();
-
- FCDTuner tuner =
- new FCDTuner( dataline, controller );
-
- return new TunerInitStatus( tuner, "LOADED" );
+ mLog.error("unable to read device descriptor [" +
+ LibUsb.errorName(result) + "]");
}
- catch ( SourceException e )
+ else
{
- mLog.error( "couldn't load funcube dongle pro plus tuner", e );
-
- reason = "error during initialization - " +
- e.getLocalizedMessage();
+ TunerInitStatus status = initTuner(device, descriptor);
+
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("usb device [");
+ sb.append(String.format("%04X", descriptor.idVendor()));
+ sb.append(":");
+ sb.append(String.format("%04X", descriptor.idProduct()));
+
+ if(status.isLoaded())
+ {
+ Tuner tuner = status.getTuner();
+
+ try
+ {
+ mTunerModel.addTuner(tuner);
+ sb.append("] LOADED: ");
+ sb.append(tuner.toString());
+ }
+ catch(Exception e)
+ {
+ sb.append("] NOT LOADED: ");
+ sb.append(status.getInfo());
+ sb.append(" Error:" + e.getMessage());
+ }
+ }
+ else
+ {
+ sb.append("] NOT LOADED: ");
+ sb.append(status.getInfo());
+ }
+
+ mLog.info(sb.toString());
}
- }
- else
- {
- reason = "couldn't find matching mixer dataline";
- }
+ }
- return new TunerInitStatus( null, "Funcube Dongle Pro tuner not "
- + "loaded - " + reason );
- }
+ LibUsb.freeDeviceList(deviceList, true);
+ }
- private TunerInitStatus initHackRFTuner( Device device,
- DeviceDescriptor descriptor )
- {
- try
- {
- HackRFTunerController hackRFController =
- new HackRFTunerController( device, descriptor,
- mThreadPoolManager );
-
- hackRFController.init();
-
- HackRFTuner tuner = new HackRFTuner( hackRFController );
-
- return new TunerInitStatus( tuner, "LOADED" );
- }
- catch( SourceException se )
- {
- mLog.error( "couldn't construct HackRF controller/tuner", se );
-
- return new TunerInitStatus( null,
- "error constructing HackRF tuner controller" );
- }
- }
+ private TunerInitStatus initTuner(Device device,
+ DeviceDescriptor descriptor)
+ {
+ if(device != null && descriptor != null)
+ {
+ TunerClass tunerClass = TunerClass.valueOf(descriptor.idVendor(),
+ descriptor.idProduct());
- private TunerInitStatus initRTL2832Tuner( TunerClass tunerClass,
- Device device,
- DeviceDescriptor deviceDescriptor )
- {
- String reason = "NOT LOADED";
+ switch(tunerClass)
+ {
+ case AIRSPY:
+ return initAirspyTuner(device, descriptor);
+ case ETTUS_USRP_B100:
+ return initEttusB100Tuner(device, descriptor);
+ case FUNCUBE_DONGLE_PRO:
+ return initFuncubeProTuner(device, descriptor);
+ case FUNCUBE_DONGLE_PRO_PLUS:
+ return initFuncubeProPlusTuner(device, descriptor);
+ case HACKRF_ONE:
+ case RAD1O:
+ return initHackRFTuner(device, descriptor);
+ case COMPRO_VIDEOMATE_U620F:
+ case COMPRO_VIDEOMATE_U650F:
+ case COMPRO_VIDEOMATE_U680F:
+ case GENERIC_2832:
+ case GENERIC_2838:
+ case DEXATEK_5217_DVBT:
+ case DEXATEK_DIGIVOX_MINI_II_REV3:
+ case DEXATEK_LOGILINK_VG002A:
+ case GIGABYTE_GTU7300:
+ case GTEK_T803:
+ case LIFEVIEW_LV5T_DELUXE:
+ case MYGICA_TD312:
+ case PEAK_102569AGPK:
+ case PROLECTRIX_DV107669:
+ case SVEON_STV20:
+ case TERRATEC_CINERGY_T_REV1:
+ case TERRATEC_CINERGY_T_REV3:
+ case TERRATEC_NOXON_REV1_B3:
+ case TERRATEC_NOXON_REV1_B4:
+ case TERRATEC_NOXON_REV1_B7:
+ case TERRATEC_NOXON_REV1_C6:
+ case TERRATEC_NOXON_REV2:
+ case TERRATEC_T_STICK_PLUS:
+ case TWINTECH_UT40:
+ case ZAAPA_ZTMINDVBZP:
+ return initRTL2832Tuner(tunerClass, device, descriptor);
+ case UNKNOWN:
+ default:
+ break;
+ }
+ }
- TunerType tunerType = tunerClass.getTunerType();
-
- if( tunerType == TunerType.RTL2832_VARIOUS )
- {
- try
- {
- tunerType = RTL2832TunerController.identifyTunerType( device );
- }
- catch( SourceException e )
- {
- mLog.error( "couldn't determine RTL2832 tuner type", e );
- tunerType = TunerType.UNKNOWN;
- }
- }
-
- switch( tunerType )
- {
- case ELONICS_E4000:
- try
- {
- E4KTunerController controller =
- new E4KTunerController( device, deviceDescriptor,
- mThreadPoolManager );
-
- controller.init();
-
- RTL2832Tuner rtlTuner =
- new RTL2832Tuner( tunerClass, controller );
-
- return new TunerInitStatus( rtlTuner, "LOADED" );
- }
- catch( SourceException se )
- {
- return new TunerInitStatus( null, "Error constructing E4K tuner "
- + "controller - " + se.getLocalizedMessage() );
- }
- case RAFAELMICRO_R820T:
- try
- {
- R820TTunerController controller =
- new R820TTunerController( device, deviceDescriptor,
- mThreadPoolManager );
-
- controller.init();
-
- RTL2832Tuner rtlTuner =
- new RTL2832Tuner( tunerClass, controller );
-
- return new TunerInitStatus( rtlTuner, "LOADED" );
- }
- catch( SourceException se )
- {
- mLog.error( "error constructing tuner", se );
-
- return new TunerInitStatus( null, "Error constructing R820T "
- + "tuner controller - " + se.getLocalizedMessage() );
- }
- case FITIPOWER_FC0012:
- case FITIPOWER_FC0013:
- case RAFAELMICRO_R828D:
- case UNKNOWN:
- default:
- reason = "SDRTRunk doesn't currently support RTL2832 "
- + "Dongle with [" + tunerType.toString() +
- "] tuner for tuner class[" + tunerClass.toString() + "]";
- break;
- }
-
- return new TunerInitStatus( null, reason );
- }
+ return new TunerInitStatus(null, "Unknown Device");
+ }
+
+ private TunerInitStatus initAirspyTuner(Device device,
+ DeviceDescriptor descriptor)
+ {
+ try
+ {
+ AirspyTunerController airspyController = new AirspyTunerController(device);
+
+ airspyController.init();
+
+ AirspyTuner tuner = new AirspyTuner(airspyController);
+
+ return new TunerInitStatus(tuner, "LOADED");
+ }
+ catch(SourceException se)
+ {
+ mLog.error("couldn't construct Airspy controller/tuner", se);
+
+ return new TunerInitStatus(null,
+ "error constructing Airspy tuner controller");
+ }
+ }
+
+
+ private TunerInitStatus initEttusB100Tuner(Device device,
+ DeviceDescriptor descriptor)
+ {
+ return new TunerInitStatus(null, "Ettus B100 tuner not currently "
+ + "supported");
+ }
+
+ private TunerInitStatus initFuncubeProTuner(Device device,
+ DeviceDescriptor descriptor)
+ {
+ String reason = "NOT LOADED";
+
+ MixerTunerDataLine dataline = getMixerTunerDataLine(
+ TunerClass.FUNCUBE_DONGLE_PRO.getTunerType());
+
+ if(dataline != null)
+ {
+ FCD1TunerController controller =
+ new FCD1TunerController(device, descriptor);
+
+ try
+ {
+ controller.init();
+
+ FCDTuner tuner =
+ new FCDTuner(dataline, controller);
+
+ return new TunerInitStatus(tuner, "LOADED");
+ }
+ catch(SourceException e)
+ {
+ mLog.error("couldn't load funcube dongle pro tuner", e);
+
+ reason = "error during initialization - " + e.getLocalizedMessage();
+ }
+ }
+ else
+ {
+ reason = "couldn't find matching mixer dataline";
+ }
+
+ return new TunerInitStatus(null, "Funcube Dongle Pro tuner not "
+ + "loaded - " + reason);
+ }
+
+ private TunerInitStatus initFuncubeProPlusTuner(Device device,
+ DeviceDescriptor descriptor)
+ {
+ String reason = "NOT LOADED";
+
+ MixerTunerDataLine dataline = getMixerTunerDataLine(
+ TunerClass.FUNCUBE_DONGLE_PRO_PLUS.getTunerType());
+
+ if(dataline != null)
+ {
+ FCD2TunerController controller =
+ new FCD2TunerController(device, descriptor);
+
+ try
+ {
+ controller.init();
+
+ FCDTuner tuner =
+ new FCDTuner(dataline, controller);
+
+ return new TunerInitStatus(tuner, "LOADED");
+ }
+ catch(SourceException e)
+ {
+ mLog.error("couldn't load funcube dongle pro plus tuner", e);
+
+ reason = "error during initialization - " +
+ e.getLocalizedMessage();
+ }
+ }
+ else
+ {
+ reason = "couldn't find matching mixer dataline";
+ }
+
+ return new TunerInitStatus(null, "Funcube Dongle Pro tuner not "
+ + "loaded - " + reason);
+ }
+
+ private TunerInitStatus initHackRFTuner(Device device,
+ DeviceDescriptor descriptor)
+ {
+ try
+ {
+ HackRFTunerController hackRFController = new HackRFTunerController(device, descriptor);
+
+ hackRFController.init();
+
+ HackRFTuner tuner = new HackRFTuner(hackRFController);
+
+ return new TunerInitStatus(tuner, "LOADED");
+ }
+ catch(SourceException se)
+ {
+ mLog.error("couldn't construct HackRF controller/tuner", se);
+
+ return new TunerInitStatus(null,
+ "error constructing HackRF tuner controller");
+ }
+ }
+
+ private TunerInitStatus initRTL2832Tuner(TunerClass tunerClass,
+ Device device,
+ DeviceDescriptor deviceDescriptor)
+ {
+ String reason = "NOT LOADED";
+
+ TunerType tunerType = tunerClass.getTunerType();
+
+ if(tunerType == TunerType.RTL2832_VARIOUS)
+ {
+ try
+ {
+ tunerType = RTL2832TunerController.identifyTunerType(device);
+ }
+ catch(SourceException e)
+ {
+ mLog.error("couldn't determine RTL2832 tuner type", e);
+ tunerType = TunerType.UNKNOWN;
+ }
+ }
+
+ switch(tunerType)
+ {
+ case ELONICS_E4000:
+ try
+ {
+ E4KTunerController controller = new E4KTunerController(device, deviceDescriptor);
+
+ controller.init();
+
+ RTL2832Tuner rtlTuner = new RTL2832Tuner(tunerClass, controller);
+
+ return new TunerInitStatus(rtlTuner, "LOADED");
+ }
+ catch(SourceException se)
+ {
+ return new TunerInitStatus(null, "Error constructing E4K tuner controller - " +
+ se.getLocalizedMessage());
+ }
+ case RAFAELMICRO_R820T:
+ try
+ {
+ R820TTunerController controller = new R820TTunerController(device, deviceDescriptor);
+
+ controller.init();
+
+ RTL2832Tuner rtlTuner = new RTL2832Tuner(tunerClass, controller);
+
+ return new TunerInitStatus(rtlTuner, "LOADED");
+ }
+ catch(SourceException se)
+ {
+ mLog.error("error constructing tuner", se);
+
+ return new TunerInitStatus(null, "Error constructing R820T "
+ + "tuner controller - " + se.getLocalizedMessage());
+ }
+ case FITIPOWER_FC0012:
+ case FITIPOWER_FC0013:
+ case RAFAELMICRO_R828D:
+ case UNKNOWN:
+ default:
+ reason = "SDRTRunk doesn't currently support RTL2832 "
+ + "Dongle with [" + tunerType.toString() +
+ "] tuner for tuner class[" + tunerClass.toString() + "]";
+ break;
+ }
+
+ return new TunerInitStatus(null, reason);
+ }
/**
* Gets the first tuner mixer dataline that corresponds to the tuner class.
- *
+ *
* Note: this method is not currently able to align multiple tuner mixer
* data lines of the same tuner type. If you have multiple Funcube Dongle
- * tuners of the same TYPE, there is no guarantee that you will get the
+ * tuners of the same TYPE, there is no guarantee that you will get the
* correct mixer.
- *
+ *
* @param tunerClass
* @return
*/
- private MixerTunerDataLine getMixerTunerDataLine( TunerType tunerClass )
+ private MixerTunerDataLine getMixerTunerDataLine(TunerType tunerClass)
{
- Collection datalines =
- mMixerManager.getMixerTunerDataLines();
+ Collection datalines =
+ mMixerManager.getMixerTunerDataLines();
- for( MixerTunerDataLine mixerTDL: datalines )
- {
- if( mixerTDL.getMixerTunerType().getTunerClass() == tunerClass )
- {
- return mixerTDL;
- }
- }
-
- return null;
+ for(MixerTunerDataLine mixerTDL : datalines)
+ {
+ if(mixerTDL.getMixerTunerType().getTunerClass() == tunerClass)
+ {
+ return mixerTDL;
+ }
+ }
+
+ return null;
}
-
+
public class TunerInitStatus
{
- private Tuner mTuner;
- private String mInfo;
-
- public TunerInitStatus( Tuner tuner, String info )
- {
- mTuner = tuner;
- mInfo = info;
- }
-
- public Tuner getTuner()
- {
- return mTuner;
- }
-
- public String getInfo()
- {
- return mInfo;
- }
-
- public boolean isLoaded()
- {
- return mTuner != null;
- }
+ private Tuner mTuner;
+ private String mInfo;
+
+ public TunerInitStatus(Tuner tuner, String info)
+ {
+ mTuner = tuner;
+ mInfo = info;
+ }
+
+ public Tuner getTuner()
+ {
+ return mTuner;
+ }
+
+ public String getInfo()
+ {
+ return mInfo;
+ }
+
+ public boolean isLoaded()
+ {
+ return mTuner != null;
+ }
}
}
diff --git a/src/source/tuner/airspy/AirspyTunerController.java b/src/source/tuner/airspy/AirspyTunerController.java
index eef5988a..aaab5fd4 100644
--- a/src/source/tuner/airspy/AirspyTunerController.java
+++ b/src/source/tuner/airspy/AirspyTunerController.java
@@ -1,5 +1,25 @@
package source.tuner.airspy;
+import dsp.filter.dc.DCRemovalFilter_RB;
+import dsp.filter.hilbert.HilbertTransform;
+import org.apache.commons.io.EndianUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.usb4java.Device;
+import org.usb4java.DeviceHandle;
+import org.usb4java.LibUsb;
+import org.usb4java.LibUsbException;
+import org.usb4java.Transfer;
+import org.usb4java.TransferCallback;
+import sample.Broadcaster;
+import sample.Listener;
+import sample.complex.ComplexBuffer;
+import source.SourceException;
+import source.tuner.TunerController;
+import source.tuner.configuration.TunerConfiguration;
+import util.ThreadPool;
+
+import javax.usb.UsbException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.text.DecimalFormat;
@@ -11,33 +31,10 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
-import javax.usb.UsbException;
-
-import org.apache.commons.io.EndianUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.usb4java.Device;
-import org.usb4java.DeviceHandle;
-import org.usb4java.LibUsb;
-import org.usb4java.LibUsbException;
-import org.usb4java.Transfer;
-import org.usb4java.TransferCallback;
-
-import sample.Broadcaster;
-import sample.Listener;
-import sample.complex.ComplexBuffer;
-import source.SourceException;
-import source.tuner.TunerController;
-import source.tuner.configuration.TunerConfiguration;
-import controller.ThreadPoolManager;
-import controller.ThreadPoolManager.ThreadType;
-import dsp.filter.dc.DCRemovalFilter_RB;
-import dsp.filter.hilbert.HilbertTransform;
-
/**
- * SDR Trunk
- * Copyright (C) 2015-2016 Dennis Sheirer
- *
+ * SDR Trunk
+ * Copyright (C) 2015-2017 Dennis Sheirer
+ *
* Ported from libairspy at:
* https://github.com/airspy/host/tree/master/libairspy
* -----------------------------------------------------------------------------
@@ -46,1432 +43,1412 @@ import dsp.filter.hilbert.HilbertTransform;
* Copyright (c) 2014, Youssef Touil
* Copyright (c) 2014, Benjamin Vernoux
* Copyright (c) 2015, Ian Gilmour
- *
+ *
* All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
+ *
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
+ *
+ * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * Neither the name of AirSpy nor the names of its contributors may be used to
- * endorse or promote products derived from this software without specific prior
+ * Neither the name of AirSpy nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific prior
* written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
public class AirspyTunerController extends TunerController
{
- public static final Gain LINEARITY_GAIN_DEFAULT = Gain.LINEARITY_14;
- public static final Gain SENSITIVITY_GAIN_DEFAULT = Gain.SENSITIVITY_10;
- public static final int GAIN_MIN = 1;
- public static final int GAIN_MAX = 22;
- public static final int LNA_GAIN_MIN = 0;
- public static final int LNA_GAIN_MAX = 14;
- public static final int LNA_GAIN_DEFAULT = 7;
- public static final int MIXER_GAIN_MIN = 0;
- public static final int MIXER_GAIN_MAX = 15;
- public static final int MIXER_GAIN_DEFAULT = 9;
- public static final int IF_GAIN_MIN = 0;
- public static final int IF_GAIN_MAX = 15;
- public static final int IF_GAIN_DEFAULT = 9;
- public static final long FREQUENCY_MIN = 24000000l;
- public static final long FREQUENCY_MAX = 1800000000l;
- public static final long FREQUENCY_DEFAULT = 101100000;
- public static final double USABLE_BANDWIDTH_PERCENT = 0.90;
- public static final AirspySampleRate DEFAULT_SAMPLE_RATE =
- new AirspySampleRate( 0, 10000000, "10.00 MHz" );
+ public static final Gain LINEARITY_GAIN_DEFAULT = Gain.LINEARITY_14;
+ public static final Gain SENSITIVITY_GAIN_DEFAULT = Gain.SENSITIVITY_10;
+ public static final int GAIN_MIN = 1;
+ public static final int GAIN_MAX = 22;
+ public static final int LNA_GAIN_MIN = 0;
+ public static final int LNA_GAIN_MAX = 14;
+ public static final int LNA_GAIN_DEFAULT = 7;
+ public static final int MIXER_GAIN_MIN = 0;
+ public static final int MIXER_GAIN_MAX = 15;
+ public static final int MIXER_GAIN_DEFAULT = 9;
+ public static final int IF_GAIN_MIN = 0;
+ public static final int IF_GAIN_MAX = 15;
+ public static final int IF_GAIN_DEFAULT = 9;
+ public static final long FREQUENCY_MIN = 24000000l;
+ public static final long FREQUENCY_MAX = 1800000000l;
+ public static final long FREQUENCY_DEFAULT = 101100000;
+ public static final double USABLE_BANDWIDTH_PERCENT = 0.90;
+ public static final AirspySampleRate DEFAULT_SAMPLE_RATE =
+ new AirspySampleRate(0, 10000000, "10.00 MHz");
- public static final long USB_TIMEOUT_MS = 2000l; //milliseconds
- public static final byte USB_ENDPOINT = (byte)0x81;
- public static final byte USB_INTERFACE = (byte)0x0;
- public static final int TRANSFER_BUFFER_POOL_SIZE = 16;
-
- public static final byte USB_REQUEST_IN =
- (byte)( LibUsb.ENDPOINT_IN |
- LibUsb.REQUEST_TYPE_VENDOR |
- LibUsb.RECIPIENT_DEVICE );
-
- public static final byte USB_REQUEST_OUT =
- (byte)( LibUsb.ENDPOINT_OUT |
- LibUsb.REQUEST_TYPE_VENDOR |
- LibUsb.RECIPIENT_DEVICE );
+ public static final long USB_TIMEOUT_MS = 2000l; //milliseconds
+ public static final byte USB_ENDPOINT = (byte) 0x81;
+ public static final byte USB_INTERFACE = (byte) 0x0;
+ public static final int TRANSFER_BUFFER_POOL_SIZE = 16;
- public static final DecimalFormat MHZ_FORMATTER = new DecimalFormat( "#.00 MHz" );
-
- private final static Logger mLog =
- LoggerFactory.getLogger( AirspyTunerController.class );
-
- private Device mDevice;
- private DeviceHandle mDeviceHandle;
+ public static final byte USB_REQUEST_IN =
+ (byte) (LibUsb.ENDPOINT_IN |
+ LibUsb.REQUEST_TYPE_VENDOR |
+ LibUsb.RECIPIENT_DEVICE);
- private ThreadPoolManager mThreadPoolManager;
- private LinkedTransferQueue mFilledBuffers =
- new LinkedTransferQueue();
+ public static final byte USB_REQUEST_OUT =
+ (byte) (LibUsb.ENDPOINT_OUT |
+ LibUsb.REQUEST_TYPE_VENDOR |
+ LibUsb.RECIPIENT_DEVICE);
+
+ public static final DecimalFormat MHZ_FORMATTER = new DecimalFormat("#.00 MHz");
+
+ private final static Logger mLog = LoggerFactory.getLogger(AirspyTunerController.class);
+
+ private Device mDevice;
+ private DeviceHandle mDeviceHandle;
+
+ private LinkedTransferQueue mFilledBuffers = new LinkedTransferQueue();
private Broadcaster mComplexBufferBroadcaster = new Broadcaster<>();
- private int mBufferSize = 262144;
- private BufferProcessor mBufferProcessor = new BufferProcessor();
- private AirspySampleAdapter mSampleAdapter = new AirspySampleAdapter();
- private DCRemovalFilter_RB mDCFilter = new DCRemovalFilter_RB( 0.01f );
- private HilbertTransform mHilbertTransform = new HilbertTransform();
-
- private AirspyDeviceInformation mDeviceInfo;
- private List mSampleRates = new ArrayList<>();
- private int mSampleRate = 0;
-
- public AirspyTunerController( Device device, ThreadPoolManager threadPoolManager )
- throws SourceException
- {
- super( FREQUENCY_MIN, FREQUENCY_MAX, 0, USABLE_BANDWIDTH_PERCENT );
-
- mDevice = device;
- mThreadPoolManager = threadPoolManager;
- }
-
- public void init() throws SourceException
- {
- mDeviceHandle = new DeviceHandle();
+ private int mBufferSize = 262144;
+ private BufferProcessor mBufferProcessor = new BufferProcessor();
+ private AirspySampleAdapter mSampleAdapter = new AirspySampleAdapter();
+ private DCRemovalFilter_RB mDCFilter = new DCRemovalFilter_RB(0.01f);
+ private HilbertTransform mHilbertTransform = new HilbertTransform();
- int result = LibUsb.open( mDevice, mDeviceHandle );
-
- if( result != 0 )
- {
- if( result == LibUsb.ERROR_ACCESS )
- {
- mLog.error( "Unable to access Airspy - insufficient permissions."
- + " If you are running a Linux OS, have you installed the "
- + "airspy rules file in \\etc\\udev\\rules.d ??" );
- }
-
- throw new SourceException( "Couldn't open airspy device - " +
- LibUsb.strError( result ) );
- }
+ private AirspyDeviceInformation mDeviceInfo;
+ private List mSampleRates = new ArrayList<>();
+ private int mSampleRate = 0;
- try
- {
- claimInterface();
- }
- catch( Exception e )
- {
- throw new SourceException( "Airspy Tuner Controller - error while "
- + "setting USB configuration, claiming USB interface or "
- + "reset the kernel mode driver", e );
- }
-
- try
- {
- setSamplePacking( false );
- }
- catch( LibUsbException | UsbException | UnsupportedOperationException e )
- {
- mLog.info( "Sample packing is not supported by airspy firmware" );
- }
-
- try
- {
- setReceiverMode( true );
- }
- catch( Exception e )
- {
- mLog.error( "Couldn't enable airspy receiver mode", e );
- }
+ public AirspyTunerController(Device device) throws SourceException
+ {
+ super(FREQUENCY_MIN, FREQUENCY_MAX, 0, USABLE_BANDWIDTH_PERCENT);
- setFrequency( FREQUENCY_DEFAULT );
-
- try
- {
- determineAvailableSampleRates();
- }
- catch ( LibUsbException | UsbException e )
- {
- mLog.error( "Error identifying available samples rates", e );
- }
-
- try
- {
- setSampleRate( DEFAULT_SAMPLE_RATE );
- }
- catch ( IllegalArgumentException | LibUsbException | UsbException e )
- {
- mLog.error( "Setting sample rate is not supported by firmware", e );
- }
- }
-
- /**
- * Claims the USB interface. If another application currently has
- * the interface claimed, the USB_FORCE_CLAIM_INTERFACE setting
- * will dictate if the interface is forcibly claimed from the other
- * application
- */
- private void claimInterface() throws SourceException
- {
- if( mDeviceHandle != null )
- {
- int result = LibUsb.kernelDriverActive( mDeviceHandle, USB_INTERFACE );
-
- if( result == 1 )
- {
-
- result = LibUsb.detachKernelDriver( mDeviceHandle, USB_INTERFACE );
+ mDevice = device;
+ }
- if( result != LibUsb.SUCCESS )
- {
- mLog.error( "failed attempt to detach kernel driver [" +
- LibUsb.errorName( result ) + "]" );
-
- throw new SourceException( "couldn't detach kernel driver "
- + "from device" );
- }
- }
+ public void init() throws SourceException
+ {
+ mDeviceHandle = new DeviceHandle();
- result = LibUsb.setConfiguration( mDeviceHandle, 1 );
-
- if( result != LibUsb.SUCCESS )
- {
- throw new SourceException( "couldn't set USB configuration 1 [" +
- LibUsb.errorName( result ) + "]" );
- }
+ int result = LibUsb.open(mDevice, mDeviceHandle);
- result = LibUsb.claimInterface( mDeviceHandle, USB_INTERFACE );
-
- if( result != LibUsb.SUCCESS )
- {
- throw new SourceException( "couldn't claim usb interface [" +
- LibUsb.errorName( result ) + "]" );
- }
- }
- else
- {
- throw new SourceException( "couldn't claim usb interface - no "
- + "device handle" );
- }
- }
-
- public static String getTransferStatus( int status )
- {
- switch( status )
- {
- case 0:
- return "TRANSFER COMPLETED (0)";
- case 1:
- return "TRANSFER ERROR (1)";
- case 2:
- return "TRANSFER TIMED OUT (2)";
- case 3:
- return "TRANSFER CANCELLED (3)";
- case 4:
- return "TRANSFER STALL (4)";
- case 5:
- return "TRANSFER NO DEVICE (5)";
- case 6:
- return "TRANSFER OVERFLOW (6)";
- default:
- return "UNKNOWN TRANSFER STATUS (" + status + ")";
- }
- }
+ if(result != 0)
+ {
+ if(result == LibUsb.ERROR_ACCESS)
+ {
+ mLog.error("Unable to access Airspy - insufficient permissions."
+ + " If you are running a Linux OS, have you installed the "
+ + "airspy rules file in \\etc\\udev\\rules.d ??");
+ }
-
- @Override
- public void apply( TunerConfiguration config ) throws SourceException
- {
- if( config instanceof AirspyTunerConfiguration )
- {
- AirspyTunerConfiguration airspy = (AirspyTunerConfiguration)config;
+ throw new SourceException("Couldn't open airspy device - " +
+ LibUsb.strError(result));
+ }
- int sampleRate = airspy.getSampleRate();
+ try
+ {
+ claimInterface();
+ }
+ catch(Exception e)
+ {
+ throw new SourceException("Airspy Tuner Controller - error while "
+ + "setting USB configuration, claiming USB interface or "
+ + "reset the kernel mode driver", e);
+ }
- AirspySampleRate rate = getSampleRate( sampleRate );
+ try
+ {
+ setSamplePacking(false);
+ }
+ catch(LibUsbException | UsbException | UnsupportedOperationException e)
+ {
+ mLog.info("Sample packing is not supported by airspy firmware");
+ }
- if( rate == null )
- {
- if( !mSampleRates.isEmpty() )
- {
- rate = mSampleRates.get( 0 );
- }
- else
- {
- rate = DEFAULT_SAMPLE_RATE;
- }
- }
-
- try
- {
- setSampleRate( rate );
- }
- catch( UsbException e )
- {
- throw new SourceException( "Couldn't set sample rate [" +
- rate.toString() + "]", e );
- }
+ try
+ {
+ setReceiverMode(true);
+ }
+ catch(Exception e)
+ {
+ mLog.error("Couldn't enable airspy receiver mode", e);
+ }
- try
- {
- setIFGain( airspy.getIFGain() );
- setMixerGain( airspy.getMixerGain() );
- setLNAGain( airspy.getLNAGain() );
-
- setMixerAGC( airspy.isMixerAGC() );
- setLNAAGC( airspy.isLNAAGC() );
+ setFrequency(FREQUENCY_DEFAULT);
- //Set the gain mode last, so custom values are already set, and
- //linearity and sensitivity modes will automatically override
- //the custom values.
- setGain( airspy.getGain() );
-
- setFrequencyCorrection( airspy.getFrequencyCorrection() );
- }
- catch( Exception e )
- {
- throw new SourceException( "Couldn't apply gain settings from "
- + "airspy config", e );
- }
-
- try
- {
- setFrequency( airspy.getFrequency() );
- }
- catch( SourceException se )
- {
- //Do nothing, we couldn't set the frequency
- }
-
- }
- else
- {
- throw new IllegalArgumentException( "Invalid tuner config:" +
- config.getClass() );
- }
- }
+ try
+ {
+ determineAvailableSampleRates();
+ }
+ catch(LibUsbException | UsbException e)
+ {
+ mLog.error("Error identifying available samples rates", e);
+ }
- @Override
- public long getTunedFrequency() throws SourceException
- {
- return mFrequencyController.getTunedFrequency();
- }
+ try
+ {
+ setSampleRate(DEFAULT_SAMPLE_RATE);
+ }
+ catch(IllegalArgumentException | LibUsbException | UsbException e)
+ {
+ mLog.error("Setting sample rate is not supported by firmware", e);
+ }
+ }
- @Override
- public void setTunedFrequency( long frequency ) throws SourceException
- {
- if( FREQUENCY_MIN <= frequency && frequency <= FREQUENCY_MAX )
- {
- ByteBuffer buffer = ByteBuffer.allocateDirect( 4 );
-
- buffer.order( ByteOrder.LITTLE_ENDIAN );
+ /**
+ * Claims the USB interface. If another application currently has
+ * the interface claimed, the USB_FORCE_CLAIM_INTERFACE setting
+ * will dictate if the interface is forcibly claimed from the other
+ * application
+ */
+ private void claimInterface() throws SourceException
+ {
+ if(mDeviceHandle != null)
+ {
+ int result = LibUsb.kernelDriverActive(mDeviceHandle, USB_INTERFACE);
- buffer.putInt( (int)frequency );
+ if(result == 1)
+ {
- buffer.rewind();
+ result = LibUsb.detachKernelDriver(mDeviceHandle, USB_INTERFACE);
- try
- {
- write( Command.SET_FREQUENCY, 0, 0, buffer );
- }
- catch( UsbException e )
- {
- mLog.error( "error setting frequency [" + frequency + "]", e );
-
- throw new SourceException( "error setting frequency [" +
- frequency + "]", e );
- }
- }
- else
- {
- throw new SourceException( "Frequency [" + frequency + "] outside "
- + "of tunable range " + FREQUENCY_MIN + "-" + FREQUENCY_MAX );
- }
- }
+ if(result != LibUsb.SUCCESS)
+ {
+ mLog.error("failed attempt to detach kernel driver [" +
+ LibUsb.errorName(result) + "]");
- @Override
- public int getCurrentSampleRate() throws SourceException
- {
- return mSampleRate;
- }
+ throw new SourceException("couldn't detach kernel driver "
+ + "from device");
+ }
+ }
- /**
- * Sets the sample rate to the rate specified by the index value in the
- * available sample rates map
- *
- * @param rate to a sample rate in the available samples rates map.
- *
- * @throws IllegalArgumentException if index is not a valid rate index
- * @throws LibUsbException if there was a read error or if this operation
- * is not supported by the current firmware
- *
- * @throws UsbException if there was a USB error
- */
- public void setSampleRate( AirspySampleRate rate ) throws
- LibUsbException, UsbException, SourceException
- {
- if( rate.getRate() != mSampleRate )
- {
- int result = readByte( Command.SET_SAMPLE_RATE, 0, rate.getIndex(), true );
+ result = LibUsb.setConfiguration(mDeviceHandle, 1);
- if( result != 1 )
- {
- throw new UsbException( "Error setting sample rate [" +
- rate + "] rate - return value [" + result + "]" );
- }
- else
- {
- mSampleRate = rate.getRate();
- mFrequencyController.setSampleRate( mSampleRate );
- }
- }
- }
+ if(result != LibUsb.SUCCESS)
+ {
+ throw new SourceException("couldn't set USB configuration 1 [" +
+ LibUsb.errorName(result) + "]");
+ }
- /**
- * Returns a list of sample rates supported by the firmware version
- */
- public List getSampleRates()
- {
- return mSampleRates;
- }
-
- /**
- * Airspy sample rate object that matches the current sample rate setting.
- */
- public AirspySampleRate getAirspySampleRate()
- {
- return getSampleRate( mSampleRate );
- }
+ result = LibUsb.claimInterface(mDeviceHandle, USB_INTERFACE);
- /**
- * Airspy sample rate object that matches the specified rate in hertz, or
- * null if there are no available sample rates for the tuner that match the
- * argument value.
- */
- public AirspySampleRate getSampleRate( int rate )
- {
- for( AirspySampleRate sampleRate: mSampleRates )
- {
- if( sampleRate.getRate() == rate )
- {
- return sampleRate;
- }
- }
-
- //We should never get to here ...
- return null;
- }
-
- /**
- * Enables/Disables sample packing to allow two 12-bit samples to be packed
- * into 3 bytes (enabled) or 4 bytes (disabled).
- *
- * @param enabled
- *
- * @throws UsbException if sample packing is not supported by the current
- * device firmware or if there were usb communication issues
- */
- public void setSamplePacking( boolean enabled )
- throws LibUsbException, UsbException
- {
- int result = readByte( Command.SET_PACKING, 0, ( enabled ? 1 : 0 ), true );
-
- if( result != 1 )
- {
- throw new UsbException( "Couldnt set sample packing enabled: " + enabled );
- }
+ if(result != LibUsb.SUCCESS)
+ {
+ throw new SourceException("couldn't claim usb interface [" +
+ LibUsb.errorName(result) + "]");
+ }
+ }
+ else
+ {
+ throw new SourceException("couldn't claim usb interface - no "
+ + "device handle");
+ }
+ }
+
+ public static String getTransferStatus(int status)
+ {
+ switch(status)
+ {
+ case 0:
+ return "TRANSFER COMPLETED (0)";
+ case 1:
+ return "TRANSFER ERROR (1)";
+ case 2:
+ return "TRANSFER TIMED OUT (2)";
+ case 3:
+ return "TRANSFER CANCELLED (3)";
+ case 4:
+ return "TRANSFER STALL (4)";
+ case 5:
+ return "TRANSFER NO DEVICE (5)";
+ case 6:
+ return "TRANSFER OVERFLOW (6)";
+ default:
+ return "UNKNOWN TRANSFER STATUS (" + status + ")";
+ }
+ }
+
+
+ @Override
+ public void apply(TunerConfiguration config) throws SourceException
+ {
+ if(config instanceof AirspyTunerConfiguration)
+ {
+ AirspyTunerConfiguration airspy = (AirspyTunerConfiguration) config;
+
+ int sampleRate = airspy.getSampleRate();
+
+ AirspySampleRate rate = getSampleRate(sampleRate);
+
+ if(rate == null)
+ {
+ if(!mSampleRates.isEmpty())
+ {
+ rate = mSampleRates.get(0);
+ }
+ else
+ {
+ rate = DEFAULT_SAMPLE_RATE;
+ }
+ }
+
+ try
+ {
+ setSampleRate(rate);
+ }
+ catch(UsbException e)
+ {
+ throw new SourceException("Couldn't set sample rate [" +
+ rate.toString() + "]", e);
+ }
+
+ try
+ {
+ setIFGain(airspy.getIFGain());
+ setMixerGain(airspy.getMixerGain());
+ setLNAGain(airspy.getLNAGain());
+
+ setMixerAGC(airspy.isMixerAGC());
+ setLNAAGC(airspy.isLNAAGC());
+
+ //Set the gain mode last, so custom values are already set, and
+ //linearity and sensitivity modes will automatically override
+ //the custom values.
+ setGain(airspy.getGain());
+
+ setFrequencyCorrection(airspy.getFrequencyCorrection());
+ }
+ catch(Exception e)
+ {
+ throw new SourceException("Couldn't apply gain settings from "
+ + "airspy config", e);
+ }
+
+ try
+ {
+ setFrequency(airspy.getFrequency());
+ }
+ catch(SourceException se)
+ {
+ //Do nothing, we couldn't set the frequency
+ }
+
+ }
+ else
+ {
+ throw new IllegalArgumentException("Invalid tuner config:" +
+ config.getClass());
+ }
+ }
+
+ @Override
+ public long getTunedFrequency() throws SourceException
+ {
+ return mFrequencyController.getTunedFrequency();
+ }
+
+ @Override
+ public void setTunedFrequency(long frequency) throws SourceException
+ {
+ if(FREQUENCY_MIN <= frequency && frequency <= FREQUENCY_MAX)
+ {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(4);
+
+ buffer.order(ByteOrder.LITTLE_ENDIAN);
+
+ buffer.putInt((int) frequency);
+
+ buffer.rewind();
+
+ try
+ {
+ write(Command.SET_FREQUENCY, 0, 0, buffer);
+ }
+ catch(UsbException e)
+ {
+ mLog.error("error setting frequency [" + frequency + "]", e);
+
+ throw new SourceException("error setting frequency [" +
+ frequency + "]", e);
+ }
+ }
+ else
+ {
+ throw new SourceException("Frequency [" + frequency + "] outside "
+ + "of tunable range " + FREQUENCY_MIN + "-" + FREQUENCY_MAX);
+ }
+ }
+
+ @Override
+ public int getCurrentSampleRate() throws SourceException
+ {
+ return mSampleRate;
+ }
+
+ /**
+ * Sets the sample rate to the rate specified by the index value in the
+ * available sample rates map
+ *
+ * @param rate to a sample rate in the available samples rates map.
+ * @throws IllegalArgumentException if index is not a valid rate index
+ * @throws LibUsbException if there was a read error or if this operation
+ * is not supported by the current firmware
+ * @throws UsbException if there was a USB error
+ */
+ public void setSampleRate(AirspySampleRate rate) throws
+ LibUsbException, UsbException, SourceException
+ {
+ if(rate.getRate() != mSampleRate)
+ {
+ int result = readByte(Command.SET_SAMPLE_RATE, 0, rate.getIndex(), true);
+
+ if(result != 1)
+ {
+ throw new UsbException("Error setting sample rate [" +
+ rate + "] rate - return value [" + result + "]");
+ }
+ else
+ {
+ mSampleRate = rate.getRate();
+ mFrequencyController.setSampleRate(mSampleRate);
+ }
+ }
+ }
+
+ /**
+ * Returns a list of sample rates supported by the firmware version
+ */
+ public List getSampleRates()
+ {
+ return mSampleRates;
+ }
+
+ /**
+ * Airspy sample rate object that matches the current sample rate setting.
+ */
+ public AirspySampleRate getAirspySampleRate()
+ {
+ return getSampleRate(mSampleRate);
+ }
+
+ /**
+ * Airspy sample rate object that matches the specified rate in hertz, or
+ * null if there are no available sample rates for the tuner that match the
+ * argument value.
+ */
+ public AirspySampleRate getSampleRate(int rate)
+ {
+ for(AirspySampleRate sampleRate : mSampleRates)
+ {
+ if(sampleRate.getRate() == rate)
+ {
+ return sampleRate;
+ }
+ }
+
+ //We should never get to here ...
+ return null;
+ }
+
+ /**
+ * Enables/Disables sample packing to allow two 12-bit samples to be packed
+ * into 3 bytes (enabled) or 4 bytes (disabled).
+ *
+ * @param enabled
+ * @throws UsbException if sample packing is not supported by the current
+ * device firmware or if there were usb communication issues
+ */
+ public void setSamplePacking(boolean enabled)
+ throws LibUsbException, UsbException
+ {
+ int result = readByte(Command.SET_PACKING, 0, (enabled ? 1 : 0), true);
+
+ if(result != 1)
+ {
+ throw new UsbException("Couldnt set sample packing enabled: " + enabled);
+ }
/* If we didn't throw an exception above, then update the sample adapter
- * to process samples accordingly */
- mSampleAdapter.setSamplePacking( enabled );
- }
-
- /**
- * Enables/disables the mixer automatic gain setting
- *
- * @param enabled
- *
- * @throws LibUsbException on unsuccessful read operation
- * @throws UsbException on USB error
- */
- public void setMixerAGC( boolean enabled )
- throws LibUsbException, UsbException
- {
- int result = readByte( Command.SET_MIXER_AGC, 0, ( enabled ? 1 : 0 ), true );
-
- if( result != LibUsb.SUCCESS )
- {
- throw new UsbException( "Couldnt set mixer AGC enabled: " + enabled );
- }
- }
+ * to process samples accordingly */
+ mSampleAdapter.setSamplePacking(enabled);
+ }
- /**
- * Enables/disables the low noise amplifier automatic gain setting
- *
- * @param enabled
- *
- * @throws LibUsbException on unsuccessful read operation
- * @throws UsbException on USB error
- */
- public void setLNAAGC( boolean enabled ) throws LibUsbException, UsbException
- {
- int result = readByte( Command.SET_LNA_AGC, 0, ( enabled ? 1 : 0 ), true );
-
- if( result != LibUsb.SUCCESS )
- {
- throw new UsbException( "Couldnt set LNA AGC enabled: " + enabled );
- }
- }
-
- public void setGain( Gain gain ) throws UsbException
- {
- if( gain != Gain.CUSTOM )
- {
- setMixerAGC( false );
- setLNAAGC( false );
- setLNAGain( gain.getLNA() );
- setMixerGain( gain.getMixer() );
- setIFGain( gain.getIF() );
- }
- }
+ /**
+ * Enables/disables the mixer automatic gain setting
+ *
+ * @param enabled
+ * @throws LibUsbException on unsuccessful read operation
+ * @throws UsbException on USB error
+ */
+ public void setMixerAGC(boolean enabled)
+ throws LibUsbException, UsbException
+ {
+ int result = readByte(Command.SET_MIXER_AGC, 0, (enabled ? 1 : 0), true);
- /**
- * Sets LNA gain
- *
- * @param gain - value within range of LNA_GAIN_MIN to LNA_GAIN_MAX
- *
- * @throws LibUsbException on error in java USB wrapper
- * @throws UsbException on error in USB transfer
- * @throws IllegalArgumentException if gain value is invalid
- */
- public void setLNAGain( int gain )
- throws LibUsbException, UsbException, IllegalArgumentException
- {
- if( LNA_GAIN_MIN <= gain && gain <= LNA_GAIN_MAX )
- {
- int result = readByte( Command.SET_LNA_GAIN, 0, gain, true );
-
- if( result != LibUsb.SUCCESS )
- {
- throw new UsbException( "Couldnt set LNA gain to: " + gain );
- }
- }
- else
- {
- throw new IllegalArgumentException( "LNA gain value [" + gain +
- "] is outside value range: " + LNA_GAIN_MIN + "-" + LNA_GAIN_MAX );
- }
- }
+ if(result != LibUsb.SUCCESS)
+ {
+ throw new UsbException("Couldnt set mixer AGC enabled: " + enabled);
+ }
+ }
- /**
- * Sets Mixer gain
- *
- * @param gain - value within range of MIXER_GAIN_MIN to MIXER_GAIN_MAX
- *
- * @throws LibUsbException on error in java USB wrapper
- * @throws UsbException on error in USB transfer
- * @throws IllegalArgumentException if gain value is invalid
- */
- public void setMixerGain( int gain )
- throws LibUsbException, UsbException, IllegalArgumentException
- {
- if( MIXER_GAIN_MIN <= gain && gain <= MIXER_GAIN_MAX )
- {
- int result = readByte( Command.SET_MIXER_GAIN, 0, gain, true );
-
- if( result != LibUsb.SUCCESS )
- {
- throw new UsbException( "Couldnt set mixer gain to: " + gain );
- }
- }
- else
- {
- throw new IllegalArgumentException( "Mixer gain value [" + gain +
- "] is outside value range: " + MIXER_GAIN_MIN + "-" + MIXER_GAIN_MAX );
- }
- }
+ /**
+ * Enables/disables the low noise amplifier automatic gain setting
+ *
+ * @param enabled
+ * @throws LibUsbException on unsuccessful read operation
+ * @throws UsbException on USB error
+ */
+ public void setLNAAGC(boolean enabled) throws LibUsbException, UsbException
+ {
+ int result = readByte(Command.SET_LNA_AGC, 0, (enabled ? 1 : 0), true);
- /**
- * Sets IF (VGA) gain
- *
- * @param gain - value within range of VGA_GAIN_MIN to VGA_GAIN_MAX
- *
- * @throws LibUsbException on error in java USB wrapper
- * @throws UsbException on error in USB transfer
- * @throws IllegalArgumentException if gain value is invalid
- */
- public void setIFGain( int gain )
- throws LibUsbException, UsbException, IllegalArgumentException
- {
- if( IF_GAIN_MIN <= gain && gain <= IF_GAIN_MAX )
- {
- int result = readByte( Command.SET_VGA_GAIN, 0, gain, true );
-
- if( result != LibUsb.SUCCESS )
- {
- throw new UsbException( "Couldnt set VGA gain to: " + gain );
- }
- }
- else
- {
- throw new IllegalArgumentException( "VGA gain value [" + gain +
- "] is outside value range: " + IF_GAIN_MIN + "-" + IF_GAIN_MAX );
- }
- }
-
- public void setReceiverMode( boolean enabled ) throws LibUsbException, UsbException
- {
- //Empty buffer to throw away
- ByteBuffer buffer = ByteBuffer.allocateDirect( 0 );
-
- write( Command.RECEIVER_MODE, ( enabled ? 1 : 0 ), 0, buffer );
- }
-
- /**
- * Queries the device for available sample rates. Will always provide at
- * least the default 10 MHz sample rate.
- */
- private void determineAvailableSampleRates()
- throws LibUsbException, UsbException
- {
- mSampleRates.clear();
-
- //Get a count of available sample rates. If we get an exception, then
- //we're using an older firmware revision and only the default 10 MHz
- //rate is supported
- try
- {
- byte[] rawCount = readArray( Command.GET_SAMPLE_RATES, 0, 0, 4 );
+ if(result != LibUsb.SUCCESS)
+ {
+ throw new UsbException("Couldnt set LNA AGC enabled: " + enabled);
+ }
+ }
- if( rawCount != null )
- {
- int count = EndianUtils.readSwappedInteger( rawCount, 0 );
+ public void setGain(Gain gain) throws UsbException
+ {
+ if(gain != Gain.CUSTOM)
+ {
+ setMixerAGC(false);
+ setLNAAGC(false);
+ setLNAGain(gain.getLNA());
+ setMixerGain(gain.getMixer());
+ setIFGain(gain.getIF());
+ }
+ }
- byte[] rawRates = readArray( Command.GET_SAMPLE_RATES, 0,
- count, ( count * 4 ) );
+ /**
+ * Sets LNA gain
+ *
+ * @param gain - value within range of LNA_GAIN_MIN to LNA_GAIN_MAX
+ * @throws LibUsbException on error in java USB wrapper
+ * @throws UsbException on error in USB transfer
+ * @throws IllegalArgumentException if gain value is invalid
+ */
+ public void setLNAGain(int gain)
+ throws LibUsbException, UsbException, IllegalArgumentException
+ {
+ if(LNA_GAIN_MIN <= gain && gain <= LNA_GAIN_MAX)
+ {
+ int result = readByte(Command.SET_LNA_GAIN, 0, gain, true);
- for( int x = 0; x < count; x++ )
- {
- int rate = EndianUtils.readSwappedInteger( rawRates, ( x * 4 ) );
+ if(result != LibUsb.SUCCESS)
+ {
+ throw new UsbException("Couldnt set LNA gain to: " + gain);
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("LNA gain value [" + gain +
+ "] is outside value range: " + LNA_GAIN_MIN + "-" + LNA_GAIN_MAX);
+ }
+ }
- mSampleRates.add( new AirspySampleRate( x, rate, formatSampleRate( rate ) ) );
- }
- }
- }
- catch( LibUsbException e )
- {
- //Press on, nothing else to do here ..
- }
+ /**
+ * Sets Mixer gain
+ *
+ * @param gain - value within range of MIXER_GAIN_MIN to MIXER_GAIN_MAX
+ * @throws LibUsbException on error in java USB wrapper
+ * @throws UsbException on error in USB transfer
+ * @throws IllegalArgumentException if gain value is invalid
+ */
+ public void setMixerGain(int gain)
+ throws LibUsbException, UsbException, IllegalArgumentException
+ {
+ if(MIXER_GAIN_MIN <= gain && gain <= MIXER_GAIN_MAX)
+ {
+ int result = readByte(Command.SET_MIXER_GAIN, 0, gain, true);
- if( mSampleRates.isEmpty())
- {
- mSampleRates.add( DEFAULT_SAMPLE_RATE );
- }
- }
+ if(result != LibUsb.SUCCESS)
+ {
+ throw new UsbException("Couldnt set mixer gain to: " + gain);
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("Mixer gain value [" + gain +
+ "] is outside value range: " + MIXER_GAIN_MIN + "-" + MIXER_GAIN_MAX);
+ }
+ }
- /**
- * Formats the rate in hertz for display as megahertz
- */
- private static String formatSampleRate( int rate )
- {
- return MHZ_FORMATTER.format( (double)rate / 1E6d );
- }
+ /**
+ * Sets IF (VGA) gain
+ *
+ * @param gain - value within range of VGA_GAIN_MIN to VGA_GAIN_MAX
+ * @throws LibUsbException on error in java USB wrapper
+ * @throws UsbException on error in USB transfer
+ * @throws IllegalArgumentException if gain value is invalid
+ */
+ public void setIFGain(int gain)
+ throws LibUsbException, UsbException, IllegalArgumentException
+ {
+ if(IF_GAIN_MIN <= gain && gain <= IF_GAIN_MAX)
+ {
+ int result = readByte(Command.SET_VGA_GAIN, 0, gain, true);
- /**
- * Device information
- */
- public AirspyDeviceInformation getDeviceInfo()
- {
- //Lazy initialization
- if( mDeviceInfo == null )
- {
- readDeviceInfo();
- }
-
- return mDeviceInfo;
- }
+ if(result != LibUsb.SUCCESS)
+ {
+ throw new UsbException("Couldnt set VGA gain to: " + gain);
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("VGA gain value [" + gain +
+ "] is outside value range: " + IF_GAIN_MIN + "-" + IF_GAIN_MAX);
+ }
+ }
- /**
- * Reads version information from the device and populates the info object
- */
- private void readDeviceInfo()
- {
- if( mDeviceInfo == null )
- {
- mDeviceInfo = new AirspyDeviceInformation();
- }
+ public void setReceiverMode(boolean enabled) throws LibUsbException, UsbException
+ {
+ //Empty buffer to throw away
+ ByteBuffer buffer = ByteBuffer.allocateDirect(0);
+
+ write(Command.RECEIVER_MODE, (enabled ? 1 : 0), 0, buffer);
+ }
+
+ /**
+ * Queries the device for available sample rates. Will always provide at
+ * least the default 10 MHz sample rate.
+ */
+ private void determineAvailableSampleRates()
+ throws LibUsbException, UsbException
+ {
+ mSampleRates.clear();
+
+ //Get a count of available sample rates. If we get an exception, then
+ //we're using an older firmware revision and only the default 10 MHz
+ //rate is supported
+ try
+ {
+ byte[] rawCount = readArray(Command.GET_SAMPLE_RATES, 0, 0, 4);
+
+ if(rawCount != null)
+ {
+ int count = EndianUtils.readSwappedInteger(rawCount, 0);
+
+ byte[] rawRates = readArray(Command.GET_SAMPLE_RATES, 0,
+ count, (count * 4));
+
+ for(int x = 0; x < count; x++)
+ {
+ int rate = EndianUtils.readSwappedInteger(rawRates, (x * 4));
+
+ mSampleRates.add(new AirspySampleRate(x, rate, formatSampleRate(rate)));
+ }
+ }
+ }
+ catch(LibUsbException e)
+ {
+ //Press on, nothing else to do here ..
+ }
+
+ if(mSampleRates.isEmpty())
+ {
+ mSampleRates.add(DEFAULT_SAMPLE_RATE);
+ }
+ }
+
+ /**
+ * Formats the rate in hertz for display as megahertz
+ */
+ private static String formatSampleRate(int rate)
+ {
+ return MHZ_FORMATTER.format((double) rate / 1E6d);
+ }
+
+ /**
+ * Device information
+ */
+ public AirspyDeviceInformation getDeviceInfo()
+ {
+ //Lazy initialization
+ if(mDeviceInfo == null)
+ {
+ readDeviceInfo();
+ }
+
+ return mDeviceInfo;
+ }
+
+ /**
+ * Reads version information from the device and populates the info object
+ */
+ private void readDeviceInfo()
+ {
+ if(mDeviceInfo == null)
+ {
+ mDeviceInfo = new AirspyDeviceInformation();
+ }
/* Board ID */
- try
- {
- int boardID = readByte( Command.BOARD_ID_READ, 0, 0, true );
-
- mDeviceInfo.setBoardID( boardID );
- }
- catch ( LibUsbException | UsbException e )
- {
- mLog.error( "Error reading airspy board ID", e );
- }
+ try
+ {
+ int boardID = readByte(Command.BOARD_ID_READ, 0, 0, true);
+
+ mDeviceInfo.setBoardID(boardID);
+ }
+ catch(LibUsbException | UsbException e)
+ {
+ mLog.error("Error reading airspy board ID", e);
+ }
/* Version String */
- try
- {
- //NOTE: libairspy is internally reading 127 bytes, however airspy_info
- //script is telling it to read 255 bytes ... things that make you go hmmmm
- byte[] version = readArray( Command.VERSION_STRING_READ, 0, 0, 127 );
+ try
+ {
+ //NOTE: libairspy is internally reading 127 bytes, however airspy_info
+ //script is telling it to read 255 bytes ... things that make you go hmmmm
+ byte[] version = readArray(Command.VERSION_STRING_READ, 0, 0, 127);
- mDeviceInfo.setVersion( version );
- }
- catch ( LibUsbException | UsbException e )
- {
- mLog.error( "Error reading airspy version string", e );
- }
+ mDeviceInfo.setVersion(version);
+ }
+ catch(LibUsbException | UsbException e)
+ {
+ mLog.error("Error reading airspy version string", e);
+ }
/* Part ID and Serial Number */
- try
- {
- //Read 6 x 32-bit integers = 24 bytes
- byte[] serial = readArray(
- Command.BOARD_PART_ID_SERIAL_NUMBER_READ, 0, 0, 24 );
-
- mDeviceInfo.setPartAndSerialNumber( serial );
- }
- catch ( LibUsbException | UsbException e )
- {
- mLog.error( "Error reading airspy version string", e );
- }
- }
-
- /**
- * Reads a single byte value from the device.
- *
- * @param command - airspy command
- *
- * @param value - value field for usb setup packet
- * @param index - index field for usb setup packet
- *
- * @return - byte value as an integer
- *
- * @throws LibUsbException if the operation is unsuccesful
- * @throws UsbException on any usb errors
- */
- private int readByte( Command command, int value, int index, boolean signed )
- throws LibUsbException, UsbException
- {
- if( mDeviceHandle != null )
- {
- ByteBuffer buffer = ByteBuffer.allocateDirect( 1 );
-
- int transferred = LibUsb.controlTransfer( mDeviceHandle,
- USB_REQUEST_IN,
- command.getValue(),
- (short)value,
- (short)index,
- buffer,
- USB_TIMEOUT_MS );
-
- if( transferred < 0 )
- {
- throw new LibUsbException( "read error", transferred );
- }
-
- byte result = buffer.get( 0 );
-
- if( signed )
- {
- return ( result & 0xFF );
- }
- else
- {
- return result;
- }
- }
- else
- {
- throw new LibUsbException( "device handle is null",
- LibUsb.ERROR_NO_DEVICE );
- }
- }
-
- /**
- * Reads a multi-byte value from the device
- *
- * @param command - airspy command
- * @param value - usb packet value
- * @param index - usb packet index
- * @param length - number of bytes to read
- * @return - bytes read from the device
- *
- * @throws LibUsbException if quantity of bytes read doesn't equal the
- * requested number of bytes
- * @throws UsbException on error communicating with the device
- */
- private byte[] readArray( Command command, int value, int index, int length )
- throws LibUsbException, UsbException
- {
- if( mDeviceHandle != null )
- {
- ByteBuffer buffer = ByteBuffer.allocateDirect( length );
-
- int transferred = LibUsb.controlTransfer( mDeviceHandle,
- USB_REQUEST_IN,
- command.getValue(),
- (short)value,
- (short)index,
- buffer,
- USB_TIMEOUT_MS );
-
- if( transferred < 0 )
- {
- throw new LibUsbException( "read error", transferred );
- }
-
- byte[] results = new byte[ transferred ];
-
- buffer.get( results );
-
- return results;
- }
- else
- {
- throw new LibUsbException( "device handle is null",
- LibUsb.ERROR_NO_DEVICE );
- }
- }
-
- /**
- * Writes the buffer contents to the device
- *
- * @param command - airspy command
- * @param value - usb packet value
- * @param index - usb packet index
- * @param buffer - data to write to the device
- * @throws UsbException on error
- */
- public void write( Command command, int value, int index, ByteBuffer buffer )
- throws UsbException
- {
- if( mDeviceHandle != null )
- {
- int transferred = LibUsb.controlTransfer( mDeviceHandle,
- USB_REQUEST_OUT,
- command.getValue(),
- (short)value,
- (short)index,
- buffer,
- USB_TIMEOUT_MS );
-
- if( transferred < 0 )
- {
- throw new LibUsbException( "error writing byte buffer",
- transferred );
- }
- else if( transferred != buffer.capacity() )
- {
- throw new LibUsbException( "transferred bytes [" +
- transferred + "] is not what was expected [" +
- buffer.capacity() + "]", transferred );
- }
- }
- else
- {
- throw new LibUsbException( "device handle is null",
- LibUsb.ERROR_NO_DEVICE );
- }
- }
-
- public enum GainMode
- {
- LINEARITY,
- SENSITIVITY,
- CUSTOM;
- }
-
- public enum Gain
- {
- LINEARITY_1( 1, 4, 0, 0 ),
- LINEARITY_2( 2, 5, 0, 0 ),
- LINEARITY_3( 3, 6, 1, 0 ),
- LINEARITY_4( 4, 7, 1, 0 ),
- LINEARITY_5( 5, 8, 1, 0 ),
- LINEARITY_6( 6, 9, 1, 0 ),
- LINEARITY_7( 7, 10, 2, 0 ),
- LINEARITY_8( 8, 10, 2, 1 ),
- LINEARITY_9( 9, 10, 0, 3 ),
- LINEARITY_10( 10, 10, 0, 5 ),
- LINEARITY_11( 11, 10, 1, 6 ),
- LINEARITY_12( 12, 10, 0, 8 ),
- LINEARITY_13( 13, 10, 0, 9 ),
- LINEARITY_14( 14, 10, 5, 8 ),
- LINEARITY_15( 15, 10, 6, 9 ),
- LINEARITY_16( 16, 11, 6, 9 ),
- LINEARITY_17( 17, 11, 7, 10 ),
- LINEARITY_18( 18, 11, 8, 12 ),
- LINEARITY_19( 19, 11, 9, 13 ),
- LINEARITY_20( 20, 11, 11, 14 ),
- LINEARITY_21( 21, 12, 12, 14 ),
- LINEARITY_22( 22, 13, 12, 14 ),
- SENSITIVITY_1( 1, 4, 0, 0 ),
- SENSITIVITY_2( 2, 4, 0, 1 ),
- SENSITIVITY_3( 3, 4, 0, 2 ),
- SENSITIVITY_4( 4, 4, 0, 3 ),
- SENSITIVITY_5( 5, 4, 1, 5 ),
- SENSITIVITY_6( 6, 4, 2, 6 ),
- SENSITIVITY_7( 7, 4, 2, 7 ),
- SENSITIVITY_8( 8, 4, 3, 8 ),
- SENSITIVITY_9( 9, 4, 4, 9 ),
- SENSITIVITY_10( 10, 5, 4, 9 ),
- SENSITIVITY_11( 11, 5, 4, 12 ),
- SENSITIVITY_12( 12, 5, 7, 12 ),
- SENSITIVITY_13( 13, 5, 8, 13 ),
- SENSITIVITY_14( 14, 5, 9, 14 ),
- SENSITIVITY_15( 15, 6, 9, 14 ),
- SENSITIVITY_16( 16, 7, 10, 14 ),
- SENSITIVITY_17( 17, 8, 10, 14 ),
- SENSITIVITY_18( 18, 9, 11, 14 ),
- SENSITIVITY_19( 19, 10, 12, 14 ),
- SENSITIVITY_20( 20, 11, 12, 14 ),
- SENSITIVITY_21( 21, 12, 12, 14 ),
- SENSITIVITY_22( 22, 13, 12, 14 ),
- CUSTOM( 1, 0, 0, 0 );
-
- private int mValue;
- private int mIF;
- private int mMixer;
- private int mLNA;
-
- private Gain( int value, int ifGain, int mixer, int lna )
- {
- mValue = value;
- mIF = ifGain;
- mMixer = mixer;
- mLNA = lna;
- }
-
- public int getValue()
- {
- return mValue;
- }
-
- public int getIF()
- {
- return mIF;
- }
-
- public int getMixer()
- {
- return mMixer;
- }
-
- public int getLNA()
- {
- return mLNA;
- }
-
- public static Gain getGain( GainMode mode, int value )
- {
- assert( GAIN_MIN <= value && value <= GAIN_MAX );
-
- switch( mode )
- {
- case LINEARITY:
- for( Gain gain: getLinearityGains() )
- {
- if( gain.getValue() == value )
- {
- return gain;
- }
- }
- return LINEARITY_GAIN_DEFAULT;
- case SENSITIVITY:
- for( Gain gain: getSensitivityGains() )
- {
- if( gain.getValue() == value )
- {
- return gain;
- }
- }
- return SENSITIVITY_GAIN_DEFAULT;
- case CUSTOM:
- default:
- return Gain.CUSTOM;
- }
- }
-
- public static GainMode getGainMode( Gain gain )
- {
- if( gain == CUSTOM )
- {
- return GainMode.CUSTOM;
- }
- else if( getLinearityGains().contains( gain ) )
- {
- return GainMode.LINEARITY;
- }
- else if( getSensitivityGains().contains( gain ) )
- {
- return GainMode.SENSITIVITY;
- }
-
- return GainMode.CUSTOM;
- }
-
- public static EnumSet getLinearityGains()
- {
- return EnumSet.range( LINEARITY_1, LINEARITY_22 );
- }
-
- public static EnumSet getSensitivityGains()
- {
- return EnumSet.range( SENSITIVITY_1, SENSITIVITY_22 );
- }
- }
-
-
-
- /**
- * Airspy Board Identifier
- */
- public enum BoardID
- {
- AIRSPY( 0, "Airspy" ),
- UNKNOWN( -1, "Unknown" );
-
- private int mValue;
- private String mLabel;
-
- private BoardID( int value, String label )
- {
- mValue = value;
- mLabel = label;
- }
-
- public int getValue()
- {
- return mValue;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
-
- public static BoardID fromValue( int value )
- {
- if( value == 0 )
- {
- return AIRSPY;
- }
-
- return UNKNOWN;
- }
- }
-
- /**
- * Airspy Commands
- */
- public enum Command
- {
- INVALID( 0 ),
- RECEIVER_MODE( 1 ),
- SI5351C_WRITE( 2 ),
- SI5351C_READ( 3 ),
- R820T_WRITE( 4 ),
- R820T_READ( 5 ),
- SPIFLASH_ERASE( 6 ),
- SPIFLASH_WRITE( 7 ),
- SPIFLASH_READ( 8 ),
- BOARD_ID_READ( 9 ),
- VERSION_STRING_READ( 10 ),
- BOARD_PART_ID_SERIAL_NUMBER_READ( 11 ),
- SET_SAMPLE_RATE( 12 ),
- SET_FREQUENCY( 13 ),
- SET_LNA_GAIN( 14 ),
- SET_MIXER_GAIN( 15 ),
- SET_VGA_GAIN( 16 ),
- SET_LNA_AGC( 17 ),
- SET_MIXER_AGC( 18 ),
- MS_VENDOR_COMMAND( 19 ),
- SET_RF_BIAS_COMMAND( 20 ),
- GPIO_WRITE( 21 ),
- GPIO_READ( 22 ),
- GPIO_DIR__WRITE( 23 ),
- GPIO_DIR_READ( 24 ),
- GET_SAMPLE_RATES( 25 ),
- SET_PACKING( 26 );
-
- private int mValue;
-
- private Command( int value )
- {
- mValue = value;
- }
-
- public byte getValue()
- {
- return (byte)mValue;
- }
-
- public static Command fromValue( int value )
- {
- if( 0 <= value && value <= 25 )
- {
- return Command.values()[ value ];
- }
-
- return INVALID;
- }
- }
-
- public enum ReceiverMode
- {
- OFF( 0 ),
- ON( 1 );
-
- private int mValue;
-
- private ReceiverMode( int value )
- {
- mValue = value;
- }
-
- public int getValue()
- {
- return mValue;
- }
- }
-
- /**
- * General Purpose Input/Output Ports (accessible on the airspy board)
- */
- public enum GPIOPort
- {
- PORT_0( 0 ),
- PORT_1( 1 ),
- PORT_2( 2 ),
- PORT_3( 3 ),
- PORT_4( 4 ),
- PORT_5( 5 ),
- PORT_6( 6 ),
- PORT_7( 7 );
-
- private int mValue;
-
- private GPIOPort( int value )
- {
- mValue = value;
- }
-
- public int getValue()
- {
- return mValue;
- }
- }
-
- /**
- * General Purpose Input/Output Pins (accessible on the airspy board)
- */
- public enum GPIOPin
- {
- PIN_0( 0 ),
- PIN_1( 1 ),
- PIN_2( 2 ),
- PIN_3( 3 ),
- PIN_4( 4 ),
- PIN_5( 5 ),
- PIN_6( 6 ),
- PIN_7( 7 ),
- PIN_8( 8 ),
- PIN_9( 9 ),
- PIN_10( 10 ),
- PIN_11( 11 ),
- PIN_12( 12 ),
- PIN_13( 13 ),
- PIN_14( 14 ),
- PIN_15( 15 ),
- PIN_16( 16 ),
- PIN_17( 17 ),
- PIN_18( 18 ),
- PIN_19( 19 ),
- PIN_20( 20 ),
- PIN_21( 21 ),
- PIN_22( 22 ),
- PIN_23( 23 ),
- PIN_24( 24 ),
- PIN_25( 25 ),
- PIN_26( 26 ),
- PIN_27( 27 ),
- PIN_28( 28 ),
- PIN_29( 29 ),
- PIN_30( 30 ),
- PIN_31( 31 );
-
- private int mValue;
-
- private GPIOPin( int value )
- {
- mValue = value;
- }
-
- public int getValue()
- {
- return mValue;
- }
- }
-
- /**
- * Adds a sample listener. If the buffer processing thread is
- * not currently running, starts it running in a new thread.
- */
- public void addListener( Listener listener )
- {
- synchronized ( mComplexBufferBroadcaster )
- {
- mComplexBufferBroadcaster.addListener( listener );
-
- if( mBufferProcessor == null || !mBufferProcessor.isRunning() )
- {
- mBufferProcessor = new BufferProcessor();
-
- Thread thread = new Thread( mBufferProcessor );
- thread.setDaemon( true );
- thread.setName( "Airspy Buffer Processor" );
-
- thread.start();
- }
- }
- }
-
- /**
- * Removes the sample listener. If this is the last registered listener,
- * shuts down the buffer processing thread.
- */
- public void removeListener( Listener listener )
- {
- synchronized ( mComplexBufferBroadcaster )
- {
- mComplexBufferBroadcaster.removeListener( listener );
-
- if( !mComplexBufferBroadcaster.hasListeners() )
- {
- mBufferProcessor.stop();
- }
- }
- }
-
- /**
- * Buffer processing thread. Fetches samples from the Airspy Tuner and
- * dispatches them to all registered listeners
- */
- public class BufferProcessor implements Runnable, TransferCallback
- {
- private ScheduledFuture> mSampleDispatcherTask;
- private LinkedTransferQueue mAvailableTransfers;
- private LinkedTransferQueue mTransfersInProgress = new LinkedTransferQueue<>();
- private AtomicBoolean mRunning = new AtomicBoolean();
- private ByteBuffer mLibUsbHandlerStatus;
- private boolean mCancel = false;
-
- @Override
- public void run()
+ try
{
- if( mRunning.compareAndSet( false, true ) )
- {
- prepareTransfers();
-
- mSampleDispatcherTask = mThreadPoolManager.scheduleFixedRate(
- ThreadType.SOURCE_SAMPLE_PROCESSING, new BufferDispatcher(),
- 20, TimeUnit.MILLISECONDS );
+ //Read 6 x 32-bit integers = 24 bytes
+ byte[] serial = readArray(
+ Command.BOARD_PART_ID_SERIAL_NUMBER_READ, 0, 0, 24);
- mLibUsbHandlerStatus = ByteBuffer.allocateDirect( 4 );
-
- List transfers = new ArrayList<>();
-
- mCancel = false;
-
- while( mRunning.get() )
- {
- mAvailableTransfers.drainTo( transfers );
-
- for( Transfer transfer: transfers )
- {
- int result = LibUsb.submitTransfer( transfer );
-
- if( result == LibUsb.SUCCESS )
- {
- mTransfersInProgress.add( transfer );
- }
- else
- {
- mLog.error( "error submitting transfer [" +
- LibUsb.errorName( result ) + "]" );
- }
- }
-
- int result = LibUsb.handleEventsTimeoutCompleted(
- null, USB_TIMEOUT_MS, mLibUsbHandlerStatus.asIntBuffer() );
-
- if( result != LibUsb.SUCCESS )
- {
- mLog.error( "error handling events for libusb" );
- }
-
- transfers.clear();
-
- mLibUsbHandlerStatus.rewind();
- }
-
- if( mCancel )
- {
- for( Transfer transfer: mTransfersInProgress )
- {
- LibUsb.cancelTransfer( transfer );
- }
-
- int result = LibUsb.handleEventsTimeoutCompleted( null,
- USB_TIMEOUT_MS, mLibUsbHandlerStatus.asIntBuffer() );
-
- if( result != LibUsb.SUCCESS )
- {
- mLog.error( "error handling events for libusb during cancel" );
- }
-
- mLibUsbHandlerStatus.rewind();
- }
- }
+ mDeviceInfo.setPartAndSerialNumber(serial);
+ }
+ catch(LibUsbException | UsbException e)
+ {
+ mLog.error("Error reading airspy version string", e);
+ }
+ }
+
+ /**
+ * Reads a single byte value from the device.
+ *
+ * @param command - airspy command
+ * @param value - value field for usb setup packet
+ * @param index - index field for usb setup packet
+ * @return - byte value as an integer
+ * @throws LibUsbException if the operation is unsuccesful
+ * @throws UsbException on any usb errors
+ */
+ private int readByte(Command command, int value, int index, boolean signed)
+ throws LibUsbException, UsbException
+ {
+ if(mDeviceHandle != null)
+ {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(1);
+
+ int transferred = LibUsb.controlTransfer(mDeviceHandle,
+ USB_REQUEST_IN,
+ command.getValue(),
+ (short) value,
+ (short) index,
+ buffer,
+ USB_TIMEOUT_MS);
+
+ if(transferred < 0)
+ {
+ throw new LibUsbException("read error", transferred);
+ }
+
+ byte result = buffer.get(0);
+
+ if(signed)
+ {
+ return (result & 0xFF);
+ }
+ else
+ {
+ return result;
+ }
+ }
+ else
+ {
+ throw new LibUsbException("device handle is null",
+ LibUsb.ERROR_NO_DEVICE);
+ }
+ }
+
+ /**
+ * Reads a multi-byte value from the device
+ *
+ * @param command - airspy command
+ * @param value - usb packet value
+ * @param index - usb packet index
+ * @param length - number of bytes to read
+ * @return - bytes read from the device
+ * @throws LibUsbException if quantity of bytes read doesn't equal the
+ * requested number of bytes
+ * @throws UsbException on error communicating with the device
+ */
+ private byte[] readArray(Command command, int value, int index, int length)
+ throws LibUsbException, UsbException
+ {
+ if(mDeviceHandle != null)
+ {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(length);
+
+ int transferred = LibUsb.controlTransfer(mDeviceHandle,
+ USB_REQUEST_IN,
+ command.getValue(),
+ (short) value,
+ (short) index,
+ buffer,
+ USB_TIMEOUT_MS);
+
+ if(transferred < 0)
+ {
+ throw new LibUsbException("read error", transferred);
+ }
+
+ byte[] results = new byte[transferred];
+
+ buffer.get(results);
+
+ return results;
+ }
+ else
+ {
+ throw new LibUsbException("device handle is null",
+ LibUsb.ERROR_NO_DEVICE);
+ }
+ }
+
+ /**
+ * Writes the buffer contents to the device
+ *
+ * @param command - airspy command
+ * @param value - usb packet value
+ * @param index - usb packet index
+ * @param buffer - data to write to the device
+ * @throws UsbException on error
+ */
+ public void write(Command command, int value, int index, ByteBuffer buffer)
+ throws UsbException
+ {
+ if(mDeviceHandle != null)
+ {
+ int transferred = LibUsb.controlTransfer(mDeviceHandle,
+ USB_REQUEST_OUT,
+ command.getValue(),
+ (short) value,
+ (short) index,
+ buffer,
+ USB_TIMEOUT_MS);
+
+ if(transferred < 0)
+ {
+ throw new LibUsbException("error writing byte buffer",
+ transferred);
+ }
+ else if(transferred != buffer.capacity())
+ {
+ throw new LibUsbException("transferred bytes [" +
+ transferred + "] is not what was expected [" +
+ buffer.capacity() + "]", transferred);
+ }
+ }
+ else
+ {
+ throw new LibUsbException("device handle is null",
+ LibUsb.ERROR_NO_DEVICE);
+ }
+ }
+
+ public enum GainMode
+ {
+ LINEARITY,
+ SENSITIVITY,
+ CUSTOM;
+ }
+
+ public enum Gain
+ {
+ LINEARITY_1(1, 4, 0, 0),
+ LINEARITY_2(2, 5, 0, 0),
+ LINEARITY_3(3, 6, 1, 0),
+ LINEARITY_4(4, 7, 1, 0),
+ LINEARITY_5(5, 8, 1, 0),
+ LINEARITY_6(6, 9, 1, 0),
+ LINEARITY_7(7, 10, 2, 0),
+ LINEARITY_8(8, 10, 2, 1),
+ LINEARITY_9(9, 10, 0, 3),
+ LINEARITY_10(10, 10, 0, 5),
+ LINEARITY_11(11, 10, 1, 6),
+ LINEARITY_12(12, 10, 0, 8),
+ LINEARITY_13(13, 10, 0, 9),
+ LINEARITY_14(14, 10, 5, 8),
+ LINEARITY_15(15, 10, 6, 9),
+ LINEARITY_16(16, 11, 6, 9),
+ LINEARITY_17(17, 11, 7, 10),
+ LINEARITY_18(18, 11, 8, 12),
+ LINEARITY_19(19, 11, 9, 13),
+ LINEARITY_20(20, 11, 11, 14),
+ LINEARITY_21(21, 12, 12, 14),
+ LINEARITY_22(22, 13, 12, 14),
+ SENSITIVITY_1(1, 4, 0, 0),
+ SENSITIVITY_2(2, 4, 0, 1),
+ SENSITIVITY_3(3, 4, 0, 2),
+ SENSITIVITY_4(4, 4, 0, 3),
+ SENSITIVITY_5(5, 4, 1, 5),
+ SENSITIVITY_6(6, 4, 2, 6),
+ SENSITIVITY_7(7, 4, 2, 7),
+ SENSITIVITY_8(8, 4, 3, 8),
+ SENSITIVITY_9(9, 4, 4, 9),
+ SENSITIVITY_10(10, 5, 4, 9),
+ SENSITIVITY_11(11, 5, 4, 12),
+ SENSITIVITY_12(12, 5, 7, 12),
+ SENSITIVITY_13(13, 5, 8, 13),
+ SENSITIVITY_14(14, 5, 9, 14),
+ SENSITIVITY_15(15, 6, 9, 14),
+ SENSITIVITY_16(16, 7, 10, 14),
+ SENSITIVITY_17(17, 8, 10, 14),
+ SENSITIVITY_18(18, 9, 11, 14),
+ SENSITIVITY_19(19, 10, 12, 14),
+ SENSITIVITY_20(20, 11, 12, 14),
+ SENSITIVITY_21(21, 12, 12, 14),
+ SENSITIVITY_22(22, 13, 12, 14),
+ CUSTOM(1, 0, 0, 0);
+
+ private int mValue;
+ private int mIF;
+ private int mMixer;
+ private int mLNA;
+
+ private Gain(int value, int ifGain, int mixer, int lna)
+ {
+ mValue = value;
+ mIF = ifGain;
+ mMixer = mixer;
+ mLNA = lna;
}
- /**
- * Stops the sample fetching thread
- */
- public void stop()
- {
- mCancel = true;
-
- if( mRunning.compareAndSet( true, false ) )
- {
- if( mSampleDispatcherTask != null )
- {
- mSampleDispatcherTask.cancel( true );
- mFilledBuffers.clear();
- }
- }
- }
+ public int getValue()
+ {
+ return mValue;
+ }
- /**
- * Indicates if this thread is running
- */
- public boolean isRunning()
- {
- return mRunning.get();
- }
-
- @Override
- public void processTransfer( Transfer transfer )
- {
- mTransfersInProgress.remove( transfer );
-
- switch( transfer.status() )
- {
- case LibUsb.TRANSFER_COMPLETED:
- case LibUsb.TRANSFER_STALL:
- if( transfer.actualLength() > 0 )
- {
- ByteBuffer buffer = transfer.buffer();
-
- byte[] data = new byte[ transfer.actualLength() ];
-
- buffer.get( data );
-
- buffer.rewind();
-
- if( isRunning() )
- {
- mFilledBuffers.add( data );
- }
- }
- break;
- case LibUsb.TRANSFER_CANCELLED:
- break;
- default:
+ public int getIF()
+ {
+ return mIF;
+ }
+
+ public int getMixer()
+ {
+ return mMixer;
+ }
+
+ public int getLNA()
+ {
+ return mLNA;
+ }
+
+ public static Gain getGain(GainMode mode, int value)
+ {
+ assert (GAIN_MIN <= value && value <= GAIN_MAX);
+
+ switch(mode)
+ {
+ case LINEARITY:
+ for(Gain gain : getLinearityGains())
+ {
+ if(gain.getValue() == value)
+ {
+ return gain;
+ }
+ }
+ return LINEARITY_GAIN_DEFAULT;
+ case SENSITIVITY:
+ for(Gain gain : getSensitivityGains())
+ {
+ if(gain.getValue() == value)
+ {
+ return gain;
+ }
+ }
+ return SENSITIVITY_GAIN_DEFAULT;
+ case CUSTOM:
+ default:
+ return Gain.CUSTOM;
+ }
+ }
+
+ public static GainMode getGainMode(Gain gain)
+ {
+ if(gain == CUSTOM)
+ {
+ return GainMode.CUSTOM;
+ }
+ else if(getLinearityGains().contains(gain))
+ {
+ return GainMode.LINEARITY;
+ }
+ else if(getSensitivityGains().contains(gain))
+ {
+ return GainMode.SENSITIVITY;
+ }
+
+ return GainMode.CUSTOM;
+ }
+
+ public static EnumSet getLinearityGains()
+ {
+ return EnumSet.range(LINEARITY_1, LINEARITY_22);
+ }
+
+ public static EnumSet getSensitivityGains()
+ {
+ return EnumSet.range(SENSITIVITY_1, SENSITIVITY_22);
+ }
+ }
+
+
+ /**
+ * Airspy Board Identifier
+ */
+ public enum BoardID
+ {
+ AIRSPY(0, "Airspy"),
+ UNKNOWN(-1, "Unknown");
+
+ private int mValue;
+ private String mLabel;
+
+ private BoardID(int value, String label)
+ {
+ mValue = value;
+ mLabel = label;
+ }
+
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ public String getLabel()
+ {
+ return mLabel;
+ }
+
+ public static BoardID fromValue(int value)
+ {
+ if(value == 0)
+ {
+ return AIRSPY;
+ }
+
+ return UNKNOWN;
+ }
+ }
+
+ /**
+ * Airspy Commands
+ */
+ public enum Command
+ {
+ INVALID(0),
+ RECEIVER_MODE(1),
+ SI5351C_WRITE(2),
+ SI5351C_READ(3),
+ R820T_WRITE(4),
+ R820T_READ(5),
+ SPIFLASH_ERASE(6),
+ SPIFLASH_WRITE(7),
+ SPIFLASH_READ(8),
+ BOARD_ID_READ(9),
+ VERSION_STRING_READ(10),
+ BOARD_PART_ID_SERIAL_NUMBER_READ(11),
+ SET_SAMPLE_RATE(12),
+ SET_FREQUENCY(13),
+ SET_LNA_GAIN(14),
+ SET_MIXER_GAIN(15),
+ SET_VGA_GAIN(16),
+ SET_LNA_AGC(17),
+ SET_MIXER_AGC(18),
+ MS_VENDOR_COMMAND(19),
+ SET_RF_BIAS_COMMAND(20),
+ GPIO_WRITE(21),
+ GPIO_READ(22),
+ GPIO_DIR__WRITE(23),
+ GPIO_DIR_READ(24),
+ GET_SAMPLE_RATES(25),
+ SET_PACKING(26);
+
+ private int mValue;
+
+ private Command(int value)
+ {
+ mValue = value;
+ }
+
+ public byte getValue()
+ {
+ return (byte) mValue;
+ }
+
+ public static Command fromValue(int value)
+ {
+ if(0 <= value && value <= 25)
+ {
+ return Command.values()[value];
+ }
+
+ return INVALID;
+ }
+ }
+
+ public enum ReceiverMode
+ {
+ OFF(0),
+ ON(1);
+
+ private int mValue;
+
+ private ReceiverMode(int value)
+ {
+ mValue = value;
+ }
+
+ public int getValue()
+ {
+ return mValue;
+ }
+ }
+
+ /**
+ * General Purpose Input/Output Ports (accessible on the airspy board)
+ */
+ public enum GPIOPort
+ {
+ PORT_0(0),
+ PORT_1(1),
+ PORT_2(2),
+ PORT_3(3),
+ PORT_4(4),
+ PORT_5(5),
+ PORT_6(6),
+ PORT_7(7);
+
+ private int mValue;
+
+ private GPIOPort(int value)
+ {
+ mValue = value;
+ }
+
+ public int getValue()
+ {
+ return mValue;
+ }
+ }
+
+ /**
+ * General Purpose Input/Output Pins (accessible on the airspy board)
+ */
+ public enum GPIOPin
+ {
+ PIN_0(0),
+ PIN_1(1),
+ PIN_2(2),
+ PIN_3(3),
+ PIN_4(4),
+ PIN_5(5),
+ PIN_6(6),
+ PIN_7(7),
+ PIN_8(8),
+ PIN_9(9),
+ PIN_10(10),
+ PIN_11(11),
+ PIN_12(12),
+ PIN_13(13),
+ PIN_14(14),
+ PIN_15(15),
+ PIN_16(16),
+ PIN_17(17),
+ PIN_18(18),
+ PIN_19(19),
+ PIN_20(20),
+ PIN_21(21),
+ PIN_22(22),
+ PIN_23(23),
+ PIN_24(24),
+ PIN_25(25),
+ PIN_26(26),
+ PIN_27(27),
+ PIN_28(28),
+ PIN_29(29),
+ PIN_30(30),
+ PIN_31(31);
+
+ private int mValue;
+
+ private GPIOPin(int value)
+ {
+ mValue = value;
+ }
+
+ public int getValue()
+ {
+ return mValue;
+ }
+ }
+
+ /**
+ * Adds a sample listener. If the buffer processing thread is
+ * not currently running, starts it running in a new thread.
+ */
+ public void addListener(Listener listener)
+ {
+ synchronized(mComplexBufferBroadcaster)
+ {
+ mComplexBufferBroadcaster.addListener(listener);
+
+ if(mBufferProcessor == null || !mBufferProcessor.isRunning())
+ {
+ mBufferProcessor = new BufferProcessor();
+
+ Thread thread = new Thread(mBufferProcessor);
+ thread.setDaemon(true);
+ thread.setName("Airspy Buffer Processor");
+
+ thread.start();
+ }
+ }
+ }
+
+ /**
+ * Removes the sample listener. If this is the last registered listener,
+ * shuts down the buffer processing thread.
+ */
+ public void removeListener(Listener listener)
+ {
+ synchronized(mComplexBufferBroadcaster)
+ {
+ mComplexBufferBroadcaster.removeListener(listener);
+
+ if(!mComplexBufferBroadcaster.hasListeners())
+ {
+ mBufferProcessor.stop();
+ }
+ }
+ }
+
+ /**
+ * Buffer processing thread. Fetches samples from the Airspy Tuner and
+ * dispatches them to all registered listeners
+ */
+ public class BufferProcessor implements Runnable, TransferCallback
+ {
+ private ScheduledFuture> mSampleDispatcherTask;
+ private LinkedTransferQueue mAvailableTransfers;
+ private LinkedTransferQueue mTransfersInProgress = new LinkedTransferQueue<>();
+ private AtomicBoolean mRunning = new AtomicBoolean();
+ private ByteBuffer mLibUsbHandlerStatus;
+ private boolean mCancel = false;
+
+ @Override
+ public void run()
+ {
+ if(mRunning.compareAndSet(false, true))
+ {
+ prepareTransfers();
+
+ mSampleDispatcherTask = ThreadPool.SCHEDULED.scheduleAtFixedRate(new BufferDispatcher(),
+ 20, 20, TimeUnit.MILLISECONDS);
+
+ mLibUsbHandlerStatus = ByteBuffer.allocateDirect(4);
+
+ List transfers = new ArrayList<>();
+
+ mCancel = false;
+
+ while(mRunning.get())
+ {
+ mAvailableTransfers.drainTo(transfers);
+
+ for(Transfer transfer : transfers)
+ {
+ int result = LibUsb.submitTransfer(transfer);
+
+ if(result == LibUsb.SUCCESS)
+ {
+ mTransfersInProgress.add(transfer);
+ }
+ else
+ {
+ mLog.error("error submitting transfer [" + LibUsb.errorName(result) + "]");
+ }
+ }
+
+ int result = LibUsb.handleEventsTimeoutCompleted(
+ null, USB_TIMEOUT_MS, mLibUsbHandlerStatus.asIntBuffer());
+
+ if(result != LibUsb.SUCCESS)
+ {
+ mLog.error("error handling events for libusb");
+ }
+
+ transfers.clear();
+
+ mLibUsbHandlerStatus.rewind();
+ }
+
+ if(mCancel)
+ {
+ for(Transfer transfer : mTransfersInProgress)
+ {
+ LibUsb.cancelTransfer(transfer);
+ }
+
+ int result = LibUsb.handleEventsTimeoutCompleted(null,
+ USB_TIMEOUT_MS, mLibUsbHandlerStatus.asIntBuffer());
+
+ if(result != LibUsb.SUCCESS)
+ {
+ mLog.error("error handling events for libusb during cancel");
+ }
+
+ mLibUsbHandlerStatus.rewind();
+ }
+ }
+ }
+
+ /**
+ * Stops the sample fetching thread
+ */
+ public void stop()
+ {
+ mCancel = true;
+
+ if(mRunning.compareAndSet(true, false))
+ {
+ if(mSampleDispatcherTask != null)
+ {
+ mSampleDispatcherTask.cancel(true);
+ mFilledBuffers.clear();
+ }
+ }
+ }
+
+ /**
+ * Indicates if this thread is running
+ */
+ public boolean isRunning()
+ {
+ return mRunning.get();
+ }
+
+ @Override
+ public void processTransfer(Transfer transfer)
+ {
+ mTransfersInProgress.remove(transfer);
+
+ switch(transfer.status())
+ {
+ case LibUsb.TRANSFER_COMPLETED:
+ case LibUsb.TRANSFER_STALL:
+ if(transfer.actualLength() > 0)
+ {
+ ByteBuffer buffer = transfer.buffer();
+
+ byte[] data = new byte[transfer.actualLength()];
+
+ buffer.get(data);
+
+ buffer.rewind();
+
+ if(isRunning())
+ {
+ mFilledBuffers.add(data);
+ }
+ }
+ break;
+ case LibUsb.TRANSFER_CANCELLED:
+ break;
+ default:
/* unexpected error */
- mLog.error( "transfer error [" +
- getTransferStatus( transfer.status() ) +
- "] transferred actual: " + transfer.actualLength() );
- }
-
- mAvailableTransfers.add( transfer );
- }
-
- /**
- * Prepares (allocates) a set of transfer buffers for use in
- * transferring data from the tuner via the bulk interface
- */
- private void prepareTransfers() throws LibUsbException
- {
- if( mAvailableTransfers == null )
- {
- mAvailableTransfers = new LinkedTransferQueue<>();
-
- for( int x = 0; x < TRANSFER_BUFFER_POOL_SIZE; x++ )
- {
- Transfer transfer = LibUsb.allocTransfer();
+ mLog.error("transfer error [" +
+ getTransferStatus(transfer.status()) +
+ "] transferred actual: " + transfer.actualLength());
+ }
- if( transfer == null )
- {
- throw new LibUsbException( "couldn't allocate transfer",
- LibUsb.ERROR_NO_MEM );
- }
-
- final ByteBuffer buffer =
- ByteBuffer.allocateDirect( mBufferSize );
-
- LibUsb.fillBulkTransfer( transfer, mDeviceHandle, USB_ENDPOINT,
- buffer, BufferProcessor.this, "Buffer", USB_TIMEOUT_MS );
+ mAvailableTransfers.add(transfer);
+ }
- mAvailableTransfers.add( transfer );
- }
- }
- }
- }
+ /**
+ * Prepares (allocates) a set of transfer buffers for use in
+ * transferring data from the tuner via the bulk interface
+ */
+ private void prepareTransfers() throws LibUsbException
+ {
+ if(mAvailableTransfers == null)
+ {
+ mAvailableTransfers = new LinkedTransferQueue<>();
- /**
- * Fetches byte[] chunks from the raw sample buffer. Converts each byte
- * array and broadcasts the array to all registered listeners
- */
- public class BufferDispatcher implements Runnable
- {
- @Override
+ for(int x = 0; x < TRANSFER_BUFFER_POOL_SIZE; x++)
+ {
+ Transfer transfer = LibUsb.allocTransfer();
+
+ if(transfer == null)
+ {
+ throw new LibUsbException("couldn't allocate transfer",
+ LibUsb.ERROR_NO_MEM);
+ }
+
+ final ByteBuffer buffer =
+ ByteBuffer.allocateDirect(mBufferSize);
+
+ LibUsb.fillBulkTransfer(transfer, mDeviceHandle, USB_ENDPOINT,
+ buffer, BufferProcessor.this, "Buffer", USB_TIMEOUT_MS);
+
+ mAvailableTransfers.add(transfer);
+ }
+ }
+ }
+ }
+
+ /**
+ * Fetches byte[] chunks from the raw sample buffer. Converts each byte
+ * array and broadcasts the array to all registered listeners
+ */
+ public class BufferDispatcher implements Runnable
+ {
+ @Override
public void run()
{
- try
- {
- ArrayList buffers = new ArrayList<>();
-
- mFilledBuffers.drainTo( buffers );
+ try
+ {
+ ArrayList buffers = new ArrayList<>();
- for( byte[] buffer: buffers )
- {
- float[] realSamples = mSampleAdapter.convert( buffer );
+ mFilledBuffers.drainTo(buffers);
- realSamples = mDCFilter.filter( realSamples );
+ for(byte[] buffer : buffers)
+ {
+ float[] realSamples = mSampleAdapter.convert(buffer);
- float[] quadratureSamples = mHilbertTransform.filter( realSamples );
-
- mComplexBufferBroadcaster.broadcast(
- new ComplexBuffer( quadratureSamples ) );
- }
- }
- catch( Exception e )
- {
- mLog.error( "error during Airspy buffer dispatching", e );
- }
+ realSamples = mDCFilter.filter(realSamples);
+
+ float[] quadratureSamples = mHilbertTransform.filter(realSamples);
+
+ mComplexBufferBroadcaster.broadcast(
+ new ComplexBuffer(quadratureSamples));
+ }
+ }
+ catch(Exception e)
+ {
+ mLog.error("error during Airspy buffer dispatching", e);
+ }
}
- }
+ }
}
diff --git a/src/source/tuner/hackrf/HackRFTunerController.java b/src/source/tuner/hackrf/HackRFTunerController.java
index 69698afe..fb570199 100644
--- a/src/source/tuner/hackrf/HackRFTunerController.java
+++ b/src/source/tuner/hackrf/HackRFTunerController.java
@@ -1,30 +1,30 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 Dennis Sheirer
- *
+ *
* Ported from libhackrf at:
* https://github.com/mossmann/hackrf/tree/master/host/libhackrf
- *
+ *
* Copyright (c) 2012, Jared Boone
* Copyright (c) 2013, Benjamin Vernoux
* copyright (c) 2013, Michael Ossmann
- *
+ *
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Great Scott Gadgets nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
@@ -37,34 +37,22 @@
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* 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 source.tuner.hackrf;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.LinkedTransferQueue;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import javax.usb.UsbException;
-
import org.apache.commons.io.EndianUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -75,7 +63,6 @@ import org.usb4java.LibUsb;
import org.usb4java.LibUsbException;
import org.usb4java.Transfer;
import org.usb4java.TransferCallback;
-
import sample.Broadcaster;
import sample.Listener;
import sample.adapter.ByteSampleAdapter;
@@ -83,1078 +70,1084 @@ import sample.complex.ComplexBuffer;
import source.SourceException;
import source.tuner.TunerController;
import source.tuner.configuration.TunerConfiguration;
-import controller.ThreadPoolManager;
-import controller.ThreadPoolManager.ThreadType;
+import util.ThreadPool;
+
+import javax.usb.UsbException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.LinkedTransferQueue;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
public class HackRFTunerController extends TunerController
{
- private final static Logger mLog =
- LoggerFactory.getLogger( HackRFTunerController.class );
+ private final static Logger mLog =
+ LoggerFactory.getLogger(HackRFTunerController.class);
- public final static long USB_TIMEOUT_US = 1000000l; //uSeconds
- public static final byte USB_ENDPOINT = (byte)0x81;
- public static final byte USB_INTERFACE = (byte)0x0;
-
- public static final byte REQUEST_TYPE_IN =
- (byte)( LibUsb.ENDPOINT_IN |
- LibUsb.REQUEST_TYPE_VENDOR |
- LibUsb.RECIPIENT_DEVICE );
-
- public static final byte REQUEST_TYPE_OUT =
- (byte)( LibUsb.ENDPOINT_OUT |
- LibUsb.REQUEST_TYPE_VENDOR |
- LibUsb.RECIPIENT_DEVICE );
+ public final static long USB_TIMEOUT_US = 1000000l; //uSeconds
+ public static final byte USB_ENDPOINT = (byte) 0x81;
+ public static final byte USB_INTERFACE = (byte) 0x0;
- public static final long MIN_FREQUENCY = 10000000l;
- public static final long MAX_FREQUENCY = 6000000000l;
- public static final long DEFAULT_FREQUENCY = 101100000;
- public static final double USABLE_BANDWIDTH_PERCENT = 0.95;
- public static final int DC_SPIKE_AVOID_BUFFER = 5000;
+ public static final byte REQUEST_TYPE_IN =
+ (byte) (LibUsb.ENDPOINT_IN |
+ LibUsb.REQUEST_TYPE_VENDOR |
+ LibUsb.RECIPIENT_DEVICE);
+
+ public static final byte REQUEST_TYPE_OUT =
+ (byte) (LibUsb.ENDPOINT_OUT |
+ LibUsb.REQUEST_TYPE_VENDOR |
+ LibUsb.RECIPIENT_DEVICE);
+
+ public static final long MIN_FREQUENCY = 10000000l;
+ public static final long MAX_FREQUENCY = 6000000000l;
+ public static final long DEFAULT_FREQUENCY = 101100000;
+ public static final double USABLE_BANDWIDTH_PERCENT = 0.95;
+ public static final int DC_SPIKE_AVOID_BUFFER = 5000;
+
+ public final static int TRANSFER_BUFFER_POOL_SIZE = 16;
+
+ private LinkedTransferQueue mFilledBuffers =
+ new LinkedTransferQueue();
- public final static int TRANSFER_BUFFER_POOL_SIZE = 16;
-
- private LinkedTransferQueue mFilledBuffers =
- new LinkedTransferQueue();
-
private Broadcaster mComplexBufferBroadcaster = new Broadcaster<>();
-
- private ByteSampleAdapter mSampleAdapter = new ByteSampleAdapter();
- private BufferProcessor mBufferProcessor = new BufferProcessor();
-
- private HackRFSampleRate mSampleRate = HackRFSampleRate.RATE2_016MHZ;
- public int mBufferSize = 262144;
- private boolean mAmplifierEnabled = false;
-
- private Device mDevice;
- private DeviceDescriptor mDeviceDescriptor;
- private DeviceHandle mDeviceHandle;
- private ThreadPoolManager mThreadPoolManager;
-
- public HackRFTunerController( Device device, DeviceDescriptor descriptor,
- ThreadPoolManager threadPoolManager ) throws SourceException
- {
- super( MIN_FREQUENCY, MAX_FREQUENCY, DC_SPIKE_AVOID_BUFFER, USABLE_BANDWIDTH_PERCENT );
- mDevice = device;
- mDeviceDescriptor = descriptor;
- mThreadPoolManager = threadPoolManager;
- }
-
- public void init() throws SourceException
- {
- mDeviceHandle = new DeviceHandle();
-
- int result = LibUsb.open( mDevice, mDeviceHandle );
-
- if( result != 0 )
- {
- if( result == LibUsb.ERROR_ACCESS )
- {
- mLog.error( "Unable to access HackRF - insufficient permissions. "
- + "If you are running a Linux OS, have you installed the "
- + "hackRF rules file in \\etc\\udev\\rules.d ??" );
- }
-
- throw new SourceException( "Couldn't open hackrf device - " +
- LibUsb.strError( result ) );
- }
+ private ByteSampleAdapter mSampleAdapter = new ByteSampleAdapter();
+ private BufferProcessor mBufferProcessor = new BufferProcessor();
- try
- {
- claimInterface();
+ private HackRFSampleRate mSampleRate = HackRFSampleRate.RATE2_016MHZ;
+ public int mBufferSize = 262144;
+ private boolean mAmplifierEnabled = false;
- setMode( Mode.RECEIVE );
-
- setFrequency( DEFAULT_FREQUENCY );
- }
- catch( Exception e )
- {
- throw new SourceException( "HackRF Tuner Controller - couldn't "
- + "claim USB interface or get endpoint or pipe", e );
- }
- }
+ private Device mDevice;
+ private DeviceDescriptor mDeviceDescriptor;
+ private DeviceHandle mDeviceHandle;
- /**
- * Claims the USB interface. If another application currently has
- * the interface claimed, the USB_FORCE_CLAIM_INTERFACE setting
- * will dictate if the interface is forcibly claimed from the other
- * application
- */
- private void claimInterface() throws SourceException
- {
- if( mDeviceHandle != null )
- {
- int result = LibUsb.kernelDriverActive( mDeviceHandle, USB_INTERFACE );
-
- if( result == 1 )
- {
- result = LibUsb.detachKernelDriver( mDeviceHandle, USB_INTERFACE );
+ public HackRFTunerController(Device device, DeviceDescriptor descriptor) throws SourceException
+ {
+ super(MIN_FREQUENCY, MAX_FREQUENCY, DC_SPIKE_AVOID_BUFFER, USABLE_BANDWIDTH_PERCENT);
- if( result != LibUsb.SUCCESS )
- {
- mLog.error( "failed attempt to detach kernel driver [" +
- LibUsb.errorName( result ) + "]" );
-
- throw new SourceException( "couldn't detach kernel driver "
- + "from device" );
- }
- }
-
- result = LibUsb.claimInterface( mDeviceHandle, USB_INTERFACE );
-
- if( result != LibUsb.SUCCESS )
- {
- throw new SourceException( "couldn't claim usb interface [" +
- LibUsb.errorName( result ) + "]" );
- }
- }
- else
- {
- throw new SourceException( "couldn't claim usb interface - no "
- + "device handle" );
- }
- }
+ mDevice = device;
+ mDeviceDescriptor = descriptor;
+ }
- /**
- * HackRF board identifier/type
- */
- public BoardID getBoardID() throws UsbException
- {
- int id = readByte( Request.BOARD_ID_READ, (byte)0, (byte)0, false );
-
- return BoardID.lookup( id );
- }
-
- /**
- * HackRF firmware version string
- */
- public String getFirmwareVersion() throws UsbException
- {
- ByteBuffer buffer = readArray( Request.VERSION_STRING_READ, 0, 0, 255 );
+ public void init() throws SourceException
+ {
+ mDeviceHandle = new DeviceHandle();
- byte[] data = new byte[ 255 ];
-
- buffer.get( data );
+ int result = LibUsb.open(mDevice, mDeviceHandle);
- return new String( data );
- }
-
- /**
- * HackRF part id number and serial number
- */
- public Serial getSerial() throws UsbException
- {
- ByteBuffer buffer = readArray( Request.BOARD_PARTID_SERIALNO_READ, 0, 0, 24 );
+ if(result != 0)
+ {
+ if(result == LibUsb.ERROR_ACCESS)
+ {
+ mLog.error("Unable to access HackRF - insufficient permissions. "
+ + "If you are running a Linux OS, have you installed the "
+ + "hackRF rules file in \\etc\\udev\\rules.d ??");
+ }
- return new Serial( buffer );
- }
+ throw new SourceException("Couldn't open hackrf device - " +
+ LibUsb.strError(result));
+ }
- /**
- * Sets the HackRF transceiver mode
- */
- public void setMode( Mode mode ) throws UsbException
- {
- write( Request.SET_TRANSCEIVER_MODE, mode.getNumber(), 0 );
- }
+ try
+ {
+ claimInterface();
- /**
- * Sets the HackRF baseband filter
- */
- public void setBasebandFilter( BasebandFilter filter ) throws UsbException
- {
- write( Request.BASEBAND_FILTER_BANDWIDTH_SET,
- filter.getLowValue(),
- filter.getHighValue() );
- }
+ setMode(Mode.RECEIVE);
- /**
- * Enables (true) or disables (false) the amplifier
- */
- public void setAmplifierEnabled( boolean enabled ) throws UsbException
- {
- write( Request.AMP_ENABLE, ( enabled ? 1 : 0 ), 0 );
-
- mAmplifierEnabled = enabled;
- }
-
- public boolean getAmplifier()
- {
- return mAmplifierEnabled;
- }
+ setFrequency(DEFAULT_FREQUENCY);
+ }
+ catch(Exception e)
+ {
+ throw new SourceException("HackRF Tuner Controller - couldn't "
+ + "claim USB interface or get endpoint or pipe", e);
+ }
+ }
- /**
- * Sets the IF LNA Gain
- */
- public void setLNAGain( HackRFLNAGain gain ) throws UsbException
- {
- int result = readByte( Request.SET_LNA_GAIN, 0, gain.getValue(), true );
-
- if( result != 1 )
- {
- throw new UsbException( "couldn't set lna gain to " + gain );
- }
- }
-
- /**
- * Sets the Baseband VGA Gain
- */
- public void setVGAGain( HackRFVGAGain gain ) throws UsbException
- {
- int result = readByte( Request.SET_VGA_GAIN, 0, gain.getValue(), true );
-
- if( result != 1 )
- {
- throw new UsbException( "couldn't set vga gain to " + gain );
- }
- }
+ /**
+ * Claims the USB interface. If another application currently has
+ * the interface claimed, the USB_FORCE_CLAIM_INTERFACE setting
+ * will dictate if the interface is forcibly claimed from the other
+ * application
+ */
+ private void claimInterface() throws SourceException
+ {
+ if(mDeviceHandle != null)
+ {
+ int result = LibUsb.kernelDriverActive(mDeviceHandle, USB_INTERFACE);
- /**
- * Not implemented
- */
+ if(result == 1)
+ {
+ result = LibUsb.detachKernelDriver(mDeviceHandle, USB_INTERFACE);
+
+ if(result != LibUsb.SUCCESS)
+ {
+ mLog.error("failed attempt to detach kernel driver [" +
+ LibUsb.errorName(result) + "]");
+
+ throw new SourceException("couldn't detach kernel driver "
+ + "from device");
+ }
+ }
+
+ result = LibUsb.claimInterface(mDeviceHandle, USB_INTERFACE);
+
+ if(result != LibUsb.SUCCESS)
+ {
+ throw new SourceException("couldn't claim usb interface [" +
+ LibUsb.errorName(result) + "]");
+ }
+ }
+ else
+ {
+ throw new SourceException("couldn't claim usb interface - no "
+ + "device handle");
+ }
+ }
+
+ /**
+ * HackRF board identifier/type
+ */
+ public BoardID getBoardID() throws UsbException
+ {
+ int id = readByte(Request.BOARD_ID_READ, (byte) 0, (byte) 0, false);
+
+ return BoardID.lookup(id);
+ }
+
+ /**
+ * HackRF firmware version string
+ */
+ public String getFirmwareVersion() throws UsbException
+ {
+ ByteBuffer buffer = readArray(Request.VERSION_STRING_READ, 0, 0, 255);
+
+ byte[] data = new byte[255];
+
+ buffer.get(data);
+
+ return new String(data);
+ }
+
+ /**
+ * HackRF part id number and serial number
+ */
+ public Serial getSerial() throws UsbException
+ {
+ ByteBuffer buffer = readArray(Request.BOARD_PARTID_SERIALNO_READ, 0, 0, 24);
+
+ return new Serial(buffer);
+ }
+
+ /**
+ * Sets the HackRF transceiver mode
+ */
+ public void setMode(Mode mode) throws UsbException
+ {
+ write(Request.SET_TRANSCEIVER_MODE, mode.getNumber(), 0);
+ }
+
+ /**
+ * Sets the HackRF baseband filter
+ */
+ public void setBasebandFilter(BasebandFilter filter) throws UsbException
+ {
+ write(Request.BASEBAND_FILTER_BANDWIDTH_SET,
+ filter.getLowValue(),
+ filter.getHighValue());
+ }
+
+ /**
+ * Enables (true) or disables (false) the amplifier
+ */
+ public void setAmplifierEnabled(boolean enabled) throws UsbException
+ {
+ write(Request.AMP_ENABLE, (enabled ? 1 : 0), 0);
+
+ mAmplifierEnabled = enabled;
+ }
+
+ public boolean getAmplifier()
+ {
+ return mAmplifierEnabled;
+ }
+
+ /**
+ * Sets the IF LNA Gain
+ */
+ public void setLNAGain(HackRFLNAGain gain) throws UsbException
+ {
+ int result = readByte(Request.SET_LNA_GAIN, 0, gain.getValue(), true);
+
+ if(result != 1)
+ {
+ throw new UsbException("couldn't set lna gain to " + gain);
+ }
+ }
+
+ /**
+ * Sets the Baseband VGA Gain
+ */
+ public void setVGAGain(HackRFVGAGain gain) throws UsbException
+ {
+ int result = readByte(Request.SET_VGA_GAIN, 0, gain.getValue(), true);
+
+ if(result != 1)
+ {
+ throw new UsbException("couldn't set vga gain to " + gain);
+ }
+ }
+
+ /**
+ * Not implemented
+ */
public long getTunedFrequency() throws SourceException
{
- return mFrequencyController.getTunedFrequency();
+ return mFrequencyController.getTunedFrequency();
}
- @Override
- public void setTunedFrequency( long frequency ) throws SourceException
+ @Override
+ public void setTunedFrequency(long frequency) throws SourceException
{
- ByteBuffer buffer = ByteBuffer.allocateDirect( 8 );
- buffer.order( ByteOrder.LITTLE_ENDIAN );
-
- int mhz = (int)( frequency / 1E6 );
- int hz = (int)( frequency - ( mhz * 1E6 ) );
+ ByteBuffer buffer = ByteBuffer.allocateDirect(8);
+ buffer.order(ByteOrder.LITTLE_ENDIAN);
- buffer.putInt( mhz );
- buffer.putInt( hz );
+ int mhz = (int) (frequency / 1E6);
+ int hz = (int) (frequency - (mhz * 1E6));
- buffer.rewind();
+ buffer.putInt(mhz);
+ buffer.putInt(hz);
- try
- {
- write( Request.SET_FREQUENCY, 0, 0, buffer );
- }
- catch( UsbException e )
- {
- mLog.error( "error setting frequency [" + frequency + "]", e );
-
- throw new SourceException( "error setting frequency [" +
- frequency + "]", e );
- }
+ buffer.rewind();
+
+ try
+ {
+ write(Request.SET_FREQUENCY, 0, 0, buffer);
+ }
+ catch(UsbException e)
+ {
+ mLog.error("error setting frequency [" + frequency + "]", e);
+
+ throw new SourceException("error setting frequency [" +
+ frequency + "]", e);
+ }
}
- @Override
+ @Override
public int getCurrentSampleRate() throws SourceException
{
- return mSampleRate.getRate();
+ return mSampleRate.getRate();
}
- @Override
- public void apply( TunerConfiguration config ) throws SourceException
+ @Override
+ public void apply(TunerConfiguration config) throws SourceException
{
- if( config instanceof HackRFTunerConfiguration )
- {
- HackRFTunerConfiguration hackRFConfig =
- (HackRFTunerConfiguration)config;
-
- try
- {
- setSampleRate( hackRFConfig.getSampleRate() );
- setFrequencyCorrection( hackRFConfig.getFrequencyCorrection() );
- setAmplifierEnabled( hackRFConfig.getAmplifierEnabled() );
- setLNAGain( hackRFConfig.getLNAGain() );
- setVGAGain( hackRFConfig.getVGAGain() );
- setFrequency( getFrequency() );
- }
- catch ( UsbException e )
- {
- throw new SourceException( "Error while applying tuner "
- + "configuration", e );
- }
-
- try
- {
- setFrequency( hackRFConfig.getFrequency() );
- }
- catch( SourceException se )
- {
- //Do nothing, we couldn't set the frequency
- }
- }
- else
- {
- throw new IllegalArgumentException( "Invalid tuner configuration "
- + "type [" + config.getClass() + "]" );
- }
- }
-
- public ByteBuffer readArray( Request request,
- int value,
- int index,
- int length ) throws UsbException
- {
- if( mDeviceHandle != null )
- {
- ByteBuffer buffer = ByteBuffer.allocateDirect( length );
-
- int transferred = LibUsb.controlTransfer( mDeviceHandle,
- REQUEST_TYPE_IN,
- request.getRequestNumber(),
- (short)value,
- (short)index,
- buffer,
- USB_TIMEOUT_US );
-
- if( transferred < 0 )
- {
- throw new LibUsbException( "read error", transferred );
- }
-
- return buffer;
- }
- else
- {
- throw new LibUsbException( "device handle is null",
- LibUsb.ERROR_NO_DEVICE );
- }
- }
-
- public int read( Request request, int value, int index, int length )
- throws UsbException
- {
- if( !( length == 1 || length == 2 || length == 4 ) )
- {
- throw new IllegalArgumentException( "invalid length [" + length +
- "] must be: byte=1, short=2, int=4 to read a primitive" );
- }
-
- ByteBuffer buffer = readArray( request, value, index, length );
-
- byte[] data = new byte[ buffer.capacity() ];
-
- buffer.get( data );
-
- switch( data.length )
- {
- case 1:
- return data[ 0 ];
- case 2:
- return EndianUtils.readSwappedShort( data, 0 );
- case 4:
- return EndianUtils.readSwappedInteger( data, 0 );
- default:
- throw new UsbException( "read() primitive returned an "
- + "unrecognized byte array " + Arrays.toString( data ) );
- }
- }
-
- public int readByte( Request request, int value, int index, boolean signed )
- throws UsbException
- {
- ByteBuffer buffer = readArray( request, value, index, 1 );
-
- if( signed )
- {
- return (int)( buffer.get() );
- }
- else
- {
- return (int)( buffer.get() & 0xFF );
- }
- }
-
- public void write( Request request,
- int value,
- int index,
- ByteBuffer buffer ) throws UsbException
- {
- if( mDeviceHandle != null )
- {
- int transferred = LibUsb.controlTransfer( mDeviceHandle,
- REQUEST_TYPE_OUT,
- request.getRequestNumber(),
- (short)value,
- (short)index,
- buffer,
- USB_TIMEOUT_US );
-
- if( transferred < 0 )
- {
- throw new LibUsbException( "error writing byte buffer",
- transferred );
- }
- else if( transferred != buffer.capacity() )
- {
- throw new LibUsbException( "transferred bytes [" +
- transferred + "] is not what was expected [" +
- buffer.capacity() + "]", transferred );
- }
- }
- else
- {
- throw new LibUsbException( "device handle is null",
- LibUsb.ERROR_NO_DEVICE );
- }
- }
-
- /**
- * Sends a request that doesn't have a data payload
- */
- public void write( Request request,
- int value,
- int index ) throws UsbException
- {
- write( request, value, index, ByteBuffer.allocateDirect( 0 ) );
- }
-
- /**
- * Sample Rate
- *
- * Note: the libhackrf set sample rate method is designed to allow fractional
- * sample rates. However, since we're only using integral sample rates, we
- * simply invoke the setSampleRateManual method directly.
- */
- public void setSampleRate( HackRFSampleRate rate ) throws UsbException, SourceException
- {
- setSampleRateManual( rate.getRate(), 1 );
-
- mFrequencyController.setSampleRate( rate.getRate() );
-
- setBasebandFilter( rate.getFilter() );
-
- mSampleRate = rate;
- }
-
- public void setSampleRateManual( int frequency, int divider )
- throws UsbException
- {
- ByteBuffer buffer = ByteBuffer.allocateDirect( 8 );
-
- buffer.order( ByteOrder.LITTLE_ENDIAN );
-
- buffer.putInt( frequency );
- buffer.putInt( divider );
-
- write( Request.SET_SAMPLE_RATE, 0, 0, buffer );
- }
-
- public int getSampleRate()
- {
- return mSampleRate.getRate();
- }
-
- public enum Request
- {
- SET_TRANSCEIVER_MODE( 1 ),
- MAX2837_TRANSCEIVER_WRITE( 2 ),
- MAX2837_TRANSCEIVER_READ( 3 ),
- SI5351C_CLOCK_GENERATOR_WRITE( 4 ),
- SI5351C_CLOCK_GENERATOR_READ( 5 ),
- SET_SAMPLE_RATE( 6 ),
- BASEBAND_FILTER_BANDWIDTH_SET( 7 ),
- RFFC5071_MIXER_WRITE( 8 ),
- RFFC5071_MIXER_READ( 9 ),
- SPIFLASH_ERASE( 10 ),
- SPIFLASH_WRITE( 11 ),
- SPIFLASH_READ( 12 ),
- BOARD_ID_READ( 14 ),
- VERSION_STRING_READ( 15 ),
- SET_FREQUENCY( 16 ),
- AMP_ENABLE( 17 ),
- BOARD_PARTID_SERIALNO_READ( 18 ),
- SET_LNA_GAIN( 19 ),
- SET_VGA_GAIN( 20 ),
- SET_TXVGA_GAIN( 21 ),
- ANTENNA_ENABLE( 23 ),
- SET_FREQUENCY_EXPLICIT( 24 );
-
- private byte mRequestNumber;
-
- private Request( int number )
- {
- mRequestNumber = (byte)number;
- }
-
- public byte getRequestNumber()
- {
- return mRequestNumber;
- }
- }
-
- public enum HackRFSampleRate
- {
- RATE2_016MHZ( 2016000, "2.016 MHz", BasebandFilter.F3_50 ),
- RATE3_024MHZ( 3024000, "3.024 MHz", BasebandFilter.F5_00 ),
- RATE4_464MHZ( 4464000, "4.464 MHz", BasebandFilter.F6_00 ),
- RATE5_376MHZ( 5376000, "5.376 MHz", BasebandFilter.F7_00 ),
- RATE7_488MHZ( 7488000, "7.488 MHz", BasebandFilter.F9_00 ),
- RATE10_080MHZ( 10080000, "10.080 MHz", BasebandFilter.F12_00 ),
- RATE12_000MHZ( 12000000, "12.000 MHz", BasebandFilter.F14_00 ),
- RATE13_440MHZ( 13440000, "13.440 MHz", BasebandFilter.F15_00 ),
- RATE14_976MHZ( 14976000, "14.976 MHz", BasebandFilter.F20_00 ),
- RATE19_968MHZ( 19968000, "19.968 MHz", BasebandFilter.F24_00 );
-
- private int mRate;
- private String mLabel;
- private BasebandFilter mFilter;
-
- private HackRFSampleRate( int rate,
- String label,
- BasebandFilter filter )
- {
- mRate = rate;
- mLabel = label;
- mFilter = filter;
- }
-
- public int getRate()
- {
- return mRate;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
-
- public String toString()
- {
- return mLabel;
- }
-
- public BasebandFilter getFilter()
- {
- return mFilter;
- }
- }
-
- public enum BasebandFilter
- {
- FAUTO( 0, "AUTO" ),
- F1_75( 1750000, "1.75 MHz" ),
- F2_50( 2500000, "2.50 MHz" ),
- F3_50( 3500000, "3.50 MHz" ),
- F5_00( 5000000, "5.00 MHz" ),
- F5_50( 5500000, "5.50 MHz" ),
- F6_00( 6000000, "6.00 MHz" ),
- F7_00( 7000000, "7.00 MHz" ),
- F8_00( 8000000, "8.00 MHz" ),
- F9_00( 9000000, "9.00 MHz" ),
- F10_00( 10000000, "10.00 MHz" ),
- F12_00( 12000000, "12.00 MHz" ),
- F14_00( 14000000, "14.00 MHz" ),
- F15_00( 15000000, "15.00 MHz" ),
- F20_00( 20000000, "20.00 MHz" ),
- F24_00( 24000000, "24.00 MHz" ),
- F28_00( 28000000, "28.00 MHz" );
-
- private int mBandwidth;
- private String mLabel;
-
- private BasebandFilter( int bandwidth, String label )
- {
- mBandwidth = bandwidth;
- mLabel = label;
- }
-
- public int getBandwidth()
- {
- return mBandwidth;
- }
-
- public int getHighValue()
- {
- return mBandwidth >> 16;
- }
-
- public int getLowValue()
- {
- return mBandwidth & 0xFFFF;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
- }
-
- public enum BoardID
- {
- JELLYBEAN( 0x00, "HackRF Jelly Bean" ),
- JAWBREAKER( 0x01, "HackRF Jaw Breaker" ),
- HACKRF_ONE( 0x02, "HackRF One" ),
- INVALID( 0xFF, "HackRF Unknown Board" );
-
- private byte mIDNumber;
- private String mLabel;
-
- private BoardID( int number, String label )
- {
- mIDNumber = (byte)number;
- mLabel = label;
- }
-
- public String toString()
- {
- return mLabel;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
-
- public byte getNumber()
- {
- return mIDNumber;
- }
-
- public static BoardID lookup( int value )
- {
- switch( value )
- {
- case 0:
- return JELLYBEAN;
- case 1:
- return JAWBREAKER;
- case 2:
- return HACKRF_ONE;
- default:
- return INVALID;
- }
- }
- }
-
- public enum Mode
- {
- OFF( 0, "Off" ),
- RECEIVE( 1, "Receive" ),
- TRANSMIT( 2, "Transmit" ),
- SS( 3, "SS" );
-
- private byte mNumber;
- private String mLabel;
-
- private Mode( int number, String label )
- {
- mNumber = (byte)number;
- mLabel = label;
- }
-
- public byte getNumber()
- {
- return mNumber;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
-
- public String toString()
- {
- return mLabel;
- }
- }
-
- public enum HackRFLNAGain
- {
- GAIN_0( 0 ),
- GAIN_8( 8 ),
- GAIN_16( 16 ),
- GAIN_24( 24 ),
- GAIN_32( 32 ),
- GAIN_40( 40 );
-
- private int mValue;
-
- private HackRFLNAGain( int value )
- {
- mValue = value;
- }
-
- public int getValue()
- {
- return mValue;
- }
-
- public String toString()
- {
- return String.valueOf( mValue ) + " dB";
- }
- }
-
- /**
- * Receive (baseband) VGA Gain values
- */
- public enum HackRFVGAGain
- {
- GAIN_0( 0 ),
- GAIN_2( 2 ),
- GAIN_4( 4 ),
- GAIN_6( 6 ),
- GAIN_8( 8 ),
- GAIN_10( 10 ),
- GAIN_12( 12 ),
- GAIN_14( 14 ),
- GAIN_16( 16 ),
- GAIN_18( 18 ),
- GAIN_20( 20 ),
- GAIN_22( 22 ),
- GAIN_23( 24 ),
- GAIN_26( 26 ),
- GAIN_28( 28 ),
- GAIN_30( 30 ),
- GAIN_32( 32 ),
- GAIN_34( 34 ),
- GAIN_36( 36 ),
- GAIN_38( 38 ),
- GAIN_40( 40 ),
- GAIN_42( 42 ),
- GAIN_44( 44 ),
- GAIN_46( 46 ),
- GAIN_48( 48 ),
- GAIN_50( 50 ),
- GAIN_52( 52 ),
- GAIN_54( 54 ),
- GAIN_56( 56 ),
- GAIN_58( 58 ),
- GAIN_60( 60 ),
- GAIN_62( 62 );
-
- private int mValue;
-
- private HackRFVGAGain( int value )
- {
- mValue = value;
- }
-
- public int getValue()
- {
- return mValue;
- }
-
- public String toString()
- {
- return String.valueOf( mValue ) + " dB";
- }
- }
-
- /**
- * HackRF part id and serial number parsing class
- */
- public class Serial
- {
- private byte[] mData;
-
- public Serial( ByteBuffer buffer )
- {
- mData = new byte[ buffer.capacity() ];
-
- buffer.get( mData );
- }
-
- public String getPartID()
- {
- int part0 = EndianUtils.readSwappedInteger( mData, 0 );
- int part1 = EndianUtils.readSwappedInteger( mData, 4 );
-
- StringBuilder sb = new StringBuilder();
-
- sb.append( String.format( "%08X", part0 ) );
- sb.append( "-" );
- sb.append( String.format( "%08X", part1 ) );
-
- return sb.toString();
- }
-
- public String getSerialNumber()
- {
- int serial0 = EndianUtils.readSwappedInteger( mData, 8 );
- int serial1 = EndianUtils.readSwappedInteger( mData, 12 );
- int serial2 = EndianUtils.readSwappedInteger( mData, 16 );
- int serial3 = EndianUtils.readSwappedInteger( mData, 20 );
-
- StringBuilder sb = new StringBuilder();
-
- sb.append( String.format( "%08X", serial0 ) );
- sb.append( "-" );
- sb.append( String.format( "%08X", serial1 ) );
- sb.append( "-" );
- sb.append( String.format( "%08X", serial2 ) );
- sb.append( "-" );
- sb.append( String.format( "%08X", serial3 ) );
-
- return sb.toString();
- }
- }
-
- /**
- * Adds a sample listener. If the buffer processing thread is
- * not currently running, starts it running in a new thread.
- */
- public void addListener( Listener listener )
- {
- synchronized ( mComplexBufferBroadcaster )
- {
- mComplexBufferBroadcaster.addListener( listener );
-
- if( mBufferProcessor == null || !mBufferProcessor.isRunning() )
- {
- mBufferProcessor = new BufferProcessor();
-
- Thread thread = new Thread( mBufferProcessor );
- thread.setDaemon( true );
- thread.setName( "HackRF Sample Processor" );
-
- thread.start();
- }
- }
- }
-
- /**
- * Removes the sample listener. If this is the last registered listener,
- * shuts down the buffer processing thread.
- */
- public void removeListener( Listener listener )
- {
- synchronized ( mComplexBufferBroadcaster )
- {
- mComplexBufferBroadcaster.removeListener( listener );
-
- if( !mComplexBufferBroadcaster.hasListeners() )
- {
- mBufferProcessor.stop();
- }
- }
- }
-
- /**
- * Buffer processing thread. Fetches samples from the HackRF Tuner and
- * dispatches them to all registered listeners
- */
- public class BufferProcessor implements Runnable, TransferCallback
- {
- private ScheduledFuture> mSampleDispatcherTask;
- private AtomicBoolean mRunning = new AtomicBoolean();
- private LinkedTransferQueue mAvailableTransfers;
- private LinkedTransferQueue mTransfersInProgress = new LinkedTransferQueue<>();
- private ByteBuffer mLibUsbHandlerStatus;
- private boolean mCancel = false;
-
- @Override
- public void run()
+ if(config instanceof HackRFTunerConfiguration)
{
- if( mRunning.compareAndSet( false, true ) )
- {
- prepareTransfers();
-
- mSampleDispatcherTask = mThreadPoolManager.scheduleFixedRate(
- ThreadType.SOURCE_SAMPLE_PROCESSING, new BufferDispatcher(),
- 20, TimeUnit.MILLISECONDS );
+ HackRFTunerConfiguration hackRFConfig =
+ (HackRFTunerConfiguration) config;
- mLibUsbHandlerStatus = ByteBuffer.allocateDirect( 4 );
-
- List transfers = new ArrayList<>();
-
- mCancel = false;
-
- while( mRunning.get() )
- {
- mAvailableTransfers.drainTo( transfers );
-
- for( Transfer transfer: transfers )
- {
- int result = LibUsb.submitTransfer( transfer );
-
- if( result == LibUsb.SUCCESS )
- {
- mTransfersInProgress.add( transfer );
- }
- else
- {
- mLog.error( "error submitting transfer [" +
- LibUsb.errorName( result ) + "]" );
- }
- }
-
- int result = LibUsb.handleEventsTimeoutCompleted(
- null, USB_TIMEOUT_US, mLibUsbHandlerStatus.asIntBuffer() );
-
- if( result != LibUsb.SUCCESS )
- {
- mLog.error( "error handling events for libusb" );
- }
-
- transfers.clear();
-
- mLibUsbHandlerStatus.rewind();
- }
-
- if( mCancel )
- {
- for( Transfer transfer: mTransfersInProgress )
- {
- LibUsb.cancelTransfer( transfer );
- }
-
- int result = LibUsb.handleEventsTimeoutCompleted( null,
- USB_TIMEOUT_US, mLibUsbHandlerStatus.asIntBuffer() );
-
- if( result != LibUsb.SUCCESS )
- {
- mLog.error( "error cancelling transfers in progress" );
- }
-
- mLibUsbHandlerStatus.rewind();
- }
- }
+ try
+ {
+ setSampleRate(hackRFConfig.getSampleRate());
+ setFrequencyCorrection(hackRFConfig.getFrequencyCorrection());
+ setAmplifierEnabled(hackRFConfig.getAmplifierEnabled());
+ setLNAGain(hackRFConfig.getLNAGain());
+ setVGAGain(hackRFConfig.getVGAGain());
+ setFrequency(getFrequency());
+ }
+ catch(UsbException e)
+ {
+ throw new SourceException("Error while applying tuner "
+ + "configuration", e);
+ }
+
+ try
+ {
+ setFrequency(hackRFConfig.getFrequency());
+ }
+ catch(SourceException se)
+ {
+ //Do nothing, we couldn't set the frequency
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("Invalid tuner configuration "
+ + "type [" + config.getClass() + "]");
+ }
+ }
+
+ public ByteBuffer readArray(Request request,
+ int value,
+ int index,
+ int length) throws UsbException
+ {
+ if(mDeviceHandle != null)
+ {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(length);
+
+ int transferred = LibUsb.controlTransfer(mDeviceHandle,
+ REQUEST_TYPE_IN,
+ request.getRequestNumber(),
+ (short) value,
+ (short) index,
+ buffer,
+ USB_TIMEOUT_US);
+
+ if(transferred < 0)
+ {
+ throw new LibUsbException("read error", transferred);
+ }
+
+ return buffer;
+ }
+ else
+ {
+ throw new LibUsbException("device handle is null",
+ LibUsb.ERROR_NO_DEVICE);
+ }
+ }
+
+ public int read(Request request, int value, int index, int length)
+ throws UsbException
+ {
+ if(!(length == 1 || length == 2 || length == 4))
+ {
+ throw new IllegalArgumentException("invalid length [" + length +
+ "] must be: byte=1, short=2, int=4 to read a primitive");
}
- /**
- * Stops the sample fetching thread
- */
- public void stop()
- {
- mCancel = true;
-
- if( mRunning.compareAndSet( true, false ) )
- {
- if( mSampleDispatcherTask != null )
- {
- mSampleDispatcherTask.cancel( true );
- mFilledBuffers.clear();
- }
- }
- }
+ ByteBuffer buffer = readArray(request, value, index, length);
- /**
- * Indicates if this thread is running
- */
- public boolean isRunning()
- {
- return mRunning.get();
- }
-
- @Override
- public void processTransfer( Transfer transfer )
- {
- mTransfersInProgress.remove( transfer );
-
- switch( transfer.status() )
- {
- case LibUsb.TRANSFER_COMPLETED:
- case LibUsb.TRANSFER_STALL:
- if( transfer.actualLength() > 0 )
- {
- ByteBuffer buffer = transfer.buffer();
-
- byte[] data = new byte[ transfer.actualLength() ];
-
- buffer.get( data );
+ byte[] data = new byte[buffer.capacity()];
- buffer.rewind();
+ buffer.get(data);
- if( isRunning() )
- {
- mFilledBuffers.add( data );
- }
- }
- break;
- case LibUsb.TRANSFER_CANCELLED:
- break;
- default:
- /* unexpected error */
- mLog.error( "transfer error [" +
- getTransferStatus( transfer.status() ) +
- "] transferred actual: " + transfer.actualLength() );
- }
-
- mAvailableTransfers.add( transfer );
- }
-
- /**
- * Prepares (allocates) a set of transfer buffers for use in
- * transferring data from the tuner via the bulk interface
- */
- private void prepareTransfers() throws LibUsbException
- {
- if( mAvailableTransfers == null )
- {
- mAvailableTransfers = new LinkedTransferQueue<>();
-
- for( int x = 0; x < TRANSFER_BUFFER_POOL_SIZE; x++ )
- {
- Transfer transfer = LibUsb.allocTransfer();
+ switch(data.length)
+ {
+ case 1:
+ return data[0];
+ case 2:
+ return EndianUtils.readSwappedShort(data, 0);
+ case 4:
+ return EndianUtils.readSwappedInteger(data, 0);
+ default:
+ throw new UsbException("read() primitive returned an "
+ + "unrecognized byte array " + Arrays.toString(data));
+ }
+ }
- if( transfer == null )
- {
- throw new LibUsbException( "couldn't allocate transfer",
- LibUsb.ERROR_NO_MEM );
- }
-
- final ByteBuffer buffer =
- ByteBuffer.allocateDirect( mBufferSize );
-
- LibUsb.fillBulkTransfer( transfer, mDeviceHandle,USB_ENDPOINT,
- buffer, BufferProcessor.this, "Buffer", USB_TIMEOUT_US );
+ public int readByte(Request request, int value, int index, boolean signed)
+ throws UsbException
+ {
+ ByteBuffer buffer = readArray(request, value, index, 1);
- mAvailableTransfers.add( transfer );
- }
- }
- }
- }
+ if(signed)
+ {
+ return (int) (buffer.get());
+ }
+ else
+ {
+ return (int) (buffer.get() & 0xFF);
+ }
+ }
- /**
- * Fetches byte[] chunks from the raw sample buffer. Converts each byte
- * array and broadcasts the array to all registered listeners
- */
- public class BufferDispatcher implements Runnable
- {
- @Override
+ public void write(Request request,
+ int value,
+ int index,
+ ByteBuffer buffer) throws UsbException
+ {
+ if(mDeviceHandle != null)
+ {
+ int transferred = LibUsb.controlTransfer(mDeviceHandle,
+ REQUEST_TYPE_OUT,
+ request.getRequestNumber(),
+ (short) value,
+ (short) index,
+ buffer,
+ USB_TIMEOUT_US);
+
+ if(transferred < 0)
+ {
+ throw new LibUsbException("error writing byte buffer",
+ transferred);
+ }
+ else if(transferred != buffer.capacity())
+ {
+ throw new LibUsbException("transferred bytes [" +
+ transferred + "] is not what was expected [" +
+ buffer.capacity() + "]", transferred);
+ }
+ }
+ else
+ {
+ throw new LibUsbException("device handle is null",
+ LibUsb.ERROR_NO_DEVICE);
+ }
+ }
+
+ /**
+ * Sends a request that doesn't have a data payload
+ */
+ public void write(Request request,
+ int value,
+ int index) throws UsbException
+ {
+ write(request, value, index, ByteBuffer.allocateDirect(0));
+ }
+
+ /**
+ * Sample Rate
+ *
+ * Note: the libhackrf set sample rate method is designed to allow fractional
+ * sample rates. However, since we're only using integral sample rates, we
+ * simply invoke the setSampleRateManual method directly.
+ */
+ public void setSampleRate(HackRFSampleRate rate) throws UsbException, SourceException
+ {
+ setSampleRateManual(rate.getRate(), 1);
+
+ mFrequencyController.setSampleRate(rate.getRate());
+
+ setBasebandFilter(rate.getFilter());
+
+ mSampleRate = rate;
+ }
+
+ public void setSampleRateManual(int frequency, int divider)
+ throws UsbException
+ {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(8);
+
+ buffer.order(ByteOrder.LITTLE_ENDIAN);
+
+ buffer.putInt(frequency);
+ buffer.putInt(divider);
+
+ write(Request.SET_SAMPLE_RATE, 0, 0, buffer);
+ }
+
+ public int getSampleRate()
+ {
+ return mSampleRate.getRate();
+ }
+
+ public enum Request
+ {
+ SET_TRANSCEIVER_MODE(1),
+ MAX2837_TRANSCEIVER_WRITE(2),
+ MAX2837_TRANSCEIVER_READ(3),
+ SI5351C_CLOCK_GENERATOR_WRITE(4),
+ SI5351C_CLOCK_GENERATOR_READ(5),
+ SET_SAMPLE_RATE(6),
+ BASEBAND_FILTER_BANDWIDTH_SET(7),
+ RFFC5071_MIXER_WRITE(8),
+ RFFC5071_MIXER_READ(9),
+ SPIFLASH_ERASE(10),
+ SPIFLASH_WRITE(11),
+ SPIFLASH_READ(12),
+ BOARD_ID_READ(14),
+ VERSION_STRING_READ(15),
+ SET_FREQUENCY(16),
+ AMP_ENABLE(17),
+ BOARD_PARTID_SERIALNO_READ(18),
+ SET_LNA_GAIN(19),
+ SET_VGA_GAIN(20),
+ SET_TXVGA_GAIN(21),
+ ANTENNA_ENABLE(23),
+ SET_FREQUENCY_EXPLICIT(24);
+
+ private byte mRequestNumber;
+
+ private Request(int number)
+ {
+ mRequestNumber = (byte) number;
+ }
+
+ public byte getRequestNumber()
+ {
+ return mRequestNumber;
+ }
+ }
+
+ public enum HackRFSampleRate
+ {
+ RATE2_016MHZ(2016000, "2.016 MHz", BasebandFilter.F3_50),
+ RATE3_024MHZ(3024000, "3.024 MHz", BasebandFilter.F5_00),
+ RATE4_464MHZ(4464000, "4.464 MHz", BasebandFilter.F6_00),
+ RATE5_376MHZ(5376000, "5.376 MHz", BasebandFilter.F7_00),
+ RATE7_488MHZ(7488000, "7.488 MHz", BasebandFilter.F9_00),
+ RATE10_080MHZ(10080000, "10.080 MHz", BasebandFilter.F12_00),
+ RATE12_000MHZ(12000000, "12.000 MHz", BasebandFilter.F14_00),
+ RATE13_440MHZ(13440000, "13.440 MHz", BasebandFilter.F15_00),
+ RATE14_976MHZ(14976000, "14.976 MHz", BasebandFilter.F20_00),
+ RATE19_968MHZ(19968000, "19.968 MHz", BasebandFilter.F24_00);
+
+ private int mRate;
+ private String mLabel;
+ private BasebandFilter mFilter;
+
+ private HackRFSampleRate(int rate,
+ String label,
+ BasebandFilter filter)
+ {
+ mRate = rate;
+ mLabel = label;
+ mFilter = filter;
+ }
+
+ public int getRate()
+ {
+ return mRate;
+ }
+
+ public String getLabel()
+ {
+ return mLabel;
+ }
+
+ public String toString()
+ {
+ return mLabel;
+ }
+
+ public BasebandFilter getFilter()
+ {
+ return mFilter;
+ }
+ }
+
+ public enum BasebandFilter
+ {
+ FAUTO(0, "AUTO"),
+ F1_75(1750000, "1.75 MHz"),
+ F2_50(2500000, "2.50 MHz"),
+ F3_50(3500000, "3.50 MHz"),
+ F5_00(5000000, "5.00 MHz"),
+ F5_50(5500000, "5.50 MHz"),
+ F6_00(6000000, "6.00 MHz"),
+ F7_00(7000000, "7.00 MHz"),
+ F8_00(8000000, "8.00 MHz"),
+ F9_00(9000000, "9.00 MHz"),
+ F10_00(10000000, "10.00 MHz"),
+ F12_00(12000000, "12.00 MHz"),
+ F14_00(14000000, "14.00 MHz"),
+ F15_00(15000000, "15.00 MHz"),
+ F20_00(20000000, "20.00 MHz"),
+ F24_00(24000000, "24.00 MHz"),
+ F28_00(28000000, "28.00 MHz");
+
+ private int mBandwidth;
+ private String mLabel;
+
+ private BasebandFilter(int bandwidth, String label)
+ {
+ mBandwidth = bandwidth;
+ mLabel = label;
+ }
+
+ public int getBandwidth()
+ {
+ return mBandwidth;
+ }
+
+ public int getHighValue()
+ {
+ return mBandwidth >> 16;
+ }
+
+ public int getLowValue()
+ {
+ return mBandwidth & 0xFFFF;
+ }
+
+ public String getLabel()
+ {
+ return mLabel;
+ }
+ }
+
+ public enum BoardID
+ {
+ JELLYBEAN(0x00, "HackRF Jelly Bean"),
+ JAWBREAKER(0x01, "HackRF Jaw Breaker"),
+ HACKRF_ONE(0x02, "HackRF One"),
+ INVALID(0xFF, "HackRF Unknown Board");
+
+ private byte mIDNumber;
+ private String mLabel;
+
+ private BoardID(int number, String label)
+ {
+ mIDNumber = (byte) number;
+ mLabel = label;
+ }
+
+ public String toString()
+ {
+ return mLabel;
+ }
+
+ public String getLabel()
+ {
+ return mLabel;
+ }
+
+ public byte getNumber()
+ {
+ return mIDNumber;
+ }
+
+ public static BoardID lookup(int value)
+ {
+ switch(value)
+ {
+ case 0:
+ return JELLYBEAN;
+ case 1:
+ return JAWBREAKER;
+ case 2:
+ return HACKRF_ONE;
+ default:
+ return INVALID;
+ }
+ }
+ }
+
+ public enum Mode
+ {
+ OFF(0, "Off"),
+ RECEIVE(1, "Receive"),
+ TRANSMIT(2, "Transmit"),
+ SS(3, "SS");
+
+ private byte mNumber;
+ private String mLabel;
+
+ private Mode(int number, String label)
+ {
+ mNumber = (byte) number;
+ mLabel = label;
+ }
+
+ public byte getNumber()
+ {
+ return mNumber;
+ }
+
+ public String getLabel()
+ {
+ return mLabel;
+ }
+
+ public String toString()
+ {
+ return mLabel;
+ }
+ }
+
+ public enum HackRFLNAGain
+ {
+ GAIN_0(0),
+ GAIN_8(8),
+ GAIN_16(16),
+ GAIN_24(24),
+ GAIN_32(32),
+ GAIN_40(40);
+
+ private int mValue;
+
+ private HackRFLNAGain(int value)
+ {
+ mValue = value;
+ }
+
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ public String toString()
+ {
+ return String.valueOf(mValue) + " dB";
+ }
+ }
+
+ /**
+ * Receive (baseband) VGA Gain values
+ */
+ public enum HackRFVGAGain
+ {
+ GAIN_0(0),
+ GAIN_2(2),
+ GAIN_4(4),
+ GAIN_6(6),
+ GAIN_8(8),
+ GAIN_10(10),
+ GAIN_12(12),
+ GAIN_14(14),
+ GAIN_16(16),
+ GAIN_18(18),
+ GAIN_20(20),
+ GAIN_22(22),
+ GAIN_23(24),
+ GAIN_26(26),
+ GAIN_28(28),
+ GAIN_30(30),
+ GAIN_32(32),
+ GAIN_34(34),
+ GAIN_36(36),
+ GAIN_38(38),
+ GAIN_40(40),
+ GAIN_42(42),
+ GAIN_44(44),
+ GAIN_46(46),
+ GAIN_48(48),
+ GAIN_50(50),
+ GAIN_52(52),
+ GAIN_54(54),
+ GAIN_56(56),
+ GAIN_58(58),
+ GAIN_60(60),
+ GAIN_62(62);
+
+ private int mValue;
+
+ private HackRFVGAGain(int value)
+ {
+ mValue = value;
+ }
+
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ public String toString()
+ {
+ return String.valueOf(mValue) + " dB";
+ }
+ }
+
+ /**
+ * HackRF part id and serial number parsing class
+ */
+ public class Serial
+ {
+ private byte[] mData;
+
+ public Serial(ByteBuffer buffer)
+ {
+ mData = new byte[buffer.capacity()];
+
+ buffer.get(mData);
+ }
+
+ public String getPartID()
+ {
+ int part0 = EndianUtils.readSwappedInteger(mData, 0);
+ int part1 = EndianUtils.readSwappedInteger(mData, 4);
+
+ StringBuilder sb = new StringBuilder();
+
+ sb.append(String.format("%08X", part0));
+ sb.append("-");
+ sb.append(String.format("%08X", part1));
+
+ return sb.toString();
+ }
+
+ public String getSerialNumber()
+ {
+ int serial0 = EndianUtils.readSwappedInteger(mData, 8);
+ int serial1 = EndianUtils.readSwappedInteger(mData, 12);
+ int serial2 = EndianUtils.readSwappedInteger(mData, 16);
+ int serial3 = EndianUtils.readSwappedInteger(mData, 20);
+
+ StringBuilder sb = new StringBuilder();
+
+ sb.append(String.format("%08X", serial0));
+ sb.append("-");
+ sb.append(String.format("%08X", serial1));
+ sb.append("-");
+ sb.append(String.format("%08X", serial2));
+ sb.append("-");
+ sb.append(String.format("%08X", serial3));
+
+ return sb.toString();
+ }
+ }
+
+ /**
+ * Adds a sample listener. If the buffer processing thread is
+ * not currently running, starts it running in a new thread.
+ */
+ public void addListener(Listener listener)
+ {
+ synchronized(mComplexBufferBroadcaster)
+ {
+ mComplexBufferBroadcaster.addListener(listener);
+
+ if(mBufferProcessor == null || !mBufferProcessor.isRunning())
+ {
+ mBufferProcessor = new BufferProcessor();
+
+ Thread thread = new Thread(mBufferProcessor);
+ thread.setDaemon(true);
+ thread.setName("HackRF Sample Processor");
+
+ thread.start();
+ }
+ }
+ }
+
+ /**
+ * Removes the sample listener. If this is the last registered listener,
+ * shuts down the buffer processing thread.
+ */
+ public void removeListener(Listener listener)
+ {
+ synchronized(mComplexBufferBroadcaster)
+ {
+ mComplexBufferBroadcaster.removeListener(listener);
+
+ if(!mComplexBufferBroadcaster.hasListeners())
+ {
+ mBufferProcessor.stop();
+ }
+ }
+ }
+
+ /**
+ * Buffer processing thread. Fetches samples from the HackRF Tuner and
+ * dispatches them to all registered listeners
+ */
+ public class BufferProcessor implements Runnable, TransferCallback
+ {
+ private ScheduledFuture> mSampleDispatcherTask;
+ private AtomicBoolean mRunning = new AtomicBoolean();
+ private LinkedTransferQueue mAvailableTransfers;
+ private LinkedTransferQueue mTransfersInProgress = new LinkedTransferQueue<>();
+ private ByteBuffer mLibUsbHandlerStatus;
+ private boolean mCancel = false;
+
+ @Override
public void run()
{
- try
- {
- ArrayList buffers = new ArrayList();
-
- mFilledBuffers.drainTo( buffers );
+ if(mRunning.compareAndSet(false, true))
+ {
+ prepareTransfers();
- for( byte[] buffer: buffers )
- {
- float[] samples = mSampleAdapter.convert( buffer );
-
- mComplexBufferBroadcaster.broadcast( new ComplexBuffer( samples ) );
- }
- }
- catch( Exception e )
- {
- mLog.error( "error duruing HackRF buffer dispatching", e );
- }
+ mSampleDispatcherTask = ThreadPool.SCHEDULED.scheduleAtFixedRate(new BufferDispatcher(),
+ 20, 20, TimeUnit.MILLISECONDS);
+
+ mLibUsbHandlerStatus = ByteBuffer.allocateDirect(4);
+
+ List transfers = new ArrayList<>();
+
+ mCancel = false;
+
+ while(mRunning.get())
+ {
+ mAvailableTransfers.drainTo(transfers);
+
+ for(Transfer transfer : transfers)
+ {
+ int result = LibUsb.submitTransfer(transfer);
+
+ if(result == LibUsb.SUCCESS)
+ {
+ mTransfersInProgress.add(transfer);
+ }
+ else
+ {
+ mLog.error("error submitting transfer [" +
+ LibUsb.errorName(result) + "]");
+ }
+ }
+
+ int result = LibUsb.handleEventsTimeoutCompleted(
+ null, USB_TIMEOUT_US, mLibUsbHandlerStatus.asIntBuffer());
+
+ if(result != LibUsb.SUCCESS)
+ {
+ mLog.error("error handling events for libusb");
+ }
+
+ transfers.clear();
+
+ mLibUsbHandlerStatus.rewind();
+ }
+
+ if(mCancel)
+ {
+ for(Transfer transfer : mTransfersInProgress)
+ {
+ LibUsb.cancelTransfer(transfer);
+ }
+
+ int result = LibUsb.handleEventsTimeoutCompleted(null,
+ USB_TIMEOUT_US, mLibUsbHandlerStatus.asIntBuffer());
+
+ if(result != LibUsb.SUCCESS)
+ {
+ mLog.error("error cancelling transfers in progress");
+ }
+
+ mLibUsbHandlerStatus.rewind();
+ }
+ }
}
- }
-
- public static String getTransferStatus( int status )
- {
- switch( status )
- {
- case 0:
- return "TRANSFER COMPLETED (0)";
- case 1:
- return "TRANSFER ERROR (1)";
- case 2:
- return "TRANSFER TIMED OUT (2)";
- case 3:
- return "TRANSFER CANCELLED (3)";
- case 4:
- return "TRANSFER STALL (4)";
- case 5:
- return "TRANSFER NO DEVICE (5)";
- case 6:
- return "TRANSFER OVERFLOW (6)";
- default:
- return "UNKNOWN TRANSFER STATUS (" + status + ")";
- }
- }
+
+ /**
+ * Stops the sample fetching thread
+ */
+ public void stop()
+ {
+ mCancel = true;
+
+ if(mRunning.compareAndSet(true, false))
+ {
+ if(mSampleDispatcherTask != null)
+ {
+ mSampleDispatcherTask.cancel(true);
+ mFilledBuffers.clear();
+ }
+ }
+ }
+
+ /**
+ * Indicates if this thread is running
+ */
+ public boolean isRunning()
+ {
+ return mRunning.get();
+ }
+
+ @Override
+ public void processTransfer(Transfer transfer)
+ {
+ mTransfersInProgress.remove(transfer);
+
+ switch(transfer.status())
+ {
+ case LibUsb.TRANSFER_COMPLETED:
+ case LibUsb.TRANSFER_STALL:
+ if(transfer.actualLength() > 0)
+ {
+ ByteBuffer buffer = transfer.buffer();
+
+ byte[] data = new byte[transfer.actualLength()];
+
+ buffer.get(data);
+
+ buffer.rewind();
+
+ if(isRunning())
+ {
+ mFilledBuffers.add(data);
+ }
+ }
+ break;
+ case LibUsb.TRANSFER_CANCELLED:
+ break;
+ default:
+ /* unexpected error */
+ mLog.error("transfer error [" +
+ getTransferStatus(transfer.status()) +
+ "] transferred actual: " + transfer.actualLength());
+ }
+
+ mAvailableTransfers.add(transfer);
+ }
+
+ /**
+ * Prepares (allocates) a set of transfer buffers for use in
+ * transferring data from the tuner via the bulk interface
+ */
+ private void prepareTransfers() throws LibUsbException
+ {
+ if(mAvailableTransfers == null)
+ {
+ mAvailableTransfers = new LinkedTransferQueue<>();
+
+ for(int x = 0; x < TRANSFER_BUFFER_POOL_SIZE; x++)
+ {
+ Transfer transfer = LibUsb.allocTransfer();
+
+ if(transfer == null)
+ {
+ throw new LibUsbException("couldn't allocate transfer",
+ LibUsb.ERROR_NO_MEM);
+ }
+
+ final ByteBuffer buffer =
+ ByteBuffer.allocateDirect(mBufferSize);
+
+ LibUsb.fillBulkTransfer(transfer, mDeviceHandle, USB_ENDPOINT,
+ buffer, BufferProcessor.this, "Buffer", USB_TIMEOUT_US);
+
+ mAvailableTransfers.add(transfer);
+ }
+ }
+ }
+ }
+
+ /**
+ * Fetches byte[] chunks from the raw sample buffer. Converts each byte
+ * array and broadcasts the array to all registered listeners
+ */
+ public class BufferDispatcher implements Runnable
+ {
+ @Override
+ public void run()
+ {
+ try
+ {
+ ArrayList buffers = new ArrayList();
+
+ mFilledBuffers.drainTo(buffers);
+
+ for(byte[] buffer : buffers)
+ {
+ float[] samples = mSampleAdapter.convert(buffer);
+
+ mComplexBufferBroadcaster.broadcast(new ComplexBuffer(samples));
+ }
+ }
+ catch(Exception e)
+ {
+ mLog.error("error duruing HackRF buffer dispatching", e);
+ }
+ }
+ }
+
+ public static String getTransferStatus(int status)
+ {
+ switch(status)
+ {
+ case 0:
+ return "TRANSFER COMPLETED (0)";
+ case 1:
+ return "TRANSFER ERROR (1)";
+ case 2:
+ return "TRANSFER TIMED OUT (2)";
+ case 3:
+ return "TRANSFER CANCELLED (3)";
+ case 4:
+ return "TRANSFER STALL (4)";
+ case 5:
+ return "TRANSFER NO DEVICE (5)";
+ case 6:
+ return "TRANSFER OVERFLOW (6)";
+ default:
+ return "UNKNOWN TRANSFER STATUS (" + status + ")";
+ }
+ }
}
diff --git a/src/source/tuner/rtl/RTL2832TunerController.java b/src/source/tuner/rtl/RTL2832TunerController.java
index e102d4d7..d31a6499 100644
--- a/src/source/tuner/rtl/RTL2832TunerController.java
+++ b/src/source/tuner/rtl/RTL2832TunerController.java
@@ -1,26 +1,47 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 Dennis Sheirer
- *
+ *
* Java version based on librtlsdr
* Copyright (C) 2012-2013 by Steve Markgraf
* Copyright (C) 2012 by Dimitri Stolnikov
- *
+ *
* 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 source.tuner.rtl;
+import buffer.FloatAveragingBuffer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.usb4java.Device;
+import org.usb4java.DeviceDescriptor;
+import org.usb4java.DeviceHandle;
+import org.usb4java.LibUsb;
+import org.usb4java.LibUsbException;
+import org.usb4java.Transfer;
+import org.usb4java.TransferCallback;
+import sample.Broadcaster;
+import sample.Listener;
+import sample.adapter.ByteSampleAdapter;
+import sample.complex.ComplexBuffer;
+import source.SourceException;
+import source.tuner.TunerController;
+import source.tuner.TunerType;
+import util.ThreadPool;
+
+import javax.usb.UsbDisconnectedException;
+import javax.usb.UsbException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.Charset;
@@ -34,1934 +55,1894 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
-import javax.usb.UsbDisconnectedException;
-import javax.usb.UsbException;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.usb4java.Device;
-import org.usb4java.DeviceDescriptor;
-import org.usb4java.DeviceHandle;
-import org.usb4java.LibUsb;
-import org.usb4java.LibUsbException;
-import org.usb4java.Transfer;
-import org.usb4java.TransferCallback;
-
-import sample.Broadcaster;
-import sample.Listener;
-import sample.adapter.ByteSampleAdapter;
-import sample.complex.ComplexBuffer;
-import source.SourceException;
-import source.tuner.TunerController;
-import source.tuner.TunerType;
-import buffer.FloatAveragingBuffer;
-import controller.ThreadPoolManager;
-import controller.ThreadPoolManager.ThreadType;
-
public abstract class RTL2832TunerController extends TunerController
{
- private final static Logger mLog =
- LoggerFactory.getLogger( RTL2832TunerController.class );
+ private final static Logger mLog = LoggerFactory.getLogger(RTL2832TunerController.class);
- public final static int INT_NULL_VALUE = -1;
- public final static long LONG_NULL_VALUE = -1l;
- public final static double DOUBLE_NULL_VALUE = -1.0D;
- public final static int TWO_TO_22_POWER = 4194304;
-
- public final static byte USB_INTERFACE = (byte)0x0;
- public final static byte USB_BULK_ENDPOINT = (byte)0x81;
- public final static byte CONTROL_ENDPOINT_IN =
- (byte)( LibUsb.ENDPOINT_IN | LibUsb.REQUEST_TYPE_VENDOR );
- public final static byte CONTROL_ENDPOINT_OUT =
- (byte)( LibUsb.ENDPOINT_OUT | LibUsb.REQUEST_TYPE_VENDOR );
+ public final static int INT_NULL_VALUE = -1;
+ public final static long LONG_NULL_VALUE = -1l;
+ public final static double DOUBLE_NULL_VALUE = -1.0D;
+ public final static int TWO_TO_22_POWER = 4194304;
- public final static long TIMEOUT_US = 1000000l; //uSeconds
+ public final static byte USB_INTERFACE = (byte) 0x0;
+ public final static byte USB_BULK_ENDPOINT = (byte) 0x81;
+ public final static byte CONTROL_ENDPOINT_IN =
+ (byte) (LibUsb.ENDPOINT_IN | LibUsb.REQUEST_TYPE_VENDOR);
+ public final static byte CONTROL_ENDPOINT_OUT =
+ (byte) (LibUsb.ENDPOINT_OUT | LibUsb.REQUEST_TYPE_VENDOR);
- public final static byte REQUEST_ZERO = (byte)0;
-
- public final static int TRANSFER_BUFFER_POOL_SIZE = 16;
-
- public final static byte EEPROM_ADDRESS = (byte)0xA0;
-
- public final static byte[] sFIR_COEFFICIENTS =
- {
- (byte)0xCA, (byte)0xDC, (byte)0xD7, (byte)0xD8, (byte)0xE0,
- (byte)0xF2, (byte)0x0E, (byte)0x35, (byte)0x06, (byte)0x50,
- (byte)0x9C, (byte)0x0D, (byte)0x71, (byte)0x11, (byte)0x14,
- (byte)0x71, (byte)0x74, (byte)0x19, (byte)0x41, (byte)0xA5
- };
-
- public static final SampleRate DEFAULT_SAMPLE_RATE =
- SampleRate.RATE_0_960MHZ;
+ public final static long TIMEOUT_US = 1000000l; //uSeconds
- protected Device mDevice;
- protected DeviceDescriptor mDeviceDescriptor;
- protected DeviceHandle mDeviceHandle;
-
- private SampleRate mSampleRate = DEFAULT_SAMPLE_RATE;
-
- private BufferProcessor mBufferProcessor;
-
- private ByteSampleAdapter mSampleAdapter = new ByteSampleAdapter();
+ public final static byte REQUEST_ZERO = (byte) 0;
- private Broadcaster mComplexBufferBroadcaster = new Broadcaster<>();
-
- private LinkedTransferQueue mFilledBuffers =
- new LinkedTransferQueue();
-
- private SampleRateMonitor mSampleRateMonitor;
+ public final static int TRANSFER_BUFFER_POOL_SIZE = 16;
+
+ public final static byte EEPROM_ADDRESS = (byte) 0xA0;
+
+ public final static byte[] sFIR_COEFFICIENTS =
+ {
+ (byte) 0xCA, (byte) 0xDC, (byte) 0xD7, (byte) 0xD8, (byte) 0xE0,
+ (byte) 0xF2, (byte) 0x0E, (byte) 0x35, (byte) 0x06, (byte) 0x50,
+ (byte) 0x9C, (byte) 0x0D, (byte) 0x71, (byte) 0x11, (byte) 0x14,
+ (byte) 0x71, (byte) 0x74, (byte) 0x19, (byte) 0x41, (byte) 0xA5
+ };
+
+ public static final SampleRate DEFAULT_SAMPLE_RATE =
+ SampleRate.RATE_0_960MHZ;
+
+ protected Device mDevice;
+ protected DeviceDescriptor mDeviceDescriptor;
+ protected DeviceHandle mDeviceHandle;
+
+ private SampleRate mSampleRate = DEFAULT_SAMPLE_RATE;
+
+ private BufferProcessor mBufferProcessor;
+
+ private ByteSampleAdapter mSampleAdapter = new ByteSampleAdapter();
+
+ private Broadcaster mComplexBufferBroadcaster = new Broadcaster<>();
+
+ private LinkedTransferQueue mFilledBuffers =
+ new LinkedTransferQueue();
+
+ private SampleRateMonitor mSampleRateMonitor;
private AtomicInteger mSampleCounter = new AtomicInteger();
- private static final DecimalFormat mDecimalFormatter =
- new DecimalFormat( "###,###,###.0" );
- private static final DecimalFormat mPercentFormatter =
- new DecimalFormat( "###.00" );
-
- protected int mOscillatorFrequency = 28800000; //28.8 MHz
- public int mBufferSize = 131072;
+ private static final DecimalFormat mDecimalFormatter =
+ new DecimalFormat("###,###,###.0");
+ private static final DecimalFormat mPercentFormatter =
+ new DecimalFormat("###.00");
- protected Descriptor mDescriptor;
- private ThreadPoolManager mThreadPoolManager;
-
- /**
- * Abstract tuner controller device. Use the static getTunerClass() method
- * to determine the tuner type, and construct the corresponding child
- * tuner controller class for that tuner type.
- */
- public RTL2832TunerController( Device device,
- DeviceDescriptor deviceDescriptor,
- ThreadPoolManager threadPoolManager,
- long minTunableFrequency,
- long maxTunableFrequency,
- int centerUnusableBandwidth,
- double usableBandwidthPercentage ) throws SourceException
- {
- super( minTunableFrequency,
- maxTunableFrequency,
- centerUnusableBandwidth,
- usableBandwidthPercentage );
-
- mThreadPoolManager = threadPoolManager;
+ protected int mOscillatorFrequency = 28800000; //28.8 MHz
+ public int mBufferSize = 131072;
- mDevice = device;
- mDeviceDescriptor = deviceDescriptor;
- }
+ protected Descriptor mDescriptor;
-
- public void init() throws SourceException
- {
- mDeviceHandle = new DeviceHandle();
-
- int result = LibUsb.open( mDevice, mDeviceHandle );
+ /**
+ * Abstract tuner controller device. Use the static getTunerClass() method
+ * to determine the tuner type, and construct the corresponding child
+ * tuner controller class for that tuner type.
+ */
+ public RTL2832TunerController(Device device, DeviceDescriptor deviceDescriptor, long minTunableFrequency,
+ long maxTunableFrequency, int centerUnusableBandwidth,
+ double usableBandwidthPercentage) throws SourceException
+ {
+ super(minTunableFrequency,
+ maxTunableFrequency,
+ centerUnusableBandwidth,
+ usableBandwidthPercentage);
- if( result != LibUsb.SUCCESS )
- {
- mDeviceHandle = null;
-
- throw new SourceException( "libusb couldn't open RTL2832 usb "
- + "device [" + LibUsb.errorName( result ) + "]" );
- }
+ mDevice = device;
+ mDeviceDescriptor = deviceDescriptor;
+ }
- claimInterface( mDeviceHandle );
- try
- {
- setSampleRate( DEFAULT_SAMPLE_RATE );
- }
- catch( Exception e )
- {
- throw new SourceException( "RTL2832 Tuner Controller - couldn't "
- + "set default sample rate", e );
- }
+ public void init() throws SourceException
+ {
+ mDeviceHandle = new DeviceHandle();
- byte[] eeprom = null;
-
- try
- {
- /* Read the contents of the 256-byte EEPROM */
- eeprom = readEEPROM( mDeviceHandle, (short)0, 256 );
- }
- catch( Exception e )
- {
- mLog.error( "error while reading the EEPROM device descriptor", e );
- }
-
- try
- {
- mDescriptor = new Descriptor( eeprom );
+ int result = LibUsb.open(mDevice, mDeviceHandle);
- if( eeprom == null )
- {
- mLog.error( "eeprom byte array was null - constructed "
- + "empty descriptor object" );
- }
- }
- catch( Exception e )
- {
- mLog.error( "error while constructing device descriptor using "
- + "descriptor byte array " +
- ( eeprom == null ? "[null]" : Arrays.toString( eeprom )), e );
- }
- }
-
- /**
- * Claims the USB interface. Attempts to detach the active kernel driver
- * if one is currently attached.
- */
- public static void claimInterface( DeviceHandle handle ) throws SourceException
- {
- if( handle != null )
- {
- int result = LibUsb.kernelDriverActive( handle, USB_INTERFACE );
-
- if( result == 1 )
- {
- result = LibUsb.detachKernelDriver( handle, USB_INTERFACE );
+ if(result != LibUsb.SUCCESS)
+ {
+ mDeviceHandle = null;
- if( result != LibUsb.SUCCESS )
- {
- mLog.error( "failed attempt to detach kernel driver [" +
- LibUsb.errorName( result ) + "]" );
-
- throw new SourceException( "couldn't detach kernel driver "
- + "from device" );
- }
- }
-
- result = LibUsb.claimInterface( handle, USB_INTERFACE );
-
- if( result != LibUsb.SUCCESS )
- {
- throw new SourceException( "couldn't claim usb interface [" +
- LibUsb.errorName( result ) + "]" );
- }
- }
- else
- {
- throw new SourceException( "couldn't claim usb interface - no "
- + "device handle" );
- }
- }
-
- public static void releaseInterface( DeviceHandle handle )
- throws SourceException
- {
- int result = LibUsb.releaseInterface( handle, USB_INTERFACE );
-
- if( result != LibUsb.SUCCESS )
- {
- throw new SourceException( "couldn't release interface [" +
- LibUsb.errorName( result ) + "]" );
- }
- }
+ throw new SourceException("libusb couldn't open RTL2832 usb "
+ + "device [" + LibUsb.errorName(result) + "]");
+ }
- /**
- * Descriptor contains all identifiers and labels parsed from the EEPROM.
- *
- * May return null if unable to get 256 byte eeprom descriptor from tuner
- * or if the descriptor doesn't begin with byte values of 0x28 and 0x32
- * meaning it is a valid (and can be parsed) RTL2832 descriptor
- */
- public Descriptor getDescriptor()
- {
- if( mDescriptor != null && mDescriptor.isValid() )
- {
- return mDescriptor;
- }
+ claimInterface(mDeviceHandle);
- return null;
- }
-
- public void setSamplingMode( SampleMode mode ) throws LibUsbException
- {
- switch( mode )
- {
- case QUADRATURE:
+ try
+ {
+ setSampleRate(DEFAULT_SAMPLE_RATE);
+ }
+ catch(Exception e)
+ {
+ throw new SourceException("RTL2832 Tuner Controller - couldn't "
+ + "set default sample rate", e);
+ }
+
+ byte[] eeprom = null;
+
+ try
+ {
+ /* Read the contents of the 256-byte EEPROM */
+ eeprom = readEEPROM(mDeviceHandle, (short) 0, 256);
+ }
+ catch(Exception e)
+ {
+ mLog.error("error while reading the EEPROM device descriptor", e);
+ }
+
+ try
+ {
+ mDescriptor = new Descriptor(eeprom);
+
+ if(eeprom == null)
+ {
+ mLog.error("eeprom byte array was null - constructed "
+ + "empty descriptor object");
+ }
+ }
+ catch(Exception e)
+ {
+ mLog.error("error while constructing device descriptor using "
+ + "descriptor byte array " +
+ (eeprom == null ? "[null]" : Arrays.toString(eeprom)), e);
+ }
+ }
+
+ /**
+ * Claims the USB interface. Attempts to detach the active kernel driver
+ * if one is currently attached.
+ */
+ public static void claimInterface(DeviceHandle handle) throws SourceException
+ {
+ if(handle != null)
+ {
+ int result = LibUsb.kernelDriverActive(handle, USB_INTERFACE);
+
+ if(result == 1)
+ {
+ result = LibUsb.detachKernelDriver(handle, USB_INTERFACE);
+
+ if(result != LibUsb.SUCCESS)
+ {
+ mLog.error("failed attempt to detach kernel driver [" +
+ LibUsb.errorName(result) + "]");
+
+ throw new SourceException("couldn't detach kernel driver "
+ + "from device");
+ }
+ }
+
+ result = LibUsb.claimInterface(handle, USB_INTERFACE);
+
+ if(result != LibUsb.SUCCESS)
+ {
+ throw new SourceException("couldn't claim usb interface [" +
+ LibUsb.errorName(result) + "]");
+ }
+ }
+ else
+ {
+ throw new SourceException("couldn't claim usb interface - no "
+ + "device handle");
+ }
+ }
+
+ public static void releaseInterface(DeviceHandle handle)
+ throws SourceException
+ {
+ int result = LibUsb.releaseInterface(handle, USB_INTERFACE);
+
+ if(result != LibUsb.SUCCESS)
+ {
+ throw new SourceException("couldn't release interface [" +
+ LibUsb.errorName(result) + "]");
+ }
+ }
+
+ /**
+ * Descriptor contains all identifiers and labels parsed from the EEPROM.
+ *
+ * May return null if unable to get 256 byte eeprom descriptor from tuner
+ * or if the descriptor doesn't begin with byte values of 0x28 and 0x32
+ * meaning it is a valid (and can be parsed) RTL2832 descriptor
+ */
+ public Descriptor getDescriptor()
+ {
+ if(mDescriptor != null && mDescriptor.isValid())
+ {
+ return mDescriptor;
+ }
+
+ return null;
+ }
+
+ public void setSamplingMode(SampleMode mode) throws LibUsbException
+ {
+ switch(mode)
+ {
+ case QUADRATURE:
/* Set intermediate frequency to 0 Hz */
- setIFFrequency( 0 );
+ setIFFrequency(0);
/* Enable I/Q ADC Input */
- writeDemodRegister( mDeviceHandle,
- Page.ZERO,
- (short)0x08,
- (short)0xCD,
- 1 );
+ writeDemodRegister(mDeviceHandle,
+ Page.ZERO,
+ (short) 0x08,
+ (short) 0xCD,
+ 1);
/* Enable zero-IF mode */
- writeDemodRegister( mDeviceHandle,
- Page.ONE,
- (short)0xB1,
- (short)0x1B,
- 1 );
+ writeDemodRegister(mDeviceHandle,
+ Page.ONE,
+ (short) 0xB1,
+ (short) 0x1B,
+ 1);
/* Set default i/q path */
- writeDemodRegister( mDeviceHandle,
- Page.ZERO,
- (short)0x06,
- (short)0x80,
- 1 );
- break;
- case DIRECT:
- default:
- throw new LibUsbException( "QUADRATURE mode is the only mode "
- + "currently supported", LibUsb.ERROR_NOT_SUPPORTED );
- }
- }
-
- public void setIFFrequency( int frequency ) throws LibUsbException
- {
- long ifFrequency = ( (long)TWO_TO_22_POWER * (long)frequency ) /
- (long)mOscillatorFrequency * -1;
+ writeDemodRegister(mDeviceHandle,
+ Page.ZERO,
+ (short) 0x06,
+ (short) 0x80,
+ 1);
+ break;
+ case DIRECT:
+ default:
+ throw new LibUsbException("QUADRATURE mode is the only mode "
+ + "currently supported", LibUsb.ERROR_NOT_SUPPORTED);
+ }
+ }
+
+ public void setIFFrequency(int frequency) throws LibUsbException
+ {
+ long ifFrequency = ((long) TWO_TO_22_POWER * (long) frequency) /
+ (long) mOscillatorFrequency * -1;
/* Write byte 2 (high) */
- writeDemodRegister( mDeviceHandle,
- Page.ONE,
- (short)0x19,
- (short)( Long.rotateRight( ifFrequency, 16 ) & 0x3F ),
- 1 );
+ writeDemodRegister(mDeviceHandle,
+ Page.ONE,
+ (short) 0x19,
+ (short) (Long.rotateRight(ifFrequency, 16) & 0x3F),
+ 1);
/* Write byte 1 (middle) */
- writeDemodRegister( mDeviceHandle,
- Page.ONE,
- (short)0x1A,
- (short)( Long.rotateRight( ifFrequency, 8 ) & 0xFF ),
- 1 );
+ writeDemodRegister(mDeviceHandle,
+ Page.ONE,
+ (short) 0x1A,
+ (short) (Long.rotateRight(ifFrequency, 8) & 0xFF),
+ 1);
/* Write byte 0 (low) */
- writeDemodRegister( mDeviceHandle,
- Page.ONE,
- (short)0x1B,
- (short)( ifFrequency & 0xFF ),
- 1 );
- }
+ writeDemodRegister(mDeviceHandle,
+ Page.ONE,
+ (short) 0x1B,
+ (short) (ifFrequency & 0xFF),
+ 1);
+ }
- public abstract void initTuner( boolean controlI2CRepeater )
- throws UsbException;
+ public abstract void initTuner(boolean controlI2CRepeater)
+ throws UsbException;
- /**
- * Provides a unique identifier to use in distinctly identifying this
- * tuner from among other tuners of the same type, so that we can fetch a
- * tuner configuration from the settings manager for this specific tuner.
- *
- * @return serial number of the device
- */
- public String getUniqueID()
- {
- if( mDescriptor != null && mDescriptor.hasSerial() )
- {
- return mDescriptor.getSerial();
- }
- else
- {
- int serial =
- ( 0xFF & mDeviceDescriptor.iSerialNumber() );
+ /**
+ * Provides a unique identifier to use in distinctly identifying this
+ * tuner from among other tuners of the same type, so that we can fetch a
+ * tuner configuration from the settings manager for this specific tuner.
+ *
+ * @return serial number of the device
+ */
+ public String getUniqueID()
+ {
+ if(mDescriptor != null && mDescriptor.hasSerial())
+ {
+ return mDescriptor.getSerial();
+ }
+ else
+ {
+ int serial =
+ (0xFF & mDeviceDescriptor.iSerialNumber());
- return "SER#" + serial;
- }
- }
-
- public abstract void setSampleRateFilters( int sampleRate )
- throws SourceException;
-
- public abstract TunerType getTunerType();
-
- public static TunerType identifyTunerType( Device device )
- throws SourceException
- {
- DeviceHandle handle = new DeviceHandle();
-
- int reason = LibUsb.open( device, handle );
-
- if( reason != LibUsb.SUCCESS )
- {
- throw new SourceException( "couldn't open device - check permissions"
- + " (udev.rule) [" + LibUsb.errorName( reason ) + "]" );
- }
-
- TunerType tunerClass = TunerType.UNKNOWN;
-
- try
- {
- claimInterface( handle );
+ return "SER#" + serial;
+ }
+ }
+
+ public abstract void setSampleRateFilters(int sampleRate)
+ throws SourceException;
+
+ public abstract TunerType getTunerType();
+
+ public static TunerType identifyTunerType(Device device)
+ throws SourceException
+ {
+ DeviceHandle handle = new DeviceHandle();
+
+ int reason = LibUsb.open(device, handle);
+
+ if(reason != LibUsb.SUCCESS)
+ {
+ throw new SourceException("couldn't open device - check permissions"
+ + " (udev.rule) [" + LibUsb.errorName(reason) + "]");
+ }
+
+ TunerType tunerClass = TunerType.UNKNOWN;
+
+ try
+ {
+ claimInterface(handle);
/* Perform a dummy write to see if the device needs reset */
- boolean resetRequired = false;
-
- try
- {
- writeRegister( handle,
- Block.USB,
- Address.USB_SYSCTL.getAddress(),
- 0x09,
- 1 );
- }
- catch( LibUsbException e )
- {
-
- if( e.getErrorCode() < 0 )
- {
- mLog.error( "error performing dummy write - attempting "
- + "device reset", e );
+ boolean resetRequired = false;
- resetRequired = true;
- }
- else
- {
- throw new SourceException( "error performing dummy write "
- + "to device [" + LibUsb.errorName(
- e.getErrorCode() ) + "]", e );
- }
- }
+ try
+ {
+ writeRegister(handle,
+ Block.USB,
+ Address.USB_SYSCTL.getAddress(),
+ 0x09,
+ 1);
+ }
+ catch(LibUsbException e)
+ {
- if( resetRequired )
- {
- reason = LibUsb.resetDevice( handle );
-
- try
- {
- writeRegister( handle,
- Block.USB,
- Address.USB_SYSCTL.getAddress(),
- 0x09,
- 1 );
- }
- catch( LibUsbException e2 )
- {
- mLog.error( "device reset attempted, but lost device handle. "
- + "Try restarting the application to use this device" );
+ if(e.getErrorCode() < 0)
+ {
+ mLog.error("error performing dummy write - attempting "
+ + "device reset", e);
- throw new SourceException( "couldn't reset device" );
- }
- }
+ resetRequired = true;
+ }
+ else
+ {
+ throw new SourceException("error performing dummy write "
+ + "to device [" + LibUsb.errorName(
+ e.getErrorCode()) + "]", e);
+ }
+ }
+
+ if(resetRequired)
+ {
+ reason = LibUsb.resetDevice(handle);
+
+ try
+ {
+ writeRegister(handle,
+ Block.USB,
+ Address.USB_SYSCTL.getAddress(),
+ 0x09,
+ 1);
+ }
+ catch(LibUsbException e2)
+ {
+ mLog.error("device reset attempted, but lost device handle. "
+ + "Try restarting the application to use this device");
+
+ throw new SourceException("couldn't reset device");
+ }
+ }
/* Initialize the baseband */
- initBaseband( handle );
+ initBaseband(handle);
- enableI2CRepeater( handle, true );
-
- boolean controlI2CRepeater = false;
+ enableI2CRepeater(handle, true);
+
+ boolean controlI2CRepeater = false;
/* Test for each tuner type until we find the correct one */
- if( isTuner( TunerTypeCheck.E4K, handle, controlI2CRepeater ) )
- {
- tunerClass = TunerType.ELONICS_E4000;
- }
- else if( isTuner( TunerTypeCheck.FC0013, handle, controlI2CRepeater ) )
- {
- tunerClass = TunerType.FITIPOWER_FC0013;
- }
- else if( isTuner( TunerTypeCheck.R820T, handle, controlI2CRepeater ) )
- {
- tunerClass = TunerType.RAFAELMICRO_R820T;
- }
- else if( isTuner( TunerTypeCheck.R828D, handle, controlI2CRepeater ) )
- {
- tunerClass = TunerType.RAFAELMICRO_R828D;
- }
- else if( isTuner( TunerTypeCheck.FC2580, handle, controlI2CRepeater ) )
- {
- tunerClass = TunerType.FCI_FC2580;
- }
- else if( isTuner( TunerTypeCheck.FC0012, handle, controlI2CRepeater ) )
- {
- tunerClass = TunerType.FITIPOWER_FC0012;
- }
-
- enableI2CRepeater( handle, false );
+ if(isTuner(TunerTypeCheck.E4K, handle, controlI2CRepeater))
+ {
+ tunerClass = TunerType.ELONICS_E4000;
+ }
+ else if(isTuner(TunerTypeCheck.FC0013, handle, controlI2CRepeater))
+ {
+ tunerClass = TunerType.FITIPOWER_FC0013;
+ }
+ else if(isTuner(TunerTypeCheck.R820T, handle, controlI2CRepeater))
+ {
+ tunerClass = TunerType.RAFAELMICRO_R820T;
+ }
+ else if(isTuner(TunerTypeCheck.R828D, handle, controlI2CRepeater))
+ {
+ tunerClass = TunerType.RAFAELMICRO_R828D;
+ }
+ else if(isTuner(TunerTypeCheck.FC2580, handle, controlI2CRepeater))
+ {
+ tunerClass = TunerType.FCI_FC2580;
+ }
+ else if(isTuner(TunerTypeCheck.FC0012, handle, controlI2CRepeater))
+ {
+ tunerClass = TunerType.FITIPOWER_FC0012;
+ }
- releaseInterface( handle );
-
- LibUsb.close( handle );
- }
- catch( Exception e )
- {
- mLog.error( "error while determining tuner type", e );
- }
-
- return tunerClass;
- }
+ enableI2CRepeater(handle, false);
+
+ releaseInterface(handle);
+
+ LibUsb.close(handle);
+ }
+ catch(Exception e)
+ {
+ mLog.error("error while determining tuner type", e);
+ }
+
+ return tunerClass;
+ }
/**
* Releases the USB interface
*/
public void release()
{
- try
+ try
{
- if( mBufferProcessor.isRunning() )
- {
- mBufferProcessor.stop();
- }
-
- LibUsb.releaseInterface( mDeviceHandle, USB_INTERFACE );
-
- LibUsb.exit( null );
+ if(mBufferProcessor.isRunning())
+ {
+ mBufferProcessor.stop();
+ }
+
+ LibUsb.releaseInterface(mDeviceHandle, USB_INTERFACE);
+
+ LibUsb.exit(null);
}
- catch ( Exception e )
+ catch(Exception e)
{
- mLog.error( "attempt to release USB interface failed", e );
+ mLog.error("attempt to release USB interface failed", e);
}
}
-
- public void resetUSBBuffer() throws LibUsbException
- {
- writeRegister( mDeviceHandle, Block.USB, Address.USB_EPA_CTL.getAddress(), 0x1002, 2 );
- writeRegister( mDeviceHandle, Block.USB, Address.USB_EPA_CTL.getAddress(), 0x0000, 2 );
- }
-
- public static void initBaseband( DeviceHandle handle ) throws LibUsbException
- {
+
+ public void resetUSBBuffer() throws LibUsbException
+ {
+ writeRegister(mDeviceHandle, Block.USB, Address.USB_EPA_CTL.getAddress(), 0x1002, 2);
+ writeRegister(mDeviceHandle, Block.USB, Address.USB_EPA_CTL.getAddress(), 0x0000, 2);
+ }
+
+ public static void initBaseband(DeviceHandle handle) throws LibUsbException
+ {
/* Initialize USB */
- writeRegister( handle, Block.USB, Address.USB_SYSCTL.getAddress(), 0x09, 1 );
- writeRegister( handle, Block.USB, Address.USB_EPA_MAXPKT.getAddress(), 0x0002, 2 );
- writeRegister( handle, Block.USB, Address.USB_EPA_CTL.getAddress(), 0x1002, 2 );
+ writeRegister(handle, Block.USB, Address.USB_SYSCTL.getAddress(), 0x09, 1);
+ writeRegister(handle, Block.USB, Address.USB_EPA_MAXPKT.getAddress(), 0x0002, 2);
+ writeRegister(handle, Block.USB, Address.USB_EPA_CTL.getAddress(), 0x1002, 2);
/* Power on demod */
- writeRegister( handle, Block.SYS, Address.DEMOD_CTL_1.getAddress(), 0x22, 1 );
- writeRegister( handle, Block.SYS, Address.DEMOD_CTL.getAddress(), 0xE8, 1 );
+ writeRegister(handle, Block.SYS, Address.DEMOD_CTL_1.getAddress(), 0x22, 1);
+ writeRegister(handle, Block.SYS, Address.DEMOD_CTL.getAddress(), 0xE8, 1);
/* Reset demod */
- writeDemodRegister( handle, Page.ONE, (short)0x01, 0x14, 1 ); //Bit 3 = soft reset
- writeDemodRegister( handle, Page.ONE, (short)0x01, 0x10, 1 );
+ writeDemodRegister(handle, Page.ONE, (short) 0x01, 0x14, 1); //Bit 3 = soft reset
+ writeDemodRegister(handle, Page.ONE, (short) 0x01, 0x10, 1);
/* Disable spectrum inversion and adjacent channel rejection */
- writeDemodRegister( handle, Page.ONE, (short)0x15, 0x00, 1 );
- writeDemodRegister( handle, Page.ONE, (short)0x16, 0x0000, 2 );
+ writeDemodRegister(handle, Page.ONE, (short) 0x15, 0x00, 1);
+ writeDemodRegister(handle, Page.ONE, (short) 0x16, 0x0000, 2);
/* Clear DDC shift and IF frequency registers */
- writeDemodRegister( handle, Page.ONE, (short)0x16, 0x00, 1 );
- writeDemodRegister( handle, Page.ONE, (short)0x17, 0x00, 1 );
- writeDemodRegister( handle, Page.ONE, (short)0x18, 0x00, 1 );
- writeDemodRegister( handle, Page.ONE, (short)0x19, 0x00, 1 );
- writeDemodRegister( handle, Page.ONE, (short)0x1A, 0x00, 1 );
- writeDemodRegister( handle, Page.ONE, (short)0x1B, 0x00, 1 );
+ writeDemodRegister(handle, Page.ONE, (short) 0x16, 0x00, 1);
+ writeDemodRegister(handle, Page.ONE, (short) 0x17, 0x00, 1);
+ writeDemodRegister(handle, Page.ONE, (short) 0x18, 0x00, 1);
+ writeDemodRegister(handle, Page.ONE, (short) 0x19, 0x00, 1);
+ writeDemodRegister(handle, Page.ONE, (short) 0x1A, 0x00, 1);
+ writeDemodRegister(handle, Page.ONE, (short) 0x1B, 0x00, 1);
/* Set FIR coefficients */
- for( int x = 0; x < sFIR_COEFFICIENTS.length; x++ )
- {
- writeDemodRegister( handle,
- Page.ONE,
- (short)( 0x1C + x ),
- sFIR_COEFFICIENTS[ x ],
- 1 );
- }
+ for(int x = 0; x < sFIR_COEFFICIENTS.length; x++)
+ {
+ writeDemodRegister(handle,
+ Page.ONE,
+ (short) (0x1C + x),
+ sFIR_COEFFICIENTS[x],
+ 1);
+ }
/* Enable SDR mode, disable DAGC (bit 5) */
- writeDemodRegister( handle, Page.ZERO, (short)0x19, 0x05, 1 );
+ writeDemodRegister(handle, Page.ZERO, (short) 0x19, 0x05, 1);
/* Init FSM state-holding register */
- writeDemodRegister( handle, Page.ONE, (short)0x93, 0xF0, 1 );
- writeDemodRegister( handle, Page.ONE, (short)0x94, 0x0F, 1 );
+ writeDemodRegister(handle, Page.ONE, (short) 0x93, 0xF0, 1);
+ writeDemodRegister(handle, Page.ONE, (short) 0x94, 0x0F, 1);
/* Disable AGC (en_dagc, bit 0) (seems to have no effect) */
- writeDemodRegister( handle, Page.ONE, (short)0x11, 0x00, 1 );
+ writeDemodRegister(handle, Page.ONE, (short) 0x11, 0x00, 1);
/* Disable RF and IF AGC loop */
- writeDemodRegister( handle, Page.ONE, (short)0x04, 0x00, 1 );
+ writeDemodRegister(handle, Page.ONE, (short) 0x04, 0x00, 1);
/* Disable PID filter */
- writeDemodRegister( handle, Page.ZERO, (short)0x61, 0x60, 1 );
+ writeDemodRegister(handle, Page.ZERO, (short) 0x61, 0x60, 1);
/* opt_adc_iq = 0, default ADC_I/ADC_Q datapath */
- writeDemodRegister( handle, Page.ZERO, (short)0x06, 0x80, 1 );
+ writeDemodRegister(handle, Page.ZERO, (short) 0x06, 0x80, 1);
/* Enable Zero-if mode (en_bbin bit),
* DC cancellation (en_dc_est),
* IQ estimation/compensation (en_iq_comp, en_iq_est) */
- writeDemodRegister( handle, Page.ONE, (short)0xB1, 0x1B, 1 );
+ writeDemodRegister(handle, Page.ONE, (short) 0xB1, 0x1B, 1);
/* Disable 4.096 MHz clock output on pin TP_CK0 */
- writeDemodRegister( handle, Page.ZERO, (short)0x0D, 0x83, 1 );
- }
-
- protected void deinitBaseband( DeviceHandle handle )
- throws IllegalArgumentException, UsbDisconnectedException, UsbException
- {
- writeRegister( handle, Block.SYS, Address.DEMOD_CTL.getAddress(), 0x20, 1);
- }
+ writeDemodRegister(handle, Page.ZERO, (short) 0x0D, 0x83, 1);
+ }
- /**
- * Sets the General Purpose Input/Output (GPIO) register bit
- *
- * @param handle - USB tuner device
- * @param bitMask - bit mask with one for targeted register bits and zero
- * for the non-targeted register bits
- * @param enabled - true to set the bit and false to clear the bit
- * @throws UsbDisconnectedException - if the tuner device is disconnected
- * @throws UsbException - if there is a USB error while communicating with
- * the device
- */
- protected static void setGPIOBit( DeviceHandle handle,
- byte bitMask,
- boolean enabled ) throws LibUsbException
- {
- //Get current register value
- int value = readRegister( handle, Block.SYS, Address.GPO.getAddress(), 1 );
+ protected void deinitBaseband(DeviceHandle handle)
+ throws IllegalArgumentException, UsbDisconnectedException, UsbException
+ {
+ writeRegister(handle, Block.SYS, Address.DEMOD_CTL.getAddress(), 0x20, 1);
+ }
- //Update the masked bits
- if( enabled )
- {
- value |= bitMask;
- }
- else
- {
- value &= ~bitMask;
- }
+ /**
+ * Sets the General Purpose Input/Output (GPIO) register bit
+ *
+ * @param handle - USB tuner device
+ * @param bitMask - bit mask with one for targeted register bits and zero
+ * for the non-targeted register bits
+ * @param enabled - true to set the bit and false to clear the bit
+ * @throws UsbDisconnectedException - if the tuner device is disconnected
+ * @throws UsbException - if there is a USB error while communicating with
+ * the device
+ */
+ protected static void setGPIOBit(DeviceHandle handle,
+ byte bitMask,
+ boolean enabled) throws LibUsbException
+ {
+ //Get current register value
+ int value = readRegister(handle, Block.SYS, Address.GPO.getAddress(), 1);
- //Write the change back to the device
- writeRegister( handle, Block.SYS, Address.GPO.getAddress(), value, 1 );
- }
+ //Update the masked bits
+ if(enabled)
+ {
+ value |= bitMask;
+ }
+ else
+ {
+ value &= ~bitMask;
+ }
- /**
- * Enables GPIO Output
- * @param handle - usb tuner device
- * @param bitMask - mask containing one bit value in targeted bit field(s)
- * @throws UsbDisconnectedException
- * @throws UsbException
- */
- protected static void setGPIOOutput( DeviceHandle handle, byte bitMask )
- throws LibUsbException
- {
- //Get current register value
- int value = readRegister( handle, Block.SYS, Address.GPD.getAddress(), 1 );
+ //Write the change back to the device
+ writeRegister(handle, Block.SYS, Address.GPO.getAddress(), value, 1);
+ }
- //Mask the value and rewrite it
- writeRegister( handle, Block.SYS, Address.GPO.getAddress(),
- value & ~bitMask, 1 );
-
- //Get current register value
- value = readRegister( handle, Block.SYS, Address.GPOE.getAddress(), 1 );
+ /**
+ * Enables GPIO Output
+ *
+ * @param handle - usb tuner device
+ * @param bitMask - mask containing one bit value in targeted bit field(s)
+ * @throws UsbDisconnectedException
+ * @throws UsbException
+ */
+ protected static void setGPIOOutput(DeviceHandle handle, byte bitMask)
+ throws LibUsbException
+ {
+ //Get current register value
+ int value = readRegister(handle, Block.SYS, Address.GPD.getAddress(), 1);
- //Mask the value and rewrite it
- writeRegister( handle, Block.SYS, Address.GPOE.getAddress(),
- value | bitMask, 1 );
- }
-
- protected static void enableI2CRepeater( DeviceHandle handle,
- boolean enabled )
- throws LibUsbException
- {
- Page page = Page.ONE;
- short address = 1;
- int value;
-
- if( enabled )
- {
- value = 0x18; //ON
- }
- else
- {
- value = 0x10; //OFF
- }
+ //Mask the value and rewrite it
+ writeRegister(handle, Block.SYS, Address.GPO.getAddress(),
+ value & ~bitMask, 1);
- writeDemodRegister( handle, page, address, value, 1 );
- }
-
- protected boolean isI2CRepeaterEnabled() throws SourceException
- {
- int register = readDemodRegister( mDeviceHandle, Page.ONE, (short)0x1, 1 );
-
- return register == 0x18;
- }
-
- protected static int readI2CRegister( DeviceHandle handle,
- byte i2CAddress,
- byte i2CRegister,
- boolean controlI2CRepeater )
- throws LibUsbException
- {
- short address = (short)( i2CAddress & 0xFF );
+ //Get current register value
+ value = readRegister(handle, Block.SYS, Address.GPOE.getAddress(), 1);
- ByteBuffer buffer = ByteBuffer.allocateDirect( 1 );
- buffer.put( i2CRegister );
- buffer.rewind();
-
- ByteBuffer data = ByteBuffer.allocateDirect( 1 );
+ //Mask the value and rewrite it
+ writeRegister(handle, Block.SYS, Address.GPOE.getAddress(),
+ value | bitMask, 1);
+ }
- if( controlI2CRepeater )
- {
- enableI2CRepeater( handle, true );
+ protected static void enableI2CRepeater(DeviceHandle handle,
+ boolean enabled)
+ throws LibUsbException
+ {
+ Page page = Page.ONE;
+ short address = 1;
+ int value;
- write( handle, address, Block.I2C, buffer );
- read( handle, address, Block.I2C, data );
+ if(enabled)
+ {
+ value = 0x18; //ON
+ }
+ else
+ {
+ value = 0x10; //OFF
+ }
- enableI2CRepeater( handle, false );
- }
- else
- {
- write( handle, address, Block.I2C, buffer );
- read( handle, address, Block.I2C, data );
- }
-
- return (int)( data.get() & 0xFF );
- }
-
- protected void writeI2CRegister( DeviceHandle handle,
- byte i2CAddress,
- byte i2CRegister,
- byte value,
- boolean controlI2CRepeater ) throws LibUsbException
- {
-
- short address = (short)( i2CAddress & 0xFF );
+ writeDemodRegister(handle, page, address, value, 1);
+ }
- ByteBuffer buffer = ByteBuffer.allocateDirect( 2 );
- buffer.put( i2CRegister );
- buffer.put( value );
+ protected boolean isI2CRepeaterEnabled() throws SourceException
+ {
+ int register = readDemodRegister(mDeviceHandle, Page.ONE, (short) 0x1, 1);
- buffer.rewind();
+ return register == 0x18;
+ }
- if( controlI2CRepeater )
- {
- enableI2CRepeater( handle, true );
- write( handle, address, Block.I2C, buffer );
- enableI2CRepeater( handle, false );
- }
- else
- {
- write( handle, address, Block.I2C, buffer );
- }
- }
+ protected static int readI2CRegister(DeviceHandle handle,
+ byte i2CAddress,
+ byte i2CRegister,
+ boolean controlI2CRepeater)
+ throws LibUsbException
+ {
+ short address = (short) (i2CAddress & 0xFF);
- protected static void writeDemodRegister( DeviceHandle handle,
- Page page,
- short address,
- int value,
- int length ) throws LibUsbException
- {
- ByteBuffer buffer = ByteBuffer.allocateDirect( length );
- buffer.order( ByteOrder.BIG_ENDIAN );
-
- if( length == 1 )
- {
- buffer.put( (byte)( value & 0xFF ) );
- }
- else if( length == 2 )
- {
- buffer.putShort( (short)( value & 0xFFFF ) );
- }
- else
- {
- throw new IllegalArgumentException( "Cannot write value greater "
- + "than 16 bits to the register - length [" + length + "]" );
- }
+ ByteBuffer buffer = ByteBuffer.allocateDirect(1);
+ buffer.put(i2CRegister);
+ buffer.rewind();
- short index = (short)( 0x10 | page.getPage() );
-
- short newAddress = (short)( address << 8 | 0x20 );
+ ByteBuffer data = ByteBuffer.allocateDirect(1);
- write( handle, newAddress, index, buffer );
-
- readDemodRegister( handle, Page.TEN, (short)1, length );
- }
+ if(controlI2CRepeater)
+ {
+ enableI2CRepeater(handle, true);
- protected static int readDemodRegister( DeviceHandle handle,
- Page page,
- short address,
- int length ) throws LibUsbException
- {
- short index = page.getPage();
- short newAddress = (short)( ( address << 8 ) | 0x20 );
-
- ByteBuffer buffer = ByteBuffer.allocateDirect( length );
-
- read( handle, newAddress, index, buffer );
- buffer.order( ByteOrder.LITTLE_ENDIAN );
+ write(handle, address, Block.I2C, buffer);
+ read(handle, address, Block.I2C, data);
- if( length == 2 )
- {
- return (int)( buffer.getShort() & 0xFFFF );
- }
- else
- {
- return (int)( buffer.get() & 0xFF );
- }
- }
-
- protected static void writeRegister( DeviceHandle handle,
- Block block,
- short address,
- int value,
- int length ) throws LibUsbException
- {
- ByteBuffer buffer = ByteBuffer.allocateDirect( length );
- buffer.order( ByteOrder.BIG_ENDIAN );
-
- if( length == 1 )
- {
- buffer.put( (byte)( value & 0xFF ) ) ;
- }
- else if( length == 2 )
- {
- buffer.putShort( (short)value );
- }
- else
- {
- throw new IllegalArgumentException( "Cannot write value greater "
- + "than 16 bits to the register - length [" + length + "]" );
- }
-
- buffer.rewind();
+ enableI2CRepeater(handle, false);
+ }
+ else
+ {
+ write(handle, address, Block.I2C, buffer);
+ read(handle, address, Block.I2C, data);
+ }
- write( handle, address, block, buffer );
- }
+ return (int) (data.get() & 0xFF);
+ }
- protected static int readRegister( DeviceHandle handle,
- Block block,
- short address,
- int length ) throws LibUsbException
- {
- ByteBuffer buffer = ByteBuffer.allocateDirect( 2 );
+ protected void writeI2CRegister(DeviceHandle handle,
+ byte i2CAddress,
+ byte i2CRegister,
+ byte value,
+ boolean controlI2CRepeater) throws LibUsbException
+ {
- read( handle, address, block, buffer );
+ short address = (short) (i2CAddress & 0xFF);
- buffer.order( ByteOrder.LITTLE_ENDIAN );
-
- if( length == 2 )
- {
- return (int)( buffer.getShort() & 0xFFFF );
- }
- else
- {
- return (int)( buffer.get() & 0xFF );
- }
- }
+ ByteBuffer buffer = ByteBuffer.allocateDirect(2);
+ buffer.put(i2CRegister);
+ buffer.put(value);
- /**
- */
- protected static void write( DeviceHandle handle,
- short address,
- Block block,
- ByteBuffer buffer ) throws LibUsbException
- {
- write( handle, address, block.getWriteIndex(), buffer );
- }
-
- protected static void write( DeviceHandle handle,
- short value,
- short index,
- ByteBuffer buffer ) throws LibUsbException
- {
- if( handle != null )
- {
- int transferred = LibUsb.controlTransfer( handle,
- CONTROL_ENDPOINT_OUT,
- REQUEST_ZERO,
- value,
- index,
- buffer,
- TIMEOUT_US );
+ buffer.rewind();
- if( transferred < 0 )
- {
- throw new LibUsbException( "error writing byte buffer",
- transferred );
- }
- else if( transferred != buffer.capacity() )
- {
- throw new LibUsbException( "transferred bytes [" +
- transferred + "] is not what was expected [" +
- buffer.capacity() + "]", transferred );
- }
- }
- else
- {
- throw new LibUsbException( "device handle is null",
- LibUsb.ERROR_NO_DEVICE );
- }
- }
+ if(controlI2CRepeater)
+ {
+ enableI2CRepeater(handle, true);
+ write(handle, address, Block.I2C, buffer);
+ enableI2CRepeater(handle, false);
+ }
+ else
+ {
+ write(handle, address, Block.I2C, buffer);
+ }
+ }
- /**
- * Performs a control type read
- */
- protected static void read( DeviceHandle handle,
- short address,
- short index,
- ByteBuffer buffer ) throws LibUsbException
- {
- if( handle != null )
- {
- int transferred = LibUsb.controlTransfer( handle,
- CONTROL_ENDPOINT_IN,
- REQUEST_ZERO,
- address,
- index,
- buffer,
- TIMEOUT_US );
+ protected static void writeDemodRegister(DeviceHandle handle,
+ Page page,
+ short address,
+ int value,
+ int length) throws LibUsbException
+ {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(length);
+ buffer.order(ByteOrder.BIG_ENDIAN);
- if( transferred < 0 )
- {
- throw new LibUsbException( "read error", transferred );
- }
- else if( transferred != buffer.capacity() )
- {
- throw new LibUsbException( "transferred bytes [" +
- transferred + "] is not what was expected [" +
- buffer.capacity() + "]", transferred );
- }
- }
- else
- {
- throw new LibUsbException( "device handle is null",
- LibUsb.ERROR_NO_DEVICE );
- }
- }
-
- /**
- * Reads byte array from index at the address.
- *
- * @return big-endian byte array (needs to be swapped to be usable)
- *
- */
- protected static void read( DeviceHandle handle,
- short address,
- Block block,
- ByteBuffer buffer ) throws LibUsbException
- {
- read( handle, address, block.getReadIndex(), buffer );
- }
+ if(length == 1)
+ {
+ buffer.put((byte) (value & 0xFF));
+ }
+ else if(length == 2)
+ {
+ buffer.putShort((short) (value & 0xFFFF));
+ }
+ else
+ {
+ throw new IllegalArgumentException("Cannot write value greater "
+ + "than 16 bits to the register - length [" + length + "]");
+ }
- /**
- * Tests if the specified tuner type is contained in the usb tuner device.
- *
- * @param type - tuner type to test for
- * @param handle - handle to the usb tuner device
- * @param controlI2CRepeater - indicates if the method should control the
- * I2C repeater independently
- *
- * @return - true if the device is the specified tuner type
- */
- protected static boolean isTuner( TunerTypeCheck type,
- DeviceHandle handle,
- boolean controlI2CRepeater )
- {
- try
- {
- if( type == TunerTypeCheck.FC0012 ||
- type == TunerTypeCheck.FC2580 )
- {
- /* Initialize the GPIOs */
- setGPIOOutput( handle, (byte)0x20 );
+ short index = (short) (0x10 | page.getPage());
- /* Reset tuner before probing */
- setGPIOBit( handle, (byte)0x20, true );
- setGPIOBit( handle, (byte)0x20, false );
- }
-
- int value = readI2CRegister( handle, type.getI2CAddress(),
- type.getCheckAddress(), controlI2CRepeater );
+ short newAddress = (short) (address << 8 | 0x20);
- if( type == TunerTypeCheck.FC2580 )
- {
- return ( ( value & 0x7F ) == type.getCheckValue() );
- }
- else
- {
- return ( value == type.getCheckValue() );
- }
- }
- catch( LibUsbException e )
- {
- //Do nothing ... it's not the specified tuner
- }
-
- return false;
- }
+ write(handle, newAddress, index, buffer);
- public int getCurrentSampleRate() throws SourceException
- {
- return mSampleRate.getRate();
- }
-
- public int getSampleRateFromTuner() throws SourceException
- {
+ readDemodRegister(handle, Page.TEN, (short) 1, length);
+ }
+
+ protected static int readDemodRegister(DeviceHandle handle,
+ Page page,
+ short address,
+ int length) throws LibUsbException
+ {
+ short index = page.getPage();
+ short newAddress = (short) ((address << 8) | 0x20);
+
+ ByteBuffer buffer = ByteBuffer.allocateDirect(length);
+
+ read(handle, newAddress, index, buffer);
+ buffer.order(ByteOrder.LITTLE_ENDIAN);
+
+ if(length == 2)
+ {
+ return (int) (buffer.getShort() & 0xFFFF);
+ }
+ else
+ {
+ return (int) (buffer.get() & 0xFF);
+ }
+ }
+
+ protected static void writeRegister(DeviceHandle handle,
+ Block block,
+ short address,
+ int value,
+ int length) throws LibUsbException
+ {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(length);
+ buffer.order(ByteOrder.BIG_ENDIAN);
+
+ if(length == 1)
+ {
+ buffer.put((byte) (value & 0xFF));
+ }
+ else if(length == 2)
+ {
+ buffer.putShort((short) value);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Cannot write value greater "
+ + "than 16 bits to the register - length [" + length + "]");
+ }
+
+ buffer.rewind();
+
+ write(handle, address, block, buffer);
+ }
+
+ protected static int readRegister(DeviceHandle handle,
+ Block block,
+ short address,
+ int length) throws LibUsbException
+ {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(2);
+
+ read(handle, address, block, buffer);
+
+ buffer.order(ByteOrder.LITTLE_ENDIAN);
+
+ if(length == 2)
+ {
+ return (int) (buffer.getShort() & 0xFFFF);
+ }
+ else
+ {
+ return (int) (buffer.get() & 0xFF);
+ }
+ }
+
+ /**
+ */
+ protected static void write(DeviceHandle handle,
+ short address,
+ Block block,
+ ByteBuffer buffer) throws LibUsbException
+ {
+ write(handle, address, block.getWriteIndex(), buffer);
+ }
+
+ protected static void write(DeviceHandle handle,
+ short value,
+ short index,
+ ByteBuffer buffer) throws LibUsbException
+ {
+ if(handle != null)
+ {
+ int transferred = LibUsb.controlTransfer(handle,
+ CONTROL_ENDPOINT_OUT,
+ REQUEST_ZERO,
+ value,
+ index,
+ buffer,
+ TIMEOUT_US);
+
+ if(transferred < 0)
+ {
+ throw new LibUsbException("error writing byte buffer",
+ transferred);
+ }
+ else if(transferred != buffer.capacity())
+ {
+ throw new LibUsbException("transferred bytes [" +
+ transferred + "] is not what was expected [" +
+ buffer.capacity() + "]", transferred);
+ }
+ }
+ else
+ {
+ throw new LibUsbException("device handle is null",
+ LibUsb.ERROR_NO_DEVICE);
+ }
+ }
+
+ /**
+ * Performs a control type read
+ */
+ protected static void read(DeviceHandle handle,
+ short address,
+ short index,
+ ByteBuffer buffer) throws LibUsbException
+ {
+ if(handle != null)
+ {
+ int transferred = LibUsb.controlTransfer(handle,
+ CONTROL_ENDPOINT_IN,
+ REQUEST_ZERO,
+ address,
+ index,
+ buffer,
+ TIMEOUT_US);
+
+ if(transferred < 0)
+ {
+ throw new LibUsbException("read error", transferred);
+ }
+ else if(transferred != buffer.capacity())
+ {
+ throw new LibUsbException("transferred bytes [" +
+ transferred + "] is not what was expected [" +
+ buffer.capacity() + "]", transferred);
+ }
+ }
+ else
+ {
+ throw new LibUsbException("device handle is null",
+ LibUsb.ERROR_NO_DEVICE);
+ }
+ }
+
+ /**
+ * Reads byte array from index at the address.
+ *
+ * @return big-endian byte array (needs to be swapped to be usable)
+ */
+ protected static void read(DeviceHandle handle,
+ short address,
+ Block block,
+ ByteBuffer buffer) throws LibUsbException
+ {
+ read(handle, address, block.getReadIndex(), buffer);
+ }
+
+ /**
+ * Tests if the specified tuner type is contained in the usb tuner device.
+ *
+ * @param type - tuner type to test for
+ * @param handle - handle to the usb tuner device
+ * @param controlI2CRepeater - indicates if the method should control the
+ * I2C repeater independently
+ * @return - true if the device is the specified tuner type
+ */
+ protected static boolean isTuner(TunerTypeCheck type,
+ DeviceHandle handle,
+ boolean controlI2CRepeater)
+ {
try
{
- int high= readDemodRegister( mDeviceHandle, Page.ONE, (short)0x9F, 2 );
- int low = readDemodRegister( mDeviceHandle, Page.ONE, (short)0xA1, 2 );
+ if(type == TunerTypeCheck.FC0012 ||
+ type == TunerTypeCheck.FC2580)
+ {
+ /* Initialize the GPIOs */
+ setGPIOOutput(handle, (byte) 0x20);
- int ratio = Integer.rotateLeft( high, 16 ) | low;
-
- int rate = (int)( mOscillatorFrequency * TWO_TO_22_POWER / ratio );
-
- SampleRate sampleRate = SampleRate.getClosest( rate );
+ /* Reset tuner before probing */
+ setGPIOBit(handle, (byte) 0x20, true);
+ setGPIOBit(handle, (byte) 0x20, false);
+ }
+
+ int value = readI2CRegister(handle, type.getI2CAddress(),
+ type.getCheckAddress(), controlI2CRepeater);
+
+ if(type == TunerTypeCheck.FC2580)
+ {
+ return ((value & 0x7F) == type.getCheckValue());
+ }
+ else
+ {
+ return (value == type.getCheckValue());
+ }
+ }
+ catch(LibUsbException e)
+ {
+ //Do nothing ... it's not the specified tuner
+ }
+
+ return false;
+ }
+
+ public int getCurrentSampleRate() throws SourceException
+ {
+ return mSampleRate.getRate();
+ }
+
+ public int getSampleRateFromTuner() throws SourceException
+ {
+ try
+ {
+ int high = readDemodRegister(mDeviceHandle, Page.ONE, (short) 0x9F, 2);
+ int low = readDemodRegister(mDeviceHandle, Page.ONE, (short) 0xA1, 2);
+
+ int ratio = Integer.rotateLeft(high, 16) | low;
+
+ int rate = (int) (mOscillatorFrequency * TWO_TO_22_POWER / ratio);
+
+ SampleRate sampleRate = SampleRate.getClosest(rate);
/* If we're not currently set to this rate, set it as the current rate */
- if( sampleRate.getRate() != rate )
- {
- setSampleRate( sampleRate );
-
- return sampleRate.getRate();
- }
+ if(sampleRate.getRate() != rate)
+ {
+ setSampleRate(sampleRate);
+
+ return sampleRate.getRate();
+ }
}
- catch ( Exception e )
+ catch(Exception e)
{
- throw new SourceException( "RTL2832 Tuner Controller - cannot get "
- + "current sample rate", e );
+ throw new SourceException("RTL2832 Tuner Controller - cannot get "
+ + "current sample rate", e);
}
return DEFAULT_SAMPLE_RATE.getRate();
- }
-
- public void setSampleRate( SampleRate sampleRate ) throws SourceException
- {
+ }
+
+ public void setSampleRate(SampleRate sampleRate) throws SourceException
+ {
/* Write high-order 16-bits of sample rate ratio to demod register */
- writeDemodRegister( mDeviceHandle, Page.ONE, (short)0x9F,
- sampleRate.getRatioHighBits(), 2 );
+ writeDemodRegister(mDeviceHandle, Page.ONE, (short) 0x9F,
+ sampleRate.getRatioHighBits(), 2);
/* Write low-order 16-bits of sample rate ratio to demod register.
* Note: none of the defined rates have a low order ratio value, so we
* simply write a zero to the register */
- writeDemodRegister( mDeviceHandle, Page.ONE, (short)0xA1, 0, 2 );
+ writeDemodRegister(mDeviceHandle, Page.ONE, (short) 0xA1, 0, 2);
/* Set sample rate correction to 0 */
- setSampleRateFrequencyCorrection( 0 );
+ setSampleRateFrequencyCorrection(0);
/* Reset the demod for the changes to take effect */
- writeDemodRegister( mDeviceHandle, Page.ONE, (short)0x01, 0x14, 1 );
- writeDemodRegister( mDeviceHandle, Page.ONE, (short)0x01, 0x10, 1 );
+ writeDemodRegister(mDeviceHandle, Page.ONE, (short) 0x01, 0x14, 1);
+ writeDemodRegister(mDeviceHandle, Page.ONE, (short) 0x01, 0x10, 1);
/* Apply any tuner specific sample rate filter settings */
- setSampleRateFilters( sampleRate.getRate() );
+ setSampleRateFilters(sampleRate.getRate());
- mSampleRate = sampleRate;
+ mSampleRate = sampleRate;
- mFrequencyController.setSampleRate( sampleRate.getRate() );
-
- if( mSampleRateMonitor != null )
- {
- mSampleRateMonitor.setSampleRate( mSampleRate.getRate() );
- }
- }
-
- public void setSampleRateFrequencyCorrection( int ppm ) throws SourceException
- {
- int offset = -ppm * TWO_TO_22_POWER / 1000000;
-
- writeDemodRegister( mDeviceHandle,
- Page.ONE,
- (short)0x3F,
- ( offset & 0xFF ),
- 1 );
- writeDemodRegister( mDeviceHandle,
- Page.ONE,
- (short)0x3E,
- ( Integer.rotateRight( offset, 8 ) & 0xFF ),
- 1 );
+ mFrequencyController.setSampleRate(sampleRate.getRate());
+
+ if(mSampleRateMonitor != null)
+ {
+ mSampleRateMonitor.setSampleRate(mSampleRate.getRate());
+ }
+ }
+
+ public void setSampleRateFrequencyCorrection(int ppm) throws SourceException
+ {
+ int offset = -ppm * TWO_TO_22_POWER / 1000000;
+
+ writeDemodRegister(mDeviceHandle,
+ Page.ONE,
+ (short) 0x3F,
+ (offset & 0xFF),
+ 1);
+ writeDemodRegister(mDeviceHandle,
+ Page.ONE,
+ (short) 0x3E,
+ (Integer.rotateRight(offset, 8) & 0xFF),
+ 1);
/* Test to retune controller to apply frequency correction */
- try
- {
- mFrequencyController.setFrequency( mFrequencyController.getFrequency() );
- }
- catch( Exception e )
- {
- throw new SourceException( "couldn't set sample rate frequency correction", e );
- }
- }
-
- public int getSampleRateFrequencyCorrection() throws UsbException
- {
- int high = readDemodRegister( mDeviceHandle, Page.ONE, (short)0x3E, 1 );
- int low = readDemodRegister( mDeviceHandle, Page.ONE, (short)0x3F, 1 );
-
- return ( Integer.rotateLeft( high, 8 ) | low );
- }
+ try
+ {
+ mFrequencyController.setFrequency(mFrequencyController.getFrequency());
+ }
+ catch(Exception e)
+ {
+ throw new SourceException("couldn't set sample rate frequency correction", e);
+ }
+ }
- /**
- * Returns contents of the 256-byte EEPROM. The contents are as follows:
- *
- * 256-byte EEPROM (in hex):
- * 00/01 - 2832 Signature
- * 03/02 - 0BDA Vendor ID
- * 05/04 - 2832 Product ID
- * 06 - A5 (has serial id?)
- * 07 - 16 (bit field - bit 0 = remote wakeup, bit 1 = IR enabled
- * 08 - 02 or 12
- * 10/09 0310 ETX(0x03) plus label length (includes length and ETX bytes)
- * 12/11 First UTF-16 character
- * 14/13 Second UTF-16 character ...
- *
- * Label 1: vendor
- * Label 2: product
- * Label 3: serial
- * Label 4,5 ... (user defined)
- */
- public byte[] readEEPROM( DeviceHandle handle, short offset, int length )
- throws IllegalArgumentException
- {
- if( offset + length > 256 )
- {
- throw new IllegalArgumentException( "cannot read more than 256 "
- + "bytes from EEPROM - requested to read to byte [" +
- ( offset + length ) + "]" );
- }
+ public int getSampleRateFrequencyCorrection() throws UsbException
+ {
+ int high = readDemodRegister(mDeviceHandle, Page.ONE, (short) 0x3E, 1);
+ int low = readDemodRegister(mDeviceHandle, Page.ONE, (short) 0x3F, 1);
- byte[] data = new byte[ length ];
- ByteBuffer buffer = ByteBuffer.allocateDirect( 1 );
-
- try
- {
+ return (Integer.rotateLeft(high, 8) | low);
+ }
+
+ /**
+ * Returns contents of the 256-byte EEPROM. The contents are as follows:
+ *
+ * 256-byte EEPROM (in hex):
+ * 00/01 - 2832 Signature
+ * 03/02 - 0BDA Vendor ID
+ * 05/04 - 2832 Product ID
+ * 06 - A5 (has serial id?)
+ * 07 - 16 (bit field - bit 0 = remote wakeup, bit 1 = IR enabled
+ * 08 - 02 or 12
+ * 10/09 0310 ETX(0x03) plus label length (includes length and ETX bytes)
+ * 12/11 First UTF-16 character
+ * 14/13 Second UTF-16 character ...
+ *
+ * Label 1: vendor
+ * Label 2: product
+ * Label 3: serial
+ * Label 4,5 ... (user defined)
+ */
+ public byte[] readEEPROM(DeviceHandle handle, short offset, int length)
+ throws IllegalArgumentException
+ {
+ if(offset + length > 256)
+ {
+ throw new IllegalArgumentException("cannot read more than 256 "
+ + "bytes from EEPROM - requested to read to byte [" +
+ (offset + length) + "]");
+ }
+
+ byte[] data = new byte[length];
+ ByteBuffer buffer = ByteBuffer.allocateDirect(1);
+
+ try
+ {
/* Tell the RTL-2832 to address the EEPROM */
- writeRegister( handle, Block.I2C, EEPROM_ADDRESS, (byte)offset, 1 );
- }
- catch( LibUsbException e )
- {
- mLog.error( "usb error while attempting to set read address to "
- + "EEPROM register, prior to reading the EEPROM device "
- + "descriptor", e );
- }
-
- for( int x = 0; x < length; x++ )
- {
- try
- {
- read( handle, EEPROM_ADDRESS, Block.I2C, buffer );
- data[ x ] = buffer.get();
- buffer.rewind();
- }
- catch( Exception e )
- {
- mLog.error( "error while reading eeprom byte [" + x + "/" +
- length + "] aborting eeprom read and returning partially "
- + "filled descriptor byte array", e );
- x = length;
- }
- }
-
- return data;
- }
-
- /**
- * Writes a single byte to the 256-byte EEPROM using the specified offset.
- *
- * Note: introduce a 5 millisecond delay between each successive write to
- * the EEPROM or subsequent writes may fail.
- */
- public void writeEEPROMByte( DeviceHandle handle, byte offset, byte value )
- throws IllegalArgumentException, UsbDisconnectedException, UsbException
- {
- if( offset < 0 || offset > 255 )
- {
- throw new IllegalArgumentException( "RTL2832 Tuner Controller - "
- + "EEPROM offset must be within range of 0 - 255" );
- }
-
- int offsetAndValue = Integer.rotateLeft( ( 0xFF & offset ), 8 ) |
- ( 0xFF & value );
-
- writeRegister( handle, Block.I2C, EEPROM_ADDRESS, offsetAndValue, 2 );
- }
-
- public enum Address
- {
- USB_SYSCTL( 0x2000 ),
- USB_CTRL( 0x2010 ),
- USB_STAT( 0x2014 ),
- USB_EPA_CFG( 0x2144 ),
- USB_EPA_CTL( 0x2148 ),
- USB_EPA_MAXPKT( 0x2158 ),
- USB_EPA_MAXPKT_2( 0x215A ),
- USB_EPA_FIFO_CFG( 0x2160 ),
- DEMOD_CTL( 0x3000 ),
- GPO( 0x3001 ),
- GPI( 0x3002 ),
- GPOE( 0x3003 ),
- GPD( 0x3004 ),
- SYSINTE( 0x3005 ),
- SYSINTS( 0x3006 ),
- GP_CFG0( 0x3007 ),
- GP_CFG1( 0x3008 ),
- SYSINTE_1( 0x3009 ),
- SYSINTS_1( 0x300A ),
- DEMOD_CTL_1( 0x300B ),
- IR_SUSPEND( 0x300C );
-
- private int mAddress;
-
- private Address( int address )
- {
- mAddress = address;
- }
-
- public short getAddress()
- {
- return (short)mAddress;
- }
- }
-
- public enum Page
- {
- ZERO( 0x0 ),
- ONE( 0x1 ),
- TEN( 0xA );
-
- private int mPage;
-
- private Page( int page )
- {
- mPage = page;
- }
-
- public byte getPage()
- {
- return (byte)( mPage & 0xFF );
- }
- }
-
- public enum SampleMode
- {
- QUADRATURE, DIRECT;
- }
-
- public enum Block
- {
- DEMOD( 0 ),
- USB( 1 ),
- SYS( 2 ),
- TUN( 3 ),
- ROM( 4 ),
- IR( 5 ),
- I2C( 6 ); //I2C controller
-
- private int mValue;
-
- private Block( int value )
- {
- mValue = value;
- }
-
- public int getValue()
- {
- return mValue;
- }
-
- /**
- * Returns the value left shifted 8 bits
- */
- public short getReadIndex()
- {
- return (short)Integer.rotateLeft( mValue, 8 );
- }
-
- public short getWriteIndex()
- {
- return (short)( getReadIndex() | 0x10 );
- }
- }
-
- /**
- * Sample rates supported by the RTL-2832.
- *
- * Formula to calculate the ratio value:
- *
- * ratio = ( ( crystal_frequency * 2^22 ) / sample_rate ) & ~3
- *
- * Default crystal_frequency is 28,800,000
- *
- * This produces a 32-bit value that has to be set in 2 x 16-bit registers.
- * Place the high 16-bit value in ratioMSB and the low 16-bit value in
- * ratioLSB. Use integer for these values to avoid sign-extension issues.
- *
- * Mask the value with 0xFFFF when setting the register.
- */
- public enum SampleRate
- {
- /* Note: sample rates below 1.0MHz are subject to aliasing */
- RATE_0_240MHZ( 0x1E00, 240000, "0.240 MHz" ),
- RATE_0_288MHZ( 0x1900, 288000, "0.288 MHz" ),
- RATE_0_960MHZ( 0x0780, 960000, "0.960 MHz" ),
- RATE_1_200MHZ( 0x0600, 1200000, "1.200 MHz" ),
- RATE_1_440MHZ( 0x0500, 1440000, "1.440 MHz" ),
- RATE_1_920MHZ( 0x03C0, 2016000, "2.016 MHz" ),
- RATE_2_304MHZ( 0x0320, 2208000, "2.208 MHz" ),
- RATE_2_400MHZ( 0x0300, 2400000, "2.400 MHz" ),
- RATE_2_880MHZ( 0x0280, 2880000, "2.880 MHz" );
-
- private int mRatioHigh;
- private int mRate;
- private String mLabel;
-
- private SampleRate( int ratioHigh,
- int rate,
- String label )
- {
- mRatioHigh = ratioHigh;
- mRate = rate;
- mLabel = label;
- }
-
- public int getRatioHighBits()
- {
- return mRatioHigh;
- }
-
- public int getRate()
- {
- return mRate;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
-
- public String toString()
- {
- return mLabel;
- }
-
- /**
- * Returns the sample rate that is equal to the argument or the next
- * higher sample rate
- * @param sampleRate
- * @return
- */
- public static SampleRate getClosest( int sampleRate )
- {
- for( SampleRate rate: values () )
- {
- if( rate.getRate() >= sampleRate )
- {
- return rate;
- }
- }
-
- return DEFAULT_SAMPLE_RATE;
- }
- }
-
- /**
- * Adds a sample listener. If the buffer processing thread is
- * not currently running, starts it running in a new thread.
- */
- public void addListener( Listener listener )
- {
- synchronized( mComplexBufferBroadcaster )
- {
- mComplexBufferBroadcaster.addListener( listener );
-
- if( mBufferProcessor == null )
- {
- mBufferProcessor = new BufferProcessor( mThreadPoolManager );
- }
-
- if( !mBufferProcessor.isRunning() )
- {
- Thread thread = new Thread( mBufferProcessor );
- thread.setDaemon( true );
- thread.setName( "RTL2832 Sample Processor" );
-
- thread.start();
- }
- }
- }
-
- /**
- * Removes the sample listener. If this is the last registered listener,
- * shuts down the buffer processing thread.
- */
- public void removeListener( Listener listener )
- {
- synchronized( mComplexBufferBroadcaster )
- {
- mComplexBufferBroadcaster.removeListener( listener );
-
- if( !mComplexBufferBroadcaster.hasListeners() )
- {
- mBufferProcessor.stop();
- }
- }
- }
-
- /**
- * Buffer processing thread. Fetches samples from the RTL2832 Tuner and
- * dispatches them to all registered listeners
- */
- public class BufferProcessor implements Runnable, TransferCallback
- {
- private ScheduledFuture> mSampleDispatcherTask;
- private LinkedTransferQueue mAvailableTransfers;
- private LinkedTransferQueue mTransfersInProgress = new LinkedTransferQueue<>();
- private AtomicBoolean mRunning = new AtomicBoolean();
- private ThreadPoolManager mThreadPoolManager;
- private ByteBuffer mLibUsbHandlerStatus;
- private boolean mCancel = false;
-
- public BufferProcessor( ThreadPoolManager manager )
- {
- mThreadPoolManager = manager;
- }
-
- @Override
- public void run()
+ writeRegister(handle, Block.I2C, EEPROM_ADDRESS, (byte) offset, 1);
+ }
+ catch(LibUsbException e)
{
- if( mRunning.compareAndSet( false, true ) )
- {
- try
- {
- setSampleRate( mSampleRate );
-
- resetUSBBuffer();
- }
- catch( SourceException e )
- {
- mLog.error( "couldn't start buffer processor", e );
-
- mRunning.set( false );
- }
-
- prepareTransfers();
-
- try
- {
- mSampleDispatcherTask = mThreadPoolManager.scheduleFixedRate(
- ThreadType.SOURCE_SAMPLE_PROCESSING, new BufferDispatcher(),
- 20, TimeUnit.MILLISECONDS );
- }
- catch( NullPointerException npe )
- {
- mLog.error( "NPE! = tpm null: " + ( mThreadPoolManager == null ), npe );
- }
-
- mLibUsbHandlerStatus = ByteBuffer.allocateDirect( 4 );
-
- List transfers = new ArrayList<>();
-
- mCancel = false;
-
- while( mRunning.get() )
- {
- mAvailableTransfers.drainTo( transfers );
-
- for( Transfer transfer: transfers )
- {
- int result = LibUsb.submitTransfer( transfer );
-
- if( result == LibUsb.SUCCESS )
- {
- mTransfersInProgress.add( transfer );
- }
- else
- {
- mLog.error( "Error submitting transfer [" +
- LibUsb.errorName( result ) + "]" );
- }
- }
-
- int result = LibUsb.handleEventsTimeoutCompleted(
- null, TIMEOUT_US, mLibUsbHandlerStatus.asIntBuffer() );
-
- if( result != LibUsb.SUCCESS )
- {
- mLog.error( "error handling events for libusb" );
- }
-
- transfers.clear();
-
- mLibUsbHandlerStatus.rewind();
- }
-
- if( mCancel )
- {
- for( Transfer transfer: mTransfersInProgress )
- {
- LibUsb.cancelTransfer( transfer );
- }
-
- int result = LibUsb.handleEventsTimeoutCompleted( null,
- TIMEOUT_US, mLibUsbHandlerStatus.asIntBuffer() );
-
- if( result != LibUsb.SUCCESS )
- {
- mLog.error( "error handling events for libusb during cancel" );
- }
-
- mLibUsbHandlerStatus.rewind();
- }
- }
+ mLog.error("usb error while attempting to set read address to "
+ + "EEPROM register, prior to reading the EEPROM device "
+ + "descriptor", e);
}
- /**
- * Stops the sample fetching thread
- */
- public void stop()
- {
- mCancel = true;
-
- if( mRunning.compareAndSet( true, false ) )
- {
- if( mSampleDispatcherTask != null )
- {
- mThreadPoolManager.cancel( mSampleDispatcherTask );
- mSampleDispatcherTask = null;
- mFilledBuffers.clear();
- }
- }
- }
+ for(int x = 0; x < length; x++)
+ {
+ try
+ {
+ read(handle, EEPROM_ADDRESS, Block.I2C, buffer);
+ data[x] = buffer.get();
+ buffer.rewind();
+ }
+ catch(Exception e)
+ {
+ mLog.error("error while reading eeprom byte [" + x + "/" +
+ length + "] aborting eeprom read and returning partially "
+ + "filled descriptor byte array", e);
+ x = length;
+ }
+ }
- /**
- * Indicates if this thread is running
- */
- public boolean isRunning()
- {
- return mRunning.get();
- }
-
- @Override
- public void processTransfer( Transfer transfer )
- {
- mTransfersInProgress.remove( transfer );
-
- switch( transfer.status() )
- {
- case LibUsb.TRANSFER_COMPLETED:
- case LibUsb.TRANSFER_STALL:
- if( transfer.actualLength() > 0 )
- {
- ByteBuffer buffer = transfer.buffer();
-
- byte[] data = new byte[ transfer.actualLength() ];
-
- buffer.get( data );
+ return data;
+ }
- buffer.rewind();
+ /**
+ * Writes a single byte to the 256-byte EEPROM using the specified offset.
+ *
+ * Note: introduce a 5 millisecond delay between each successive write to
+ * the EEPROM or subsequent writes may fail.
+ */
+ public void writeEEPROMByte(DeviceHandle handle, byte offset, byte value)
+ throws IllegalArgumentException, UsbDisconnectedException, UsbException
+ {
+ if(offset < 0 || offset > 255)
+ {
+ throw new IllegalArgumentException("RTL2832 Tuner Controller - "
+ + "EEPROM offset must be within range of 0 - 255");
+ }
- if( isRunning() )
- {
- mFilledBuffers.add( data );
- }
- }
- break;
- case LibUsb.TRANSFER_CANCELLED:
- break;
- default:
+ int offsetAndValue = Integer.rotateLeft((0xFF & offset), 8) |
+ (0xFF & value);
+
+ writeRegister(handle, Block.I2C, EEPROM_ADDRESS, offsetAndValue, 2);
+ }
+
+ public enum Address
+ {
+ USB_SYSCTL(0x2000),
+ USB_CTRL(0x2010),
+ USB_STAT(0x2014),
+ USB_EPA_CFG(0x2144),
+ USB_EPA_CTL(0x2148),
+ USB_EPA_MAXPKT(0x2158),
+ USB_EPA_MAXPKT_2(0x215A),
+ USB_EPA_FIFO_CFG(0x2160),
+ DEMOD_CTL(0x3000),
+ GPO(0x3001),
+ GPI(0x3002),
+ GPOE(0x3003),
+ GPD(0x3004),
+ SYSINTE(0x3005),
+ SYSINTS(0x3006),
+ GP_CFG0(0x3007),
+ GP_CFG1(0x3008),
+ SYSINTE_1(0x3009),
+ SYSINTS_1(0x300A),
+ DEMOD_CTL_1(0x300B),
+ IR_SUSPEND(0x300C);
+
+ private int mAddress;
+
+ private Address(int address)
+ {
+ mAddress = address;
+ }
+
+ public short getAddress()
+ {
+ return (short) mAddress;
+ }
+ }
+
+ public enum Page
+ {
+ ZERO(0x0),
+ ONE(0x1),
+ TEN(0xA);
+
+ private int mPage;
+
+ private Page(int page)
+ {
+ mPage = page;
+ }
+
+ public byte getPage()
+ {
+ return (byte) (mPage & 0xFF);
+ }
+ }
+
+ public enum SampleMode
+ {
+ QUADRATURE, DIRECT;
+ }
+
+ public enum Block
+ {
+ DEMOD(0),
+ USB(1),
+ SYS(2),
+ TUN(3),
+ ROM(4),
+ IR(5),
+ I2C(6); //I2C controller
+
+ private int mValue;
+
+ private Block(int value)
+ {
+ mValue = value;
+ }
+
+ public int getValue()
+ {
+ return mValue;
+ }
+
+ /**
+ * Returns the value left shifted 8 bits
+ */
+ public short getReadIndex()
+ {
+ return (short) Integer.rotateLeft(mValue, 8);
+ }
+
+ public short getWriteIndex()
+ {
+ return (short) (getReadIndex() | 0x10);
+ }
+ }
+
+ /**
+ * Sample rates supported by the RTL-2832.
+ *
+ * Formula to calculate the ratio value:
+ *
+ * ratio = ( ( crystal_frequency * 2^22 ) / sample_rate ) & ~3
+ *
+ * Default crystal_frequency is 28,800,000
+ *
+ * This produces a 32-bit value that has to be set in 2 x 16-bit registers.
+ * Place the high 16-bit value in ratioMSB and the low 16-bit value in
+ * ratioLSB. Use integer for these values to avoid sign-extension issues.
+ *
+ * Mask the value with 0xFFFF when setting the register.
+ */
+ public enum SampleRate
+ {
+ /* Note: sample rates below 1.0MHz are subject to aliasing */
+ RATE_0_240MHZ(0x1E00, 240000, "0.240 MHz"),
+ RATE_0_288MHZ(0x1900, 288000, "0.288 MHz"),
+ RATE_0_960MHZ(0x0780, 960000, "0.960 MHz"),
+ RATE_1_200MHZ(0x0600, 1200000, "1.200 MHz"),
+ RATE_1_440MHZ(0x0500, 1440000, "1.440 MHz"),
+ RATE_1_920MHZ(0x03C0, 2016000, "2.016 MHz"),
+ RATE_2_304MHZ(0x0320, 2208000, "2.208 MHz"),
+ RATE_2_400MHZ(0x0300, 2400000, "2.400 MHz"),
+ RATE_2_880MHZ(0x0280, 2880000, "2.880 MHz");
+
+ private int mRatioHigh;
+ private int mRate;
+ private String mLabel;
+
+ private SampleRate(int ratioHigh,
+ int rate,
+ String label)
+ {
+ mRatioHigh = ratioHigh;
+ mRate = rate;
+ mLabel = label;
+ }
+
+ public int getRatioHighBits()
+ {
+ return mRatioHigh;
+ }
+
+ public int getRate()
+ {
+ return mRate;
+ }
+
+ public String getLabel()
+ {
+ return mLabel;
+ }
+
+ public String toString()
+ {
+ return mLabel;
+ }
+
+ /**
+ * Returns the sample rate that is equal to the argument or the next
+ * higher sample rate
+ *
+ * @param sampleRate
+ * @return
+ */
+ public static SampleRate getClosest(int sampleRate)
+ {
+ for(SampleRate rate : values())
+ {
+ if(rate.getRate() >= sampleRate)
+ {
+ return rate;
+ }
+ }
+
+ return DEFAULT_SAMPLE_RATE;
+ }
+ }
+
+ /**
+ * Adds a sample listener. If the buffer processing thread is
+ * not currently running, starts it running in a new thread.
+ */
+ public void addListener(Listener listener)
+ {
+ synchronized(mComplexBufferBroadcaster)
+ {
+ mComplexBufferBroadcaster.addListener(listener);
+
+ if(mBufferProcessor == null)
+ {
+ mBufferProcessor = new BufferProcessor();
+ }
+
+ if(!mBufferProcessor.isRunning())
+ {
+ Thread thread = new Thread(mBufferProcessor);
+ thread.setDaemon(true);
+ thread.setName("RTL2832 Sample Processor");
+
+ thread.start();
+ }
+ }
+ }
+
+ /**
+ * Removes the sample listener. If this is the last registered listener,
+ * shuts down the buffer processing thread.
+ */
+ public void removeListener(Listener listener)
+ {
+ synchronized(mComplexBufferBroadcaster)
+ {
+ mComplexBufferBroadcaster.removeListener(listener);
+
+ if(!mComplexBufferBroadcaster.hasListeners())
+ {
+ mBufferProcessor.stop();
+ }
+ }
+ }
+
+ /**
+ * Buffer processing thread. Fetches samples from the RTL2832 Tuner and
+ * dispatches them to all registered listeners
+ */
+ public class BufferProcessor implements Runnable, TransferCallback
+ {
+ private ScheduledFuture> mSampleDispatcherTask;
+ private LinkedTransferQueue mAvailableTransfers;
+ private LinkedTransferQueue mTransfersInProgress = new LinkedTransferQueue<>();
+ private AtomicBoolean mRunning = new AtomicBoolean();
+ private ByteBuffer mLibUsbHandlerStatus;
+ private boolean mCancel = false;
+
+ public BufferProcessor()
+ {
+ }
+
+ @Override
+ public void run()
+ {
+ if(mRunning.compareAndSet(false, true))
+ {
+ try
+ {
+ setSampleRate(mSampleRate);
+
+ resetUSBBuffer();
+ }
+ catch(SourceException e)
+ {
+ mLog.error("couldn't start buffer processor", e);
+
+ mRunning.set(false);
+ }
+
+ prepareTransfers();
+
+ mSampleDispatcherTask = ThreadPool.SCHEDULED.scheduleAtFixedRate(new BufferDispatcher(),
+ 20, 20, TimeUnit.MILLISECONDS);
+
+ mLibUsbHandlerStatus = ByteBuffer.allocateDirect(4);
+
+ List transfers = new ArrayList<>();
+
+ mCancel = false;
+
+ while(mRunning.get())
+ {
+ mAvailableTransfers.drainTo(transfers);
+
+ for(Transfer transfer : transfers)
+ {
+ int result = LibUsb.submitTransfer(transfer);
+
+ if(result == LibUsb.SUCCESS)
+ {
+ mTransfersInProgress.add(transfer);
+ }
+ else
+ {
+ mLog.error("Error submitting transfer [" +
+ LibUsb.errorName(result) + "]");
+ }
+ }
+
+ int result = LibUsb.handleEventsTimeoutCompleted(
+ null, TIMEOUT_US, mLibUsbHandlerStatus.asIntBuffer());
+
+ if(result != LibUsb.SUCCESS)
+ {
+ mLog.error("error handling events for libusb");
+ }
+
+ transfers.clear();
+
+ mLibUsbHandlerStatus.rewind();
+ }
+
+ if(mCancel)
+ {
+ for(Transfer transfer : mTransfersInProgress)
+ {
+ LibUsb.cancelTransfer(transfer);
+ }
+
+ int result = LibUsb.handleEventsTimeoutCompleted(null,
+ TIMEOUT_US, mLibUsbHandlerStatus.asIntBuffer());
+
+ if(result != LibUsb.SUCCESS)
+ {
+ mLog.error("error handling events for libusb during cancel");
+ }
+
+ mLibUsbHandlerStatus.rewind();
+ }
+ }
+ }
+
+ /**
+ * Stops the sample fetching thread
+ */
+ public void stop()
+ {
+ mCancel = true;
+
+ if(mRunning.compareAndSet(true, false))
+ {
+ if(mSampleDispatcherTask != null)
+ {
+ mSampleDispatcherTask.cancel(true);
+ mSampleDispatcherTask = null;
+ mFilledBuffers.clear();
+ }
+ }
+ }
+
+ /**
+ * Indicates if this thread is running
+ */
+ public boolean isRunning()
+ {
+ return mRunning.get();
+ }
+
+ @Override
+ public void processTransfer(Transfer transfer)
+ {
+ mTransfersInProgress.remove(transfer);
+
+ switch(transfer.status())
+ {
+ case LibUsb.TRANSFER_COMPLETED:
+ case LibUsb.TRANSFER_STALL:
+ if(transfer.actualLength() > 0)
+ {
+ ByteBuffer buffer = transfer.buffer();
+
+ byte[] data = new byte[transfer.actualLength()];
+
+ buffer.get(data);
+
+ buffer.rewind();
+
+ if(isRunning())
+ {
+ mFilledBuffers.add(data);
+ }
+ }
+ break;
+ case LibUsb.TRANSFER_CANCELLED:
+ break;
+ default:
/* unexpected error */
- mLog.error( "transfer error [" +
- getTransferStatus( transfer.status() ) +
- "] transferred actual: " + transfer.actualLength() );
- }
-
- mAvailableTransfers.add( transfer );
- }
-
- /**
- * Prepares (allocates) a set of transfer buffers for use in
- * transferring data from the tuner via the bulk interface
- */
- private void prepareTransfers() throws LibUsbException
- {
- if( mAvailableTransfers == null )
- {
- mAvailableTransfers = new LinkedTransferQueue<>();
-
- for( int x = 0; x < TRANSFER_BUFFER_POOL_SIZE; x++ )
- {
- Transfer transfer = LibUsb.allocTransfer();
+ mLog.error("transfer error [" +
+ getTransferStatus(transfer.status()) +
+ "] transferred actual: " + transfer.actualLength());
+ }
- if( transfer == null )
- {
- throw new LibUsbException( "couldn't allocate transfer",
- LibUsb.ERROR_NO_MEM );
- }
-
- final ByteBuffer buffer =
- ByteBuffer.allocateDirect( mBufferSize );
-
- LibUsb.fillBulkTransfer( transfer, mDeviceHandle, USB_BULK_ENDPOINT,
- buffer, BufferProcessor.this, "Buffer", TIMEOUT_US );
-
- mAvailableTransfers.add( transfer );
- }
- }
- }
- }
-
- /**
- * Fetches byte[] chunks from the raw sample buffer. Converts each byte
- * array and broadcasts the array to all registered listeners
- */
- public class BufferDispatcher implements Runnable
- {
- @Override
- public void run()
- {
- try
- {
- ArrayList buffers = new ArrayList();
-
- mFilledBuffers.drainTo( buffers );
-
- for( byte[] buffer: buffers )
- {
- float[] samples = mSampleAdapter.convert( buffer );
-
- mComplexBufferBroadcaster.broadcast( new ComplexBuffer( samples ) );
- }
- }
- catch( Exception e )
- {
- mLog.error( "error during rtl2832 buffer dispatcher run", e );
- }
+ mAvailableTransfers.add(transfer);
}
- }
-
- public static String getTransferStatus( int status )
- {
- switch( status )
- {
- case 0:
- return "TRANSFER COMPLETED (0)";
- case 1:
- return "TRANSFER ERROR (1)";
- case 2:
- return "TRANSFER TIMED OUT (2)";
- case 3:
- return "TRANSFER CANCELLED (3)";
- case 4:
- return "TRANSFER STALL (4)";
- case 5:
- return "TRANSFER NO DEVICE (5)";
- case 6:
- return "TRANSFER OVERFLOW (6)";
- default:
- return "UNKNOWN TRANSFER STATUS (" + status + ")";
- }
- }
-
-
- public class USBEventHandlingThread implements Runnable
- {
- /** If thread should abort. */
- private volatile boolean mAbort;
+ /**
+ * Prepares (allocates) a set of transfer buffers for use in
+ * transferring data from the tuner via the bulk interface
+ */
+ private void prepareTransfers() throws LibUsbException
+ {
+ if(mAvailableTransfers == null)
+ {
+ mAvailableTransfers = new LinkedTransferQueue<>();
- /**
- * Aborts the event handling thread.
- */
- public void abort()
- {
- mAbort = true;
- }
+ for(int x = 0; x < TRANSFER_BUFFER_POOL_SIZE; x++)
+ {
+ Transfer transfer = LibUsb.allocTransfer();
- @Override
- public void run()
- {
- while ( !mAbort )
- {
- int result = LibUsb.handleEventsTimeout( null, 1000 );
-
- if ( result != LibUsb.SUCCESS )
- {
- mAbort = true;
+ if(transfer == null)
+ {
+ throw new LibUsbException("couldn't allocate transfer",
+ LibUsb.ERROR_NO_MEM);
+ }
- mLog.error( "error handling usb events [" +
- LibUsb.errorName( result ) + "]" );
-
- throw new LibUsbException("Unable to handle USB "
- + "events", result );
- }
- }
- }
- }
+ final ByteBuffer buffer =
+ ByteBuffer.allocateDirect(mBufferSize);
- public enum TunerTypeCheck
- {
- E4K( 0xC8, 0x02, 0x40 ),
- FC0012( 0xC6, 0x00, 0xA1 ),
- FC0013( 0xC6, 0x00, 0xA3 ),
- FC2580( 0xAC, 0x01, 0x56 ),
- R820T( 0x34, 0x00, 0x69 ),
- R828D( 0x74, 0x00, 0x69 );
-
- private int mI2CAddress;
- private int mCheckAddress;
- private int mCheckValue;
-
- private TunerTypeCheck( int i2c, int address, int value )
- {
- mI2CAddress = i2c;
- mCheckAddress = address;
- mCheckValue = value;
- }
+ LibUsb.fillBulkTransfer(transfer, mDeviceHandle, USB_BULK_ENDPOINT,
+ buffer, BufferProcessor.this, "Buffer", TIMEOUT_US);
- public byte getI2CAddress()
- {
- return (byte)mI2CAddress;
- }
-
- public byte getCheckAddress()
- {
- return (byte)mCheckAddress;
- }
-
- public byte getCheckValue()
- {
- return (byte)mCheckValue;
- }
- }
-
-
- /**
- * Averages the sample rate over a 10-second period. The count is for the
- * number of bytes received from the tuner. There are two bytes for each
- * sample. So, we divide by 20 to get the average sample rate.
- */
- public class SampleRateMonitor implements Runnable
- {
- private static final int BUFFER_SIZE = 5;
- private int mTargetSampleRate;
- private int mSampleRateMinimum;
- private int mSampleRateMaximum;
- private int mNewTargetSampleRate;
- private FloatAveragingBuffer mRateErrorBuffer =
- new FloatAveragingBuffer( BUFFER_SIZE );
- private AtomicBoolean mRateChanged = new AtomicBoolean();
-
- public SampleRateMonitor( int sampleRate )
- {
- setTargetRate( sampleRate );
- }
-
- public void setSampleRate( int sampleRate )
- {
- mNewTargetSampleRate = sampleRate;
- mRateChanged.set( true );
- }
-
- private void setTargetRate( int rate )
- {
- mTargetSampleRate = rate;
- mSampleRateMinimum = (int)( (float)mTargetSampleRate * 0.95f );
- mSampleRateMaximum = (int)( (float)mTargetSampleRate * 1.05f );
+ mAvailableTransfers.add(transfer);
+ }
+ }
+ }
+ }
- for( int x = 0; x < BUFFER_SIZE; x++ )
- {
- mRateErrorBuffer.get( 0 );
- }
- }
-
- @Override
+ /**
+ * Fetches byte[] chunks from the raw sample buffer. Converts each byte
+ * array and broadcasts the array to all registered listeners
+ */
+ public class BufferDispatcher implements Runnable
+ {
+ @Override
public void run()
{
- if( mRateChanged.compareAndSet( true, false ) )
- {
- setTargetRate( mNewTargetSampleRate );
+ try
+ {
+ ArrayList buffers = new ArrayList();
+
+ mFilledBuffers.drainTo(buffers);
+
+ for(byte[] buffer : buffers)
+ {
+ float[] samples = mSampleAdapter.convert(buffer);
+
+ mComplexBufferBroadcaster.broadcast(new ComplexBuffer(samples));
+ }
+ }
+ catch(Exception e)
+ {
+ mLog.error("error during rtl2832 buffer dispatcher run", e);
+ }
+ }
+ }
+
+ public static String getTransferStatus(int status)
+ {
+ switch(status)
+ {
+ case 0:
+ return "TRANSFER COMPLETED (0)";
+ case 1:
+ return "TRANSFER ERROR (1)";
+ case 2:
+ return "TRANSFER TIMED OUT (2)";
+ case 3:
+ return "TRANSFER CANCELLED (3)";
+ case 4:
+ return "TRANSFER STALL (4)";
+ case 5:
+ return "TRANSFER NO DEVICE (5)";
+ case 6:
+ return "TRANSFER OVERFLOW (6)";
+ default:
+ return "UNKNOWN TRANSFER STATUS (" + status + ")";
+ }
+ }
+
+
+ public class USBEventHandlingThread implements Runnable
+ {
+ /**
+ * If thread should abort.
+ */
+ private volatile boolean mAbort;
+
+ /**
+ * Aborts the event handling thread.
+ */
+ public void abort()
+ {
+ mAbort = true;
+ }
+
+ @Override
+ public void run()
+ {
+ while(!mAbort)
+ {
+ int result = LibUsb.handleEventsTimeout(null, 1000);
+
+ if(result != LibUsb.SUCCESS)
+ {
+ mAbort = true;
+
+ mLog.error("error handling usb events [" +
+ LibUsb.errorName(result) + "]");
+
+ throw new LibUsbException("Unable to handle USB "
+ + "events", result);
+ }
+ }
+ }
+ }
+
+ public enum TunerTypeCheck
+ {
+ E4K(0xC8, 0x02, 0x40),
+ FC0012(0xC6, 0x00, 0xA1),
+ FC0013(0xC6, 0x00, 0xA3),
+ FC2580(0xAC, 0x01, 0x56),
+ R820T(0x34, 0x00, 0x69),
+ R828D(0x74, 0x00, 0x69);
+
+ private int mI2CAddress;
+ private int mCheckAddress;
+ private int mCheckValue;
+
+ private TunerTypeCheck(int i2c, int address, int value)
+ {
+ mI2CAddress = i2c;
+ mCheckAddress = address;
+ mCheckValue = value;
+ }
+
+ public byte getI2CAddress()
+ {
+ return (byte) mI2CAddress;
+ }
+
+ public byte getCheckAddress()
+ {
+ return (byte) mCheckAddress;
+ }
+
+ public byte getCheckValue()
+ {
+ return (byte) mCheckValue;
+ }
+ }
+
+
+ /**
+ * Averages the sample rate over a 10-second period. The count is for the
+ * number of bytes received from the tuner. There are two bytes for each
+ * sample. So, we divide by 20 to get the average sample rate.
+ */
+ public class SampleRateMonitor implements Runnable
+ {
+ private static final int BUFFER_SIZE = 5;
+ private int mTargetSampleRate;
+ private int mSampleRateMinimum;
+ private int mSampleRateMaximum;
+ private int mNewTargetSampleRate;
+ private FloatAveragingBuffer mRateErrorBuffer =
+ new FloatAveragingBuffer(BUFFER_SIZE);
+ private AtomicBoolean mRateChanged = new AtomicBoolean();
+
+ public SampleRateMonitor(int sampleRate)
+ {
+ setTargetRate(sampleRate);
+ }
+
+ public void setSampleRate(int sampleRate)
+ {
+ mNewTargetSampleRate = sampleRate;
+ mRateChanged.set(true);
+ }
+
+ private void setTargetRate(int rate)
+ {
+ mTargetSampleRate = rate;
+ mSampleRateMinimum = (int) ((float) mTargetSampleRate * 0.95f);
+ mSampleRateMaximum = (int) ((float) mTargetSampleRate * 1.05f);
+
+ for(int x = 0; x < BUFFER_SIZE; x++)
+ {
+ mRateErrorBuffer.get(0);
+ }
+ }
+
+ @Override
+ public void run()
+ {
+ if(mRateChanged.compareAndSet(true, false))
+ {
+ setTargetRate(mNewTargetSampleRate);
/* Reset the sample counter */
- mSampleCounter.set( 0 );
-
- mLog.info( "monitor reset for new sample rate [" + mTargetSampleRate + "]" );
- }
- else
- {
- int count = mSampleCounter.getAndSet( 0 );
-
- float current = (float)count / 20.0f;
+ mSampleCounter.set(0);
- /**
- * Only accept values +/- 5% of target rate
- */
- float average;
-
- if( mSampleRateMinimum < current && current < mSampleRateMaximum )
- {
- average = mRateErrorBuffer.get( (float)mTargetSampleRate - current );
- }
- else
- {
- average = mTargetSampleRate;
- }
-
- StringBuilder sb = new StringBuilder();
- sb.append( "[" );
- if( mDescriptor != null )
- {
- sb.append( mDescriptor.getSerial() );
- }
- else
- {
- sb.append( "DESCRIPTOR IS NULL" );
- }
- sb.append( "] sample rate current [" );
- sb.append( mDecimalFormatter.format( current ) );
- sb.append( " Hz " );
- sb.append( mPercentFormatter.format( 100.0f * ( current / (float)mTargetSampleRate ) ) );
- sb.append( "% ] error [" );
- sb.append( average );
- sb.append( " Hz ] target " );
- sb.append( mDecimalFormatter.format( mTargetSampleRate ) );
-
- mLog.info( sb.toString() );
- }
+ mLog.info("monitor reset for new sample rate [" + mTargetSampleRate + "]");
+ }
+ else
+ {
+ int count = mSampleCounter.getAndSet(0);
+
+ float current = (float) count / 20.0f;
+
+ /**
+ * Only accept values +/- 5% of target rate
+ */
+ float average;
+
+ if(mSampleRateMinimum < current && current < mSampleRateMaximum)
+ {
+ average = mRateErrorBuffer.get((float) mTargetSampleRate - current);
+ }
+ else
+ {
+ average = mTargetSampleRate;
+ }
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("[");
+ if(mDescriptor != null)
+ {
+ sb.append(mDescriptor.getSerial());
+ }
+ else
+ {
+ sb.append("DESCRIPTOR IS NULL");
+ }
+ sb.append("] sample rate current [");
+ sb.append(mDecimalFormatter.format(current));
+ sb.append(" Hz ");
+ sb.append(mPercentFormatter.format(100.0f * (current / (float) mTargetSampleRate)));
+ sb.append("% ] error [");
+ sb.append(average);
+ sb.append(" Hz ] target ");
+ sb.append(mDecimalFormatter.format(mTargetSampleRate));
+
+ mLog.info(sb.toString());
+ }
}
- }
- /**
- * RTL2832 EEPROM byte array descriptor parsing class
- */
- public class Descriptor
- {
- private byte[] mData;
- private ArrayList mLabels = new ArrayList();
-
- public Descriptor( byte[] data )
- {
- if( data != null )
- {
- mData = data;
- }
- else
- {
- data = new byte[ 256 ];
- }
-
- getLabels();
- }
-
- public boolean isValid()
- {
- return mData[ 0 ] == (byte)0x28 &&
- mData[ 1 ] == (byte)0x32;
- }
-
- public String getVendorID()
- {
- int id = Integer.rotateLeft( ( 0xFF & mData[ 3] ), 8 ) |
- ( 0xFF & mData[ 2 ] );
+ }
- return String.format("%04X", id );
- }
-
- public String getVendorLabel()
- {
- return mLabels.get( 0 );
- }
-
- public String getProductID()
- {
- int id = Integer.rotateLeft( ( 0xFF & mData[ 5] ), 8 ) |
- ( 0xFF & mData[ 4 ] );
+ /**
+ * RTL2832 EEPROM byte array descriptor parsing class
+ */
+ public class Descriptor
+ {
+ private byte[] mData;
+ private ArrayList mLabels = new ArrayList();
- return String.format("%04X", id );
- }
-
- public String getProductLabel()
- {
- return mLabels.get( 1 );
- }
-
- public boolean hasSerial()
- {
- return mData[ 6 ] == (byte)0xA5;
- }
+ public Descriptor(byte[] data)
+ {
+ if(data != null)
+ {
+ mData = data;
+ }
+ else
+ {
+ data = new byte[256];
+ }
- public String getSerial()
- {
- return mLabels.get( 2 );
- }
-
- public boolean remoteWakeupEnabled()
- {
- byte mask = (byte)0x01;
-
- return ( mData[ 7 ] & mask ) == mask;
- }
-
- public boolean irEnabled()
- {
- byte mask = (byte)0x02;
-
- return ( mData[ 7 ] & mask ) == mask;
- }
+ getLabels();
+ }
- private void getLabels()
- {
- mLabels.clear();
-
- int start = 0x09;
-
- while( start < 256 )
- {
- start = getLabel( start );
- }
- }
-
- private int getLabel( int start )
- {
+ public boolean isValid()
+ {
+ return mData[0] == (byte) 0x28 &&
+ mData[1] == (byte) 0x32;
+ }
+
+ public String getVendorID()
+ {
+ int id = Integer.rotateLeft((0xFF & mData[3]), 8) |
+ (0xFF & mData[2]);
+
+ return String.format("%04X", id);
+ }
+
+ public String getVendorLabel()
+ {
+ return mLabels.get(0);
+ }
+
+ public String getProductID()
+ {
+ int id = Integer.rotateLeft((0xFF & mData[5]), 8) |
+ (0xFF & mData[4]);
+
+ return String.format("%04X", id);
+ }
+
+ public String getProductLabel()
+ {
+ return mLabels.get(1);
+ }
+
+ public boolean hasSerial()
+ {
+ return mData[6] == (byte) 0xA5;
+ }
+
+ public String getSerial()
+ {
+ return mLabels.get(2);
+ }
+
+ public boolean remoteWakeupEnabled()
+ {
+ byte mask = (byte) 0x01;
+
+ return (mData[7] & mask) == mask;
+ }
+
+ public boolean irEnabled()
+ {
+ byte mask = (byte) 0x02;
+
+ return (mData[7] & mask) == mask;
+ }
+
+ private void getLabels()
+ {
+ mLabels.clear();
+
+ int start = 0x09;
+
+ while(start < 256)
+ {
+ start = getLabel(start);
+ }
+ }
+
+ private int getLabel(int start)
+ {
/* Validate length and check second byte for ETX (0x03) */
- if( start > 254 || mData[ start + 1 ] != (byte)0x03 )
- {
- return 256;
- }
+ if(start > 254 || mData[start + 1] != (byte) 0x03)
+ {
+ return 256;
+ }
/* Get label length, including the length and ETX bytes */
- int length = 0xFF & mData[ start ];
+ int length = 0xFF & mData[start];
- if( start + length > 255 )
- {
- return 256;
- }
+ if(start + length > 255)
+ {
+ return 256;
+ }
/* Get the label bytes */
- byte[] data = Arrays.copyOfRange( mData, start + 2, start + length );
+ byte[] data = Arrays.copyOfRange(mData, start + 2, start + length);
/* Translate the bytes as UTF-16 Little Endian and store the label */
- String label = new String( data, Charset.forName( "UTF-16LE" ) );
-
- mLabels.add( label );
+ String label = new String(data, Charset.forName("UTF-16LE"));
- return start + length;
- }
-
- public String toString()
- {
- StringBuilder sb = new StringBuilder();
- sb.append( "RTL-2832 EEPROM Descriptor\n" );
+ mLabels.add(label);
- sb.append( "Vendor: " );
- sb.append( getVendorID() );
- sb.append( " [" );
- sb.append( getVendorLabel() );
- sb.append( "]\n" );
+ return start + length;
+ }
- sb.append( "Product: " );
- sb.append( getProductID() );
- sb.append( " [" );
- sb.append( getProductLabel() );
- sb.append( "]\n" );
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("RTL-2832 EEPROM Descriptor\n");
- sb.append( "Serial: " );
- if( hasSerial() )
- {
- sb.append( "yes [" );
- sb.append( getSerial() );
- sb.append( "]\n" );
- }
- else
- {
- sb.append( "no\n" );
- }
+ sb.append("Vendor: ");
+ sb.append(getVendorID());
+ sb.append(" [");
+ sb.append(getVendorLabel());
+ sb.append("]\n");
- sb.append( "Remote Wakeup Enabled: " );
- sb.append( ( remoteWakeupEnabled() ? "yes" : "no" ) );
- sb.append( "\n" );
+ sb.append("Product: ");
+ sb.append(getProductID());
+ sb.append(" [");
+ sb.append(getProductLabel());
+ sb.append("]\n");
- sb.append( "IR Enabled: " );
- sb.append( ( irEnabled() ? "yes" : "no" ) );
- sb.append( "\n" );
+ sb.append("Serial: ");
+ if(hasSerial())
+ {
+ sb.append("yes [");
+ sb.append(getSerial());
+ sb.append("]\n");
+ }
+ else
+ {
+ sb.append("no\n");
+ }
+
+ sb.append("Remote Wakeup Enabled: ");
+ sb.append((remoteWakeupEnabled() ? "yes" : "no"));
+ sb.append("\n");
+
+ sb.append("IR Enabled: ");
+ sb.append((irEnabled() ? "yes" : "no"));
+ sb.append("\n");
+
+ if(mLabels.size() > 3)
+ {
+ sb.append("Additional Labels: ");
+
+ for(int x = 3; x < mLabels.size(); x++)
+ {
+ sb.append(" [");
+ sb.append(mLabels.get(x));
+ sb.append("\n");
+ }
+ }
+
+ return sb.toString();
+ }
+ }
- if( mLabels.size() > 3 )
- {
- sb.append( "Additional Labels: " );
-
- for( int x = 3; x < mLabels.size(); x++ )
- {
- sb.append( " [" );
- sb.append( mLabels.get( x ) );
- sb.append( "\n" );
- }
- }
-
- return sb.toString();
- }
- }
-
}
diff --git a/src/source/tuner/rtl/e4k/E4KTunerController.java b/src/source/tuner/rtl/e4k/E4KTunerController.java
index 2a84405c..a04e1a42 100644
--- a/src/source/tuner/rtl/e4k/E4KTunerController.java
+++ b/src/source/tuner/rtl/e4k/E4KTunerController.java
@@ -1,26 +1,22 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 Dennis Sheirer
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
******************************************************************************/
package source.tuner.rtl.e4k;
-import java.util.Arrays;
-
-import javax.usb.UsbException;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.usb4java.Device;
@@ -28,2483 +24,2484 @@ import org.usb4java.DeviceDescriptor;
import org.usb4java.DeviceHandle;
import org.usb4java.LibUsb;
import org.usb4java.LibUsbException;
-
import source.SourceException;
import source.tuner.TunerType;
import source.tuner.configuration.TunerConfiguration;
import source.tuner.rtl.RTL2832TunerController;
-import controller.ThreadPoolManager;
+
+import javax.usb.UsbException;
+import java.util.Arrays;
public class E4KTunerController extends RTL2832TunerController
{
- private final static Logger mLog =
- LoggerFactory.getLogger( E4KTunerController.class );
+ private final static Logger mLog =
+ LoggerFactory.getLogger(E4KTunerController.class);
- public static final long MIN_FREQUENCY = 52000000;
- public static final long MAX_FREQUENCY = 2200000000l;
- public static final double USABLE_BANDWIDTH_PERCENT = 0.95;
- public static final int DC_SPIKE_AVOID_BUFFER = 15000;
+ public static final long MIN_FREQUENCY = 52000000;
+ public static final long MAX_FREQUENCY = 2200000000l;
+ public static final double USABLE_BANDWIDTH_PERCENT = 0.95;
+ public static final int DC_SPIKE_AVOID_BUFFER = 15000;
- /* The local oscillator is defined by whole (integer) units of the oscillator
- * frequency and fractional units representing 1/65536th of the oscillator
- * frequency, meaning we can only tune the local oscillator in units of
+ /* The local oscillator is defined by whole (integer) units of the oscillator
+ * frequency and fractional units representing 1/65536th of the oscillator
+ * frequency, meaning we can only tune the local oscillator in units of
* 439.453125 hertz. */
- public static final long E4K_PLL_Y = 65536l; /* 16-bit fractional register */
- public static final byte MASTER1_RESET = (byte)0x01;
- public static final byte MASTER1_NORM_STBY = (byte)0x02;
- public static final byte MASTER1_POR_DET = (byte)0x04;
-
- public static final byte SYNTH1_PLL_LOCK = (byte)0x01;
- public static final byte SYNTH1_BAND_SHIF = (byte)0x01;
+ public static final long E4K_PLL_Y = 65536l; /* 16-bit fractional register */
+ public static final byte MASTER1_RESET = (byte) 0x01;
+ public static final byte MASTER1_NORM_STBY = (byte) 0x02;
+ public static final byte MASTER1_POR_DET = (byte) 0x04;
- public static final byte SYNTH7_3PHASE_EN = (byte)0x08;
+ public static final byte SYNTH1_PLL_LOCK = (byte) 0x01;
+ public static final byte SYNTH1_BAND_SHIF = (byte) 0x01;
- public static final byte SYNTH8_VCOCAL_UPD = (byte)0x04;
-
- public static final byte FILT3_MASK = (byte)0x20;
- public static final byte FILT3_ENABLE = (byte)0x00;
- public static final byte FILT3_DISABLE = (byte)0x20;
-
- public static final byte MIXER_FILTER_MASK = (byte)0xF0;
- public static final byte IF_CHANNEL_FILTER_MASK = (byte)0x1F;
- public static final byte IF_RC_FILTER_MASK = (byte)0x0F;
-
+ public static final byte SYNTH7_3PHASE_EN = (byte) 0x08;
- public static final byte AGC1_LIN_MODE = (byte)0x10;
- public static final byte AGC1_LNA_UPDATE = (byte)0x20;
- public static final byte AGC1_LNA_G_LOW = (byte)0x40;
- public static final byte AGC1_LNA_G_HIGH = (byte)0x80;
- public static final byte AGC1_MOD_MASK = (byte)0xF;
+ public static final byte SYNTH8_VCOCAL_UPD = (byte) 0x04;
- public static final byte GAIN1_MOD_MASK = (byte)0xF;
- public static final byte IF_GAIN_MODE_SWITCHING_MASK = (byte)0x1;
+ public static final byte FILT3_MASK = (byte) 0x20;
+ public static final byte FILT3_ENABLE = (byte) 0x00;
+ public static final byte FILT3_DISABLE = (byte) 0x20;
- public static final byte AGC6_LNA_CAL_REQ = (byte)0x10;
-
- public static final byte AGC7_MIXER_GAIN_MASK = (byte)0x01;
- public static final byte AGC7_MIX_GAIN_MANUAL = (byte)0x00;
- public static final byte AGC7_MIX_GAIN_AUTO = (byte)0x01;
- public static final byte AGC7_GAIN_STEP_5DB = (byte)0x20;
-
- public static final byte AGC8_SENS_LIN_AUTO = (byte)0x01;
+ public static final byte MIXER_FILTER_MASK = (byte) 0xF0;
+ public static final byte IF_CHANNEL_FILTER_MASK = (byte) 0x1F;
+ public static final byte IF_RC_FILTER_MASK = (byte) 0x0F;
- public static final byte AGC11_LNA_GAIN_ENH = (byte)0x01;
- public static final byte ENH_GAIN_MOD_MASK = (byte)0x07;
- public static final byte MIXER_GAIN_MASK = (byte)0x01;
-
- public static final byte DC1_CAL_REQ = (byte)0x01;
-
- public static final byte DC5_I_LUT_EN = (byte)0x01;
- public static final byte DC5_Q_LUT_EN = (byte)0x02;
- public static final byte DC5_RANGE_DETECTOR_ENABLED_MASK = (byte)0x04; //DC Offset Detector Enabled
- public static final byte DC5_RANGE_DETECTOR_ENABLED = (byte)0x04; //DC Offset Detector Enabled
- public static final byte DC5_RANGE_EN = (byte)0x08;
- public static final byte DC5_RANGE_DETECTOR_DISABLED_MASK = (byte)0x03;
- public static final byte DC5_RANGE_DETECTOR_DISABLED = (byte)0x00;
-
- public static final byte DC5_TIMEVAR_EN = (byte)0x10;
-
- public static final byte CLKOUT_DISABLE = (byte)0x96;
-
- public static final byte CHFCALIB_CMD = (byte)0x01;
-
- public E4KTunerController( Device device,
- DeviceDescriptor deviceDescriptor,
- ThreadPoolManager threadPoolManager )
- throws SourceException
- {
- super( device, deviceDescriptor, threadPoolManager, MIN_FREQUENCY,
- MAX_FREQUENCY, DC_SPIKE_AVOID_BUFFER, USABLE_BANDWIDTH_PERCENT );
- }
- @Override
+ public static final byte AGC1_LIN_MODE = (byte) 0x10;
+ public static final byte AGC1_LNA_UPDATE = (byte) 0x20;
+ public static final byte AGC1_LNA_G_LOW = (byte) 0x40;
+ public static final byte AGC1_LNA_G_HIGH = (byte) 0x80;
+ public static final byte AGC1_MOD_MASK = (byte) 0xF;
+
+ public static final byte GAIN1_MOD_MASK = (byte) 0xF;
+ public static final byte IF_GAIN_MODE_SWITCHING_MASK = (byte) 0x1;
+
+ public static final byte AGC6_LNA_CAL_REQ = (byte) 0x10;
+
+ public static final byte AGC7_MIXER_GAIN_MASK = (byte) 0x01;
+ public static final byte AGC7_MIX_GAIN_MANUAL = (byte) 0x00;
+ public static final byte AGC7_MIX_GAIN_AUTO = (byte) 0x01;
+ public static final byte AGC7_GAIN_STEP_5DB = (byte) 0x20;
+
+ public static final byte AGC8_SENS_LIN_AUTO = (byte) 0x01;
+
+ public static final byte AGC11_LNA_GAIN_ENH = (byte) 0x01;
+ public static final byte ENH_GAIN_MOD_MASK = (byte) 0x07;
+ public static final byte MIXER_GAIN_MASK = (byte) 0x01;
+
+ public static final byte DC1_CAL_REQ = (byte) 0x01;
+
+ public static final byte DC5_I_LUT_EN = (byte) 0x01;
+ public static final byte DC5_Q_LUT_EN = (byte) 0x02;
+ public static final byte DC5_RANGE_DETECTOR_ENABLED_MASK = (byte) 0x04; //DC Offset Detector Enabled
+ public static final byte DC5_RANGE_DETECTOR_ENABLED = (byte) 0x04; //DC Offset Detector Enabled
+ public static final byte DC5_RANGE_EN = (byte) 0x08;
+ public static final byte DC5_RANGE_DETECTOR_DISABLED_MASK = (byte) 0x03;
+ public static final byte DC5_RANGE_DETECTOR_DISABLED = (byte) 0x00;
+
+ public static final byte DC5_TIMEVAR_EN = (byte) 0x10;
+
+ public static final byte CLKOUT_DISABLE = (byte) 0x96;
+
+ public static final byte CHFCALIB_CMD = (byte) 0x01;
+
+ public E4KTunerController(Device device, DeviceDescriptor deviceDescriptor) throws SourceException
+ {
+ super(device, deviceDescriptor, MIN_FREQUENCY, MAX_FREQUENCY, DC_SPIKE_AVOID_BUFFER, USABLE_BANDWIDTH_PERCENT);
+ }
+
+ @Override
public TunerType getTunerType()
{
- return TunerType.ELONICS_E4000;
+ return TunerType.ELONICS_E4000;
}
-
- @Override
- public void apply( TunerConfiguration config ) throws SourceException
+
+ @Override
+ public void apply(TunerConfiguration config) throws SourceException
{
- if( config != null && config instanceof E4KTunerConfiguration )
- {
- E4KTunerConfiguration e4kConfig = (E4KTunerConfiguration)config;
+ if(config != null && config instanceof E4KTunerConfiguration)
+ {
+ E4KTunerConfiguration e4kConfig = (E4KTunerConfiguration) config;
+
+ try
+ {
+ SampleRate sampleRate = e4kConfig.getSampleRate();
+ setSampleRate(sampleRate);
+
+ double correction = e4kConfig.getFrequencyCorrection();
+ setFrequencyCorrection(correction);
+
+ E4KGain masterGain = e4kConfig.getMasterGain();
+ setGain(masterGain, true);
+
+ if(masterGain == E4KGain.MANUAL)
+ {
+ E4KMixerGain mixerGain = e4kConfig.getMixerGain();
+ setMixerGain(mixerGain, true);
+
+ E4KLNAGain lnaGain = e4kConfig.getLNAGain();
+ setLNAGain(lnaGain, true);
+
+ E4KEnhanceGain enhanceGain = e4kConfig.getEnhanceGain();
+ setEnhanceGain(enhanceGain, true);
+ }
+
+ try
+ {
+ setFrequency(e4kConfig.getFrequency());
+ }
+ catch(SourceException se)
+ {
+ //Do nothing, we couldn't set the frequency
+ }
+ }
+ catch(UsbException e)
+ {
+ throw new SourceException("E4KTunerController - usb error "
+ + "while applying tuner config", e);
+ }
+
+ }
+ else
+ {
+ throw new IllegalArgumentException("E4KTunerController - cannot "
+ + "apply tuner configuration of type:[" +
+ config.getClass() + "]");
+ }
- try
- {
- SampleRate sampleRate = e4kConfig.getSampleRate();
- setSampleRate( sampleRate );
-
- double correction = e4kConfig.getFrequencyCorrection();
- setFrequencyCorrection( correction );
-
- E4KGain masterGain = e4kConfig.getMasterGain();
- setGain( masterGain, true );
-
- if( masterGain == E4KGain.MANUAL )
- {
- E4KMixerGain mixerGain = e4kConfig.getMixerGain();
- setMixerGain( mixerGain, true );
-
- E4KLNAGain lnaGain = e4kConfig.getLNAGain();
- setLNAGain( lnaGain, true );
-
- E4KEnhanceGain enhanceGain = e4kConfig.getEnhanceGain();
- setEnhanceGain( enhanceGain, true );
- }
-
- try
- {
- setFrequency( e4kConfig.getFrequency() );
- }
- catch( SourceException se )
- {
- //Do nothing, we couldn't set the frequency
- }
- }
- catch( UsbException e )
- {
- throw new SourceException( "E4KTunerController - usb error "
- + "while applying tuner config", e );
- }
-
- }
- else
- {
- throw new IllegalArgumentException( "E4KTunerController - cannot "
- + "apply tuner configuration of type:[" +
- config.getClass() + "]" );
- }
-
}
- public void init() throws SourceException
- {
- mDeviceHandle = new DeviceHandle();
-
- int result = LibUsb.open( mDevice, mDeviceHandle );
+ public void init() throws SourceException
+ {
+ mDeviceHandle = new DeviceHandle();
- if( result != LibUsb.SUCCESS )
- {
- mDeviceHandle = null;
-
- throw new SourceException( "libusb couldn't open RTL2832 usb "
- + "device [" + LibUsb.errorName( result ) + "]" );
- }
+ int result = LibUsb.open(mDevice, mDeviceHandle);
- claimInterface( mDeviceHandle );
+ if(result != LibUsb.SUCCESS)
+ {
+ mDeviceHandle = null;
- byte[] eeprom = null;
-
- try
- {
+ throw new SourceException("libusb couldn't open RTL2832 usb "
+ + "device [" + LibUsb.errorName(result) + "]");
+ }
+
+ claimInterface(mDeviceHandle);
+
+ byte[] eeprom = null;
+
+ try
+ {
/* Read the contents of the 256-byte EEPROM */
- eeprom = readEEPROM( mDeviceHandle, (short)0, 256 );
- }
- catch( Exception e )
- {
- mLog.error( "error while reading the EEPROM device descriptor", e );
- }
-
- try
- {
- mDescriptor = new Descriptor( eeprom );
+ eeprom = readEEPROM(mDeviceHandle, (short) 0, 256);
+ }
+ catch(Exception e)
+ {
+ mLog.error("error while reading the EEPROM device descriptor", e);
+ }
- if( eeprom == null )
- {
- mLog.error( "eeprom byte array was null - constructed "
- + "empty descriptor object" );
- }
- }
- catch( Exception e )
- {
- mLog.error( "error while constructing device descriptor using "
- + "descriptor byte array " +
- ( eeprom == null ? "[null]" : Arrays.toString( eeprom )), e );
- }
+ try
+ {
+ mDescriptor = new Descriptor(eeprom);
- try
- {
+ if(eeprom == null)
+ {
+ mLog.error("eeprom byte array was null - constructed "
+ + "empty descriptor object");
+ }
+ }
+ catch(Exception e)
+ {
+ mLog.error("error while constructing device descriptor using "
+ + "descriptor byte array " +
+ (eeprom == null ? "[null]" : Arrays.toString(eeprom)), e);
+ }
+
+ try
+ {
/* Dummy write to test USB interface */
- writeRegister( mDeviceHandle, Block.USB,
- Address.USB_SYSCTL.getAddress(), (short)0x09, 1 );
+ writeRegister(mDeviceHandle, Block.USB,
+ Address.USB_SYSCTL.getAddress(), (short) 0x09, 1);
- initBaseband( mDeviceHandle );
+ initBaseband(mDeviceHandle);
- enableI2CRepeater( mDeviceHandle, true );
-
- boolean i2CRepeaterControl = false;
-
- initTuner( i2CRepeaterControl );
+ enableI2CRepeater(mDeviceHandle, true);
- enableI2CRepeater( mDeviceHandle, false );
-
- try
- {
- setSampleRate( DEFAULT_SAMPLE_RATE );
- }
- catch( Exception e )
- {
- throw new SourceException( "RTL2832 Tuner Controller - couldn't "
- + "set default sample rate", e );
- }
+ boolean i2CRepeaterControl = false;
- }
- catch( UsbException e )
- {
- e.printStackTrace();
- throw new SourceException( "E4K Tuner Controller - error during "
- + "init()", e );
- }
- }
-
- /**
- * Sets the IF filters (mixer, channel and RC) to the correct filter setting
- * for the selected bandwidth/sample rate
- */
- @Override
- public void setSampleRateFilters( int bandwidth ) throws SourceException
+ initTuner(i2CRepeaterControl);
+
+ enableI2CRepeater(mDeviceHandle, false);
+
+ try
+ {
+ setSampleRate(DEFAULT_SAMPLE_RATE);
+ }
+ catch(Exception e)
+ {
+ throw new SourceException("RTL2832 Tuner Controller - couldn't "
+ + "set default sample rate", e);
+ }
+
+ }
+ catch(UsbException e)
+ {
+ e.printStackTrace();
+ throw new SourceException("E4K Tuner Controller - error during "
+ + "init()", e);
+ }
+ }
+
+ /**
+ * Sets the IF filters (mixer, channel and RC) to the correct filter setting
+ * for the selected bandwidth/sample rate
+ */
+ @Override
+ public void setSampleRateFilters(int bandwidth) throws SourceException
{
/* Determine repeater state so we can restore it when done */
- boolean i2CRepeaterEnabled = isI2CRepeaterEnabled();
+ boolean i2CRepeaterEnabled = isI2CRepeaterEnabled();
- if( !i2CRepeaterEnabled )
- {
- enableI2CRepeater( mDeviceHandle, true );
- }
+ if(!i2CRepeaterEnabled)
+ {
+ enableI2CRepeater(mDeviceHandle, true);
+ }
- boolean controlI2CRepeater = false;
-
- MixerFilter mixer = MixerFilter.getFilter( bandwidth );
- setMixerFilter( mixer, controlI2CRepeater );
+ boolean controlI2CRepeater = false;
- ChannelFilter channel = ChannelFilter.getFilter( bandwidth );
- setChannelFilter( channel, controlI2CRepeater );
+ MixerFilter mixer = MixerFilter.getFilter(bandwidth);
+ setMixerFilter(mixer, controlI2CRepeater);
- RCFilter rc = RCFilter.getFilter( bandwidth );
- setRCFilter( rc, controlI2CRepeater );
+ ChannelFilter channel = ChannelFilter.getFilter(bandwidth);
+ setChannelFilter(channel, controlI2CRepeater);
- if( !i2CRepeaterEnabled )
- {
- enableI2CRepeater( mDeviceHandle, false );
- }
+ RCFilter rc = RCFilter.getFilter(bandwidth);
+ setRCFilter(rc, controlI2CRepeater);
+
+ if(!i2CRepeaterEnabled)
+ {
+ enableI2CRepeater(mDeviceHandle, false);
+ }
}
- @Override
+ @Override
public long getTunedFrequency() throws SourceException
{
- try
- {
+ try
+ {
/* Determine repeater state so we can restore it when done */
- boolean i2CRepeaterEnabled = isI2CRepeaterEnabled();
+ boolean i2CRepeaterEnabled = isI2CRepeaterEnabled();
- if( !i2CRepeaterEnabled )
- {
- enableI2CRepeater( mDeviceHandle, true );
- }
+ if(!i2CRepeaterEnabled)
+ {
+ enableI2CRepeater(mDeviceHandle, true);
+ }
- boolean controlI2CRepeater = false;
-
- byte z = (byte)readE4KRegister( Register.SYNTH3, controlI2CRepeater );
-
- int xHigh = readE4KRegister( Register.SYNTH4, controlI2CRepeater );
- int xLow = readE4KRegister( Register.SYNTH5, controlI2CRepeater );
+ boolean controlI2CRepeater = false;
- int x = ( Integer.rotateLeft( xHigh, 8 ) ) | xLow;
+ byte z = (byte) readE4KRegister(Register.SYNTH3, controlI2CRepeater);
+
+ int xHigh = readE4KRegister(Register.SYNTH4, controlI2CRepeater);
+ int xLow = readE4KRegister(Register.SYNTH5, controlI2CRepeater);
+
+ int x = (Integer.rotateLeft(xHigh, 8)) | xLow;
+
+ int pllSetting = readE4KRegister(Register.SYNTH7, controlI2CRepeater);
+ PLL pll = PLL.fromSetting(pllSetting);
- int pllSetting = readE4KRegister( Register.SYNTH7, controlI2CRepeater );
- PLL pll = PLL.fromSetting( pllSetting );
-
/* Return the repeater to its previous state */
- if( !i2CRepeaterEnabled )
- {
- enableI2CRepeater( mDeviceHandle, false );
- }
+ if(!i2CRepeaterEnabled)
+ {
+ enableI2CRepeater(mDeviceHandle, false);
+ }
- return calculateActualFrequency( pll, z, x );
- }
- catch( LibUsbException e )
- {
- throw new SourceException( "E4K tuner controller - couldn't get "
- + "tuned frequency", e );
- }
+ return calculateActualFrequency(pll, z, x);
+ }
+ catch(LibUsbException e)
+ {
+ throw new SourceException("E4K tuner controller - couldn't get "
+ + "tuned frequency", e);
+ }
}
- @Override
- public void setTunedFrequency( long frequency ) throws SourceException
+ @Override
+ public void setTunedFrequency(long frequency) throws SourceException
{
- /* Get the phase locked loop setting */
- PLL pll = PLL.fromFrequency( frequency );
+ /* Get the phase locked loop setting */
+ PLL pll = PLL.fromFrequency(frequency);
- /* Z is an integer representing the number of scaled oscillator frequency
+ /* Z is an integer representing the number of scaled oscillator frequency
* increments the multiplied frequency. */
- byte z = (byte)( frequency / pll.getScaledOscillator() );
-
+ byte z = (byte) (frequency / pll.getScaledOscillator());
+
/* remainder is just as it describes. It is what is left over after we
- * carve out scaled oscillator frequency increments (z) from the desired
+ * carve out scaled oscillator frequency increments (z) from the desired
* frequency. */
- int remainder = (int)( frequency - ( ( z & 0xFF ) * pll.getScaledOscillator() ) );
+ int remainder = (int) (frequency - ((z & 0xFF) * pll.getScaledOscillator()));
/* X is a 16-bit representation of the remainder */
- int x = (int)( (double)remainder / (double)pll.getScaledOscillator() * E4K_PLL_Y );
+ int x = (int) ((double) remainder / (double) pll.getScaledOscillator() * E4K_PLL_Y);
/* Calculate the exact (tunable) frequency and apply that to the tuner */
- long actualFrequency = calculateActualFrequency( pll, z, x );
-
- /**
- * Hack: if we're trying to set the minimum frequency for the E4K, due
- * to rounding errors, 52 mhz becomes 51.999993, so we need to adjust
- * x to get 52.000003 mhz ... otherwise the PLL won't lock on the freq
- */
- if( actualFrequency < getMinFrequency() )
- {
- x++;
- actualFrequency = calculateActualFrequency( pll, z, x );
- }
-
- /* Apply the actual frequency */
- try
- {
- enableI2CRepeater( mDeviceHandle, true );
+ long actualFrequency = calculateActualFrequency(pll, z, x);
+
+ /**
+ * Hack: if we're trying to set the minimum frequency for the E4K, due
+ * to rounding errors, 52 mhz becomes 51.999993, so we need to adjust
+ * x to get 52.000003 mhz ... otherwise the PLL won't lock on the freq
+ */
+ if(actualFrequency < getMinFrequency())
+ {
+ x++;
+ actualFrequency = calculateActualFrequency(pll, z, x);
+ }
+
+ /* Apply the actual frequency */
+ try
+ {
+ enableI2CRepeater(mDeviceHandle, true);
+
+ boolean controlI2CRepeater = false;
- boolean controlI2CRepeater = false;
-
/* Write the PLL setting */
- writeE4KRegister( Register.SYNTH7, pll.getIndex(), controlI2CRepeater );
-
+ writeE4KRegister(Register.SYNTH7, pll.getIndex(), controlI2CRepeater);
+
/* Write z (integral) value */
- writeE4KRegister( Register.SYNTH3, z, controlI2CRepeater );
-
+ writeE4KRegister(Register.SYNTH3, z, controlI2CRepeater);
+
/* Write the x (fractional) value high-order byte to synth4 register */
- writeE4KRegister( Register.SYNTH4, (byte)( x & 0xFF ), controlI2CRepeater );
-
+ writeE4KRegister(Register.SYNTH4, (byte) (x & 0xFF), controlI2CRepeater);
+
/* Write the x (fractional) value low-order byte to synth5 register */
- writeE4KRegister( Register.SYNTH5,
- (byte)( ( Integer.rotateRight( x, 8 ) ) & 0xFF ),
- controlI2CRepeater );
+ writeE4KRegister(Register.SYNTH5,
+ (byte) ((Integer.rotateRight(x, 8)) & 0xFF),
+ controlI2CRepeater);
/* Set the band for the new frequency */
- setBand( actualFrequency, controlI2CRepeater );
+ setBand(actualFrequency, controlI2CRepeater);
/* Set the filter */
- setRFFilter( actualFrequency, controlI2CRepeater );
-
+ setRFFilter(actualFrequency, controlI2CRepeater);
+
/* Check for PLL lock */
- int lock = readE4KRegister( Register.SYNTH1, controlI2CRepeater );
-
- if( !( ( lock & 0x1 ) == 0x1 ) )
- {
- throw new SourceException( "E4K tuner controller - couldn't "
- + "achieve PLL lock for frequency [" +
- actualFrequency + "] lock value [" + lock + "]" );
- }
-
- enableI2CRepeater( mDeviceHandle, false );
- }
- catch( UsbException e )
- {
- throw new SourceException( "E4K tuner controller - error tuning "
- + "frequency [" + frequency + "]", e );
- }
+ int lock = readE4KRegister(Register.SYNTH1, controlI2CRepeater);
+
+ if(!((lock & 0x1) == 0x1))
+ {
+ throw new SourceException("E4K tuner controller - couldn't "
+ + "achieve PLL lock for frequency [" +
+ actualFrequency + "] lock value [" + lock + "]");
+ }
+
+ enableI2CRepeater(mDeviceHandle, false);
+ }
+ catch(UsbException e)
+ {
+ throw new SourceException("E4K tuner controller - error tuning "
+ + "frequency [" + frequency + "]", e);
+ }
}
-
- private long calculateActualFrequency( PLL pll, byte z, int x )
- {
- long whole = pll.getScaledOscillator() * ( z & 0xFF );
- int fractional = (int)( pll.getScaledOscillator() *
- ( (double)x / (double)E4K_PLL_Y ) );
+ private long calculateActualFrequency(PLL pll, byte z, int x)
+ {
+ long whole = pll.getScaledOscillator() * (z & 0xFF);
- return whole + fractional;
- }
+ int fractional = (int) (pll.getScaledOscillator() *
+ ((double) x / (double) E4K_PLL_Y));
+
+ return whole + fractional;
+ }
+
+ public void initTuner(boolean controlI2CRepeater) throws UsbException
+ {
+ if(controlI2CRepeater)
+ {
+ enableI2CRepeater(mDeviceHandle, true);
+ }
+
+ boolean i2CRepeaterControl = false;
- public void initTuner( boolean controlI2CRepeater ) throws UsbException
- {
- if( controlI2CRepeater )
- {
- enableI2CRepeater( mDeviceHandle, true );
- }
-
- boolean i2CRepeaterControl = false;
-
/* Perform dummy read */
- readE4KRegister( Register.DUMMY, i2CRepeaterControl );
+ readE4KRegister(Register.DUMMY, i2CRepeaterControl);
/* Reset everything and clear POR indicator */
/* NOTE: register value remains 0010 even after we write 0111 to it */
- writeE4KRegister( Register.MASTER1, (byte)( MASTER1_RESET |
- MASTER1_NORM_STBY |
- MASTER1_POR_DET ),
- i2CRepeaterControl );
+ writeE4KRegister(Register.MASTER1, (byte) (MASTER1_RESET |
+ MASTER1_NORM_STBY |
+ MASTER1_POR_DET),
+ i2CRepeaterControl);
/* Configure clock input */
- writeE4KRegister( Register.CLK_INP, (byte)0x00, i2CRepeaterControl );
-
+ writeE4KRegister(Register.CLK_INP, (byte) 0x00, i2CRepeaterControl);
+
/* Disable clock output */
- writeE4KRegister( Register.REF_CLK, (byte)0x00, i2CRepeaterControl );
- writeE4KRegister( Register.CLKOUT_PWDN, (byte)0x96, i2CRepeaterControl );
-
+ writeE4KRegister(Register.REF_CLK, (byte) 0x00, i2CRepeaterControl);
+ writeE4KRegister(Register.CLKOUT_PWDN, (byte) 0x96, i2CRepeaterControl);
+
/* Magic Init */
- magicInit( i2CRepeaterControl );
+ magicInit(i2CRepeaterControl);
// /* Set common mode voltage a bit higher for more margin - 850 mv */
-// writeMaskedE4KRegister( Register.DC7, (byte)0x7,
+// writeMaskedE4KRegister( Register.DC7, (byte)0x7,
// (byte)0x4, i2CRepeaterControl );
//
// /* Initialize DC offset lookup tables */
// generateDCOffsetTables( i2CRepeaterControl );
-//
+//
// /* Enable time variant DC correction */
// writeE4KRegister( Register.DCTIME1, (byte)0x01, i2CRepeaterControl );
// writeE4KRegister( Register.DCTIME2, (byte)0x01, i2CRepeaterControl );
-//
+//
/* Set LNA Mode */
- writeE4KRegister( Register.AGC4, (byte)0x10, i2CRepeaterControl ); //High Threshold
- writeE4KRegister( Register.AGC5, (byte)0x04, i2CRepeaterControl ); //Low Threshold
- writeE4KRegister( Register.AGC6, (byte)0x1A, i2CRepeaterControl ); //LNA calibrate + loop rate
+ writeE4KRegister(Register.AGC4, (byte) 0x10, i2CRepeaterControl); //High Threshold
+ writeE4KRegister(Register.AGC5, (byte) 0x04, i2CRepeaterControl); //Low Threshold
+ writeE4KRegister(Register.AGC6, (byte) 0x1A, i2CRepeaterControl); //LNA calibrate + loop rate
+
+ //TODO: lna and mixer gain were already set to manual when we generated
+ //the DC offset tables. Check the LNA gain setting after we set the
+ //LNA mode above, to see if the lna or mixer gain settings have changed
+ //and if not, remove the next two steps
- //TODO: lna and mixer gain were already set to manual when we generated
- //the DC offset tables. Check the LNA gain setting after we set the
- //LNA mode above, to see if the lna or mixer gain settings have changed
- //and if not, remove the next two steps
-
// /* Set LNA gain to manual using current auto LNA gain setting */
// LNAGain lnaGain = getLNAGain( i2CRepeaterControl );
// setLNAGain( lnaGain, i2CRepeaterControl );
-//
+//
// /* Set Mixer gain to manual using current auto Mixer gain setting */
// MixerGain mixerGain = getMixerGain( i2CRepeaterControl );
// setMixerGain( mixerGain, i2CRepeaterControl );
-
- //Temp - manual set lna mode to manual
- writeMaskedE4KRegister( Register.AGC1,
- AGC1_MOD_MASK,
- AGCMode.SERIAL.getValue(),
- false );
- //Temp - set mixer gain to manual
- writeMaskedE4KRegister( Register.AGC7,
- AGC7_MIXER_GAIN_MASK,
- AGC7_MIX_GAIN_MANUAL,
- false );
-
-
+
+ //Temp - manual set lna mode to manual
+ writeMaskedE4KRegister(Register.AGC1,
+ AGC1_MOD_MASK,
+ AGCMode.SERIAL.getValue(),
+ false);
+ //Temp - set mixer gain to manual
+ writeMaskedE4KRegister(Register.AGC7,
+ AGC7_MIXER_GAIN_MASK,
+ AGC7_MIX_GAIN_MANUAL,
+ false);
+
+
// /* Enable enhance gain */
// setEnhanceGain( EnhanceGain.GAIN_5, i2CRepeaterControl );
//
// /* Enable automatic IF gain mode switching */
-// writeMaskedE4KRegister( Register.AGC8,
-// IF_GAIN_MODE_SWITCHING_MASK,
+// writeMaskedE4KRegister( Register.AGC8,
+// IF_GAIN_MODE_SWITCHING_MASK,
// AGC8_SENS_LIN_AUTO,
// i2CRepeaterControl );
-
- /* Use automatic gain as a default */
- setLNAGain( E4KLNAGain.AUTOMATIC, i2CRepeaterControl );
- setMixerGain( E4KMixerGain.AUTOMATIC, i2CRepeaterControl );
- setEnhanceGain( E4KEnhanceGain.AUTOMATIC, i2CRepeaterControl );
-
- /* Set IF gain stages */
- setIFStage1Gain( IFStage1Gain.GAIN_PLUS6, i2CRepeaterControl );
- setIFStage2Gain( IFStage2Gain.GAIN_PLUS0, i2CRepeaterControl );
- setIFStage3Gain( IFStage3Gain.GAIN_PLUS0, i2CRepeaterControl );
- setIFStage4Gain( IFStage4Gain.GAIN_PLUS0, i2CRepeaterControl );
- setIFStage5Gain( IFStage5Gain.GAIN_PLUS9, i2CRepeaterControl );
- setIFStage6Gain( IFStage6Gain.GAIN_PLUS9, i2CRepeaterControl );
-
- /* Set the most narrow filter we can possible use */
- setMixerFilter( MixerFilter.BW_1M9, i2CRepeaterControl );
- setRCFilter( RCFilter.BW_1M0, i2CRepeaterControl );
- setChannelFilter( ChannelFilter.BW_2M15, i2CRepeaterControl );
- setChannelFilterEnabled( true, i2CRepeaterControl );
+ /* Use automatic gain as a default */
+ setLNAGain(E4KLNAGain.AUTOMATIC, i2CRepeaterControl);
+ setMixerGain(E4KMixerGain.AUTOMATIC, i2CRepeaterControl);
+ setEnhanceGain(E4KEnhanceGain.AUTOMATIC, i2CRepeaterControl);
+
+ /* Set IF gain stages */
+ setIFStage1Gain(IFStage1Gain.GAIN_PLUS6, i2CRepeaterControl);
+ setIFStage2Gain(IFStage2Gain.GAIN_PLUS0, i2CRepeaterControl);
+ setIFStage3Gain(IFStage3Gain.GAIN_PLUS0, i2CRepeaterControl);
+ setIFStage4Gain(IFStage4Gain.GAIN_PLUS0, i2CRepeaterControl);
+ setIFStage5Gain(IFStage5Gain.GAIN_PLUS9, i2CRepeaterControl);
+ setIFStage6Gain(IFStage6Gain.GAIN_PLUS9, i2CRepeaterControl);
+
+ /* Set the most narrow filter we can possible use */
+ setMixerFilter(MixerFilter.BW_1M9, i2CRepeaterControl);
+ setRCFilter(RCFilter.BW_1M0, i2CRepeaterControl);
+ setChannelFilter(ChannelFilter.BW_2M15, i2CRepeaterControl);
+
+ setChannelFilterEnabled(true, i2CRepeaterControl);
// /* Disable DC detector */
// setDCRangeDetectorEnabled( false, i2CRepeaterControl );
/* Disable time variant DC correction */
- writeMaskedE4KRegister( Register.DC5, (byte)0x03, (byte)0, i2CRepeaterControl );
- writeMaskedE4KRegister( Register.DCTIME1, (byte)0x03, (byte)0, i2CRepeaterControl );
- writeMaskedE4KRegister( Register.DCTIME2, (byte)0x03, (byte)0, i2CRepeaterControl );
-
- if( controlI2CRepeater )
- {
- enableI2CRepeater( mDeviceHandle, false );
- }
- }
-
- @SuppressWarnings("unused")
- private void generateDCOffsetTables( boolean controlI2CRepeater )
- throws UsbException
- {
- boolean i2CRepeaterControl = false;
-
- if( controlI2CRepeater )
- {
- enableI2CRepeater( mDeviceHandle, true );
- }
-
+ writeMaskedE4KRegister(Register.DC5, (byte) 0x03, (byte) 0, i2CRepeaterControl);
+ writeMaskedE4KRegister(Register.DCTIME1, (byte) 0x03, (byte) 0, i2CRepeaterControl);
+ writeMaskedE4KRegister(Register.DCTIME2, (byte) 0x03, (byte) 0, i2CRepeaterControl);
+
+ if(controlI2CRepeater)
+ {
+ enableI2CRepeater(mDeviceHandle, false);
+ }
+ }
+
+ @SuppressWarnings("unused")
+ private void generateDCOffsetTables(boolean controlI2CRepeater)
+ throws UsbException
+ {
+ boolean i2CRepeaterControl = false;
+
+ if(controlI2CRepeater)
+ {
+ enableI2CRepeater(mDeviceHandle, true);
+ }
+
/* Capture current gain settings to reapply at the end */
- IFStage1Gain stage1 = getIFStage1Gain( i2CRepeaterControl );
- IFStage2Gain stage2 = getIFStage2Gain( i2CRepeaterControl );
- IFStage3Gain stage3 = getIFStage3Gain( i2CRepeaterControl );
- IFStage4Gain stage4 = getIFStage4Gain( i2CRepeaterControl );
- IFStage5Gain stage5 = getIFStage5Gain( i2CRepeaterControl );
- IFStage6Gain stage6 = getIFStage6Gain( i2CRepeaterControl );
+ IFStage1Gain stage1 = getIFStage1Gain(i2CRepeaterControl);
+ IFStage2Gain stage2 = getIFStage2Gain(i2CRepeaterControl);
+ IFStage3Gain stage3 = getIFStage3Gain(i2CRepeaterControl);
+ IFStage4Gain stage4 = getIFStage4Gain(i2CRepeaterControl);
+ IFStage5Gain stage5 = getIFStage5Gain(i2CRepeaterControl);
+ IFStage6Gain stage6 = getIFStage6Gain(i2CRepeaterControl);
/* Set Mixer gain to manual using current auto Mixer gain setting */
- E4KMixerGain mixerGain = getMixerGain( i2CRepeaterControl );
- setMixerGain( mixerGain, i2CRepeaterControl );
-
+ E4KMixerGain mixerGain = getMixerGain(i2CRepeaterControl);
+ setMixerGain(mixerGain, i2CRepeaterControl);
+
/* Set LNA gain to manual using current auto LNA gain setting */
- E4KLNAGain lnaGain = getLNAGain( i2CRepeaterControl );
- setLNAGain( lnaGain, i2CRepeaterControl );
-
+ E4KLNAGain lnaGain = getLNAGain(i2CRepeaterControl);
+ setLNAGain(lnaGain, i2CRepeaterControl);
+
/* Set IF Stage 2 - 6 gains to maximum */
- setIFStage2Gain( IFStage2Gain.GAIN_PLUS9, i2CRepeaterControl );
- setIFStage3Gain( IFStage3Gain.GAIN_PLUS9, i2CRepeaterControl );
- setIFStage4Gain( IFStage4Gain.GAIN_PLUS2B, i2CRepeaterControl );
- setIFStage5Gain( IFStage5Gain.GAIN_PLUS15D, i2CRepeaterControl );
- setIFStage6Gain( IFStage6Gain.GAIN_PLUS15D, i2CRepeaterControl );
-
- /**
- * Iterate all DC gain combinations, apply gain settings, read the
- * DC offset value and apply it to the lookup table entry
- */
- for( DCGainCombination combo: DCGainCombination.values() )
- {
+ setIFStage2Gain(IFStage2Gain.GAIN_PLUS9, i2CRepeaterControl);
+ setIFStage3Gain(IFStage3Gain.GAIN_PLUS9, i2CRepeaterControl);
+ setIFStage4Gain(IFStage4Gain.GAIN_PLUS2B, i2CRepeaterControl);
+ setIFStage5Gain(IFStage5Gain.GAIN_PLUS15D, i2CRepeaterControl);
+ setIFStage6Gain(IFStage6Gain.GAIN_PLUS15D, i2CRepeaterControl);
+
+ /**
+ * Iterate all DC gain combinations, apply gain settings, read the
+ * DC offset value and apply it to the lookup table entry
+ */
+ for(DCGainCombination combo : DCGainCombination.values())
+ {
/* Set mixer and stage1 gain values */
- setMixerGain( combo.getMixerGain(), i2CRepeaterControl );
- setIFStage1Gain( combo.getIFStage1Gain(), i2CRepeaterControl );
+ setMixerGain(combo.getMixerGain(), i2CRepeaterControl);
+ setIFStage1Gain(combo.getIFStage1Gain(), i2CRepeaterControl);
/* Turn on the DC range detector */
- setDCRangeDetectorEnabled( true, i2CRepeaterControl );
-
+ setDCRangeDetectorEnabled(true, i2CRepeaterControl);
+
/* Calibrate the DC value */
- writeE4KRegister( Register.DC1, (byte)0x01, i2CRepeaterControl );
+ writeE4KRegister(Register.DC1, (byte) 0x01, i2CRepeaterControl);
/* Get the I/Q offset and range values */
- byte offsetI = (byte)( readE4KRegister( Register.DC2,
- i2CRepeaterControl ) & 0x3F );
- byte offsetQ = (byte)( readE4KRegister( Register.DC3,
- i2CRepeaterControl ) & 0x3F );
- byte range = (byte)readE4KRegister( Register.DC4,
- i2CRepeaterControl );
- byte rangeI = (byte)( range & 0x3 );
- byte rangeQ = (byte)( ( range >> 4 ) & 0x3 );
-
+ byte offsetI = (byte) (readE4KRegister(Register.DC2,
+ i2CRepeaterControl) & 0x3F);
+ byte offsetQ = (byte) (readE4KRegister(Register.DC3,
+ i2CRepeaterControl) & 0x3F);
+ byte range = (byte) readE4KRegister(Register.DC4,
+ i2CRepeaterControl);
+ byte rangeI = (byte) (range & 0x3);
+ byte rangeQ = (byte) ((range >> 4) & 0x3);
+
/* Write the offset and range values to the lookup table */
- writeE4KRegister( combo.getIRegister(),
- (byte)( offsetI | ( rangeI << 6 ) ),
- i2CRepeaterControl );
+ writeE4KRegister(combo.getIRegister(),
+ (byte) (offsetI | (rangeI << 6)),
+ i2CRepeaterControl);
- writeE4KRegister( combo.getQRegister(),
- (byte)( offsetQ | ( rangeQ << 6 ) ),
- i2CRepeaterControl );
- }
-
- if( controlI2CRepeater )
- {
- enableI2CRepeater( mDeviceHandle, false );
- }
- }
-
- public void setDCRangeDetectorEnabled( boolean enabled,
- boolean controlI2CRepeater ) throws UsbException
- {
- if( enabled )
- {
- writeMaskedE4KRegister( Register.DC5,
- DC5_RANGE_DETECTOR_ENABLED_MASK,
- DC5_RANGE_DETECTOR_ENABLED,
- controlI2CRepeater );
- }
- else
- {
- writeMaskedE4KRegister( Register.DC5,
- DC5_RANGE_DETECTOR_DISABLED_MASK,
- DC5_RANGE_DETECTOR_DISABLED,
- controlI2CRepeater );
- }
- }
+ writeE4KRegister(combo.getQRegister(),
+ (byte) (offsetQ | (rangeQ << 6)),
+ i2CRepeaterControl);
+ }
- /**
- * Sets the LNA gain within the E4K Tuner
- *
- * Note: requires I2C repeater enabled
- *
- * @param gain
- * @throws UsbException
- */
- public void setLNAGain( E4KLNAGain gain, boolean controlI2CRepeater )
- throws UsbException
- {
- if( controlI2CRepeater )
- {
- enableI2CRepeater( mDeviceHandle, true );
- }
-
- if( gain == E4KLNAGain.AUTOMATIC )
- {
- writeMaskedE4KRegister( Register.AGC1,
- AGC1_MOD_MASK,
- AGCMode.IF_SERIAL_LNA_AUTON.getValue(),
- false );
- }
- else
- {
- writeMaskedE4KRegister( Register.AGC1,
- AGC1_MOD_MASK,
- AGCMode.SERIAL.getValue(),
- false );
-
+ if(controlI2CRepeater)
+ {
+ enableI2CRepeater(mDeviceHandle, false);
+ }
+ }
+
+ public void setDCRangeDetectorEnabled(boolean enabled,
+ boolean controlI2CRepeater) throws UsbException
+ {
+ if(enabled)
+ {
+ writeMaskedE4KRegister(Register.DC5,
+ DC5_RANGE_DETECTOR_ENABLED_MASK,
+ DC5_RANGE_DETECTOR_ENABLED,
+ controlI2CRepeater);
+ }
+ else
+ {
+ writeMaskedE4KRegister(Register.DC5,
+ DC5_RANGE_DETECTOR_DISABLED_MASK,
+ DC5_RANGE_DETECTOR_DISABLED,
+ controlI2CRepeater);
+ }
+ }
+
+ /**
+ * Sets the LNA gain within the E4K Tuner
+ *
+ * Note: requires I2C repeater enabled
+ *
+ * @param gain
+ * @throws UsbException
+ */
+ public void setLNAGain(E4KLNAGain gain, boolean controlI2CRepeater)
+ throws UsbException
+ {
+ if(controlI2CRepeater)
+ {
+ enableI2CRepeater(mDeviceHandle, true);
+ }
+
+ if(gain == E4KLNAGain.AUTOMATIC)
+ {
+ writeMaskedE4KRegister(Register.AGC1,
+ AGC1_MOD_MASK,
+ AGCMode.IF_SERIAL_LNA_AUTON.getValue(),
+ false);
+ }
+ else
+ {
+ writeMaskedE4KRegister(Register.AGC1,
+ AGC1_MOD_MASK,
+ AGCMode.SERIAL.getValue(),
+ false);
+
+
+ writeMaskedE4KRegister(E4KLNAGain.getRegister(),
+ E4KLNAGain.getMask(),
+ gain.getValue(),
+ false);
+ }
+
+ if(controlI2CRepeater)
+ {
+ enableI2CRepeater(mDeviceHandle, false);
+ }
+ }
- writeMaskedE4KRegister( E4KLNAGain.getRegister(),
- E4KLNAGain.getMask(),
- gain.getValue(),
- false );
- }
-
- if( controlI2CRepeater )
- {
- enableI2CRepeater( mDeviceHandle, false );
- }
- }
-
/**
* Reads LNA gain from E4K tuner
- *
+ *
* Note: requires I2C repeater enabled
*/
- public E4KLNAGain getLNAGain( boolean controlI2CRepeater ) throws UsbException
- {
- return E4KLNAGain.fromRegisterValue(
- readE4KRegister( E4KLNAGain.getRegister(), controlI2CRepeater ) );
- }
+ public E4KLNAGain getLNAGain(boolean controlI2CRepeater) throws UsbException
+ {
+ return E4KLNAGain.fromRegisterValue(
+ readE4KRegister(E4KLNAGain.getRegister(), controlI2CRepeater));
+ }
- /**
- * Sets enhanced gain for E4K repeater.
- *
- * Note: requires I2C repeater enabled
- *
- * @param gain
- * @throws UsbException
- */
- public void setEnhanceGain( E4KEnhanceGain gain, boolean controlI2CRepeater )
- throws UsbException
- {
- writeMaskedE4KRegister( E4KEnhanceGain.getRegister(),
- E4KEnhanceGain.getMask(),
- gain.getValue(),
- controlI2CRepeater );
- }
+ /**
+ * Sets enhanced gain for E4K repeater.
+ *
+ * Note: requires I2C repeater enabled
+ *
+ * @param gain
+ * @throws UsbException
+ */
+ public void setEnhanceGain(E4KEnhanceGain gain, boolean controlI2CRepeater)
+ throws UsbException
+ {
+ writeMaskedE4KRegister(E4KEnhanceGain.getRegister(),
+ E4KEnhanceGain.getMask(),
+ gain.getValue(),
+ controlI2CRepeater);
+ }
- /**
- * Gets the enhanced gain setting in the E4K tuner.
- *
- * Note: requires I2C repeater
- * @return
- * @throws UsbException
- */
- public E4KEnhanceGain getEnhanceGain( boolean controlI2CRepeater )
- throws UsbException
- {
- return E4KEnhanceGain.fromRegisterValue(
- readE4KRegister( E4KEnhanceGain.getRegister(), controlI2CRepeater ) );
- }
-
- public void setMixerGain( E4KMixerGain gain, boolean controlI2CRepeater )
- throws UsbException
- {
- if( controlI2CRepeater )
- {
- enableI2CRepeater( mDeviceHandle, true );
- }
-
- boolean localI2CRepeaterControl = false;
-
- if( gain == E4KMixerGain.AUTOMATIC )
- {
- writeMaskedE4KRegister( Register.AGC7,
- AGC7_MIXER_GAIN_MASK,
- AGC7_MIX_GAIN_AUTO,
- localI2CRepeaterControl );
- }
- else
- {
- writeMaskedE4KRegister( Register.AGC7,
- AGC7_MIXER_GAIN_MASK,
- AGC7_MIX_GAIN_MANUAL,
- localI2CRepeaterControl );
+ /**
+ * Gets the enhanced gain setting in the E4K tuner.
+ *
+ * Note: requires I2C repeater
+ *
+ * @return
+ * @throws UsbException
+ */
+ public E4KEnhanceGain getEnhanceGain(boolean controlI2CRepeater)
+ throws UsbException
+ {
+ return E4KEnhanceGain.fromRegisterValue(
+ readE4KRegister(E4KEnhanceGain.getRegister(), controlI2CRepeater));
+ }
+
+ public void setMixerGain(E4KMixerGain gain, boolean controlI2CRepeater)
+ throws UsbException
+ {
+ if(controlI2CRepeater)
+ {
+ enableI2CRepeater(mDeviceHandle, true);
+ }
+
+ boolean localI2CRepeaterControl = false;
+
+ if(gain == E4KMixerGain.AUTOMATIC)
+ {
+ writeMaskedE4KRegister(Register.AGC7,
+ AGC7_MIXER_GAIN_MASK,
+ AGC7_MIX_GAIN_AUTO,
+ localI2CRepeaterControl);
+ }
+ else
+ {
+ writeMaskedE4KRegister(Register.AGC7,
+ AGC7_MIXER_GAIN_MASK,
+ AGC7_MIX_GAIN_MANUAL,
+ localI2CRepeaterControl);
/* Set the desired manual gain setting */
- writeMaskedE4KRegister( E4KMixerGain.getRegister(),
- E4KMixerGain.getMask(),
- gain.getValue(),
- localI2CRepeaterControl );
- }
-
- if( controlI2CRepeater )
- {
- enableI2CRepeater( mDeviceHandle, false );
- }
- }
-
- public E4KMixerGain getMixerGain( boolean controlI2CRepeater )
- throws UsbException
- {
- byte autoOrManual = readMaskedE4KRegister( Register.AGC7,
- AGC7_MIXER_GAIN_MASK,
- controlI2CRepeater );
+ writeMaskedE4KRegister(E4KMixerGain.getRegister(),
+ E4KMixerGain.getMask(),
+ gain.getValue(),
+ localI2CRepeaterControl);
+ }
- if( autoOrManual == AGC7_MIX_GAIN_AUTO )
- {
- return E4KMixerGain.AUTOMATIC;
- }
- else
- {
- int register = readE4KRegister( E4KMixerGain.getRegister(),
- controlI2CRepeater );
-
- return E4KMixerGain.fromRegisterValue( register );
- }
- }
-
- public void setIFStage1Gain( IFStage1Gain gain,
- boolean controlI2CRepeater ) throws UsbException
- {
- writeMaskedE4KRegister( IFStage1Gain.getRegister(),
- IFStage1Gain.getMask(),
- gain.getValue(),
- controlI2CRepeater );
- }
-
- public IFStage1Gain getIFStage1Gain( boolean controlI2CRepeater )
- throws UsbException
- {
- return IFStage1Gain.fromRegisterValue(
- readE4KRegister( IFStage1Gain.getRegister(), controlI2CRepeater ) );
- }
-
- public void setIFStage2Gain( IFStage2Gain gain,
- boolean controlI2CRepeater ) throws UsbException
- {
- writeMaskedE4KRegister( IFStage2Gain.getRegister(),
- IFStage2Gain.getMask(),
- gain.getValue(),
- controlI2CRepeater );
- }
-
- public IFStage2Gain getIFStage2Gain( boolean controlI2CRepeater )
- throws UsbException
- {
- return IFStage2Gain.fromRegisterValue(
- readE4KRegister( IFStage2Gain.getRegister(), controlI2CRepeater ) );
- }
-
- public void setIFStage3Gain( IFStage3Gain gain,
- boolean controlI2CRepeater ) throws UsbException
- {
- writeMaskedE4KRegister( IFStage3Gain.getRegister(),
- IFStage3Gain.getMask(),
- gain.getValue(),
- controlI2CRepeater );
- }
-
- public IFStage3Gain getIFStage3Gain( boolean controlI2CRepeater )
- throws UsbException
- {
- return IFStage3Gain.fromRegisterValue(
- readE4KRegister( IFStage3Gain.getRegister(), controlI2CRepeater ) );
- }
-
- public void setIFStage4Gain( IFStage4Gain gain,
- boolean controlI2CRepeater ) throws UsbException
- {
- writeMaskedE4KRegister( IFStage4Gain.getRegister(),
- IFStage4Gain.getMask(),
- gain.getValue(),
- controlI2CRepeater );
- }
-
- public IFStage4Gain getIFStage4Gain( boolean controlI2CRepeater )
- throws UsbException
- {
- return IFStage4Gain.fromRegisterValue(
- readE4KRegister( IFStage4Gain.getRegister(), controlI2CRepeater ) );
- }
-
- public void setIFStage5Gain( IFStage5Gain gain,
- boolean controlI2CRepeater ) throws UsbException
- {
- writeMaskedE4KRegister( IFStage5Gain.getRegister(),
- IFStage5Gain.getMask(),
- gain.getValue(),
- controlI2CRepeater );
- }
-
- public IFStage5Gain getIFStage5Gain( boolean controlI2CRepeater )
- throws UsbException
- {
- return IFStage5Gain.fromRegisterValue(
- readE4KRegister( IFStage5Gain.getRegister(), controlI2CRepeater ) );
- }
-
- public void setIFStage6Gain( IFStage6Gain gain,
- boolean controlI2CRepeater ) throws UsbException
- {
- writeMaskedE4KRegister( IFStage6Gain.getRegister(),
- IFStage6Gain.getMask(),
- gain.getValue(),
- controlI2CRepeater );
- }
-
- public IFStage6Gain getIFStage6Gain( boolean controlI2CRepeater )
- throws UsbException
- {
- return IFStage6Gain.fromRegisterValue(
- readE4KRegister( IFStage6Gain.getRegister(), controlI2CRepeater ) );
- }
-
- public void setMixerFilter( MixerFilter filter,
- boolean controlI2CRepeater ) throws LibUsbException
- {
- writeMaskedE4KRegister( MixerFilter.getRegister(),
- MixerFilter.getMask(),
- filter.getValue(),
- controlI2CRepeater );
- }
-
- public MixerFilter getMixerFilter( boolean controlI2CRepeater )
- throws UsbException
- {
- int value = readE4KRegister( MixerFilter.getRegister(),
- controlI2CRepeater );
-
- return MixerFilter.fromRegisterValue( value );
- }
-
- public void setRCFilter( RCFilter filter,
- boolean controlI2CRepeater ) throws LibUsbException
- {
- writeMaskedE4KRegister( RCFilter.getRegister(),
- RCFilter.getMask(),
- filter.getValue(),
- controlI2CRepeater );
- }
-
- public RCFilter getRCFilter( boolean controlI2CRepeater ) throws UsbException
- {
- int value = readE4KRegister( RCFilter.getRegister(), controlI2CRepeater );
-
- return RCFilter.fromRegisterValue( value );
- }
-
- public void setChannelFilter( ChannelFilter filter,
- boolean controlI2CRepeater ) throws LibUsbException
- {
- writeMaskedE4KRegister( ChannelFilter.getRegister(),
- ChannelFilter.getMask(),
- filter.getValue(),
- controlI2CRepeater );
- }
-
- public ChannelFilter getChannelFilter( boolean controlI2CRepeater )
- throws UsbException
- {
- int value = readE4KRegister( ChannelFilter.getRegister(), controlI2CRepeater );
-
- return ChannelFilter.fromRegisterValue( value );
-
- }
-
- public void setChannelFilterEnabled( boolean enabled,
- boolean controlI2CRepeater ) throws UsbException
- {
- if( enabled )
- {
- writeMaskedE4KRegister( Register.FILT3,
- FILT3_MASK,
- FILT3_ENABLE,
- controlI2CRepeater );
- }
- else
- {
- writeMaskedE4KRegister( Register.FILT3,
- FILT3_MASK,
- FILT3_DISABLE,
- controlI2CRepeater );
- }
+ if(controlI2CRepeater)
+ {
+ enableI2CRepeater(mDeviceHandle, false);
+ }
}
-
- public void setBand( long frequency,
- boolean controlI2CRepeater ) throws UsbException
- {
- if( controlI2CRepeater )
- {
- enableI2CRepeater( mDeviceHandle, true );
- }
- Band band = Band.fromFrequency( frequency );
+ public E4KMixerGain getMixerGain(boolean controlI2CRepeater)
+ throws UsbException
+ {
+ byte autoOrManual = readMaskedE4KRegister(Register.AGC7,
+ AGC7_MIXER_GAIN_MASK,
+ controlI2CRepeater);
+
+ if(autoOrManual == AGC7_MIX_GAIN_AUTO)
+ {
+ return E4KMixerGain.AUTOMATIC;
+ }
+ else
+ {
+ int register = readE4KRegister(E4KMixerGain.getRegister(),
+ controlI2CRepeater);
+
+ return E4KMixerGain.fromRegisterValue(register);
+ }
+ }
+
+ public void setIFStage1Gain(IFStage1Gain gain,
+ boolean controlI2CRepeater) throws UsbException
+ {
+ writeMaskedE4KRegister(IFStage1Gain.getRegister(),
+ IFStage1Gain.getMask(),
+ gain.getValue(),
+ controlI2CRepeater);
+ }
+
+ public IFStage1Gain getIFStage1Gain(boolean controlI2CRepeater)
+ throws UsbException
+ {
+ return IFStage1Gain.fromRegisterValue(
+ readE4KRegister(IFStage1Gain.getRegister(), controlI2CRepeater));
+ }
+
+ public void setIFStage2Gain(IFStage2Gain gain,
+ boolean controlI2CRepeater) throws UsbException
+ {
+ writeMaskedE4KRegister(IFStage2Gain.getRegister(),
+ IFStage2Gain.getMask(),
+ gain.getValue(),
+ controlI2CRepeater);
+ }
+
+ public IFStage2Gain getIFStage2Gain(boolean controlI2CRepeater)
+ throws UsbException
+ {
+ return IFStage2Gain.fromRegisterValue(
+ readE4KRegister(IFStage2Gain.getRegister(), controlI2CRepeater));
+ }
+
+ public void setIFStage3Gain(IFStage3Gain gain,
+ boolean controlI2CRepeater) throws UsbException
+ {
+ writeMaskedE4KRegister(IFStage3Gain.getRegister(),
+ IFStage3Gain.getMask(),
+ gain.getValue(),
+ controlI2CRepeater);
+ }
+
+ public IFStage3Gain getIFStage3Gain(boolean controlI2CRepeater)
+ throws UsbException
+ {
+ return IFStage3Gain.fromRegisterValue(
+ readE4KRegister(IFStage3Gain.getRegister(), controlI2CRepeater));
+ }
+
+ public void setIFStage4Gain(IFStage4Gain gain,
+ boolean controlI2CRepeater) throws UsbException
+ {
+ writeMaskedE4KRegister(IFStage4Gain.getRegister(),
+ IFStage4Gain.getMask(),
+ gain.getValue(),
+ controlI2CRepeater);
+ }
+
+ public IFStage4Gain getIFStage4Gain(boolean controlI2CRepeater)
+ throws UsbException
+ {
+ return IFStage4Gain.fromRegisterValue(
+ readE4KRegister(IFStage4Gain.getRegister(), controlI2CRepeater));
+ }
+
+ public void setIFStage5Gain(IFStage5Gain gain,
+ boolean controlI2CRepeater) throws UsbException
+ {
+ writeMaskedE4KRegister(IFStage5Gain.getRegister(),
+ IFStage5Gain.getMask(),
+ gain.getValue(),
+ controlI2CRepeater);
+ }
+
+ public IFStage5Gain getIFStage5Gain(boolean controlI2CRepeater)
+ throws UsbException
+ {
+ return IFStage5Gain.fromRegisterValue(
+ readE4KRegister(IFStage5Gain.getRegister(), controlI2CRepeater));
+ }
+
+ public void setIFStage6Gain(IFStage6Gain gain,
+ boolean controlI2CRepeater) throws UsbException
+ {
+ writeMaskedE4KRegister(IFStage6Gain.getRegister(),
+ IFStage6Gain.getMask(),
+ gain.getValue(),
+ controlI2CRepeater);
+ }
+
+ public IFStage6Gain getIFStage6Gain(boolean controlI2CRepeater)
+ throws UsbException
+ {
+ return IFStage6Gain.fromRegisterValue(
+ readE4KRegister(IFStage6Gain.getRegister(), controlI2CRepeater));
+ }
+
+ public void setMixerFilter(MixerFilter filter,
+ boolean controlI2CRepeater) throws LibUsbException
+ {
+ writeMaskedE4KRegister(MixerFilter.getRegister(),
+ MixerFilter.getMask(),
+ filter.getValue(),
+ controlI2CRepeater);
+ }
+
+ public MixerFilter getMixerFilter(boolean controlI2CRepeater)
+ throws UsbException
+ {
+ int value = readE4KRegister(MixerFilter.getRegister(),
+ controlI2CRepeater);
+
+ return MixerFilter.fromRegisterValue(value);
+ }
+
+ public void setRCFilter(RCFilter filter,
+ boolean controlI2CRepeater) throws LibUsbException
+ {
+ writeMaskedE4KRegister(RCFilter.getRegister(),
+ RCFilter.getMask(),
+ filter.getValue(),
+ controlI2CRepeater);
+ }
+
+ public RCFilter getRCFilter(boolean controlI2CRepeater) throws UsbException
+ {
+ int value = readE4KRegister(RCFilter.getRegister(), controlI2CRepeater);
+
+ return RCFilter.fromRegisterValue(value);
+ }
+
+ public void setChannelFilter(ChannelFilter filter,
+ boolean controlI2CRepeater) throws LibUsbException
+ {
+ writeMaskedE4KRegister(ChannelFilter.getRegister(),
+ ChannelFilter.getMask(),
+ filter.getValue(),
+ controlI2CRepeater);
+ }
+
+ public ChannelFilter getChannelFilter(boolean controlI2CRepeater)
+ throws UsbException
+ {
+ int value = readE4KRegister(ChannelFilter.getRegister(), controlI2CRepeater);
+
+ return ChannelFilter.fromRegisterValue(value);
+
+ }
+
+ public void setChannelFilterEnabled(boolean enabled,
+ boolean controlI2CRepeater) throws UsbException
+ {
+ if(enabled)
+ {
+ writeMaskedE4KRegister(Register.FILT3,
+ FILT3_MASK,
+ FILT3_ENABLE,
+ controlI2CRepeater);
+ }
+ else
+ {
+ writeMaskedE4KRegister(Register.FILT3,
+ FILT3_MASK,
+ FILT3_DISABLE,
+ controlI2CRepeater);
+ }
+ }
+
+ public void setBand(long frequency,
+ boolean controlI2CRepeater) throws UsbException
+ {
+ if(controlI2CRepeater)
+ {
+ enableI2CRepeater(mDeviceHandle, true);
+ }
+
+ Band band = Band.fromFrequency(frequency);
/* Set the bias */
- switch( band )
- {
- case UHF:
- case VHF2:
- case VHF3:
- writeE4KRegister( Register.BIAS, (byte)0x3, false );
- break;
- case L:
- default:
- writeE4KRegister( Register.BIAS, (byte)0x0, false );
- break;
-
- }
-
- /**
- * Workaround - reset register (set value to 0) before writing to it, to
- * avoid a gap around 325-350 MHz
- */
- writeMaskedE4KRegister( Register.SYNTH1, Band.getMask(), (byte)0x0, false );
- writeMaskedE4KRegister( Register.SYNTH1, Band.getMask(), band.getValue(), false );
+ switch(band)
+ {
+ case UHF:
+ case VHF2:
+ case VHF3:
+ writeE4KRegister(Register.BIAS, (byte) 0x3, false);
+ break;
+ case L:
+ default:
+ writeE4KRegister(Register.BIAS, (byte) 0x0, false);
+ break;
- if( controlI2CRepeater )
- {
- enableI2CRepeater( mDeviceHandle, false );
- }
+ }
+
+ /**
+ * Workaround - reset register (set value to 0) before writing to it, to
+ * avoid a gap around 325-350 MHz
+ */
+ writeMaskedE4KRegister(Register.SYNTH1, Band.getMask(), (byte) 0x0, false);
+ writeMaskedE4KRegister(Register.SYNTH1, Band.getMask(), band.getValue(), false);
+
+ if(controlI2CRepeater)
+ {
+ enableI2CRepeater(mDeviceHandle, false);
+ }
}
-
- private void setRFFilter( long frequency,
- boolean controlI2CRepeater ) throws UsbException
+
+ private void setRFFilter(long frequency,
+ boolean controlI2CRepeater) throws UsbException
{
- RFFilter filter = RFFilter.fromFrequency( frequency );
+ RFFilter filter = RFFilter.fromFrequency(frequency);
- writeMaskedE4KRegister( Register.FILT1,
- RFFilter.getMask(),
- filter.getValue(),
- controlI2CRepeater );
+ writeMaskedE4KRegister(Register.FILT1,
+ RFFilter.getMask(),
+ filter.getValue(),
+ controlI2CRepeater);
}
-
+
/**
* Sets the gain combination setting.
- *
+ *
* Note: does not respond to the MANUAL setting. Use the manual setting
- * to configure gui components to expose the individual Mixer, LNA and
+ * to configure gui components to expose the individual Mixer, LNA and
* Enhance gain settings, to allow the user to change those settings
* individually.
- *
+ *
* @param gain - requested gain setting
* @throws UsbException if there are any errors
*/
- public void setGain( E4KGain gain, boolean controlI2CRepeater ) throws UsbException
+ public void setGain(E4KGain gain, boolean controlI2CRepeater) throws UsbException
{
- if( gain != E4KGain.MANUAL )
- {
- if( controlI2CRepeater )
- {
- enableI2CRepeater( mDeviceHandle, true );
- }
+ if(gain != E4KGain.MANUAL)
+ {
+ if(controlI2CRepeater)
+ {
+ enableI2CRepeater(mDeviceHandle, true);
+ }
- boolean i2CRepeaterControl = false;
-
- setLNAGain( gain.getLNAGain(), i2CRepeaterControl );
- setMixerGain( gain.getMixerGain(), i2CRepeaterControl );
- setEnhanceGain( gain.getEnhanceGain(), i2CRepeaterControl );
+ boolean i2CRepeaterControl = false;
- if( controlI2CRepeater )
- {
- enableI2CRepeater( mDeviceHandle, false );
- }
- }
+ setLNAGain(gain.getLNAGain(), i2CRepeaterControl);
+ setMixerGain(gain.getMixerGain(), i2CRepeaterControl);
+ setEnhanceGain(gain.getEnhanceGain(), i2CRepeaterControl);
+
+ if(controlI2CRepeater)
+ {
+ enableI2CRepeater(mDeviceHandle, false);
+ }
+ }
}
-
- /*
+
+ /*
* Performs magic initialization ... and that's all we need to know, I guess
*/
- private void magicInit( boolean controlI2CRepeater ) throws UsbException
- {
- if( controlI2CRepeater )
- {
- enableI2CRepeater( mDeviceHandle, true );
- }
+ private void magicInit(boolean controlI2CRepeater) throws UsbException
+ {
+ if(controlI2CRepeater)
+ {
+ enableI2CRepeater(mDeviceHandle, true);
+ }
- writeE4KRegister( Register.MAGIC_1, (byte)0x01, false );
- writeE4KRegister( Register.MAGIC_2, (byte)0xFE, false );
- writeE4KRegister( Register.MAGIC_3, (byte)0x00, false );
- writeE4KRegister( Register.MAGIC_4, (byte)0x50, false ); //Polarity A
- writeE4KRegister( Register.MAGIC_5, (byte)0x20, false );
- writeE4KRegister( Register.MAGIC_6, (byte)0x01, false );
- writeE4KRegister( Register.MAGIC_7, (byte)0x7F, false );
- writeE4KRegister( Register.MAGIC_8, (byte)0x07, false );
+ writeE4KRegister(Register.MAGIC_1, (byte) 0x01, false);
+ writeE4KRegister(Register.MAGIC_2, (byte) 0xFE, false);
+ writeE4KRegister(Register.MAGIC_3, (byte) 0x00, false);
+ writeE4KRegister(Register.MAGIC_4, (byte) 0x50, false); //Polarity A
+ writeE4KRegister(Register.MAGIC_5, (byte) 0x20, false);
+ writeE4KRegister(Register.MAGIC_6, (byte) 0x01, false);
+ writeE4KRegister(Register.MAGIC_7, (byte) 0x7F, false);
+ writeE4KRegister(Register.MAGIC_8, (byte) 0x07, false);
- if( controlI2CRepeater )
- {
- enableI2CRepeater( mDeviceHandle, false );
- }
- }
-
- private byte readMaskedE4KRegister( Register register,
- byte mask,
- boolean controlI2CRepeater )
- throws UsbException
- {
- int temp = readE4KRegister( register, controlI2CRepeater );
- return (byte)( temp & mask );
- }
-
- private void writeMaskedE4KRegister( Register register,
- byte mask,
- byte value,
- boolean controlI2CRepeater ) throws LibUsbException
- {
- int temp = readE4KRegister( register, controlI2CRepeater );
+ if(controlI2CRepeater)
+ {
+ enableI2CRepeater(mDeviceHandle, false);
+ }
+ }
+
+ private byte readMaskedE4KRegister(Register register,
+ byte mask,
+ boolean controlI2CRepeater)
+ throws UsbException
+ {
+ int temp = readE4KRegister(register, controlI2CRepeater);
+ return (byte) (temp & mask);
+ }
+
+ private void writeMaskedE4KRegister(Register register,
+ byte mask,
+ byte value,
+ boolean controlI2CRepeater) throws LibUsbException
+ {
+ int temp = readE4KRegister(register, controlI2CRepeater);
/* If the register is not set to the masked value, then change it */
- if( (byte)( temp & mask ) != value )
- {
- writeE4KRegister( register,
- (byte)( ( temp & ~mask ) | ( value & mask ) ),
- controlI2CRepeater );
-
- readE4KRegister( register, controlI2CRepeater );
- }
- }
-
- private int readE4KRegister( Register register,
- boolean controlI2CRepeater ) throws LibUsbException
- {
- return readI2CRegister( mDeviceHandle, Register.I2C_REGISTER.getValue(),
- register.getValue(), controlI2CRepeater );
- }
+ if((byte) (temp & mask) != value)
+ {
+ writeE4KRegister(register,
+ (byte) ((temp & ~mask) | (value & mask)),
+ controlI2CRepeater);
+
+ readE4KRegister(register, controlI2CRepeater);
+ }
+ }
+
+ private int readE4KRegister(Register register,
+ boolean controlI2CRepeater) throws LibUsbException
+ {
+ return readI2CRegister(mDeviceHandle, Register.I2C_REGISTER.getValue(),
+ register.getValue(), controlI2CRepeater);
+ }
- private void writeE4KRegister( Register register,
- byte value,
- boolean controlI2CRepeater ) throws LibUsbException
- {
- writeI2CRegister( mDeviceHandle, Register.I2C_REGISTER.getValue(),
- register.getValue(), value, controlI2CRepeater );
- }
+ private void writeE4KRegister(Register register,
+ byte value,
+ boolean controlI2CRepeater) throws LibUsbException
+ {
+ writeI2CRegister(mDeviceHandle, Register.I2C_REGISTER.getValue(),
+ register.getValue(), value, controlI2CRepeater);
+ }
- public enum Band
- {
- VHF2( 0 ),
- VHF3( 2 ),
- UHF( 4 ),
- L( 6 );
-
- private int mValue;
-
- private Band( int value )
- {
- mValue = value;
- }
-
- public static byte getMask()
- {
- return (byte)0x06;
- }
-
- public byte getValue()
- {
- return (byte)mValue;
- }
-
- public String getLabel()
- {
- return toString();
- }
-
- public static Band fromFrequency( long frequency )
- {
- if( frequency < 140000000 ) //140 MHz
- {
- return VHF2;
- }
- else if( frequency < 350000000 ) //350 MHz
- {
- return VHF3;
- }
- else if( frequency < 1135000000 ) //1135 MHz
- {
- return UHF;
- }
- else
- {
- return L;
- }
- }
- }
+ public enum Band
+ {
+ VHF2(0),
+ VHF3(2),
+ UHF(4),
+ L(6);
- public enum PLL
- {
- PLL_72M4( 0x0F, 72400000, 48, 600000, true, "72.4 MHz" ),
- PLL_81M2( 0x0E, 81200000, 40, 720000, true, "81.2 MHz" ),
- PLL_108M3( 0x0D, 108300000, 32, 900000, true, "108.3 MHz" ),
- PLL_162M5( 0x0C, 162500000, 24, 1200000, true, "162.5 MHz" ),
- PLL_216M6( 0x0B, 216600000, 16, 1800000, true, "216.6 MHz" ),
- PLL_325M0( 0x0A, 325000000, 12, 2400000, true, "325.0 MHz" ),
- PLL_350M0( 0x09, 350000000, 8, 3600000, true, "350.0 MHz" ),
- PLL_432M0( 0x03, 432000000, 8, 3600000, false, "432.0 MHz" ),
- PLL_667M0( 0x02, 667000000, 6, 4800000, false, "667.0 MHz" ),
- PLL_1200M0( 0x01, 1200000000, 4, 7200000, false, "1200.0 MHz" );
-
- private int mValue;
- private long mFrequency;
- private int mMultiplier;
- private int mScaledOscillator;
- private boolean mRequires3PhaseMixing;
- private String mLabel;
-
- private PLL( int value,
- long frequency,
- int multiplier,
- int scaledOscillator,
- boolean requires3Phase,
- String label )
- {
- mValue = value;
- mFrequency = frequency;
- mMultiplier = multiplier;
- mScaledOscillator = scaledOscillator;
- mRequires3PhaseMixing = requires3Phase;
- mLabel = label;
-
- }
+ private int mValue;
- public byte getIndex()
- {
- return (byte)mValue;
- }
-
- public long getFrequency()
- {
- return mFrequency;
- }
-
- public byte getMultiplier()
- {
- return (byte)mMultiplier;
- }
-
- public int getScaledOscillator()
- {
- return mScaledOscillator;
- }
-
- public boolean requires3PhaseMixing()
- {
- return mRequires3PhaseMixing;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
-
- public String toString()
- {
- return mLabel;
- }
-
- /* Returns the PLL setting with the closest frequency that is greater
+ private Band(int value)
+ {
+ mValue = value;
+ }
+
+ public static byte getMask()
+ {
+ return (byte) 0x06;
+ }
+
+ public byte getValue()
+ {
+ return (byte) mValue;
+ }
+
+ public String getLabel()
+ {
+ return toString();
+ }
+
+ public static Band fromFrequency(long frequency)
+ {
+ if(frequency < 140000000) //140 MHz
+ {
+ return VHF2;
+ }
+ else if(frequency < 350000000) //350 MHz
+ {
+ return VHF3;
+ }
+ else if(frequency < 1135000000) //1135 MHz
+ {
+ return UHF;
+ }
+ else
+ {
+ return L;
+ }
+ }
+ }
+
+ public enum PLL
+ {
+ PLL_72M4(0x0F, 72400000, 48, 600000, true, "72.4 MHz"),
+ PLL_81M2(0x0E, 81200000, 40, 720000, true, "81.2 MHz"),
+ PLL_108M3(0x0D, 108300000, 32, 900000, true, "108.3 MHz"),
+ PLL_162M5(0x0C, 162500000, 24, 1200000, true, "162.5 MHz"),
+ PLL_216M6(0x0B, 216600000, 16, 1800000, true, "216.6 MHz"),
+ PLL_325M0(0x0A, 325000000, 12, 2400000, true, "325.0 MHz"),
+ PLL_350M0(0x09, 350000000, 8, 3600000, true, "350.0 MHz"),
+ PLL_432M0(0x03, 432000000, 8, 3600000, false, "432.0 MHz"),
+ PLL_667M0(0x02, 667000000, 6, 4800000, false, "667.0 MHz"),
+ PLL_1200M0(0x01, 1200000000, 4, 7200000, false, "1200.0 MHz");
+
+ private int mValue;
+ private long mFrequency;
+ private int mMultiplier;
+ private int mScaledOscillator;
+ private boolean mRequires3PhaseMixing;
+ private String mLabel;
+
+ private PLL(int value,
+ long frequency,
+ int multiplier,
+ int scaledOscillator,
+ boolean requires3Phase,
+ String label)
+ {
+ mValue = value;
+ mFrequency = frequency;
+ mMultiplier = multiplier;
+ mScaledOscillator = scaledOscillator;
+ mRequires3PhaseMixing = requires3Phase;
+ mLabel = label;
+
+ }
+
+ public byte getIndex()
+ {
+ return (byte) mValue;
+ }
+
+ public long getFrequency()
+ {
+ return mFrequency;
+ }
+
+ public byte getMultiplier()
+ {
+ return (byte) mMultiplier;
+ }
+
+ public int getScaledOscillator()
+ {
+ return mScaledOscillator;
+ }
+
+ public boolean requires3PhaseMixing()
+ {
+ return mRequires3PhaseMixing;
+ }
+
+ public String getLabel()
+ {
+ return mLabel;
+ }
+
+ public String toString()
+ {
+ return mLabel;
+ }
+
+ /* Returns the PLL setting with the closest frequency that is greater
* than the frequency argument */
- public static PLL fromFrequency( long frequency )
- {
- for( PLL pll: values() )
- {
- if( frequency < pll.getFrequency() )
- {
- return pll;
- }
- }
-
- //Default
- return PLL.PLL_72M4;
- }
-
- public static PLL fromSetting( int setting )
- {
- int value = setting & 0xF;
-
- for( PLL pll: values() )
- {
- if( value == pll.getIndex() )
- {
- return pll;
- }
- }
+ public static PLL fromFrequency(long frequency)
+ {
+ for(PLL pll : values())
+ {
+ if(frequency < pll.getFrequency())
+ {
+ return pll;
+ }
+ }
- //Default
- return PLL.PLL_72M4;
- }
- }
+ //Default
+ return PLL.PLL_72M4;
+ }
- /**
- * RF filters - UHF Band. Each enum entry defines the center frequency for
- * the filter and the applicable frequency minimums and maximums for the
- * filter.
- *
- * Note: max frequency overlaps with the next minimum frequency, so valid
- * frequencies should be less than the maximum frequency defined for the
- * filter.
- */
- public enum RFFilter
- {
- NO_FILTER( 0, 0, 0 ),
-
- //UHF band Filters
- M360( 0, 350000000, 370000000 ),
- M380( 1, 370000000, 392500000 ),
- M405( 2, 392500000, 417500000 ),
- M425( 3, 417500000, 437500000 ),
- M450( 4, 437500000, 462500000 ),
- M475( 5, 462500000, 490000000 ),
- M505( 6, 490000000, 522500000 ),
- M540( 7, 522500000, 557500000 ),
- M575( 8, 557500000, 595000000 ),
- M615( 9, 595000000, 642500000 ),
- M670( 10, 642500000, 695000000 ),
- M720( 11, 695000000, 740000000 ),
- M760( 12, 740000000, 800000000 ),
- M840( 13, 800000000, 865000000 ),
- M890( 14, 865000000, 930000000 ),
- M970( 15, 930000000, 1135000000 ),
-
- //L band filters
- M1300( 0, 1135000000, 1310000000 ),
- M1320( 1, 1310000000, 1340000000 ),
- M1360( 2, 1340000000, 1385000000 ),
- M1410( 3, 1385000000, 1427500000 ),
- M1445( 4, 1427500000, 1452500000 ),
- M1460( 5, 1452500000, 1475000000 ),
- M1490( 6, 1475000000, 1510000000 ),
- M1530( 7, 1510000000, 1545000000 ),
- M1560( 8, 1545000000, 1575000000 ),
- M1590( 9, 1575000000, 1615000000 ),
- M1640( 10, 1615000000, 1650000000 ),
- M1660( 11, 1650000000, 1670000000 ),
- M1680( 12, 1670000000, 1690000000 ),
- M1700( 13, 1690000000, 1710000000 ),
- M1720( 14, 1710000000, 1735000000 ),
+ public static PLL fromSetting(int setting)
+ {
+ int value = setting & 0xF;
- /* Note: max frequency is currently limited by the max integer value
+ for(PLL pll : values())
+ {
+ if(value == pll.getIndex())
+ {
+ return pll;
+ }
+ }
+
+ //Default
+ return PLL.PLL_72M4;
+ }
+ }
+
+ /**
+ * RF filters - UHF Band. Each enum entry defines the center frequency for
+ * the filter and the applicable frequency minimums and maximums for the
+ * filter.
+ *
+ * Note: max frequency overlaps with the next minimum frequency, so valid
+ * frequencies should be less than the maximum frequency defined for the
+ * filter.
+ */
+ public enum RFFilter
+ {
+ NO_FILTER(0, 0, 0),
+
+ //UHF band Filters
+ M360(0, 350000000, 370000000),
+ M380(1, 370000000, 392500000),
+ M405(2, 392500000, 417500000),
+ M425(3, 417500000, 437500000),
+ M450(4, 437500000, 462500000),
+ M475(5, 462500000, 490000000),
+ M505(6, 490000000, 522500000),
+ M540(7, 522500000, 557500000),
+ M575(8, 557500000, 595000000),
+ M615(9, 595000000, 642500000),
+ M670(10, 642500000, 695000000),
+ M720(11, 695000000, 740000000),
+ M760(12, 740000000, 800000000),
+ M840(13, 800000000, 865000000),
+ M890(14, 865000000, 930000000),
+ M970(15, 930000000, 1135000000),
+
+ //L band filters
+ M1300(0, 1135000000, 1310000000),
+ M1320(1, 1310000000, 1340000000),
+ M1360(2, 1340000000, 1385000000),
+ M1410(3, 1385000000, 1427500000),
+ M1445(4, 1427500000, 1452500000),
+ M1460(5, 1452500000, 1475000000),
+ M1490(6, 1475000000, 1510000000),
+ M1530(7, 1510000000, 1545000000),
+ M1560(8, 1545000000, 1575000000),
+ M1590(9, 1575000000, 1615000000),
+ M1640(10, 1615000000, 1650000000),
+ M1660(11, 1650000000, 1670000000),
+ M1680(12, 1670000000, 1690000000),
+ M1700(13, 1690000000, 1710000000),
+ M1720(14, 1710000000, 1735000000),
+
+ /* Note: max frequency is currently limited by the max integer value
* and we set the max frequency for this filter to 2147 MHz */
- M1750( 15, 1735000000, 2147000000 );
-
- private int mValue;
- private long mMinFrequency;
- private long mMaxFrequency;
-
- private RFFilter( int value, long minFrequency, long maxFrequency )
- {
- mValue = value;
- mMinFrequency = minFrequency;
- mMaxFrequency = maxFrequency;
- }
-
- public static Register getRegister()
- {
- return Register.FILT1;
- }
-
- public static byte getMask()
- {
- return (byte)0xF; //TODO: make this a constant
- }
-
- public byte getValue()
- {
- return (byte)mValue;
- }
+ M1750(15, 1735000000, 2147000000);
- /**
- * Minimum frequency for this filter.
- */
- public long getMinimumFrequency()
- {
- return mMinFrequency;
- }
-
- /**
- * Maximum frequency for this filter is less than this value, but does
- * not include this value.
- */
- public long getMaximumFrequency()
- {
- return mMaxFrequency;
- }
-
- /**
- * Selects the appropriate filter for the frequency
- *
- * @param frequency
- * @return selected filter
- * @throws IllegalArgumentException if the frequency is outside the
- * max value (2200 MHz)
- */
- public static RFFilter fromFrequency( long frequency )
- {
- if( frequency < 350000000 )
- {
- return NO_FILTER;
- }
-
- for( RFFilter filter: values() )
- {
- if( filter.getMinimumFrequency() <= frequency &&
- frequency < filter.getMaximumFrequency() )
- {
- return filter;
- }
- }
+ private int mValue;
+ private long mMinFrequency;
+ private long mMaxFrequency;
- throw new IllegalArgumentException( "E4KTunerController - "
- + "cannot find RF filter for frequency [" + frequency + "]" );
- }
- }
-
- public enum MixerFilter
- {
- BW_27M0( 0x00, 27000000, 4800000, 28800000, "27.0 MHz" ),
- BW_4M6( 0x80, 4600000, 4400000, 4800000, "4.6 MHz" ),
- BW_4M2( 0x90, 4200000, 4000000, 4400000, "4.2 MHz" ),
- BW_3M8( 0xA0, 3800000, 3600000, 4000000, "3.8 MHz" ),
- BW_3M4( 0xB0, 3400000, 3200000, 3600000, "3.4 MHz" ),
- BW_3M0( 0xC0, 3000000, 2850000, 3200000, "3.0 MHz" ),
- BW_2M7( 0xD0, 2700000, 2500000, 2850000, "2.7 MHz" ),
- BW_2M3( 0xE0, 2300000, 2100000, 2500000, "2.3 MHz" ),
- BW_1M9( 0xF0, 1900000, 0, 2100000, "1.9 MHz" );
-
- private int mValue;
- private int mBandwidth;
- private int mMinBandwidth;
- private int mMaxBandwidth;
- private String mLabel;
-
- private MixerFilter( int value,
- int bandwidth,
- int minimumBandwidth,
- int maximumBandwidth,
- String label )
- {
- mValue = value;
- mBandwidth = bandwidth;
- mMinBandwidth = minimumBandwidth;
- mMaxBandwidth = maximumBandwidth;
- mLabel = label;
- }
-
- public static Register getRegister()
- {
- return Register.FILT2;
- }
-
- public static byte getMask()
- {
- return MIXER_FILTER_MASK;
- }
-
- public byte getValue()
- {
- return (byte)mValue;
- }
-
- public int getBandwidth()
- {
- return mBandwidth;
- }
-
- public int getMinimumBandwidth()
- {
- return mMinBandwidth;
- }
-
- public int getMaximumBandwidth()
- {
- return mMaxBandwidth;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
+ private RFFilter(int value, long minFrequency, long maxFrequency)
+ {
+ mValue = value;
+ mMinFrequency = minFrequency;
+ mMaxFrequency = maxFrequency;
+ }
- /**
- * Returns the correct filter to use for the bandwidth/sample rate
- * @param bandwidth - current sample rate
- * @return - correct filter to use for the bandwidth/sample rate
- */
- public static MixerFilter getFilter( int bandwidth )
- {
- for( MixerFilter filter: values() )
- {
- if( filter.getMinimumBandwidth() <= bandwidth &&
- bandwidth < filter.getMaximumBandwidth() )
- {
- return filter;
- }
- }
+ public static Register getRegister()
+ {
+ return Register.FILT1;
+ }
+
+ public static byte getMask()
+ {
+ return (byte) 0xF; //TODO: make this a constant
+ }
+
+ public byte getValue()
+ {
+ return (byte) mValue;
+ }
+
+ /**
+ * Minimum frequency for this filter.
+ */
+ public long getMinimumFrequency()
+ {
+ return mMinFrequency;
+ }
+
+ /**
+ * Maximum frequency for this filter is less than this value, but does
+ * not include this value.
+ */
+ public long getMaximumFrequency()
+ {
+ return mMaxFrequency;
+ }
+
+ /**
+ * Selects the appropriate filter for the frequency
+ *
+ * @param frequency
+ * @return selected filter
+ * @throws IllegalArgumentException if the frequency is outside the
+ * max value (2200 MHz)
+ */
+ public static RFFilter fromFrequency(long frequency)
+ {
+ if(frequency < 350000000)
+ {
+ return NO_FILTER;
+ }
+
+ for(RFFilter filter : values())
+ {
+ if(filter.getMinimumFrequency() <= frequency &&
+ frequency < filter.getMaximumFrequency())
+ {
+ return filter;
+ }
+ }
+
+ throw new IllegalArgumentException("E4KTunerController - "
+ + "cannot find RF filter for frequency [" + frequency + "]");
+ }
+ }
+
+ public enum MixerFilter
+ {
+ BW_27M0(0x00, 27000000, 4800000, 28800000, "27.0 MHz"),
+ BW_4M6(0x80, 4600000, 4400000, 4800000, "4.6 MHz"),
+ BW_4M2(0x90, 4200000, 4000000, 4400000, "4.2 MHz"),
+ BW_3M8(0xA0, 3800000, 3600000, 4000000, "3.8 MHz"),
+ BW_3M4(0xB0, 3400000, 3200000, 3600000, "3.4 MHz"),
+ BW_3M0(0xC0, 3000000, 2850000, 3200000, "3.0 MHz"),
+ BW_2M7(0xD0, 2700000, 2500000, 2850000, "2.7 MHz"),
+ BW_2M3(0xE0, 2300000, 2100000, 2500000, "2.3 MHz"),
+ BW_1M9(0xF0, 1900000, 0, 2100000, "1.9 MHz");
+
+ private int mValue;
+ private int mBandwidth;
+ private int mMinBandwidth;
+ private int mMaxBandwidth;
+ private String mLabel;
+
+ private MixerFilter(int value,
+ int bandwidth,
+ int minimumBandwidth,
+ int maximumBandwidth,
+ String label)
+ {
+ mValue = value;
+ mBandwidth = bandwidth;
+ mMinBandwidth = minimumBandwidth;
+ mMaxBandwidth = maximumBandwidth;
+ mLabel = label;
+ }
+
+ public static Register getRegister()
+ {
+ return Register.FILT2;
+ }
+
+ public static byte getMask()
+ {
+ return MIXER_FILTER_MASK;
+ }
+
+ public byte getValue()
+ {
+ return (byte) mValue;
+ }
+
+ public int getBandwidth()
+ {
+ return mBandwidth;
+ }
+
+ public int getMinimumBandwidth()
+ {
+ return mMinBandwidth;
+ }
+
+ public int getMaximumBandwidth()
+ {
+ return mMaxBandwidth;
+ }
+
+ public String getLabel()
+ {
+ return mLabel;
+ }
+
+ /**
+ * Returns the correct filter to use for the bandwidth/sample rate
+ *
+ * @param bandwidth - current sample rate
+ * @return - correct filter to use for the bandwidth/sample rate
+ */
+ public static MixerFilter getFilter(int bandwidth)
+ {
+ for(MixerFilter filter : values())
+ {
+ if(filter.getMinimumBandwidth() <= bandwidth &&
+ bandwidth < filter.getMaximumBandwidth())
+ {
+ return filter;
+ }
+ }
/* default */
- return MixerFilter.BW_27M0;
- }
-
- public static MixerFilter fromRegisterValue( int registerValue )
- {
- int value = registerValue & getMask();
+ return MixerFilter.BW_27M0;
+ }
- for( MixerFilter filter: values() )
- {
- if( value == filter.getValue() )
- {
- return filter;
- }
- }
+ public static MixerFilter fromRegisterValue(int registerValue)
+ {
+ int value = registerValue & getMask();
- throw new IllegalArgumentException( "E4KTunerController - "
- + "unrecognized mixer filter value [" + value + "]" );
- }
- }
-
- public enum RCFilter
- {
- BW_21M4( 0x00, 21400000, 21200000, 28800000, "21.4 MHz" ),
- BW_21M0( 0x01, 21000000, 19300000, 21200000, "21.0 MHz" ),
- BW_17M6( 0x02, 17600000, 16150000, 19300000, "17.6 MHz" ),
- BW_14M7( 0x03, 14700000, 13550000, 16150000, "14.7 MHz" ),
- BW_12M4( 0x04, 12400000, 11500000, 13550000, "12.4 MHz" ),
- BW_10M6( 0x05, 10600000, 9800000, 11500000, "10.6 MHz" ),
- BW_9M0( 0x06, 9000000, 8350000, 9800000, "9.0 MHz" ),
- BW_7M7( 0x07, 7700000, 7050000, 8350000, "7.7 MHz" ),
- BW_6M4( 0x08, 6400000, 5805000, 7050000, "6.4 MHz" ),
- BW_5M3( 0x09, 5300000, 4850000, 5805000, "5.3 MHz" ),
- BW_4M4( 0x0A, 4400000, 3900000, 4850000, "4.4 MHz" ),
- BW_3M4( 0x0B, 3400000, 3000000, 3900000, "3.4 MHz" ),
- BW_2M6( 0x0C, 2600000, 2200000, 3000000, "2.6 MHz" ),
- BW_1M8( 0x0D, 1800000, 1500000, 2200000, "1.8 MHz" ),
- BW_1M2( 0x0E, 1200000, 1100000, 1500000, "1.2 MHz" ),
- BW_1M0( 0x0F, 1000000, 0, 1100000, "1.0 MHz" );
-
- private int mValue;
- private int mBandwidth;
- private int mMinBandwidth;
- private int mMaxBandwidth;
- private String mLabel;
-
- private RCFilter( int value,
- int bandwidth,
- int minimumBandwidth,
- int maximumBandwidth,
- String label )
- {
- mValue = value;
- mBandwidth = bandwidth;
- mMinBandwidth = minimumBandwidth;
- mMaxBandwidth = maximumBandwidth;
- mLabel = label;
- }
-
- public static Register getRegister()
- {
- return Register.FILT2;
- }
-
- public static byte getMask()
- {
- return IF_RC_FILTER_MASK;
- }
-
- public byte getValue()
- {
- return (byte)mValue;
- }
-
- public int getBandwidth()
- {
- return mBandwidth;
- }
-
- public int getMinimumBandwidth()
- {
- return mMinBandwidth;
- }
-
- public int getMaximumBandwidth()
- {
- return mMaxBandwidth;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
-
- /**
- * Returns the correct filter to use for the bandwidth/sample rate
- * @param bandwidth - current sample rate
- * @return - correct filter to use for the bandwidth/sample rate
- */
- public static RCFilter getFilter( int bandwidth )
- {
- for( RCFilter filter: values() )
- {
- if( filter.getMinimumBandwidth() <= bandwidth &&
- bandwidth < filter.getMaximumBandwidth() )
- {
- return filter;
- }
- }
+ for(MixerFilter filter : values())
+ {
+ if(value == filter.getValue())
+ {
+ return filter;
+ }
+ }
+
+ throw new IllegalArgumentException("E4KTunerController - "
+ + "unrecognized mixer filter value [" + value + "]");
+ }
+ }
+
+ public enum RCFilter
+ {
+ BW_21M4(0x00, 21400000, 21200000, 28800000, "21.4 MHz"),
+ BW_21M0(0x01, 21000000, 19300000, 21200000, "21.0 MHz"),
+ BW_17M6(0x02, 17600000, 16150000, 19300000, "17.6 MHz"),
+ BW_14M7(0x03, 14700000, 13550000, 16150000, "14.7 MHz"),
+ BW_12M4(0x04, 12400000, 11500000, 13550000, "12.4 MHz"),
+ BW_10M6(0x05, 10600000, 9800000, 11500000, "10.6 MHz"),
+ BW_9M0(0x06, 9000000, 8350000, 9800000, "9.0 MHz"),
+ BW_7M7(0x07, 7700000, 7050000, 8350000, "7.7 MHz"),
+ BW_6M4(0x08, 6400000, 5805000, 7050000, "6.4 MHz"),
+ BW_5M3(0x09, 5300000, 4850000, 5805000, "5.3 MHz"),
+ BW_4M4(0x0A, 4400000, 3900000, 4850000, "4.4 MHz"),
+ BW_3M4(0x0B, 3400000, 3000000, 3900000, "3.4 MHz"),
+ BW_2M6(0x0C, 2600000, 2200000, 3000000, "2.6 MHz"),
+ BW_1M8(0x0D, 1800000, 1500000, 2200000, "1.8 MHz"),
+ BW_1M2(0x0E, 1200000, 1100000, 1500000, "1.2 MHz"),
+ BW_1M0(0x0F, 1000000, 0, 1100000, "1.0 MHz");
+
+ private int mValue;
+ private int mBandwidth;
+ private int mMinBandwidth;
+ private int mMaxBandwidth;
+ private String mLabel;
+
+ private RCFilter(int value,
+ int bandwidth,
+ int minimumBandwidth,
+ int maximumBandwidth,
+ String label)
+ {
+ mValue = value;
+ mBandwidth = bandwidth;
+ mMinBandwidth = minimumBandwidth;
+ mMaxBandwidth = maximumBandwidth;
+ mLabel = label;
+ }
+
+ public static Register getRegister()
+ {
+ return Register.FILT2;
+ }
+
+ public static byte getMask()
+ {
+ return IF_RC_FILTER_MASK;
+ }
+
+ public byte getValue()
+ {
+ return (byte) mValue;
+ }
+
+ public int getBandwidth()
+ {
+ return mBandwidth;
+ }
+
+ public int getMinimumBandwidth()
+ {
+ return mMinBandwidth;
+ }
+
+ public int getMaximumBandwidth()
+ {
+ return mMaxBandwidth;
+ }
+
+ public String getLabel()
+ {
+ return mLabel;
+ }
+
+ /**
+ * Returns the correct filter to use for the bandwidth/sample rate
+ *
+ * @param bandwidth - current sample rate
+ * @return - correct filter to use for the bandwidth/sample rate
+ */
+ public static RCFilter getFilter(int bandwidth)
+ {
+ for(RCFilter filter : values())
+ {
+ if(filter.getMinimumBandwidth() <= bandwidth &&
+ bandwidth < filter.getMaximumBandwidth())
+ {
+ return filter;
+ }
+ }
/* default */
- return RCFilter.BW_21M4;
- }
-
- public static RCFilter fromRegisterValue( int registerValue )
- {
- int value = registerValue & getMask();
+ return RCFilter.BW_21M4;
+ }
- for( RCFilter filter: values() )
- {
- if( value == filter.getValue() )
- {
- return filter;
- }
- }
+ public static RCFilter fromRegisterValue(int registerValue)
+ {
+ int value = registerValue & getMask();
- throw new IllegalArgumentException( "E4KTunerController - "
- + "unrecognized rc filter value [" + value + "]" );
- }
- }
-
- public enum ChannelFilter
- {
- BW_5M50( 0x00, 5500000, 5400000, 28800000, "5.50 MHz" ),
- BW_5M30( 0x01, 5300000, 5150000, 5400000, "5.30 MHz" ),
- BW_5M00( 0x02, 5000000, 4900000, 5150000, "5.00 MHz" ),
- BW_4M80( 0x03, 4800000, 4700000, 4900000, "4.80 MHz" ),
- BW_4M60( 0x04, 4600000, 4500000, 4700000, "4.60 MHz" ),
- BW_4M40( 0x05, 4400000, 4350000, 4500000, "4.40 MHz" ),
- BW_4M30( 0x06, 4300000, 4200000, 4350000, "4.30 MHz" ),
- BW_4M10( 0x07, 4100000, 4000000, 4200000, "4.10 MHz" ),
- BW_3M90( 0x08, 3900000, 3850000, 4000000, "3.90 MHz" ),
- BW_3M80( 0x09, 3800000, 3750000, 3850000, "3.80 MHz" ),
- BW_3M70( 0x0A, 3700000, 3650000, 3750000, "3.70 MHz" ),
- BW_3M60( 0x0B, 3600000, 3500000, 3650000, "3.60 MHz" ),
- BW_3M40( 0x0C, 3400000, 3350000, 3500000, "3.40 MHz" ),
- BW_3M30( 0x0D, 3300000, 3250000, 3350000, "3.30 MHz" ),
- BW_3M20( 0x0E, 3200000, 3150000, 3250000, "3.20 MHz" ),
- BW_3M10( 0x0F, 3100000, 3050000, 3150000, "3.10 MHz" ),
- BW_3M00( 0x10, 3000000, 2975000, 3050000, "3.00 MHz" ),
- BW_2M95( 0x11, 2950000, 2925000, 2975000, "2.95 MHz" ),
- BW_2M90( 0x12, 2900000, 2850000, 2925000, "2.90 MHz" ),
- BW_2M80( 0x13, 2800000, 2775000, 2850000, "2.80 MHz" ),
- BW_2M75( 0x14, 2750000, 2750000, 2775000, "2.75 MHz" ),
- BW_2M70( 0x15, 2700000, 2650000, 2750000, "2.70 MHz" ),
- BW_2M60( 0x16, 2600000, 2575000, 2650000, "2.60 MHz" ),
- BW_2M55( 0x17, 2550000, 2525000, 2575000, "2.55 MHz" ),
- BW_2M50( 0x18, 2500000, 2475000, 2525000, "2.50 MHz" ),
- BW_2M45( 0x19, 2450000, 2425000, 2475000, "2.45 MHz" ),
- BW_2M40( 0x1A, 2400000, 2350000, 2425000, "2.40 MHz" ),
- BW_2M30( 0x1B, 2300000, 2290000, 2350000, "2.30 MHz" ),
- BW_2M28( 0x1C, 2280000, 2260000, 2290000, "2.28 MHz" ),
- BW_2M24( 0x1D, 2240000, 2220000, 2260000, "2.24 MHz" ),
- BW_2M20( 0x1E, 2200000, 2175000, 2220000, "2.20 MHz" ),
- BW_2M15( 0x1F, 2150000, 0, 2175000, "2.15 MHz" );
-
- private int mValue;
- private int mBandwidth;
- private int mMinBandwidth;
- private int mMaxBandwidth;
- private String mLabel;
-
- private ChannelFilter( int value,
- int bandwidth,
- int minimumBandwidth,
- int maximumBandwidth,
- String label )
- {
- mValue = value;
- mBandwidth = bandwidth;
- mMinBandwidth = minimumBandwidth;
- mMaxBandwidth = maximumBandwidth;
- mLabel = label;
- }
-
- public static Register getRegister()
- {
- return Register.FILT3;
- }
-
- public static byte getMask()
- {
- return IF_CHANNEL_FILTER_MASK;
- }
-
- public byte getValue()
- {
- return (byte)mValue;
- }
-
- public int getBandwidth()
- {
- return mBandwidth;
- }
-
- public int getMinimumBandwidth()
- {
- return mMinBandwidth;
- }
-
- public int getMaximumBandwidth()
- {
- return mMaxBandwidth;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
-
- /**
- * Returns the correct filter to use for the bandwidth/sample rate
- * @param bandwidth - current sample rate
- * @return - correct filter to use for the bandwidth/sample rate
- */
- public static ChannelFilter getFilter( int bandwidth )
- {
- for( ChannelFilter filter: values() )
- {
- if( filter.getMinimumBandwidth() <= bandwidth &&
- bandwidth < filter.getMaximumBandwidth() )
- {
- return filter;
- }
- }
+ for(RCFilter filter : values())
+ {
+ if(value == filter.getValue())
+ {
+ return filter;
+ }
+ }
+
+ throw new IllegalArgumentException("E4KTunerController - "
+ + "unrecognized rc filter value [" + value + "]");
+ }
+ }
+
+ public enum ChannelFilter
+ {
+ BW_5M50(0x00, 5500000, 5400000, 28800000, "5.50 MHz"),
+ BW_5M30(0x01, 5300000, 5150000, 5400000, "5.30 MHz"),
+ BW_5M00(0x02, 5000000, 4900000, 5150000, "5.00 MHz"),
+ BW_4M80(0x03, 4800000, 4700000, 4900000, "4.80 MHz"),
+ BW_4M60(0x04, 4600000, 4500000, 4700000, "4.60 MHz"),
+ BW_4M40(0x05, 4400000, 4350000, 4500000, "4.40 MHz"),
+ BW_4M30(0x06, 4300000, 4200000, 4350000, "4.30 MHz"),
+ BW_4M10(0x07, 4100000, 4000000, 4200000, "4.10 MHz"),
+ BW_3M90(0x08, 3900000, 3850000, 4000000, "3.90 MHz"),
+ BW_3M80(0x09, 3800000, 3750000, 3850000, "3.80 MHz"),
+ BW_3M70(0x0A, 3700000, 3650000, 3750000, "3.70 MHz"),
+ BW_3M60(0x0B, 3600000, 3500000, 3650000, "3.60 MHz"),
+ BW_3M40(0x0C, 3400000, 3350000, 3500000, "3.40 MHz"),
+ BW_3M30(0x0D, 3300000, 3250000, 3350000, "3.30 MHz"),
+ BW_3M20(0x0E, 3200000, 3150000, 3250000, "3.20 MHz"),
+ BW_3M10(0x0F, 3100000, 3050000, 3150000, "3.10 MHz"),
+ BW_3M00(0x10, 3000000, 2975000, 3050000, "3.00 MHz"),
+ BW_2M95(0x11, 2950000, 2925000, 2975000, "2.95 MHz"),
+ BW_2M90(0x12, 2900000, 2850000, 2925000, "2.90 MHz"),
+ BW_2M80(0x13, 2800000, 2775000, 2850000, "2.80 MHz"),
+ BW_2M75(0x14, 2750000, 2750000, 2775000, "2.75 MHz"),
+ BW_2M70(0x15, 2700000, 2650000, 2750000, "2.70 MHz"),
+ BW_2M60(0x16, 2600000, 2575000, 2650000, "2.60 MHz"),
+ BW_2M55(0x17, 2550000, 2525000, 2575000, "2.55 MHz"),
+ BW_2M50(0x18, 2500000, 2475000, 2525000, "2.50 MHz"),
+ BW_2M45(0x19, 2450000, 2425000, 2475000, "2.45 MHz"),
+ BW_2M40(0x1A, 2400000, 2350000, 2425000, "2.40 MHz"),
+ BW_2M30(0x1B, 2300000, 2290000, 2350000, "2.30 MHz"),
+ BW_2M28(0x1C, 2280000, 2260000, 2290000, "2.28 MHz"),
+ BW_2M24(0x1D, 2240000, 2220000, 2260000, "2.24 MHz"),
+ BW_2M20(0x1E, 2200000, 2175000, 2220000, "2.20 MHz"),
+ BW_2M15(0x1F, 2150000, 0, 2175000, "2.15 MHz");
+
+ private int mValue;
+ private int mBandwidth;
+ private int mMinBandwidth;
+ private int mMaxBandwidth;
+ private String mLabel;
+
+ private ChannelFilter(int value,
+ int bandwidth,
+ int minimumBandwidth,
+ int maximumBandwidth,
+ String label)
+ {
+ mValue = value;
+ mBandwidth = bandwidth;
+ mMinBandwidth = minimumBandwidth;
+ mMaxBandwidth = maximumBandwidth;
+ mLabel = label;
+ }
+
+ public static Register getRegister()
+ {
+ return Register.FILT3;
+ }
+
+ public static byte getMask()
+ {
+ return IF_CHANNEL_FILTER_MASK;
+ }
+
+ public byte getValue()
+ {
+ return (byte) mValue;
+ }
+
+ public int getBandwidth()
+ {
+ return mBandwidth;
+ }
+
+ public int getMinimumBandwidth()
+ {
+ return mMinBandwidth;
+ }
+
+ public int getMaximumBandwidth()
+ {
+ return mMaxBandwidth;
+ }
+
+ public String getLabel()
+ {
+ return mLabel;
+ }
+
+ /**
+ * Returns the correct filter to use for the bandwidth/sample rate
+ *
+ * @param bandwidth - current sample rate
+ * @return - correct filter to use for the bandwidth/sample rate
+ */
+ public static ChannelFilter getFilter(int bandwidth)
+ {
+ for(ChannelFilter filter : values())
+ {
+ if(filter.getMinimumBandwidth() <= bandwidth &&
+ bandwidth < filter.getMaximumBandwidth())
+ {
+ return filter;
+ }
+ }
/* default */
- return ChannelFilter.BW_5M50;
- }
-
- public static ChannelFilter fromRegisterValue( int registerValue )
- {
- int value = registerValue & getMask();
+ return ChannelFilter.BW_5M50;
+ }
- for( ChannelFilter filter: values() )
- {
- if( value == filter.getValue() )
- {
- return filter;
- }
- }
+ public static ChannelFilter fromRegisterValue(int registerValue)
+ {
+ int value = registerValue & getMask();
- throw new IllegalArgumentException( "E4KTunerController - "
- + "unrecognized channel filter value [" + value + "]" );
- }
- }
-
- public enum E4KLNAGain
- {
- AUTOMATIC( -1, "Auto" ),
- GAIN_MINUS_50( 0, "-5.0 db" ),
- GAIN_MINUS_25( 1, "-2.5 db" ),
- GAIN_PLUS_0( 4, "0.0 db" ),
- GAIN_PLUS_25( 5, "2.5 db" ),
- GAIN_PLUS_50( 6, "5.0 db" ),
- GAIN_PLUS_75( 7, "7.5 db" ),
- GAIN_PLUS_100( 8, "10.0 db" ),
- GAIN_PLUS_125( 9, "12.5 db" ),
- GAIN_PLUS_150( 10, "15.0 db" ),
- GAIN_PLUS_175( 11, "17.5 db" ),
- GAIN_PLUS_200( 12, "20.0 db" ),
- GAIN_PLUS_250( 13, "25.0 db" ),
- GAIN_PLUS_300( 14, "30.0 db" );
-
- private int mValue;
- private String mLabel;
-
- private E4KLNAGain( int value, String label )
- {
- mValue = value;
- mLabel = label;
- }
-
- public static Register getRegister()
- {
- return Register.GAIN1;
- }
-
- public static byte getMask()
- {
- return GAIN1_MOD_MASK;
- }
-
- public byte getValue()
- {
- return (byte)mValue;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
-
- public String toString()
- {
- return mLabel;
- }
-
- public static E4KLNAGain fromRegisterValue( int registerValue )
- {
- int value = registerValue & getMask();
+ for(ChannelFilter filter : values())
+ {
+ if(value == filter.getValue())
+ {
+ return filter;
+ }
+ }
- for( E4KLNAGain setting: values() )
- {
- if( value == setting.getValue() )
- {
- return setting;
- }
- }
+ throw new IllegalArgumentException("E4KTunerController - "
+ + "unrecognized channel filter value [" + value + "]");
+ }
+ }
- throw new IllegalArgumentException( "E4KTunerController"
- + " - unrecognized LNA Gain value [" +
- value + "]" );
- }
- }
+ public enum E4KLNAGain
+ {
+ AUTOMATIC(-1, "Auto"),
+ GAIN_MINUS_50(0, "-5.0 db"),
+ GAIN_MINUS_25(1, "-2.5 db"),
+ GAIN_PLUS_0(4, "0.0 db"),
+ GAIN_PLUS_25(5, "2.5 db"),
+ GAIN_PLUS_50(6, "5.0 db"),
+ GAIN_PLUS_75(7, "7.5 db"),
+ GAIN_PLUS_100(8, "10.0 db"),
+ GAIN_PLUS_125(9, "12.5 db"),
+ GAIN_PLUS_150(10, "15.0 db"),
+ GAIN_PLUS_175(11, "17.5 db"),
+ GAIN_PLUS_200(12, "20.0 db"),
+ GAIN_PLUS_250(13, "25.0 db"),
+ GAIN_PLUS_300(14, "30.0 db");
- /**
- * Defines the default gain settings that are exposed to the user.
- *
- * Manual is an override that keeps each of the settings intact and allows
- * the user to change each of them individually
- */
- public enum E4KGain
- {
- AUTOMATIC( "Auto", E4KMixerGain.AUTOMATIC, E4KLNAGain.AUTOMATIC, E4KEnhanceGain.AUTOMATIC ),
- MANUAL( "Manual", null, null, null ),
- MINUS_10( "-1.0 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_MINUS_50, E4KEnhanceGain.AUTOMATIC ),
- PLUS_15( "1.5 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_MINUS_25, E4KEnhanceGain.AUTOMATIC ),
- PLUS_40( "4.0 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_0, E4KEnhanceGain.AUTOMATIC ),
- PLUS_65( "6.5 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_25, E4KEnhanceGain.AUTOMATIC ),
- PLUS_90( "9.0 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_50, E4KEnhanceGain.AUTOMATIC ),
- PLUS_115( "11.5 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_75, E4KEnhanceGain.AUTOMATIC ),
- PLUS_140( "14.0 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_100, E4KEnhanceGain.AUTOMATIC ),
- PLUS_165( "16.5 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_125, E4KEnhanceGain.AUTOMATIC ),
- PLUS_190( "19.0 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_150, E4KEnhanceGain.AUTOMATIC ),
- PLUS_215( "21.5 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_175, E4KEnhanceGain.AUTOMATIC ),
- PLUS_240( "24.0 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_200, E4KEnhanceGain.AUTOMATIC ),
- PLUS_290( "29.0 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_250, E4KEnhanceGain.AUTOMATIC ),
- PLUS_340( "34.0 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_300, E4KEnhanceGain.AUTOMATIC ),
- PLUS_420( "42.0 db", E4KMixerGain.GAIN_12, E4KLNAGain.GAIN_PLUS_300, E4KEnhanceGain.AUTOMATIC );
-
- private String mLabel;
- private E4KMixerGain mMixerGain;
- private E4KLNAGain mLNAGain;
- private E4KEnhanceGain mEnhanceGain;
-
- private E4KGain( String label,
- E4KMixerGain mixerGain,
- E4KLNAGain lnaGain,
- E4KEnhanceGain enhanceGain )
- {
- mLabel = label;
- mMixerGain = mixerGain;
- mLNAGain = lnaGain;
- mEnhanceGain = enhanceGain;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
+ private int mValue;
+ private String mLabel;
- public String toString()
- {
- return mLabel;
- }
-
- public E4KMixerGain getMixerGain()
- {
- return mMixerGain;
- }
-
- public E4KLNAGain getLNAGain()
- {
- return mLNAGain;
- }
-
- public E4KEnhanceGain getEnhanceGain()
- {
- return mEnhanceGain;
- }
- }
-
- public enum E4KEnhanceGain
- {
- AUTOMATIC( 0, "Auto" ),
- GAIN_1( 1, "10 db" ),
- GAIN_3( 3, "30 db" ),
- GAIN_5( 5, "50 db" ),
- GAIN_7( 7, "70 db" );
-
- private int mValue;
- private String mLabel;
-
- private E4KEnhanceGain( int value, String label )
- {
- mValue = value;
- mLabel = label;
- }
-
- public static Register getRegister()
- {
- return Register.AGC11;
- }
-
- public static byte getMask()
- {
- return ENH_GAIN_MOD_MASK;
- }
-
- public byte getValue()
- {
- return (byte)mValue;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
-
- public String toString()
- {
- return mLabel;
- }
+ private E4KLNAGain(int value, String label)
+ {
+ mValue = value;
+ mLabel = label;
+ }
- public static E4KEnhanceGain fromRegisterValue( int registerValue )
- {
- int value = registerValue & getMask();
+ public static Register getRegister()
+ {
+ return Register.GAIN1;
+ }
- for( E4KEnhanceGain setting: values() )
- {
- if( value == setting.getValue() )
- {
- return setting;
- }
- }
+ public static byte getMask()
+ {
+ return GAIN1_MOD_MASK;
+ }
- throw new IllegalArgumentException( "E4KTunerController"
- + " - unrecognized Enhance Gain value [" +
- value + "]" );
- }
- }
+ public byte getValue()
+ {
+ return (byte) mValue;
+ }
- public enum DCGainCombination
- {
- LOOKUP_TABLE_0( Register.QLUT0,
- Register.ILUT0,
- E4KMixerGain.GAIN_4,
- IFStage1Gain.GAIN_MINUS3 ),
- LOOKUP_TABLE_1( Register.QLUT1,
- Register.ILUT1,
- E4KMixerGain.GAIN_4,
- IFStage1Gain.GAIN_PLUS6 ),
- LOOKUP_TABLE_2( Register.QLUT2,
- Register.ILUT2,
- E4KMixerGain.GAIN_12,
- IFStage1Gain.GAIN_MINUS3 ),
- LOOKUP_TABLE_3( Register.QLUT3,
- Register.ILUT3,
- E4KMixerGain.GAIN_12,
- IFStage1Gain.GAIN_PLUS6 );
-
- private Register mQRegister;
- private Register mIRegister;
- private E4KMixerGain mMixerGain;
- private IFStage1Gain mIFStage1Gain;
-
- private DCGainCombination( Register qRegister,
- Register iRegister,
- E4KMixerGain mixer,
- IFStage1Gain stage1 )
- {
- mQRegister = qRegister;
- mIRegister = iRegister;
- mMixerGain = mixer;
- mIFStage1Gain = stage1;
- }
-
- public Register getQRegister()
- {
- return mQRegister;
- }
-
- public Register getIRegister()
- {
- return mIRegister;
- }
-
- public E4KMixerGain getMixerGain()
- {
- return mMixerGain;
- }
-
- public IFStage1Gain getIFStage1Gain()
- {
- return mIFStage1Gain;
- }
- }
-
-
- public enum E4KMixerGain
- {
- AUTOMATIC( -1, "Auto" ),
- GAIN_4( 0, "4 db" ),
- GAIN_12( 1, "12 db" );
-
- private int mValue;
- private String mLabel;
-
- private E4KMixerGain( int value, String label )
- {
- mValue = value;
- mLabel = label;
- }
-
- public static Register getRegister()
- {
- return Register.GAIN2;
- }
-
- public static byte getMask()
- {
- return MIXER_GAIN_MASK;
- }
-
- public byte getValue()
- {
- return (byte)mValue;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
-
- public String toString()
- {
- return mLabel;
- }
-
- public static E4KMixerGain fromRegisterValue( int registerValue )
- {
- int value = registerValue & getMask();
+ public String getLabel()
+ {
+ return mLabel;
+ }
- for( E4KMixerGain setting: values() )
- {
- if( value == setting.getValue() )
- {
- return setting;
- }
- }
+ public String toString()
+ {
+ return mLabel;
+ }
- throw new IllegalArgumentException( "E4KTunerController"
- + " - unrecognized Mixer Gain value [" +
- value + "]" );
- }
- }
+ public static E4KLNAGain fromRegisterValue(int registerValue)
+ {
+ int value = registerValue & getMask();
- public enum IFStage1Gain
- {
- GAIN_MINUS3( 0x0, "-3 db" ),
- GAIN_PLUS6( 0x1, "6 db" );
+ for(E4KLNAGain setting : values())
+ {
+ if(value == setting.getValue())
+ {
+ return setting;
+ }
+ }
- private int mValue;
- private String mLabel;
-
- private IFStage1Gain( int value, String label )
- {
- mValue = value;
- mLabel = label;
- }
+ throw new IllegalArgumentException("E4KTunerController"
+ + " - unrecognized LNA Gain value [" +
+ value + "]");
+ }
+ }
- public static Register getRegister()
- {
- return Register.GAIN3;
- }
-
- public static byte getMask()
- {
- return (byte)0x1;
- }
-
- public byte getValue()
- {
- return (byte)mValue;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
-
- public String toString()
- {
- return mLabel;
- }
-
- public static IFStage1Gain fromRegisterValue( int registerValue )
- {
- int value = registerValue & getMask();
+ /**
+ * Defines the default gain settings that are exposed to the user.
+ *
+ * Manual is an override that keeps each of the settings intact and allows
+ * the user to change each of them individually
+ */
+ public enum E4KGain
+ {
+ AUTOMATIC("Auto", E4KMixerGain.AUTOMATIC, E4KLNAGain.AUTOMATIC, E4KEnhanceGain.AUTOMATIC),
+ MANUAL("Manual", null, null, null),
+ MINUS_10("-1.0 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_MINUS_50, E4KEnhanceGain.AUTOMATIC),
+ PLUS_15("1.5 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_MINUS_25, E4KEnhanceGain.AUTOMATIC),
+ PLUS_40("4.0 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_0, E4KEnhanceGain.AUTOMATIC),
+ PLUS_65("6.5 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_25, E4KEnhanceGain.AUTOMATIC),
+ PLUS_90("9.0 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_50, E4KEnhanceGain.AUTOMATIC),
+ PLUS_115("11.5 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_75, E4KEnhanceGain.AUTOMATIC),
+ PLUS_140("14.0 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_100, E4KEnhanceGain.AUTOMATIC),
+ PLUS_165("16.5 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_125, E4KEnhanceGain.AUTOMATIC),
+ PLUS_190("19.0 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_150, E4KEnhanceGain.AUTOMATIC),
+ PLUS_215("21.5 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_175, E4KEnhanceGain.AUTOMATIC),
+ PLUS_240("24.0 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_200, E4KEnhanceGain.AUTOMATIC),
+ PLUS_290("29.0 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_250, E4KEnhanceGain.AUTOMATIC),
+ PLUS_340("34.0 db", E4KMixerGain.GAIN_4, E4KLNAGain.GAIN_PLUS_300, E4KEnhanceGain.AUTOMATIC),
+ PLUS_420("42.0 db", E4KMixerGain.GAIN_12, E4KLNAGain.GAIN_PLUS_300, E4KEnhanceGain.AUTOMATIC);
- for( IFStage1Gain setting: values() )
- {
- if( value == setting.getValue() )
- {
- return setting;
- }
- }
+ private String mLabel;
+ private E4KMixerGain mMixerGain;
+ private E4KLNAGain mLNAGain;
+ private E4KEnhanceGain mEnhanceGain;
- throw new IllegalArgumentException( "E4KTunerController"
- + " - unrecognized IF Gain Stage 1 value [" +
- value + "]" );
- }
- }
+ private E4KGain(String label,
+ E4KMixerGain mixerGain,
+ E4KLNAGain lnaGain,
+ E4KEnhanceGain enhanceGain)
+ {
+ mLabel = label;
+ mMixerGain = mixerGain;
+ mLNAGain = lnaGain;
+ mEnhanceGain = enhanceGain;
+ }
- public enum IFStage2Gain
- {
- GAIN_PLUS0( 0x0, "0 db" ),
- GAIN_PLUS3( 0x2, "3 db" ),
- GAIN_PLUS6( 0x4, "6 db" ),
- GAIN_PLUS9( 0x6, "9 db" );
+ public String getLabel()
+ {
+ return mLabel;
+ }
- private int mValue;
- private String mLabel;
-
- private IFStage2Gain( int value, String label )
- {
- mValue = value;
- mLabel = label;
- }
+ public String toString()
+ {
+ return mLabel;
+ }
- public static Register getRegister()
- {
- return Register.GAIN3;
- }
-
- public static byte getMask()
- {
- return (byte)0x6;
- }
-
- public byte getValue()
- {
- return (byte)mValue;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
-
- public String toString()
- {
- return mLabel;
- }
+ public E4KMixerGain getMixerGain()
+ {
+ return mMixerGain;
+ }
- public static IFStage2Gain fromRegisterValue( int registerValue )
- {
- int value = registerValue & getMask();
+ public E4KLNAGain getLNAGain()
+ {
+ return mLNAGain;
+ }
- for( IFStage2Gain setting: values() )
- {
- if( value == setting.getValue() )
- {
- return setting;
- }
- }
+ public E4KEnhanceGain getEnhanceGain()
+ {
+ return mEnhanceGain;
+ }
+ }
- throw new IllegalArgumentException( "E4KTunerController"
- + " - unrecognized IF Gain Stage 2 value [" +
- value + "]" );
- }
- }
+ public enum E4KEnhanceGain
+ {
+ AUTOMATIC(0, "Auto"),
+ GAIN_1(1, "10 db"),
+ GAIN_3(3, "30 db"),
+ GAIN_5(5, "50 db"),
+ GAIN_7(7, "70 db");
- public enum IFStage3Gain
- {
- GAIN_PLUS0( 0x00, "0 db" ),
- GAIN_PLUS3( 0x08, "3 db" ),
- GAIN_PLUS6( 0x10, "6 db" ),
- GAIN_PLUS9( 0x30, "9 db" );
+ private int mValue;
+ private String mLabel;
- private int mValue;
- private String mLabel;
-
- private IFStage3Gain( int value, String label )
- {
- mValue = value;
- mLabel = label;
- }
+ private E4KEnhanceGain(int value, String label)
+ {
+ mValue = value;
+ mLabel = label;
+ }
- public static Register getRegister()
- {
- return Register.GAIN3;
- }
-
- public static byte getMask()
- {
- return (byte)0x18;
- }
-
- public byte getValue()
- {
- return (byte)mValue;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
-
- public String toString()
- {
- return mLabel;
- }
+ public static Register getRegister()
+ {
+ return Register.AGC11;
+ }
- public static IFStage3Gain fromRegisterValue( int registerValue )
- {
- int value = registerValue & getMask();
+ public static byte getMask()
+ {
+ return ENH_GAIN_MOD_MASK;
+ }
- for( IFStage3Gain setting: values() )
- {
- if( value == setting.getValue() )
- {
- return setting;
- }
- }
+ public byte getValue()
+ {
+ return (byte) mValue;
+ }
- throw new IllegalArgumentException( "E4KTunerController"
- + " - unrecognized IF Gain Stage 3 value [" +
- value + "]" );
- }
- }
+ public String getLabel()
+ {
+ return mLabel;
+ }
- public enum IFStage4Gain
- {
- GAIN_PLUS0( 0x00, "0 db" ),
- GAIN_PLUS1( 0x20, "1 db" ),
- GAIN_PLUS2A( 0x40, "2 db" ),
- GAIN_PLUS2B( 0x60, "2 db" );
+ public String toString()
+ {
+ return mLabel;
+ }
- private int mValue;
- private String mLabel;
-
- private IFStage4Gain( int value, String label )
- {
- mValue = value;
- mLabel = label;
- }
+ public static E4KEnhanceGain fromRegisterValue(int registerValue)
+ {
+ int value = registerValue & getMask();
- public static Register getRegister()
- {
- return Register.GAIN3;
- }
-
- public static byte getMask()
- {
- return (byte)0x60;
- }
-
- public byte getValue()
- {
- return (byte)mValue;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
-
- public String toString()
- {
- return mLabel;
- }
+ for(E4KEnhanceGain setting : values())
+ {
+ if(value == setting.getValue())
+ {
+ return setting;
+ }
+ }
- public static IFStage4Gain fromRegisterValue( int registerValue )
- {
- int value = registerValue & getMask();
+ throw new IllegalArgumentException("E4KTunerController"
+ + " - unrecognized Enhance Gain value [" +
+ value + "]");
+ }
+ }
- for( IFStage4Gain setting: values() )
- {
- if( value == setting.getValue() )
- {
- return setting;
- }
- }
+ public enum DCGainCombination
+ {
+ LOOKUP_TABLE_0(Register.QLUT0,
+ Register.ILUT0,
+ E4KMixerGain.GAIN_4,
+ IFStage1Gain.GAIN_MINUS3),
+ LOOKUP_TABLE_1(Register.QLUT1,
+ Register.ILUT1,
+ E4KMixerGain.GAIN_4,
+ IFStage1Gain.GAIN_PLUS6),
+ LOOKUP_TABLE_2(Register.QLUT2,
+ Register.ILUT2,
+ E4KMixerGain.GAIN_12,
+ IFStage1Gain.GAIN_MINUS3),
+ LOOKUP_TABLE_3(Register.QLUT3,
+ Register.ILUT3,
+ E4KMixerGain.GAIN_12,
+ IFStage1Gain.GAIN_PLUS6);
- throw new IllegalArgumentException( "E4KTunerController"
- + " - unrecognized IF Gain Stage 4 value [" +
- value + "]" );
- }
- }
+ private Register mQRegister;
+ private Register mIRegister;
+ private E4KMixerGain mMixerGain;
+ private IFStage1Gain mIFStage1Gain;
- public enum IFStage5Gain
- {
- GAIN_PLUS3( 0x0, "3 db" ),
- GAIN_PLUS6( 0x1, "6 db" ),
- GAIN_PLUS9( 0x2, "9 db" ),
- GAIN_PLUS12( 0x3, "12 db" ),
- GAIN_PLUS15A( 0x4, "15 db" ),
- GAIN_PLUS15B( 0x5, "15 db" ),
- GAIN_PLUS15C( 0x6, "15 db" ),
- GAIN_PLUS15D( 0x7, "15 db" );
+ private DCGainCombination(Register qRegister,
+ Register iRegister,
+ E4KMixerGain mixer,
+ IFStage1Gain stage1)
+ {
+ mQRegister = qRegister;
+ mIRegister = iRegister;
+ mMixerGain = mixer;
+ mIFStage1Gain = stage1;
+ }
- private int mValue;
- private String mLabel;
-
- private IFStage5Gain( int value, String label )
- {
- mValue = value;
- mLabel = label;
- }
+ public Register getQRegister()
+ {
+ return mQRegister;
+ }
- public static Register getRegister()
- {
- return Register.GAIN4;
- }
-
- public static byte getMask()
- {
- return (byte)0x7;
- }
-
- public byte getValue()
- {
- return (byte)mValue;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
-
- public String toString()
- {
- return mLabel;
- }
-
- public static IFStage5Gain fromRegisterValue( int registerValue )
- {
- int value = registerValue & getMask();
+ public Register getIRegister()
+ {
+ return mIRegister;
+ }
- for( IFStage5Gain setting: values() )
- {
- if( value == setting.getValue() )
- {
- return setting;
- }
- }
+ public E4KMixerGain getMixerGain()
+ {
+ return mMixerGain;
+ }
- throw new IllegalArgumentException( "E4KTunerController"
- + " - unrecognized IF Gain Stage 5 value [" +
- value + "]" );
- }
-
- }
+ public IFStage1Gain getIFStage1Gain()
+ {
+ return mIFStage1Gain;
+ }
+ }
- public enum IFStage6Gain
- {
- GAIN_PLUS3( 0x00, "3 db" ),
- GAIN_PLUS6( 0x08, "6 db" ),
- GAIN_PLUS9( 0x10, "9 db" ),
- GAIN_PLUS12( 0x18, "12 db" ),
- GAIN_PLUS15A( 0x20, "15 db" ),
- GAIN_PLUS15B( 0x28, "15 db" ),
- GAIN_PLUS15C( 0x30, "15 db" ),
- GAIN_PLUS15D( 0x38, "15 db" );
- private int mValue;
- private String mLabel;
-
- private IFStage6Gain( int value, String label )
- {
- mValue = value;
- mLabel = label;
- }
+ public enum E4KMixerGain
+ {
+ AUTOMATIC(-1, "Auto"),
+ GAIN_4(0, "4 db"),
+ GAIN_12(1, "12 db");
- public static Register getRegister()
- {
- return Register.GAIN4;
- }
-
- public static byte getMask()
- {
- return (byte)0x38;
- }
-
- public byte getValue()
- {
- return (byte)mValue;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
-
- public String toString()
- {
- return mLabel;
- }
+ private int mValue;
+ private String mLabel;
- public static IFStage6Gain fromRegisterValue( int registerValue )
- {
- int value = registerValue & getMask();
+ private E4KMixerGain(int value, String label)
+ {
+ mValue = value;
+ mLabel = label;
+ }
- for( IFStage6Gain setting: values() )
- {
- if( value == setting.getValue() )
- {
- return setting;
- }
- }
+ public static Register getRegister()
+ {
+ return Register.GAIN2;
+ }
- throw new IllegalArgumentException( "E4KTunerController"
- + " - unrecognized IF Gain Stage 6 value [" +
- value + "]" );
- }
- }
+ public static byte getMask()
+ {
+ return MIXER_GAIN_MASK;
+ }
- public enum IFFilter
- {
- MIX( "Mix" ),
- CHAN( "Channel" ),
- RC( "RC" );
-
- private String mLabel;
-
- private IFFilter( String label )
- {
- mLabel = label;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
- }
+ public byte getValue()
+ {
+ return (byte) mValue;
+ }
- public enum AGCMode
- {
- SERIAL( (byte)0x0 ),
- IF_PWM_LNA_SERIAL( (byte)0x1 ),
- IF_PWM_LNA_AUTONL( (byte)0x2 ),
- IF_PWM_LNA_SUPERV( (byte)0x3 ),
- IF_SERIAL_LNA_PWM( (byte)0x4 ),
- IF_PWM_LNA_PWM( (byte)0x5 ),
- IF_DIG_LNA_SERIAL( (byte)0x6 ),
- IF_DIG_LNA_AUTON( (byte)0x7 ),
- IF_DIG_LNA_SUPERV( (byte)0x8 ),
- IF_SERIAL_LNA_AUTON( (byte)0x9 ),
- IF_SERIAL_LNA_SUPERV( (byte)0xA );
-
- private byte mValue;
-
- private AGCMode( byte value )
- {
- mValue = value;
- }
-
- public byte getValue()
- {
- return mValue;
- }
- }
-
- public enum Register
- {
- DUMMY( 0x00 ),
- MASTER1( 0x00 ),
- MASTER2( 0x01 ),
- MASTER3( 0x02 ),
- MASTER4( 0x03 ),
- MASTER5( 0x04 ),
- CLK_INP( 0x05 ),
- REF_CLK( 0x06 ),
- SYNTH1( 0x07 ),
- SYNTH2( 0x08 ),
- SYNTH3( 0x09 ),
- SYNTH4( 0x0A ),
- SYNTH5( 0x0B ),
- SYNTH6( 0x0C ),
- SYNTH7( 0x0D ),
- SYNTH8( 0x0E ),
- SYNTH9( 0x0F ),
- FILT1( 0x10 ),
- FILT2( 0x11 ),
- FILT3( 0x12 ),
- GAIN1( 0x14 ),
- GAIN2( 0x15 ),
- GAIN3( 0x16 ),
- GAIN4( 0x17 ),
- AGC1( 0x1A ),
- AGC2( 0x1B ),
- AGC3( 0x1C ),
- AGC4( 0x1D ),
- AGC5( 0x1E ),
- AGC6( 0x1F ),
- AGC7( 0x20 ),
- AGC8( 0x21 ),
- AGC11( 0x24 ),
- AGC12( 0x25 ),
- DC1( 0x29 ),
- DC2( 0x2A ),
- DC3( 0x2B ),
- DC4( 0x2C ),
- DC5( 0x2D ),
- DC6( 0x2E ),
- DC7( 0x2F ),
- DC8( 0x30 ),
- QLUT0( 0x50 ),
- QLUT1( 0x51 ),
- QLUT2( 0x52 ),
- QLUT3( 0x53 ),
- ILUT0( 0x60 ),
- ILUT1( 0x61 ),
- ILUT2( 0x62 ),
- ILUT3( 0x63 ),
- DCTIME1( 0x70 ),
- DCTIME2( 0x71 ),
- DCTIME3( 0x72 ),
- DCTIME4( 0x73 ),
- PWM1( 0x74 ),
- PWM2( 0x75 ),
- PWM3( 0x76 ),
- PWM4( 0x77 ),
- BIAS( 0x78 ),
- CLKOUT_PWDN( 0x7A ),
- CHFILT_CALIB( 0x7B ),
- I2C_REG_ADDR( 0x7D ),
- MAGIC_1( 0x7E ),
- MAGIC_2( 0x7F ),
- MAGIC_3( 0x82 ),
- MAGIC_4( 0x86 ),
- MAGIC_5( 0x87 ),
- MAGIC_6( 0x88 ),
- MAGIC_7( 0x9F ),
- MAGIC_8( 0xA0 ),
- I2C_REGISTER( 0xC8 );
+ public String getLabel()
+ {
+ return mLabel;
+ }
- private int mValue;
-
- private Register( int value )
- {
- mValue = value;
- }
-
- public byte getValue()
- {
- return (byte)mValue;
- }
- }
+ public String toString()
+ {
+ return mLabel;
+ }
+
+ public static E4KMixerGain fromRegisterValue(int registerValue)
+ {
+ int value = registerValue & getMask();
+
+ for(E4KMixerGain setting : values())
+ {
+ if(value == setting.getValue())
+ {
+ return setting;
+ }
+ }
+
+ throw new IllegalArgumentException("E4KTunerController"
+ + " - unrecognized Mixer Gain value [" +
+ value + "]");
+ }
+ }
+
+ public enum IFStage1Gain
+ {
+ GAIN_MINUS3(0x0, "-3 db"),
+ GAIN_PLUS6(0x1, "6 db");
+
+ private int mValue;
+ private String mLabel;
+
+ private IFStage1Gain(int value, String label)
+ {
+ mValue = value;
+ mLabel = label;
+ }
+
+ public static Register getRegister()
+ {
+ return Register.GAIN3;
+ }
+
+ public static byte getMask()
+ {
+ return (byte) 0x1;
+ }
+
+ public byte getValue()
+ {
+ return (byte) mValue;
+ }
+
+ public String getLabel()
+ {
+ return mLabel;
+ }
+
+ public String toString()
+ {
+ return mLabel;
+ }
+
+ public static IFStage1Gain fromRegisterValue(int registerValue)
+ {
+ int value = registerValue & getMask();
+
+ for(IFStage1Gain setting : values())
+ {
+ if(value == setting.getValue())
+ {
+ return setting;
+ }
+ }
+
+ throw new IllegalArgumentException("E4KTunerController"
+ + " - unrecognized IF Gain Stage 1 value [" +
+ value + "]");
+ }
+ }
+
+ public enum IFStage2Gain
+ {
+ GAIN_PLUS0(0x0, "0 db"),
+ GAIN_PLUS3(0x2, "3 db"),
+ GAIN_PLUS6(0x4, "6 db"),
+ GAIN_PLUS9(0x6, "9 db");
+
+ private int mValue;
+ private String mLabel;
+
+ private IFStage2Gain(int value, String label)
+ {
+ mValue = value;
+ mLabel = label;
+ }
+
+ public static Register getRegister()
+ {
+ return Register.GAIN3;
+ }
+
+ public static byte getMask()
+ {
+ return (byte) 0x6;
+ }
+
+ public byte getValue()
+ {
+ return (byte) mValue;
+ }
+
+ public String getLabel()
+ {
+ return mLabel;
+ }
+
+ public String toString()
+ {
+ return mLabel;
+ }
+
+ public static IFStage2Gain fromRegisterValue(int registerValue)
+ {
+ int value = registerValue & getMask();
+
+ for(IFStage2Gain setting : values())
+ {
+ if(value == setting.getValue())
+ {
+ return setting;
+ }
+ }
+
+ throw new IllegalArgumentException("E4KTunerController"
+ + " - unrecognized IF Gain Stage 2 value [" +
+ value + "]");
+ }
+ }
+
+ public enum IFStage3Gain
+ {
+ GAIN_PLUS0(0x00, "0 db"),
+ GAIN_PLUS3(0x08, "3 db"),
+ GAIN_PLUS6(0x10, "6 db"),
+ GAIN_PLUS9(0x30, "9 db");
+
+ private int mValue;
+ private String mLabel;
+
+ private IFStage3Gain(int value, String label)
+ {
+ mValue = value;
+ mLabel = label;
+ }
+
+ public static Register getRegister()
+ {
+ return Register.GAIN3;
+ }
+
+ public static byte getMask()
+ {
+ return (byte) 0x18;
+ }
+
+ public byte getValue()
+ {
+ return (byte) mValue;
+ }
+
+ public String getLabel()
+ {
+ return mLabel;
+ }
+
+ public String toString()
+ {
+ return mLabel;
+ }
+
+ public static IFStage3Gain fromRegisterValue(int registerValue)
+ {
+ int value = registerValue & getMask();
+
+ for(IFStage3Gain setting : values())
+ {
+ if(value == setting.getValue())
+ {
+ return setting;
+ }
+ }
+
+ throw new IllegalArgumentException("E4KTunerController"
+ + " - unrecognized IF Gain Stage 3 value [" +
+ value + "]");
+ }
+ }
+
+ public enum IFStage4Gain
+ {
+ GAIN_PLUS0(0x00, "0 db"),
+ GAIN_PLUS1(0x20, "1 db"),
+ GAIN_PLUS2A(0x40, "2 db"),
+ GAIN_PLUS2B(0x60, "2 db");
+
+ private int mValue;
+ private String mLabel;
+
+ private IFStage4Gain(int value, String label)
+ {
+ mValue = value;
+ mLabel = label;
+ }
+
+ public static Register getRegister()
+ {
+ return Register.GAIN3;
+ }
+
+ public static byte getMask()
+ {
+ return (byte) 0x60;
+ }
+
+ public byte getValue()
+ {
+ return (byte) mValue;
+ }
+
+ public String getLabel()
+ {
+ return mLabel;
+ }
+
+ public String toString()
+ {
+ return mLabel;
+ }
+
+ public static IFStage4Gain fromRegisterValue(int registerValue)
+ {
+ int value = registerValue & getMask();
+
+ for(IFStage4Gain setting : values())
+ {
+ if(value == setting.getValue())
+ {
+ return setting;
+ }
+ }
+
+ throw new IllegalArgumentException("E4KTunerController"
+ + " - unrecognized IF Gain Stage 4 value [" +
+ value + "]");
+ }
+ }
+
+ public enum IFStage5Gain
+ {
+ GAIN_PLUS3(0x0, "3 db"),
+ GAIN_PLUS6(0x1, "6 db"),
+ GAIN_PLUS9(0x2, "9 db"),
+ GAIN_PLUS12(0x3, "12 db"),
+ GAIN_PLUS15A(0x4, "15 db"),
+ GAIN_PLUS15B(0x5, "15 db"),
+ GAIN_PLUS15C(0x6, "15 db"),
+ GAIN_PLUS15D(0x7, "15 db");
+
+ private int mValue;
+ private String mLabel;
+
+ private IFStage5Gain(int value, String label)
+ {
+ mValue = value;
+ mLabel = label;
+ }
+
+ public static Register getRegister()
+ {
+ return Register.GAIN4;
+ }
+
+ public static byte getMask()
+ {
+ return (byte) 0x7;
+ }
+
+ public byte getValue()
+ {
+ return (byte) mValue;
+ }
+
+ public String getLabel()
+ {
+ return mLabel;
+ }
+
+ public String toString()
+ {
+ return mLabel;
+ }
+
+ public static IFStage5Gain fromRegisterValue(int registerValue)
+ {
+ int value = registerValue & getMask();
+
+ for(IFStage5Gain setting : values())
+ {
+ if(value == setting.getValue())
+ {
+ return setting;
+ }
+ }
+
+ throw new IllegalArgumentException("E4KTunerController"
+ + " - unrecognized IF Gain Stage 5 value [" +
+ value + "]");
+ }
+
+ }
+
+ public enum IFStage6Gain
+ {
+ GAIN_PLUS3(0x00, "3 db"),
+ GAIN_PLUS6(0x08, "6 db"),
+ GAIN_PLUS9(0x10, "9 db"),
+ GAIN_PLUS12(0x18, "12 db"),
+ GAIN_PLUS15A(0x20, "15 db"),
+ GAIN_PLUS15B(0x28, "15 db"),
+ GAIN_PLUS15C(0x30, "15 db"),
+ GAIN_PLUS15D(0x38, "15 db");
+
+ private int mValue;
+ private String mLabel;
+
+ private IFStage6Gain(int value, String label)
+ {
+ mValue = value;
+ mLabel = label;
+ }
+
+ public static Register getRegister()
+ {
+ return Register.GAIN4;
+ }
+
+ public static byte getMask()
+ {
+ return (byte) 0x38;
+ }
+
+ public byte getValue()
+ {
+ return (byte) mValue;
+ }
+
+ public String getLabel()
+ {
+ return mLabel;
+ }
+
+ public String toString()
+ {
+ return mLabel;
+ }
+
+ public static IFStage6Gain fromRegisterValue(int registerValue)
+ {
+ int value = registerValue & getMask();
+
+ for(IFStage6Gain setting : values())
+ {
+ if(value == setting.getValue())
+ {
+ return setting;
+ }
+ }
+
+ throw new IllegalArgumentException("E4KTunerController"
+ + " - unrecognized IF Gain Stage 6 value [" +
+ value + "]");
+ }
+ }
+
+ public enum IFFilter
+ {
+ MIX("Mix"),
+ CHAN("Channel"),
+ RC("RC");
+
+ private String mLabel;
+
+ private IFFilter(String label)
+ {
+ mLabel = label;
+ }
+
+ public String getLabel()
+ {
+ return mLabel;
+ }
+ }
+
+ public enum AGCMode
+ {
+ SERIAL((byte) 0x0),
+ IF_PWM_LNA_SERIAL((byte) 0x1),
+ IF_PWM_LNA_AUTONL((byte) 0x2),
+ IF_PWM_LNA_SUPERV((byte) 0x3),
+ IF_SERIAL_LNA_PWM((byte) 0x4),
+ IF_PWM_LNA_PWM((byte) 0x5),
+ IF_DIG_LNA_SERIAL((byte) 0x6),
+ IF_DIG_LNA_AUTON((byte) 0x7),
+ IF_DIG_LNA_SUPERV((byte) 0x8),
+ IF_SERIAL_LNA_AUTON((byte) 0x9),
+ IF_SERIAL_LNA_SUPERV((byte) 0xA);
+
+ private byte mValue;
+
+ private AGCMode(byte value)
+ {
+ mValue = value;
+ }
+
+ public byte getValue()
+ {
+ return mValue;
+ }
+ }
+
+ public enum Register
+ {
+ DUMMY(0x00),
+ MASTER1(0x00),
+ MASTER2(0x01),
+ MASTER3(0x02),
+ MASTER4(0x03),
+ MASTER5(0x04),
+ CLK_INP(0x05),
+ REF_CLK(0x06),
+ SYNTH1(0x07),
+ SYNTH2(0x08),
+ SYNTH3(0x09),
+ SYNTH4(0x0A),
+ SYNTH5(0x0B),
+ SYNTH6(0x0C),
+ SYNTH7(0x0D),
+ SYNTH8(0x0E),
+ SYNTH9(0x0F),
+ FILT1(0x10),
+ FILT2(0x11),
+ FILT3(0x12),
+ GAIN1(0x14),
+ GAIN2(0x15),
+ GAIN3(0x16),
+ GAIN4(0x17),
+ AGC1(0x1A),
+ AGC2(0x1B),
+ AGC3(0x1C),
+ AGC4(0x1D),
+ AGC5(0x1E),
+ AGC6(0x1F),
+ AGC7(0x20),
+ AGC8(0x21),
+ AGC11(0x24),
+ AGC12(0x25),
+ DC1(0x29),
+ DC2(0x2A),
+ DC3(0x2B),
+ DC4(0x2C),
+ DC5(0x2D),
+ DC6(0x2E),
+ DC7(0x2F),
+ DC8(0x30),
+ QLUT0(0x50),
+ QLUT1(0x51),
+ QLUT2(0x52),
+ QLUT3(0x53),
+ ILUT0(0x60),
+ ILUT1(0x61),
+ ILUT2(0x62),
+ ILUT3(0x63),
+ DCTIME1(0x70),
+ DCTIME2(0x71),
+ DCTIME3(0x72),
+ DCTIME4(0x73),
+ PWM1(0x74),
+ PWM2(0x75),
+ PWM3(0x76),
+ PWM4(0x77),
+ BIAS(0x78),
+ CLKOUT_PWDN(0x7A),
+ CHFILT_CALIB(0x7B),
+ I2C_REG_ADDR(0x7D),
+ MAGIC_1(0x7E),
+ MAGIC_2(0x7F),
+ MAGIC_3(0x82),
+ MAGIC_4(0x86),
+ MAGIC_5(0x87),
+ MAGIC_6(0x88),
+ MAGIC_7(0x9F),
+ MAGIC_8(0xA0),
+ I2C_REGISTER(0xC8);
+
+ private int mValue;
+
+ private Register(int value)
+ {
+ mValue = value;
+ }
+
+ public byte getValue()
+ {
+ return (byte) mValue;
+ }
+ }
}
diff --git a/src/source/tuner/rtl/r820t/R820TTunerController.java b/src/source/tuner/rtl/r820t/R820TTunerController.java
index 4ce92492..762cb080 100644
--- a/src/source/tuner/rtl/r820t/R820TTunerController.java
+++ b/src/source/tuner/rtl/r820t/R820TTunerController.java
@@ -1,758 +1,753 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014-2016 Dennis Sheirer
- *
+ *
* Java port of librtlsdr
- *
+ *
* Copyright (C) 2013 Mauro Carvalho Chehab
* Copyright (C) 2013 Steve Markgraf
- *
+ *
* 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 source.tuner.rtl.r820t;
-import java.nio.ByteBuffer;
-
-import javax.swing.JPanel;
-import javax.usb.UsbException;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.usb4java.Device;
import org.usb4java.DeviceDescriptor;
import org.usb4java.LibUsbException;
-
import source.SourceException;
import source.tuner.TunerType;
import source.tuner.configuration.TunerConfiguration;
import source.tuner.rtl.RTL2832TunerController;
-import controller.ThreadPoolManager;
+
+import javax.swing.*;
+import javax.usb.UsbException;
+import java.nio.ByteBuffer;
public class R820TTunerController extends RTL2832TunerController
{
- private final static Logger mLog =
- LoggerFactory.getLogger( R820TTunerController.class );
+ private final static Logger mLog =
+ LoggerFactory.getLogger(R820TTunerController.class);
- public static final long MIN_FREQUENCY = 3180000;
- public static final long MAX_FREQUENCY = 1782030000;
- public static final double USABLE_BANDWIDTH_PERCENT = 1.0;
- public static final int DC_SPIKE_AVOID_BUFFER = 5000;
+ public static final long MIN_FREQUENCY = 3180000;
+ public static final long MAX_FREQUENCY = 1782030000;
+ public static final double USABLE_BANDWIDTH_PERCENT = 1.0;
+ public static final int DC_SPIKE_AVOID_BUFFER = 5000;
- public static final int R820T_IF_FREQUENCY = 3570000;
- public static final byte VERSION = (byte)49;
-
- public static final byte[] BIT_REV_LOOKUP_TABLE =
- { (byte)0x0, (byte)0x8, (byte)0x4, (byte)0xC,
- (byte)0x2, (byte)0xA, (byte)0x6, (byte)0xE,
- (byte)0x1, (byte)0x9, (byte)0x5, (byte)0xD,
- (byte)0x3, (byte)0xB, (byte)0x7, (byte)0xF };
-
- /* R820T I2C address */
- private byte mI2CAddress = (byte)0x34;
-
- /* Shadow register is used to keep a cached (in-memory) copy of all
- * registers, so that we don't have to read a full byte from a register in
- * order to apply a masked value and then re-write the full byte. With the
- * shadow register, we can apply the masked value to the cached value, and
- * then just write the masked byte, skipping the need to read the byte
- * first. */
- private int[] mShadowRegister =
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x32, 0x75,
- 0xC0, 0x40, 0xD6, 0x6C, 0xF5, 0x63, 0x75, 0x68,
- 0x6C, 0x83, 0x80, 0x00, 0x0F, 0x00, 0xC0, 0x30,
- 0x48, 0xCC, 0x60, 0x00, 0x54, 0xAE, 0x4A, 0xC0 };
-
- private JPanel mEditor;
-
- public R820TTunerController( Device device,
- DeviceDescriptor deviceDescriptor,
- ThreadPoolManager threadPoolManager )
- throws SourceException
- {
- super( device, deviceDescriptor, threadPoolManager, MIN_FREQUENCY,
- MAX_FREQUENCY, DC_SPIKE_AVOID_BUFFER, USABLE_BANDWIDTH_PERCENT );
- }
+ public static final int R820T_IF_FREQUENCY = 3570000;
+ public static final byte VERSION = (byte) 49;
- @Override
+ public static final byte[] BIT_REV_LOOKUP_TABLE =
+ {(byte) 0x0, (byte) 0x8, (byte) 0x4, (byte) 0xC,
+ (byte) 0x2, (byte) 0xA, (byte) 0x6, (byte) 0xE,
+ (byte) 0x1, (byte) 0x9, (byte) 0x5, (byte) 0xD,
+ (byte) 0x3, (byte) 0xB, (byte) 0x7, (byte) 0xF};
+
+ /* R820T I2C address */
+ private byte mI2CAddress = (byte) 0x34;
+
+ /* Shadow register is used to keep a cached (in-memory) copy of all
+ * registers, so that we don't have to read a full byte from a register in
+ * order to apply a masked value and then re-write the full byte. With the
+ * shadow register, we can apply the masked value to the cached value, and
+ * then just write the masked byte, skipping the need to read the byte
+ * first. */
+ private int[] mShadowRegister =
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x32, 0x75,
+ 0xC0, 0x40, 0xD6, 0x6C, 0xF5, 0x63, 0x75, 0x68,
+ 0x6C, 0x83, 0x80, 0x00, 0x0F, 0x00, 0xC0, 0x30,
+ 0x48, 0xCC, 0x60, 0x00, 0x54, 0xAE, 0x4A, 0xC0};
+
+ private JPanel mEditor;
+
+ public R820TTunerController(Device device, DeviceDescriptor deviceDescriptor) throws SourceException
+ {
+ super(device, deviceDescriptor, MIN_FREQUENCY, MAX_FREQUENCY, DC_SPIKE_AVOID_BUFFER,
+ USABLE_BANDWIDTH_PERCENT);
+ }
+
+ @Override
public TunerType getTunerType()
{
- return TunerType.RAFAELMICRO_R820T;
- }
-
- @Override
- public void setSampleRateFilters( int sampleRate ) throws LibUsbException
- {
- //TODO: why is this being forced as an abstract method on sub classes?
- }
-
- @Override
- public void apply( TunerConfiguration tunerConfig ) throws SourceException
- {
- if( tunerConfig != null &&
- tunerConfig instanceof R820TTunerConfiguration )
- {
- R820TTunerConfiguration config = (R820TTunerConfiguration)tunerConfig;
-
- try
- {
- SampleRate sampleRate = config.getSampleRate();
- setSampleRate( sampleRate );
-
- double correction = config.getFrequencyCorrection();
- setFrequencyCorrection( correction );
-
- R820TGain masterGain = config.getMasterGain();
- setGain( masterGain, true );
-
- if( masterGain == R820TGain.MANUAL )
- {
- R820TMixerGain mixerGain = config.getMixerGain();
- setMixerGain( mixerGain, true );
-
- R820TLNAGain lnaGain = config.getLNAGain();
- setLNAGain( lnaGain, true );
-
- R820TVGAGain vgaGain = config.getVGAGain();
- setVGAGain( vgaGain, true );
- }
-
- try
- {
- setFrequency( config.getFrequency() );
- }
- catch( SourceException se )
- {
- //Do nothing, we couldn't set the frequency
- }
- }
- catch( UsbException e )
- {
- throw new SourceException( "R820TTunerController - usb error "
- + "while applying tuner config", e );
- }
- }
+ return TunerType.RAFAELMICRO_R820T;
}
- /**
- * Not implemented.
- */
- @Override
+ @Override
+ public void setSampleRateFilters(int sampleRate) throws LibUsbException
+ {
+ //TODO: why is this being forced as an abstract method on sub classes?
+ }
+
+ @Override
+ public void apply(TunerConfiguration tunerConfig) throws SourceException
+ {
+ if(tunerConfig != null &&
+ tunerConfig instanceof R820TTunerConfiguration)
+ {
+ R820TTunerConfiguration config = (R820TTunerConfiguration) tunerConfig;
+
+ try
+ {
+ SampleRate sampleRate = config.getSampleRate();
+ setSampleRate(sampleRate);
+
+ double correction = config.getFrequencyCorrection();
+ setFrequencyCorrection(correction);
+
+ R820TGain masterGain = config.getMasterGain();
+ setGain(masterGain, true);
+
+ if(masterGain == R820TGain.MANUAL)
+ {
+ R820TMixerGain mixerGain = config.getMixerGain();
+ setMixerGain(mixerGain, true);
+
+ R820TLNAGain lnaGain = config.getLNAGain();
+ setLNAGain(lnaGain, true);
+
+ R820TVGAGain vgaGain = config.getVGAGain();
+ setVGAGain(vgaGain, true);
+ }
+
+ try
+ {
+ setFrequency(config.getFrequency());
+ }
+ catch(SourceException se)
+ {
+ //Do nothing, we couldn't set the frequency
+ }
+ }
+ catch(UsbException e)
+ {
+ throw new SourceException("R820TTunerController - usb error "
+ + "while applying tuner config", e);
+ }
+ }
+ }
+
+ /**
+ * Not implemented.
+ */
+ @Override
public long getTunedFrequency() throws SourceException
{
- return 0;
+ return 0;
}
- /**
- * Sets the center frequency. Setting the frequency is a two-part process
- * of setting the multiplexer and then setting the Oscillator (PLL).
- */
- @Override
- public void setTunedFrequency( long frequency ) throws SourceException
+ /**
+ * Sets the center frequency. Setting the frequency is a two-part process
+ * of setting the multiplexer and then setting the Oscillator (PLL).
+ */
+ @Override
+ public void setTunedFrequency(long frequency) throws SourceException
{
- try
- {
- enableI2CRepeater( mDeviceHandle, true );
+ try
+ {
+ enableI2CRepeater(mDeviceHandle, true);
- boolean controlI2C = false;
-
- long offsetFrequency = frequency + R820T_IF_FREQUENCY;
-
- setMux( offsetFrequency, controlI2C );
-
- setPLL( offsetFrequency, controlI2C );
+ boolean controlI2C = false;
- enableI2CRepeater( mDeviceHandle, false );
- }
- catch( UsbException e )
- {
- throw new SourceException( "R820TTunerController - exception "
- + "while setting frequency [" + frequency + "] - " +
- e.getLocalizedMessage() );
- }
+ long offsetFrequency = frequency + R820T_IF_FREQUENCY;
+
+ setMux(offsetFrequency, controlI2C);
+
+ setPLL(offsetFrequency, controlI2C);
+
+ enableI2CRepeater(mDeviceHandle, false);
+ }
+ catch(UsbException e)
+ {
+ throw new SourceException("R820TTunerController - exception "
+ + "while setting frequency [" + frequency + "] - " +
+ e.getLocalizedMessage());
+ }
}
- /**
- * Overrides the same method from the RTL2832 tuner controller to apply
- * settings specific to the R820T tuner.
- */
- public void setSamplingMode( SampleMode mode ) throws LibUsbException
- {
- switch( mode )
- {
- case QUADRATURE:
- /* Set intermediate frequency to R820T IF frequency */
- setIFFrequency( R820T_IF_FREQUENCY );
+ /**
+ * Overrides the same method from the RTL2832 tuner controller to apply
+ * settings specific to the R820T tuner.
+ */
+ public void setSamplingMode(SampleMode mode) throws LibUsbException
+ {
+ switch(mode)
+ {
+ case QUADRATURE:
+ /* Set intermediate frequency to R820T IF frequency */
+ setIFFrequency(R820T_IF_FREQUENCY);
/* Enable spectrum inversion */
- writeDemodRegister( mDeviceHandle,
- Page.ONE,
- (short)0x15,
- (short)0x01,
- 1 );
+ writeDemodRegister(mDeviceHandle,
+ Page.ONE,
+ (short) 0x15,
+ (short) 0x01,
+ 1);
/* Set default i/q path */
- writeDemodRegister( mDeviceHandle,
- Page.ZERO,
- (short)0x06,
- (short)0x80,
- 1 );
- break;
- default:
- break;
-
- }
- }
+ writeDemodRegister(mDeviceHandle,
+ Page.ZERO,
+ (short) 0x06,
+ (short) 0x80,
+ 1);
+ break;
+ default:
+ break;
- /**
- * Sets the multiplexer for the desired center frequency.
- */
- private void setMux( long frequency, boolean controlI2C ) throws UsbException
- {
- FrequencyRange range = FrequencyRange.getRangeForFrequency( frequency );
+ }
+ }
+
+ /**
+ * Sets the multiplexer for the desired center frequency.
+ */
+ private void setMux(long frequency, boolean controlI2C) throws UsbException
+ {
+ FrequencyRange range = FrequencyRange.getRangeForFrequency(frequency);
/* Set open drain */
- writeR820TRegister( Register.DRAIN, range.getOpenDrain(), controlI2C );
+ writeR820TRegister(Register.DRAIN, range.getOpenDrain(), controlI2C);
/* RF_MUX, Polymux */
- writeR820TRegister( Register.RF_POLY_MUX, range.getRFMuxPolyMux(), controlI2C );
+ writeR820TRegister(Register.RF_POLY_MUX, range.getRFMuxPolyMux(), controlI2C);
/* TF Band */
- writeR820TRegister( Register.TF_BAND, range.getTFC(), controlI2C );
+ writeR820TRegister(Register.TF_BAND, range.getTFC(), controlI2C);
/* XTAL CAP & Drive */
- writeR820TRegister( Register.PLL_XTAL_CAPACITOR_AND_DRIVE,
- range.getXTALHighCap0P(), controlI2C );
+ writeR820TRegister(Register.PLL_XTAL_CAPACITOR_AND_DRIVE,
+ range.getXTALHighCap0P(), controlI2C);
/* Register 8 - what is it? */
- writeR820TRegister( Register.UNKNOWN_REGISTER_8, (byte)0x00, controlI2C );
+ writeR820TRegister(Register.UNKNOWN_REGISTER_8, (byte) 0x00, controlI2C);
/* Register 9 - what is it? */
- writeR820TRegister( Register.UNKNOWN_REGISTER_9, (byte)0x00, controlI2C );
- }
+ writeR820TRegister(Register.UNKNOWN_REGISTER_9, (byte) 0x00, controlI2C);
+ }
- /**
- * Initializes the tuner for use.
- */
- public void init() throws SourceException
- {
+ /**
+ * Initializes the tuner for use.
+ */
+ public void init() throws SourceException
+ {
/* Initialize the super class to open and claim the usb interface*/
- super.init();
-
- try
- {
- initBaseband( mDeviceHandle );
+ super.init();
- enableI2CRepeater( mDeviceHandle, true );
-
- boolean i2CRepeaterControl = false;
-
- initTuner( i2CRepeaterControl );
+ try
+ {
+ initBaseband(mDeviceHandle);
- enableI2CRepeater( mDeviceHandle, false );
- }
- catch( UsbException e )
- {
- throw new SourceException( "error during init()", e );
- }
- }
+ enableI2CRepeater(mDeviceHandle, true);
- /**
- * Initializes the tuner section.
- */
- public void initTuner( boolean controlI2C ) throws UsbException
- {
+ boolean i2CRepeaterControl = false;
+
+ initTuner(i2CRepeaterControl);
+
+ enableI2CRepeater(mDeviceHandle, false);
+ }
+ catch(UsbException e)
+ {
+ throw new SourceException("error during init()", e);
+ }
+ }
+
+ /**
+ * Initializes the tuner section.
+ */
+ public void initTuner(boolean controlI2C) throws UsbException
+ {
/* Disable zero IF mode */
- writeDemodRegister( mDeviceHandle,
- Page.ONE,
- (short)0xB1,
- (short)0x1A,
- 1 );
+ writeDemodRegister(mDeviceHandle,
+ Page.ONE,
+ (short) 0xB1,
+ (short) 0x1A,
+ 1);
/* Only enable in-phase ADC input */
- writeDemodRegister( mDeviceHandle,
- Page.ZERO,
- (short)0x08,
- (short)0x4D,
- 1 );
+ writeDemodRegister(mDeviceHandle,
+ Page.ZERO,
+ (short) 0x08,
+ (short) 0x4D,
+ 1);
/* Set intermediate frequency to R820T IF frequency (3.57 MHz) */
- setIFFrequency( R820T_IF_FREQUENCY );
+ setIFFrequency(R820T_IF_FREQUENCY);
/* Enable spectrum inversion */
- writeDemodRegister( mDeviceHandle,
- Page.ONE,
- (short)0x15,
- (short)0x01,
- 1 );
-
- initializeRegisters( controlI2C );
+ writeDemodRegister(mDeviceHandle,
+ Page.ONE,
+ (short) 0x15,
+ (short) 0x01,
+ 1);
- setTVStandard( controlI2C );
-
- systemFrequencySelect( 0, controlI2C );
- }
+ initializeRegisters(controlI2C);
- /**
- * Partially implements the r82xx_set_tv_standard() method from librtlsdr.
- * Sets standard to digital tv to support sdr operations only.
- */
- private void setTVStandard( boolean controlI2C ) throws UsbException
- {
+ setTVStandard(controlI2C);
+
+ systemFrequencySelect(0, controlI2C);
+ }
+
+ /**
+ * Partially implements the r82xx_set_tv_standard() method from librtlsdr.
+ * Sets standard to digital tv to support sdr operations only.
+ */
+ private void setTVStandard(boolean controlI2C) throws UsbException
+ {
/* Init Flag & Xtal check Result */
- writeR820TRegister( Register.XTAL_CHECK, (byte)0x00, controlI2C );
+ writeR820TRegister(Register.XTAL_CHECK, (byte) 0x00, controlI2C);
/* Set version */
- writeR820TRegister( Register.VERSION, VERSION, controlI2C );
+ writeR820TRegister(Register.VERSION, VERSION, controlI2C);
/* LT Gain Test */
- writeR820TRegister( Register.LNA_TOP, (byte)0x00, controlI2C );
+ writeR820TRegister(Register.LNA_TOP, (byte) 0x00, controlI2C);
int calibrationCode = 0;
-
- for( int x = 0; x < 2; x++ )
+
+ for(int x = 0; x < 2; x++)
{
/* Set filter cap */
- writeR820TRegister( Register.FILTER_CAPACITOR, (byte)0x6B, controlI2C );
+ writeR820TRegister(Register.FILTER_CAPACITOR, (byte) 0x6B, controlI2C);
/* Set calibration clock on */
- writeR820TRegister( Register.CALIBRATION_CLOCK, (byte)0x04, controlI2C );
+ writeR820TRegister(Register.CALIBRATION_CLOCK, (byte) 0x04, controlI2C);
/* XTAL capacitor 0pF for PLL */
- writeR820TRegister( Register.PLL_XTAL_CAPACITOR, (byte)0x00, controlI2C );
+ writeR820TRegister(Register.PLL_XTAL_CAPACITOR, (byte) 0x00, controlI2C);
- setPLL( 56000 * 1000, controlI2C );
+ setPLL(56000 * 1000, controlI2C);
/* Start trigger */
- writeR820TRegister( Register.CALIBRATION_TRIGGER, (byte)0x10, controlI2C );
+ writeR820TRegister(Register.CALIBRATION_TRIGGER, (byte) 0x10, controlI2C);
/* Stop trigger */
- writeR820TRegister( Register.CALIBRATION_TRIGGER, (byte)0x00, controlI2C );
+ writeR820TRegister(Register.CALIBRATION_TRIGGER, (byte) 0x00, controlI2C);
/* Set calibration clock off */
- writeR820TRegister( Register.CALIBRATION_CLOCK, (byte)0x00, controlI2C );
+ writeR820TRegister(Register.CALIBRATION_CLOCK, (byte) 0x00, controlI2C);
- calibrationCode = getCalibrationCode( controlI2C );
-
- if( !calibrationSuccessful( calibrationCode ) )
+ calibrationCode = getCalibrationCode(controlI2C);
+
+ if(!calibrationSuccessful(calibrationCode))
{
- mLog.error( "Calibration NOT successful - code: " +
- calibrationCode );
+ mLog.error("Calibration NOT successful - code: " +
+ calibrationCode);
}
}
- if( calibrationCode == 0x0F )
- {
- calibrationCode = 0;
- }
+ if(calibrationCode == 0x0F)
+ {
+ calibrationCode = 0;
+ }
/* Write calibration code */
- byte filt_q = 0x10;
-
- writeR820TRegister( Register.FILTER_CALIBRATION_CODE,
- (byte)( calibrationCode | filt_q ), controlI2C );
+ byte filt_q = 0x10;
+
+ writeR820TRegister(Register.FILTER_CALIBRATION_CODE,
+ (byte) (calibrationCode | filt_q), controlI2C);
/* Set BW, Filter gain & HP Corner */
- writeR820TRegister( Register.BANDWIDTH_FILTER_GAIN_HIGHPASS_FILTER_CORNER,
- (byte)0x6B, controlI2C );
+ writeR820TRegister(Register.BANDWIDTH_FILTER_GAIN_HIGHPASS_FILTER_CORNER,
+ (byte) 0x6B, controlI2C);
/* Set Image_R */
- writeR820TRegister( Register.IMAGE_REVERSE, (byte)0x00, controlI2C );
+ writeR820TRegister(Register.IMAGE_REVERSE, (byte) 0x00, controlI2C);
/* Set filter_3db, V6MHz */
- writeR820TRegister( Register.FILTER_GAIN, (byte)0x10, controlI2C );
+ writeR820TRegister(Register.FILTER_GAIN, (byte) 0x10, controlI2C);
/* Channel filter extension */
- writeR820TRegister( Register.CHANNEL_FILTER_EXTENSION, (byte)0x60, controlI2C );
+ writeR820TRegister(Register.CHANNEL_FILTER_EXTENSION, (byte) 0x60, controlI2C);
/* Loop through */
- writeR820TRegister( Register.LOOP_THROUGH, (byte)0x00, controlI2C );
+ writeR820TRegister(Register.LOOP_THROUGH, (byte) 0x00, controlI2C);
/* Loop through attenuation */
- writeR820TRegister( Register.LOOP_THROUGH_ATTENUATION, (byte)0x00, controlI2C );
+ writeR820TRegister(Register.LOOP_THROUGH_ATTENUATION, (byte) 0x00, controlI2C);
/* Filter extension widest */
- writeR820TRegister( Register.FILTER_EXTENSION_WIDEST, (byte)0x00, controlI2C );
+ writeR820TRegister(Register.FILTER_EXTENSION_WIDEST, (byte) 0x00, controlI2C);
/* RF poly filter current */
- writeR820TRegister( Register.RF_POLY_FILTER_CURRENT, (byte)0x60, controlI2C );
- }
+ writeR820TRegister(Register.RF_POLY_FILTER_CURRENT, (byte) 0x60, controlI2C);
+ }
- /**
- * Indicates if a calibration request was successful.
- */
- private boolean calibrationSuccessful( int calibrationCode )
- {
- return calibrationCode != 0 && calibrationCode != 0x0F;
- }
+ /**
+ * Indicates if a calibration request was successful.
+ */
+ private boolean calibrationSuccessful(int calibrationCode)
+ {
+ return calibrationCode != 0 && calibrationCode != 0x0F;
+ }
- /**
- * Returns the calibration code resulting from a calibration request.
- */
- private int getCalibrationCode( boolean controlI2C ) throws UsbException
- {
- return getStatusRegister( 4, controlI2C ) & 0x0F;
- }
+ /**
+ * Returns the calibration code resulting from a calibration request.
+ */
+ private int getCalibrationCode(boolean controlI2C) throws UsbException
+ {
+ return getStatusRegister(4, controlI2C) & 0x0F;
+ }
- /**
- * Sets the system IF frequency
- */
- private void systemFrequencySelect( long frequency, boolean controlI2C )
- throws UsbException
- {
+ /**
+ * Sets the system IF frequency
+ */
+ private void systemFrequencySelect(long frequency, boolean controlI2C)
+ throws UsbException
+ {
/* LNA top? */
- writeR820TRegister( Register.LNA_TOP2, (byte)0xE5, controlI2C );
-
- byte mixer_top;
- byte cp_cur;
- byte div_buf_cur;
-
- if( frequency == 506000000 ||
- frequency == 666000000 ||
- frequency == 818000000 )
- {
- mixer_top = (byte)0x14;
- cp_cur = (byte)0x28;
- div_buf_cur = (byte)0x20;
- }
- else
- {
- mixer_top = (byte)0x24;
- cp_cur = (byte)0x38;
- div_buf_cur = (byte)0x30;
- }
+ writeR820TRegister(Register.LNA_TOP2, (byte) 0xE5, controlI2C);
- writeR820TRegister( Register.MIXER_TOP, mixer_top, controlI2C );
+ byte mixer_top;
+ byte cp_cur;
+ byte div_buf_cur;
- writeR820TRegister( Register.LNA_VTH_L, (byte)0x53, controlI2C );
+ if(frequency == 506000000 ||
+ frequency == 666000000 ||
+ frequency == 818000000)
+ {
+ mixer_top = (byte) 0x14;
+ cp_cur = (byte) 0x28;
+ div_buf_cur = (byte) 0x20;
+ }
+ else
+ {
+ mixer_top = (byte) 0x24;
+ cp_cur = (byte) 0x38;
+ div_buf_cur = (byte) 0x30;
+ }
- writeR820TRegister( Register.MIXER_VTH_L, (byte)0x75, controlI2C );
+ writeR820TRegister(Register.MIXER_TOP, mixer_top, controlI2C);
+
+ writeR820TRegister(Register.LNA_VTH_L, (byte) 0x53, controlI2C);
+
+ writeR820TRegister(Register.MIXER_VTH_L, (byte) 0x75, controlI2C);
/* Air-In only for Astrometa */
- writeR820TRegister( Register.AIR_CABLE1_INPUT_SELECTOR, (byte)0x00, controlI2C );
-
- writeR820TRegister( Register.CABLE2_INPUT_SELECTOR, (byte)0x00, controlI2C );
-
- writeR820TRegister( Register.CP_CUR, cp_cur, controlI2C );
-
- writeR820TRegister( Register.DIVIDER_BUFFER_CURRENT, div_buf_cur, controlI2C );
+ writeR820TRegister(Register.AIR_CABLE1_INPUT_SELECTOR, (byte) 0x00, controlI2C);
- writeR820TRegister( Register.FILTER_CURRENT, (byte)0x40, controlI2C );
+ writeR820TRegister(Register.CABLE2_INPUT_SELECTOR, (byte) 0x00, controlI2C);
+
+ writeR820TRegister(Register.CP_CUR, cp_cur, controlI2C);
+
+ writeR820TRegister(Register.DIVIDER_BUFFER_CURRENT, div_buf_cur, controlI2C);
+
+ writeR820TRegister(Register.FILTER_CURRENT, (byte) 0x40, controlI2C);
/* if( type != TUNER_ANALOG_TV ) ... */
-
- writeR820TRegister( Register.LNA_TOP, (byte)0x00, controlI2C );
- writeR820TRegister( Register.MIXER_TOP2, (byte)0x00, controlI2C );
-
- writeR820TRegister( Register.PRE_DETECT, (byte)0x00, controlI2C );
-
- writeR820TRegister( Register.AGC_CLOCK, (byte)0x30, controlI2C );
+ writeR820TRegister(Register.LNA_TOP, (byte) 0x00, controlI2C);
- writeR820TRegister( Register.LNA_TOP, (byte)0x18, controlI2C );
+ writeR820TRegister(Register.MIXER_TOP2, (byte) 0x00, controlI2C);
- writeR820TRegister( Register.MIXER_TOP2, mixer_top, controlI2C );
+ writeR820TRegister(Register.PRE_DETECT, (byte) 0x00, controlI2C);
+
+ writeR820TRegister(Register.AGC_CLOCK, (byte) 0x30, controlI2C);
+
+ writeR820TRegister(Register.LNA_TOP, (byte) 0x18, controlI2C);
+
+ writeR820TRegister(Register.MIXER_TOP2, mixer_top, controlI2C);
/* LNA discharge current */
- writeR820TRegister( Register.LNA_DISCHARGE_CURRENT, (byte)0x14, controlI2C );
+ writeR820TRegister(Register.LNA_DISCHARGE_CURRENT, (byte) 0x14, controlI2C);
/* AGC clock 1 khz, external det1 cap 1u */
- writeR820TRegister( Register.AGC_CLOCK, (byte)0x20, controlI2C );
- }
-
- /**
- * Sets the tuner's Phase-Locked-Loop (PLL) oscillator used for frequency
- * (tuning) control
- *
- * @param frequency - desired center frequency
- * @param controlI2C - control the I2C repeater locally
- * @throws UsbException - if unable to set any of the R820T registers
- */
- private void setPLL( long frequency, boolean controlI2C ) throws UsbException
- {
+ writeR820TRegister(Register.AGC_CLOCK, (byte) 0x20, controlI2C);
+ }
+
+ /**
+ * Sets the tuner's Phase-Locked-Loop (PLL) oscillator used for frequency
+ * (tuning) control
+ *
+ * @param frequency - desired center frequency
+ * @param controlI2C - control the I2C repeater locally
+ * @throws UsbException - if unable to set any of the R820T registers
+ */
+ private void setPLL(long frequency, boolean controlI2C) throws UsbException
+ {
/* Set reference divider to 0 */
- writeR820TRegister( Register.REFERENCE_DIVIDER_2, (byte)0x00, controlI2C );
+ writeR820TRegister(Register.REFERENCE_DIVIDER_2, (byte) 0x00, controlI2C);
/* Set PLL autotune to 128kHz */
- writeR820TRegister( Register.PLL_AUTOTUNE, (byte)0x00, controlI2C );
+ writeR820TRegister(Register.PLL_AUTOTUNE, (byte) 0x00, controlI2C);
/* Set VCO current to 100 */
- writeR820TRegister( Register.VCO_CURRENT, (byte)0x80, controlI2C );
+ writeR820TRegister(Register.VCO_CURRENT, (byte) 0x80, controlI2C);
/* Set the frequency divider - adjust for vco_fine_tune status */
- FrequencyDivider divider = FrequencyDivider.fromFrequency( frequency );
+ FrequencyDivider divider = FrequencyDivider.fromFrequency(frequency);
- int statusRegister4 = getStatusRegister( 4, controlI2C );
+ int statusRegister4 = getStatusRegister(4, controlI2C);
- int vco_fine_tune = ( statusRegister4 & 0x30 ) >> 4;
-
- int div_num = divider.getDividerNumber( vco_fine_tune );
-
- writeR820TRegister( Register.DIVIDER, (byte)( div_num << 5 ), controlI2C );
+ int vco_fine_tune = (statusRegister4 & 0x30) >> 4;
+
+ int div_num = divider.getDividerNumber(vco_fine_tune);
+
+ writeR820TRegister(Register.DIVIDER, (byte) (div_num << 5), controlI2C);
/* Get the integral number for this divider and frequency */
- Integral integral = divider.getIntegral( frequency );
+ Integral integral = divider.getIntegral(frequency);
- writeR820TRegister( Register.PLL, integral.getRegisterValue(), controlI2C );
+ writeR820TRegister(Register.PLL, integral.getRegisterValue(), controlI2C);
/* Calculate the sigma-delta modulator fractional setting. If it's
* non-zero, power up the sdm and apply the fractional setting,
* otherwise turn it off */
- int sdm = divider.getSDM( integral, frequency );
+ int sdm = divider.getSDM(integral, frequency);
- if( sdm != 0 )
+ if(sdm != 0)
{
- writeR820TRegister( Register.SIGMA_DELTA_MODULATOR_POWER,
- (byte)0x00, controlI2C );
+ writeR820TRegister(Register.SIGMA_DELTA_MODULATOR_POWER,
+ (byte) 0x00, controlI2C);
- writeR820TRegister( Register.SIGMA_DELTA_MODULATOR_MSB,
- (byte)( ( sdm >> 8 ) & 0xFF ), controlI2C );
+ writeR820TRegister(Register.SIGMA_DELTA_MODULATOR_MSB,
+ (byte) ((sdm >> 8) & 0xFF), controlI2C);
- writeR820TRegister( Register.SIGMA_DELTA_MODULATOR_LSB,
- (byte)( sdm & 0xFF ), controlI2C );
+ writeR820TRegister(Register.SIGMA_DELTA_MODULATOR_LSB,
+ (byte) (sdm & 0xFF), controlI2C);
}
else
{
- writeR820TRegister( Register.SIGMA_DELTA_MODULATOR_POWER,
- (byte)0x08, controlI2C );
+ writeR820TRegister(Register.SIGMA_DELTA_MODULATOR_POWER,
+ (byte) 0x08, controlI2C);
}
/* Check to see if the PLL locked with these divider, integral and sdm
* settings */
- if( !isPLLLocked( controlI2C ) )
+ if(!isPLLLocked(controlI2C))
{
/* Increase VCO current */
- writeR820TRegister( Register.VCO_CURRENT, (byte)0x60, controlI2C );
-
- if( !isPLLLocked( controlI2C ) )
- {
- throw new UsbException( "R820T Tuner Controller - couldn't "
- + "achieve PLL lock on frequency [" + frequency + "]" );
- }
+ writeR820TRegister(Register.VCO_CURRENT, (byte) 0x60, controlI2C);
+
+ if(!isPLLLocked(controlI2C))
+ {
+ throw new UsbException("R820T Tuner Controller - couldn't "
+ + "achieve PLL lock on frequency [" + frequency + "]");
+ }
}
/* set pll autotune to 8kHz */
- writeR820TRegister( Register.PLL_AUTOTUNE_VARIANT, (byte)0x08, controlI2C );
- }
+ writeR820TRegister(Register.PLL_AUTOTUNE_VARIANT, (byte) 0x08, controlI2C);
+ }
- /**
- * Indicates if the Phase Locked Loop (PLL) oscillator is locked following
- * a change in the tuned center frequency. Checks status register 2 to see
- * if the PLL locked indicator bit is set.
- */
- private boolean isPLLLocked( boolean controlI2C ) throws UsbException
- {
- int register = getStatusRegister( 2, controlI2C );
-
- return ( register & 0x40 ) == 0x40;
- }
-
- /**
- * Writes initial starting value of registers 0x05 through 0x1F using the
- * default value initialized in the shadow register array. This method only
- * needs to be called once, upon initialization.
- * @throws UsbException
- */
- private void initializeRegisters( boolean controlI2C ) throws UsbException
- {
- for( int x = 5; x < mShadowRegister.length; x++ )
- {
- writeI2CRegister( mDeviceHandle,
- mI2CAddress,
- (byte)x,
- (byte)mShadowRegister[ x ],
- controlI2C );
- }
- }
+ /**
+ * Indicates if the Phase Locked Loop (PLL) oscillator is locked following
+ * a change in the tuned center frequency. Checks status register 2 to see
+ * if the PLL locked indicator bit is set.
+ */
+ private boolean isPLLLocked(boolean controlI2C) throws UsbException
+ {
+ int register = getStatusRegister(2, controlI2C);
- /**
- * Returns the contents of status registers 0 through 4
- */
- private int getStatusRegister( int register, boolean controlI2C ) throws UsbException
- {
- ByteBuffer buffer = ByteBuffer.allocateDirect( 5 );
-
- read( mDeviceHandle, mI2CAddress, Block.I2C, buffer );
+ return (register & 0x40) == 0x40;
+ }
- return bitReverse( buffer.get( register ) & 0xFF );
- }
-
- /**
- * Assumes value is a byte value and reverses the bits in the byte.
- */
- private static int bitReverse( int value )
- {
- return BIT_REV_LOOKUP_TABLE[ value & 0x0F ] << 4 |
- BIT_REV_LOOKUP_TABLE[ ( value & 0xF0 ) >> 4 ];
- }
+ /**
+ * Writes initial starting value of registers 0x05 through 0x1F using the
+ * default value initialized in the shadow register array. This method only
+ * needs to be called once, upon initialization.
+ *
+ * @throws UsbException
+ */
+ private void initializeRegisters(boolean controlI2C) throws UsbException
+ {
+ for(int x = 5; x < mShadowRegister.length; x++)
+ {
+ writeI2CRegister(mDeviceHandle,
+ mI2CAddress,
+ (byte) x,
+ (byte) mShadowRegister[x],
+ controlI2C);
+ }
+ }
- /**
- * Writes the byte value to the specified register, optionally controlling
- * the I2C repeater as needed.
- */
- public void writeR820TRegister( Register register,
- byte value,
- boolean controlI2C ) throws UsbException
- {
- if( register.isMasked() )
- {
- int current = mShadowRegister[ register.getRegister() ];
+ /**
+ * Returns the contents of status registers 0 through 4
+ */
+ private int getStatusRegister(int register, boolean controlI2C) throws UsbException
+ {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(5);
- value = (byte)( ( current & ~register.getMask() ) |
- ( value & register.getMask() ) );
- }
+ read(mDeviceHandle, mI2CAddress, Block.I2C, buffer);
- writeI2CRegister( mDeviceHandle, mI2CAddress,
- (byte)register.getRegister(), value, controlI2C );
+ return bitReverse(buffer.get(register) & 0xFF);
+ }
+
+ /**
+ * Assumes value is a byte value and reverses the bits in the byte.
+ */
+ private static int bitReverse(int value)
+ {
+ return BIT_REV_LOOKUP_TABLE[value & 0x0F] << 4 |
+ BIT_REV_LOOKUP_TABLE[(value & 0xF0) >> 4];
+ }
+
+ /**
+ * Writes the byte value to the specified register, optionally controlling
+ * the I2C repeater as needed.
+ */
+ public void writeR820TRegister(Register register,
+ byte value,
+ boolean controlI2C) throws UsbException
+ {
+ if(register.isMasked())
+ {
+ int current = mShadowRegister[register.getRegister()];
+
+ value = (byte) ((current & ~register.getMask()) |
+ (value & register.getMask()));
+ }
+
+ writeI2CRegister(mDeviceHandle, mI2CAddress,
+ (byte) register.getRegister(), value, controlI2C);
+
+ mShadowRegister[register.getRegister()] = value;
- mShadowRegister[ register.getRegister() ] = value;
-
// Log.info( "R820T writing register " +
// String.format( "%02X", register.getRegister() ) + " value " +
// String.format( "%02X", value ) );
- }
+ }
- /**
- * Reads the specified register, optionally controlling the I2C repeater
- */
- public int readR820TRegister( Register register, boolean controlI2C )
- throws UsbException
- {
- int value = readI2CRegister( mDeviceHandle,
- mI2CAddress,
- (byte)register.getRegister(),
- controlI2C );
-
- return value;
- }
-
- /**
- * Sets master gain by applying gain component values to LNA, Mixer and
- * VGA gain registers.
- */
- public void setGain( R820TGain gain, boolean controlI2C ) throws UsbException
- {
- setLNAGain( gain.getLNAGain(), controlI2C );
- setMixerGain( gain.getMixerGain(), controlI2C );
- setVGAGain( gain.getVGAGain(), controlI2C );
- }
-
- /**
- * Sets LNA gain
- */
- public void setLNAGain( R820TLNAGain gain, boolean controlI2C ) throws UsbException
- {
- writeR820TRegister( Register.LNA_GAIN, gain.getSetting(), controlI2C );
- }
-
- /**
- * Sets Mixer gain
- */
- public void setMixerGain( R820TMixerGain gain, boolean controlI2C ) throws UsbException
- {
- writeR820TRegister( Register.MIXER_GAIN, gain.getSetting(), controlI2C );
- }
-
- /**
- * Sets VGA gain
- */
- public void setVGAGain( R820TVGAGain gain, boolean controlI2C ) throws UsbException
- {
- writeR820TRegister( Register.VGA_GAIN, gain.getSetting(), controlI2C );
- }
-
- /**
- * R820T VGA gain settings
- */
- public enum R820TVGAGain
- {
- GAIN_0( "0", 0x00 ),
- GAIN_26( "26", 0x01 ),
- GAIN_52( "52", 0x02 ),
- GAIN_82( "82", 0x03 ),
- GAIN_124( "124", 0x04 ),
- GAIN_159( "159", 0x05 ),
- GAIN_183( "183", 0x06 ),
- GAIN_196( "196", 0x07 ),
- GAIN_210( "210", 0x08 ),
- GAIN_242( "242", 0x09 ),
- GAIN_278( "278", 0x0A ),
- GAIN_312( "312", 0x0B ),
- GAIN_347( "347", 0x0C ),
- GAIN_384( "384", 0x0D ),
- GAIN_419( "419", 0x0E ),
- GAIN_455( "455", 0x0F );
-
- private String mLabel;
- private int mSetting;
-
- private R820TVGAGain( String label, int setting )
- {
- mLabel = label;
- mSetting = setting;
- }
-
- public String toString()
- {
- return mLabel;
- }
-
- public byte getSetting()
- {
- return (byte)mSetting;
- }
- }
-
- /**
- * R820T Low Noise Amplifier gain settings
- */
- public enum R820TLNAGain
+ /**
+ * Reads the specified register, optionally controlling the I2C repeater
+ */
+ public int readR820TRegister(Register register, boolean controlI2C)
+ throws UsbException
{
- AUTOMATIC( "Automatic", 0x00 ),
- GAIN_0( "0", 0x10 ),
- GAIN_9( "9", 0x11 ),
- GAIN_21( "21", 0x12 ),
- GAIN_61( "61", 0x13 ),
- GAIN_99( "99", 0x14 ),
- GAIN_112( "112", 0x15 ),
- GAIN_143( "143", 0x16 ),
- GAIN_165( "165", 0x17 ),
- GAIN_191( "191", 0x18 ),
- GAIN_222( "222", 0x19 ),
- GAIN_248( "248", 0x1A ),
- GAIN_262( "262", 0x1B ),
- GAIN_281( "281", 0x1C ),
- GAIN_286( "286", 0x1D ),
- GAIN_321( "321", 0x1E ),
- GAIN_334( "334", 0x1F );
-
+ int value = readI2CRegister(mDeviceHandle,
+ mI2CAddress,
+ (byte) register.getRegister(),
+ controlI2C);
+
+ return value;
+ }
+
+ /**
+ * Sets master gain by applying gain component values to LNA, Mixer and
+ * VGA gain registers.
+ */
+ public void setGain(R820TGain gain, boolean controlI2C) throws UsbException
+ {
+ setLNAGain(gain.getLNAGain(), controlI2C);
+ setMixerGain(gain.getMixerGain(), controlI2C);
+ setVGAGain(gain.getVGAGain(), controlI2C);
+ }
+
+ /**
+ * Sets LNA gain
+ */
+ public void setLNAGain(R820TLNAGain gain, boolean controlI2C) throws UsbException
+ {
+ writeR820TRegister(Register.LNA_GAIN, gain.getSetting(), controlI2C);
+ }
+
+ /**
+ * Sets Mixer gain
+ */
+ public void setMixerGain(R820TMixerGain gain, boolean controlI2C) throws UsbException
+ {
+ writeR820TRegister(Register.MIXER_GAIN, gain.getSetting(), controlI2C);
+ }
+
+ /**
+ * Sets VGA gain
+ */
+ public void setVGAGain(R820TVGAGain gain, boolean controlI2C) throws UsbException
+ {
+ writeR820TRegister(Register.VGA_GAIN, gain.getSetting(), controlI2C);
+ }
+
+ /**
+ * R820T VGA gain settings
+ */
+ public enum R820TVGAGain
+ {
+ GAIN_0("0", 0x00),
+ GAIN_26("26", 0x01),
+ GAIN_52("52", 0x02),
+ GAIN_82("82", 0x03),
+ GAIN_124("124", 0x04),
+ GAIN_159("159", 0x05),
+ GAIN_183("183", 0x06),
+ GAIN_196("196", 0x07),
+ GAIN_210("210", 0x08),
+ GAIN_242("242", 0x09),
+ GAIN_278("278", 0x0A),
+ GAIN_312("312", 0x0B),
+ GAIN_347("347", 0x0C),
+ GAIN_384("384", 0x0D),
+ GAIN_419("419", 0x0E),
+ GAIN_455("455", 0x0F);
+
private String mLabel;
private int mSetting;
-
- private R820TLNAGain( String label, int setting )
+
+ private R820TVGAGain(String label, int setting)
{
mLabel = label;
mSetting = setting;
}
-
+
public String toString()
{
return mLabel;
}
-
+
public byte getSetting()
{
- return (byte)mSetting;
+ return (byte) mSetting;
+ }
+ }
+
+ /**
+ * R820T Low Noise Amplifier gain settings
+ */
+ public enum R820TLNAGain
+ {
+ AUTOMATIC("Automatic", 0x00),
+ GAIN_0("0", 0x10),
+ GAIN_9("9", 0x11),
+ GAIN_21("21", 0x12),
+ GAIN_61("61", 0x13),
+ GAIN_99("99", 0x14),
+ GAIN_112("112", 0x15),
+ GAIN_143("143", 0x16),
+ GAIN_165("165", 0x17),
+ GAIN_191("191", 0x18),
+ GAIN_222("222", 0x19),
+ GAIN_248("248", 0x1A),
+ GAIN_262("262", 0x1B),
+ GAIN_281("281", 0x1C),
+ GAIN_286("286", 0x1D),
+ GAIN_321("321", 0x1E),
+ GAIN_334("334", 0x1F);
+
+ private String mLabel;
+ private int mSetting;
+
+ private R820TLNAGain(String label, int setting)
+ {
+ mLabel = label;
+ mSetting = setting;
+ }
+
+ public String toString()
+ {
+ return mLabel;
+ }
+
+ public byte getSetting()
+ {
+ return (byte) mSetting;
}
}
@@ -761,100 +756,100 @@ public class R820TTunerController extends RTL2832TunerController
*/
public enum R820TMixerGain
{
- AUTOMATIC( "Automatic", 0x10 ),
- GAIN_0( "0", 0x00 ),
- GAIN_5( "5", 0x01 ),
- GAIN_15( "15", 0x02 ),
- GAIN_25( "25", 0x03 ),
- GAIN_44( "44", 0x04 ),
- GAIN_53( "53", 0x05 ),
- GAIN_63( "63", 0x06 ),
- GAIN_88( "88", 0x07 ),
- GAIN_105( "105", 0x08 ),
- GAIN_115( "115", 0x09 ),
- GAIN_123( "123", 0x0A ),
- GAIN_139( "139", 0x0B ),
- GAIN_152( "152", 0x0C ),
- GAIN_158( "158", 0x0D ),
- GAIN_161( "161", 0x0E ),
- GAIN_153( "153", 0x0F );
-
+ AUTOMATIC("Automatic", 0x10),
+ GAIN_0("0", 0x00),
+ GAIN_5("5", 0x01),
+ GAIN_15("15", 0x02),
+ GAIN_25("25", 0x03),
+ GAIN_44("44", 0x04),
+ GAIN_53("53", 0x05),
+ GAIN_63("63", 0x06),
+ GAIN_88("88", 0x07),
+ GAIN_105("105", 0x08),
+ GAIN_115("115", 0x09),
+ GAIN_123("123", 0x0A),
+ GAIN_139("139", 0x0B),
+ GAIN_152("152", 0x0C),
+ GAIN_158("158", 0x0D),
+ GAIN_161("161", 0x0E),
+ GAIN_153("153", 0x0F);
+
private String mLabel;
private int mSetting;
-
- private R820TMixerGain( String label, int setting )
+
+ private R820TMixerGain(String label, int setting)
{
mLabel = label;
mSetting = setting;
}
-
+
public String toString()
{
return mLabel;
}
-
+
public byte getSetting()
{
- return (byte)mSetting;
+ return (byte) mSetting;
}
}
-
+
/**
- * R820T Master gain settings
+ * R820T Master gain settings
*/
public enum R820TGain
{
- AUTOMATIC( "Automatic", R820TVGAGain.GAIN_312, R820TLNAGain.AUTOMATIC, R820TMixerGain.AUTOMATIC ),
- MANUAL( "Manual", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_248, R820TMixerGain.GAIN_123 ),
- GAIN_0( "0", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_0, R820TMixerGain.GAIN_0 ),
- GAIN_9( "9", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_9, R820TMixerGain.GAIN_0 ),
- GAIN_14( "14", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_9, R820TMixerGain.GAIN_5 ),
- GAIN_26( "26", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_21, R820TMixerGain.GAIN_5 ),
- GAIN_36( "36", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_21, R820TMixerGain.GAIN_15 ),
- GAIN_76( "76", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_61, R820TMixerGain.GAIN_15 ),
- GAIN_86( "86", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_61, R820TMixerGain.GAIN_25 ),
- GAIN_124( "124", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_99, R820TMixerGain.GAIN_25 ),
- GAIN_143( "143", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_99, R820TMixerGain.GAIN_44 ),
- GAIN_156( "156", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_112, R820TMixerGain.GAIN_44 ),
- GAIN_165( "165", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_112, R820TMixerGain.GAIN_53 ),
- GAIN_196( "196", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_143, R820TMixerGain.GAIN_53 ),
- GAIN_208( "208", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_143, R820TMixerGain.GAIN_63 ),
- GAIN_228( "228", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_165, R820TMixerGain.GAIN_63 ),
- GAIN_253( "253", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_165, R820TMixerGain.GAIN_88 ),
- GAIN_279( "279", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_191, R820TMixerGain.GAIN_88 ),
- GAIN_296( "296", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_191, R820TMixerGain.GAIN_105 ),
- GAIN_327( "327", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_222, R820TMixerGain.GAIN_105 ),
- GAIN_337( "337", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_222, R820TMixerGain.GAIN_115 ),
- GAIN_363( "363", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_248, R820TMixerGain.GAIN_115 ),
- GAIN_371( "371", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_248, R820TMixerGain.GAIN_123 ),
- GAIN_385( "385", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_262, R820TMixerGain.GAIN_123 ),
- GAIN_401( "401", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_262, R820TMixerGain.GAIN_139 ),
- GAIN_420( "420", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_281, R820TMixerGain.GAIN_139 ),
- GAIN_433( "433", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_281, R820TMixerGain.GAIN_152 ),
- GAIN_438( "438", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_286, R820TMixerGain.GAIN_152 ),
- GAIN_444( "444", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_286, R820TMixerGain.GAIN_158 ),
- GAIN_479( "479", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_321, R820TMixerGain.GAIN_158 ),
- GAIN_482( "482", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_321, R820TMixerGain.GAIN_161 ),
- GAIN_495( "495", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_334, R820TMixerGain.GAIN_161 );
-
+ AUTOMATIC("Automatic", R820TVGAGain.GAIN_312, R820TLNAGain.AUTOMATIC, R820TMixerGain.AUTOMATIC),
+ MANUAL("Manual", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_248, R820TMixerGain.GAIN_123),
+ GAIN_0("0", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_0, R820TMixerGain.GAIN_0),
+ GAIN_9("9", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_9, R820TMixerGain.GAIN_0),
+ GAIN_14("14", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_9, R820TMixerGain.GAIN_5),
+ GAIN_26("26", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_21, R820TMixerGain.GAIN_5),
+ GAIN_36("36", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_21, R820TMixerGain.GAIN_15),
+ GAIN_76("76", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_61, R820TMixerGain.GAIN_15),
+ GAIN_86("86", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_61, R820TMixerGain.GAIN_25),
+ GAIN_124("124", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_99, R820TMixerGain.GAIN_25),
+ GAIN_143("143", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_99, R820TMixerGain.GAIN_44),
+ GAIN_156("156", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_112, R820TMixerGain.GAIN_44),
+ GAIN_165("165", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_112, R820TMixerGain.GAIN_53),
+ GAIN_196("196", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_143, R820TMixerGain.GAIN_53),
+ GAIN_208("208", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_143, R820TMixerGain.GAIN_63),
+ GAIN_228("228", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_165, R820TMixerGain.GAIN_63),
+ GAIN_253("253", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_165, R820TMixerGain.GAIN_88),
+ GAIN_279("279", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_191, R820TMixerGain.GAIN_88),
+ GAIN_296("296", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_191, R820TMixerGain.GAIN_105),
+ GAIN_327("327", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_222, R820TMixerGain.GAIN_105),
+ GAIN_337("337", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_222, R820TMixerGain.GAIN_115),
+ GAIN_363("363", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_248, R820TMixerGain.GAIN_115),
+ GAIN_371("371", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_248, R820TMixerGain.GAIN_123),
+ GAIN_385("385", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_262, R820TMixerGain.GAIN_123),
+ GAIN_401("401", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_262, R820TMixerGain.GAIN_139),
+ GAIN_420("420", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_281, R820TMixerGain.GAIN_139),
+ GAIN_433("433", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_281, R820TMixerGain.GAIN_152),
+ GAIN_438("438", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_286, R820TMixerGain.GAIN_152),
+ GAIN_444("444", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_286, R820TMixerGain.GAIN_158),
+ GAIN_479("479", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_321, R820TMixerGain.GAIN_158),
+ GAIN_482("482", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_321, R820TMixerGain.GAIN_161),
+ GAIN_495("495", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_334, R820TMixerGain.GAIN_161);
+
private String mLabel;
private R820TVGAGain mVGAGain;
private R820TLNAGain mLNAGain;
private R820TMixerGain mMixerGain;
-
- private R820TGain( String label, R820TVGAGain vga, R820TLNAGain lna, R820TMixerGain mixer )
+
+ private R820TGain(String label, R820TVGAGain vga, R820TLNAGain lna, R820TMixerGain mixer)
{
mLabel = label;
mVGAGain = vga;
mLNAGain = lna;
mMixerGain = mixer;
}
-
+
public String toString()
{
return mLabel;
}
-
+
public R820TVGAGain getVGAGain()
{
return mVGAGain;
@@ -864,438 +859,438 @@ public class R820TTunerController extends RTL2832TunerController
{
return mLNAGain;
}
-
+
public R820TMixerGain getMixerGain()
{
return mMixerGain;
}
}
-
+
/**
* R820T tuner registers and register mask values
*/
public enum Register
- {
- LNA_GAIN( 0x05, 0x1F ),
- AIR_CABLE1_INPUT_SELECTOR( 0x05, 0x60 ),
- LOOP_THROUGH( 0x05, 0x80 ),
- CABLE2_INPUT_SELECTOR( 0x06, 0x08 ),
- FILTER_GAIN( 0x06, 0x30 ),
- PRE_DETECT( 0x06, 0x40 ),
- MIXER_GAIN( 0x07, 0x1F ),
- IMAGE_REVERSE( 0x07, 0x80 ),
- UNKNOWN_REGISTER_8( 0x08, 0x3F ),
- UNKNOWN_REGISTER_9( 0x09, 0x3F ),
- FILTER_CALIBRATION_CODE( 0x0A, 0x1F ),
- FILTER_CURRENT( 0x0A, 0x60 ),
- CALIBRATION_TRIGGER( 0x0B, 0x10 ),
- FILTER_CAPACITOR( 0x0B, 0x60 ),
- BANDWIDTH_FILTER_GAIN_HIGHPASS_FILTER_CORNER( 0x0B, 0xEF ),
- XTAL_CHECK( 0x0C, 0x0F ),
- VGA_GAIN( 0x0C, 0x9F ),
- LNA_VTH_L( 0x0D, 0x0 ),
- MIXER_VTH_L( 0x0E, 0x0 ),
- CALIBRATION_CLOCK( 0x0F, 0x04 ),
- FILTER_EXTENSION_WIDEST( 0x0F, 0x80 ),
- PLL_XTAL_CAPACITOR( 0x10, 0x03 ),
- UNKNOWN_REGISTER_10( 0x10, 0x04 ),
- PLL_XTAL_CAPACITOR_AND_DRIVE( 0x10, 0x0B ),
- REFERENCE_DIVIDER_2( 0x10, 0x10 ),
- CAPACITOR_SELECTOR( 0x10, 0x1B ),
- DIVIDER( 0x10, 0xE0 ),
- CP_CUR( 0x11, 0x38 ),
- SIGMA_DELTA_MODULATOR_POWER( 0x12, 0x08 ),
- VCO_CURRENT( 0x12, 0xE0 ),
- VERSION( 0x13, 0x3F ),
- PLL( 0x14, 0x0 ),
- SIGMA_DELTA_MODULATOR_LSB( 0x15, 0x0 ),
- SIGMA_DELTA_MODULATOR_MSB( 0x16, 0x0 ),
- DRAIN( 0x17, 0x08 ),
- DIVIDER_BUFFER_CURRENT( 0x17, 0x30 ),
- RF_POLY_FILTER_CURRENT( 0x19, 0x60 ),
- PLL_AUTOTUNE( 0x1A, 0x0C ),
- PLL_AUTOTUNE_VARIANT( 0x1A, 0x08 ),
- AGC_CLOCK( 0x1A, 0x30 ),
- RF_POLY_MUX( 0x1A, 0xC3 ),
- TF_BAND( 0x1B, 0x0 ),
- MIXER_TOP( 0x1C, 0xF8 ),
- MIXER_TOP2( 0X1C, 0x04 ),
- LNA_TOP( 0x1D, 0x38 ),
- LNA_TOP2( 0x1D, 0xC7 ),
- CHANNEL_FILTER_EXTENSION( 0x1E, 0x60 ),
- LNA_DISCHARGE_CURRENT( 0x1E, 0x1F ),
- LOOP_THROUGH_ATTENUATION( 0x1F, 0x80 );
+ {
+ LNA_GAIN(0x05, 0x1F),
+ AIR_CABLE1_INPUT_SELECTOR(0x05, 0x60),
+ LOOP_THROUGH(0x05, 0x80),
+ CABLE2_INPUT_SELECTOR(0x06, 0x08),
+ FILTER_GAIN(0x06, 0x30),
+ PRE_DETECT(0x06, 0x40),
+ MIXER_GAIN(0x07, 0x1F),
+ IMAGE_REVERSE(0x07, 0x80),
+ UNKNOWN_REGISTER_8(0x08, 0x3F),
+ UNKNOWN_REGISTER_9(0x09, 0x3F),
+ FILTER_CALIBRATION_CODE(0x0A, 0x1F),
+ FILTER_CURRENT(0x0A, 0x60),
+ CALIBRATION_TRIGGER(0x0B, 0x10),
+ FILTER_CAPACITOR(0x0B, 0x60),
+ BANDWIDTH_FILTER_GAIN_HIGHPASS_FILTER_CORNER(0x0B, 0xEF),
+ XTAL_CHECK(0x0C, 0x0F),
+ VGA_GAIN(0x0C, 0x9F),
+ LNA_VTH_L(0x0D, 0x0),
+ MIXER_VTH_L(0x0E, 0x0),
+ CALIBRATION_CLOCK(0x0F, 0x04),
+ FILTER_EXTENSION_WIDEST(0x0F, 0x80),
+ PLL_XTAL_CAPACITOR(0x10, 0x03),
+ UNKNOWN_REGISTER_10(0x10, 0x04),
+ PLL_XTAL_CAPACITOR_AND_DRIVE(0x10, 0x0B),
+ REFERENCE_DIVIDER_2(0x10, 0x10),
+ CAPACITOR_SELECTOR(0x10, 0x1B),
+ DIVIDER(0x10, 0xE0),
+ CP_CUR(0x11, 0x38),
+ SIGMA_DELTA_MODULATOR_POWER(0x12, 0x08),
+ VCO_CURRENT(0x12, 0xE0),
+ VERSION(0x13, 0x3F),
+ PLL(0x14, 0x0),
+ SIGMA_DELTA_MODULATOR_LSB(0x15, 0x0),
+ SIGMA_DELTA_MODULATOR_MSB(0x16, 0x0),
+ DRAIN(0x17, 0x08),
+ DIVIDER_BUFFER_CURRENT(0x17, 0x30),
+ RF_POLY_FILTER_CURRENT(0x19, 0x60),
+ PLL_AUTOTUNE(0x1A, 0x0C),
+ PLL_AUTOTUNE_VARIANT(0x1A, 0x08),
+ AGC_CLOCK(0x1A, 0x30),
+ RF_POLY_MUX(0x1A, 0xC3),
+ TF_BAND(0x1B, 0x0),
+ MIXER_TOP(0x1C, 0xF8),
+ MIXER_TOP2(0X1C, 0x04),
+ LNA_TOP(0x1D, 0x38),
+ LNA_TOP2(0x1D, 0xC7),
+ CHANNEL_FILTER_EXTENSION(0x1E, 0x60),
+ LNA_DISCHARGE_CURRENT(0x1E, 0x1F),
+ LOOP_THROUGH_ATTENUATION(0x1F, 0x80);
- private int mRegister;
- private int mMask;
-
- private Register( int register, int mask )
- {
- mRegister = register;
- mMask = mask;
- }
-
- public int getRegister()
- {
- return mRegister;
- }
-
- public byte getMask()
- {
- return (byte)mMask;
- }
-
- public boolean isMasked()
- {
- return mMask != 0;
- }
- }
-
- public enum FrequencyRange
- {
- RANGE_024( 24000000, 49999999, 0x08, 0x02, 0xDF, 0x02, 0x01 ),
- RANGE_050( 50000000, 54999999, 0x08, 0x02, 0xBE, 0x02, 0x01 ),
- RANGE_055( 55000000, 59999999, 0x08, 0x02, 0x8B, 0x02, 0x01 ),
- RANGE_060( 60000000, 64999999, 0x08, 0x02, 0x7B, 0x02, 0x01 ),
- RANGE_065( 65000000, 69999999, 0x08, 0x02, 0x69, 0x02, 0x01 ),
- RANGE_070( 70000000, 74999999, 0x08, 0x02, 0x58, 0x02, 0x01 ),
- RANGE_075( 75000000, 79999999, 0x00, 0x02, 0x44, 0x02, 0x01 ),
- RANGE_080( 80000000, 89999999, 0x00, 0x02, 0x44, 0x02, 0x01 ),
- RANGE_090( 90000000, 99999999, 0x00, 0x02, 0x34, 0x01, 0x01 ),
- RANGE_100( 100000000, 109999999, 0x00, 0x02, 0x34, 0x01, 0x01 ),
- RANGE_110( 110000000, 119999999, 0x00, 0x02, 0x24, 0x01, 0x01 ),
- RANGE_120( 120000000, 139999999, 0x00, 0x02, 0x24, 0x01, 0x01 ),
- RANGE_140( 140000000, 179999999, 0x00, 0x02, 0x14, 0x01, 0x01 ),
- RANGE_180( 180000000, 219999999, 0x00, 0x02, 0x13, 0x00, 0x00 ),
- RANGE_220( 220000000, 249999999, 0x00, 0x02, 0x13, 0x00, 0x00 ),
- RANGE_250( 250000000, 279999999, 0x00, 0x02, 0x11, 0x00, 0x00 ),
- RANGE_280( 280000000, 309999999, 0x00, 0x02, 0x00, 0x00, 0x00 ),
- RANGE_310( 310000000, 449999999, 0x00, 0x41, 0x00, 0x00, 0x00 ),
- RANGE_450( 450000000, 587999999, 0x00, 0x41, 0x00, 0x00, 0x00 ),
- RANGE_588( 588000000, 649999999, 0x00, 0x40, 0x00, 0x00, 0x00 ),
- RANGE_650( 650000000, 1766000000, 0x00, 0x40, 0x00, 0x00, 0x00 ),
- RANGE_UNK( 0, 0, 0, 0, 0, 0, 0 );
+ private int mRegister;
+ private int mMask;
- private long mMinFrequency;
- private long mMaxFrequency;
- private int mOpenDrain;
- private int mRFMux_PolyMux;
- private int mTF_c;
- private int mXtalCap20p;
- private int mXtalCap10p;
-
- private FrequencyRange( long minFrequency,
- long maxFrequency,
- int openDrain,
- int rfMuxPloy,
- int tf_c,
- int xtalCap20p,
- int xtalCap10p )
- {
- mMinFrequency = minFrequency;
- mMaxFrequency = maxFrequency;
- mOpenDrain = openDrain;
- mRFMux_PolyMux = rfMuxPloy;
- mTF_c = tf_c;
- mXtalCap20p = xtalCap20p;
- mXtalCap10p = xtalCap10p;
- }
-
- public boolean contains( long frequency )
- {
- return mMinFrequency <= frequency && frequency <= mMaxFrequency;
- }
-
- public static FrequencyRange getRangeForFrequency( long frequency )
- {
- for( FrequencyRange range: values() )
- {
- if( range.contains( frequency ) )
- {
- return range;
- }
- }
-
- return RANGE_UNK;
- }
-
- public long getMinFrequency()
- {
- return mMinFrequency;
- }
-
- public long getMaxFrequency()
- {
- return mMaxFrequency;
- }
-
- public byte getOpenDrain()
- {
- return (byte)mOpenDrain;
- }
-
- public byte getRFMuxPolyMux()
- {
- return (byte)mRFMux_PolyMux;
- }
-
- public byte getTFC()
- {
- return (byte) mTF_c;
- }
-
- public byte getXTALCap20P()
- {
- return (byte)mXtalCap20p;
- }
-
- public byte getXTALCap10P()
- {
- return (byte)mXtalCap10p;
- }
-
- public byte getXTALLowCap0P()
- {
- return (byte)0x08;
- }
+ private Register(int register, int mask)
+ {
+ mRegister = register;
+ mMask = mask;
+ }
+
+ public int getRegister()
+ {
+ return mRegister;
+ }
+
+ public byte getMask()
+ {
+ return (byte) mMask;
+ }
+
+ public boolean isMasked()
+ {
+ return mMask != 0;
+ }
+ }
+
+ public enum FrequencyRange
+ {
+ RANGE_024(24000000, 49999999, 0x08, 0x02, 0xDF, 0x02, 0x01),
+ RANGE_050(50000000, 54999999, 0x08, 0x02, 0xBE, 0x02, 0x01),
+ RANGE_055(55000000, 59999999, 0x08, 0x02, 0x8B, 0x02, 0x01),
+ RANGE_060(60000000, 64999999, 0x08, 0x02, 0x7B, 0x02, 0x01),
+ RANGE_065(65000000, 69999999, 0x08, 0x02, 0x69, 0x02, 0x01),
+ RANGE_070(70000000, 74999999, 0x08, 0x02, 0x58, 0x02, 0x01),
+ RANGE_075(75000000, 79999999, 0x00, 0x02, 0x44, 0x02, 0x01),
+ RANGE_080(80000000, 89999999, 0x00, 0x02, 0x44, 0x02, 0x01),
+ RANGE_090(90000000, 99999999, 0x00, 0x02, 0x34, 0x01, 0x01),
+ RANGE_100(100000000, 109999999, 0x00, 0x02, 0x34, 0x01, 0x01),
+ RANGE_110(110000000, 119999999, 0x00, 0x02, 0x24, 0x01, 0x01),
+ RANGE_120(120000000, 139999999, 0x00, 0x02, 0x24, 0x01, 0x01),
+ RANGE_140(140000000, 179999999, 0x00, 0x02, 0x14, 0x01, 0x01),
+ RANGE_180(180000000, 219999999, 0x00, 0x02, 0x13, 0x00, 0x00),
+ RANGE_220(220000000, 249999999, 0x00, 0x02, 0x13, 0x00, 0x00),
+ RANGE_250(250000000, 279999999, 0x00, 0x02, 0x11, 0x00, 0x00),
+ RANGE_280(280000000, 309999999, 0x00, 0x02, 0x00, 0x00, 0x00),
+ RANGE_310(310000000, 449999999, 0x00, 0x41, 0x00, 0x00, 0x00),
+ RANGE_450(450000000, 587999999, 0x00, 0x41, 0x00, 0x00, 0x00),
+ RANGE_588(588000000, 649999999, 0x00, 0x40, 0x00, 0x00, 0x00),
+ RANGE_650(650000000, 1766000000, 0x00, 0x40, 0x00, 0x00, 0x00),
+ RANGE_UNK(0, 0, 0, 0, 0, 0, 0);
+
+ private long mMinFrequency;
+ private long mMaxFrequency;
+ private int mOpenDrain;
+ private int mRFMux_PolyMux;
+ private int mTF_c;
+ private int mXtalCap20p;
+ private int mXtalCap10p;
+
+ private FrequencyRange(long minFrequency,
+ long maxFrequency,
+ int openDrain,
+ int rfMuxPloy,
+ int tf_c,
+ int xtalCap20p,
+ int xtalCap10p)
+ {
+ mMinFrequency = minFrequency;
+ mMaxFrequency = maxFrequency;
+ mOpenDrain = openDrain;
+ mRFMux_PolyMux = rfMuxPloy;
+ mTF_c = tf_c;
+ mXtalCap20p = xtalCap20p;
+ mXtalCap10p = xtalCap10p;
+ }
+
+ public boolean contains(long frequency)
+ {
+ return mMinFrequency <= frequency && frequency <= mMaxFrequency;
+ }
+
+ public static FrequencyRange getRangeForFrequency(long frequency)
+ {
+ for(FrequencyRange range : values())
+ {
+ if(range.contains(frequency))
+ {
+ return range;
+ }
+ }
+
+ return RANGE_UNK;
+ }
+
+ public long getMinFrequency()
+ {
+ return mMinFrequency;
+ }
+
+ public long getMaxFrequency()
+ {
+ return mMaxFrequency;
+ }
+
+ public byte getOpenDrain()
+ {
+ return (byte) mOpenDrain;
+ }
+
+ public byte getRFMuxPolyMux()
+ {
+ return (byte) mRFMux_PolyMux;
+ }
+
+ public byte getTFC()
+ {
+ return (byte) mTF_c;
+ }
+
+ public byte getXTALCap20P()
+ {
+ return (byte) mXtalCap20p;
+ }
+
+ public byte getXTALCap10P()
+ {
+ return (byte) mXtalCap10p;
+ }
+
+ public byte getXTALLowCap0P()
+ {
+ return (byte) 0x08;
+ }
+
+ public byte getXTALHighCap0P()
+ {
+ return (byte) 0x00;
+ }
+ }
- public byte getXTALHighCap0P()
- {
- return (byte)0x00;
- }
- }
-
/**
* Frequency Divider Ranges
- *
+ *
* Actual Tuned Frequency Ranges (after subtracting IF = 3.57 MHz )
- *
- * Divider 0: 860.43 to 1782.03 MHz
- * Divider 1: 428.43 to 889.23 MHz
- * Divider 2: 212.43 to 457.23 MHz
- * Divider 3: 104.43 to 219.63 MHz
- * Divider 4: 50.43 to 108.03 MHz
- * Divider 5: 23.43 to 52.23 MHz
- * Divider 6: 9.93 to 24.33 MHz
- * Divider 7: 3.18 to 10.38 MHz
+ *
+ * Divider 0: 860.43 to 1782.03 MHz
+ * Divider 1: 428.43 to 889.23 MHz
+ * Divider 2: 212.43 to 457.23 MHz
+ * Divider 3: 104.43 to 219.63 MHz
+ * Divider 4: 50.43 to 108.03 MHz
+ * Divider 5: 23.43 to 52.23 MHz
+ * Divider 6: 9.93 to 24.33 MHz
+ * Divider 7: 3.18 to 10.38 MHz
*/
- public enum FrequencyDivider
- {
- DIVIDER_0( 0, 2, 864000000, 1785600000, 0x00, 28800000 ),
- DIVIDER_1( 1, 4, 432000000, 892800000, 0x20, 14400000 ),
- DIVIDER_2( 2, 8, 216000000, 460800000, 0x40, 7200000 ),
- DIVIDER_3( 3, 16, 108000000, 223200000, 0x60, 3600000 ),
- DIVIDER_4( 4, 32, 54000000, 111600000, 0x80, 1800000 ),
- DIVIDER_5( 5, 64, 27000000, 55800000, 0xA0, 900000 ),
- DIVIDER_6( 6, 128, 13500000, 27900000, 0xC0, 450000 ),
- DIVIDER_7( 7, 256, 6750000, 13950000, 0xE0, 225000 );
-
- private int mDividerNumber;
- private int mMixerDivider;
- private long mMinimumFrequency;
- private long mMaximumFrequency;
- private int mRegisterSetting;
- private int mIntegralValue;
- private static final int mVCOPowerReference = 2;
-
- private FrequencyDivider( int dividerNumber,
- int mixerDivider,
- long minimumFrequency,
- long maximumFrequency,
- int registerSetting,
- int integralValue )
- {
- mDividerNumber = dividerNumber;
- mMixerDivider = mixerDivider;
- mMinimumFrequency = minimumFrequency;
- mMaximumFrequency = maximumFrequency;
- mRegisterSetting = registerSetting;
- mIntegralValue = integralValue;
- }
+ public enum FrequencyDivider
+ {
+ DIVIDER_0(0, 2, 864000000, 1785600000, 0x00, 28800000),
+ DIVIDER_1(1, 4, 432000000, 892800000, 0x20, 14400000),
+ DIVIDER_2(2, 8, 216000000, 460800000, 0x40, 7200000),
+ DIVIDER_3(3, 16, 108000000, 223200000, 0x60, 3600000),
+ DIVIDER_4(4, 32, 54000000, 111600000, 0x80, 1800000),
+ DIVIDER_5(5, 64, 27000000, 55800000, 0xA0, 900000),
+ DIVIDER_6(6, 128, 13500000, 27900000, 0xC0, 450000),
+ DIVIDER_7(7, 256, 6750000, 13950000, 0xE0, 225000);
- public int getDividerNumber( int vcoFineTune )
- {
- if( vcoFineTune == mVCOPowerReference )
- {
- return mDividerNumber;
- }
- else if( vcoFineTune < mVCOPowerReference )
- {
- return mDividerNumber - 1;
- }
- else if( vcoFineTune > mVCOPowerReference )
- {
- return mDividerNumber + 1;
- }
-
- return mDividerNumber;
- }
-
- public int getMixerDivider()
- {
- return mMixerDivider;
- }
-
- public long getMinimumFrequency()
- {
- return mMinimumFrequency;
- }
-
- public long getMaximumFrequency()
- {
- return mMaximumFrequency;
- }
-
- public byte getDividerRegisterSetting()
- {
- return (byte)mRegisterSetting;
- }
-
- public boolean contains( long frequency )
- {
- return mMinimumFrequency <= frequency &&
- frequency <= mMaximumFrequency;
- }
+ private int mDividerNumber;
+ private int mMixerDivider;
+ private long mMinimumFrequency;
+ private long mMaximumFrequency;
+ private int mRegisterSetting;
+ private int mIntegralValue;
+ private static final int mVCOPowerReference = 2;
- /**
- * Returns the correct frequency divider for the specified frequency,
- * or returns divider #5, if the frequency is outside of the specified
- * frequency ranges.
- * @param frequency - desired frequency
- * @return - FrequencyDivider to use for the specified frequency
- */
- public static FrequencyDivider fromFrequency( long frequency )
- {
- for( FrequencyDivider divider: FrequencyDivider.values() )
- {
- if( divider.contains( frequency ) )
- {
- return divider;
- }
- }
-
- return FrequencyDivider.DIVIDER_5;
- }
+ private FrequencyDivider(int dividerNumber,
+ int mixerDivider,
+ long minimumFrequency,
+ long maximumFrequency,
+ int registerSetting,
+ int integralValue)
+ {
+ mDividerNumber = dividerNumber;
+ mMixerDivider = mixerDivider;
+ mMinimumFrequency = minimumFrequency;
+ mMaximumFrequency = maximumFrequency;
+ mRegisterSetting = registerSetting;
+ mIntegralValue = integralValue;
+ }
- /**
- * Returns the integral to use for this frequency and divider
- */
- public Integral getIntegral( long frequency )
- {
- if( contains( frequency ) )
- {
- int delta = (int)( frequency - mMinimumFrequency );
+ public int getDividerNumber(int vcoFineTune)
+ {
+ if(vcoFineTune == mVCOPowerReference)
+ {
+ return mDividerNumber;
+ }
+ else if(vcoFineTune < mVCOPowerReference)
+ {
+ return mDividerNumber - 1;
+ }
+ else if(vcoFineTune > mVCOPowerReference)
+ {
+ return mDividerNumber + 1;
+ }
- int integral = (int)( (double)delta / (double)mIntegralValue );
+ return mDividerNumber;
+ }
- return Integral.fromValue( integral );
- }
-
- throw new IllegalArgumentException( "PLL frequency [" + frequency +
- "] is not valid for this frequency divider " + this.toString() );
- }
+ public int getMixerDivider()
+ {
+ return mMixerDivider;
+ }
- /**
- * Calculates the 16-bit value of the sigma-delta modulator setting
- * which represents the fractional portion of the requested frequency
- * that is left over after subtracting the divider minimum frequency
- * and the integral frequency units. That residual value is divided
- * by the integral unit value to derive a 16-bit fractional value,
- * returned as an integer
- */
- public int getSDM( Integral integral, long frequency )
- {
- if( contains( frequency ) )
- {
- int delta = (int)( frequency - mMinimumFrequency -
- ( integral.getNumber() * mIntegralValue ) );
+ public long getMinimumFrequency()
+ {
+ return mMinimumFrequency;
+ }
- double fractional = (double)delta / (double)mIntegralValue;
-
- //Left shift the double value 16 bits and truncate to an integer
- return (int)( fractional * 0x10000 ) & 0xFFFF;
- }
+ public long getMaximumFrequency()
+ {
+ return mMaximumFrequency;
+ }
- return 0;
- }
- }
+ public byte getDividerRegisterSetting()
+ {
+ return (byte) mRegisterSetting;
+ }
- /**
- * PLL Integral values. Each value represents one unit of the divided
- * crystal frequency as follows:
- *
- * Divider Value
- * 64 I * 0.9 MHz
- * 32 I * 1.8 MHz
- * 16 I * 3.6 MHz
- * 8 I * 7.2 MHz
- * 4 I * 14.4 MHz
- * 2 I * 28.8 MHz
- *
- */
- public enum Integral
- {
- I00( 0, 0x44 ),
- I01( 1, 0x84 ),
- I02( 2, 0xC4 ),
- I03( 3, 0x05 ),
- I04( 4, 0x45 ),
- I05( 5, 0x85 ),
- I06( 6, 0xC5 ),
- I07( 7, 0x06 ),
- I08( 8, 0x46 ),
- I09( 9, 0x86 ),
- I10( 10, 0xC6 ),
- I11( 11, 0x07 ),
- I12( 12, 0x47 ),
- I13( 13, 0x87 ),
- I14( 14, 0xC7 ),
- I15( 15, 0x08 ),
- I16( 16, 0x48 ),
- I17( 17, 0x88 ),
- I18( 18, 0xC8 ),
- I19( 19, 0x09 ),
- I20( 20, 0x49 ),
- I21( 21, 0x89 ),
- I22( 22, 0xC9 ),
- I23( 23, 0x0A ),
- I24( 24, 0x4A ),
- I25( 25, 0x8A ),
- I26( 26, 0xCA ),
- I27( 27, 0x0B ),
- I28( 28, 0x4B ),
- I29( 29, 0x8B ),
- I30( 30, 0xCB ),
- I31( 31, 0x0C );
+ public boolean contains(long frequency)
+ {
+ return mMinimumFrequency <= frequency &&
+ frequency <= mMaximumFrequency;
+ }
- private int mNumber;
- private int mRegister;
-
- private Integral( int number, int register )
- {
- mNumber = number;
- mRegister = register;
- }
-
- public int getNumber()
- {
- return mNumber;
- }
-
- public byte getRegisterValue()
- {
- return (byte)mRegister;
- }
-
- public static Integral fromValue( int value )
- {
- if( 0 <= value && value <= 31 )
- {
- return Integral.values()[ value ];
- }
-
- throw new IllegalArgumentException( "PLL integral value [" + value +
- "] must be in the range 0 - 31");
- }
- }
+ /**
+ * Returns the correct frequency divider for the specified frequency,
+ * or returns divider #5, if the frequency is outside of the specified
+ * frequency ranges.
+ *
+ * @param frequency - desired frequency
+ * @return - FrequencyDivider to use for the specified frequency
+ */
+ public static FrequencyDivider fromFrequency(long frequency)
+ {
+ for(FrequencyDivider divider : FrequencyDivider.values())
+ {
+ if(divider.contains(frequency))
+ {
+ return divider;
+ }
+ }
+
+ return FrequencyDivider.DIVIDER_5;
+ }
+
+ /**
+ * Returns the integral to use for this frequency and divider
+ */
+ public Integral getIntegral(long frequency)
+ {
+ if(contains(frequency))
+ {
+ int delta = (int) (frequency - mMinimumFrequency);
+
+ int integral = (int) ((double) delta / (double) mIntegralValue);
+
+ return Integral.fromValue(integral);
+ }
+
+ throw new IllegalArgumentException("PLL frequency [" + frequency +
+ "] is not valid for this frequency divider " + this.toString());
+ }
+
+ /**
+ * Calculates the 16-bit value of the sigma-delta modulator setting
+ * which represents the fractional portion of the requested frequency
+ * that is left over after subtracting the divider minimum frequency
+ * and the integral frequency units. That residual value is divided
+ * by the integral unit value to derive a 16-bit fractional value,
+ * returned as an integer
+ */
+ public int getSDM(Integral integral, long frequency)
+ {
+ if(contains(frequency))
+ {
+ int delta = (int) (frequency - mMinimumFrequency -
+ (integral.getNumber() * mIntegralValue));
+
+ double fractional = (double) delta / (double) mIntegralValue;
+
+ //Left shift the double value 16 bits and truncate to an integer
+ return (int) (fractional * 0x10000) & 0xFFFF;
+ }
+
+ return 0;
+ }
+ }
+
+ /**
+ * PLL Integral values. Each value represents one unit of the divided
+ * crystal frequency as follows:
+ *
+ * Divider Value
+ * 64 I * 0.9 MHz
+ * 32 I * 1.8 MHz
+ * 16 I * 3.6 MHz
+ * 8 I * 7.2 MHz
+ * 4 I * 14.4 MHz
+ * 2 I * 28.8 MHz
+ */
+ public enum Integral
+ {
+ I00(0, 0x44),
+ I01(1, 0x84),
+ I02(2, 0xC4),
+ I03(3, 0x05),
+ I04(4, 0x45),
+ I05(5, 0x85),
+ I06(6, 0xC5),
+ I07(7, 0x06),
+ I08(8, 0x46),
+ I09(9, 0x86),
+ I10(10, 0xC6),
+ I11(11, 0x07),
+ I12(12, 0x47),
+ I13(13, 0x87),
+ I14(14, 0xC7),
+ I15(15, 0x08),
+ I16(16, 0x48),
+ I17(17, 0x88),
+ I18(18, 0xC8),
+ I19(19, 0x09),
+ I20(20, 0x49),
+ I21(21, 0x89),
+ I22(22, 0xC9),
+ I23(23, 0x0A),
+ I24(24, 0x4A),
+ I25(25, 0x8A),
+ I26(26, 0xCA),
+ I27(27, 0x0B),
+ I28(28, 0x4B),
+ I29(29, 0x8B),
+ I30(30, 0xCB),
+ I31(31, 0x0C);
+
+ private int mNumber;
+ private int mRegister;
+
+ private Integral(int number, int register)
+ {
+ mNumber = number;
+ mRegister = register;
+ }
+
+ public int getNumber()
+ {
+ return mNumber;
+ }
+
+ public byte getRegisterValue()
+ {
+ return (byte) mRegister;
+ }
+
+ public static Integral fromValue(int value)
+ {
+ if(0 <= value && value <= 31)
+ {
+ return Integral.values()[value];
+ }
+
+ throw new IllegalArgumentException("PLL integral value [" + value +
+ "] must be in the range 0 - 31");
+ }
+ }
}
diff --git a/src/spectrum/DFTProcessor.java b/src/spectrum/DFTProcessor.java
index 68611fdd..795c3f2b 100644
--- a/src/spectrum/DFTProcessor.java
+++ b/src/spectrum/DFTProcessor.java
@@ -18,7 +18,6 @@
******************************************************************************/
package spectrum;
-import controller.NamingThreadFactory;
import dsp.filter.Window;
import dsp.filter.Window.WindowType;
import org.jtransforms.fft.FloatFFT_1D;
@@ -32,14 +31,14 @@ import sample.complex.ComplexBuffer;
import source.tuner.frequency.FrequencyChangeEvent;
import source.tuner.frequency.IFrequencyChangeProcessor;
import spectrum.converter.DFTResultsConverter;
+import util.ThreadPool;
import java.util.Arrays;
import java.util.Iterator;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -60,8 +59,7 @@ public class DFTProcessor implements Listener, IFrequencyChangePr
//so we set it at 12.
private BlockingQueue mQueue = new ArrayBlockingQueue<>(12);
- private ScheduledExecutorService mScheduler = Executors
- .newScheduledThreadPool(1, new NamingThreadFactory("spectrum dft processor"));
+ private ScheduledFuture> mProcessorTaskHandle;
public static final String FRAME_RATE_PROPERTY = "spectral.display.frame.rate";
@@ -184,38 +182,20 @@ public class DFTProcessor implements Listener, IFrequencyChangePr
public void start()
{
- /**
- * Reset the scheduler
- */
- mScheduler = Executors.newScheduledThreadPool(1, new NamingThreadFactory("spectrum dft"));
-
- /**
- * Schedule the DFT to run calculations at a fixed rate
- */
+ //Schedule the DFT to run calculations at a fixed rate
int initialDelay = 0;
int period = (int) (1000 / mFrameRate);
- TimeUnit unit = TimeUnit.MILLISECONDS;
- mScheduler.scheduleAtFixedRate(new DFTCalculationTask(),
- initialDelay, period, unit);
+ mProcessorTaskHandle = ThreadPool.SCHEDULED.scheduleAtFixedRate(new DFTCalculationTask(), initialDelay, period,
+ TimeUnit.MILLISECONDS);
}
public void stop()
{
- /**
- * Shutdown the scheduler and clear out any remaining tasks
- */
- try
+ //Cancel running DFT calculation task
+ if(mProcessorTaskHandle != null)
{
- mScheduler.shutdown();
-
- mScheduler.awaitTermination(100, TimeUnit.MILLISECONDS);
- }
- catch(InterruptedException e)
- {
- /* Do nothing ... we're shutting down */
-// mLog.error( "DFTProcessor - exception while awaiting shutdown of "
-// + "calculation scheduler for reset", e );
+ mProcessorTaskHandle.cancel(true);
}
}
diff --git a/src/util/ThreadPool.java b/src/util/ThreadPool.java
new file mode 100644
index 00000000..5b8f4ebf
--- /dev/null
+++ b/src/util/ThreadPool.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2017 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 util;
+
+import controller.NamingThreadFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+public class ThreadPool
+{
+ private final static Logger mLog = LoggerFactory.getLogger(ThreadPool.class);
+
+ private static int CORES = Runtime.getRuntime().availableProcessors();
+ public static ScheduledExecutorService SCHEDULED;
+
+ static
+ {
+ //Create a scheduled thread pool sized according to the available processors/cores, minimum 2
+ CORES = (CORES < 2 ? 2 : CORES);
+
+ SCHEDULED = Executors.newScheduledThreadPool(CORES, new NamingThreadFactory("sdrtrunk"));
+ }
+
+ /**
+ * Application-wide shared thread pools and scheduled executor service.
+ */
+ public ThreadPool()
+ {
+ }
+
+ public static void logSettings()
+ {
+ mLog.info("Application thread pool created with [" + CORES + "] threads");
+ }
+}