kopia lustrzana https://github.com/xdsopl/robot36
added automatic mode selection from naive scanline time estimation
rodzic
969da36a12
commit
ce67fd49f4
|
@ -45,6 +45,57 @@ static float ema_a(float cutoff, float rate, int order)
|
||||||
return dt / (RC + dt);
|
return dt / (RC + dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const float ema_estimator_a = 0.7f;
|
||||||
|
static int robot36_scanline_length;
|
||||||
|
static float robot36_estimator(int length)
|
||||||
|
{
|
||||||
|
static float variance;
|
||||||
|
float deviation = robot36_scanline_length - length;
|
||||||
|
return variance = ema_estimator_a * deviation * deviation + (1.0f - ema_estimator_a) * variance;
|
||||||
|
}
|
||||||
|
static int robot72_scanline_length;
|
||||||
|
static float robot72_estimator(int length)
|
||||||
|
{
|
||||||
|
static float variance;
|
||||||
|
float deviation = robot72_scanline_length - length;
|
||||||
|
return variance = ema_estimator_a * deviation * deviation + (1.0f - ema_estimator_a) * variance;
|
||||||
|
}
|
||||||
|
static int martin1_scanline_length;
|
||||||
|
static float martin1_estimator(int length)
|
||||||
|
{
|
||||||
|
static float variance;
|
||||||
|
float deviation = martin1_scanline_length - length;
|
||||||
|
return variance = ema_estimator_a * deviation * deviation + (1.0f - ema_estimator_a) * variance;
|
||||||
|
}
|
||||||
|
static int martin2_scanline_length;
|
||||||
|
static float martin2_estimator(int length)
|
||||||
|
{
|
||||||
|
static float variance;
|
||||||
|
float deviation = martin2_scanline_length - length;
|
||||||
|
return variance = ema_estimator_a * deviation * deviation + (1.0f - ema_estimator_a) * variance;
|
||||||
|
}
|
||||||
|
static int scottie1_scanline_length;
|
||||||
|
static float scottie1_estimator(int length)
|
||||||
|
{
|
||||||
|
static float variance;
|
||||||
|
float deviation = scottie1_scanline_length - length;
|
||||||
|
return variance = ema_estimator_a * deviation * deviation + (1.0f - ema_estimator_a) * variance;
|
||||||
|
}
|
||||||
|
static int scottie2_scanline_length;
|
||||||
|
static float scottie2_estimator(int length)
|
||||||
|
{
|
||||||
|
static float variance;
|
||||||
|
float deviation = scottie2_scanline_length - length;
|
||||||
|
return variance = ema_estimator_a * deviation * deviation + (1.0f - ema_estimator_a) * variance;
|
||||||
|
}
|
||||||
|
static int scottieDX_scanline_length;
|
||||||
|
static float scottieDX_estimator(int length)
|
||||||
|
{
|
||||||
|
static float variance;
|
||||||
|
float deviation = scottieDX_scanline_length - length;
|
||||||
|
return variance = ema_estimator_a * deviation * deviation + (1.0f - ema_estimator_a) * variance;
|
||||||
|
}
|
||||||
|
|
||||||
static float ema_power_a;
|
static float ema_power_a;
|
||||||
static float avg_power(float input)
|
static float avg_power(float input)
|
||||||
{
|
{
|
||||||
|
@ -125,6 +176,7 @@ static float dat_fmd(float2 baseband)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sample_rate, mode, even_hpos;
|
static int sample_rate, mode, even_hpos;
|
||||||
|
static int maximum_variance, minimum_sync_length;
|
||||||
static int scanline_length, minimum_length, maximum_length;
|
static int scanline_length, minimum_length, maximum_length;
|
||||||
static int vis_timeout, vis_length, bit_length;
|
static int vis_timeout, vis_length, bit_length;
|
||||||
static int break_timeout, break_length;
|
static int break_timeout, break_length;
|
||||||
|
@ -139,16 +191,27 @@ static int r_begin, r_end, b_begin, b_end, g_begin, g_end;
|
||||||
|
|
||||||
static const int mode_raw = 0;
|
static const int mode_raw = 0;
|
||||||
static const int mode_robot36 = 1;
|
static const int mode_robot36 = 1;
|
||||||
static const int mode_yuv = 2;
|
static const int mode_robot72 = 2;
|
||||||
static const int mode_rgb = 3;
|
static const int mode_martin1 = 3;
|
||||||
|
static const int mode_martin2 = 4;
|
||||||
|
static const int mode_scottie1 = 5;
|
||||||
|
static const int mode_scottie2 = 6;
|
||||||
|
static const int mode_scottieDX = 7;
|
||||||
|
|
||||||
|
static const float robot36_scanline_seconds = 0.15f;
|
||||||
|
static const float robot72_scanline_seconds = 0.3f;
|
||||||
|
static const float martin1_scanline_seconds = 0.446446f;
|
||||||
|
static const float martin2_scanline_seconds = 0.226798f;
|
||||||
|
static const float scottie1_scanline_seconds = 0.42822f;
|
||||||
|
static const float scottie2_scanline_seconds = 0.277692f;
|
||||||
|
static const float scottieDX_scanline_seconds = 1.0503f;
|
||||||
|
|
||||||
void debug_sync()
|
void debug_sync()
|
||||||
{
|
{
|
||||||
save_cnt = 1;
|
save_cnt = 1;
|
||||||
save_dat = 0;
|
save_dat = 0;
|
||||||
mode = mode_raw;
|
mode = mode_raw;
|
||||||
const float sync_len_min = 0.002f;
|
sync_length = minimum_sync_length;
|
||||||
sync_length = sync_len_min * sample_rate;
|
|
||||||
maximum_length = buffer_length;
|
maximum_length = buffer_length;
|
||||||
scanline_length = maximum_length;
|
scanline_length = maximum_length;
|
||||||
}
|
}
|
||||||
|
@ -157,8 +220,7 @@ void debug_image()
|
||||||
save_dat = 1;
|
save_dat = 1;
|
||||||
save_cnt = 0;
|
save_cnt = 0;
|
||||||
mode = mode_raw;
|
mode = mode_raw;
|
||||||
const float sync_len_min = 0.002f;
|
sync_length = minimum_sync_length;
|
||||||
sync_length = sync_len_min * sample_rate;
|
|
||||||
maximum_length = buffer_length;
|
maximum_length = buffer_length;
|
||||||
scanline_length = maximum_length;
|
scanline_length = maximum_length;
|
||||||
}
|
}
|
||||||
|
@ -167,8 +229,7 @@ void debug_both()
|
||||||
save_cnt = 1;
|
save_cnt = 1;
|
||||||
save_dat = 1;
|
save_dat = 1;
|
||||||
mode = mode_raw;
|
mode = mode_raw;
|
||||||
const float sync_len_min = 0.002f;
|
sync_length = minimum_sync_length;
|
||||||
sync_length = sync_len_min * sample_rate;
|
|
||||||
maximum_length = buffer_length;
|
maximum_length = buffer_length;
|
||||||
scanline_length = maximum_length;
|
scanline_length = maximum_length;
|
||||||
}
|
}
|
||||||
|
@ -198,15 +259,14 @@ void robot36_mode()
|
||||||
v_sep_end = u_sep_end;
|
v_sep_end = u_sep_end;
|
||||||
v_begin = v_sep_end + sep_porch_len * sample_rate;
|
v_begin = v_sep_end + sep_porch_len * sample_rate;
|
||||||
v_end = v_begin + v_scan_len * sample_rate;
|
v_end = v_begin + v_scan_len * sample_rate;
|
||||||
scanline_length = (sync_len + sync_porch_len + y_scan_len
|
scanline_length = robot36_scanline_length;
|
||||||
+ seperator_len + sep_porch_len + u_scan_len) * sample_rate;
|
|
||||||
maximum_length = scanline_length + sync_porch_len * sample_rate;
|
maximum_length = scanline_length + sync_porch_len * sample_rate;
|
||||||
}
|
}
|
||||||
void robot72_mode()
|
void robot72_mode()
|
||||||
{
|
{
|
||||||
save_dat = 1;
|
save_dat = 1;
|
||||||
save_cnt = 0;
|
save_cnt = 0;
|
||||||
mode = mode_yuv;
|
mode = mode_robot72;
|
||||||
const float tolerance = 0.8f;
|
const float tolerance = 0.8f;
|
||||||
const float settling_time = 0.0011f;
|
const float settling_time = 0.0011f;
|
||||||
const float sync_len = 0.009f;
|
const float sync_len = 0.009f;
|
||||||
|
@ -228,16 +288,14 @@ void robot72_mode()
|
||||||
v_sep_end = v_sep_begin + seperator_len * sample_rate;
|
v_sep_end = v_sep_begin + seperator_len * sample_rate;
|
||||||
v_begin = v_sep_end + sep_porch_len * sample_rate;
|
v_begin = v_sep_end + sep_porch_len * sample_rate;
|
||||||
v_end = v_begin + v_scan_len * sample_rate;
|
v_end = v_begin + v_scan_len * sample_rate;
|
||||||
scanline_length = (sync_len + sync_porch_len + y_scan_len
|
scanline_length = robot72_scanline_length;
|
||||||
+ seperator_len + sep_porch_len + u_scan_len
|
|
||||||
+ seperator_len + sep_porch_len + v_scan_len) * sample_rate;
|
|
||||||
maximum_length = scanline_length + sync_porch_len * sample_rate;
|
maximum_length = scanline_length + sync_porch_len * sample_rate;
|
||||||
}
|
}
|
||||||
void martin1_mode()
|
void martin1_mode()
|
||||||
{
|
{
|
||||||
save_cnt = 0;
|
save_cnt = 0;
|
||||||
save_dat = 1;
|
save_dat = 1;
|
||||||
mode = mode_rgb;
|
mode = mode_martin1;
|
||||||
const float tolerance = 0.5f;
|
const float tolerance = 0.5f;
|
||||||
const float sync_len = 0.004862f;
|
const float sync_len = 0.004862f;
|
||||||
const float sync_porch_len = 0.000572f;
|
const float sync_porch_len = 0.000572f;
|
||||||
|
@ -253,15 +311,14 @@ void martin1_mode()
|
||||||
b_end = b_begin + b_scan_len * sample_rate;
|
b_end = b_begin + b_scan_len * sample_rate;
|
||||||
r_begin = b_end + seperator_len * sample_rate;
|
r_begin = b_end + seperator_len * sample_rate;
|
||||||
r_end = r_begin + r_scan_len * sample_rate;
|
r_end = r_begin + r_scan_len * sample_rate;
|
||||||
scanline_length = (sync_len + sync_porch_len + g_scan_len + seperator_len
|
scanline_length = martin1_scanline_length;
|
||||||
+ b_scan_len + seperator_len + r_scan_len + seperator_len) * sample_rate;
|
|
||||||
maximum_length = scanline_length + sync_porch_len * sample_rate;
|
maximum_length = scanline_length + sync_porch_len * sample_rate;
|
||||||
}
|
}
|
||||||
void martin2_mode()
|
void martin2_mode()
|
||||||
{
|
{
|
||||||
save_cnt = 0;
|
save_cnt = 0;
|
||||||
save_dat = 1;
|
save_dat = 1;
|
||||||
mode = mode_rgb;
|
mode = mode_martin2;
|
||||||
const float tolerance = 0.5f;
|
const float tolerance = 0.5f;
|
||||||
const float sync_len = 0.004862f;
|
const float sync_len = 0.004862f;
|
||||||
const float sync_porch_len = 0.000572f;
|
const float sync_porch_len = 0.000572f;
|
||||||
|
@ -277,15 +334,14 @@ void martin2_mode()
|
||||||
b_end = b_begin + b_scan_len * sample_rate;
|
b_end = b_begin + b_scan_len * sample_rate;
|
||||||
r_begin = b_end + seperator_len * sample_rate;
|
r_begin = b_end + seperator_len * sample_rate;
|
||||||
r_end = r_begin + r_scan_len * sample_rate;
|
r_end = r_begin + r_scan_len * sample_rate;
|
||||||
scanline_length = (sync_len + sync_porch_len + g_scan_len + seperator_len
|
scanline_length = martin2_scanline_length;
|
||||||
+ b_scan_len + seperator_len + r_scan_len + seperator_len) * sample_rate;
|
|
||||||
maximum_length = scanline_length + sync_porch_len * sample_rate;
|
maximum_length = scanline_length + sync_porch_len * sample_rate;
|
||||||
}
|
}
|
||||||
void scottie1_mode()
|
void scottie1_mode()
|
||||||
{
|
{
|
||||||
save_cnt = 0;
|
save_cnt = 0;
|
||||||
save_dat = 1;
|
save_dat = 1;
|
||||||
mode = mode_rgb;
|
mode = mode_scottie1;
|
||||||
const float tolerance = 0.8f;
|
const float tolerance = 0.8f;
|
||||||
const float settling_time = 0.0011f;
|
const float settling_time = 0.0011f;
|
||||||
const float sync_len = 0.009f;
|
const float sync_len = 0.009f;
|
||||||
|
@ -302,15 +358,14 @@ void scottie1_mode()
|
||||||
g_end = g_begin + g_scan_len * sample_rate;
|
g_end = g_begin + g_scan_len * sample_rate;
|
||||||
b_begin = g_end + seperator_len * sample_rate;
|
b_begin = g_end + seperator_len * sample_rate;
|
||||||
b_end = b_begin + b_scan_len * sample_rate;
|
b_end = b_begin + b_scan_len * sample_rate;
|
||||||
scanline_length = (sync_len + sync_porch_len + g_scan_len + seperator_len
|
scanline_length = scottie1_scanline_length;
|
||||||
+ b_scan_len + seperator_len + r_scan_len) * sample_rate;
|
|
||||||
maximum_length = scanline_length + sync_porch_len * sample_rate;
|
maximum_length = scanline_length + sync_porch_len * sample_rate;
|
||||||
}
|
}
|
||||||
void scottie2_mode()
|
void scottie2_mode()
|
||||||
{
|
{
|
||||||
save_cnt = 0;
|
save_cnt = 0;
|
||||||
save_dat = 1;
|
save_dat = 1;
|
||||||
mode = mode_rgb;
|
mode = mode_scottie2;
|
||||||
const float tolerance = 0.8f;
|
const float tolerance = 0.8f;
|
||||||
const float settling_time = 0.0011f;
|
const float settling_time = 0.0011f;
|
||||||
const float sync_len = 0.009f;
|
const float sync_len = 0.009f;
|
||||||
|
@ -327,15 +382,14 @@ void scottie2_mode()
|
||||||
g_end = g_begin + g_scan_len * sample_rate;
|
g_end = g_begin + g_scan_len * sample_rate;
|
||||||
b_begin = g_end + seperator_len * sample_rate;
|
b_begin = g_end + seperator_len * sample_rate;
|
||||||
b_end = b_begin + b_scan_len * sample_rate;
|
b_end = b_begin + b_scan_len * sample_rate;
|
||||||
scanline_length = (sync_len + sync_porch_len + g_scan_len + seperator_len
|
scanline_length = scottie2_scanline_length;
|
||||||
+ b_scan_len + seperator_len + r_scan_len) * sample_rate;
|
|
||||||
maximum_length = scanline_length + sync_porch_len * sample_rate;
|
maximum_length = scanline_length + sync_porch_len * sample_rate;
|
||||||
}
|
}
|
||||||
void scottieDX_mode()
|
void scottieDX_mode()
|
||||||
{
|
{
|
||||||
save_cnt = 0;
|
save_cnt = 0;
|
||||||
save_dat = 1;
|
save_dat = 1;
|
||||||
mode = mode_rgb;
|
mode = mode_scottieDX;
|
||||||
const float tolerance = 0.8f;
|
const float tolerance = 0.8f;
|
||||||
const float settling_time = 0.0011f;
|
const float settling_time = 0.0011f;
|
||||||
const float sync_len = 0.009f;
|
const float sync_len = 0.009f;
|
||||||
|
@ -352,8 +406,7 @@ void scottieDX_mode()
|
||||||
g_end = g_begin + g_scan_len * sample_rate;
|
g_end = g_begin + g_scan_len * sample_rate;
|
||||||
b_begin = g_end + seperator_len * sample_rate;
|
b_begin = g_end + seperator_len * sample_rate;
|
||||||
b_end = b_begin + b_scan_len * sample_rate;
|
b_end = b_begin + b_scan_len * sample_rate;
|
||||||
scanline_length = (sync_len + sync_porch_len + g_scan_len + seperator_len
|
scanline_length = scottieDX_scanline_length;
|
||||||
+ b_scan_len + seperator_len + r_scan_len) * sample_rate;
|
|
||||||
maximum_length = scanline_length + sync_porch_len * sample_rate;
|
maximum_length = scanline_length + sync_porch_len * sample_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,6 +423,19 @@ void initialize(float rate, int length, int width, int height)
|
||||||
sync_counter = 0;
|
sync_counter = 0;
|
||||||
seperator_counter = 0;
|
seperator_counter = 0;
|
||||||
minimum_length = 0.05f * sample_rate;
|
minimum_length = 0.05f * sample_rate;
|
||||||
|
minimum_sync_length = 0.002f * sample_rate;
|
||||||
|
|
||||||
|
robot36_scanline_length = robot36_scanline_seconds * sample_rate;
|
||||||
|
robot72_scanline_length = robot72_scanline_seconds * sample_rate;
|
||||||
|
martin1_scanline_length = martin1_scanline_seconds * sample_rate;
|
||||||
|
martin2_scanline_length = martin2_scanline_seconds * sample_rate;
|
||||||
|
scottie1_scanline_length = scottie1_scanline_seconds * sample_rate;
|
||||||
|
scottie2_scanline_length = scottie2_scanline_seconds * sample_rate;
|
||||||
|
scottieDX_scanline_length = scottieDX_scanline_seconds * sample_rate;
|
||||||
|
|
||||||
|
const float pairwise_minimum_of_scanline_time_distances = 0.018226f;
|
||||||
|
float deviation = pairwise_minimum_of_scanline_time_distances * sample_rate;
|
||||||
|
maximum_variance = deviation * deviation;
|
||||||
|
|
||||||
const float first_leader_tolerance = 0.3f;
|
const float first_leader_tolerance = 0.3f;
|
||||||
const float second_leader_tolerance = 0.9f;
|
const float second_leader_tolerance = 0.9f;
|
||||||
|
@ -491,6 +557,80 @@ static void reset()
|
||||||
pixel_buffer[i] = rgb(0, 0, 0);
|
pixel_buffer[i] = rgb(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void scanline_estimator(int sync_level)
|
||||||
|
{
|
||||||
|
static scanline_counter, sync_counter;
|
||||||
|
|
||||||
|
int sync_pulse = !sync_level && sync_counter >= minimum_sync_length;
|
||||||
|
sync_counter = sync_level ? sync_counter + 1 : 0;
|
||||||
|
|
||||||
|
if (!sync_pulse) {
|
||||||
|
++scanline_counter;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float robot36_var = robot36_estimator(scanline_counter);
|
||||||
|
float robot72_var = robot72_estimator(scanline_counter);
|
||||||
|
float martin1_var = martin1_estimator(scanline_counter);
|
||||||
|
float martin2_var = martin2_estimator(scanline_counter);
|
||||||
|
float scottie1_var = scottie1_estimator(scanline_counter);
|
||||||
|
float scottie2_var = scottie2_estimator(scanline_counter);
|
||||||
|
float scottieDX_var = scottieDX_estimator(scanline_counter);
|
||||||
|
scanline_counter = 0;
|
||||||
|
|
||||||
|
float min_var = min(min(min(robot36_var, robot72_var),
|
||||||
|
min(martin1_var, martin2_var)),
|
||||||
|
min(min(scottie1_var, scottie2_var), scottieDX_var));
|
||||||
|
|
||||||
|
int mode_estimated = 0;
|
||||||
|
if (min_var > maximum_variance)
|
||||||
|
return;
|
||||||
|
else if (min_var == robot36_var)
|
||||||
|
mode_estimated = mode_robot36;
|
||||||
|
else if (min_var == robot72_var)
|
||||||
|
mode_estimated = mode_robot72;
|
||||||
|
else if (min_var == martin1_var)
|
||||||
|
mode_estimated = mode_martin1;
|
||||||
|
else if (min_var == martin2_var)
|
||||||
|
mode_estimated = mode_martin2;
|
||||||
|
else if (min_var == scottie1_var)
|
||||||
|
mode_estimated = mode_scottie1;
|
||||||
|
else if (min_var == scottie2_var)
|
||||||
|
mode_estimated = mode_scottie2;
|
||||||
|
else if (min_var == scottieDX_var)
|
||||||
|
mode_estimated = mode_scottieDX;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mode_estimated == mode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (mode_estimated) {
|
||||||
|
case mode_robot36:
|
||||||
|
robot36_mode();
|
||||||
|
break;
|
||||||
|
case mode_robot72:
|
||||||
|
robot72_mode();
|
||||||
|
break;
|
||||||
|
case mode_martin1:
|
||||||
|
martin1_mode();
|
||||||
|
break;
|
||||||
|
case mode_martin2:
|
||||||
|
martin2_mode();
|
||||||
|
break;
|
||||||
|
case mode_scottie1:
|
||||||
|
scottie1_mode();
|
||||||
|
break;
|
||||||
|
case mode_scottie2:
|
||||||
|
scottie2_mode();
|
||||||
|
break;
|
||||||
|
case mode_scottieDX:
|
||||||
|
scottieDX_mode();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
static int calibration_detected(float dat_value, int cnt_active, int cnt_quantized)
|
static int calibration_detected(float dat_value, int cnt_active, int cnt_quantized)
|
||||||
{
|
{
|
||||||
static int progress, countdown;
|
static int progress, countdown;
|
||||||
|
@ -626,6 +766,8 @@ void decode(int samples) {
|
||||||
int sync_pulse = !sync_level && sync_counter >= sync_length;
|
int sync_pulse = !sync_level && sync_counter >= sync_length;
|
||||||
sync_counter = sync_level ? sync_counter + 1 : 0;
|
sync_counter = sync_level ? sync_counter + 1 : 0;
|
||||||
|
|
||||||
|
scanline_estimator(sync_level);
|
||||||
|
|
||||||
int u_sep = u_sep_begin <= hpos && hpos < u_sep_end;
|
int u_sep = u_sep_begin <= hpos && hpos < u_sep_end;
|
||||||
int v_sep = v_sep_begin <= hpos && hpos < v_sep_end;
|
int v_sep = v_sep_begin <= hpos && hpos < v_sep_end;
|
||||||
seperator_counter += (u_sep || v_sep) ? dat_quantized : 0;
|
seperator_counter += (u_sep || v_sep) ? dat_quantized : 0;
|
||||||
|
@ -641,10 +783,14 @@ void decode(int samples) {
|
||||||
case mode_robot36:
|
case mode_robot36:
|
||||||
robot36_decoder();
|
robot36_decoder();
|
||||||
break;
|
break;
|
||||||
case mode_yuv:
|
case mode_robot72:
|
||||||
yuv_decoder();
|
yuv_decoder();
|
||||||
break;
|
break;
|
||||||
case mode_rgb:
|
case mode_martin1:
|
||||||
|
case mode_martin2:
|
||||||
|
case mode_scottie1:
|
||||||
|
case mode_scottie2:
|
||||||
|
case mode_scottieDX:
|
||||||
rgb_decoder();
|
rgb_decoder();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
Ładowanie…
Reference in New Issue