diff --git a/app/src/main/java/xdsopl/robot36/Decoder.java b/app/src/main/java/xdsopl/robot36/Decoder.java
index 6c45fbc..ee9b52c 100644
--- a/app/src/main/java/xdsopl/robot36/Decoder.java
+++ b/app/src/main/java/xdsopl/robot36/Decoder.java
@@ -37,6 +37,8 @@ public class Decoder {
private final int channelConfig = AudioFormat.CHANNEL_IN_MONO;
private final int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
private final int sampleRate = 44100;
+ private final int maxHeight = freeRunReserve(496);
+ private final int maxWidth = 640;
private final short[] audioBuffer;
private final int[] pixelBuffer;
private final int[] spectrumBuffer;
@@ -70,6 +72,7 @@ public class Decoder {
private final int mode_scottie2 = 6;
private final int mode_scottieDX = 7;
private final int mode_wrasseSC2_180 = 8;
+ private final int mode_pd180 = 9;
private final Thread thread = new Thread() {
@Override
@@ -80,7 +83,7 @@ public class Decoder {
return;
if (drawImage) {
image.drawCanvas();
- if(enableAnalyzer) {
+ if (enableAnalyzer) {
spectrum.drawCanvas();
spectrogram.drawCanvas();
meter.drawCanvas();
@@ -98,7 +101,7 @@ public class Decoder {
this.spectrum = spectrum;
this.meter = meter;
this.activity = activity;
- pixelBuffer = new int[image.bitmap.getWidth() * image.bitmap.getHeight()];
+ pixelBuffer = new int[maxWidth * maxHeight];
spectrumBuffer = new int[spectrum.bitmap.getWidth() * spectrum.bitmap.getHeight()];
spectrogramBuffer = new int[spectrogram.bitmap.getWidth() * spectrogram.bitmap.getHeight()];
@@ -142,8 +145,7 @@ public class Decoder {
rsDecoder.bind_saved_height(rsDecoderSavedHeight);
rsDecoder.bind_volume(rsDecoderVolume);
rsDecoder.bind_saved_buffer(rsDecoderSavedBuffer);
- rsDecoder.invoke_initialize(sampleRate, valueBufferLength,
- image.bitmap.getWidth(), image.bitmap.getHeight(),
+ rsDecoder.invoke_initialize(sampleRate, valueBufferLength, maxWidth, maxHeight,
spectrum.bitmap.getWidth(), spectrum.bitmap.getHeight(),
spectrogram.bitmap.getWidth(), spectrogram.bitmap.getHeight());
@@ -166,8 +168,9 @@ public class Decoder {
void scottie2_mode() { rsDecoder.invoke_scottie2_mode(); }
void scottieDX_mode() { rsDecoder.invoke_scottieDX_mode(); }
void wrasseSC2_180_mode() { rsDecoder.invoke_wrasseSC2_180_mode(); }
+ void pd180_mode() { rsDecoder.invoke_pd180_mode(); }
-
+ int freeRunReserve(int height) { return (height * 3) / 2; }
void increaseUpdateRate() { updateRate = Math.min(4, updateRate + 1); }
void decreaseUpdateRate() { updateRate = Math.max(0, updateRate - 1); }
void updateTitle(int id) { activity.updateTitle(activity.getString(id)); }
@@ -176,50 +179,45 @@ public class Decoder {
{
switch (mode) {
case mode_raw:
- image.imageWidth = image.bitmap.getWidth();
- image.imageHeight = image.bitmap.getHeight();
+ image.setImageResolution(maxWidth, maxHeight);
updateTitle(R.string.action_raw_mode);
break;
case mode_robot36:
- image.imageWidth = 320;
- image.imageHeight = 240;
+ image.setImageResolution(320, freeRunReserve(240));
updateTitle(R.string.action_robot36_mode);
break;
case mode_robot72:
- image.imageWidth = 320;
- image.imageHeight = 240;
+ image.setImageResolution(320, freeRunReserve(240));
updateTitle(R.string.action_robot72_mode);
break;
case mode_martin1:
- image.imageWidth = 320;
- image.imageHeight = 256;
+ image.setImageResolution(320, freeRunReserve(256));
updateTitle(R.string.action_martin1_mode);
break;
case mode_martin2:
- image.imageWidth = 320;
- image.imageHeight = 256;
+ image.setImageResolution(320, freeRunReserve(256));
updateTitle(R.string.action_martin2_mode);
break;
case mode_scottie1:
- image.imageWidth = 320;
- image.imageHeight = 256;
+ image.setImageResolution(320, freeRunReserve(256));
updateTitle(R.string.action_scottie1_mode);
break;
case mode_scottie2:
- image.imageWidth = 320;
- image.imageHeight = 256;
+ image.setImageResolution(320, freeRunReserve(256));
updateTitle(R.string.action_scottie2_mode);
break;
case mode_scottieDX:
- image.imageWidth = 320;
- image.imageHeight = 256;
+ image.setImageResolution(320, freeRunReserve(256));
updateTitle(R.string.action_scottieDX_mode);
break;
case mode_wrasseSC2_180:
- image.imageWidth = 320;
- image.imageHeight = 256;
+ image.setImageResolution(320, freeRunReserve(256));
updateTitle(R.string.action_wrasseSC2_180_mode);
break;
+ case mode_pd180:
+ image.setImageResolution(640, freeRunReserve(496));
+ updateTitle(R.string.action_pd180_mode);
+ break;
default:
break;
}
@@ -256,12 +254,13 @@ public class Decoder {
rsDecoderAudioBuffer.copyFrom(audioBuffer);
rsDecoder.invoke_decode(samples);
- rsDecoderPixelBuffer.copyTo(pixelBuffer);
- image.bitmap.setPixels(pixelBuffer, 0, image.bitmap.getWidth(), 0, 0, image.bitmap.getWidth(), image.bitmap.getHeight());
rsDecoderCurrentMode.copyTo(currentMode);
switch_mode(currentMode[0]);
+ rsDecoderPixelBuffer.copyTo(pixelBuffer);
+ image.setPixels(pixelBuffer);
+
rsDecoderVolume.copyTo(volume);
meter.volume = volume[0];
diff --git a/app/src/main/java/xdsopl/robot36/ImageView.java b/app/src/main/java/xdsopl/robot36/ImageView.java
index 0412291..ac72a43 100644
--- a/app/src/main/java/xdsopl/robot36/ImageView.java
+++ b/app/src/main/java/xdsopl/robot36/ImageView.java
@@ -29,20 +29,36 @@ import android.graphics.Paint;
public class ImageView extends SurfaceView implements SurfaceHolder.Callback {
private int canvasWidth = -1, canvasHeight = -1;
private boolean cantTouchThis = true;
- public int imageWidth = 320;
- public int imageHeight = 240;
+ private int imageWidth = -1;
+ private int imageHeight = -1;
public boolean intScale = false;
private final SurfaceHolder holder;
- public final Bitmap bitmap;
+ public Bitmap bitmap = null;
private final Paint paint;
public ImageView(Context context, AttributeSet attrs) {
super(context, attrs);
holder = getHolder();
holder.addCallback(this);
-
paint = new Paint(Paint.FILTER_BITMAP_FLAG);
- bitmap = Bitmap.createBitmap(320, 384, Bitmap.Config.ARGB_8888);
+ }
+
+ public void setImageResolution(int width, int height) {
+ synchronized (holder) {
+ if (width != imageWidth || height != imageHeight) {
+ imageWidth = width;
+ imageHeight = height;
+ if (bitmap != null)
+ bitmap.recycle();
+ bitmap = Bitmap.createBitmap(imageWidth, imageHeight, Bitmap.Config.ARGB_8888);
+ }
+ }
+ }
+
+ public void setPixels(int pixels[]) {
+ synchronized (holder) {
+ bitmap.setPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
+ }
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
@@ -67,7 +83,7 @@ public class ImageView extends SurfaceView implements SurfaceHolder.Callback {
void drawCanvas() {
synchronized (holder) {
- if (cantTouchThis)
+ if (cantTouchThis || bitmap == null)
return;
Canvas canvas = null;
try {
diff --git a/app/src/main/java/xdsopl/robot36/MainActivity.java b/app/src/main/java/xdsopl/robot36/MainActivity.java
index ac9bcf5..e9f4c9b 100644
--- a/app/src/main/java/xdsopl/robot36/MainActivity.java
+++ b/app/src/main/java/xdsopl/robot36/MainActivity.java
@@ -240,6 +240,9 @@ public class MainActivity extends Activity {
case R.id.action_wrasseSC2_180_mode:
decoder.wrasseSC2_180_mode();
return true;
+ case R.id.action_pd180_mode:
+ decoder.pd180_mode();
+ return true;
}
return super.onOptionsItemSelected(item);
}
diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml
index a5d2391..56b1d3b 100644
--- a/app/src/main/res/menu/menu_main.xml
+++ b/app/src/main/res/menu/menu_main.xml
@@ -42,6 +42,8 @@
android:orderInCategory="100" android:showAsAction="never" />
+
- Raw Mode
Robot36 Mode
Robot72 Mode
+ PD180 Mode
Martin1 Mode
Martin2 Mode
Scottie1 Mode
diff --git a/app/src/main/rs/calibration_detector.rsh b/app/src/main/rs/calibration_detector.rsh
index d189111..02d87ab 100644
--- a/app/src/main/rs/calibration_detector.rsh
+++ b/app/src/main/rs/calibration_detector.rsh
@@ -114,6 +114,8 @@ static int calibration_detector(float dat_value, float dat_amp, float cnt_amp, i
return mode_scottieDX;
case 0xb7:
return mode_wrasseSC2_180;
+ case 0x60:
+ return mode_pd180;
default:
return -1;
}
diff --git a/app/src/main/rs/constants.rsh b/app/src/main/rs/constants.rsh
index 9e3bb0b..5d7a492 100644
--- a/app/src/main/rs/constants.rsh
+++ b/app/src/main/rs/constants.rsh
@@ -22,6 +22,7 @@ static const int decoder_robot36 = 1;
static const int decoder_yuv = 2;
static const int decoder_rgb = 3;
static const int decoder_scottie = 4;
+static const int decoder_pd = 5;
static const int mode_raw = 0;
static const int mode_robot36 = 1;
@@ -32,6 +33,7 @@ static const int mode_scottie1 = 5;
static const int mode_scottie2 = 6;
static const int mode_scottieDX = 7;
static const int mode_wrasseSC2_180 = 8;
+static const int mode_pd180 = 9;
static const float sync_buildup_ms = 1.1f;
static const float scanline_tolerance = 0.05f;
@@ -43,5 +45,6 @@ static const float scottie1_scanline_ms = 428.22f;
static const float scottie2_scanline_ms = 277.692f;
static const float scottieDX_scanline_ms = 1050.3f;
static const float wrasseSC2_180_scanline_ms = 711.0225f;
+static const float pd180_scanline_ms = 754.24f;
#endif
\ No newline at end of file
diff --git a/app/src/main/rs/decoder.rs b/app/src/main/rs/decoder.rs
index 3b139f6..739d536 100644
--- a/app/src/main/rs/decoder.rs
+++ b/app/src/main/rs/decoder.rs
@@ -99,7 +99,7 @@ static void robot36_decoder(int sync_timeout)
if (parity) {
odd_sync_pos = prev_sync_pos;
int even_vpos = vpos;
- int odd_vpos = (vpos + 1) % maximum_height;
+ int odd_vpos = (vpos + 1) % freerun_height;
for (int i = 0; i < bitmap_width; ++i) {
uchar even_y = value_blur(i, even_sync_pos + y_begin, even_sync_pos + y_end);
uchar v = value_blur(i, even_sync_pos + v_begin, even_sync_pos + v_end);
@@ -145,6 +145,37 @@ static void yuv_decoder()
++vpos;
}
+static void pd_decoder()
+{
+ if (debug_mode) {
+ for (int i = 0; i < bitmap_width; ++i) {
+ uchar r, g, b;
+ r = g = b = value_blur(i, prev_sync_pos, sync_pos);
+ int pos = (i * (sync_pos - prev_sync_pos) + (sync_pos - prev_sync_pos) / 2) / bitmap_width;
+ if (v_begin <= pos && pos < v_end)
+ g = b = 0;
+ if ((y_even_begin <= pos && pos < y_even_end) || (y_odd_begin <= pos && pos < y_odd_end))
+ r = b = 0;
+ if (u_begin <= pos && pos < u_end)
+ r = g = 0;
+ pixel_buffer[bitmap_width * vpos + i] = rgb(r, g, b);
+ }
+ ++vpos;
+ } else {
+ int even_vpos = vpos;
+ int odd_vpos = (vpos + 1) % freerun_height;
+ for (int i = 0; i < bitmap_width; ++i) {
+ uchar odd_y = value_blur(i, y_odd_begin + prev_sync_pos, y_odd_end + prev_sync_pos);
+ uchar u = value_blur(i, u_begin + prev_sync_pos, u_end + prev_sync_pos);
+ uchar v = value_blur(i, v_begin + prev_sync_pos, v_end + prev_sync_pos);
+ uchar even_y = value_blur(i, y_even_begin + prev_sync_pos, y_even_end + prev_sync_pos);
+ pixel_buffer[bitmap_width * even_vpos + i] = yuv(even_y, u, v);
+ pixel_buffer[bitmap_width * odd_vpos + i] = yuv(odd_y, u, v);
+ }
+ vpos += 2;
+ }
+}
+
static void rgb_decoder()
{
for (int i = 0; i < bitmap_width; ++i) {
@@ -306,6 +337,9 @@ void decode(int samples) {
case decoder_robot36:
robot36_decoder(sync_timeout);
break;
+ case decoder_pd:
+ pd_decoder();
+ break;
case decoder_yuv:
yuv_decoder();
break;
@@ -320,8 +354,8 @@ void decode(int samples) {
}
if (vpos >= bitmap_height)
save_buffer();
- if (vpos >= maximum_height)
- vpos -= maximum_height;
+ if (vpos >= freerun_height)
+ vpos -= freerun_height;
seperator_counter = 0;
}
}
diff --git a/app/src/main/rs/initialization.rsh b/app/src/main/rs/initialization.rsh
index 77653db..9a736d7 100644
--- a/app/src/main/rs/initialization.rsh
+++ b/app/src/main/rs/initialization.rsh
@@ -56,6 +56,7 @@ void initialize(float rate, int length, int iw, int ih, int sw, int sh, int sgw,
scottie2_scanline_length = round((scottie2_scanline_ms * sample_rate) / 1000.0f);
scottieDX_scanline_length = round((scottieDX_scanline_ms * sample_rate) / 1000.0f);
wrasseSC2_180_scanline_length = round((wrasseSC2_180_scanline_ms * sample_rate) / 1000.0f);
+ pd180_scanline_length = round((pd180_scanline_ms * sample_rate) / 1000.0f);
const float pairwise_minimum_of_scanline_time_distances = 0.018226f;
maximum_absolute_deviaton = 0.5f * pairwise_minimum_of_scanline_time_distances * sample_rate;
diff --git a/app/src/main/rs/modes.rsh b/app/src/main/rs/modes.rsh
index 0c5afaa..cc81b35 100644
--- a/app/src/main/rs/modes.rsh
+++ b/app/src/main/rs/modes.rsh
@@ -21,6 +21,10 @@ limitations under the License.
#include "state.rsh"
#include "exports.rsh"
+static int freerun_reserve(int height)
+{
+ return (height * 3) / 2;
+}
void toggle_auto()
{
automatic_mode_detection ^= 1;
@@ -34,6 +38,7 @@ void raw_mode()
blur_power = -1;
*current_mode = mode_raw;
current_decoder = decoder_raw;
+ freerun_height = maximum_height;
bitmap_width = maximum_width;
bitmap_height = maximum_height;
sync_length = minimum_sync_length;
@@ -48,6 +53,7 @@ void robot36_mode()
current_decoder = decoder_robot36;
bitmap_width = 320;
bitmap_height = 240;
+ freerun_height = freerun_reserve(bitmap_height);
const float tolerance = 0.8f;
const float sync_ms = 9.0f;
const float sync_porch_ms = 3.0f;
@@ -83,6 +89,7 @@ void robot72_mode()
current_decoder = decoder_yuv;
bitmap_width = 320;
bitmap_height = 240;
+ freerun_height = freerun_reserve(bitmap_height);
const float tolerance = 0.8f;
const float sync_ms = 9.0f;
const float sync_porch_ms = 3.0f;
@@ -119,6 +126,42 @@ void robot72_mode()
minimum_length = ((1.0f - scanline_tolerance) * robot72_scanline_ms * sample_rate) / 1000.0f;
maximum_length = ((1.0f + scanline_tolerance) * robot72_scanline_ms * sample_rate) / 1000.0f;
}
+void pd180_mode()
+{
+ blur_power = 3;
+ *current_mode = mode_pd180;
+ current_decoder = decoder_pd;
+ bitmap_width = 640;
+ bitmap_height = 496;
+ freerun_height = freerun_reserve(bitmap_height);
+ const float tolerance = 0.8f;
+ const float sync_ms = 20.0f;
+ const float porch_ms = 2.08f;
+ const float yuv_scan_ms = 183.04f;
+ sync_length = tolerance * (sync_ms * sample_rate) / 1000.0f;
+
+ float y_odd_begin_ms = porch_ms;
+ float y_odd_end_ms = y_odd_begin_ms + yuv_scan_ms;
+ float v_begin_ms = y_odd_end_ms;
+ float v_end_ms = v_begin_ms + yuv_scan_ms;
+ float u_begin_ms = v_end_ms;
+ float u_end_ms = u_begin_ms + yuv_scan_ms;
+ float y_even_begin_ms = u_end_ms;
+ float y_even_end_ms = y_even_begin_ms + yuv_scan_ms;
+
+ y_odd_begin = round((y_odd_begin_ms * sample_rate) / 1000.0f);
+ y_odd_end = round((y_odd_end_ms * sample_rate) / 1000.0f);
+ v_begin = round((v_begin_ms * sample_rate) / 1000.0f);
+ v_end = round((v_end_ms * sample_rate) / 1000.0f);
+ u_begin = round((u_begin_ms * sample_rate) / 1000.0f);
+ u_end = round((u_end_ms * sample_rate) / 1000.0f);
+ y_even_begin = round((y_even_begin_ms * sample_rate) / 1000.0f);
+ y_even_end = round((y_even_end_ms * sample_rate) / 1000.0f);
+
+ scanline_length = pd180_scanline_length;
+ minimum_length = ((1.0f - scanline_tolerance) * pd180_scanline_ms * sample_rate) / 1000.0f;
+ maximum_length = ((1.0f + scanline_tolerance) * pd180_scanline_ms * sample_rate) / 1000.0f;
+}
void martin1_mode()
{
blur_power = 3;
@@ -126,6 +169,7 @@ void martin1_mode()
current_decoder = decoder_rgb;
bitmap_width = 320;
bitmap_height = 256;
+ freerun_height = freerun_reserve(bitmap_height);
const float tolerance = 0.5f;
const float sync_ms = 4.862f;
const float sync_porch_ms = 0.572f;
@@ -159,6 +203,7 @@ void martin2_mode()
current_decoder = decoder_rgb;
bitmap_width = 320;
bitmap_height = 256;
+ freerun_height = freerun_reserve(bitmap_height);
const float tolerance = 0.5f;
const float sync_ms = 4.862f;
const float sync_porch_ms = 0.572f;
@@ -192,6 +237,7 @@ void scottie1_mode()
current_decoder = decoder_scottie;
bitmap_width = 320;
bitmap_height = 256;
+ freerun_height = freerun_reserve(bitmap_height);
const float tolerance = 0.8f;
const float sync_ms = 9.0f;
const float sync_porch_ms = 1.5f;
@@ -225,6 +271,7 @@ void scottie2_mode()
current_decoder = decoder_scottie;
bitmap_width = 320;
bitmap_height = 256;
+ freerun_height = freerun_reserve(bitmap_height);
const float tolerance = 0.8f;
const float sync_ms = 9.0f;
const float sync_porch_ms = 1.5f;
@@ -258,6 +305,7 @@ void scottieDX_mode()
current_decoder = decoder_scottie;
bitmap_width = 320;
bitmap_height = 256;
+ freerun_height = freerun_reserve(bitmap_height);
const float tolerance = 0.8f;
const float sync_ms = 9.0f;
const float sync_porch_ms = 1.5f;
@@ -291,6 +339,7 @@ void wrasseSC2_180_mode()
current_decoder = decoder_rgb;
bitmap_width = 320;
bitmap_height = 256;
+ freerun_height = freerun_reserve(bitmap_height);
const float tolerance = 0.5f;
const float sync_ms = 5.5225f;
const float sync_porch_ms = 0.5f;
@@ -345,6 +394,9 @@ static void switch_mode(int new_mode)
case mode_wrasseSC2_180:
wrasseSC2_180_mode();
break;
+ case mode_pd180:
+ pd180_mode();
+ break;
default:
return;
}
diff --git a/app/src/main/rs/scanline_estimator.rsh b/app/src/main/rs/scanline_estimator.rsh
index abe68c1..fac7bc3 100644
--- a/app/src/main/rs/scanline_estimator.rsh
+++ b/app/src/main/rs/scanline_estimator.rsh
@@ -53,15 +53,19 @@ static int scanline_estimator(int sync_level)
int scottie2_adev = abs(mean - scottie2_scanline_length);
int scottieDX_adev = abs(mean - scottieDX_scanline_length);
int wrasseSC2_180_adev = abs(mean - wrasseSC2_180_scanline_length);
+ int pd180_adev = abs(mean - pd180_scanline_length);
int min_adev = min(
min(
- min(robot36_adev, robot72_adev),
- min(martin1_adev, martin2_adev)
- ), min(
- min(scottie1_adev, scottie2_adev),
- min(scottieDX_adev, wrasseSC2_180_adev)
- )
+ min(
+ min(robot36_adev, robot72_adev),
+ min(martin1_adev, martin2_adev)
+ ), min(
+ min(scottie1_adev, scottie2_adev),
+ min(scottieDX_adev, wrasseSC2_180_adev)
+ )
+ ),
+ pd180_adev
);
if (min_adev > maximum_absolute_deviaton)
@@ -82,6 +86,8 @@ static int scanline_estimator(int sync_level)
return mode_scottieDX;
else if (min_adev == wrasseSC2_180_adev)
return mode_wrasseSC2_180;
+ else if (min_adev == pd180_adev)
+ return mode_pd180;
return -1;
}
diff --git a/app/src/main/rs/state.rsh b/app/src/main/rs/state.rsh
index 051d3f9..509116f 100644
--- a/app/src/main/rs/state.rsh
+++ b/app/src/main/rs/state.rsh
@@ -37,11 +37,13 @@ static int buffer_length, buffer_mask, buffer_pos;
static int buffer_cleared;
static int bitmap_width, bitmap_height;
static int maximum_width, maximum_height;
+static int freerun_height;
static int spectrum_width, spectrum_height;
static int spectrogram_width, spectrogram_height;
static int sync_length, sync_counter, vpos, hpos;
static int seperator_counter, seperator_length;
static int u_sep_begin, u_sep_end, v_sep_begin, v_sep_end;
+static int y_even_begin, y_even_end, y_odd_begin, y_odd_end;
static int y_begin, y_end, u_begin, u_end, v_begin, v_end;
static int r_begin, r_end, b_begin, b_end, g_begin, g_end;
static int sync_buildup_length;
@@ -53,5 +55,6 @@ static int scottie1_scanline_length;
static int scottie2_scanline_length;
static int scottieDX_scanline_length;
static int wrasseSC2_180_scanline_length;
+static int pd180_scanline_length;
#endif
\ No newline at end of file