Skip to content

Commit

Permalink
v1.3
Browse files Browse the repository at this point in the history
added:
-antenna power 
-chart markers to show frequency/power
  • Loading branch information
pavsa committed Jun 27, 2017
1 parent 4771d64 commit f99349b
Show file tree
Hide file tree
Showing 12 changed files with 154 additions and 30 deletions.
Binary file modified release/hackrf_spectrum_analyzer.zip
Binary file not shown.
9 changes: 5 additions & 4 deletions src/hackrf-sweep/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#Settings:
JAVA_EXECUTABLE = "c:\Program Files (x86)\Java\jre\bin\java.exe" #required to generate jna wrapper
JAVA_EXECUTABLE = "c:\Program Files\Java\jre\bin\java.exe" #required to generate jna wrapper
IS_RELEASE = y
IS_64BIT = n
#temporary build dir
Expand Down Expand Up @@ -81,7 +81,7 @@ endif
OUTPUT_DIR = build/lib/$(LIB_DIR)

JNA_LIB = lib/hackrf-sweep-jna.jar
JNA_HEADER = $(CURDIR)/lib/hackrf/host/hackrf-tools/src/hackrf_sweep.h
JNA_SWEEP_HEADER = $(CURDIR)/lib/hackrf/host/hackrf-tools/src/hackrf_sweep.h


DLL_LIB_PTHREAD = lib/$(LIB_DIR)/libwinpthread-1.dll
Expand Down Expand Up @@ -138,8 +138,9 @@ $(DLL_LIB): $(OBJECTS) $(JNA_LIB)
$(CXX) $(LDFLAGS) -shared -Wl,--kill-at -static-libgcc -static-libstdc++ $(LDPATHS) $(OBJECTS) -o $(DLL_LIB) $(LDLIBS)
strip --strip-unneeded $(DLL_LIB)

$(JNA_LIB): $(JNA_HEADER) $(OBJECTS)
$(JAVA_EXECUTABLE) -Xmx1024M -jar $(JNAERATOR) -limitComments -emptyStructsAsForwardDecls -f -skipLibraryInstance -runtime JNA -direct -mode Jar -o lib -jar $(JNA_LIB) -v -library "hackrf-sweep" $(JNA_HEADER)
$(JNA_LIB): $(JNA_SWEEP_HEADER) $(OBJECTS)
$(JAVA_EXECUTABLE) -Xmx1024M -jar $(JNAERATOR) -limitComments -emptyStructsAsForwardDecls -f -skipLibraryInstance -runtime JNA -direct -mode Jar -o lib -jar $(JNA_LIB) -v -library "hackrf-sweep" $(JNA_SWEEP_HEADER)
$(JAVA_EXECUTABLE) -Xmx1024M -jar $(JNAERATOR) -limitComments -emptyStructsAsForwardDecls -f -skipLibraryInstance -runtime JNA -direct -mode Jar -o lib -jar libhackrf-jna.jar -v -library "hackrf-sweep" $(CURDIR)/lib/hackrf/host/libhackrf/src/hackrf.h
rm -rf $(CURDIR)/_jnaerator.*


Expand Down
2 changes: 1 addition & 1 deletion src/hackrf-sweep/lib/hackrf
Binary file modified src/hackrf-sweep/lib/hackrf-sweep-jna.jar
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.text.DecimalFormat;
Expand Down Expand Up @@ -39,13 +42,16 @@
import org.jfree.data.Range;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.RectangleAnchor;
import org.jfree.ui.RectangleInsets;
import org.jfree.ui.TextAnchor;

