From 51c241b6fb49610d0589a2ddecbc473bacb0e49e Mon Sep 17 00:00:00 2001 From: Ahmet Inan Date: Mon, 29 Apr 2024 09:07:40 +0200 Subject: [PATCH] prepare using header --- app/src/main/java/xdsopl/robot36/Decoder.java | 51 ++++++++++++------- app/src/main/java/xdsopl/robot36/Mode.java | 2 + app/src/main/java/xdsopl/robot36/PaulDon.java | 7 +++ .../main/java/xdsopl/robot36/RGBDecoder.java | 9 +++- .../main/java/xdsopl/robot36/RGBModes.java | 7 +-- .../main/java/xdsopl/robot36/RawDecoder.java | 5 ++ .../java/xdsopl/robot36/Robot_36_Color.java | 7 +++ .../java/xdsopl/robot36/Robot_72_Color.java | 7 +++ 8 files changed, 74 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/xdsopl/robot36/Decoder.java b/app/src/main/java/xdsopl/robot36/Decoder.java index 444795f..2154d57 100644 --- a/app/src/main/java/xdsopl/robot36/Decoder.java +++ b/app/src/main/java/xdsopl/robot36/Decoder.java @@ -6,8 +6,6 @@ Copyright 2024 Ahmet Inan package xdsopl.robot36; -import android.util.Log; - import java.util.ArrayList; import java.util.Arrays; @@ -27,7 +25,7 @@ public class Decoder { private final float[] last5msFrequencyOffsets; private final float[] last9msFrequencyOffsets; private final float[] last20msFrequencyOffsets; - private final float[] visCodeBitFreqs; + private final float[] visCodeBitFrequencies; private final int scanLineReserveSamples; private final int syncPulseToleranceSamples; private final int scanLineToleranceSamples; @@ -48,6 +46,7 @@ public class Decoder { private int lastSyncPulseIndex; private int lastScanLineSamples; private float lastFrequencyOffset; + private float leaderFreqOffset; Decoder(PixelBuffer scopeBuffer, int sampleRate) { this.scopeBuffer = scopeBuffer; @@ -69,7 +68,7 @@ public class Decoder { visCodeBitSamples = (int) Math.round(visCodeBitSeconds * sampleRate); double visCodeSeconds = 0.3; visCodeSamples = (int) Math.round(visCodeSeconds * sampleRate); - visCodeBitFreqs = new float[10]; + visCodeBitFrequencies = new float[10]; int scanLineCount = 4; last5msScanLines = new int[scanLineCount]; last9msScanLines = new int[scanLineCount]; @@ -218,27 +217,27 @@ public class Decoder { preBreakFreq = preBreakFreq * halfBandWidth / leaderBreakSamples + centerFreq; if (preBreakFreq < 1850 || preBreakFreq > 1950) return false; - float postBreakFreq = 0; + float leaderFreq = 0; for (int i = transitionSamples; i < leaderToneSamples - transitionSamples; ++i) - postBreakFreq += scanLineBuffer[syncPulseIndex + i]; - float freqOffset = postBreakFreq / (leaderToneSamples - 2 * transitionSamples); - postBreakFreq = postBreakFreq * halfBandWidth / (leaderToneSamples - 2 * transitionSamples) + centerFreq; - if (postBreakFreq < 1850 || postBreakFreq > 1950) + leaderFreq += scanLineBuffer[syncPulseIndex + i]; + leaderFreqOffset = leaderFreq / (leaderToneSamples - 2 * transitionSamples); + leaderFreq = leaderFreq * halfBandWidth / (leaderToneSamples - 2 * transitionSamples) + centerFreq; + if (leaderFreq < 1850 || leaderFreq > 1950) return false; - Arrays.fill(visCodeBitFreqs, 0); + Arrays.fill(visCodeBitFrequencies, 0); for (int j = 0; j < 10; ++j) for (int i = transitionSamples; i < visCodeBitSamples - transitionSamples; ++i) - visCodeBitFreqs[j] += scanLineBuffer[syncPulseIndex + leaderToneSamples + visCodeBitSamples * j + i] - freqOffset; + visCodeBitFrequencies[j] += scanLineBuffer[syncPulseIndex + leaderToneSamples + visCodeBitSamples * j + i] - leaderFreqOffset; for (int i = 0; i < 10; ++i) - visCodeBitFreqs[i] = visCodeBitFreqs[i] * halfBandWidth / (visCodeBitSamples - 2 * transitionSamples) + centerFreq; - if (visCodeBitFreqs[0] < 1150 || visCodeBitFreqs[0] > 1250 || visCodeBitFreqs[9] < 1150 || visCodeBitFreqs[9] > 1250) + visCodeBitFrequencies[i] = visCodeBitFrequencies[i] * halfBandWidth / (visCodeBitSamples - 2 * transitionSamples) + centerFreq; + if (visCodeBitFrequencies[0] < 1150 || visCodeBitFrequencies[0] > 1250 || visCodeBitFrequencies[9] < 1150 || visCodeBitFrequencies[9] > 1250) return false; for (int i = 1; i < 9; ++i) - if (visCodeBitFreqs[i] < 1050 || visCodeBitFreqs[i] > 1150 && visCodeBitFreqs[i] < 1250 || visCodeBitFreqs[i] > 1350) + if (visCodeBitFrequencies[i] < 1050 || visCodeBitFrequencies[i] > 1150 && visCodeBitFrequencies[i] < 1250 || visCodeBitFrequencies[i] > 1350) return false; visCode = 0; for (int i = 0; i < 8; ++i) - visCode |= (visCodeBitFreqs[i + 1] < 1200 ? 1 : 0) << i; + visCode |= (visCodeBitFrequencies[i + 1] < 1200 ? 1 : 0) << i; boolean check = true; for (int i = 0; i < 8; ++i) check ^= (visCode & 1 << i) != 0; @@ -326,8 +325,26 @@ public class Decoder { return false; } } - if (detectHeader(last9msSyncPulses[last9msSyncPulses.length - 1])) - Log.d("Robot36", "VIS mode: " + findMode(visCode).getName()); + if (detectHeader(last9msSyncPulses[last9msSyncPulses.length - 1])) { + Mode visMode = findMode(visCode); + if (visMode != rawMode) { + lastMode = visMode; + lastSyncPulseIndex = last9msSyncPulses[last9msSyncPulses.length - 1] + leaderToneSamples + visCodeSamples + visMode.getFirstSyncPulseIndex(); + lastScanLineSamples = visMode.getScanLineSamples(); + lastFrequencyOffset = leaderFreqOffset; + int shift = lastSyncPulseIndex - scanLineReserveSamples; + if (shift > scanLineReserveSamples) { + lastSyncPulseIndex -= shift; + adjustSyncPulses(last5msSyncPulses, shift); + adjustSyncPulses(last9msSyncPulses, shift); + adjustSyncPulses(last20msSyncPulses, shift); + int endSample = curSample; + curSample = 0; + for (int i = shift; i < endSample; ++i) + scanLineBuffer[curSample++] = scanLineBuffer[i]; + } + } + } if (lastSyncPulseIndex >= scanLineReserveSamples && curSample > lastSyncPulseIndex + (lastScanLineSamples * 5) / 4) { copyLines(lastMode.decodeScanLine(pixelBuffer, scratchBuffer, scanLineBuffer, scopeBuffer.width, lastSyncPulseIndex, lastScanLineSamples, lastFrequencyOffset)); lastSyncPulseIndex += lastScanLineSamples; diff --git a/app/src/main/java/xdsopl/robot36/Mode.java b/app/src/main/java/xdsopl/robot36/Mode.java index d776d13..e229aa0 100644 --- a/app/src/main/java/xdsopl/robot36/Mode.java +++ b/app/src/main/java/xdsopl/robot36/Mode.java @@ -11,6 +11,8 @@ public interface Mode { int getCode(); + int getFirstSyncPulseIndex(); + int getScanLineSamples(); boolean decodeScanLine(PixelBuffer pixelBuffer, float[] scratchBuffer, float[] scanLineBuffer, int scopeBufferWidth, int syncPulseIndex, int scanLineSamples, float frequencyOffset); diff --git a/app/src/main/java/xdsopl/robot36/PaulDon.java b/app/src/main/java/xdsopl/robot36/PaulDon.java index 49fab6a..1690c45 100644 --- a/app/src/main/java/xdsopl/robot36/PaulDon.java +++ b/app/src/main/java/xdsopl/robot36/PaulDon.java @@ -9,6 +9,7 @@ package xdsopl.robot36; public class PaulDon implements Mode { private final ExponentialMovingAverage lowPassFilter; private final int horizontalPixels; + private final int firstSyncPulseIndex; private final int scanLineSamples; private final int channelSamples; private final int beginSamples; @@ -27,6 +28,7 @@ public class PaulDon implements Mode { this.horizontalPixels = horizontalPixels; double syncPulseSeconds = 0.02; double syncPorchSeconds = 0.00208; + firstSyncPulseIndex = (int) Math.round(syncPulseSeconds * sampleRate); double scanLineSeconds = syncPulseSeconds + syncPorchSeconds + 4 * (channelSeconds); scanLineSamples = (int) Math.round(scanLineSeconds * sampleRate); channelSamples = (int) Math.round(channelSeconds * sampleRate); @@ -58,6 +60,11 @@ public class PaulDon implements Mode { return code; } + @Override + public int getFirstSyncPulseIndex() { + return firstSyncPulseIndex; + } + @Override public int getScanLineSamples() { return scanLineSamples; diff --git a/app/src/main/java/xdsopl/robot36/RGBDecoder.java b/app/src/main/java/xdsopl/robot36/RGBDecoder.java index a05a6f0..040eb43 100644 --- a/app/src/main/java/xdsopl/robot36/RGBDecoder.java +++ b/app/src/main/java/xdsopl/robot36/RGBDecoder.java @@ -9,6 +9,7 @@ package xdsopl.robot36; public class RGBDecoder implements Mode { private final ExponentialMovingAverage lowPassFilter; private final int horizontalPixels; + private final int firstSyncPulseIndex; private final int scanLineSamples; private final int beginSamples; private final int redBeginSamples; @@ -21,10 +22,11 @@ public class RGBDecoder implements Mode { private final String name; private final int code; - RGBDecoder(String name, int code, int horizontalPixels, double scanLineSeconds, double beginSeconds, double redBeginSeconds, double redEndSeconds, double greenBeginSeconds, double greenEndSeconds, double blueBeginSeconds, double blueEndSeconds, double endSeconds, int sampleRate) { + RGBDecoder(String name, int code, int horizontalPixels, double firstSyncPulseSeconds, double scanLineSeconds, double beginSeconds, double redBeginSeconds, double redEndSeconds, double greenBeginSeconds, double greenEndSeconds, double blueBeginSeconds, double blueEndSeconds, double endSeconds, int sampleRate) { this.name = name; this.code = code; this.horizontalPixels = horizontalPixels; + firstSyncPulseIndex = (int) Math.round(firstSyncPulseSeconds * sampleRate); scanLineSamples = (int) Math.round(scanLineSeconds * sampleRate); beginSamples = (int) Math.round(beginSeconds * sampleRate); redBeginSamples = (int) Math.round(redBeginSeconds * sampleRate) - beginSamples; @@ -51,6 +53,11 @@ public class RGBDecoder implements Mode { return code; } + @Override + public int getFirstSyncPulseIndex() { + return firstSyncPulseIndex; + } + @Override public int getScanLineSamples() { return scanLineSamples; diff --git a/app/src/main/java/xdsopl/robot36/RGBModes.java b/app/src/main/java/xdsopl/robot36/RGBModes.java index 6433778..36b9d50 100644 --- a/app/src/main/java/xdsopl/robot36/RGBModes.java +++ b/app/src/main/java/xdsopl/robot36/RGBModes.java @@ -19,12 +19,13 @@ public final class RGBModes { double blueEndSeconds = blueBeginSeconds + channelSeconds; double redBeginSeconds = blueEndSeconds + separatorSeconds; double redEndSeconds = redBeginSeconds + channelSeconds; - return new RGBDecoder("Martin " + name, code, 320, scanLineSeconds, greenBeginSeconds, redBeginSeconds, redEndSeconds, greenBeginSeconds, greenEndSeconds, blueBeginSeconds, blueEndSeconds, redEndSeconds, sampleRate); + return new RGBDecoder("Martin " + name, code, 320, syncPulseSeconds, scanLineSeconds, greenBeginSeconds, redBeginSeconds, redEndSeconds, greenBeginSeconds, greenEndSeconds, blueBeginSeconds, blueEndSeconds, redEndSeconds, sampleRate); } public static RGBDecoder Scottie(String name, int code, double channelSeconds, int sampleRate) { double syncPulseSeconds = 0.009; double separatorSeconds = 0.0015; + double firstSyncPulseSeconds = 2 * (syncPulseSeconds + separatorSeconds + channelSeconds); double scanLineSeconds = syncPulseSeconds + 3 * (channelSeconds + separatorSeconds); double blueEndSeconds = -syncPulseSeconds; double blueBeginSeconds = blueEndSeconds - channelSeconds; @@ -32,7 +33,7 @@ public final class RGBModes { double greenBeginSeconds = greenEndSeconds - channelSeconds; double redBeginSeconds = separatorSeconds; double redEndSeconds = redBeginSeconds + channelSeconds; - return new RGBDecoder("Scottie " + name, code, 320, scanLineSeconds, greenBeginSeconds, redBeginSeconds, redEndSeconds, greenBeginSeconds, greenEndSeconds, blueBeginSeconds, blueEndSeconds, redEndSeconds, sampleRate); + return new RGBDecoder("Scottie " + name, code, 320, firstSyncPulseSeconds, scanLineSeconds, greenBeginSeconds, redBeginSeconds, redEndSeconds, greenBeginSeconds, greenEndSeconds, blueBeginSeconds, blueEndSeconds, redEndSeconds, sampleRate); } public static RGBDecoder Wraase_SC2_180(int sampleRate) { @@ -46,6 +47,6 @@ public final class RGBModes { double greenEndSeconds = greenBeginSeconds + channelSeconds; double blueBeginSeconds = greenEndSeconds; double blueEndSeconds = blueBeginSeconds + channelSeconds; - return new RGBDecoder("Wraase SC2-180", 55, 320, scanLineSeconds, redBeginSeconds, redBeginSeconds, redEndSeconds, greenBeginSeconds, greenEndSeconds, blueBeginSeconds, blueEndSeconds, blueEndSeconds, sampleRate); + return new RGBDecoder("Wraase SC2-180", 55, 320, syncPulseSeconds, scanLineSeconds, redBeginSeconds, redBeginSeconds, redEndSeconds, greenBeginSeconds, greenEndSeconds, blueBeginSeconds, blueEndSeconds, blueEndSeconds, sampleRate); } } diff --git a/app/src/main/java/xdsopl/robot36/RawDecoder.java b/app/src/main/java/xdsopl/robot36/RawDecoder.java index 077ae8a..97b62d5 100644 --- a/app/src/main/java/xdsopl/robot36/RawDecoder.java +++ b/app/src/main/java/xdsopl/robot36/RawDecoder.java @@ -31,6 +31,11 @@ public class RawDecoder implements Mode { return -1; } + @Override + public int getFirstSyncPulseIndex() { + return -1; + } + @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 index de891c2..1b6b7f0 100644 --- a/app/src/main/java/xdsopl/robot36/Robot_36_Color.java +++ b/app/src/main/java/xdsopl/robot36/Robot_36_Color.java @@ -9,6 +9,7 @@ package xdsopl.robot36; public class Robot_36_Color implements Mode { private final ExponentialMovingAverage lowPassFilter; private final int horizontalPixels; + private final int firstSyncPulseIndex; private final int scanLineSamples; private final int luminanceSamples; private final int separatorSamples; @@ -29,6 +30,7 @@ public class Robot_36_Color implements Mode { double separatorSeconds = 0.0045; double porchSeconds = 0.0015; double chrominanceSeconds = 0.044; + firstSyncPulseIndex = (int) Math.round(syncPulseSeconds * sampleRate); double scanLineSeconds = syncPulseSeconds + syncPorchSeconds + luminanceSeconds + separatorSeconds + porchSeconds + chrominanceSeconds; scanLineSamples = (int) Math.round(scanLineSeconds * sampleRate); luminanceSamples = (int) Math.round(luminanceSeconds * sampleRate); @@ -61,6 +63,11 @@ public class Robot_36_Color implements Mode { return 8; } + @Override + public int getFirstSyncPulseIndex() { + return firstSyncPulseIndex; + } + @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 index 8a89786..41a6e88 100644 --- a/app/src/main/java/xdsopl/robot36/Robot_72_Color.java +++ b/app/src/main/java/xdsopl/robot36/Robot_72_Color.java @@ -9,6 +9,7 @@ package xdsopl.robot36; public class Robot_72_Color implements Mode { private final ExponentialMovingAverage lowPassFilter; private final int horizontalPixels; + private final int firstSyncPulseIndex; private final int scanLineSamples; private final int luminanceSamples; private final int chrominanceSamples; @@ -27,6 +28,7 @@ public class Robot_72_Color implements Mode { double separatorSeconds = 0.0045; double porchSeconds = 0.0015; double chrominanceSeconds = 0.069; + firstSyncPulseIndex = (int) Math.round(syncPulseSeconds * sampleRate); double scanLineSeconds = syncPulseSeconds + syncPorchSeconds + luminanceSeconds + 2 * (separatorSeconds + porchSeconds + chrominanceSeconds); scanLineSamples = (int) Math.round(scanLineSeconds * sampleRate); luminanceSamples = (int) Math.round(luminanceSeconds * sampleRate); @@ -59,6 +61,11 @@ public class Robot_72_Color implements Mode { return 12; } + @Override + public int getFirstSyncPulseIndex() { + return firstSyncPulseIndex; + } + @Override public int getScanLineSamples() { return scanLineSamples;