kopia lustrzana https://github.com/xdsopl/robot36
Renaming and refactoring
rodzic
7ad54873da
commit
1a4ffac26e
|
@ -157,7 +157,7 @@ public class Decoder {
|
|||
|
||||
private Mode findMode(ArrayList<Mode> modes, int code) {
|
||||
for (Mode mode : modes)
|
||||
if (mode.getCode() == code)
|
||||
if (mode.getVISCode() == code)
|
||||
return mode;
|
||||
return null;
|
||||
}
|
||||
|
@ -332,7 +332,7 @@ public class Decoder {
|
|||
}
|
||||
if (lockMode && mode != currentMode)
|
||||
return false;
|
||||
mode.reset();
|
||||
mode.resetState();
|
||||
imageBuffer.width = mode.getWidth();
|
||||
imageBuffer.height = mode.getHeight();
|
||||
imageBuffer.line = 0;
|
||||
|
@ -346,29 +346,29 @@ public class Decoder {
|
|||
for (int i = 0; i < pulses.length; ++i)
|
||||
pulses[i] = oldestSyncPulseIndex + i * currentScanLineSamples;
|
||||
Arrays.fill(lines, currentScanLineSamples);
|
||||
shiftSamples(lastSyncPulseIndex + mode.getBegin());
|
||||
shiftSamples(lastSyncPulseIndex + mode.getFirstPixelSampleIndex());
|
||||
drawLines(0xff00ff00, 8);
|
||||
drawLines(0xff000000, 10);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean processSyncPulse(ArrayList<Mode> modes, float[] freqOffs, int[] pulses, int[] lines, int index) {
|
||||
for (int i = 1; i < pulses.length; ++i)
|
||||
pulses[i - 1] = pulses[i];
|
||||
pulses[pulses.length - 1] = index;
|
||||
for (int i = 1; i < lines.length; ++i)
|
||||
lines[i - 1] = lines[i];
|
||||
lines[lines.length - 1] = pulses[pulses.length - 1] - pulses[pulses.length - 2];
|
||||
private boolean processSyncPulse(ArrayList<Mode> modes, float[] freqOffs, int[] syncIndexes, int[] lineLengths, int latestSyncIndex) {
|
||||
for (int i = 1; i < syncIndexes.length; ++i)
|
||||
syncIndexes[i - 1] = syncIndexes[i];
|
||||
syncIndexes[syncIndexes.length - 1] = latestSyncIndex;
|
||||
for (int i = 1; i < lineLengths.length; ++i)
|
||||
lineLengths[i - 1] = lineLengths[i];
|
||||
lineLengths[lineLengths.length - 1] = syncIndexes[syncIndexes.length - 1] - syncIndexes[syncIndexes.length - 2];
|
||||
for (int i = 1; i < freqOffs.length; ++i)
|
||||
freqOffs[i - 1] = freqOffs[i];
|
||||
freqOffs[pulses.length - 1] = demodulator.frequencyOffset;
|
||||
if (lines[0] == 0)
|
||||
freqOffs[syncIndexes.length - 1] = demodulator.frequencyOffset;
|
||||
if (lineLengths[0] == 0)
|
||||
return false;
|
||||
double mean = scanLineMean(lines);
|
||||
double mean = scanLineMean(lineLengths);
|
||||
int scanLineSamples = (int) Math.round(mean);
|
||||
if (scanLineSamples < scanLineMinSamples || scanLineSamples > scratchBuffer.length)
|
||||
return false;
|
||||
if (scanLineStdDev(lines, mean) > scanLineToleranceSamples)
|
||||
if (scanLineStdDev(lineLengths, mean) > scanLineToleranceSamples)
|
||||
return false;
|
||||
boolean pictureChanged = false;
|
||||
if (lockMode || imageBuffer.line >= 0 && imageBuffer.line < imageBuffer.height) {
|
||||
|
@ -379,7 +379,7 @@ public class Decoder {
|
|||
currentMode = detectMode(modes, scanLineSamples);
|
||||
pictureChanged = currentMode != prevMode
|
||||
|| Math.abs(currentScanLineSamples - scanLineSamples) > scanLineToleranceSamples
|
||||
|| Math.abs(lastSyncPulseIndex + scanLineSamples - pulses[pulses.length - 1]) > syncPulseToleranceSamples;
|
||||
|| Math.abs(lastSyncPulseIndex + scanLineSamples - syncIndexes[syncIndexes.length - 1]) > syncPulseToleranceSamples;
|
||||
}
|
||||
if (pictureChanged) {
|
||||
drawLines(0xff000000, 10);
|
||||
|
@ -387,23 +387,24 @@ public class Decoder {
|
|||
drawLines(0xff000000, 10);
|
||||
}
|
||||
float frequencyOffset = (float) frequencyOffsetMean(freqOffs);
|
||||
if (pulses[0] >= scanLineSamples && pictureChanged) {
|
||||
int endPulse = pulses[0];
|
||||
if (syncIndexes[0] >= scanLineSamples && pictureChanged) {
|
||||
int endPulse = syncIndexes[0];
|
||||
int extrapolate = endPulse / scanLineSamples;
|
||||
int firstPulse = endPulse - extrapolate * scanLineSamples;
|
||||
for (int pulseIndex = firstPulse; pulseIndex < endPulse; pulseIndex += scanLineSamples)
|
||||
copyLines(currentMode.decodeScanLine(pixelBuffer, scratchBuffer, scanLineBuffer, scopeBuffer.width, pulseIndex, scanLineSamples, frequencyOffset));
|
||||
}
|
||||
for (int i = pictureChanged ? 0 : lines.length - 1; i < lines.length; ++i)
|
||||
copyLines(currentMode.decodeScanLine(pixelBuffer, scratchBuffer, scanLineBuffer, scopeBuffer.width, pulses[i], lines[i], frequencyOffset));
|
||||
lastSyncPulseIndex = pulses[pulses.length - 1];
|
||||
for (int i = pictureChanged ? 0 : lineLengths.length - 1; i < lineLengths.length; ++i)
|
||||
copyLines(currentMode.decodeScanLine(pixelBuffer, scratchBuffer, scanLineBuffer, scopeBuffer.width, syncIndexes[i], lineLengths[i], frequencyOffset));
|
||||
lastSyncPulseIndex = syncIndexes[syncIndexes.length - 1];
|
||||
currentScanLineSamples = scanLineSamples;
|
||||
lastFrequencyOffset = frequencyOffset;
|
||||
shiftSamples(lastSyncPulseIndex + currentMode.getBegin());
|
||||
shiftSamples(lastSyncPulseIndex + currentMode.getFirstPixelSampleIndex());
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean process(float[] recordBuffer, int channelSelect) {
|
||||
boolean newLinesPresent = false;
|
||||
boolean syncPulseDetected = demodulator.process(recordBuffer, channelSelect);
|
||||
int syncPulseIndex = currentSample + demodulator.syncPulseOffset;
|
||||
int channels = channelSelect > 0 ? 2 : 1;
|
||||
|
@ -417,25 +418,28 @@ public class Decoder {
|
|||
if (syncPulseDetected) {
|
||||
switch (demodulator.syncPulseWidth) {
|
||||
case FiveMilliSeconds:
|
||||
return processSyncPulse(syncPulse5msModes, last5msFrequencyOffsets, last5msSyncPulses, last5msScanLines, syncPulseIndex);
|
||||
newLinesPresent = processSyncPulse(syncPulse5msModes, last5msFrequencyOffsets, last5msSyncPulses, last5msScanLines, syncPulseIndex);
|
||||
break;
|
||||
case NineMilliSeconds:
|
||||
leaderBreakIndex = syncPulseIndex;
|
||||
return processSyncPulse(syncPulse9msModes, last9msFrequencyOffsets, last9msSyncPulses, last9msScanLines, syncPulseIndex);
|
||||
newLinesPresent = processSyncPulse(syncPulse9msModes, last9msFrequencyOffsets, last9msSyncPulses, last9msScanLines, syncPulseIndex);
|
||||
break;
|
||||
case TwentyMilliSeconds:
|
||||
leaderBreakIndex = syncPulseIndex;
|
||||
return processSyncPulse(syncPulse20msModes, last20msFrequencyOffsets, last20msSyncPulses, last20msScanLines, syncPulseIndex);
|
||||
newLinesPresent = processSyncPulse(syncPulse20msModes, last20msFrequencyOffsets, last20msSyncPulses, last20msScanLines, syncPulseIndex);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (handleHeader())
|
||||
return true;
|
||||
if (currentSample > lastSyncPulseIndex + (currentScanLineSamples * 5) / 4) {
|
||||
} else if (handleHeader()) {
|
||||
newLinesPresent = true;
|
||||
} else if (currentSample > lastSyncPulseIndex + (currentScanLineSamples * 5) / 4) {
|
||||
copyLines(currentMode.decodeScanLine(pixelBuffer, scratchBuffer, scanLineBuffer, scopeBuffer.width, lastSyncPulseIndex, currentScanLineSamples, lastFrequencyOffset));
|
||||
lastSyncPulseIndex += currentScanLineSamples;
|
||||
return true;
|
||||
newLinesPresent = true;
|
||||
}
|
||||
return false;
|
||||
|
||||
return newLinesPresent;
|
||||
}
|
||||
|
||||
public void setMode(String name) {
|
||||
|
|
|
@ -13,6 +13,8 @@ public class Demodulator {
|
|||
private final SchmittTrigger syncPulseTrigger;
|
||||
private final Phasor baseBandOscillator;
|
||||
private final Delay syncPulseValueDelay;
|
||||
private final double scanLineBandwidth;
|
||||
private final double centerFrequency;
|
||||
private final float syncPulseFrequencyValue;
|
||||
private final float syncPulseFrequencyTolerance;
|
||||
private final int syncPulse5msMinSamples;
|
||||
|
@ -33,10 +35,12 @@ public class Demodulator {
|
|||
public int syncPulseOffset;
|
||||
public float frequencyOffset;
|
||||
|
||||
public static final double syncPulseFrequency = 1200;
|
||||
public static final double blackFrequency = 1500;
|
||||
public static final double whiteFrequency = 2300;
|
||||
|
||||
Demodulator(int sampleRate) {
|
||||
double blackFrequency = 1500;
|
||||
double whiteFrequency = 2300;
|
||||
double scanLineBandwidth = whiteFrequency - blackFrequency;
|
||||
scanLineBandwidth = whiteFrequency - blackFrequency;
|
||||
frequencyModulation = new FrequencyModulation(scanLineBandwidth, sampleRate);
|
||||
double syncPulse5msSeconds = 0.005;
|
||||
double syncPulse9msSeconds = 0.009;
|
||||
|
@ -63,20 +67,23 @@ public class Demodulator {
|
|||
Kaiser kaiser = new Kaiser();
|
||||
for (int i = 0; i < baseBandLowPass.length; ++i)
|
||||
baseBandLowPass.taps[i] = (float) (kaiser.window(2.0, i, baseBandLowPass.length) * Filter.lowPass(cutoffFrequency, sampleRate, i, baseBandLowPass.length));
|
||||
double centerFrequency = (lowestFrequency + highestFrequency) / 2;
|
||||
centerFrequency = (lowestFrequency + highestFrequency) / 2;
|
||||
baseBandOscillator = new Phasor(-centerFrequency, sampleRate);
|
||||
double syncPulseFrequency = 1200;
|
||||
syncPulseFrequencyValue = (float) ((syncPulseFrequency - centerFrequency) * 2 / scanLineBandwidth);
|
||||
syncPulseFrequencyValue = (float) normalizeFrequency(syncPulseFrequency);
|
||||
syncPulseFrequencyTolerance = (float) (50 * 2 / scanLineBandwidth);
|
||||
double syncPorchFrequency = 1500;
|
||||
double syncHighFrequency = (syncPulseFrequency + syncPorchFrequency) / 2;
|
||||
double syncLowFrequency = (syncPulseFrequency + syncHighFrequency) / 2;
|
||||
double syncLowValue = (syncLowFrequency - centerFrequency) * 2 / scanLineBandwidth;
|
||||
double syncHighValue = (syncHighFrequency - centerFrequency) * 2 / scanLineBandwidth;
|
||||
double syncLowValue = normalizeFrequency(syncLowFrequency);
|
||||
double syncHighValue = normalizeFrequency(syncHighFrequency);
|
||||
syncPulseTrigger = new SchmittTrigger((float) syncLowValue, (float) syncHighValue);
|
||||
baseBand = new Complex();
|
||||
}
|
||||
|
||||
private double normalizeFrequency(double frequency) {
|
||||
return (frequency - centerFrequency) * 2 / scanLineBandwidth;
|
||||
}
|
||||
|
||||
public boolean process(float[] buffer, int channelSelect) {
|
||||
boolean syncPulseDetected = false;
|
||||
int channels = channelSelect > 0 ? 2 : 1;
|
||||
|
|
|
@ -9,19 +9,23 @@ package xdsopl.robot36;
|
|||
public interface Mode {
|
||||
String getName();
|
||||
|
||||
int getCode();
|
||||
int getVISCode();
|
||||
|
||||
int getWidth();
|
||||
|
||||
int getHeight();
|
||||
|
||||
int getBegin();
|
||||
int getFirstPixelSampleIndex();
|
||||
|
||||
int getFirstSyncPulseIndex();
|
||||
|
||||
int getScanLineSamples();
|
||||
|
||||
void reset();
|
||||
void resetState();
|
||||
|
||||
/**
|
||||
* @param frequencyOffset normalized correction of frequency (expected vs actual)
|
||||
* @return true if scanline was decoded
|
||||
*/
|
||||
boolean decodeScanLine(PixelBuffer pixelBuffer, float[] scratchBuffer, float[] scanLineBuffer, int scopeBufferWidth, int syncPulseIndex, int scanLineSamples, float frequencyOffset);
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ public class PaulDon implements Mode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getCode() {
|
||||
public int getVISCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ public class PaulDon implements Mode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getBegin() {
|
||||
public int getFirstPixelSampleIndex() {
|
||||
return beginSamples;
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,7 @@ public class PaulDon implements Mode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
public void resetState() {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -51,7 +51,7 @@ public class RGBDecoder implements Mode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getCode() {
|
||||
public int getVISCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ public class RGBDecoder implements Mode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getBegin() {
|
||||
public int getFirstPixelSampleIndex() {
|
||||
return beginSamples;
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ public class RGBDecoder implements Mode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
public void resetState() {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -29,7 +29,7 @@ public class RawDecoder implements Mode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getCode() {
|
||||
public int getVISCode() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ public class RawDecoder implements Mode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getBegin() {
|
||||
public int getFirstPixelSampleIndex() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ public class RawDecoder implements Mode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
public void resetState() {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -59,7 +59,7 @@ public class Robot_36_Color implements Mode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getCode() {
|
||||
public int getVISCode() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ public class Robot_36_Color implements Mode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getBegin() {
|
||||
public int getFirstPixelSampleIndex() {
|
||||
return beginSamples;
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ public class Robot_36_Color implements Mode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
public void resetState() {
|
||||
lastEven = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ public class Robot_72_Color implements Mode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getCode() {
|
||||
public int getVISCode() {
|
||||
return 12;
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ public class Robot_72_Color implements Mode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getBegin() {
|
||||
public int getFirstPixelSampleIndex() {
|
||||
return beginSamples;
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ public class Robot_72_Color implements Mode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
public void resetState() {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Ładowanie…
Reference in New Issue