From 3dfa1b4c86f4ed967790d9e98e1be934c13b3911 Mon Sep 17 00:00:00 2001 From: Ahmet Inan Date: Sun, 4 Jan 2015 17:47:28 +0100 Subject: [PATCH] added raw, toggles for debug and autodetect mode made debug mode much more useful --- README | 2 +- .../main/java/xdsopl/robot36/ImageView.java | 12 +- .../java/xdsopl/robot36/MainActivity.java | 18 +-- app/src/main/res/menu/menu_main.xml | 12 +- app/src/main/res/values/strings.xml | 7 +- app/src/main/rs/constants.rsh | 3 +- app/src/main/rs/decoder.rs | 119 ++++++++++++++---- app/src/main/rs/initialization.rsh | 2 + app/src/main/rs/modes.rsh | 48 +------ app/src/main/rs/state.rsh | 4 +- 10 files changed, 132 insertions(+), 95 deletions(-) diff --git a/README b/README index 9fb7d6f..2a15234 100644 --- a/README +++ b/README @@ -31,7 +31,7 @@ Martin Modes: 1 & 2 Scottie Modes: 1, 2 & DX Wrasse Modes: SC2 180 -Watching of old B/W or unsupported transmission modes works even in the raw "Debug Image" mode. +Watching of old B/W or unsupported transmission modes works even in the "Raw Mode". I created the "Robot36 SSTV Alpha Testers" Community, which you can join and help test prebuilt apk's from the Google Play Store for free: diff --git a/app/src/main/java/xdsopl/robot36/ImageView.java b/app/src/main/java/xdsopl/robot36/ImageView.java index b4098f1..5005baa 100644 --- a/app/src/main/java/xdsopl/robot36/ImageView.java +++ b/app/src/main/java/xdsopl/robot36/ImageView.java @@ -64,7 +64,7 @@ public class ImageView extends SurfaceView implements SurfaceHolder.Callback { private final Allocation rsDecoderSavedHeight; private final ScriptC_decoder rsDecoder; - private final int mode_debug = 0; + private final int mode_raw = 0; private final int mode_robot36 = 1; private final int mode_robot72 = 2; private final int mode_martin1 = 3; @@ -138,9 +138,9 @@ public class ImageView extends SurfaceView implements SurfaceHolder.Callback { void toggle_scaling() { intScale ^= true; } void softer_image() { rsDecoder.invoke_incr_blur(); } void sharper_image() { rsDecoder.invoke_decr_blur(); } - void debug_sync() { rsDecoder.invoke_debug_sync(); } - void debug_image() { rsDecoder.invoke_debug_image(); } - void debug_both() { rsDecoder.invoke_debug_both(); } + void toggle_debug() { rsDecoder.invoke_toggle_debug(); } + void toggle_auto() { rsDecoder.invoke_toggle_auto(); } + void raw_mode() { rsDecoder.invoke_raw_mode(); } void robot36_mode() { rsDecoder.invoke_robot36_mode(); } void robot72_mode() { rsDecoder.invoke_robot72_mode(); } void martin1_mode() { rsDecoder.invoke_martin1_mode(); } @@ -154,10 +154,10 @@ public class ImageView extends SurfaceView implements SurfaceHolder.Callback { void switch_mode(int mode) { switch (mode) { - case mode_debug: + case mode_raw: imageWidth = bitmap.getWidth(); imageHeight = bitmap.getHeight(); - updateTitle(R.string.action_debug_mode); + updateTitle(R.string.action_raw_mode); break; case mode_robot36: imageWidth = 320; diff --git a/app/src/main/java/xdsopl/robot36/MainActivity.java b/app/src/main/java/xdsopl/robot36/MainActivity.java index 4194138..59afd27 100644 --- a/app/src/main/java/xdsopl/robot36/MainActivity.java +++ b/app/src/main/java/xdsopl/robot36/MainActivity.java @@ -151,6 +151,15 @@ public class MainActivity extends Activity { case R.id.action_toggle_scaling: view.toggle_scaling(); return true; + case R.id.action_toggle_debug: + view.toggle_debug(); + return true; + case R.id.action_toggle_auto: + view.toggle_auto(); + return true; + case R.id.action_raw_mode: + view.raw_mode(); + return true; case R.id.action_robot36_mode: view.robot36_mode(); return true; @@ -175,15 +184,6 @@ public class MainActivity extends Activity { case R.id.action_wrasseSC2_180_mode: view.wrasseSC2_180_mode(); return true; - case R.id.action_debug_sync: - view.debug_sync(); - return true; - case R.id.action_debug_image: - view.debug_image(); - return true; - case R.id.action_debug_both: - view.debug_both(); - 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 919202e..0227b12 100644 --- a/app/src/main/res/menu/menu_main.xml +++ b/app/src/main/res/menu/menu_main.xml @@ -7,6 +7,12 @@ android:orderInCategory="100" android:showAsAction="never" /> + + + - - - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d3d9194..522ef17 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -3,10 +3,9 @@ Robot36 "decoder is running - Debug Sync - Debug Image - Debug Image and Sync - Debug Mode + Toggle Auto Mode + Toggle Debug Mode + Raw Mode Robot36 Mode Robot72 Mode Martin1 Mode diff --git a/app/src/main/rs/constants.rsh b/app/src/main/rs/constants.rsh index 43fbe4e..c1e7c9d 100644 --- a/app/src/main/rs/constants.rsh +++ b/app/src/main/rs/constants.rsh @@ -23,7 +23,7 @@ static const int decoder_yuv = 2; static const int decoder_rgb = 3; static const int decoder_scottie = 4; -static const int mode_debug = 0; +static const int mode_raw = 0; static const int mode_robot36 = 1; static const int mode_robot72 = 2; static const int mode_martin1 = 3; @@ -33,7 +33,6 @@ static const int mode_scottie2 = 6; static const int mode_scottieDX = 7; static const int mode_wrasseSC2_180 = 8; - static const float sync_buildup_ms = 1.1f; static const float robot36_scanline_ms = 150.0f; static const float robot72_scanline_ms = 300.0f; diff --git a/app/src/main/rs/decoder.rs b/app/src/main/rs/decoder.rs index 4932735..82a6749 100644 --- a/app/src/main/rs/decoder.rs +++ b/app/src/main/rs/decoder.rs @@ -77,23 +77,47 @@ static void robot36_decoder(int sync_timeout) mismatch_counter = 0; } prev_timeout = sync_timeout; - static int even_sync_pos, odd_sync_pos; - if (parity) { - odd_sync_pos = prev_sync_pos; - int even_vpos = vpos; - int odd_vpos = (vpos + 1) % maximum_height; + if (debug_mode) { 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); - uchar odd_y = value_blur(i, odd_sync_pos + y_begin, odd_sync_pos + y_end); - uchar u = value_blur(i, odd_sync_pos + u_begin, odd_sync_pos + u_end); - pixel_buffer[bitmap_width * even_vpos + i] = yuv(even_y, u, v); - pixel_buffer[bitmap_width * odd_vpos + i] = yuv(odd_y, u, v); + 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 (y_begin <= pos && pos < y_end) + r = b = 0; + if (parity) { + if (v_begin <= pos && pos < v_end) + g = b = 0; + if (u_sep_begin <= pos && pos < u_sep_end) + b = 128; + } else { + if (u_begin <= pos && pos < u_end) + r = g = 0; + if (v_sep_begin <= pos && pos < v_sep_end) + r = g = 128; + } + pixel_buffer[bitmap_width * vpos + i] = rgb(r, g, b); } - vpos += 2; latch = 0; + ++vpos; } else { - even_sync_pos = prev_sync_pos; + static int even_sync_pos, odd_sync_pos; + if (parity) { + odd_sync_pos = prev_sync_pos; + int even_vpos = vpos; + int odd_vpos = (vpos + 1) % maximum_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); + uchar odd_y = value_blur(i, odd_sync_pos + y_begin, odd_sync_pos + y_end); + uchar u = value_blur(i, odd_sync_pos + u_begin, odd_sync_pos + u_end); + 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; + latch = 0; + } else { + even_sync_pos = prev_sync_pos; + } } parity ^= 1; } @@ -101,10 +125,27 @@ static void robot36_decoder(int sync_timeout) static void yuv_decoder() { for (int i = 0; i < bitmap_width; ++i) { - uchar y = value_blur(i, y_begin + prev_sync_pos, y_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); - pixel_buffer[bitmap_width * vpos + i] = yuv(y, u, v); + if (debug_mode) { + 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_begin <= pos && pos < y_end) + r = b = 0; + if (u_begin <= pos && pos < u_end) + r = g = 0; + if (u_sep_begin <= pos && pos < u_sep_end) + b = 128; + if (v_sep_begin <= pos && pos < v_sep_end) + r = g = 128; + pixel_buffer[bitmap_width * vpos + i] = rgb(r, g, b); + } else { + uchar y = value_blur(i, y_begin + prev_sync_pos, y_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); + pixel_buffer[bitmap_width * vpos + i] = yuv(y, u, v); + } } ++vpos; } @@ -112,9 +153,21 @@ static void yuv_decoder() static void rgb_decoder() { for (int i = 0; i < bitmap_width; ++i) { - uchar r = value_blur(i, r_begin + prev_sync_pos, r_end + prev_sync_pos); - uchar g = value_blur(i, g_begin + prev_sync_pos, g_end + prev_sync_pos); - uchar b = value_blur(i, b_begin + prev_sync_pos, b_end + prev_sync_pos); + uchar r, g, b; + if (debug_mode) { + 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 (r_begin <= pos && pos < r_end) + g = b = 0; + if (g_begin <= pos && pos < g_end) + r = b = 0; + if (b_begin <= pos && pos < b_end) + r = g = 0; + } else { + r = value_blur(i, r_begin + prev_sync_pos, r_end + prev_sync_pos); + g = value_blur(i, g_begin + prev_sync_pos, g_end + prev_sync_pos); + b = value_blur(i, b_begin + prev_sync_pos, b_end + prev_sync_pos); + } pixel_buffer[bitmap_width * vpos + i] = rgb(r, g, b); } ++vpos; @@ -138,7 +191,25 @@ static void scottie_decoder() return; } first_sync = 1; - rgb_decoder(); + for (int i = 0; i < bitmap_width; ++i) { + uchar r, g, b; + if (debug_mode) { + r = g = b = value_blur(i, g_begin + prev_sync_pos, r_end + prev_sync_pos); + int pos = (i * (r_end - g_begin) + (r_end - g_begin) / 2) / bitmap_width + g_begin; + if (r_begin <= pos && pos < r_end) + g = b = 0; + if (g_begin <= pos && pos < g_end) + r = b = 0; + if (b_begin <= pos && pos < b_end) + r = g = 0; + } else { + r = value_blur(i, r_begin + prev_sync_pos, r_end + prev_sync_pos); + g = value_blur(i, g_begin + prev_sync_pos, g_end + prev_sync_pos); + b = value_blur(i, b_begin + prev_sync_pos, b_end + prev_sync_pos); + } + pixel_buffer[bitmap_width * vpos + i] = rgb(r, g, b); + } + ++vpos; } void decode(int samples) { @@ -162,8 +233,8 @@ void decode(int samples) { int cnt_active = dat_amp < 1.1f * cnt_amp; int dat_active = cnt_amp < 2.0f * dat_amp; - uchar cnt_level = save_cnt && cnt_active ? 127.5f - 127.5f * cnt_value : 0.0f; - uchar dat_level = save_dat && dat_active ? 127.5f + 127.5f * dat_value : 0.0f; + uchar cnt_level = debug_mode && cnt_active ? 127.5f - 127.5f * cnt_value : 0.0f; + uchar dat_level = dat_active ? 127.5f + 127.5f * dat_value : 0.0f; value_buffer[buffer_pos & buffer_mask] = cnt_level | dat_level; int cnt_quantized = round(cnt_value); @@ -177,7 +248,7 @@ void decode(int samples) { sync_pos = buffer_pos - sync_buildup_length; } - if (*current_mode != mode_debug) { + if (automatic_mode_detection) { int detected_mode = calibration_detector(dat_value, dat_amp, cnt_amp, cnt_quantized); if (detected_mode >= 0) { free_running = 0; diff --git a/app/src/main/rs/initialization.rsh b/app/src/main/rs/initialization.rsh index 0716e29..6c4417f 100644 --- a/app/src/main/rs/initialization.rsh +++ b/app/src/main/rs/initialization.rsh @@ -32,6 +32,8 @@ void initialize(float rate, int length, int width, int height) for (int i = 0; i < width * height; ++i) pixel_buffer[i] = 0; + automatic_mode_detection = 1; + debug_mode = 0; vpos = 0; hpos = 0; prev_sync_pos = sync_pos = 0; diff --git a/app/src/main/rs/modes.rsh b/app/src/main/rs/modes.rsh index fc003ce..44fe8f1 100644 --- a/app/src/main/rs/modes.rsh +++ b/app/src/main/rs/modes.rsh @@ -21,38 +21,18 @@ limitations under the License. #include "state.rsh" #include "exports.rsh" -void debug_sync() +void toggle_auto() { - save_cnt = 1; - save_dat = 0; - blur_power = -1; - *current_mode = mode_debug; - current_decoder = decoder_raw; - bitmap_width = maximum_width; - bitmap_height = maximum_height; - sync_length = minimum_sync_length; - maximum_length = buffer_length; - scanline_length = maximum_length; + automatic_mode_detection ^= 1; } -void debug_image() +void toggle_debug() { - save_dat = 1; - save_cnt = 0; - blur_power = -1; - *current_mode = mode_debug; - current_decoder = decoder_raw; - bitmap_width = maximum_width; - bitmap_height = maximum_height; - sync_length = minimum_sync_length; - maximum_length = buffer_length; - scanline_length = maximum_length; + debug_mode ^= 1; } -void debug_both() +void raw_mode() { - save_cnt = 1; - save_dat = 1; blur_power = -1; - *current_mode = mode_debug; + *current_mode = mode_raw; current_decoder = decoder_raw; bitmap_width = maximum_width; bitmap_height = maximum_height; @@ -62,8 +42,6 @@ void debug_both() } void robot36_mode() { - save_dat = 1; - save_cnt = 0; blur_power = 2; *current_mode = mode_robot36; current_decoder = decoder_robot36; @@ -98,8 +76,6 @@ void robot36_mode() } void robot72_mode() { - save_dat = 1; - save_cnt = 0; blur_power = 3; *current_mode = mode_robot72; current_decoder = decoder_yuv; @@ -142,8 +118,6 @@ void robot72_mode() } void martin1_mode() { - save_cnt = 0; - save_dat = 1; blur_power = 3; *current_mode = mode_martin1; current_decoder = decoder_rgb; @@ -176,8 +150,6 @@ void martin1_mode() } void martin2_mode() { - save_cnt = 0; - save_dat = 1; blur_power = 2; *current_mode = mode_martin2; current_decoder = decoder_rgb; @@ -210,8 +182,6 @@ void martin2_mode() } void scottie1_mode() { - save_cnt = 0; - save_dat = 1; blur_power = 3; *current_mode = mode_scottie1; current_decoder = decoder_scottie; @@ -244,8 +214,6 @@ void scottie1_mode() } void scottie2_mode() { - save_cnt = 0; - save_dat = 1; blur_power = 2; *current_mode = mode_scottie2; current_decoder = decoder_scottie; @@ -278,8 +246,6 @@ void scottie2_mode() } void scottieDX_mode() { - save_cnt = 0; - save_dat = 1; blur_power = 5; *current_mode = mode_scottieDX; current_decoder = decoder_scottie; @@ -312,8 +278,6 @@ void scottieDX_mode() } void wrasseSC2_180_mode() { - save_cnt = 0; - save_dat = 1; blur_power = 4; *current_mode = mode_wrasseSC2_180; current_decoder = decoder_rgb; diff --git a/app/src/main/rs/state.rsh b/app/src/main/rs/state.rsh index d47e4e9..61428f5 100644 --- a/app/src/main/rs/state.rsh +++ b/app/src/main/rs/state.rsh @@ -20,6 +20,8 @@ limitations under the License. static ema_t avg_amplitude, leader_lowpass; static ddc_t cnt_ddc, dat_ddc; static fmd_t cnt_fmd, dat_fmd; +static int automatic_mode_detection; +static int debug_mode; static int current_decoder; static int blur_power, free_running; static int sample_rate, sync_pos, prev_sync_pos; @@ -34,7 +36,7 @@ static int buffer_cleared; static int bitmap_width, bitmap_height; static int maximum_width, maximum_height; static int sync_length, sync_counter, vpos, hpos; -static int save_cnt, save_dat, seperator_counter, seperator_length; +static int seperator_counter, seperator_length; static int u_sep_begin, u_sep_end, v_sep_begin, v_sep_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;