forked from cellular-infrastructure/osmocom-analog
OsmoTV: Added more test patterns for TV repair
- improved FUBK - red screen for DY adjustment - crosses and dots for convergence adjustment - EBU color bars - natural color image
This commit is contained in:
parent
e4314749fd
commit
b9cc33c6ec
|
@ -32,11 +32,19 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td><img src="amps_small.jpg" title="Advanced Mobile Phone Service"/></td>
|
||||
<td><img src="setup_small.jpg"/></td>
|
||||
<td><img src="tv_small.jpg" title="TV signal generator and transmitter"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>AMPS (USA) / TACS (UK / Ireland / Italy)</th>
|
||||
<th>Transmit TV test image signals</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="setup_small.jpg"/></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>my early radio setup</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
@ -85,6 +93,16 @@ Implemented networks:
|
|||
</ul>
|
||||
</center>
|
||||
|
||||
<p>
|
||||
Additional features:
|
||||
</p>
|
||||
|
||||
<center>
|
||||
<ul>
|
||||
<li><a href="tv.html">Osmo TV</a></li>
|
||||
</ul>
|
||||
</center>
|
||||
|
||||
<br><br>
|
||||
|
||||
</td></tr></table></center>
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<html>
|
||||
<head>
|
||||
<link href="style.css" rel="stylesheet" type="text/css" />
|
||||
<title>osmocom-analog</title>
|
||||
</head>
|
||||
<body>
|
||||
<center><table><tr><td>
|
||||
|
||||
<h2><center>Osmo TV</center></h2>
|
||||
|
||||
<center><img src="tv.jpg"/></center>
|
||||
|
||||
<p>
|
||||
OsmoTV is capable of transmitting video signals via SDR. This video signal are transmitted on given channels. Color signal and audio carriere can be disabled by option.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The following test signals are supported:
|
||||
<ul>
|
||||
<li>FUBK test chart (known as the German 'Testbild')
|
||||
<li>EBU color bars (8 bars from white to black)
|
||||
<li>Red screen for deflection yoke adjustment
|
||||
<li>Convergence pattern for convergence adjustment
|
||||
<li>A real image of natural colors
|
||||
<li>My VCR Test Chart
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
|
||||
<hr><center>[<a href="index.html">Back to main page</a>]</center><hr>
|
||||
</td></tr></table></center>
|
||||
</body>
|
||||
</html>
|
|
@ -1,4 +1,4 @@
|
|||
AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) -fstack-check
|
||||
AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) -fstack-check $(IMAGEMAGICK_CFLAGS)
|
||||
|
||||
bin_PROGRAMS = \
|
||||
osmotv
|
||||
|
@ -6,9 +6,13 @@ bin_PROGRAMS = \
|
|||
osmotv_SOURCES = \
|
||||
bas.c \
|
||||
fubk.c \
|
||||
ebu.c \
|
||||
convergence.c \
|
||||
color.c \
|
||||
font.c \
|
||||
vcr.c \
|
||||
image.c \
|
||||
sample_image.c \
|
||||
tv_modulate.c \
|
||||
channels.c \
|
||||
main.c
|
||||
|
@ -22,7 +26,7 @@ osmotv_LDADD = \
|
|||
$(top_builddir)/src/libwave/libwave.a \
|
||||
$(top_builddir)/src/libsample/libsample.a \
|
||||
$(ALSA_LIBS) \
|
||||
$(GRAPHICSMAGICK_LIBS) $(IMAGEMAGICK_LIBS) \
|
||||
$(IMAGEMAGICK_LIBS) \
|
||||
-lm
|
||||
|
||||
if HAVE_SDR
|
||||
|
|
18
src/tv/bas.c
18
src/tv/bas.c
|
@ -25,6 +25,9 @@
|
|||
#include "bas.h"
|
||||
#include "vcr.h"
|
||||
#include "fubk.h"
|
||||
#include "convergence.h"
|
||||
#include "color.h"
|
||||
#include "ebu.h"
|
||||
#include "image.h"
|
||||
|
||||
#define WHITE_LEVEL 1.0
|
||||
|
@ -49,7 +52,7 @@
|
|||
#define BURST_AMPLITUDE 0.15
|
||||
#define COLOR_FILTER_ITER 1
|
||||
|
||||
void bas_init(bas_t *bas, double samplerate, enum bas_type type, int fbas, double circle_radius, int color_bar, int grid_only, const char *station_id, unsigned short *img, int width, int height)
|
||||
void bas_init(bas_t *bas, double samplerate, enum bas_type type, int fbas, double circle_radius, int color_bar, int grid_only, const char *station_id, int grid_width, unsigned short *img, int width, int height)
|
||||
{
|
||||
memset(bas, 0, sizeof(*bas));
|
||||
bas->samplerate = samplerate;
|
||||
|
@ -60,6 +63,7 @@ void bas_init(bas_t *bas, double samplerate, enum bas_type type, int fbas, doubl
|
|||
bas->color_bar = color_bar;
|
||||
bas->grid_only = grid_only;
|
||||
bas->station_id = station_id;
|
||||
bas->grid_width = grid_width;
|
||||
bas->img = img;
|
||||
bas->img_width = width;
|
||||
bas->img_height = height;
|
||||
|
@ -111,6 +115,18 @@ int bas_generate(bas_t *bas, sample_t *sample)
|
|||
/* render FUBK test image */
|
||||
fubk_gen_line(sample, x, bas->samplerate, color_u, color_v, bas->v_polarity, H_LINE_START, H_LINE_END, middlefield_line, bas->circle_radius, bas->color_bar, bas->grid_only, bas->station_id);
|
||||
break;
|
||||
case BAS_CONVERGENCE:
|
||||
/* render color convergence test image */
|
||||
convergence_gen_line(sample, x, bas->samplerate, H_LINE_START, H_LINE_END, middlefield_line, (bas->grid_width) > 1 ? 1.0: 0.5);
|
||||
break;
|
||||
case BAS_RED:
|
||||
/* render (thin) color convergence test image */
|
||||
color_gen_line(sample, x, bas->samplerate, color_u, color_v, bas->v_polarity, H_LINE_START, H_LINE_END);
|
||||
break;
|
||||
case BAS_EBU:
|
||||
/* render (thin) color convergence test image */
|
||||
ebu_gen_line(sample, x, bas->samplerate, color_u, color_v, bas->v_polarity, H_LINE_START, H_LINE_END);
|
||||
break;
|
||||
case BAS_IMAGE: {
|
||||
/* 574 lines of image are to be rendered */
|
||||
int img_line = middlefield_line - (574 - bas->img_height) / 2;
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
|
||||
enum bas_type {
|
||||
BAS_FUBK,
|
||||
BAS_CONVERGENCE,
|
||||
BAS_RED,
|
||||
BAS_EBU,
|
||||
BAS_VCR,
|
||||
BAS_IMAGE,
|
||||
};
|
||||
|
@ -13,6 +16,7 @@ typedef struct bas {
|
|||
int color_bar; /* show only color bar on all lines */
|
||||
int grid_only; /* show only the grid */
|
||||
const char *station_id; /* text to display as station id */
|
||||
int grid_width; /* width of the grid (convergence test) */
|
||||
double color_phase; /* current phase of color carrier */
|
||||
int v_polarity; /* polarity of V color vector */
|
||||
unsigned short *img; /* image data, if it should be used */
|
||||
|
@ -20,6 +24,6 @@ typedef struct bas {
|
|||
iir_filter_t lp_y, lp_u, lp_v; /* low pass filters */
|
||||
} bas_t;
|
||||
|
||||
void bas_init(bas_t *bas, double samplerate, enum bas_type type, int fbas, double circle_radius, int color_bar, int grid_only, const char *station_id, unsigned short *img, int width, int height);
|
||||
void bas_init(bas_t *bas, double samplerate, enum bas_type type, int fbas, double circle_radius, int color_bar, int grid_only, const char *station_id, int grid_width, unsigned short *img, int width, int height);
|
||||
int bas_generate(bas_t *bas, sample_t *sample);
|
||||
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/* color test image generator
|
||||
*
|
||||
* (C) 2019 by Andreas Eversberg <jolly@eversberg.eu>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "../libsample/sample.h"
|
||||
#include "color.h"
|
||||
|
||||
#define RAMP_WIDTH 0.0000002
|
||||
|
||||
static struct color_bar {
|
||||
double amplitude, phase;
|
||||
} color_bar[8] = {
|
||||
{0.0, 0.0},
|
||||
{0.336, 167.1},
|
||||
{0.474, 283.5},
|
||||
{0.443, 240.7},
|
||||
{0.443, 60.7},
|
||||
{0.474, 103.5},
|
||||
{0.336, 347.1},
|
||||
{0.0, 0.0},
|
||||
};
|
||||
|
||||
int color_gen_line(sample_t *sample, double x, double samplerate, sample_t *color_u, sample_t *color_v, int v_polarity, double line_start, double line_end)
|
||||
{
|
||||
int b = 5;
|
||||
double step = 1.0 / samplerate;
|
||||
int i = 0;
|
||||
double amplitude, Y, U, V, colorphase;
|
||||
|
||||
/* skip x to line_start */
|
||||
while (x < line_start && x < line_end) {
|
||||
i++;
|
||||
x += step;
|
||||
}
|
||||
if (x >= line_end)
|
||||
return i;
|
||||
|
||||
/* color */
|
||||
Y = (1.0 - (double)b / 7.0) * 0.75;
|
||||
amplitude = color_bar[b].amplitude;
|
||||
if (v_polarity < 0)
|
||||
colorphase = (360.0 - color_bar[b].phase) / 180.0 * M_PI;
|
||||
else
|
||||
colorphase = color_bar[b].phase / 180.0 * M_PI;
|
||||
U = cos(colorphase) * amplitude / 2.0;
|
||||
V = sin(colorphase) * amplitude / 2.0;
|
||||
while (x < line_end) {
|
||||
color_u[i] = U;
|
||||
color_v[i] = V;
|
||||
sample[i++] = Y;
|
||||
x += step;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
int color_gen_line(sample_t *sample, double x, double samplerate, sample_t *color_u, sample_t *color_v, int v_polarity, double frame_start, double line_end);
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
/* Color Convergence test image generator
|
||||
*
|
||||
* (C) 2019 by Andreas Eversberg <jolly@eversberg.eu>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "../libsample/sample.h"
|
||||
#include "convergence.h"
|
||||
|
||||
#define GRID_LINES (4 * thick)
|
||||
#define GRID_HEIGHT 40
|
||||
#define GRID_HEIGHT2 20
|
||||
#define CENTER_LINE (287 - 2)
|
||||
|
||||
#define GRID_WIDTH 0.0000027
|
||||
#define GRID_WIDTH2 0.00000135
|
||||
#define RAMP_WIDTH (0.0000002 * thick)
|
||||
|
||||
#define GRID_LEVEL 1.0
|
||||
#define FIELD_LEVEL 0.00
|
||||
|
||||
/* create cosine ramp, so that the bandwidth is not higher than 2 * width of the ramp(0..1) */
|
||||
static inline double ramp(double x)
|
||||
{
|
||||
return 0.5 - 0.5 * cos(x * M_PI);
|
||||
}
|
||||
|
||||
int convergence_gen_line(sample_t *sample, double x, double samplerate, double line_start, double line_end, int line, double thick)
|
||||
{
|
||||
double step = 1.0 / samplerate;
|
||||
int i = 0;
|
||||
double render_start, render_end, center_x;
|
||||
|
||||
/* skip x to line_start */
|
||||
while (x < line_start && x < line_end) {
|
||||
i++;
|
||||
x += step;
|
||||
}
|
||||
if (x >= line_end)
|
||||
return i;
|
||||
|
||||
/* calculate phase for ramp start of center line */
|
||||
center_x = (line_end - line_start) / 2.0 + line_start;
|
||||
|
||||
/* calculate position in grid:
|
||||
* get the distance below the center line (line - CENTER_LINE)
|
||||
* then be sure not to get negative value: add a multiple of the grid period
|
||||
* then use modulo to get the distance below the grid line */
|
||||
if (((line - CENTER_LINE + GRID_HEIGHT*40) % GRID_HEIGHT) < GRID_LINES) {
|
||||
/* grid line after middle field */
|
||||
while (x < line_end) {
|
||||
sample[i++] = GRID_LEVEL;
|
||||
x += step;
|
||||
}
|
||||
} else {
|
||||
while (1) {
|
||||
/* calculate position for next ramp:
|
||||
* get the distance to center (center_x - x - RAMP_WIDTH)
|
||||
* then be sure not to get negative value: add a multiple of the grid period
|
||||
* then use fmod to get the next ramp start */
|
||||
if (((line - CENTER_LINE + GRID_HEIGHT2*40) % GRID_HEIGHT2) < GRID_LINES)
|
||||
render_start = fmod(center_x - x - RAMP_WIDTH + GRID_WIDTH2*40.0, GRID_WIDTH2) + x;
|
||||
else
|
||||
render_start = fmod(center_x - x - RAMP_WIDTH + GRID_WIDTH*40.0, GRID_WIDTH) + x;
|
||||
/* draw background field up to grid start */
|
||||
while (x < render_start && x < line_end) {
|
||||
sample[i++] = FIELD_LEVEL;
|
||||
x += step;
|
||||
}
|
||||
if (x >= line_end)
|
||||
break;
|
||||
/* ramp up to grid level */
|
||||
render_end = render_start + RAMP_WIDTH;
|
||||
while (x < render_end && x < line_end) {
|
||||
sample[i++] = ramp((x - render_start) / RAMP_WIDTH) * (GRID_LEVEL - FIELD_LEVEL) + FIELD_LEVEL;
|
||||
x += step;
|
||||
}
|
||||
if (x >= line_end)
|
||||
break;
|
||||
render_start = render_end;
|
||||
/* ramp down to field level */
|
||||
render_end = render_start + RAMP_WIDTH;
|
||||
while (x < render_end && x < line_end) {
|
||||
sample[i++] = ramp((x - render_start) / RAMP_WIDTH) * (FIELD_LEVEL - GRID_LEVEL) + GRID_LEVEL;
|
||||
x += step;
|
||||
}
|
||||
if (x >= line_end)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
int convergence_gen_line(sample_t *sample, double x, double samplerate, double line_start, double line_end, int line, double thick);
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/* color test image generator
|
||||
*
|
||||
* (C) 2019 by Andreas Eversberg <jolly@eversberg.eu>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "../libsample/sample.h"
|
||||
#include "ebu.h"
|
||||
|
||||
#define RAMP_WIDTH 0.0000002
|
||||
|
||||
static struct color_bar {
|
||||
double luminance, amplitude, phase;
|
||||
} color_bar[8] = {
|
||||
{1.0, 0.0, 0.0},
|
||||
{0.664, 0.336, 167.1},
|
||||
{0.526, 0.474, 283.5},
|
||||
{0.440, 0.443, 240.7},
|
||||
{0.310, 0.443, 60.7},
|
||||
{0.224, 0.474, 103.5},
|
||||
{0.086, 0.336, 347.1},
|
||||
{0.0, 0.0, 0.0},
|
||||
};
|
||||
|
||||
int ebu_gen_line(sample_t *sample, double x, double samplerate, sample_t *color_u, sample_t *color_v, int v_polarity, double line_start, double line_end)
|
||||
{
|
||||
int b = 5;
|
||||
double step = 1.0 / samplerate, render_end;
|
||||
int i = 0;
|
||||
double amplitude, Y, U, V, colorphase;
|
||||
|
||||
/* skip x to line_start */
|
||||
while (x < line_start && x < line_end) {
|
||||
i++;
|
||||
x += step;
|
||||
}
|
||||
if (x >= line_end)
|
||||
return i;
|
||||
|
||||
/* color */
|
||||
for (b = 0; b < 8; b++) {
|
||||
Y = color_bar[b].luminance;
|
||||
amplitude = color_bar[b].amplitude;
|
||||
if (v_polarity < 0)
|
||||
colorphase = (360.0 - color_bar[b].phase) / 180.0 * M_PI;
|
||||
else
|
||||
colorphase = color_bar[b].phase / 180.0 * M_PI;
|
||||
U = cos(colorphase) * amplitude / 2.0;
|
||||
V = sin(colorphase) * amplitude / 2.0;
|
||||
render_end = (line_end - line_start) / 8 * (b + 1) + line_start;
|
||||
while (x < render_end) {
|
||||
color_u[i] = U;
|
||||
color_v[i] = V;
|
||||
sample[i++] = Y;
|
||||
x += step;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
int ebu_gen_line(sample_t *sample, double x, double samplerate, sample_t *color_u, sample_t *color_v, int v_polarity, double frame_start, double line_end);
|
||||
|
|
@ -29,7 +29,8 @@
|
|||
#define CENTER_LINE (287 - 2)
|
||||
|
||||
#define GRID_WIDTH 0.0000027
|
||||
#define RAMP_WIDTH 0.0000002
|
||||
#define RAMP_WIDTH 0.00000015
|
||||
#define TEXT_WIDTH 0.0000002
|
||||
|
||||
#define GRID_LEVEL 1.0
|
||||
#define FIELD_LEVEL 0.25
|
||||
|
@ -38,7 +39,7 @@
|
|||
#define CIRCLE_CENTER (287 - 1)
|
||||
#define CIRCLE_HEIGTH 3
|
||||
|
||||
struct color_bar {
|
||||
static struct color_bar {
|
||||
double amplitude, phase;
|
||||
} color_bar[8] = {
|
||||
{0.0, 0.0},
|
||||
|
@ -51,7 +52,7 @@ struct color_bar {
|
|||
{0.0, 0.0},
|
||||
};
|
||||
|
||||
struct multi_burst {
|
||||
static struct multi_burst {
|
||||
double width; /* how whide is this portion */
|
||||
double level; /* level of this portion */
|
||||
double frequency; /* frequency of burst or zero */
|
||||
|
@ -154,7 +155,7 @@ static double mittelfeld(sample_t *sample, double samplerate, int *_i, double *_
|
|||
bit = ((bits << b) & 128);
|
||||
if (!last_bit && !bit) {
|
||||
/* keep black */
|
||||
render_end = render_start + RAMP_WIDTH;
|
||||
render_end = render_start + TEXT_WIDTH;
|
||||
while (x < render_end) {
|
||||
sample[i++] = 0.0;
|
||||
x += step;
|
||||
|
@ -163,7 +164,7 @@ static double mittelfeld(sample_t *sample, double samplerate, int *_i, double *_
|
|||
}
|
||||
if (last_bit && bit) {
|
||||
/* keep white */
|
||||
render_end = render_start + RAMP_WIDTH;
|
||||
render_end = render_start + TEXT_WIDTH;
|
||||
while (x < render_end) {
|
||||
sample[i++] = 1.0;
|
||||
x += step;
|
||||
|
@ -172,18 +173,18 @@ static double mittelfeld(sample_t *sample, double samplerate, int *_i, double *_
|
|||
}
|
||||
if (!last_bit && bit) {
|
||||
/* ramp to white */
|
||||
render_end = render_start + RAMP_WIDTH;
|
||||
render_end = render_start + TEXT_WIDTH;
|
||||
while (x < render_end) {
|
||||
sample[i++] = 1.0 - ramp((render_end - x) / RAMP_WIDTH);
|
||||
sample[i++] = 1.0 - ramp((render_end - x) / TEXT_WIDTH);
|
||||
x += step;
|
||||
}
|
||||
render_start = render_end;
|
||||
}
|
||||
if (last_bit && !bit) {
|
||||
/* ramp to black */
|
||||
render_end = render_start + RAMP_WIDTH;
|
||||
render_end = render_start + TEXT_WIDTH;
|
||||
while (x < render_end) {
|
||||
sample[i++] = ramp((render_end - x) / RAMP_WIDTH);
|
||||
sample[i++] = ramp((render_end - x) / TEXT_WIDTH);
|
||||
x += step;
|
||||
}
|
||||
render_start = render_end;
|
||||
|
|
|
@ -60,6 +60,7 @@ static double circle_radius = 6.7;
|
|||
static int color_bar = 0;
|
||||
static int grid_only = 0;
|
||||
static const char *station_id = "Jolly Roger";
|
||||
static int grid_width = 0;
|
||||
static int __attribute__((__unused__)) latency = 200;
|
||||
static double samplerate = 10e6;
|
||||
static const char *wave_file = NULL;
|
||||
|
@ -87,8 +88,11 @@ void print_help(const char *arg0)
|
|||
/* - - */
|
||||
printf("\ncommand:\n");
|
||||
printf(" tx-fubk Transmit FUBK test image (German PAL image)\n");
|
||||
printf(" tx-ebu Transmit EBU test image (color bars)\n");
|
||||
printf(" tx-convergence Transmit convergence grid for color adjustemnt\n");
|
||||
printf(" tx-red Transmit single color image for DY adjustment\n");
|
||||
printf(" tx-vcr Transmit VCR calibration pattern\n");
|
||||
printf(" tx-img <image> Transmit given image file\n");
|
||||
printf(" tx-img [<image>] Transmit natural image or given image file\n");
|
||||
printf(" Use 4:3 image with 574 lines for best result.\n");
|
||||
printf("\ngeneral options:\n");
|
||||
printf(" -f --frequency <frequency>\n");
|
||||
|
@ -118,6 +122,9 @@ void print_help(const char *arg0)
|
|||
printf(" -I --sation-id \"<text>\"\n");
|
||||
printf(" Give exactly 12 characters to display as Station ID.\n");
|
||||
printf(" (default = \"%s\")\n", station_id);
|
||||
printf("\nconvergence options:\n");
|
||||
printf(" -W --grid-width 2 | 1\n");
|
||||
printf(" Thickness of grid. (default = %d)\n", grid_width);
|
||||
#ifdef HAVE_SDR
|
||||
printf(" --limesdr\n");
|
||||
printf(" Auto-select several required options for LimeSDR\n");
|
||||
|
@ -144,6 +151,7 @@ static void add_options(void)
|
|||
option_add('C', "color-bar", 1);
|
||||
option_add('G', "grid-only", 1);
|
||||
option_add('I', "station-id", 1);
|
||||
option_add('W', "grid-width", 1);
|
||||
#ifdef HAVE_SDR
|
||||
option_add(OPT_LIMESDR, "limesdr", 0);
|
||||
option_add(OPT_LIMESDR_MINI, "limesdr-mini", 0);
|
||||
|
@ -195,6 +203,9 @@ static int handle_options(int short_option, int argi, char **argv)
|
|||
case 'G':
|
||||
grid_only = atoi(argv[argi]);
|
||||
break;
|
||||
case 'W':
|
||||
grid_width = atoi(argv[argi]);
|
||||
break;
|
||||
case 'I':
|
||||
station_id = strdup(argv[argi]);
|
||||
if (strlen(station_id) != 12) {
|
||||
|
@ -379,7 +390,7 @@ static int tx_test_picture(enum bas_type type)
|
|||
fprintf(stderr, "No mem!\n");
|
||||
goto error;
|
||||
}
|
||||
bas_init(&bas, samplerate, type, fbas, circle_radius, color_bar, grid_only, station_id, NULL, 0, 0);
|
||||
bas_init(&bas, samplerate, type, fbas, circle_radius, color_bar, grid_only, station_id, grid_width, NULL, 0, 0);
|
||||
count = bas_generate(&bas, test_bas);
|
||||
count += bas_generate(&bas, test_bas + count);
|
||||
count += bas_generate(&bas, test_bas + count);
|
||||
|
@ -413,6 +424,8 @@ error:
|
|||
return ret;
|
||||
}
|
||||
|
||||
extern uint32_t sample_image[];
|
||||
|
||||
static int tx_img(const char *filename)
|
||||
{
|
||||
unsigned short *img = NULL;
|
||||
|
@ -422,11 +435,22 @@ static int tx_img(const char *filename)
|
|||
int ret = -1;
|
||||
int count;
|
||||
|
||||
if (filename) {
|
||||
img = load_img(&width, &height, filename, 0);
|
||||
if (!img) {
|
||||
fprintf(stderr, "Failed to load image '%s'\n", filename);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
int i;
|
||||
width = 764;
|
||||
height = 574;
|
||||
img = (unsigned short *)sample_image;
|
||||
for (i = 0; i < width * height * 6 / 4; i++)
|
||||
sample_image[i] = htobe32(sample_image[i]);
|
||||
for (i = 0; i < width * height * 3; i++)
|
||||
img[i] = le16toh(img[i]);
|
||||
}
|
||||
|
||||
/* test image, add some samples in case of overflow due to rounding errors */
|
||||
img_bas = calloc(samplerate / 25.0 * 4.0 + 10.0, sizeof(sample_t));
|
||||
|
@ -434,7 +458,7 @@ static int tx_img(const char *filename)
|
|||
fprintf(stderr, "No mem!\n");
|
||||
goto error;
|
||||
}
|
||||
bas_init(&bas, samplerate, BAS_IMAGE, fbas, circle_radius, color_bar, grid_only, NULL, img, width, height);
|
||||
bas_init(&bas, samplerate, BAS_IMAGE, fbas, circle_radius, color_bar, grid_only, NULL, grid_width, img, width, height);
|
||||
count = bas_generate(&bas, img_bas);
|
||||
count += bas_generate(&bas, img_bas + count);
|
||||
count += bas_generate(&bas, img_bas + count);
|
||||
|
@ -445,6 +469,7 @@ static int tx_img(const char *filename)
|
|||
ret = 0;
|
||||
error:
|
||||
free(img_bas);
|
||||
if (filename)
|
||||
free(img);
|
||||
return ret;
|
||||
}
|
||||
|
@ -489,14 +514,16 @@ int main(int argc, char *argv[])
|
|||
exit(0);
|
||||
} else if (!strcmp(argv[argi], "tx-fubk")) {
|
||||
tx_test_picture(BAS_FUBK);
|
||||
} else if (!strcmp(argv[argi], "tx-ebu")) {
|
||||
tx_test_picture(BAS_EBU);
|
||||
} else if (!strcmp(argv[argi], "tx-convergence")) {
|
||||
tx_test_picture(BAS_CONVERGENCE);
|
||||
} else if (!strcmp(argv[argi], "tx-red")) {
|
||||
tx_test_picture(BAS_RED);
|
||||
} else if (!strcmp(argv[argi], "tx-vcr")) {
|
||||
tx_test_picture(BAS_VCR);
|
||||
} else if (!strcmp(argv[argi], "tx-img")) {
|
||||
if (argi + 1 >= argc) {
|
||||
fprintf(stderr, "Expecting image file, use '-h' for help!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
tx_img(argv[argi + 1]);
|
||||
tx_img((argi + 1 < argc) ? argv[argi + 1] : NULL);
|
||||
} else {
|
||||
fprintf(stderr, "Unknown command '%s', use '-h' for help!\n", argv[argi]);
|
||||
return -EINVAL;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -177,6 +177,7 @@ int vcr_gen_line(sample_t *sample, double x, double samplerate, sample_t *color_
|
|||
x += step;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
|
|
Loading…
Reference in New Issue