#UNAME_N=jetsen
# Additional options that can be chosen at compile time:
-# -DDIGI_MODES wide filters and no noise reduction in DIGU/DIGL
# -DSPLIT_RXTX if there is more than one receiver, TX panel only "hides" the first one
# -DPROTOCOL_DEBUG logs (on stderr) all state changes sent to the SDR (only old protocol)
-# -DDEBUG activate debug output
+# -DDEBUG activate general debug output
#
# leave the list empty if no such option should be used
#UNAME_N=jetsen
# Additional options that can be chosen at compile time:
-# -DDIGI_MODES wide filters and no noise reduction in DIGU/DIGL
# -DSPLIT_RXTX if there is more than one receiver, TX panel only "hides" the first one
# -DPROTOCOL_DEBUG logs (on stderr) all state changes sent to the SDR (only old protocol)
# -DDEBUG activate debug output
#
# leave the list empty if no such option should be used
-ADDITIONAL_OPTIONS= -DDIGI_MODES -DSPLIT_RXTX
+ADDITIONAL_OPTIONS= -DSPLIT_RXTX
CC=gcc
LINK=gcc
set_button_text_color(last_filter,"black");
last_filter=widget;
set_button_text_color(last_filter,"orange");
- // DL1YCF added return statement to make the compiler happy.
- // however I am unsure about the correct return value.
- // I would have coded this as a void function.
return FALSE;
}
}
break;
-#ifdef DIGI_MODES
- case modeDIGU:
- case modeDIGL:
- gtk_button_set_label(GTK_BUTTON(close_b), "DIGU/DIGL have a fixed wide filter.");
- break;
-#endif
-
default:
for(i=0;i<FILTERS-2;i++) {
FILTER* band_filter=&band_filters[i];
#include "receiver.h"
#include "vfo.h"
#include "button_text.h"
-#ifdef DIGI_MODES
-#include "noise_menu.h" // for noise-on/off in DIGU/L
-#endif
static GtkWidget *parent_window=NULL;
set_button_text_color(last_mode,"black");
last_mode=widget;
set_button_text_color(last_mode,"orange");
-#ifdef DIGI_MODES
- switch (m) {
- case modeDIGL:
- case modeDIGU:
- noise_off(); // diable noise reduction machine completely for DIGI modes
- break;
- default:
- update_noise(); // set noise reduction to the values stored in the current RECEIVER
- }
-#endif
vfo_mode_changed(m);
return FALSE;
}
return FALSE;
}
-#ifdef DIGI_MODES
-void noise_off() {
- SetEXTANBRun(active_receiver->id, 0);
- SetEXTNOBRun(active_receiver->id, 0);
- SetRXAANRRun(active_receiver->id, 0);
- SetRXAEMNRRun(active_receiver->id, 0);
- SetRXAANFRun(active_receiver->id, 0);
- SetRXASNBARun(active_receiver->id, 0);
-}
-
void update_noise() {
-#else
-static void update_noise() {
-#endif
SetEXTANBRun(active_receiver->id, active_receiver->nb);
SetEXTNOBRun(active_receiver->id, active_receiver->nb2);
SetRXAANRRun(active_receiver->id, active_receiver->nr);
static void nb_none_cb(GtkWidget *widget, gpointer data) {
active_receiver->nb=0;
active_receiver->nb2=0;
+ mode_settings[vfo[active_receiver->id].mode].nb=0;
+ mode_settings[vfo[active_receiver->id].mode].nb2=0;
update_noise();
}
static void nb_cb(GtkWidget *widget, gpointer data) {
active_receiver->nb=1;
active_receiver->nb2=0;
+ mode_settings[vfo[active_receiver->id].mode].nb=1;
+ mode_settings[vfo[active_receiver->id].mode].nb2=0;
update_noise();
}
static void nr_none_cb(GtkWidget *widget, gpointer data) {
active_receiver->nr=0;
active_receiver->nr2=0;
+ mode_settings[vfo[active_receiver->id].mode].nr=0;
+ mode_settings[vfo[active_receiver->id].mode].nr2=0;
update_noise();
}
static void nr_cb(GtkWidget *widget, gpointer data) {
active_receiver->nr=1;
active_receiver->nr2=0;
+ mode_settings[vfo[active_receiver->id].mode].nr=1;
+ mode_settings[vfo[active_receiver->id].mode].nr2=0;
update_noise();
}
static void nb2_cb(GtkWidget *widget, gpointer data) {
active_receiver->nb=0;
active_receiver->nb2=1;
+ mode_settings[vfo[active_receiver->id].mode].nb=0;
+ mode_settings[vfo[active_receiver->id].mode].nb2=1;
update_noise();
}
static void nr2_cb(GtkWidget *widget, gpointer data) {
active_receiver->nr=0;
- active_receiver->nr2=2;
+ active_receiver->nr2=1;
+ mode_settings[vfo[active_receiver->id].mode].nr=0;
+ mode_settings[vfo[active_receiver->id].mode].nr2=1;
update_noise();
}
static void anf_cb(GtkWidget *widget, gpointer data) {
active_receiver->anf=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+ mode_settings[vfo[active_receiver->id].mode].anf=active_receiver->anf;
update_noise();
}
static void snb_cb(GtkWidget *widget, gpointer data) {
active_receiver->snb=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+ mode_settings[vfo[active_receiver->id].mode].snb=active_receiver->snb;
update_noise();
}
gtk_grid_set_column_spacing (GTK_GRID(grid),5);
gtk_grid_set_row_spacing (GTK_GRID(grid),5);
-#ifdef DIGI_MODES
- if (mode == modeDIGU || mode == modeDIGL) {
- GtkWidget *close_b=gtk_button_new_with_label("DIGU/DIGL have no noise options.");
- g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
- gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
- }
- else {
-#endif
GtkWidget *close_b=gtk_button_new_with_label("Close");
g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
gtk_widget_show(b_nr2);
gtk_grid_attach(GTK_GRID(grid),b_nr2,col,row,1,1);
g_signal_connect(b_nr2,"pressed",G_CALLBACK(nr2_cb),NULL);
-#ifdef DIGI_MODES
- }
-#endif
gtk_container_add(GTK_CONTAINER(content),grid);
extern void noise_menu(GtkWidget *parent);
-#ifdef DIGI_MODES
-extern void noise_off();
extern void update_noise();
-#endif
if(mode!=modeCWU && mode!=modeCWL) {
// output_buffer[C1]|=0x00;
} else {
- if((tune==1) || (vox==1) || (cw_keyer_internal==0)) {
+ if((tune==1) || (vox==1) || (cw_keyer_internal==0) || (transmitter->twotone==1)) {
output_buffer[C1]|=0x00;
} else {
output_buffer[C1]|=0x01;
// If CW is done on the HPSDR board, we should not set
// the MOX bit, everything is done in the FPGA.
//
-// However, if we are doing CAT CW, local CW or tuning,
-// we must put the SDR into TX mode.
+// However, if we are doing CAT CW, local CW or tuning/TwoTone,
+// we must put the SDR into TX mode *here*.
//
- if(tune || CAT_cw_is_active || !cw_keyer_internal) {
+ if(tune || CAT_cw_is_active || !cw_keyer_internal || transmitter->twotone) {
output_buffer[C0]|=0x01;
}
} else {
- // not doing CW? set MOX in any case.
+ // not doing CW? always set MOX if transmitting
output_buffer[C0]|=0x01;
}
}
static int mic_buffer_size;
static int audio_buffer_size=256;
-//
-// compile with DummyTwoTone defined, and you will have an
-// additional "microphone" device producing a two-tone signal
-// with 700 and 1900 Hz.
-//
-#ifdef DummyTwoTone
-//
-// Dummy Two-tone input device
-//
-static int TwoTone=0;
-#define lentab 480
-static float sintab[lentab];
-static int tonept;
-#define factab 0.013089969389957471826927680763665 // 2 Pi / 480
-#endif
-
-
//
// AUDIO_GET_CARDS
//
PaError err;
-#ifdef DummyTwoTone
- // generate sine tab, 700 and 1900 Hz.
- for (i=0; i< lentab; i++) sintab[i] = 0.45*(sin(7*i*factab)+sin(19*i*factab));
-#endif
-
err = Pa_Initialize();
if( err != paNoError )
{
inputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
inputParameters.hostApiSpecificStreamInfo = NULL;
if (Pa_IsFormatSupported(&inputParameters, NULL, 48000.0) == paFormatIsSupported) {
-#ifdef DummyTwoTone
- // duplicate the first suitable device, this will become
- // a dummy two-tone generator
- if (n_input_devices == 0) {
- input_devices[n_input_devices]="TwoTone";
- in_device_no[n_input_devices++] =i;
- }
-#endif
if (n_input_devices < MAXDEVICES) {
input_devices[n_input_devices]=deviceInfo->name;
in_device_no[n_input_devices++] =i;
}
mic_buffer=(unsigned char *)malloc(2*framesPerBuffer);
mic_buffer_size=framesPerBuffer;
-#ifdef DummyTwoTone
- TwoTone=0;
- if (transmitter->input_device == 0) {
- tonept=0;
- TwoTone=1;
- }
-#endif
return 0;
}
//
// Convert input buffer in paFloat32 into a sequence of 16-bit
-// values in the mic buffer. If using the dummy Two-Tone
-// device, mic input will be discarded and a two-tone
-// signal produced instead.
+// values in the mic buffer.
//
if (mic_buffer == NULL) return paAbort;
*p++ = 0;
*p++ = 0;
}
-#ifdef DummyTwoTone
- } else if (TwoTone == 0) {
-#else
} else {
-#endif
for (i=0; i<framesPerBuffer; i++) {
isample=(short) (in[i]*32768.0);
*p++ = (isample & 0xFF); // LittleEndian
*p++ = (isample >> 8)& 0xFF;
}
-#ifdef DummyTwoTone
- } else {
- for (i=0; i<framesPerBuffer; i++) {
- isample=(short) (sintab[tonept++]*32767.0);
- if (tonept == lentab) tonept=0;
- *p++ = (isample & 0xFF); // LittleEndian
- *p++ = (isample >> 8)& 0xFF;
- }
-#endif
}
//
// Call routine to send mic buffer
bandRestoreState();
memRestoreState();
vfo_restore_state();
+ modesettings_restore_state();
#ifdef FREEDV
freedv_restore_state();
#endif
setProperty("rx2_gain_slider",value);
vfo_save_state();
+ modesettings_save_state();
sprintf(value,"%d",receivers);
setProperty("receivers",value);
for(i=0;i<receivers;i++) {
}
set_deviation(rx);
break;
-#ifdef DIGI_MODES
- case modeDIGU:
- set_filter(rx,0,3000);
- break;
- case modeDIGL:
- set_filter(rx,-3000,0);
- break;
-#endif
default:
{
FILTER *mode_filters=filters[m];
// Save in the file now..
memSaveState();
- // DL1YCF added return statement to make the compiler happy.
- // however I am unsure about the correct return value.
- // I would have coded this as a void function.
return FALSE;
}
vfo_mode_changed(mem[index].mode);
g_idle_add(ext_vfo_update,NULL);
- // DL1YCF added return statement to make the compiler happy.
- // however I am unsure about the correct return value.
- // I would have coded this as a void function.
return FALSE;
}
// It is important query tx->mode and tune only once, to assure that
// the two "if (cwmode)" queries give the same result.
- cwmode = (tx->mode == modeCWL || tx->mode == modeCWU) && !tune;
+ cwmode = (tx->mode == modeCWL || tx->mode == modeCWU) && !tune && !tx->twotone;
switch(protocol) {
case ORIGINAL_PROTOCOL:
transmitter->twotone=state;
if(state) {
// DL1YCF: set frequencies and levels
- SetTXAPostGenTTFreq(transmitter->id, 900.0, 1700.0);
+ switch(tx->mode) {
+ case modeCWL:
+ case modeLSB:
+ case modeDIGL:
+ SetTXAPostGenTTFreq(transmitter->id, -900.0, -1700.0);
+ break;
+ default:
+ SetTXAPostGenTTFreq(transmitter->id, 900.0, 1700.0);
+ break;
+ }
SetTXAPostGenTTMag (transmitter->id, 0.49, 0.49);
SetTXAPostGenMode(transmitter->id, 1);
SetTXAPostGenRun(transmitter->id, 1);
static gfloat filter_left;
static gfloat filter_right;
-#ifdef SPLIT_RXTX
#include "new_menu.h"
#include "ext.h"
#include "sliders.h"
static gboolean making_active = FALSE;
-#endif
/* Create a new surface of the appropriate size to store our scribbles */
static gboolean
has_moved=FALSE;
pressed=TRUE;
}
-#ifdef SPLIT_RXTX
making_active=(active_receiver != receiver[0]);
-#endif
return TRUE;
}
int display_height=gtk_widget_get_allocated_height (tx->panadapter);
#ifdef SPLIT_RXTX
+ // when clicking into the TX window, the first receiver is
+ // selected since the TX window only hides the display of
+ // the first RX
if (making_active) {
active_receiver=receiver[0];
making_active=FALSE;
{
int x, y;
GdkModifierType state;
-#ifdef SPLIT_RXTX
+ // do not do this upon the first click. Instead, click first, drag later
if (!making_active) {
-#endif
- gdk_window_get_device_position (event->window,
- event->device,
- &x,
- &y,
- &state);
- // DL1YCF: added a pair of () to fix an error
- if(((state & GDK_BUTTON1_MASK) == GDK_BUTTON1_MASK) || pressed) {
- int moved=last_x-x;
- vfo_move((long long)((float)moved*hz_per_pixel));
- last_x=x;
- has_moved=TRUE;
- }
-#ifdef SPLIT_RXTX
+ gdk_window_get_device_position (event->window,
+ event->device,
+ &x,
+ &y,
+ &state);
+ if(((state & GDK_BUTTON1_MASK) == GDK_BUTTON1_MASK) || pressed) {
+ int moved=last_x-x;
+ vfo_move((long long)((float)moved*hz_per_pixel));
+ last_x=x;
+ has_moved=TRUE;
+ }
}
-#endif
return TRUE;
}
int display_width=gtk_widget_get_allocated_width (tx->panadapter);
int display_height=gtk_widget_get_allocated_height (tx->panadapter);
- int id=0;
-#ifdef SPLIT_RXTX
- id = active_receiver->id;
+ int id = active_receiver->id;
if (split) {
id = 1-id;
}
-#else
- if(split) {
- id=1;
- }
-#endif
samples=tx->pixel_samples;
//hz_per_pixel=(double)tx->output_rate/(double)display_width;
//long long half=12000LL; //(long long)(tx->output_rate/2);
long long half=24000LL; //(long long)(tx->output_rate/2);
long long frequency;
- frequency=vfo[id].frequency+vfo[VFO_B].offset;
+ frequency=vfo[id].frequency+vfo[id].offset;
divisor=5000LL;
for(i=0;i<display_width;i++) {
f = frequency - half + (long) (hz_per_pixel * i);
// band edges
long long min_display=frequency-half;
long long max_display=frequency+half;
- int b;
- if(split) {
- b=vfo[1].band;
- } else {
- b=vfo[0].band;
- }
+ int b=vfo[i].band;
BAND *band=band_get_band(b);
if(band->frequencyMin!=0LL) {
cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
#include "new_menu.h"
#include "rigctl.h"
#include "ext.h"
+#include "noise_menu.h"
#ifdef FREEDV
#include "freedv.h"
#endif
static GtkWidget* menu=NULL;
static GtkWidget* band_menu=NULL;
-
static void vfo_save_bandstack() {
BANDSTACK *bandstack=bandstack_get_bandstack(vfo[0].band);
BANDSTACK_ENTRY *entry=&bandstack->entry[vfo[0].bandstack];
entry->filter=vfo[0].filter;
}
+void modesettings_save_state() {
+ int i;
+ char name[80];
+ char value[80];
+
+ for (i=0; i<MODES; i++) {
+ sprintf(name,"modeset.%d.filter", i);
+ sprintf(value,"%d", mode_settings[i].filter);
+ setProperty(name,value);
+ sprintf(name,"modeset.%d.nr", i);
+ sprintf(value,"%d", mode_settings[i].nr);
+ setProperty(name,value);
+ sprintf(name,"modeset.%d.nr2", i);
+ sprintf(value,"%d", mode_settings[i].nr2);
+ setProperty(name,value);
+ sprintf(name,"modeset.%d.nb", i);
+ sprintf(value,"%d", mode_settings[i].nb);
+ setProperty(name,value);
+ sprintf(name,"modeset.%d.nb2", i);
+ sprintf(value,"%d", mode_settings[i].nb2);
+ setProperty(name,value);
+ sprintf(name,"modeset.%d.anf", i);
+ sprintf(value,"%d", mode_settings[i].anf);
+ setProperty(name,value);
+ sprintf(name,"modeset.%d.snb", i);
+ sprintf(value,"%d", mode_settings[i].snb);
+ setProperty(name,value);
+ }
+}
+
+void modesettings_restore_state() {
+ int i;
+ char name[80];
+ char *value;
+
+ // set some reasonable defaults for the filters
+
+ for (i=0; i<MODES; i++) {
+ mode_settings[i].filter=filterF6;
+ mode_settings[i].nr=0;
+ mode_settings[i].nr2=0;
+ mode_settings[i].nb=0;
+ mode_settings[i].nb2=0;
+ mode_settings[i].anf=0;
+ mode_settings[i].snb=0;
+
+ sprintf(name,"modeset.%d.filter",i);
+ value=getProperty(name);
+ if(value) mode_settings[i].filter=atoi(value);
+ sprintf(name,"modeset.%d.nr",i);
+ value=getProperty(name);
+ if(value) mode_settings[i].nr=atoi(value);
+ sprintf(name,"modeset.%d.nr2",i);
+ value=getProperty(name);
+ if(value) mode_settings[i].nr2=atoi(value);
+ sprintf(name,"modeset.%d.nb",i);
+ value=getProperty(name);
+ if(value) mode_settings[i].nb=atoi(value);
+ sprintf(name,"modeset.%d.nb2",i);
+ value=getProperty(name);
+ if(value) mode_settings[i].nb2=atoi(value);
+ sprintf(name,"modeset.%d.anf",i);
+ value=getProperty(name);
+ if(value) mode_settings[i].anf=atoi(value);
+ sprintf(name,"modeset.%d.snb",i);
+ value=getProperty(name);
+ if(value) mode_settings[i].snb=atoi(value);
+ }
+}
+
void vfo_save_state() {
int i;
char name[80];
}
+//
+// When changing the mode, store the current filter setting
+// and for the new mode, switch to the filter we had the last time
+//
void vfo_mode_changed(int m) {
int id=active_receiver->id;
+
vfo[id].mode=m;
+ // restore filter and NR configuration used last in the new mode
+ vfo[id].filter =mode_settings[m].filter;
+ active_receiver->nr =mode_settings[m].nr;
+ active_receiver->nr2=mode_settings[m].nr2;
+ active_receiver->nb =mode_settings[m].nb;
+ active_receiver->nb2=mode_settings[m].nb2;
+ active_receiver->anf=mode_settings[m].anf;
+ active_receiver->snb=mode_settings[m].snb;
+
+ // make changes effective
+ update_noise();
switch(id) {
case 0:
receiver_mode_changed(receiver[0]);
void vfo_filter_changed(int f) {
int id=active_receiver->id;
+
+ // store changed filter in the mode settings
+ mode_settings[vfo[id].mode].filter = f;
+
vfo[id].filter=f;
switch(id) {
case 0:
int id=active_receiver->id;
FILTER* band_filters=filters[vfo[id].mode];
FILTER* band_filter=&band_filters[vfo[id].filter];
- int have_noise=1;
if(vfo_surface) {
char temp_text[32];
cairo_t *cr;
case modeAM:
sprintf(temp_text,"%s %s %s",mode_string[vfo[id].mode],band_filter->title,dv);
break;
-#ifdef DIGI_MODES
- case modeDIGU:
- case modeDIGL:
- // No band filter title
- sprintf(temp_text,"%s %s",mode_string[vfo[id].mode],dv);
- // used later on NOT to display noise reduction
- have_noise=0;
- break;
-#endif
default:
sprintf(temp_text,"%s %s",mode_string[vfo[id].mode],band_filter->title);
break;
cairo_show_text(cr, "NB");
cairo_move_to(cr, 175, 50);
- if(active_receiver->nb2 && have_noise) {
+ if(active_receiver->nb2) {
cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
} else {
cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
cairo_show_text(cr, "NB2");
cairo_move_to(cr, 200, 50);
- if(active_receiver->nr && have_noise) {
+ if(active_receiver->nr) {
cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
} else {
cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
cairo_show_text(cr, "NR");
cairo_move_to(cr, 225, 50);
- if(active_receiver->nr2 && have_noise) {
+ if(active_receiver->nr2) {
cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
} else {
cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
cairo_show_text(cr, "NR2");
cairo_move_to(cr, 250, 50);
- if(active_receiver->anf && have_noise) {
+ if(active_receiver->anf) {
cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
} else {
cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
cairo_show_text(cr, "ANF");
cairo_move_to(cr, 275, 50);
- if(active_receiver->snb && have_noise) {
+ if(active_receiver->snb) {
cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
} else {
cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
#ifndef _VFO_H
#define _VFO_H
+#include "mode.h"
enum {
VFO_A=0,
} vfo[MAX_VFOS];
+//
+// Store filter and NR settings on a per-mode basis
+//
+struct _mode_settings {
+ int filter;
+ int nb;
+ int nb2;
+ int nr;
+ int nr2;
+ int anf;
+ int snb;
+} mode_settings[MODES];
+
extern int steps[];
extern char *step_labels[];
extern void vfo_save_state();
extern void vfo_restore_state();
+extern void modesettings_save_state();
+extern void modesettings_restore_state();
extern void vfo_band_changed(int b);
extern void vfo_bandstack_changed(int b);