diff --git a/src/main/java/io/github/dsheirer/source/tuner/TunerClass.java b/src/main/java/io/github/dsheirer/source/tuner/TunerClass.java index 9278ac5f..5c23baad 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/TunerClass.java +++ b/src/main/java/io/github/dsheirer/source/tuner/TunerClass.java @@ -40,6 +40,7 @@ public enum TunerClass GIGABYTE_GTU7300( TunerType.FITIPOWER_FC0012, "1B80", "D393", "Gigabyte", "GT-U7300" ), GTEK_T803( TunerType.FITIPOWER_FC0012, "1F4D", "B803", "GTek", "T803" ), HACKRF_ONE( TunerType.HACKRF, "1D50", "6089", "Great Scott Gadgets", "HackRF One" ), + HACKRF_JAWBREAKER( TunerType.HACKRF, "1D50", "604B", "Great Scott Gadgets", "HackRF Jawbreaker" ), RAD1O( TunerType.HACKRF, "1D50", "CC15", "Munich hackerspace", "Rad1o" ), LIFEVIEW_LV5T_DELUXE( TunerType.FITIPOWER_FC0012, "1F4D", "C803", "Liveview", "LV5T Deluxe" ), MYGICA_TD312( TunerType.FITIPOWER_FC0012, "1F4D", "D286", "MyGica", "TD312" ), @@ -196,6 +197,10 @@ public enum TunerClass { retVal = HACKRF_ONE; } + else if( productID == 24651 ) //604B + { + retVal = HACKRF_JAWBREAKER; + } break; case 8013: //1F4D if( productID == 47107 ) //B803 diff --git a/src/main/java/io/github/dsheirer/source/tuner/TunerManager.java b/src/main/java/io/github/dsheirer/source/tuner/TunerManager.java index 172750f8..f4995975 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/TunerManager.java +++ b/src/main/java/io/github/dsheirer/source/tuner/TunerManager.java @@ -304,6 +304,7 @@ public class TunerManager case FUNCUBE_DONGLE_PRO_PLUS: return initFuncubeProPlusTuner(device, descriptor); case HACKRF_ONE: + case HACKRF_JAWBREAKER: case RAD1O: return initHackRFTuner(device, descriptor); case COMPRO_VIDEOMATE_U620F: diff --git a/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerController.java b/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerController.java index 395b0b5f..eb38b81c 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerController.java +++ b/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerController.java @@ -25,7 +25,7 @@ import io.github.dsheirer.source.SourceException; import io.github.dsheirer.source.tuner.configuration.TunerConfiguration; import io.github.dsheirer.source.tuner.usb.USBTransferProcessor; import io.github.dsheirer.source.tuner.usb.USBTunerController; -import io.github.dsheirer.source.tuner.usb.converter.ByteSampleConverter; +import io.github.dsheirer.source.tuner.usb.converter.SignedByteSampleConverter; import io.github.dsheirer.source.tuner.usb.converter.NativeBufferConverter; import org.apache.commons.io.EndianUtils; import org.slf4j.Logger; @@ -60,7 +60,7 @@ public class HackRFTunerController extends USBTunerController public static final double USABLE_BANDWIDTH_PERCENT = 0.75; public static final int DC_SPIKE_AVOID_BUFFER = 5000; - private NativeBufferConverter mNativeBufferConverter = new ByteSampleConverter(); + private NativeBufferConverter mNativeBufferConverter = new SignedByteSampleConverter(); private USBTransferProcessor mUSBTransferProcessor; private HackRFSampleRate mSampleRate = HackRFSampleRate.RATE2_016MHZ; diff --git a/src/main/java/io/github/dsheirer/source/tuner/usb/converter/SignedByteSampleConverter.java b/src/main/java/io/github/dsheirer/source/tuner/usb/converter/SignedByteSampleConverter.java new file mode 100644 index 00000000..90c94006 --- /dev/null +++ b/src/main/java/io/github/dsheirer/source/tuner/usb/converter/SignedByteSampleConverter.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * sdr-trunk + * Copyright (C) 2014-2018 Dennis Sheirer + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. + * If not, see + * + ******************************************************************************/ +package io.github.dsheirer.source.tuner.usb.converter; + +import java.nio.ByteBuffer; +import java.nio.FloatBuffer; + +public class SignedByteSampleConverter extends NativeBufferConverter +{ + private final static float[] LOOKUP_VALUES; + + //Creates a static lookup table that converts the signed 8-bit valued range from -128 to 127 into scaled float values + //of -1.0 to 0 to 1.0 + static + { + LOOKUP_VALUES = new float[256]; + + for(int x = 0; x < 256; x++) + { + LOOKUP_VALUES[x] = (float)((byte)x) / 128.0f; + } + } + + private FloatBuffer mFloatBuffer; + + /** + * Converts native byte buffers containing signed 8-bit complex samples into complex float samples loaded into a tracked, + * reusable complex sample buffer. Internally tracks the reusable buffer until all downstream consumers have finished + * processing the buffer contents and then reuses the buffer (and memory) for subsequent samples. + */ + public SignedByteSampleConverter() + { + } + + /** + * Converts the signed 8-bit complex samples contained in the native buffer into floats that are loaded into a float + * buffer and subsequently transferred to a reusable complex buffer by the parent class. + * + * @param nativeBuffer containing signed 8-bit complex samples + * @param length of bytes to read from the native buffer + * @return float buffer loaded with converted samples + */ + @Override + protected FloatBuffer convertSamples(ByteBuffer nativeBuffer, int length) + { + nativeBuffer.rewind(); + + if(mFloatBuffer == null || mFloatBuffer.capacity() != nativeBuffer.capacity()) + { + mFloatBuffer = FloatBuffer.allocate(nativeBuffer.capacity()); + } + + mFloatBuffer.rewind(); + + int count = 0; + + while(nativeBuffer.hasRemaining() && count < length) + { + byte sample = nativeBuffer.get(); + count++; + + mFloatBuffer.put(LOOKUP_VALUES[(sample & 0xFF)]); + } + + return mFloatBuffer; + } +}