kopia lustrzana https://github.com/xdsopl/robot36
detect mode
rodzic
0fa1a1e205
commit
5f7652e8b5
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
Mode interface
|
||||
|
||||
Copyright 2024 Ahmet Inan <xdsopl@gmail.com>
|
||||
*/
|
||||
|
||||
package xdsopl.robot36;
|
||||
|
||||
public interface Mode {
|
||||
String getName();
|
||||
int getScanLineSamples();
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
Ładowanie…
Reference in New Issue