/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package granolasdr; import edu.emory.mathcs.jtransforms.fft.FloatFFT_1D; import java.io.*; import java.net.*; import java.nio.ByteBuffer; import java.util.concurrent.LinkedBlockingQueue; import java.util.logging.Level; import java.util.logging.Logger; class TCPClient implements Runnable { private final OutputStream outToServer; private final BufferedInputStream sampleServer; private final LinkedBlockingQueue<byte[]> sampleBuffer; public static final int N = 512; private volatile int numDropped = 0; private final FloatFFT_1D fft = new FloatFFT_1D(N); private final float[] working = new float[2 * N]; private final int bufferDepth = 1000; public static enum RxCommand { CenterFreq(1), SampleRate(2), GainMode(3), Gain(4), FreqCorrection(5), IFGain(6), TestMode(7), AGCMode(8), DirectSampling(9), OffsetTuning(10), rtlXtal(11), TunerXtal(12), TunerGain(13); private final byte command; private RxCommand(int cmd) { command = (byte) cmd; } public byte getCommand() { return command; } } public TCPClient() throws IOException { this.sampleBuffer = new LinkedBlockingQueue<byte[]>(); Socket clientSocket = new Socket("localhost", 1234); outToServer = new BufferedOutputStream(clientSocket.getOutputStream()); sampleServer = new BufferedInputStream(clientSocket.getInputStream()); } public double[] getSamplesMag() throws InterruptedException { byte[] data = sampleBuffer.take(); for (int cnt = 0; cnt < 2 * N; cnt++) { working[cnt] = (float) data[cnt]; } fft.complexForward(working); double[] ret = new double[N]; for (int cnt = 0; cnt < N; cnt++) { double val = working[2 * cnt] * working[2 * cnt] + working[2 * cnt + 1] * working[2 * cnt + 1]; if (val != 0) { ret[cnt] = 10 * Math.log10(val); } } return ret; } public byte[] getNextSamples() throws InterruptedException { byte[] data = sampleBuffer.take(); return data; } public int getNumDropped() { int ret = numDropped; sampleBuffer.clear(); numDropped = 0; return ret; } @Override public void run() { byte[] samples = new byte[8192]; byte[] buffer = new byte[2 * N]; int num; int last = 0; try { float inv = 1f; while (!Thread.interrupted()) { num = sampleServer.read(samples) >> 1; for (int cnt = 0; cnt < num; cnt++) { // Note that I invert every other sample to put dc in center buffer[last++] = (byte) (((samples[2 * cnt] & 0xff) - 127.0f) * inv); buffer[last++] = (byte) (((samples[2 * cnt + 1] & 0xff) - 127.0f) * inv); inv = -inv; if (last >= 2 * N) { last = 0; if (sampleBuffer.size() < bufferDepth) { sampleBuffer.add(buffer); buffer = new byte[2 * N]; } else { numDropped++; // System.out.println("On the floor"); } } } } } catch (IOException ex) { Logger.getLogger(TCPClient.class.getName()).log(Level.SEVERE, null, ex); } } public void sendCommand(RxCommand command, int value) throws IOException { byte[] cmdbuf = new byte[5]; ByteBuffer cmd = ByteBuffer.wrap(cmdbuf); cmd.put(command.command); cmd.putInt(value); outToServer.write(cmd.array()); outToServer.flush(); } }