package de.tu.darmstadt.seemoo.ansian.tools;
import de.tu.darmstadt.seemoo.ansian.model.SamplePacket;
/**
* <h1>AnSiAn - IQ Converter</h1>
*
* Module: IQConverter.java Description: This class implements methods to
* convert the raw input data of IQ sources (bytes) to SamplePackets. It has
* also methods to do converting and down-mixing at the same time.
*
* @author Dennis Mantz
*
* Copyright (C) 2014 Dennis Mantz License:
* http://www.gnu.org/licenses/gpl.html GPL version 2 or higher
*
* This library 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 2 of the License, or (at
* your option) any later version.
*
* This library 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 library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
public abstract class IQConverter {
protected long frequency = 0; // Baseband frequency of the converted samples
// (is put into the SamplePacket)
protected int sampleRate = 0; // Sample rate of the converted samples (is
// put into the SamplePacket)
protected float[] lookupTable = null; // Lookup table to transform IQ bytes
// into doubles
protected float[][] cosineRealLookupTable = null; // Lookup table to
// transform IQ bytes
// into frequency
// shifted doubles
protected float[][] cosineImagLookupTable = null; // Lookup table to
// transform IQ bytes
// into frequency
// shifted doubles
protected int cosineFrequency; // Frequency of the cosine that is mixed to
// the signal
protected int cosineIndex; // current index within the cosine
protected static final int MAX_COSINE_LENGTH = 500; // Max length of the
// cosine lookup table
public IQConverter() {
generateLookupTable();
}
public long getFrequency() {
return frequency;
}
public void setFrequency(long frequency) {
this.frequency = frequency;
}
public int getSampleRate() {
return sampleRate;
}
public void setSampleRate(int sampleRate) {
if (this.sampleRate != sampleRate) {
this.sampleRate = sampleRate;
generateMixerLookupTable(cosineFrequency);
}
}
protected int calcOptimalCosineLength() {
// look for the best fitting array size to hold one or more full cosine
// cycles:
double cycleLength = sampleRate / Math.abs((double) cosineFrequency);
int bestLength = (int) cycleLength;
double bestLengthError = Math.abs(bestLength - cycleLength);
for (int i = 1; i * cycleLength < MAX_COSINE_LENGTH; i++) {
if (Math.abs(i * cycleLength - (int) (i * cycleLength)) < bestLengthError) {
bestLength = (int) (i * cycleLength);
bestLengthError = Math.abs(bestLength - (i * cycleLength));
}
}
return bestLength;
}
public abstract int fillPacketIntoSamplePacket(byte[] packet, SamplePacket samplePacket);
public abstract int mixPacketIntoSamplePacket(byte[] packet, SamplePacket samplePacket, long channelFrequency);
protected abstract void generateLookupTable();
protected abstract void generateMixerLookupTable(int mixFrequency);
}