import jspectrumanalyzer.core.DatasetSpectrum;
import jspectrumanalyzer.core.DatasetSpectrumPeak;
import jspectrumanalyzer.core.FFTBins;
import jspectrumanalyzer.core.HackRFSettings;
import jspectrumanalyzer.core.HackRFSweepSettingsUI;
import jspectrumanalyzer.core.PowerCalibration;
import jspectrumanalyzer.core.SpurFilter;
import jspectrumanalyzer.core.WaterfallPlot;
import jspectrumanalyzer.nativebridge.HackRFSweepDataCallback;
Expand Down Expand Up @@ -76,11 +82,11 @@ public static void main(String[] args) throws IOException
private int parameterMaxFreqMHz = 2500;
private int parameterMinFreqMHz = 2400;
private int parameterSamples = 8192;
private boolean parameterAntPower = false;
private ArrayBlockingQueue<FFTBins> processingQueue = new ArrayBlockingQueue<>(1000);
private boolean showPeaks = false;
private float spectrumInitValue = -100;
private float spectrumInitValue = -150;
private boolean spurRemoval = false;

private Thread threadHackrfSweep;
private ArrayBlockingQueue<Integer> threadLaunchCommands = new ArrayBlockingQueue<>(1);

Expand Down Expand Up @@ -127,7 +133,7 @@ public HackRFSweepSpectrumAnalyzer()
XYLineAndShapeRenderer rend = new XYLineAndShapeRenderer();
rend.setBaseShapesVisible(false);

ChartPanel chartPanel = new ChartPanel(chart);
chartPanel = new ChartPanel(chart);
chartPanel.setMaximumDrawWidth(4096);
chartPanel.setMaximumDrawHeight(2160);
chartPanel.setMouseWheelEnabled(false);
Expand Down Expand Up @@ -182,6 +188,8 @@ public HackRFSweepSpectrumAnalyzer()
}
});

addChartMouseMarkers();

waterfallPlot = new WaterfallPlot(chartPanel, 300);

waterfallPaletteStartMarker = new ValueMarker(waterfallPlot.getSpectrumPaletteStart(), palette2, new BasicStroke(1f));
Expand Down Expand Up @@ -215,7 +223,7 @@ public HackRFSweepSpectrumAnalyzer()
f.setVisible(true);

rangeAxis.setAutoRange(false);
rangeAxis.setRange(-100, 10);
rangeAxis.setRange(-110, 0);
rangeAxis.setTickUnit(new NumberTickUnit(10, new DecimalFormat("###")));

domainAxis.setNumberFormatOverride(new DecimalFormat(" #.### "));
Expand Down Expand Up @@ -288,6 +296,50 @@ public HackRFSweepSpectrumAnalyzer()
}));
}

private void addChartMouseMarkers() {
ValueMarker freqMarker = new ValueMarker(0, Color.WHITE, new BasicStroke(1f));
freqMarker.setLabelPaint(Color.white);
freqMarker.setLabelAnchor(RectangleAnchor.TOP_RIGHT);
freqMarker.setLabelTextAnchor(TextAnchor.TOP_LEFT);
freqMarker.setLabelFont(new Font(Font.MONOSPACED, Font.BOLD, 16));
ValueMarker signalMarker = new ValueMarker(0, Color.WHITE, new BasicStroke(1f));
signalMarker.setLabelPaint(Color.white);
signalMarker.setLabelAnchor(RectangleAnchor.TOP_RIGHT);
signalMarker.setLabelTextAnchor(TextAnchor.BOTTOM_RIGHT);
signalMarker.setLabelFont(new Font(Font.MONOSPACED, Font.BOLD, 16));

chartPanel.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
int x = e.getX();
int y = e.getY();

XYPlot plot = chart.getXYPlot();
Rectangle2D subplotArea = chartPanel.getChartRenderingInfo().getPlotInfo().getDataArea();
double crosshairRange = plot.getRangeAxis().java2DToValue(y, subplotArea, plot.getRangeAxisEdge());
signalMarker.setValue(crosshairRange);
signalMarker.setLabel(String.format("%.1fdB", crosshairRange));
double crosshairDomain = plot.getDomainAxis().java2DToValue(x, subplotArea, plot.getDomainAxisEdge());
freqMarker.setValue(crosshairDomain);
freqMarker.setLabel(String.format("%.1fMHz", crosshairDomain));
}
});
chartPanel.addMouseListener(new MouseAdapter() {
@Override
public void mouseExited(MouseEvent e) {
chart.getXYPlot().clearDomainMarkers();
chart.getXYPlot().clearRangeMarkers();
}
@Override
public void mouseEntered(MouseEvent e) {
chart.getXYPlot().clearDomainMarkers();
chart.getXYPlot().clearRangeMarkers();
chart.getXYPlot().addRangeMarker(signalMarker);
chart.getXYPlot().addDomainMarker(freqMarker);
}
});
}

