mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
2513 lines
73 KiB
Java
2513 lines
73 KiB
Java
/*******************************************************************************
|
|
* SDR Trunk
|
|
* Copyright (C) 2014 Dennis Sheirer
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
******************************************************************************/
|
|
package source.tuner.rtl.e4k;
|
|
|
|
import 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 source.SourceException;
|
|
import source.tuner.TunerType;
|
|
import source.tuner.configuration.TunerConfiguration;
|
|
import source.tuner.rtl.RTL2832TunerController;
|
|
|
|
import javax.usb.UsbException;
|
|
import java.util.Arrays;
|
|
|
|
public class E4KTunerController extends RTL2832TunerController
|
|
{
|
|
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;
|
|
|
|
/* 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 byte SYNTH7_3PHASE_EN = (byte) 0x08;
|
|
|
|
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 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;
|
|
}
|
|
|
|
@Override
|
|
public void apply(TunerConfiguration config) throws SourceException
|
|
{
|
|
if(config != null && config instanceof E4KTunerConfiguration)
|
|
{
|
|
E4KTunerConfiguration e4kConfig = (E4KTunerConfiguration) config;
|
|
|
|
try
|
|
{
|
|
SampleRate sampleRate = e4kConfig.getSampleRate();
|
|
setSampleRate(sampleRate);
|
|
|
|
double correction = e4kConfig.getFrequencyCorrection();
|
|
getFrequencyController().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
|
|
{
|
|
getFrequencyController().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);
|
|
|
|
if(result != LibUsb.SUCCESS)
|
|
{
|
|
mDeviceHandle = null;
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
initBaseband(mDeviceHandle);
|
|
|
|
enableI2CRepeater(mDeviceHandle, true);
|
|
|
|
boolean i2CRepeaterControl = false;
|
|
|
|
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);
|
|
}
|
|
|
|
String deviceName = getTunerType().getLabel() + " " + getUniqueID();
|
|
|
|
mUSBTransferProcessor = new RTL2832USBTransferProcessor(deviceName, mDeviceHandle, mSampleAdapter,
|
|
USB_TRANSFER_BUFFER_SIZE);
|
|
}
|
|
|
|
/**
|
|
* 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();
|
|
|
|
if(!i2CRepeaterEnabled)
|
|
{
|
|
enableI2CRepeater(mDeviceHandle, true);
|
|
}
|
|
|
|
boolean controlI2CRepeater = false;
|
|
|
|
MixerFilter mixer = MixerFilter.getFilter(bandwidth);
|
|
setMixerFilter(mixer, controlI2CRepeater);
|
|
|
|
ChannelFilter channel = ChannelFilter.getFilter(bandwidth);
|
|
setChannelFilter(channel, controlI2CRepeater);
|
|
|
|
RCFilter rc = RCFilter.getFilter(bandwidth);
|
|
setRCFilter(rc, controlI2CRepeater);
|
|
|
|
if(!i2CRepeaterEnabled)
|
|
{
|
|
enableI2CRepeater(mDeviceHandle, false);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public long getTunedFrequency() throws SourceException
|
|
{
|
|
try
|
|
{
|
|
/* Determine repeater state so we can restore it when done */
|
|
boolean i2CRepeaterEnabled = isI2CRepeaterEnabled();
|
|
|
|
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);
|
|
|
|
int x = (Integer.rotateLeft(xHigh, 8)) | xLow;
|
|
|
|
int pllSetting = readE4KRegister(Register.SYNTH7, controlI2CRepeater);
|
|
PLL pll = PLL.fromSetting(pllSetting);
|
|
|
|
/* Return the repeater to its previous state */
|
|
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);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setTunedFrequency(long frequency) throws SourceException
|
|
{
|
|
/* Get the phase locked loop setting */
|
|
PLL pll = PLL.fromFrequency(frequency);
|
|
|
|
/* Z is an integer representing the number of scaled oscillator frequency
|
|
* increments the multiplied frequency. */
|
|
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
|
|
* frequency. */
|
|
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);
|
|
|
|
/* 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 < getFrequencyController().getMinimumFrequency())
|
|
{
|
|
x++;
|
|
actualFrequency = calculateActualFrequency(pll, z, x);
|
|
}
|
|
|
|
/* Apply the actual frequency */
|
|
try
|
|
{
|
|
enableI2CRepeater(mDeviceHandle, true);
|
|
|
|
boolean controlI2CRepeater = false;
|
|
|
|
/* Write the PLL setting */
|
|
writeE4KRegister(Register.SYNTH7, pll.getIndex(), controlI2CRepeater);
|
|
|
|
/* Write z (integral) value */
|
|
writeE4KRegister(Register.SYNTH3, z, controlI2CRepeater);
|
|
|
|
/* Write the x (fractional) value high-order byte to synth4 register */
|
|
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);
|
|
|
|
/* Set the band for the new frequency */
|
|
setBand(actualFrequency, controlI2CRepeater);
|
|
|
|
/* Set the filter */
|
|
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);
|
|
}
|
|
}
|
|
|
|
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));
|
|
|
|
return whole + fractional;
|
|
}
|
|
|
|
public void initTuner(boolean controlI2CRepeater) throws UsbException
|
|
{
|
|
if(controlI2CRepeater)
|
|
{
|
|
enableI2CRepeater(mDeviceHandle, true);
|
|
}
|
|
|
|
boolean i2CRepeaterControl = false;
|
|
|
|
/* Perform dummy read */
|
|
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);
|
|
|
|
/* Configure clock input */
|
|
writeE4KRegister(Register.CLK_INP, (byte) 0x00, i2CRepeaterControl);
|
|
|
|
/* Disable clock output */
|
|
writeE4KRegister(Register.REF_CLK, (byte) 0x00, i2CRepeaterControl);
|
|
writeE4KRegister(Register.CLKOUT_PWDN, (byte) 0x96, i2CRepeaterControl);
|
|
|
|
/* Magic Init */
|
|
magicInit(i2CRepeaterControl);
|
|
|
|
// /* Set common mode voltage a bit higher for more margin - 850 mv */
|
|
// 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
|
|
|
|
//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);
|
|
|
|
|
|
// /* Enable enhance gain */
|
|
// setEnhanceGain( EnhanceGain.GAIN_5, i2CRepeaterControl );
|
|
//
|
|
// /* Enable automatic IF gain mode switching */
|
|
// 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);
|
|
|
|
// /* 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);
|
|
}
|
|
|
|
/* 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);
|
|
|
|
/* Set Mixer gain to manual using current auto Mixer gain setting */
|
|
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);
|
|
|
|
/* 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())
|
|
{
|
|
/* Set mixer and stage1 gain values */
|
|
setMixerGain(combo.getMixerGain(), i2CRepeaterControl);
|
|
setIFStage1Gain(combo.getIFStage1Gain(), i2CRepeaterControl);
|
|
|
|
/* Turn on the DC range detector */
|
|
setDCRangeDetectorEnabled(true, i2CRepeaterControl);
|
|
|
|
/* Calibrate the DC value */
|
|
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);
|
|
|
|
/* Write the offset and range values to the lookup table */
|
|
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);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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));
|
|
}
|
|
|
|
/**
|
|
* 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);
|
|
|
|
/* 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);
|
|
|
|
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);
|
|
|
|
if(controlI2CRepeater)
|
|
{
|
|
enableI2CRepeater(mDeviceHandle, false);
|
|
}
|
|
}
|
|
|
|
private void setRFFilter(long frequency,
|
|
boolean controlI2CRepeater) throws UsbException
|
|
{
|
|
RFFilter filter = RFFilter.fromFrequency(frequency);
|
|
|
|
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
|
|
* 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
|
|
{
|
|
if(gain != E4KGain.MANUAL)
|
|
{
|
|
if(controlI2CRepeater)
|
|
{
|
|
enableI2CRepeater(mDeviceHandle, true);
|
|
}
|
|
|
|
boolean i2CRepeaterControl = 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);
|
|
}
|
|
|
|
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 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);
|
|
}
|
|
|
|
|
|
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 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;
|
|
}
|
|
}
|
|
|
|
//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;
|
|
}
|
|
|
|
/**
|
|
* 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();
|
|
|
|
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();
|
|
|
|
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();
|
|
|
|
for(ChannelFilter filter : values())
|
|
{
|
|
if(value == filter.getValue())
|
|
{
|
|
return filter;
|
|
}
|
|
}
|
|
|
|
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(E4KLNAGain setting : values())
|
|
{
|
|
if(value == setting.getValue())
|
|
{
|
|
return setting;
|
|
}
|
|
}
|
|
|
|
throw new IllegalArgumentException("E4KTunerController"
|
|
+ " - unrecognized LNA Gain value [" +
|
|
value + "]");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
public static E4KEnhanceGain fromRegisterValue(int registerValue)
|
|
{
|
|
int value = registerValue & getMask();
|
|
|
|
for(E4KEnhanceGain setting : values())
|
|
{
|
|
if(value == setting.getValue())
|
|
{
|
|
return setting;
|
|
}
|
|
}
|
|
|
|
throw new IllegalArgumentException("E4KTunerController"
|
|
+ " - unrecognized Enhance Gain value [" +
|
|
value + "]");
|
|
}
|
|
}
|
|
|
|
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();
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|