unbelievably large gui revamp

pull/1/merge
Oona 2011-08-10 23:43:17 +03:00
rodzic b46e6ef395
commit b98994be20
9 zmienionych plików z 782 dodań i 456 usunięć

Wyświetl plik

@ -16,8 +16,10 @@ unsigned int SRate = 44100;
double *StoredFreq = NULL;
double StoredFreqRate = 0;
double HedrShift = 0;
int PWRdBthresh[10] = {0, -3, -5, -10, -15, -20, -25, -30, -35, -40};
int PWRdBthresh[10] = {0, -3, -5, -10, -15, -20, -25, -30, -40, -50};
int SNRdBthresh[10] = {30, 15, 10, 5, 3, 0, -3, -5, -10, -15};
int Adaptive = TRUE;
int ManualActivated = FALSE;
GtkWidget *mainwindow = NULL;
GtkWidget *notebook = NULL;
@ -28,15 +30,24 @@ GtkWidget *statusbar = NULL;
GtkWidget *snrbar = NULL;
GtkWidget *pwrbar = NULL;
GtkWidget *vugrid = NULL;
GdkPixbuf *VUpixbufPWR = NULL;
GdkPixbuf *VUpixbufDim = NULL;
GdkPixbuf *VUpixbufSNR = NULL;
GtkWidget *PWRimage[10] = {NULL};
GtkWidget *SNRimage[10] = {NULL};
GdkPixbuf *pixbufPWR = NULL;
GdkPixbuf *pixbufSNR = NULL;
GtkWidget *infolabel = NULL;
GtkWidget *aboutdialog = NULL;
GtkWidget *prefdialog = NULL;
GtkWidget *sdialog = NULL;
GtkWidget *cardcombo = NULL;
GtkWidget *modecombo = NULL;
GtkWidget *togslant = NULL;
GtkWidget *togsave = NULL;
GtkWidget *togadapt = NULL;
GtkWidget *togrx = NULL;
GtkWidget *btnabort = NULL;
GtkWidget *btnstart = NULL;
GtkWidget *manualframe = NULL;
GtkWidget *shiftspin = NULL;
GtkWidget *pwrimage = NULL;
GtkWidget *snrimage = NULL;
snd_pcm_t *pcm_handle = NULL;
@ -50,7 +61,7 @@ void ClearPixbuf(GdkPixbuf *pb, unsigned int width, unsigned int height) {
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
p = pixels + y * rowstride + x * 3;
p[0] = p[1] = p[2] = 192;
p[0] = p[2] = p[1] = 96 + (1.0*y/height) * 32;
}
}
@ -68,26 +79,63 @@ unsigned char clip (double a) {
return (unsigned char)round(a);
}
void setVU(short int PcmValue, double SNRdB) {
int i;
void setVU (short int PcmValue, double SNRdB) {
int x,y;
int PWRdB = (int)round(10 * log10(pow(PcmValue/32767.0,2)));
guchar *pixelsPWR, *pixelsSNR, *p;
unsigned int rowstridePWR,rowstrideSNR;
rowstridePWR = gdk_pixbuf_get_rowstride (pixbufPWR);
pixelsPWR = gdk_pixbuf_get_pixels (pixbufPWR);
rowstrideSNR = gdk_pixbuf_get_rowstride (pixbufSNR);
pixelsSNR = gdk_pixbuf_get_pixels (pixbufSNR);
for (y=0; y<20; y++) {
for (x=0; x<100; x++) {
p = pixelsPWR + y * rowstridePWR + (99-x) * 3;
if (PWRdB >= PWRdBthresh[x/10]) {
p[0] = 42 + 10*(10-abs(y-10));
p[1] = 96 + 7*(10-abs(y-10));
p[2] = 255;
} else {
p[0] = p[1] = p[2] = 192;
}
p = pixelsSNR + y * rowstrideSNR + (99-x) * 3;
if (SNRdB >= SNRdBthresh[x/10]) {
p[0] = 255;
p[1] = 96 + 9*(10-abs(y-10));
p[2] = 45 + 12*(10-abs(y-10));
} else {
p[0] = p[1] = p[2] = 192;
}
}
}
gdk_threads_enter();
for (i=0; i<10; i++) {
if (PWRdB >= PWRdBthresh[i]) gtk_image_set_from_pixbuf(GTK_IMAGE(PWRimage[i]), VUpixbufPWR);
else gtk_image_set_from_pixbuf(GTK_IMAGE(PWRimage[i]), VUpixbufDim);
if (SNRdB >= SNRdBthresh[i]) gtk_image_set_from_pixbuf(GTK_IMAGE(SNRimage[i]), VUpixbufSNR);
else gtk_image_set_from_pixbuf(GTK_IMAGE(SNRimage[i]), VUpixbufDim);
}
gtk_image_set_from_pixbuf(GTK_IMAGE(pwrimage), pixbufPWR);
gtk_image_set_from_pixbuf(GTK_IMAGE(snrimage), pixbufSNR);
gdk_threads_leave();
}
double deg2rad (double Deg) {
return (Deg / 180) * M_PI;
return (Deg / 180) * M_PI;
}
void delete_event() {
gtk_main_quit ();
}
void GetAdaptive() {
Adaptive = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(togadapt));
}
void ManualStart() {
ManualActivated = TRUE;
printf("start\n");
}

Wyświetl plik