public boolean isHWSendingData = false;
private void fireHardwareStateChanged(boolean sendingData)
{
Expand Down Expand Up @@ -343,6 +395,17 @@ private void fireCapturingStateChanged(boolean isCapturing)
}
}

@Override
public boolean getAntennaPowerEnable() {
return parameterAntPower;
}

@Override
public void setAntennaPowerEnable(boolean enable) {
this.parameterAntPower = enable;
restartHackrfSweep();
}

@Override public int getFFTBinHz()
{
return parameterFFTBinHz;
Expand Down Expand Up @@ -532,9 +595,10 @@ private void processingThread()
}
float binHz = bin1.fftBinWidthHz;

// PowerCalibration calibration = new PowerCalibration(-45, -12.5, 40);

datasetSpectrum = new DatasetSpectrumPeak(binHz, parameterMinFreqMHz, parameterMaxFreqMHz, spectrumInitValue, 15, 30000);
chart.getXYPlot().getDomainAxis().setRange(parameterMinFreqMHz, parameterMaxFreqMHz);


float maxPeakJitterdB = 6;
float peakThresholdAboveNoise = 4;
Expand All @@ -560,6 +624,7 @@ private void processingThread()

if (bins.freqStart != null && bins.sigPowdBm != null)
{
// PowerCalibration.correctPower(calibration, parameterGaindB, bins);
datasetSpectrum.addNewData(bins);
}

Expand All @@ -578,6 +643,7 @@ private void processingThread()
*/
if (showPeaks){
datasetSpectrum.refreshPeakSpectrum();
waterfallPlot.setStatusMessage(String.format("Total Spectrum Peak Power %.1fdBm", datasetSpectrum.calculateSpectrumPeakPower()));
}

XYSeries spectrumSeries = new XYSeries("spectrum");
Expand Down Expand Up @@ -651,6 +717,7 @@ private synchronized void restartHackrfSweep()

