pull/11/head
Ahmet Inan 2024-04-19 16:17:28 +02:00
rodzic 0fa1a1e205
commit 5f7652e8b5
10 zmienionych plików z 264 dodań i 4 usunięć

Wyświetl plik

@ -6,6 +6,8 @@ Copyright 2024 Ahmet Inan <xdsopl@gmail.com>
package xdsopl.robot36;
import java.util.ArrayList;
public class Decoder {
private final Demodulator demodulator;
@ -20,7 +22,12 @@ public class Decoder {
private final int scanLineToleranceSamples;
private final int scopeWidth;
private final int scopeHeight;
private final Mode rawMode;
private final ArrayList<Mode> syncPulse5msModes;
private final ArrayList<Mode> syncPulse9msModes;
private final ArrayList<Mode> syncPulse20msModes;
public String curMode;
public int curLine;
private int curSample;
@ -42,6 +49,25 @@ public class Decoder {
last20msSyncPulses = new int[syncPulseCount];
double scanLineToleranceSeconds = 0.001;
scanLineToleranceSamples = (int) Math.round(scanLineToleranceSeconds * sampleRate);
rawMode = new Raw();
syncPulse5msModes = new ArrayList<>();
syncPulse5msModes.add(new Wraase_SC2_180(sampleRate));
syncPulse5msModes.add(new Martin("1", 0.146432, sampleRate));
syncPulse5msModes.add(new Martin("2", 0.073216, sampleRate));
syncPulse9msModes = new ArrayList<>();
syncPulse9msModes.add(new Robot_36_Color(sampleRate));
syncPulse9msModes.add(new Robot_72_Color(sampleRate));
syncPulse9msModes.add(new Scottie("1", 0.138240, sampleRate));
syncPulse9msModes.add(new Scottie("2", 0.088064, sampleRate));
syncPulse9msModes.add(new Scottie("DX", 0.3456, sampleRate));
syncPulse20msModes = new ArrayList<>();
syncPulse20msModes.add(new PaulDon("50", 0.09152, sampleRate));
syncPulse20msModes.add(new PaulDon("90", 0.17024, sampleRate));
syncPulse20msModes.add(new PaulDon("120", 0.1216, sampleRate));
syncPulse20msModes.add(new PaulDon("160", 0.195584, sampleRate));
syncPulse20msModes.add(new PaulDon("180", 0.18304, sampleRate));
syncPulse20msModes.add(new PaulDon("240", 0.24448, sampleRate));
syncPulse20msModes.add(new PaulDon("290", 0.2288, sampleRate));
}
private void adjustSyncPulses(int[] pulses, int shift) {
@ -77,7 +103,20 @@ public class Decoder {
}
}
private boolean processSyncPulse(int[] pulses, int[] lines, int index) {
private Mode detectMode(ArrayList<Mode> modes, int line) {
Mode bestMode = rawMode;
int bestDist = Integer.MAX_VALUE;
for (Mode mode : modes) {
int dist = Math.abs(line - mode.getScanLineSamples());
if (dist <= scanLineToleranceSamples && dist < bestDist) {
bestDist = dist;
bestMode = mode;
}
}
return bestMode;
}
private boolean processSyncPulse(ArrayList<Mode> modes, int[] pulses, int[] lines, int index) {
for (int i = 1; i < lines.length; ++i)
lines[i - 1] = lines[i];
lines[lines.length - 1] = index - pulses[pulses.length - 1];
@ -88,6 +127,8 @@ public class Decoder {
return false;
if (scanLineStdDev(lines) > scanLineToleranceSamples)
return false;
Mode mode = detectMode(modes, lines[0]);
curMode = mode.getName();
if (pulses[0] >= lines[0]) {
int lineSamples = lines[0];
int endPulse = pulses[0];
@ -131,11 +172,11 @@ public class Decoder {
if (syncPulseDetected) {
switch (demodulator.syncPulseWidth) {
case FiveMilliSeconds:
return processSyncPulse(last5msSyncPulses, last5msScanLines, syncPulseIndex);
return processSyncPulse(syncPulse5msModes, last5msSyncPulses, last5msScanLines, syncPulseIndex);
case NineMilliSeconds:
return processSyncPulse(last9msSyncPulses, last9msScanLines, syncPulseIndex);
return processSyncPulse(syncPulse9msModes, last9msSyncPulses, last9msScanLines, syncPulseIndex);
case TwentyMilliSeconds:
return processSyncPulse(last20msSyncPulses, last20msScanLines, syncPulseIndex);
return processSyncPulse(syncPulse20msModes, last20msSyncPulses, last20msScanLines, syncPulseIndex);
}
}
return false;

Wyświetl plik

@ -54,6 +54,7 @@ public class MainActivity extends AppCompatActivity {
if (decoder.process(recordBuffer)) {
scopeBitmap.setPixels(scopePixels, scopeWidth * decoder.curLine, scopeWidth, 0, 0, scopeWidth, scopeHeight);
scopeView.invalidate();
status.setText(decoder.curMode);
}
}
};

Wyświetl plik

@ -0,0 +1,30 @@
/*
Martin modes
Copyright 2024 Ahmet Inan <xdsopl@gmail.com>
*/
package xdsopl.robot36;
public class Martin implements Mode {
private final int scanLineSamples;
private final String name;
Martin(String name, double channelSeconds, int sampleRate) {
this.name = "Martin " + name;
double syncPulseSeconds = 0.004862;
double separatorSeconds = 0.000572;
double scanLineSeconds = syncPulseSeconds + separatorSeconds + 3 * (channelSeconds + separatorSeconds);
scanLineSamples = (int) Math.round(scanLineSeconds * sampleRate);
}
@Override
public String getName() {
return name;
}
@Override
public int getScanLineSamples() {
return scanLineSamples;
}
}

Wyświetl plik

@ -0,0 +1,12 @@
/*
Mode interface
Copyright 2024 Ahmet Inan <xdsopl@gmail.com>
*/
package xdsopl.robot36;
public interface Mode {
String getName();
int getScanLineSamples();
}

Wyświetl plik

@ -0,0 +1,30 @@
/*
PD modes
Copyright 2024 Ahmet Inan <xdsopl@gmail.com>
*/
package xdsopl.robot36;
public class PaulDon implements Mode {
private final int scanLineSamples;
private final String name;
PaulDon(String name, double channelSeconds, int sampleRate) {
this.name = "PD " + name;
double syncPulseSeconds = 0.02;
double syncPorchSeconds = 0.00208;
double scanLineSeconds = syncPulseSeconds + syncPorchSeconds + 4 * (channelSeconds);
scanLineSamples = (int) Math.round(scanLineSeconds * sampleRate);
}
@Override
public String getName() {
return name;
}
@Override
public int getScanLineSamples() {
return scanLineSamples;
}
}

Wyświetl plik

@ -0,0 +1,23 @@
/*
Raw mode
Copyright 2024 Ahmet Inan <xdsopl@gmail.com>
*/
package xdsopl.robot36;
public class Raw implements Mode {
Raw() {
}
@Override
public String getName() {
return "Raw";
}
@Override
public int getScanLineSamples() {
return -1;
}
}

Wyświetl plik

@ -0,0 +1,32 @@
/*
Robot 36 Color
Copyright 2024 Ahmet Inan <xdsopl@gmail.com>
*/
package xdsopl.robot36;
public class Robot_36_Color implements Mode {
private final int scanLineSamples;
Robot_36_Color(int sampleRate) {
double syncPulseSeconds = 0.009;
double syncPorchSeconds = 0.003;
double luminanceSeconds = 0.088;
double separatorSeconds = 0.0045;
double porchSeconds = 0.0015;
double chrominanceSeconds = 0.044;
double scanLineSeconds = syncPulseSeconds + syncPorchSeconds + luminanceSeconds + separatorSeconds + porchSeconds + chrominanceSeconds;
scanLineSamples = (int) Math.round(scanLineSeconds * sampleRate);
}
@Override
public String getName() {
return "Robot 36 Color";
}
@Override
public int getScanLineSamples() {
return scanLineSamples;
}
}

Wyświetl plik

@ -0,0 +1,32 @@
/*
Robot 72 Color
Copyright 2024 Ahmet Inan <xdsopl@gmail.com>
*/
package xdsopl.robot36;
public class Robot_72_Color implements Mode {
private final int scanLineSamples;
Robot_72_Color(int sampleRate) {
double syncPulseSeconds = 0.009;
double syncPorchSeconds = 0.003;
double luminanceSeconds = 0.138;
double separatorSeconds = 0.0045;
double porchSeconds = 0.0015;
double chrominanceSeconds = 0.069;
double scanLineSeconds = syncPulseSeconds + syncPorchSeconds + luminanceSeconds + 2 * (separatorSeconds + porchSeconds + chrominanceSeconds);
scanLineSamples = (int) Math.round(scanLineSeconds * sampleRate);
}
@Override
public String getName() {
return "Robot 72 Color";
}
@Override
public int getScanLineSamples() {
return scanLineSamples;
}
}

Wyświetl plik

@ -0,0 +1,30 @@
/*
Scottie modes
Copyright 2024 Ahmet Inan <xdsopl@gmail.com>
*/
package xdsopl.robot36;
public class Scottie implements Mode {
private final int scanLineSamples;
private final String name;
Scottie(String name, double channelSeconds, int sampleRate) {
this.name = "Scottie " + name;
double syncPulseSeconds = 0.009;
double separatorSeconds = 0.0015;
double scanLineSeconds = syncPulseSeconds + 3 * (channelSeconds + separatorSeconds);
scanLineSamples = (int) Math.round(scanLineSeconds * sampleRate);
}
@Override
public String getName() {
return name;
}
@Override
public int getScanLineSamples() {
return scanLineSamples;
}
}

Wyświetl plik

@ -0,0 +1,29 @@
/*
Wraase SC2-180
Copyright 2024 Ahmet Inan <xdsopl@gmail.com>
*/
package xdsopl.robot36;
public class Wraase_SC2_180 implements Mode {
private final int scanLineSamples;
Wraase_SC2_180(int sampleRate) {
double syncPulseSeconds = 0.0055225;
double syncPorchSeconds = 0.0005;
double channelSeconds = 0.235;
double scanLineSeconds = syncPulseSeconds + syncPorchSeconds + 3 * channelSeconds;
scanLineSamples = (int) Math.round(scanLineSeconds * sampleRate);
}
@Override
public String getName() {
return "Wraase SC2-180";
}
@Override
public int getScanLineSamples() {
return scanLineSamples;
}
}