@ -17,6 +17,8 @@ extern double StoredFreqRate;
extern double HedrShift;
extern int PWRdBthresh[10];
extern int SNRdBthresh[10];
extern int Adaptive;
extern int ManualActivated;
extern GtkWidget *mainwindow;
extern GtkWidget *notebook;
@ -27,15 +29,24 @@ extern GtkWidget *statusbar;
extern GtkWidget *snrbar;
extern GtkWidget *pwrbar;
extern GtkWidget *vugrid;
extern GdkPixbuf *VUpixbufPWR;
extern GdkPixbuf *VUpixbufSNR;
extern GdkPixbuf *VUpixbufDim;
extern GtkWidget *PWRimage[10];
extern GtkWidget *SNRimage[10];
extern GdkPixbuf *pixbufPWR;
extern GdkPixbuf *pixbufSNR;
extern GtkWidget *infolabel;
extern GtkWidget *aboutdialog;
extern GtkWidget *prefdialog;
extern GtkWidget *sdialog;
extern GtkWidget *cardcombo;
extern GtkWidget *modecombo;
extern GtkWidget *togslant;
extern GtkWidget *togsave;
extern GtkWidget *togadapt;
extern GtkWidget *togrx;
extern GtkWidget *btnabort;
extern GtkWidget *btnstart;
extern GtkWidget *manualframe;
extern GtkWidget *shiftspin;
extern GtkWidget *pwrimage;
extern GtkWidget *snrimage;
extern snd_pcm_t *pcm_handle;
@ -71,7 +82,7 @@ extern ModeSpecDef ModeSpec[];
void ClearPixbuf (GdkPixbuf *, unsigned int, unsigned int);
void createGUI ();
int GetVideo (int, double, int, int, int);
int GetVideo (int, double, int, int);
unsigned int GetBin (double, int);
unsigned char clip (double);
void setVU (short int, double);
@ -80,5 +91,7 @@ double FindSync (unsigned int, int, double, int*);
double deg2rad (double);
void initPcmDevice ();
void delete_event ();
void GetAdaptive ();
void ManualStart ();
#endif

111
gui.c
Wyświetl plik