private volatile boolean forceStopSweep = false;
private SpurFilter spurFilter;
private ChartPanel chartPanel;
/**
* no need to synchronize, executes only in launcher thread
*/
Expand Down Expand Up @@ -771,7 +838,7 @@ private void sweep() throws IOException
System.out.println("hackrf_sweep params: freq " + parameterMinFreqMHz + "-" + parameterMaxFreqMHz + "MHz samples " + parameterSamples + " lna: "
+ lnaGain + " vga: " + vgaGain);
fireHardwareStateChanged(false);
HackRFSweepNativeBridge.start(this, parameterMinFreqMHz, parameterMaxFreqMHz, parameterFFTBinHz, parameterSamples, lnaGain, vgaGain);
HackRFSweepNativeBridge.start(this, parameterMinFreqMHz, parameterMaxFreqMHz, parameterFFTBinHz, parameterSamples, lnaGain, vgaGain, parameterAntPower);
fireHardwareStateChanged(false);
if (forceStopSweep==false){
Thread.sleep(1000);
Expand Down
2 changes: 1 addition & 1 deletion src/hackrf-sweep/src-java/jspectrumanalyzer/Version.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

public class Version
{
public static final String version = "1.2";
public static final String version = "1.3";
public static final String url = "https://github.com/pavsa/hackrf-spectrum-analyzer";
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ public void fillPeaksToXYSeries(XYSeries series)
fillToXYSeriesPriv(series, spectrumPeakHold);
}

public double calculateSpectrumPeakPower(){
double powerSum = 0;
for (int i = 0; i < spectrumPeakHold.length; i++) {
powerSum += Math.pow(10, spectrumPeakHold[i]/10); /*convert dB to mW to sum power in linear form*/
}
powerSum = 10*Math.log10(powerSum); /*convert back to dB*/
return powerSum;
}

public void refreshPeakSpectrum()
{
long timeDiffFromPrevValueMillis = System.currentTimeMillis() - lastAdded;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,7 @@ public static interface HackRFEventListener{

public void setSpectrumPaletteStart(int dB);
public void setSpurRemoval(boolean enable);

public void setAntennaPowerEnable(boolean enable);
public boolean getAntennaPowerEnable();
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public HackRFSweepSettingsUI(HackRFSettings hackRFSettings)
int maxFreq = 7250;
int freqStep = 1;

setLayout(new MigLayout("", "[123.00px,grow,leading]", "[][20px][][][20px][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]"));
setLayout(new MigLayout("", "[123.00px,grow,leading]", "[][20px][][][20px][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]"));

JLabel lblNewLabel = new JLabel("Frequency start [MHz]");
lblNewLabel.setForeground(Color.WHITE);
Expand Down Expand Up @@ -73,16 +73,15 @@ public HackRFSweepSettingsUI(HackRFSettings hackRFSettings)
spinnerFFTBinHz.setModel(new SpinnerListModel(
new String[] { "1000", "2000", "5000", "10 000", "20 000", "50 000", "100 000", "200 000", "500 000", "1 000 000", "2 000 000", "5 000 000" }));
add(spinnerFFTBinHz, "cell 0 7,growx");
spinnerFFTBinHz.setValue("100 000");
((ListEditor) spinnerFFTBinHz.getEditor()).getTextField().setHorizontalAlignment(JTextField.RIGHT);

spinnerFFTBinHz.addChangeListener(new ChangeListener()
{
@Override public void stateChanged(ChangeEvent e)
{
hackRFSettings.setFFTBin(Integer.parseInt(spinnerFFTBinHz.getValue().toString().replaceAll("\\s", "")));
}
});
spinnerFFTBinHz.setValue("100 000");

JLabel lblGain = new JLabel("Gain [dB]");
lblGain.setForeground(Color.WHITE);
Expand Down Expand Up @@ -121,18 +120,31 @@ public HackRFSweepSettingsUI(HackRFSettings hackRFSettings)
((ListEditor) spinner_numberOfSamples.getEditor()).getTextField().setEditable(false);
;
add(spinner_numberOfSamples, "cell 0 13,growx");

JCheckBox chckbxAntennaPower = new JCheckBox("Antenna power");
chckbxAntennaPower.setBackground(Color.BLACK);
chckbxAntennaPower.setForeground(Color.WHITE);
add(chckbxAntennaPower, "cell 0 15");
chckbxAntennaPower.setSelected(hackRFSettings.getAntennaPowerEnable());
chckbxAntennaPower.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
hackRFSettings.setAntennaPowerEnable(chckbxAntennaPower.isSelected());
}
});


JLabel lblWaterfallPaletteStart = new JLabel("Waterfall palette start [dB]");
lblWaterfallPaletteStart.setForeground(Color.WHITE);
add(lblWaterfallPaletteStart, "cell 0 15");
add(lblWaterfallPaletteStart, "cell 0 18");

