From 5f7652e8b5fab2175997392b2fdd99d735b499f9 Mon Sep 17 00:00:00 2001 From: Ahmet Inan Date: Fri, 19 Apr 2024 16:17:28 +0200 Subject: [PATCH] detect mode --- app/src/main/java/xdsopl/robot36/Decoder.java | 49 +++++++++++++++++-- .../java/xdsopl/robot36/MainActivity.java | 1 + app/src/main/java/xdsopl/robot36/Martin.java | 30 ++++++++++++ app/src/main/java/xdsopl/robot36/Mode.java | 12 +++++ app/src/main/java/xdsopl/robot36/PaulDon.java | 30 ++++++++++++ app/src/main/java/xdsopl/robot36/Raw.java | 23 +++++++++ .../java/xdsopl/robot36/Robot_36_Color.java | 32 ++++++++++++ .../java/xdsopl/robot36/Robot_72_Color.java | 32 ++++++++++++ app/src/main/java/xdsopl/robot36/Scottie.java | 30 ++++++++++++ .../java/xdsopl/robot36/Wraase_SC2_180.java | 29 +++++++++++ 10 files changed, 264 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/xdsopl/robot36/Martin.java create mode 100644 app/src/main/java/xdsopl/robot36/Mode.java create mode 100644 app/src/main/java/xdsopl/robot36/PaulDon.java create mode 100644 app/src/main/java/xdsopl/robot36/Raw.java create mode 100644 app/src/main/java/xdsopl/robot36/Robot_36_Color.java create mode 100644 app/src/main/java/xdsopl/robot36/Robot_72_Color.java create mode 100644 app/src/main/java/xdsopl/robot36/Scottie.java create mode 100644 app/src/main/java/xdsopl/robot36/Wraase_SC2_180.java diff --git a/app/src/main/java/xdsopl/robot36/Decoder.java b/app/src/main/java/xdsopl/robot36/Decoder.java index d01cc58..bb48588 100644 --- a/app/src/main/java/xdsopl/robot36/Decoder.java +++ b/app/src/main/java/xdsopl/robot36/Decoder.java @@ -6,6 +6,8 @@ Copyright 2024 Ahmet Inan 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 syncPulse5msModes; + private final ArrayList syncPulse9msModes; + private final ArrayList 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 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 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; diff --git a/app/src/main/java/xdsopl/robot36/MainActivity.java b/app/src/main/java/xdsopl/robot36/MainActivity.java index 2c2ee26..3a8d253 100644 --- a/app/src/main/java/xdsopl/robot36/MainActivity.java +++ b/app/src/main/java/xdsopl/robot36/MainActivity.java @@ -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); } } }; diff --git a/app/src/main/java/xdsopl/robot36/Martin.java b/app/src/main/java/xdsopl/robot36/Martin.java new file mode 100644 index 0000000..c5d3121 --- /dev/null +++ b/app/src/main/java/xdsopl/robot36/Martin.java @@ -0,0 +1,30 @@ +/* +Martin modes + +Copyright 2024 Ahmet Inan +*/ + +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; + } +} diff --git a/app/src/main/java/xdsopl/robot36/Mode.java b/app/src/main/java/xdsopl/robot36/Mode.java new file mode 100644 index 0000000..fdfbb11 --- /dev/null +++ b/app/src/main/java/xdsopl/robot36/Mode.java @@ -0,0 +1,12 @@ +/* +Mode interface + +Copyright 2024 Ahmet Inan +*/ + +package xdsopl.robot36; + +public interface Mode { + String getName(); + int getScanLineSamples(); +} diff --git a/app/src/main/java/xdsopl/robot36/PaulDon.java b/app/src/main/java/xdsopl/robot36/PaulDon.java new file mode 100644 index 0000000..f324ab2 --- /dev/null +++ b/app/src/main/java/xdsopl/robot36/PaulDon.java @@ -0,0 +1,30 @@ +/* +PD modes + +Copyright 2024 Ahmet Inan +*/ + +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; + } +} diff --git a/app/src/main/java/xdsopl/robot36/Raw.java b/app/src/main/java/xdsopl/robot36/Raw.java new file mode 100644 index 0000000..dedd465 --- /dev/null +++ b/app/src/main/java/xdsopl/robot36/Raw.java @@ -0,0 +1,23 @@ +/* +Raw mode + +Copyright 2024 Ahmet Inan +*/ + +package xdsopl.robot36; + +public class Raw implements Mode { + + Raw() { + } + + @Override + public String getName() { + return "Raw"; + } + + @Override + public int getScanLineSamples() { + return -1; + } +} diff --git a/app/src/main/java/xdsopl/robot36/Robot_36_Color.java b/app/src/main/java/xdsopl/robot36/Robot_36_Color.java new file mode 100644 index 0000000..1e6e4aa --- /dev/null +++ b/app/src/main/java/xdsopl/robot36/Robot_36_Color.java @@ -0,0 +1,32 @@ +/* +Robot 36 Color + +Copyright 2024 Ahmet Inan +*/ + +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; + } +} diff --git a/app/src/main/java/xdsopl/robot36/Robot_72_Color.java b/app/src/main/java/xdsopl/robot36/Robot_72_Color.java new file mode 100644 index 0000000..db8788f --- /dev/null +++ b/app/src/main/java/xdsopl/robot36/Robot_72_Color.java @@ -0,0 +1,32 @@ +/* +Robot 72 Color + +Copyright 2024 Ahmet Inan +*/ + +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; + } +} diff --git a/app/src/main/java/xdsopl/robot36/Scottie.java b/app/src/main/java/xdsopl/robot36/Scottie.java new file mode 100644 index 0000000..a48ec16 --- /dev/null +++ b/app/src/main/java/xdsopl/robot36/Scottie.java @@ -0,0 +1,30 @@ +/* +Scottie modes + +Copyright 2024 Ahmet Inan +*/ + +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; + } +} diff --git a/app/src/main/java/xdsopl/robot36/Wraase_SC2_180.java b/app/src/main/java/xdsopl/robot36/Wraase_SC2_180.java new file mode 100644 index 0000000..2985714 --- /dev/null +++ b/app/src/main/java/xdsopl/robot36/Wraase_SC2_180.java @@ -0,0 +1,29 @@ +/* +Wraase SC2-180 + +Copyright 2024 Ahmet Inan +*/ + +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; + } +}