@ -7,13 +7,14 @@
void createGUI() {
GtkBuilder *builder;
GtkWidget *label;
GtkWidget *quititem;
GtkWidget *aboutitem;
GtkWidget *prefitem;
builder = gtk_builder_new();
gtk_builder_add_from_file(builder, "slowrx.ui", NULL);
gtk_builder_add_from_file(builder, "aboutdialog.ui", NULL);
gtk_builder_add_from_file(builder, "prefs.ui", NULL);
vugrid = GTK_WIDGET(gtk_builder_get_object(builder,"vugrid"));
mainwindow = GTK_WIDGET(gtk_builder_get_object(builder,"mainwindow"));
@ -21,103 +22,47 @@ void createGUI() {
statusbar = GTK_WIDGET(gtk_builder_get_object(builder,"statusbar"));
infolabel = GTK_WIDGET(gtk_builder_get_object(builder,"infolabel"));
quititem = GTK_WIDGET(gtk_builder_get_object(builder,"quititem"));
prefitem = GTK_WIDGET(gtk_builder_get_object(builder,"prefmenuitem"));
aboutitem = GTK_WIDGET(gtk_builder_get_object(builder,"aboutitem"));
aboutdialog = GTK_WIDGET(gtk_builder_get_object(builder,"aboutdialog"));
prefdialog = GTK_WIDGET(gtk_builder_get_object(builder,"prefdialog"));
cardcombo = GTK_WIDGET(gtk_builder_get_object(builder,"cardcombo"));
togslant = GTK_WIDGET(gtk_builder_get_object(builder,"TogSlant"));
togsave = GTK_WIDGET(gtk_builder_get_object(builder,"TogSave"));
togadapt = GTK_WIDGET(gtk_builder_get_object(builder,"TogAdapt"));
togrx = GTK_WIDGET(gtk_builder_get_object(builder,"TogRx"));
modecombo = GTK_WIDGET(gtk_builder_get_object(builder,"modecombo"));
btnabort = GTK_WIDGET(gtk_builder_get_object(builder,"BtnAbort"));
btnstart = GTK_WIDGET(gtk_builder_get_object(builder,"BtnStart"));
manualframe = GTK_WIDGET(gtk_builder_get_object(builder,"ManualFrame"));
shiftspin = GTK_WIDGET(gtk_builder_get_object(builder,"ShiftSpin"));
pwrimage = GTK_WIDGET(gtk_builder_get_object(builder,"PowerImage"));
snrimage = GTK_WIDGET(gtk_builder_get_object(builder,"SNRImage"));
g_signal_connect (quititem, "activate", G_CALLBACK(delete_event), NULL);
g_signal_connect (mainwindow, "delete-event", G_CALLBACK(delete_event), NULL);
g_signal_connect_swapped(aboutitem, "activate", G_CALLBACK(gtk_widget_show_all), aboutdialog);
g_signal_connect_swapped(aboutitem, "activate", G_CALLBACK(gtk_widget_show_all), aboutdialog);
g_signal_connect_swapped(prefitem, "activate", G_CALLBACK(gtk_widget_show_all), prefdialog);
g_signal_connect_swapped(aboutdialog, "close", G_CALLBACK(gtk_widget_hide), aboutdialog);
g_signal_connect_swapped(togadapt, "toggled", G_CALLBACK(GetAdaptive), NULL);
g_signal_connect (btnstart, "clicked", G_CALLBACK(ManualStart), NULL);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(togslant), TRUE);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(togsave), TRUE);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(togadapt), TRUE);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(togrx), TRUE);
gtk_combo_box_set_active (GTK_COMBO_BOX(modecombo), 0);
gtk_widget_set_sensitive (btnabort, FALSE);
RxPixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 320, 256);
ClearPixbuf (RxPixbuf, 320, 256);
DispPixbuf = gdk_pixbuf_scale_simple (RxPixbuf, 500, 400, GDK_INTERP_NEAREST);
gtk_image_set_from_pixbuf(GTK_IMAGE(RxImage), DispPixbuf);
/* PWR & SNR indicators */
pixbufPWR = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 100, 20);
pixbufSNR = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 100, 20);
int i;
char dbstr[40];
/* dB labels */
for (i=0; i<10; i++) {
label = gtk_label_new("");
if (PWRdBthresh[i] < 0) snprintf(dbstr, sizeof(dbstr)-1, "<span font='9px'>%d</span>", abs(PWRdBthresh[i]));
else snprintf(dbstr, sizeof(dbstr)-1, "<span font='9px'>%d</span>", PWRdBthresh[i]);
gtk_label_set_markup (GTK_LABEL(label), dbstr);
gtk_misc_set_alignment (GTK_MISC(label),1,0);
gtk_grid_attach (GTK_GRID(vugrid), label, 0, i, 1, 1);
}
for (i=0; i<10; i++) {
label = gtk_label_new("");
if (SNRdBthresh[i] < 0) snprintf(dbstr, sizeof(dbstr)-1, "<span font='9px'>%d</span>", abs(SNRdBthresh[i]));
else snprintf(dbstr, sizeof(dbstr)-1, "<span font='9px'>%+d</span>", SNRdBthresh[i]);
gtk_label_set_markup (GTK_LABEL(label), dbstr);
gtk_misc_set_alignment (GTK_MISC(label), 0, 0);
gtk_grid_attach (GTK_GRID(vugrid), label, 3, i, 1, 1);
}
/* Indicator pictures */
guchar *pixels, *p;
unsigned int x,y,rowstride;
VUpixbufPWR = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 20, 14);
VUpixbufSNR = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 20, 14);
VUpixbufDim = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 20, 14);
rowstride = gdk_pixbuf_get_rowstride (VUpixbufDim);
pixels = gdk_pixbuf_get_pixels (VUpixbufDim);
for (y = 0; y < 14; y++) {
for (x = 0; x < 20; x++) {
p = pixels + y * rowstride + x * 3;
p[0] = p[1] = p[2] = 3*(10-abs(x-10)) + (y % 2 ? 192 : 160);
}
}
rowstride = gdk_pixbuf_get_rowstride (VUpixbufPWR);
pixels = gdk_pixbuf_get_pixels (VUpixbufPWR);
for (y = 0; y < 14; y++) {
for (x = 0; x < 20; x++) {
p = pixels + y * rowstride + x * 3;
if (y % 2 == 0) {
p[0] = 42 + 15*(10-abs(x-10));
p[1] = 96 + 12*(10-abs(x-10));
p[2] = 255;
} else {
p[0] = p[1] = p[2] = 192;
}
}
}
rowstride = gdk_pixbuf_get_rowstride (VUpixbufSNR);
pixels = gdk_pixbuf_get_pixels (VUpixbufSNR);
for (y = 0; y < 14; y++) {
for (x = 0; x < 20; x++) {
p = pixels + y * rowstride + x * 3;
if (y % 2 == 0) {
p[0] = 255;
p[1] = 96 + 12*(10-abs(x-10));
p[2] = 45 + 15*(10-abs(x-10));
} else {
p[0] = p[1] = p[2] = 192;
}
}
}
for (i=0;i<10;i++) {
PWRimage[i] = gtk_image_new_from_pixbuf (VUpixbufDim);
SNRimage[i] = gtk_image_new_from_pixbuf (VUpixbufDim);
gtk_grid_attach(GTK_GRID(vugrid), PWRimage[i], 1, i, 1, 1);
gtk_grid_attach(GTK_GRID(vugrid), SNRimage[i], 2, i, 1, 1);
}
setVU(0, -100);
gtk_widget_show_all (mainwindow);

Wyświetl plik