JSlider slider_waterfallPaletteStart = new JSlider();
slider_waterfallPaletteStart.setForeground(Color.WHITE);
slider_waterfallPaletteStart.setBackground(Color.BLACK);
slider_waterfallPaletteStart.setMinimum(-100);
slider_waterfallPaletteStart.setMaximum(0);
slider_waterfallPaletteStart.setValue(-30);
add(slider_waterfallPaletteStart, "cell 0 16,growx");
add(slider_waterfallPaletteStart, "cell 0 19,growx");
slider_waterfallPaletteStart.setValue(hackRFSettings.getSpectrumPaletteStart());
slider_waterfallPaletteStart.addChangeListener(new ChangeListener()
{
Expand All @@ -153,12 +165,12 @@ public HackRFSweepSettingsUI(HackRFSettings hackRFSettings)

JLabel lblWaterfallPaletteLength = new JLabel("Waterfall palette length [dB]");
lblWaterfallPaletteLength.setForeground(Color.WHITE);
add(lblWaterfallPaletteLength, "cell 0 18");
add(lblWaterfallPaletteLength, "cell 0 21");

JSlider slider_waterfallPaletteSize = new JSlider(HackRFSweepSpectrumAnalyzer.SPECTRUM_PALETTE_SIZE_MIN, 100);
slider_waterfallPaletteSize.setBackground(Color.BLACK);
slider_waterfallPaletteSize.setForeground(Color.WHITE);
add(slider_waterfallPaletteSize, "cell 0 19,growx");
add(slider_waterfallPaletteSize, "cell 0 22,growx");

slider_waterfallPaletteSize.setValue(hackRFSettings.getSpectrumPaletteSize());

Expand All @@ -181,23 +193,23 @@ public HackRFSweepSettingsUI(HackRFSettings hackRFSettings)
JCheckBox chckbxShowPeaks = new JCheckBox("Show peaks");
chckbxShowPeaks.setForeground(Color.WHITE);
chckbxShowPeaks.setBackground(Color.BLACK);
add(chckbxShowPeaks, "cell 0 21,growx");
add(chckbxShowPeaks, "cell 0 24,growx");

JCheckBox chckbxRemoveSpurs = new JCheckBox("Spur filter (may distort real signals)");
chckbxRemoveSpurs.setForeground(Color.WHITE);
chckbxRemoveSpurs.setBackground(Color.BLACK);
add(chckbxRemoveSpurs, "cell 0 23");
add(chckbxRemoveSpurs, "cell 0 26");

txtHackrfConnected = new JTextField();
txtHackrfConnected.setText("HackRF connected");
txtHackrfConnected.setForeground(Color.WHITE);
txtHackrfConnected.setBackground(Color.BLACK);
add(txtHackrfConnected, "cell 0 26,growx");
add(txtHackrfConnected, "cell 0 29,growx");
txtHackrfConnected.setColumns(10);
txtHackrfConnected.setBorder(null);

JButton btnPause = new JButton("Pause");
add(btnPause, "cell 0 28,growx");
add(btnPause, "cell 0 31,growx");
btnPause.setBackground(Color.black);

JButton btnAbout = new JButton("Visit homepage");
Expand All @@ -218,9 +230,9 @@ public HackRFSweepSettingsUI(HackRFSettings hackRFSettings)
});

Label labelVersion = new Label("Version: v"+Version.version);
add(labelVersion, "flowx,cell 0 39");
add(labelVersion, "flowx,cell 0 42");
btnAbout.setBackground(Color.BLACK);
add(btnAbout, "cell 0 39,alignx right");
add(btnAbout, "cell 0 42,alignx right");
btnPause.addActionListener(new ActionListener()
{
@Override public void actionPerformed(ActionEvent e)
Expand All @@ -240,7 +252,6 @@ public HackRFSweepSettingsUI(HackRFSettings hackRFSettings)
}
});;


JCheckBox chckbxFilterSpectrum = new JCheckBox("Filter spectrum");
chckbxFilterSpectrum.setBackground(Color.BLACK);
chckbxFilterSpectrum.setForeground(Color.WHITE);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package jspectrumanalyzer.core;

public class PowerCalibration
{
public final double offset_dB;
public final double gain;
public PowerCalibration(double expectedPower_dBm, double measuredPower_dBm, double measuredAtGain)
{
offset_dB = expectedPower_dBm - measuredPower_dBm;
this.gain = measuredAtGain;
}
public double getOffset_dB(double gain){
return offset_dB + (this.gain - gain);
}

public static void correctPower(PowerCalibration cal, double gain, FFTBins bins){
// bins.fftBinWidthHz
double offset = cal.getOffset_dB(gain);
for (int i = 0; i < bins.sigPowdBm.length; i++) {
bins.sigPowdBm[i] += offset;
}
}
}
Loading

0 comments on commit f99349b

Please sign in to comment.