Skip to content

Commit

Permalink
#1455 airspy discovery WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Dennis Sheirer committed Mar 20, 2023
1 parent 5096da8 commit 369c429
Show file tree
Hide file tree
Showing 11 changed files with 1,006 additions and 48 deletions.
@@ -0,0 +1,131 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2023 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/

package io.github.dsheirer.buffer.airspy.hf;

import io.github.dsheirer.buffer.INativeBuffer;
import io.github.dsheirer.sample.complex.ComplexSamples;
import io.github.dsheirer.sample.complex.InterleavedComplexSamples;
import java.util.Iterator;

/**
* Native buffer implementation for Airspy HF+ & Discovery tuners.
*/
public class AirspyHfNativeBuffer implements INativeBuffer
{
private static final float SCALE = 1.0f / 32768.0f;
private long mTimestamp;
private short[] mInterleavedSamples;

/**
* Constructs an instance.
* @param timestamp of the first sample of the buffer
* @param interleavedSamples pairs of 16-bit complex samples.
*/
public AirspyHfNativeBuffer(long timestamp, short[] interleavedSamples)
{
mTimestamp = timestamp;
mInterleavedSamples = interleavedSamples;
}

@Override
public Iterator<ComplexSamples> iterator()
{
return new IteratorComplexSamples();
}

@Override
public Iterator<InterleavedComplexSamples> iteratorInterleaved()
{
return new IteratorInterleaved();
}

@Override
public int sampleCount()
{
return mInterleavedSamples.length / 2;
}

@Override
public long getTimestamp()
{
return mTimestamp;
}

/**
* Scalar implementation of complex samples buffer iterator
*/
public class IteratorComplexSamples implements Iterator<ComplexSamples>
{
private boolean mHasNext = true;

@Override
public boolean hasNext()
{
return mHasNext;
}

@Override
public ComplexSamples next()
{
float[] i = new float[mInterleavedSamples.length / 2];
float[] q = new float[mInterleavedSamples.length / 2];

for(int x = 0; x < mInterleavedSamples.length; x += 2)
{
int index = mInterleavedSamples.length / 2;
i[index] = mInterleavedSamples[x] * SCALE;
q[index] = mInterleavedSamples[x + 1] * SCALE;
}

mHasNext = false;

return new ComplexSamples(i, q, mTimestamp);
}
}

/**
* Scalar implementation of interleaved sample buffer iterator.
*/
public class IteratorInterleaved implements Iterator<InterleavedComplexSamples>
{
private boolean mHasNext = true;

@Override
public boolean hasNext()
{
return mHasNext;
}

@Override
public InterleavedComplexSamples next()
{
float[] samples = new float[mInterleavedSamples.length];

for(int x = 0; x < mInterleavedSamples.length; x++)
{
samples[x] = mInterleavedSamples[x] * SCALE;
}

mHasNext = false;

return new InterleavedComplexSamples(samples, mTimestamp);
}
}
}
@@ -0,0 +1,50 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2023 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/

package io.github.dsheirer.buffer.airspy.hf;

import io.github.dsheirer.buffer.AbstractNativeBufferFactory;
import io.github.dsheirer.buffer.INativeBuffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;

/**
* Airspy HF+ native buffer factory.
*
* Note: the tuner provides 1024 samples in each transfer where samples are 16-bit interleaved complex.
*/
public class AirspyHfNativeBufferFactory extends AbstractNativeBufferFactory
{
/**
* Constructs an instance
*/
public AirspyHfNativeBufferFactory()
{
}

@Override
public INativeBuffer getBuffer(ByteBuffer samples, long timestamp)
{
ShortBuffer shortBuffer = samples.order(ByteOrder.LITTLE_ENDIAN).asShortBuffer();
short[] converted = new short[shortBuffer.capacity() / 2];
shortBuffer.get(converted);
return new AirspyHfNativeBuffer(timestamp, converted);
}
}
Expand Up @@ -31,6 +31,7 @@
import io.github.dsheirer.source.tuner.airspy.hf.AirspyHfTuner;
import io.github.dsheirer.source.tuner.airspy.hf.AirspyHfTunerConfiguration;
import io.github.dsheirer.source.tuner.airspy.hf.AirspyHfTunerController;
import io.github.dsheirer.source.tuner.airspy.hf.AirspyHfTunerEditor;
import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
import io.github.dsheirer.source.tuner.fcd.FCDTuner;
import io.github.dsheirer.source.tuner.fcd.proV1.FCD1TunerConfiguration;
Expand Down Expand Up @@ -412,6 +413,8 @@ public static TunerEditor getEditor(UserPreferences userPreferences, DiscoveredT
{
case AIRSPY:
return new AirspyTunerEditor(userPreferences, tunerManager, discoveredTuner);
case AIRSPY_HF:
return new AirspyHfTunerEditor(userPreferences, tunerManager, discoveredTuner);
case FUNCUBE_DONGLE_PRO:
return new FCD1TunerEditor(userPreferences, tunerManager, discoveredTuner);
case FUNCUBE_DONGLE_PRO_PLUS:
Expand Down
@@ -1,3 +1,22 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2023 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/

package io.github.dsheirer.source.tuner.airspy.hf;

import java.text.DecimalFormat;
Expand All @@ -8,25 +27,41 @@
public class AirspyHfSampleRate
{
private static final DecimalFormat KILOHERTZ_FORMATTER = new DecimalFormat("0.0");
private int mValue;
private int mSampleRate;
private boolean mLowIf;

public AirspyHfSampleRate(int value)
/**
* Constructs an instance
* @param sampleRate in Hertz
* @param lowIf true if Low IF (LIF) or (default) false if Zero IF (ZIF)
*/
public AirspyHfSampleRate(int sampleRate, boolean lowIf)
{
mValue = value;
mSampleRate = sampleRate;
mLowIf = lowIf;
}

/**
* Value of sample rate
* @return rate in Hertz
*/
public int getValue()
public int getSampleRate()
{
return mSampleRate;
}

/**
* Indicates if the sample rate uses Low IF (LIF) versus Zero IF (ZIF)
* @return true if LIF
*/
public boolean isLowIf()
{
return mValue;
return mLowIf;
}

@Override
public String toString()
{
return KILOHERTZ_FORMATTER.format(mValue / 1E3) + " kHz";
return KILOHERTZ_FORMATTER.format(mSampleRate / 1E3) + " kHz " + (isLowIf() ? "(Low IF)" : "(Zero IF)");
}
}
Expand Up @@ -84,13 +84,13 @@ public TunerClass getTunerClass()
@Override
public double getSampleSize()
{
return 13.0;
return 18.0;
}

@Override
public int getMaximumUSBBitsPerSecond()
{
//4-bytes per sample = 32 bits times 10 MSps = 320,000,000 bits per second
return 320000000;
//4-bytes per sample = 32 bits times 912 kSps = 29,184,000 bits per second
return 29_184_000;
}
}

0 comments on commit 369c429

Please sign in to comment.