@ -17,7 +17,7 @@
* LineLen Time in seconds from the beginning of a sync pulse to the beginning of the next one
* ImgWidth Pixels per scanline
* ImgHeight Number of scanlines
* YScale Integer factor by which the final image needs to be scaled y-axis-wise (1 or 2)
* YScale Vertical size of a pixel (1 or 2)
* ColorEnc Color format (GBR, RGB, YUV, BW)
*
*
@ -165,7 +165,7 @@ ModeSpecDef ModeSpec[] = {
.ColorEnc = YUV },
[R24BW] = { // N7CXI, 2000
.Name = "Robot 24 B&W",
.Name = "Robot 24 B/W",
.ShortName = "R24BW",
.SyncLen = 7e-3,
.PorchLen = 0e-3,
@ -178,7 +178,7 @@ ModeSpecDef ModeSpec[] = {
.ColorEnc = BW },
[R12BW] = { // N7CXI, 2000
.Name = "Robot 12 B&W",
.Name = "Robot 12 B/W",
.ShortName = "R12BW",
.SyncLen = 7e-3,
.PorchLen = 0e-3,
@ -191,12 +191,12 @@ ModeSpecDef ModeSpec[] = {
.ColorEnc = BW },
[R8BW] = { // N7CXI, 2000
.Name = "Robot 8 B&W",
.Name = "Robot 8 B/W",
.ShortName = "R8BW",
.SyncLen = 7e-3,
.PorchLen = 0e-3,
.SeparatorLen = 0e-3,
.PixelLen = 0.188e-3,
.PixelLen = .188e-3,
.LineLen = 67e-3,
.ImgWidth = 320,
.ImgHeight = 120,

100
prefs.ui 100644
Wyświetl plik

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkDialog" id="prefdialog">
<property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="title" translatable="yes">Preferences - slowrx</property>
<property name="type_hint">dialog</property>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox1">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="dialog-action_area1">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="button2">
<property name="label">gtk-cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button1">
<property name="label">gtk-ok</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="DevFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkAlignment" id="alignment3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="top_padding">10</property>
<property name="bottom_padding">10</property>
<property name="left_padding">12</property>
<property name="right_padding">10</property>
<child>
<object class="GtkComboBoxText" id="cardcombo">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Capture device</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="0">button2</action-widget>
<action-widget response="0">button1</action-widget>
</action-widgets>
</object>
</interface>

112
slowrx.c
Wyświetl plik

@ -38,7 +38,8 @@ void *Listen() {
// Wait for VIS
HedrShift = 0;
gdk_threads_enter();
gtk_widget_set_sensitive(vugrid, TRUE);
gtk_widget_set_sensitive(vugrid, TRUE);
gtk_widget_set_sensitive(btnabort, FALSE);
gdk_threads_leave();
snd_pcm_prepare(pcm_handle);
@ -71,9 +72,11 @@ void *Listen() {
}
// Get video
strftime(rctime, sizeof(rctime)-1, "%H:%Mz", timeptr);
snprintf(infostr, sizeof(infostr)-1, "%s @ %+.0f Hz, received at %s", ModeSpec[Mode].Name, HedrShift, rctime);
strftime(rctime, sizeof(rctime)-1, "%H:%M", timeptr);
snprintf(infostr, sizeof(infostr)-1, "%s, %s UTC", ModeSpec[Mode].Name, rctime);
gdk_threads_enter();
gtk_widget_set_sensitive( manualframe, FALSE);
gtk_widget_set_sensitive( btnabort, TRUE);
gtk_statusbar_push( GTK_STATUSBAR(statusbar), 0, "Receiving video" );
gtk_label_set_markup(GTK_LABEL(infolabel), infostr);
gdk_threads_leave();
@ -83,58 +86,75 @@ void *Listen() {
Skip = 0;
printf(" getvideo @ %.02f Hz, Skip %d, HedrShift %.0f Hz\n", Rate, Skip, HedrShift);
GetVideo(Mode, Rate, Skip, TRUE, FALSE);
GetVideo(Mode, Rate, Skip, FALSE);
snd_pcm_drop(pcm_handle);
// Fix slant
gdk_threads_enter();
gtk_statusbar_push( GTK_STATUSBAR(statusbar), 0, "Calculating slant" );
gtk_widget_set_sensitive(vugrid, FALSE);
gtk_widget_set_sensitive( btnabort, FALSE);
gtk_widget_set_sensitive( manualframe, TRUE);
gdk_threads_leave();
printf(" FindSync @ %.02f Hz\n",Rate);
Rate = FindSync(PcmPointer, Mode, Rate, &Skip);
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(togslant))) {
// Fix slant
setVU(0,-100);
gdk_threads_enter();
gtk_statusbar_push( GTK_STATUSBAR(statusbar), 0, "Calculating slant" );
gtk_widget_set_sensitive(vugrid, FALSE);
gdk_threads_leave();
printf(" FindSync @ %.02f Hz\n",Rate);
Rate = FindSync(PcmPointer, Mode, Rate, &Skip);
// Final image
gdk_threads_enter();
gtk_statusbar_push( GTK_STATUSBAR(statusbar), 0, "Redrawing" );
gdk_threads_leave();
printf(" getvideo @ %.02f Hz, Skip %d, HedrShift %.0f Hz\n", Rate, Skip, HedrShift);
GetVideo(Mode, Rate, Skip, TRUE);
}
free(PCM);
PCM = NULL;
// Final image
gdk_threads_enter();
gtk_statusbar_push( GTK_STATUSBAR(statusbar), 0, "Redrawing" );
gdk_threads_leave();
printf(" getvideo @ %.02f Hz, Skip %d, HedrShift %.0f Hz\n", Rate, Skip, HedrShift);
GetVideo(Mode, Rate, Skip, TRUE, TRUE);
gdk_threads_enter();
gtk_statusbar_push( GTK_STATUSBAR(statusbar), 0, "Saving" );
gdk_threads_leave();
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(togsave))) {
// Save the raw signal
Lum = malloc( (ModeSpec[Mode].LineLen * ModeSpec[Mode].ImgHeight) * SRATE );
if (Lum == NULL) {
perror("Unable to allocate memory for lum data");
exit(EXIT_FAILURE);
// Save the raw signal
setVU(0,-100);
gdk_threads_enter();
gtk_statusbar_push( GTK_STATUSBAR(statusbar), 0, "Saving" );
gdk_threads_leave();
Lum = malloc( (ModeSpec[Mode].LineLen * ModeSpec[Mode].ImgHeight) * SRATE );
if (Lum == NULL) {
perror("Unable to allocate memory for lum data");
exit(EXIT_FAILURE);
}
for (i=0; i<(ModeSpec[Mode].LineLen * ModeSpec[Mode].ImgHeight) * SRATE; i++)
Lum[i] = clip((StoredFreq[i] - (1500 + HedrShift)) / 3.1372549);
LumFile = fopen(lumfilename,"w");
if (LumFile == NULL) {
perror("Unable to open luma file for writing");
exit(EXIT_FAILURE);
}
fwrite(Lum,1,(ModeSpec[Mode].LineLen * ModeSpec[Mode].ImgHeight) * SRATE,LumFile);
fclose(LumFile);
printf("save png\n");
// Save the received image as PNG
png_t png;
png_init(0,0);
guchar *pixels;
pixels = gdk_pixbuf_get_pixels(RxPixbuf);
printf("write\n");
png_open_file_write(&png, pngfilename);
printf("set data\n");
printf("%d x %d\n",ModeSpec[Mode].ImgWidth, ModeSpec[Mode].ImgHeight);
png_set_data(&png, ModeSpec[Mode].ImgWidth, ModeSpec[Mode].ImgHeight, 8, PNG_TRUECOLOR, pixels);
png_close_file(&png);
printf("ok\n");
}
for (i=0; i<(ModeSpec[Mode].LineLen * ModeSpec[Mode].ImgHeight) * SRATE; i++)
Lum[i] = clip((StoredFreq[i] - (1500 + HedrShift)) / 3.1372549);
LumFile = fopen(lumfilename,"w");
if (LumFile == NULL) {
perror("Unable to open luma file for writing");
exit(EXIT_FAILURE);
}
fwrite(Lum,1,(ModeSpec[Mode].LineLen * ModeSpec[Mode].ImgHeight) * SRATE,LumFile);
fclose(LumFile);
// Save the received image as PNG
png_t png;
png_init(0,0);
guchar *pixels;
pixels = gdk_pixbuf_get_pixels(RxPixbuf);
png_open_file_write(&png, pngfilename);
png_set_data(&png, ModeSpec[Mode].ImgWidth, ModeSpec[Mode].ImgHeight * ModeSpec[Mode].YScale, 8, PNG_TRUECOLOR, pixels);
png_close_file(&png);
free(StoredFreq);
StoredFreq = NULL;

631
slowrx.ui
Wyświetl plik

@ -1,12 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkListStore" id="SavedStore"/>
<object class="GtkAdjustment" id="ShiftAdj">
<property name="lower">-700</property>
<property name="upper">1400</property>
<property name="step_increment">10</property>
<property name="page_increment">100</property>
</object>
<object class="GtkWindow" id="mainwindow">
<property name="can_focus">False</property>
<property name="title" translatable="yes">slowrx</property>
<signal name="delete-event" handler="delete_event" swapped="no"/>
<child>
<object class="GtkBox" id="box1">
<object class="GtkBox" id="MainBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
@ -37,6 +44,16 @@
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="prefmenuitem">
<property name="label">gtk-preferences</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property>
@ -102,200 +119,11 @@
<property name="left_padding">10</property>
<property name="right_padding">10</property>
<child>
<object class="GtkGrid" id="grid1">
<object class="GtkGrid" id="MainGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">5</property>
<property name="column_spacing">5</property>
<child>
<object class="GtkFrame" id="dBFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkAlignment" id="alignment4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="top_padding">10</property>
<property name="bottom_padding">10</property>
<property name="left_padding">10</property>
<property name="right_padding">10</property>
<child>
<object class="GtkGrid" id="vugrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">2</property>
<property name="n_rows">11</property>
<property name="n_columns">4</property>
<child>
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="yalign">1.1175870895385742e-08</property>
<property name="label" translatable="yes">PWR</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">10</property>
<property name="width">2</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="yalign">0</property>
<property name="label" translatable="yes">SNR</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">10</property>
<property name="width">2</property>
<property name="height">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Signal dB</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="ImgFrame">
<property name="visible">True</property>
@ -355,39 +183,408 @@
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="width">2</property>
<property name="height">2</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="DevFrame">
<object class="GtkVBox" id="ButtonVBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">start</property>
<property name="spacing">5</property>
<child>
<object class="GtkFrame" id="OptsFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">start</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkAlignment" id="alignment3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="top_padding">5</property>
<property name="bottom_padding">5</property>
<property name="left_padding">7</property>
<property name="right_padding">5</property>
<child>
<object class="GtkGrid" id="OptsGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="column_homogeneous">True</property>
<property name="n_rows">4</property>
<property name="n_columns">2</property>
<child>
<object class="GtkToggleButton" id="TogSlant">
<property name="label" translatable="yes">AutoSlant</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkToggleButton" id="TogSave">
<property name="label" translatable="yes">AutoSave</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkToggleButton" id="TogAdapt">
<property name="label" translatable="yes">NoiseAdapt</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="BtnAbort">
<property name="label" translatable="yes">Abort</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
<property name="width">2</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkToggleButton" id="TogRx">
<property name="label" translatable="yes">AutoStart</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkSeparator" id="separator1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">5</property>
<property name="margin_bottom">5</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
<property name="width">2</property>
<property name="height">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Rx options</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="ManualFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">start</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkAlignment" id="alignment5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="top_padding">5</property>
<property name="bottom_padding">5</property>
<property name="left_padding">7</property>
<property name="right_padding">5</property>
<child>
<object class="GtkBox" id="ManualVBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkComboBoxText" id="modecombo">
<property name="visible">True</property>
<property name="can_focus">False</property>
<items>
<item translatable="yes">Martin M1</item>
<item translatable="yes">Martin M2</item>
<item translatable="yes">Martin M3</item>
<item translatable="yes">Martin M4</item>
<item translatable="yes">Scottie S1</item>
<item translatable="yes">Scottie S2</item>
<item translatable="yes">Scottie DX</item>
<item translatable="yes">Robot 72</item>
<item translatable="yes">Robot 36</item>
<item translatable="yes">Robot 24</item>
<item translatable="yes">Robot 24 B/W</item>
<item translatable="yes">Robot 12 B/W</item>
<item translatable="yes">Robot 8 B/W</item>
<item translatable="yes">PD-50</item>
<item translatable="yes">PD-90</item>
<item translatable="yes">PD-120</item>
<item translatable="yes">PD-160</item>
<item translatable="yes">PD-180</item>
<item translatable="yes">PD-240</item>
<item translatable="yes">PD-290</item>
<item translatable="yes">Pasokon P3</item>
<item translatable="yes">Pasokon P5</item>
<item translatable="yes">Pasokon P7</item>
<item translatable="yes">Wraase SC2 120</item>
<item translatable="yes">Wraase SC2 180</item>
</items>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="ShiftBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">7</property>
<child>
<object class="GtkLabel" id="label7">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Shift Hz</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="ShiftSpin">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="has_frame">False</property>
<property name="invisible_char">•</property>
<property name="adjustment">ShiftAdj</property>
<property name="snap_to_ticks">True</property>
<property name="numeric">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="BtnStart">
<property name="label" translatable="yes">Start</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label6">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Manual start</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="LevelFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkAlignment" id="alignment6">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="top_padding">5</property>
<property name="bottom_padding">5</property>
<property name="left_padding">7</property>
<property name="right_padding">5</property>
<child>
<object class="GtkGrid" id="vugrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">4</property>
<property name="column_spacing">4</property>
<property name="n_rows">2</property>
<property name="n_columns">2</property>
<child>
<object class="GtkLabel" id="label10">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Power</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label11">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">S/N ratio</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkImage" id="PowerImage">
<property name="width_request">100</property>
<property name="height_request">20</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-missing-image</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkImage" id="SNRImage">
<property name="width_request">100</property>
<property name="height_request">20</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-missing-image</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label9">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Signal level</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">2</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="SavedFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkAlignment" id="alignment3">
<object class="GtkIconView" id="iconview1">
<property name="height_request">100</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="top_padding">10</property>
<property name="bottom_padding">10</property>
<property name="left_padding">12</property>
<property name="right_padding">10</property>
<child>
<object class="GtkComboBoxText" id="cardcombo">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<property name="can_focus">True</property>
<property name="margin_left">5</property>
<property name="margin_right">5</property>
<property name="margin_top">5</property>
<property name="margin_bottom">5</property>
<property name="model">SavedStore</property>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label5">
<object class="GtkLabel" id="label8">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Device</property>
<property name="label" translatable="yes">Saved pictures</property>
<property name="use_markup">True</property>
</object>
</child>
@ -395,25 +592,10 @@
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
<property name="width">1</property>
<property name="width">3</property>
<property name="height">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
@ -433,7 +615,8 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
<property name="pack_type">end</property>
<property name="position">3</property>
</packing>
</child>
</object>

124
video.c
Wyświetl plik

@ -12,10 +12,9 @@
* Mode: M1, M2, S1, S2, R72, R36...
* Rate: exact sampling rate used
* Skip: number of PCM samples to skip at the beginning (for sync phase adjustment)
* Adaptive: false = Static window size, true = Adapt window to noise
* Redraw: false = Apply windowing and FFT to the signal, true = Redraw from cached FFT data
*/
int GetVideo(int Mode, double Rate, int Skip, int Adaptive, int Redraw) {
int GetVideo(int Mode, double Rate, int Skip, int Redraw) {
unsigned int MaxBin = 0;
unsigned int VideoPlusNoiseBins=0, ReceiverBins=0, NoiseOnlyBins=0;
@ -24,7 +23,7 @@ int GetVideo(int Mode, double Rate, int Skip, int Adaptive, int Redraw) {
int Length=0, Sample=0;
int FFTLen=0, WinLength=0;
int samplesread = 0, WinIdx = 0, LineNum = 0;
int x = 0, y = 0, prevline=0, tx=0, ty=0, MaxPcm=0;
int x = 0, y = 0, prevline=0, tx=0, MaxPcm=0;
int HannLens[7] = { 64, 96, 128, 256, 512, 1024, 2048 };
double Hann[7][2048] = {{0}};
double t=0, Freq = 0, NextPixel = 0, NextSNR = 0, NextFFT = 0;
@ -105,13 +104,12 @@ int GetVideo(int Mode, double Rate, int Skip, int Adaptive, int Redraw) {
}
// Initialize pixbuffer for gtk
// Initialize pixbuffer
if (!Redraw) {
gdk_pixbuf_unref(RxPixbuf);
RxPixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, ModeSpec[Mode].ImgWidth, ModeSpec[Mode].ImgHeight *
ModeSpec[Mode].YScale);
ClearPixbuf(RxPixbuf, ModeSpec[Mode].ImgWidth, ModeSpec[Mode].ImgHeight * ModeSpec[Mode].YScale);
RxPixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, ModeSpec[Mode].ImgWidth, ModeSpec[Mode].ImgHeight);
ClearPixbuf(RxPixbuf, ModeSpec[Mode].ImgWidth, ModeSpec[Mode].ImgHeight);
}
int rowstride = gdk_pixbuf_get_rowstride (RxPixbuf);
@ -160,59 +158,53 @@ int GetVideo(int Mode, double Rate, int Skip, int Adaptive, int Redraw) {
if (t >= NextSNR) {
if (Adaptive == 0) {
// SNR estimation can be turned off
SNR = 70;
} else {
// Apply Hann window to SNRSIZE samples
for (i = 0; i < SNRSIZE; i++) in[i] = PCM[Sample + i] * Hann[6][i];
// Apply Hann window to SNRSIZE samples
for (i = 0; i < SNRSIZE; i++) in[i] = PCM[Sample + i] * Hann[6][i];
// FFT
fftw_execute(SNRPlan);
// FFT
fftw_execute(SNRPlan);
// Calculate video-plus-noise power (1500-2300 Hz)
// Calculate video-plus-noise power (1500-2300 Hz)
Pvideo_plus_noise = 0;
for (n = GetBin(1500+HedrShift, SNRSIZE); n <= GetBin(2300+HedrShift, SNRSIZE); n++)
Pvideo_plus_noise += pow(out[n], 2) + pow(out[SNRSIZE - n], 2);
Pvideo_plus_noise = 0;
for (n = GetBin(1500+HedrShift, SNRSIZE); n <= GetBin(2300+HedrShift, SNRSIZE); n++)
Pvideo_plus_noise += pow(out[n], 2) + pow(out[SNRSIZE - n], 2);
// Calculate noise-only power (400-800 Hz + 2700-3400 Hz)
// Calculate noise-only power (400-800 Hz + 2700-3400 Hz)
Pnoise_only = 0;
for (n = GetBin(400+HedrShift, SNRSIZE); n <= GetBin(800+HedrShift, SNRSIZE); n++)
Pnoise_only += pow(out[n], 2) + pow(out[SNRSIZE - n], 2);
Pnoise_only = 0;
for (n = GetBin(400+HedrShift, SNRSIZE); n <= GetBin(800+HedrShift, SNRSIZE); n++)
Pnoise_only += pow(out[n], 2) + pow(out[SNRSIZE - n], 2);
for (n = GetBin(2700+HedrShift, SNRSIZE); n <= GetBin(3400+HedrShift, SNRSIZE); n++)
Pnoise_only += pow(out[n], 2) + pow(out[SNRSIZE - n], 2);
for (n = GetBin(2700+HedrShift, SNRSIZE); n <= GetBin(3400+HedrShift, SNRSIZE); n++)
Pnoise_only += pow(out[n], 2) + pow(out[SNRSIZE - n], 2);
// Bandwidths
VideoPlusNoiseBins = GetBin(2300, SNRSIZE) - GetBin(1500, SNRSIZE) + 1;
// Bandwidths
VideoPlusNoiseBins = GetBin(2300, SNRSIZE) - GetBin(1500, SNRSIZE) + 1;
NoiseOnlyBins = GetBin(800, SNRSIZE) - GetBin(400, SNRSIZE) + 1 +
GetBin(3400, SNRSIZE) - GetBin(2700, SNRSIZE) + 1;
NoiseOnlyBins = GetBin(800, SNRSIZE) - GetBin(400, SNRSIZE) + 1 +
GetBin(3400, SNRSIZE) - GetBin(2700, SNRSIZE) + 1;
ReceiverBins = GetBin(3400, SNRSIZE) - GetBin(400, SNRSIZE);
ReceiverBins = GetBin(3400, SNRSIZE) - GetBin(400, SNRSIZE);
// Eq 15
Pnoise = Pnoise_only * (1.0 * ReceiverBins / NoiseOnlyBins);
Psignal = Pvideo_plus_noise - Pnoise_only * (1.0 * VideoPlusNoiseBins / NoiseOnlyBins);
// Eq 15
Pnoise = Pnoise_only * (1.0 * ReceiverBins / NoiseOnlyBins);
Psignal = Pvideo_plus_noise - Pnoise_only * (1.0 * VideoPlusNoiseBins / NoiseOnlyBins);
// Lower bound to -20 dB
SNR = ((Psignal / Pnoise < .01) ? -20 : 10 * log10(Psignal / Pnoise));
// Lower bound to -20 dB
SNR = ((Psignal / Pnoise < .01) ? -20 : 10 * log10(Psignal / Pnoise));
NextSNR += ModeSpec[Mode].LineLen / 60;
}
NextSNR += ModeSpec[Mode].LineLen / 60;
}
if (t >= NextFFT) {
// Set window size based on SNR
// Adapt window size to SNR
FFTLen = 512;
if (SNR >= 30) WinLength = 37;
if (!Adaptive) WinLength = 37;
else if (SNR >= 30) WinLength = 37;
else {
if (SNR < -10) { WinIdx = 5; FFTLen = 1024; }
else if (SNR < -5) WinIdx = 4;
@ -235,7 +227,7 @@ int GetVideo(int Mode, double Rate, int Skip, int Adaptive, int Redraw) {
// Select window function based on SNR
if (SNR < 30) {
if (Adaptive && SNR < 30) {
// Apply Hann window
for (i = 0; i < WinLength; i++)
@ -365,35 +357,33 @@ int GetVideo(int Mode, double Rate, int Skip, int Adaptive, int Redraw) {
// Calculate and draw pixels on line change
if (LineNum != prevline) {
for (tx = 0; tx < ModeSpec[Mode].ImgWidth; tx++) {
for (ty = prevline * ModeSpec[Mode].YScale; ty < prevline * ModeSpec[Mode].YScale + ModeSpec[Mode].YScale; ty++) {
p = pixels + ty * rowstride + tx * 3;
p = pixels + prevline * rowstride + tx * 3;
switch(ModeSpec[Mode].ColorEnc) {
switch(ModeSpec[Mode].ColorEnc) {
case RGB:
p[0] = Image[tx][prevline][0];
p[1] = Image[tx][prevline][1];
p[2] = Image[tx][prevline][2];
break;
case RGB:
p[0] = Image[tx][prevline][0];
p[1] = Image[tx][prevline][1];
p[2] = Image[tx][prevline][2];
break;
case GBR:
p[0] = Image[tx][prevline][2];
p[1] = Image[tx][prevline][0];
p[2] = Image[tx][prevline][1];
break;
case GBR:
p[0] = Image[tx][prevline][2];
p[1] = Image[tx][prevline][0];
p[2] = Image[tx][prevline][1];
break;
case YUV:
p[0] = clip((100 * Image[tx][prevline][0] + 140 * Image[tx][prevline][1] - 17850) / 100.0);
p[1] = clip((100 * Image[tx][prevline][0] - 71 * Image[tx][prevline][1] - 33 *
Image[tx][prevline][2] + 13260) / 100.0);
p[2] = clip((100 * Image[tx][prevline][0] + 178 * Image[tx][prevline][2] - 22695) / 100.0);
break;
case YUV:
p[0] = clip((100 * Image[tx][prevline][0] + 140 * Image[tx][prevline][1] - 17850) / 100.0);
p[1] = clip((100 * Image[tx][prevline][0] - 71 * Image[tx][prevline][1] - 33 *
Image[tx][prevline][2] + 13260) / 100.0);
p[2] = clip((100 * Image[tx][prevline][0] + 178 * Image[tx][prevline][2] - 22695) / 100.0);
break;
case BW:
p[0] = p[1] = p[2] = Image[tx][prevline][0];
break;
case BW:
p[0] = p[1] = p[2] = Image[tx][prevline][0];
break;
}
}
}
@ -420,9 +410,9 @@ int GetVideo(int Mode, double Rate, int Skip, int Adaptive, int Redraw) {
}
// High-quality scaling when finished
if (Redraw) {
if (Redraw || !(gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(togslant)))) {
gdk_pixbuf_unref(DispPixbuf);
DispPixbuf = gdk_pixbuf_scale_simple(RxPixbuf,500,500.0/ModeSpec[Mode].ImgWidth * ModeSpec[Mode].ImgHeight * ModeSpec[Mode].YScale,GDK_INTERP_BILINEAR);
DispPixbuf = gdk_pixbuf_scale_simple(RxPixbuf,500,500.0/ModeSpec[Mode].ImgWidth * ModeSpec[Mode].ImgHeight * ModeSpec[Mode].YScale,GDK_INTERP_HYPER);
gdk_threads_enter();
gtk_image_set_from_pixbuf(GTK_IMAGE(RxImage), DispPixbuf);

43
vis.c
Wyświetl plik

@ -27,6 +27,7 @@ int GetVIS () {
double *in;
double *out;
unsigned int FFTLen = 2048;
int selmode;
// Plan for frequency estimation
in = fftw_malloc(sizeof(double) * FFTLen);
@ -50,7 +51,7 @@ int GetVIS () {
double HedrBuf[100] = {0}, tone[100] = {0};
int HedrPtr = 0;
short int MaxPcm = 0;
char infostr[60] = {0}, visfail = FALSE;
char infostr[60] = {0}, gotvis = FALSE;
for (i = 0; i < FFTLen; i++) in[i] = 0;
@ -65,6 +66,8 @@ int GetVIS () {
exit(EXIT_FAILURE);
}
ManualActivated = FALSE;
while ( TRUE ) {
// Read 10 ms from DSP
@ -128,7 +131,7 @@ int GetVIS () {
// Is there a pattern that looks like (the end of) a calibration header + VIS?
// Tolerance ±25 Hz
HedrShift = 0;
visfail = TRUE;
gotvis = FALSE;
for (i = 0; i < 3; i++) {
if (HedrShift != 0) break;
for (j = 0; j < 3; j++) {
@ -145,16 +148,16 @@ int GetVIS () {
// Read VIS
visfail = FALSE;
gotvis = TRUE;
for (k = 0; k < 8; k++) {
if (tone[18+i+3*k] > tone[0+j] - 625 && tone[18+i+3*k] < tone[0+j] - 575) Bit[k] = 0;
else if (tone[18+i+3*k] > tone[0+j] - 825 && tone[18+i+3*k] < tone[0+j] - 775) Bit[k] = 1;
else { // erroneous bit
visfail = TRUE;
gotvis = FALSE;
break;
}
}
if (!visfail) {
if (gotvis) {
HedrShift = tone[0+j] - 1900;
VIS = Bit[0] + (Bit[1] << 1) + (Bit[2] << 2) + (Bit[3] << 3) + (Bit[4] << 4) +
@ -167,11 +170,11 @@ int GetVIS () {
if (Parity != ParityBit && VIS != 0x06) {
printf(" Parity fail\n");
visfail = TRUE;
gotvis = FALSE;
} else if (VISmap[VIS] == UNKNOWN) {
printf(" Unknown VIS\n");
snprintf(infostr, sizeof(infostr)-1, "How to decode image with VIS %d (%02Xh)?", VIS, VIS);
visfail = TRUE;
gotvis = FALSE;
gdk_threads_enter();
gtk_label_set_markup(GTK_LABEL(infolabel), infostr);
gdk_threads_leave();
@ -183,7 +186,31 @@ int GetVIS () {
}
}
if (!visfail) break;
if (gotvis) {
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(togrx))) {
break;
}
}
// Manual start
if (ManualActivated) {
gdk_threads_enter();
gtk_widget_set_sensitive( manualframe, FALSE );
gdk_threads_leave();
selmode = gtk_combo_box_get_active (GTK_COMBO_BOX(modecombo)) + 1;
HedrShift = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(shiftspin));
VIS = 0;
for (i=0; i<0x80; i++) {
if (VISmap[i] == selmode) {
VIS = i;
break;
}
}
break;
}
if (++Pointer >= 50) Pointer = 0;