mirror of
https://github.com/xdsopl/robot36.git
synced 2026-01-05 07:49:58 +01:00
187 lines
6.2 KiB
Rust
187 lines
6.2 KiB
Rust
/*
|
|
Copyright 2014 Ahmet Inan <xdsopl@googlemail.com>
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
#pragma version(1)
|
|
#pragma rs java_package_name(xdsopl.robot36)
|
|
|
|
#include "complex.rsh"
|
|
#include "ema.rsh"
|
|
#include "ddc.rsh"
|
|
#include "fmd.rsh"
|
|
#include "scanline_estimator.rsh"
|
|
#include "calibration_detector.rsh"
|
|
#include "initialization.rsh"
|
|
#include "modes.rsh"
|
|
#include "constants.rsh"
|
|
#include "state.rsh"
|
|
#include "exports.rsh"
|
|
|
|
static inline uchar4 rgb(uchar r, uchar g, uchar b) { return (uchar4){ b, g, r, 255 }; }
|
|
static inline uchar4 yuv(uchar y, uchar u, uchar v)
|
|
{
|
|
uchar4 bgra = rsYuvToRGBA_uchar4(y, u, v);
|
|
return rgb(bgra[0], bgra[1], bgra[2]);
|
|
}
|
|
|
|
static void reset()
|
|
{
|
|
vpos = 0;
|
|
hpos = 0;
|
|
even_hpos = 0;
|
|
seperator_counter = 0;
|
|
sync_counter = sync_length;
|
|
for (int i = 0; i < bitmap_width * bitmap_height; ++i)
|
|
pixel_buffer[i] = rgb(0, 0, 0);
|
|
}
|
|
|
|
static void robot36_decoder()
|
|
{
|
|
static prev_timeout;
|
|
if (!prev_timeout && 2 * abs(seperator_counter) > seperator_length)
|
|
vpos = (~1 & vpos) | (seperator_counter > 0);
|
|
prev_timeout = hpos >= maximum_length;
|
|
if (vpos & 1) {
|
|
for (int i = 0; i < bitmap_width; ++i) {
|
|
uchar even_y = value_buffer[i * (y_end-y_begin) / bitmap_width + y_begin];
|
|
uchar v = value_buffer[i * (v_end-v_begin) / bitmap_width + v_begin];
|
|
uchar odd_y = value_buffer[i * (y_end-y_begin) / bitmap_width + even_hpos + y_begin];
|
|
uchar u = value_buffer[i * (u_end-u_begin) / bitmap_width + even_hpos + u_begin];
|
|
pixel_buffer[bitmap_width * (vpos-1) + i] = yuv(even_y, u, v);
|
|
pixel_buffer[bitmap_width * vpos + i] = yuv(odd_y, u, v);
|
|
}
|
|
if (prev_timeout)
|
|
hpos -= scanline_length;
|
|
else
|
|
hpos = 0;
|
|
even_hpos = 0;
|
|
} else {
|
|
if (prev_timeout) {
|
|
even_hpos = scanline_length;
|
|
hpos -= scanline_length;
|
|
} else {
|
|
even_hpos = hpos;
|
|
hpos = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void yuv_decoder()
|
|
{
|
|
for (int i = 0; i < bitmap_width; ++i) {
|
|
uchar y = value_buffer[i * (y_end-y_begin) / bitmap_width + y_begin];
|
|
uchar u = value_buffer[i * (u_end-u_begin) / bitmap_width + u_begin];
|
|
uchar v = value_buffer[i * (v_end-v_begin) / bitmap_width + v_begin];
|
|
pixel_buffer[bitmap_width * vpos + i] = yuv(y, u, v);
|
|
}
|
|
if (hpos >= maximum_length)
|
|
hpos -= scanline_length;
|
|
else
|
|
hpos = 0;
|
|
even_hpos = 0;
|
|
}
|
|
|
|
static void rgb_decoder()
|
|
{
|
|
for (int i = 0; i < bitmap_width; ++i) {
|
|
uchar r = value_buffer[i * (r_end-r_begin) / bitmap_width + r_begin];
|
|
uchar g = value_buffer[i * (g_end-g_begin) / bitmap_width + g_begin];
|
|
uchar b = value_buffer[i * (b_end-b_begin) / bitmap_width + b_begin];
|
|
pixel_buffer[bitmap_width * vpos + i] = rgb(r, g, b);
|
|
}
|
|
if (hpos >= maximum_length)
|
|
hpos -= scanline_length;
|
|
else
|
|
hpos = 0;
|
|
even_hpos = 0;
|
|
}
|
|
|
|
static void raw_decoder()
|
|
{
|
|
for (int i = 0; i < bitmap_width; ++i) {
|
|
uchar value = value_buffer[i * hpos / bitmap_width];
|
|
pixel_buffer[bitmap_width * vpos + i] = rgb(value, value, value);
|
|
}
|
|
even_hpos = hpos = 0;
|
|
}
|
|
|
|
void decode(int samples) {
|
|
for (int sample = 0; sample < samples; ++sample) {
|
|
float amp = audio_buffer[sample] / 32768.0f;
|
|
float power = amp * amp;
|
|
if (filter(&avg_power, power) < 0.0000001f)
|
|
continue;
|
|
|
|
complex_t cnt_baseband = convert(&cnt_ddc, amp);
|
|
complex_t dat_baseband = convert(&dat_ddc, amp);
|
|
|
|
float cnt_value = demodulate(&cnt_fmd, cnt_baseband);
|
|
float dat_value = demodulate(&dat_fmd, dat_baseband);
|
|
|
|
int cnt_active = cabs(dat_baseband) < 4.0f * cabs(cnt_baseband);
|
|
int dat_active = cabs(cnt_baseband) < 4.0f * cabs(dat_baseband);
|
|
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;
|
|
value_buffer[hpos + even_hpos] = cnt_level | dat_level;
|
|
|
|
int cnt_quantized = round(cnt_value);
|
|
int dat_quantized = round(dat_value);
|
|
|
|
int sync_level = cnt_active && cnt_quantized == 0;
|
|
int sync_pulse = !sync_level && sync_counter >= sync_length;
|
|
sync_counter = sync_level ? sync_counter + 1 : 0;
|
|
|
|
if (*current_mode != mode_debug) {
|
|
int detected_mode = calibration_detector(dat_value, dat_active, cnt_active, cnt_quantized);
|
|
if (detected_mode >= 0)
|
|
reset();
|
|
switch_mode(detected_mode);
|
|
int estimated_mode = scanline_estimator(sync_level);
|
|
if (estimated_mode >= 0 && estimated_mode != *current_mode)
|
|
reset();
|
|
switch_mode(estimated_mode);
|
|
}
|
|
|
|
int u_sep = u_sep_begin <= hpos && hpos < u_sep_end;
|
|
int v_sep = v_sep_begin <= hpos && hpos < v_sep_end;
|
|
seperator_counter += (u_sep || v_sep) ? dat_quantized : 0;
|
|
|
|
if (++hpos >= maximum_length || sync_pulse) {
|
|
if (hpos < minimum_length) {
|
|
hpos = 0;
|
|
even_hpos = 0;
|
|
seperator_counter = 0;
|
|
continue;
|
|
}
|
|
switch (current_decoder) {
|
|
case decoder_robot36:
|
|
robot36_decoder();
|
|
break;
|
|
case decoder_yuv:
|
|
yuv_decoder();
|
|
break;
|
|
case decoder_rgb:
|
|
rgb_decoder();
|
|
break;
|
|
default:
|
|
raw_decoder();
|
|
}
|
|
if (++vpos >= bitmap_height)
|
|
vpos = 0;
|
|
seperator_counter = 0;
|
|
}
|
|
}
|
|
}
|