]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
New version to support 2 receivers
authorJohn Melton - G0ORX/N6LYT <john.d.melton@googlemail.com>
Mon, 13 Feb 2017 09:37:30 +0000 (09:37 +0000)
committerJohn Melton - G0ORX/N6LYT <john.d.melton@googlemail.com>
Mon, 13 Feb 2017 09:37:30 +0000 (09:37 +0000)
109 files changed:
Makefile
agc_menu.c
ant_menu.c
audio.c
audio.h
audio_menu.c
band.c
band.h
band_menu.c
band_menu.h
bandstack.h
bandstack_menu.c
configure.c
cw_menu.c
discovered.h
discovery.c [new file with mode: 0644]
discovery.h [new file with mode: 0644]
display_menu.c
dsp_menu.c
encoder_menu.c [new file with mode: 0644]
encoder_menu.h [new file with mode: 0644]
equalizer_menu.c
filter.c
filter.h
filter_menu.c
filter_menu.h
fm_menu.c
freqent_menu.c
general_menu.c
gpio.c
gpio.h
gpio_mraa.c
i2c.c [new file with mode: 0644]
i2c.h [new file with mode: 0644]
libusbio.c [new file with mode: 0644]
libusbio.h [new file with mode: 0644]
main.c
main.h
meter.c
meter.h
meter_menu.c
mode.c
mode.h
mode_menu.c
new_discovery.c
new_menu.c
new_menu.h
new_protocol.c
new_protocol.h
noise_menu.c
oc_menu.c
old_discovery.c
old_protocol.c
old_protocol.h
ozyio.c [new file with mode: 0644]
ozyio.h [new file with mode: 0644]
pa_menu.c
panadapter.c [deleted file]
panadapter.h [deleted file]
property.c
property.h
psk.c
psk_waterfall.c
psk_waterfall.h
radio.c
radio.h
radio_menu.c [new file with mode: 0644]
radio_menu.h [new file with mode: 0644]
receiver.c [new file with mode: 0644]
receiver.h
rigctl.c
rigctl.h
rit.c
rx_menu.c [new file with mode: 0644]
rx_menu.h [new file with mode: 0644]
rx_panadapter.c [new file with mode: 0644]
rx_panadapter.h [new file with mode: 0644]
sliders.c
sliders.h
soundio.c [new file with mode: 0644]
soundio.h [new file with mode: 0644]
splash.c
splash.h
store.c [new file with mode: 0644]
store.h [new file with mode: 0644]
store_menu.c [new file with mode: 0644]
store_menu.h [new file with mode: 0644]
toolbar.c
toolbar.h
transmitter.c [new file with mode: 0644]
transmitter.h [new file with mode: 0644]
tx_menu.c [new file with mode: 0644]
tx_menu.h [new file with mode: 0644]
tx_panadapter.c [new file with mode: 0644]
tx_panadapter.h [new file with mode: 0644]
update.h
vfo.c
vfo.h
vfo_menu.c [new file with mode: 0644]
vfo_menu.h [new file with mode: 0644]
vox.c
vox.h
vox_menu.c
vox_menu.h
waterfall.c
waterfall.h
wdsp_init.c
wdsp_init.h [deleted file]
xvtr_menu.c

index 773c00b0c9424cdfe02a99500858152e7a44cae4..78ab4d5fcb27c7ca5b8d4edbdb21c1c75101576b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -3,11 +3,17 @@
 GIT_DATE := $(firstword $(shell git --no-pager show --date=short --format="%ai" --name-only))
 GIT_VERSION := $(shell git describe --abbrev=0 --tags)
 
+# uncomment the line below to include GPIO
+GPIO_INCLUDE=GPIO
+
+# uncomment the line below to include USB Ozy support
+USBOZY_INCLUDE=USBOZY
+
 # uncomment the line below to include support for psk31
-PSK_INCLUDE=PSK
+#PSK_INCLUDE=PSK
 
 # uncomment the line to below include support for FreeDV codec2
-FREEDV_INCLUDE=FREEDV
+#FREEDV_INCLUDE=FREEDV
 
 # uncomment the line to below include support for sx1509 i2c expander
 #SX1509_INCLUDE=sx1509
@@ -15,12 +21,15 @@ FREEDV_INCLUDE=FREEDV
 # uncomment the line to below include support local CW keyer
 #LOCALCW_INCLUDE=LOCALCW
 
+# uncomment the line below to include MCP23017 I2C
+#I2C_INCLUDE=I2C
+
 #uncomment the line below for the platform being compiled on
-UNAME_N=raspberrypi
+#UNAME_N=raspberrypi
 #UNAME_N=odroid
 #UNAME_N=up
 #UNAME_N=pine64
-#UNAME_N=x86
+UNAME_N=x86
 
 CC=gcc
 LINK=gcc
@@ -28,6 +37,17 @@ LINK=gcc
 # uncomment the line below for various debug facilities
 #DEBUG_OPTION=-D DEBUG
 
+ifeq ($(USBOZY_INCLUDE),USBOZY)
+USBOZY_OPTIONS=-D USBOZY
+USBOZY_LIBS=-lusb-1.0
+USBOZY_SOURCES= \
+ozyio.c
+USBOZY_HEADERS= \
+ozyio.h
+USBOZY_OBJS= \
+ozyio.o
+endif
+
 # uncomment the line below for LimeSDR (uncomment line below)
 #LIMESDR_INCLUDE=LIMESDR
 
@@ -88,50 +108,39 @@ beep.o \
 iambic.o
 endif
 
-#required for MRAA GPIO
-#MRAA_INCLUDE=MRAA
-
-ifeq ($(MRAA_INCLUDE),MRAA)
-  GPIO_OPTIONS=-D GPIO
-  GPIO_LIBS=-lmraa
-  GPIO_SOURCES= \
-  gpio_mraa.c
-  GPIO_HEADERS= \
-  gpio.h
-  GPIO_OBJS= \
-  gpio_mraa.o
-else
-  ifeq ($(UNAME_N),raspberrypi)
+ifeq ($(GPIO_INCLUDE),GPIO)
   GPIO_OPTIONS=-D GPIO
   GPIO_LIBS=-lwiringPi -lpigpio
-  endif
-  ifeq ($(UNAME_N),odroid)
-  GPIO_LIBS=-lwiringPi
-  endif
-  ifeq ($(SX1509_INCLUDE),sx1509)
-  GPIO_OPTIONS=-D GPIO
-  GPIO_OPTIONS+=-D sx1509
-  GPIO_LIBS+=-lsx1509
-  endif
   GPIO_SOURCES= \
-  gpio.c
+  gpio.c \
+  encoder_menu.c
   GPIO_HEADERS= \
-  gpio.h
+  gpio.h \
+  encoder_menu.h
   GPIO_OBJS= \
-  gpio.o
+  gpio.o \
+  encoder_menu.o
+endif
+
+ifeq ($(I2C_INCLUDE),I2C)
+  I2C_OPTIONS=-D I2C
+  I2C_SOURCES=i2c.c
+  I2C_HEADERS=i2c.h
+  I2C_OBJS=i2c.o
 endif
 
 #uncomment if build for SHORT FRAMES (MIC and Audio)
-SHORT_FRAMES="-D SHORT_FRAMES"
+SHORT_FRAMES=-D SHORT_FRAMES
 
 GTKINCLUDES=`pkg-config --cflags gtk+-3.0`
 GTKLIBS=`pkg-config --libs gtk+-3.0`
 
 AUDIO_LIBS=-lasound
+#AUDIO_LIBS=-lsoundio
 
-OPTIONS=-g -D $(UNAME_N) $(GPIO_OPTIONS) $(LIMESDR_OPTIONS) $(FREEDV_OPTIONS) $(LOCALCW_OPTIONS) $(PSK_OPTIONS) $(SHORT_FRAMES) -D GIT_DATE='"$(GIT_DATE)"' -D GIT_VERSION='"$(GIT_VERSION)"' $(DEBUG_OPTION) -O3
+OPTIONS=-g -Wno-deprecated-declarations -D $(UNAME_N) $(USBOZY_OPTIONS) $(I2C_OPTIONS) $(GPIO_OPTIONS) $(LIMESDR_OPTIONS) $(FREEDV_OPTIONS) $(LOCALCW_OPTIONS) $(PSK_OPTIONS) $(SHORT_FRAMES) -D GIT_DATE='"$(GIT_DATE)"' -D GIT_VERSION='"$(GIT_VERSION)"' $(DEBUG_OPTION) -O3
 
-LIBS=-lrt -lm -lwdsp -lpthread $(AUDIO_LIBS) $(PSKLIBS) $(GTKLIBS) $(GPIO_LIBS) $(SOAPYSDRLIBS) $(FREEDVLIBS)
+LIBS=-lrt -lm -lwdsp -lpthread $(AUDIO_LIBS) $(USBOZY_LIBS) $(PSKLIBS) $(GTKLIBS) $(GPIO_LIBS) $(SOAPYSDRLIBS) $(FREEDVLIBS)
 INCLUDES=$(GTKINCLUDES)
 
 COMPILE=$(CC) $(OPTIONS) $(INCLUDES)
@@ -144,12 +153,13 @@ band.c \
 configure.c \
 frequency.c \
 discovered.c \
+discovery.c \
 filter.c \
 main.c \
 new_menu.c \
 exit_menu.c \
-general_menu.c \
-audio_menu.c \
+radio_menu.c \
+rx_menu.c \
 ant_menu.c \
 display_menu.c \
 dsp_menu.c \
@@ -166,12 +176,12 @@ mode_menu.c \
 filter_menu.c \
 noise_menu.c \
 agc_menu.c \
-fm_menu.c \
 vox_menu.c \
 diversity_menu.c \
 freqent_menu.c \
+tx_menu.c \
+vfo_menu.c \
 test_menu.c \
-rit.c \
 meter.c \
 mode.c \
 old_discovery.c \
@@ -179,21 +189,23 @@ new_discovery.c \
 old_protocol.c \
 new_protocol.c \
 new_protocol_programmer.c \
-panadapter.c \
+rx_panadapter.c \
+tx_panadapter.c \
 property.c \
 radio.c \
+receiver.c \
 rigctl.c \
-signal.c \
-splash.c \
 toolbar.c \
+transmitter.c \
 sliders.c \
 version.c \
 vfo.c \
 waterfall.c \
-wdsp_init.c \
 button_text.c \
 vox.c \
 update.c \
+store.c \
+store_menu.c \
 memory.c
 
 
@@ -207,11 +219,12 @@ frequency.h \
 bandstack.h \
 channel.h \
 discovered.h \
+discovery.h \
 filter.h \
 new_menu.h \
+rx_menu.h \
 exit_menu.h \
-general_menu.h \
-audio_menu.h \
+radio_menu.h \
 ant_menu.h \
 display_menu.h \
 dsp_menu.h \
@@ -228,33 +241,35 @@ mode_menu.h \
 filter_menu.h \
 noise_menu.h \
 agc_menu.h \
-fm_menu.h \
 vox_menu.h \
 diversity_menu.h \
 freqent_menu.h \
+tx_menu.h \
+vfo_menu.h \
 test_menu.h \
-rit.h \
 meter.h \
 mode.h \
 old_discovery.h \
 new_discovery.h \
 old_protocol.h \
 new_protocol.h \
-panadapter.h \
+rx_panadapter.h \
+tx_panadapter.h \
 property.h \
 radio.h \
+receiver.h \
 rigctl.h \
-signal.h \
-splash.h \
 toolbar.h \
+transmitter.h \
 sliders.h \
 version.h \
 vfo.h \
 waterfall.h \
-wdsp_init.h \
 button_text.h \
 vox.h \
 update.h \
+store.h \
+store_menu.h \
 memory.h
 
 
@@ -264,13 +279,14 @@ band.o \
 configure.o \
 frequency.o \
 discovered.o \
+discovery.o \
 filter.o \
 version.o \
 main.o \
 new_menu.o \
+rx_menu.o \
 exit_menu.o \
-general_menu.o \
-audio_menu.o \
+radio_menu.o \
 ant_menu.o \
 display_menu.o \
 dsp_menu.o \
@@ -287,12 +303,12 @@ mode_menu.o \
 filter_menu.o \
 noise_menu.o \
 agc_menu.o \
-fm_menu.o \
 vox_menu.o \
 diversity_menu.o \
 freqent_menu.o \
+tx_menu.o \
+vfo_menu.o \
 test_menu.o \
-rit.o \
 meter.o \
 mode.o \
 old_discovery.o \
@@ -300,29 +316,31 @@ new_discovery.o \
 old_protocol.o \
 new_protocol.o \
 new_protocol_programmer.o \
-panadapter.o \
+rx_panadapter.o \
+tx_panadapter.o \
 property.o \
 radio.o \
+receiver.o \
 rigctl.o \
-signal.o \
-splash.o \
 toolbar.o \
+transmitter.o \
 sliders.o \
 vfo.o \
 waterfall.o \
-wdsp_init.o \
 button_text.o \
 vox.o \
 update.o \
+store.o \
+store_menu.o \
 memory.o
 
-all: prebuild $(PROGRAM) $(HEADERS) $(LIMESDR_HEADERS) $(FREEDV_HEADERS) $(LOCALCW_HEADERS) $(GPIO_HEADERS) $(PSK_HEADERS) $(SOURCES) $(LIMESDR_SOURCES) $(FREEDV_SOURCES) $(GPIO_SOURCES) $(PSK_SOURCES)
+all: prebuild $(PROGRAM) $(HEADERS) $(USBOZY_HEADERS) $(LIMESDR_HEADERS) $(FREEDV_HEADERS) $(LOCALCW_HEADERS) $(I2C_HEADERS) $(GPIO_HEADERS) $(PSK_HEADERS) $(SOURCES) $(USBOZY_SOURCES) $(LIMESDR_SOURCES) $(FREEDV_SOURCES) $(I2C_SOURCES) $(GPIO_SOURCES) $(PSK_SOURCES)
 
 prebuild:
        rm -f version.o
 
-$(PROGRAM): $(OBJS) $(LIMESDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(GPIO_OBJS) $(PSK_OBJS)
-       $(LINK) -o $(PROGRAM) $(OBJS) $(GPIO_OBJS) $(LIMESDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(PSK_OBJS) $(LIBS)
+$(PROGRAM): $(OBJS) $(USBOZY_OBJS) $(LIMESDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(I2C_OBJS) $(GPIO_OBJS) $(PSK_OBJS)
+       $(LINK) -o $(PROGRAM) $(OBJS) $(USBOZY_OBJS) $(I2C_OBJS) $(GPIO_OBJS) $(LIMESDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(PSK_OBJS) $(LIBS)
 
 .c.o:
        $(COMPILE) -c -o $@ $<
index 1c88fcbf7cd907df4c33187daea43a18a53ca5fb..1f8485c646a36520bae912ab989b66f3058bdf18 100644 (file)
@@ -27,6 +27,7 @@
 #include "band.h"
 #include "channel.h"
 #include "radio.h"
+#include "receiver.h"
 #include "vfo.h"
 #include "button_text.h"
 
@@ -44,8 +45,9 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat
 }
 
 static gboolean agc_select_cb (GtkWidget *widget, gpointer        data) {
-  agc=(int)data;
-  wdsp_set_agc(CHANNEL_RX0, agc);
+  active_receiver->agc=(int)data;
+  //wdsp_set_agc(CHANNEL_RX0, agc);
+  set_agc(active_receiver, active_receiver->agc);
   vfo_update(NULL);
 }
 
@@ -80,37 +82,42 @@ void agc_menu(GtkWidget *parent) {
   g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
   gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
 
+  char label[32];
+  sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B");
+  GtkWidget *rx_label=gtk_label_new(label);
+  gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1);
+
   GtkWidget *b_off=gtk_radio_button_new_with_label(NULL,"Off");
   //gtk_widget_override_font(b_off, pango_font_description_from_string("Arial 16"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_off), agc==AGC_OFF);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_off), active_receiver->agc==AGC_OFF);
   gtk_widget_show(b_off);
   gtk_grid_attach(GTK_GRID(grid),b_off,0,1,2,1);
   g_signal_connect(b_off,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_OFF);
 
   GtkWidget *b_long=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_off),"Long");
   //gtk_widget_override_font(b_long, pango_font_description_from_string("Arial 16"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_long), agc==AGC_LONG);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_long), active_receiver->agc==AGC_LONG);
   gtk_widget_show(b_long);
   gtk_grid_attach(GTK_GRID(grid),b_long,0,2,2,1);
   g_signal_connect(b_long,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_LONG);
 
   GtkWidget *b_slow=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_long),"Slow");
   //gtk_widget_override_font(b_slow, pango_font_description_from_string("Arial 16"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_slow), agc==AGC_SLOW);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_slow), active_receiver->agc==AGC_SLOW);
   gtk_widget_show(b_slow);
   gtk_grid_attach(GTK_GRID(grid),b_slow,0,3,2,1);
   g_signal_connect(b_slow,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_SLOW);
 
   GtkWidget *b_medium=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_slow),"Medium");
   //gtk_widget_override_font(b_medium, pango_font_description_from_string("Arial 16"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_medium), agc==AGC_MEDIUM);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_medium), active_receiver->agc==AGC_MEDIUM);
   gtk_widget_show(b_medium);
   gtk_grid_attach(GTK_GRID(grid),b_medium,0,4,2,1);
   g_signal_connect(b_medium,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_MEDIUM);
 
   GtkWidget *b_fast=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_medium),"Fast");
   //gtk_widget_override_font(b_fast, pango_font_description_from_string("Arial 16"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_fast), agc==AGC_FAST);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_fast), active_receiver->agc==AGC_FAST);
   gtk_widget_show(b_fast);
   gtk_grid_attach(GTK_GRID(grid),b_fast,0,5,2,1);
   g_signal_connect(b_fast,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_FAST);
index de36b4c1f412e0999fc32bd9efaafd461bff39a4..9cef50323f84e8b843f7ef1f8aba49864797f338 100644 (file)
@@ -47,14 +47,18 @@ static void rx_ant_cb(GtkWidget *widget, gpointer data) {
   int ant=((int)data)&0xF;
   BAND *band=band_get_band(b);
   band->alexRxAntenna=ant;
-  set_alex_rx_antenna(ant);
+  if(active_receiver->id==0) {
+    set_alex_rx_antenna(ant);
+  }
 }
 
 static void rx_lime_ant_cb(GtkWidget *widget, gpointer data) {
   int ant=((int)data)&0xF;
   BAND *band=band_get_current_band();
   band->alexRxAntenna=ant;
-  set_alex_rx_antenna(ant);
+  if(active_receiver->id==0) {
+    set_alex_rx_antenna(ant);
+  }
 }
 
 static void tx_ant_cb(GtkWidget *widget, gpointer data) {
@@ -62,7 +66,9 @@ static void tx_ant_cb(GtkWidget *widget, gpointer data) {
   int ant=((int)data)&0xF;
   BAND *band=band_get_band(b);
   band->alexTxAntenna=ant;
-  set_alex_tx_antenna(ant);
+  if(active_receiver->id==0) {
+    set_alex_tx_antenna(ant);
+  }
 }
 
 void ant_menu(GtkWidget *parent) {
diff --git a/audio.c b/audio.c
index 0b3ae131c41f8c19b15c997baa03f1b440b7b7d6..d7fa469bce893335b4ad70e5d3da4b9d63dd0d1e 100644 (file)
--- a/audio.c
+++ b/audio.c
 
 #include <alsa/asoundlib.h>
 
-#include "audio.h"
 #include "new_protocol.h"
 #include "old_protocol.h"
 #include "radio.h"
+#include "receiver.h"
+#include "audio.h"
 
 int audio = 0;
 int audio_buffer_size = 256; // samples (both left and right)
 int mic_buffer_size = 720; // samples (both left and right)
 
-static snd_pcm_t *playback_handle=NULL;
+//static snd_pcm_t *playback_handle=NULL;
 static snd_pcm_t *record_handle=NULL;
 
 // each buffer contains 63 samples of left and right audio at 16 bits
@@ -49,16 +50,16 @@ static snd_pcm_t *record_handle=NULL;
 #define AUDIO_SAMPLE_SIZE 2
 #define AUDIO_CHANNELS 2
 #define AUDIO_BUFFERS 10
-#define AUDIO_BUFFER_SIZE (AUDIO_SAMPLE_SIZE*AUDIO_CHANNELS*audio_buffer_size)
+#define OUTPUT_BUFFER_SIZE (AUDIO_SAMPLE_SIZE*AUDIO_CHANNELS*audio_buffer_size)
 
 #define MIC_BUFFER_SIZE (AUDIO_SAMPLE_SIZE*AUDIO_CHANNELS*mic_buffer_size)
 
-static unsigned char *audio_buffer=NULL;
-static int audio_offset=0;
+//static unsigned char *audio_buffer=NULL;
+//static int audio_offset=0;
 
 static unsigned char *mic_buffer=NULL;
 
-static pthread_t mic_read_thread_id;
+static GThread *mic_read_thread_id;
 
 static int running=FALSE;
 
@@ -66,29 +67,29 @@ static void *mic_read_thread(void *arg);
 
 char *input_devices[16];
 int n_input_devices=0;
-int n_selected_input_device=-1;
+//int n_selected_input_device=-1;
 
 char *output_devices[16];
 int n_output_devices=0;
-int n_selected_output_device=-1;
+//int n_selected_output_device=-1;
 
-int audio_open_output() {
+int audio_open_output(RECEIVER *rx) {
   int err;
   snd_pcm_hw_params_t *hw_params;
   int rate=48000;
   int dir=0;
 
 
-  if(n_selected_output_device<0 || n_selected_output_device>=n_output_devices) {
-    n_selected_output_device=-1;
+  if(rx->audio_device<0 || rx->audio_device>=n_output_devices) {
+    rx->audio_device=-1;
     return -1;
   }
 
   int i;
-  char hw[16];
-  char *selected=output_devices[n_selected_output_device];
+  char hw[64];
+  char *selected=output_devices[rx->audio_device];
  
-fprintf(stderr,"audio_open_output: selected=%d:%s\n",n_selected_output_device,selected);
+fprintf(stderr,"audio_open_output: selected=%d:%s\n",rx->audio_device,selected);
 
   i=0;
   while(selected[i]!=' ') {
@@ -97,7 +98,7 @@ fprintf(stderr,"audio_open_output: selected=%d:%s\n",n_selected_output_device,se
   }
   hw[i]='\0';
   
-  if ((err = snd_pcm_open (&playback_handle, hw, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
+  if ((err = snd_pcm_open (&rx->playback_handle, hw, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
     fprintf (stderr, "audio_open_output: cannot open audio device %s (%s)\n", 
             hw,
             snd_strerror (err));
@@ -111,38 +112,38 @@ fprintf(stderr,"audio_open_output: selected=%d:%s\n",n_selected_output_device,se
     return -1;
   }
 
-  if ((err = snd_pcm_hw_params_any (playback_handle, hw_params)) < 0) {
+  if ((err = snd_pcm_hw_params_any (rx->playback_handle, hw_params)) < 0) {
     fprintf (stderr, "audio_open_output: cannot initialize hardware parameter structure (%s)\n",
             snd_strerror (err));
     return -1;
   }
 
-  if ((err = snd_pcm_hw_params_set_access (playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+  if ((err = snd_pcm_hw_params_set_access (rx->playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
     fprintf (stderr, "audio_open_output: cannot set access type (%s)\n",
             snd_strerror (err));
     return -1;
 }
        
-  if ((err = snd_pcm_hw_params_set_format (playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
+  if ((err = snd_pcm_hw_params_set_format (rx->playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
     fprintf (stderr, "audio_open_output: cannot set sample format (%s)\n",
             snd_strerror (err));
     return -1;
   }
        
 
-  if ((err = snd_pcm_hw_params_set_rate_near (playback_handle, hw_params, &rate, &dir)) < 0) {
+  if ((err = snd_pcm_hw_params_set_rate_near (rx->playback_handle, hw_params, &rate, &dir)) < 0) {
     fprintf (stderr, "audio_open_output: cannot set sample rate (%s)\n",
             snd_strerror (err));
     return -1;
   }
        
-  if ((err = snd_pcm_hw_params_set_channels (playback_handle, hw_params, 2)) < 0) {
+  if ((err = snd_pcm_hw_params_set_channels (rx->playback_handle, hw_params, 2)) < 0) {
     fprintf (stderr, "audio_open_output: cannot set channel count (%s)\n",
             snd_strerror (err));
     return -1;
   }
        
-  if ((err = snd_pcm_hw_params (playback_handle, hw_params)) < 0) {
+  if ((err = snd_pcm_hw_params (rx->playback_handle, hw_params)) < 0) {
     fprintf (stderr, "audio_open_output: cannot set parameters (%s)\n",
             snd_strerror (err));
     return -1;
@@ -150,8 +151,8 @@ fprintf(stderr,"audio_open_output: selected=%d:%s\n",n_selected_output_device,se
        
   snd_pcm_hw_params_free (hw_params);
 
-  audio_offset=0;
-  audio_buffer=(unsigned char *)malloc(AUDIO_BUFFER_SIZE);
+  rx->playback_offset=0;
+  rx->playback_buffer=(unsigned char *)malloc(OUTPUT_BUFFER_SIZE);
 
   return 0;
 }
@@ -162,16 +163,16 @@ int audio_open_input() {
   int rate=48000;
   int dir=0;
 
-fprintf(stderr,"audio_open_input: %d\n",n_selected_input_device);
-  if(n_selected_input_device<0 || n_selected_input_device>=n_input_devices) {
-    n_selected_input_device=-1;
+fprintf(stderr,"audio_open_input: %d\n",transmitter->input_device);
+  if(transmitter->input_device<0 || transmitter->input_device>=n_input_devices) {
+    transmitter->input_device=0;
     return -1;
   }
 
   int i;
   char hw[16];
-  char *selected=input_devices[n_selected_input_device];
-  fprintf(stderr,"audio_open_input: selected=%d:%s\n",n_selected_input_device,selected);
+  char *selected=input_devices[transmitter->input_device];
+  fprintf(stderr,"audio_open_input: selected=%d:%s\n",transmitter->input_device,selected);
   
   switch(protocol) {
     case ORIGINAL_PROTOCOL:
@@ -248,23 +249,24 @@ fprintf(stderr,"audio_open_input: %d\n",n_selected_input_device);
   mic_buffer=(unsigned char *)malloc(MIC_BUFFER_SIZE);
 
   running=TRUE;
-  err=pthread_create(&mic_read_thread_id,NULL,mic_read_thread,NULL);
-  if(err != 0) {
-    fprintf(stderr,"pthread_create failed on mic_read_thread: rc=%d\n", err);
-    return -1;
+  mic_read_thread_id = g_thread_new( "local mic", mic_read_thread, NULL);
+  if(!mic_read_thread_id )
+  {
+    fprintf(stderr,"g_thread_new failed on mic_read_thread\n");
   }
 
+
   return 0;
 }
 
-void audio_close_output() {
-  if(playback_handle!=NULL) {
-    snd_pcm_close (playback_handle);
-    playback_handle=NULL;
+void audio_close_output(RECEIVER *rx) {
+  if(rx->playback_handle!=NULL) {
+    snd_pcm_close (rx->playback_handle);
+    rx->playback_handle=NULL;
   }
-  if(audio_buffer!=NULL) {
-    free(audio_buffer);
-    audio_buffer=NULL;
+  if(rx->playback_buffer!=NULL) {
+    free(rx->playback_buffer);
+    rx->playback_buffer=NULL;
   }
 }
 
@@ -280,49 +282,49 @@ void audio_close_input() {
   }
 }
 
-int audio_write(short left_sample,short right_sample) {
+int audio_write(RECEIVER *rx,short left_sample,short right_sample) {
   snd_pcm_sframes_t delay;
   int error;
   long trim;
 
-  if(playback_handle!=NULL && audio_buffer!=NULL) {
-    audio_buffer[audio_offset++]=left_sample;
-    audio_buffer[audio_offset++]=left_sample>>8;
-    audio_buffer[audio_offset++]=right_sample;
-    audio_buffer[audio_offset++]=right_sample>>8;
+  if(rx->playback_handle!=NULL && rx->playback_buffer!=NULL) {
+    rx->playback_buffer[rx->playback_offset++]=right_sample;
+    rx->playback_buffer[rx->playback_offset++]=right_sample>>8;
+    rx->playback_buffer[rx->playback_offset++]=left_sample;
+    rx->playback_buffer[rx->playback_offset++]=left_sample>>8;
 
-    if(audio_offset==AUDIO_BUFFER_SIZE) {
+    if(rx->playback_offset==OUTPUT_BUFFER_SIZE) {
 
       trim=0;
 
-      if(snd_pcm_delay(playback_handle,&delay)==0) {
+      if(snd_pcm_delay(rx->playback_handle,&delay)==0) {
         if(delay>2048) {
           trim=delay-2048;
 //fprintf(stderr,"audio delay=%ld trim=%ld\n",delay,trim);
         }
       }
 
-      if ((error = snd_pcm_writei (playback_handle, audio_buffer, audio_buffer_size-trim)) != audio_buffer_size-trim) {
+      if ((error = snd_pcm_writei (rx->playback_handle, rx->playback_buffer, audio_buffer_size-trim)) != audio_buffer_size-trim) {
         if(error==-EPIPE) {
-          if ((error = snd_pcm_prepare (playback_handle)) < 0) {
+          if ((error = snd_pcm_prepare (rx->playback_handle)) < 0) {
             fprintf (stderr, "audio_write: cannot prepare audio interface for use (%s)\n",
                     snd_strerror (error));
             return -1;
           }
-          if ((error = snd_pcm_writei (playback_handle, audio_buffer, audio_buffer_size)) != audio_buffer_size) {
+          if ((error = snd_pcm_writei (rx->playback_handle, rx->playback_buffer, audio_buffer_size-trim)) != audio_buffer_size) {
             fprintf (stderr, "audio_write: write to audio interface failed (%s)\n",
                     snd_strerror (error));
             return -1;
           }
         }
       }
-      audio_offset=0;
+      rx->playback_offset=0;
     }
   }
   return 0;
 }
 
-static void *mic_read_thread(void *arg) {
+static gpointer mic_read_thread(gpointer arg) {
   int rc;
   if ((rc = snd_pcm_prepare (record_handle)) < 0) {
     fprintf (stderr, "mic_read_thread: cannot prepare audio interface for use (%s)\n",
@@ -359,25 +361,27 @@ fprintf(stderr,"mic_read_thread: exiting\n");
 
 }
 
-void audio_get_cards(int input) {
+void audio_get_cards() {
   snd_ctl_card_info_t *info;
   snd_pcm_info_t *pcminfo;
   snd_ctl_card_info_alloca(&info);
   snd_pcm_info_alloca(&pcminfo);
   int i;
+  char *device_id=malloc(64);
+  int card = -1;
 
-  if(input) {
-    for(i=0;i<n_input_devices;i++) {
-      free(input_devices[i]);
-    }
-    n_input_devices=0;
-  } else {
-    for(i=0;i<n_output_devices;i++) {
-      free(output_devices[i]);
-    }
-    n_output_devices=0;
+fprintf(stderr,"audio_get_cards\n");
+
+  for(i=0;i<n_input_devices;i++) {
+    free(input_devices[i]);
   }
-  int card = -1;
+  n_input_devices=0;
+
+  for(i=0;i<n_output_devices;i++) {
+    free(output_devices[i]);
+  }
+  n_output_devices=0;
+
   while (snd_card_next(&card) >= 0 && card >= 0) {
     int err = 0;
     snd_ctl_t *handle;
@@ -393,29 +397,60 @@ void audio_get_cards(int input) {
     }
 
     int dev = -1;
+
     while (snd_ctl_pcm_next_device(handle, &dev) >= 0 && dev >= 0) {
       snd_pcm_info_set_device(pcminfo, dev);
       snd_pcm_info_set_subdevice(pcminfo, 0);
-      snd_pcm_info_set_stream(pcminfo, input ? SND_PCM_STREAM_CAPTURE
-          : SND_PCM_STREAM_PLAYBACK);
-      if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
-        continue;
-      }
 
-      char *device_id=malloc(64);
-      
-      snprintf(device_id, 64, "plughw:%d,%d %s", card, dev, snd_ctl_card_info_get_name(info));
-      if(input) {
-fprintf(stderr,"input_device: %s\n",device_id);
+      // input devices
+      snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE);
+      if ((err = snd_ctl_pcm_info(handle, pcminfo)) == 0) {
+        snprintf(device_id, 64, "plughw:%d,%d %s", card, dev, snd_ctl_card_info_get_name(info));
         input_devices[n_input_devices++]=device_id;
-      } else {
+fprintf(stderr,"input_device: %s\n",device_id);
+      }
+
+      // ouput devices
+      snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK);
+      if ((err = snd_ctl_pcm_info(handle, pcminfo)) == 0) {
+        snprintf(device_id, 64, "plughw:%d,%d %s", card, dev, snd_ctl_card_info_get_name(info));
         output_devices[n_output_devices++]=device_id;
 fprintf(stderr,"output_device: %s\n",device_id);
       }
-
     }
 
     snd_ctl_close(handle);
+   
+  }
+
+  // look for dmix
+  void **hints, **n;
+  char *name, *descr, *io;
+
+  if (snd_device_name_hint(-1, "pcm", &hints) < 0)
+    return;
+  n = hints;
+  while (*n != NULL) {
+    name = snd_device_name_get_hint(*n, "NAME");
+    descr = snd_device_name_get_hint(*n, "DESC");
+    io = snd_device_name_get_hint(*n, "IOID");
+    
+    if(strncmp("dmix:", name, 5)==0/* || strncmp("pulse", name, 5)==0*/) {
+      fprintf(stderr,"name=%s descr=%s io=%s\n",name, descr, io);
+      char *device_id=malloc(64);
+      
+      snprintf(device_id, 64, "%s", name);
+      output_devices[n_output_devices++]=device_id;
+fprintf(stderr,"output_device: %s\n",device_id);
+    }
 
+    if (name != NULL)
+      free(name);
+    if (descr != NULL)
+      free(descr);
+    if (io != NULL)
+      free(io);
+    n++;
   }
+  snd_device_name_free_hint(hints);
 }
diff --git a/audio.h b/audio.h
index 57ad396cab1ea4a53fefa87700381d010df55a4a..e8a56f41ee864f75d370f1cc5ed34e320b1bcd04 100644 (file)
--- a/audio.h
+++ b/audio.h
 #ifndef _AUDIO_H
 #define _AUDIO_H
 
+#include "receiver.h"
+
 extern char *input_devices[];
 extern int n_input_devices;
-extern int n_selected_input_device;
+//extern int n_selected_input_device;
 
 extern char *output_devices[];
 extern int n_output_devices;
-extern int n_selected_output_device;
+//extern int n_selected_output_device;
 
-extern int audio_open_output();
 extern int audio_open_input();
-extern void audio_close_output();
 extern void audio_close_input();
-extern int audio_write(short left_sample,short right_sample);
+extern int audio_open_output(RECEIVER *rx);
+extern void audio_close_output(RECEIVER *rx);
+extern int audio_write(RECEIVER *rx,short left_sample,short right_sample);
 extern void audio_get_cards();
 #endif
index 2045be87a390a80bcd7d655c1712881feb04fb59..2826dcec09fef7f6db01369ce08a2294d190fc25 100644 (file)
@@ -50,7 +50,7 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat
 
 static void binaural_cb(GtkWidget *widget, gpointer data) {
   binaural=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
-  SetRXAPanelBinaural(CHANNEL_RX0, binaural);
+  SetRXAPanelBinaural(active_receiver->id, binaural);
 }
 
 static void micboost_cb(GtkWidget *widget, gpointer data) {
@@ -59,7 +59,7 @@ static void micboost_cb(GtkWidget *widget, gpointer data) {
 
 static void linein_cb(GtkWidget *widget, gpointer data) {
   mic_linein=mic_linein==1?0:1;
-  linein_changed();
+  g_idle_add(linein_changed,NULL);
 }
 
 static void local_audio_cb(GtkWidget *widget, gpointer data) {
diff --git a/band.c b/band.c
index 980d94fbdfe5aecf587d990b34c82ffba389a4ca..c3fa969d04e009d873e7cfdc4913180b63217876 100644 (file)
--- a/band.c
+++ b/band.c
@@ -39,135 +39,135 @@ int xvtr_band=BANDS;
 */
 /* ----------------------------------------------------------------------------*/
 BANDSTACK_ENTRY bandstack_entries136[] =
-    {{135800,135800,modeCWL,filterF4,-2800,-200,-2800,-200},
-     {137100,137100,modeCWL,filterF4,-2800,-200,-2800,-200}};
+    {{135800,modeCWL,filterF6,-2800,-200,-2800,-200},
+     {137100,modeCWL,filterF6,-2800,-200,-2800,-200}};
 
 BANDSTACK_ENTRY bandstack_entries472[] =
-    {{472100LL,472100LL,modeCWL,filterF4,-2800,-200,-2800,-200},
-     {475100LL,475100LL,modeCWL,filterF4,-2800,-200,-2800,-200}};
+    {{472100LL,modeCWL,filterF6,-2800,-200,-2800,-200},
+     {475100LL,modeCWL,filterF6,-2800,-200,-2800,-200}};
 
 BANDSTACK_ENTRY bandstack_entries160[] =
-    {{1810000LL,1810000LL,modeCWL,filterF4,-2800,-200,-2800,-200},
-     {1835000LL,1835000LL,modeCWU,filterF0,-2800,-200,-2800,-200},
-     {1845000LL,1845000LL,modeUSB,filterF5,-2800,-200,-2800,-200}};
+    {{1810000LL,modeCWL,filterF6,-2800,-200,-2800,-200},
+     {1835000LL,modeCWU,filterF6,-2800,-200,-2800,-200},
+     {1845000LL,modeUSB,filterF5,-2800,-200,-2800,-200}};
 
 BANDSTACK_ENTRY bandstack_entries80[] =
-    {{3501000LL,3501000LL,modeCWL,filterF0,-2800,-200,-2800,-200},
-     {3751000LL,3751000LL,modeLSB,filterF5,-2800,-200,-2800,-200},
-     {3850000LL,3850000LL,modeLSB,filterF5,-2800,-200,-2800,-200}};
+    {{3501000LL,modeCWL,filterF6,-2800,-200,-2800,-200},
+     {3751000LL,modeLSB,filterF5,-2800,-200,-2800,-200},
+     {3850000LL,modeLSB,filterF5,-2800,-200,-2800,-200}};
 
 BANDSTACK_ENTRY bandstack_entries60[] =
-    {{5330500LL,5330500LL,modeUSB,filterF5,-2800,-200,-2800,-200},
-     {5346500LL,5346500LL,modeUSB,filterF5,-2800,-200,-2800,-200},
-     {5366500LL,5366500LL,modeUSB,filterF5,-2800,-200,-2800,-200},
-     {5371500LL,5371500LL,modeUSB,filterF5,-2800,-200,-2800,-200},
-     {5403500LL,5403500LL,modeUSB,filterF5,-2800,-200,-2800,-200}};
+    {{5330500LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+     {5346500LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+     {5366500LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+     {5371500LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+     {5403500LL,modeUSB,filterF5,-2800,-200,-2800,-200}};
 
 BANDSTACK_ENTRY bandstack_entries40[] =
-    {{7001000LL,7001000LL,modeCWL,filterF0,-2800,-200,-2800,-200},
-     {7152000LL,7152000LL,modeLSB,filterF5,-2800,-200,-2800,-200},
-     {7255000LL,7255000LL,modeLSB,filterF5,-2800,-200,-2800,-200}};
+    {{7001000LL,modeCWL,filterF6,-2800,-200,-2800,-200},
+     {7152000LL,modeLSB,filterF5,-2800,-200,-2800,-200},
+     {7255000LL,modeLSB,filterF5,-2800,-200,-2800,-200}};
 
 BANDSTACK_ENTRY bandstack_entries30[] =
-    {{10120000LL,10120000LL,modeCWU,filterF0,200,2800,200,2800},
-     {10130000LL,10130000LL,modeCWU,filterF0,200,2800,200,2800},
-     {10140000LL,10140000LL,modeCWU,filterF4,200,2800,200,2800}};
+    {{10120000LL,modeCWU,filterF6,200,2800,200,2800},
+     {10130000LL,modeCWU,filterF6,200,2800,200,2800},
+     {10140000LL,modeCWU,filterF6,200,2800,200,2800}};
 
 BANDSTACK_ENTRY bandstack_entries20[] =
-    {{14010000LL,14010000LL,modeCWU,filterF0,200,2800,200,2800},
-     {14150000LL,14010000LL,modeUSB,filterF5,200,2800,200,2800},
-     {14230000LL,14010000LL,modeUSB,filterF5,200,2800,200,2800},
-     {14336000LL,14010000LL,modeUSB,filterF5,200,2800,200,2800}};
+    {{14010000LL,modeCWU,filterF6,200,2800,200,2800},
+     {14150000LL,modeUSB,filterF5,200,2800,200,2800},
+     {14230000LL,modeUSB,filterF5,200,2800,200,2800},
+     {14336000LL,modeUSB,filterF5,200,2800,200,2800}};
 
 BANDSTACK_ENTRY bandstack_entries18[] =
-    {{18068600LL,18068600LL,modeCWU,filterF0,200,2800,200,2800},
-     {18125000LL,18068600LL,modeUSB,filterF5,200,2800,200,2800},
-     {18140000LL,18068600LL,modeUSB,filterF5,200,2800,200,2800}};
+    {{18068600LL,modeCWU,filterF6,200,2800,200,2800},
+     {18125000LL,modeUSB,filterF5,200,2800,200,2800},
+     {18140000LL,modeUSB,filterF5,200,2800,200,2800}};
 
 BANDSTACK_ENTRY bandstack_entries15[] =
-    {{21001000LL,21001000LL,modeCWU,filterF0,200,2800,200,2800},
-     {21255000LL,21001000LL,modeUSB,filterF5,200,2800,200,2800},
-     {21300000LL,21001000LL,modeUSB,filterF5,200,2800,200,2800}};
+    {{21001000LL,modeCWU,filterF6,200,2800,200,2800},
+     {21255000LL,modeUSB,filterF5,200,2800,200,2800},
+     {21300000LL,modeUSB,filterF5,200,2800,200,2800}};
 
 BANDSTACK_ENTRY bandstack_entries12[] =
-    {{24895000LL,24895000LL,modeCWU,filterF0,200,2800,200,2800},
-     {24900000LL,24895000LL,modeUSB,filterF5,200,2800,200,2800},
-     {24910000LL,24895000LL,modeUSB,filterF5,200,2800,200,2800}};
+    {{24895000LL,modeCWU,filterF6,200,2800,200,2800},
+     {24900000LL,modeUSB,filterF5,200,2800,200,2800},
+     {24910000LL,modeUSB,filterF5,200,2800,200,2800}};
 
 BANDSTACK_ENTRY bandstack_entries10[] =
-    {{28010000LL,28010000LL,modeCWU,filterF0,200,2800,200,2800},
-     {28300000LL,28010000LL,modeUSB,filterF5,200,2800,200,2800},
-     {28400000LL,28010000LL,modeUSB,filterF5,200,2800,200,2800}};
+    {{28010000LL,modeCWU,filterF6,200,2800,200,2800},
+     {28300000LL,modeUSB,filterF5,200,2800,200,2800},
+     {28400000LL,modeUSB,filterF5,200,2800,200,2800}};
 
 BANDSTACK_ENTRY bandstack_entries50[] =
-    {{50010000LL,50010000LL,modeCWU,filterF0,200,2800,200,2800},
-     {50125000LL,50010000LL,modeUSB,filterF5,200,2800,200,2800},
-     {50200000LL,50010000LL,modeUSB,filterF5,200,2800,200,2800}};
+    {{50010000LL,modeCWU,filterF6,200,2800,200,2800},
+     {50125000LL,modeUSB,filterF5,200,2800,200,2800},
+     {50200000LL,modeUSB,filterF5,200,2800,200,2800}};
 
 #ifdef LIMESDR
 BANDSTACK_ENTRY bandstack_entries70[] =
-    {{70010000LL,70010000LL,modeCWU,filterF0,200,2800,200,2800},
-     {70200000LL,70010000LL,modeUSB,filterF5,200,2800,200,2800},
-     {70250000LL,70010000LL,modeUSB,filterF5,200,2800,200,2800}};
+    {{70010000LL,modeCWU,filterF6,200,2800,200,2800},
+     {70200000LL,modeUSB,filterF5,200,2800,200,2800},
+     {70250000LL,modeUSB,filterF5,200,2800,200,2800}};
 
 BANDSTACK_ENTRY bandstack_entries144[] =
-    {{144010000LL,144010000LL,modeCWU,filterF0,200,2800,200,2800},
-     {144200000LL,144010000LL,modeUSB,filterF5,200,2800,200,2800},
-     {144250000LL,144010000LL,modeUSB,filterF5,200,2800,200,2800},
-     {145600000LL,144010000LL,modeFMN,filterF1,200,2800,200,2800},
-     {145725000LL,144010000LL,modeFMN,filterF1,200,2800,200,2800},
-     {145900000LL,144010000LL,modeFMN,filterF1,200,2800,200,2800}};
+    {{144010000LL,modeCWU,filterF6,200,2800,200,2800},
+     {144200000LL,modeUSB,filterF5,200,2800,200,2800},
+     {144250000LL,modeUSB,filterF5,200,2800,200,2800},
+     {145600000LL,modeFMN,filterF1,200,2800,200,2800},
+     {145725000LL,modeFMN,filterF1,200,2800,200,2800},
+     {145900000LL,modeFMN,filterF1,200,2800,200,2800}};
 
 BANDSTACK_ENTRY bandstack_entries220[] =
-    {{220010000LL,220010000,modeCWU,filterF0,200,2800,200,2800},
-     {220200000LL,220010000,modeUSB,filterF5,200,2800,200,2800},
-     {220250000LL,220010000,modeUSB,filterF5,200,2800,200,2800}};
+    {{220010000LL,modeCWU,filterF6,200,2800,200,2800},
+     {220200000LL,modeUSB,filterF5,200,2800,200,2800},
+     {220250000LL,modeUSB,filterF5,200,2800,200,2800}};
 
 BANDSTACK_ENTRY bandstack_entries430[] =
-    {{430010000LL,430010000LL,modeCWU,filterF0,200,2800,200,2800},
-     {432100000LL,430010000LL,modeUSB,filterF5,200,2800,200,2800},
-     {432300000LL,430010000LL,modeUSB,filterF5,200,2800,200,2800}};
+    {{430010000LL,modeCWU,filterF6,200,2800,200,2800},
+     {432100000LL,modeUSB,filterF5,200,2800,200,2800},
+     {432300000LL,modeUSB,filterF5,200,2800,200,2800}};
 
 BANDSTACK_ENTRY bandstack_entries902[] =
-    {{902010000LL,902010000LL,modeCWU,filterF0,200,2800,200,2800},
-     {902100000LL,902010000LL,modeUSB,filterF5,200,2800,200,2800},
-     {902300000LL,902010000LL,modeUSB,filterF5,200,2800,200,2800}};
+    {{902010000LL,modeCWU,filterF6,200,2800,200,2800},
+     {902100000LL,modeUSB,filterF5,200,2800,200,2800},
+     {902300000LL,modeUSB,filterF5,200,2800,200,2800}};
 
 BANDSTACK_ENTRY bandstack_entries1240[] =
-    {{1240010000LL,1240010000LL,modeCWU,filterF0,200,2800,200,2800},
-     {1240100000LL,1240010000LL,modeUSB,filterF5,200,2800,200,2800},
-     {1240300000LL,1240010000LL,modeUSB,filterF5,200,2800,200,2800}};
+    {{1240010000LL,modeCWU,filterF6,200,2800,200,2800},
+     {1240100000LL,modeUSB,filterF5,200,2800,200,2800},
+     {1240300000LL,modeUSB,filterF5,200,2800,200,2800}};
 
 BANDSTACK_ENTRY bandstack_entries2300[] =
-    {{2300010000LL,2300010000LL,modeCWU,filterF0,200,2800,200,2800},
-     {2300100000LL,2300010000LL,modeUSB,filterF5,200,2800,200,2800},
-     {2300300000LL,2300010000LL,modeUSB,filterF5,200,2800,200,2800}};
+    {{2300010000LL,modeCWU,filterF6,200,2800,200,2800},
+     {2300100000LL,modeUSB,filterF5,200,2800,200,2800},
+     {2300300000LL,modeUSB,filterF5,200,2800,200,2800}};
 
 BANDSTACK_ENTRY bandstack_entries3400[] =
-    {{3400010000LL,3400010000LL,modeCWU,filterF0,200,2800,200,2800},
-     {3400100000LL,3400010000LL,modeUSB,filterF5,200,2800,200,2800},
-     {3400300000LL,3400010000LL,modeUSB,filterF5,200,2800,200,2800}};
+    {{3400010000LL,modeCWU,filterF6,200,2800,200,2800},
+     {3400100000LL,modeUSB,filterF5,200,2800,200,2800},
+     {3400300000LL,modeUSB,filterF5,200,2800,200,2800}};
 
 BANDSTACK_ENTRY bandstack_entriesAIR[] =
-    {{118800000LL,118800000LL,modeAM,filterF1,200,2800,200,2800},
-     {120000000LL,118800000LL,modeAM,filterF1,200,2800,200,2800},
-     {121700000LL,118800000LL,modeAM,filterF1,200,2800,200,2800},
-     {124100000LL,118800000LL,modeAM,filterF1,200,2800,200,2800},
-     {126600000LL,118800000LL,modeAM,filterF1,200,2800,200,2800},
-     {136500000LL,118800000LL,modeAM,filterF1,200,2800,200,2800}};
+    {{118800000LL,modeAM,filterF3,200,2800,200,2800},
+     {120000000LL,modeAM,filterF3,200,2800,200,2800},
+     {121700000LL,modeAM,filterF3,200,2800,200,2800},
+     {124100000LL,modeAM,filterF3,200,2800,200,2800},
+     {126600000LL,modeAM,filterF3,200,2800,200,2800},
+     {136500000LL,modeAM,filterF3,200,2800,200,2800}};
 #endif
 
 BANDSTACK_ENTRY bandstack_entriesGEN[] =
-    {{909000LL,909000LL,modeAM,filterF6,-6000,6000,-6000,60000},
-     {5975000LL,909000LL,modeAM,filterF6,-6000,6000,-6000,60000},
-     {13845000LL,909000LL,modeAM,filterF6,-6000,6000,-6000,60000}};
+    {{909000LL,modeAM,filterF3,-6000,6000,-6000,60000},
+     {5975000LL,modeAM,filterF3,-6000,6000,-6000,60000},
+     {13845000LL,modeAM,filterF3,-6000,6000,-6000,60000}};
 
 BANDSTACK_ENTRY bandstack_entriesWWV[] =
-    {{2500000LL,2500000LL,modeSAM,filterF6,200,2800,200,2800},
-     {5000000LL,2500000LL,modeSAM,filterF6,200,2800,200,2800},
-     {10000000LL,2500000LL,modeSAM,filterF6,200,2800,200,2800},
-     {15000000LL,2500000LL,modeSAM,filterF6,200,2800,200,2800},
-     {20000000LL,2500000LL,modeSAM,filterF6,200,2800,200,2800}};
+    {{2500000LL,modeSAM,filterF3,200,2800,200,2800},
+     {5000000LL,modeSAM,filterF3,200,2800,200,2800},
+     {10000000LL,modeSAM,filterF3,200,2800,200,2800},
+     {15000000LL,modeSAM,filterF3,200,2800,200,2800},
+     {20000000LL,modeSAM,filterF3,200,2800,200,2800}};
 
 BANDSTACK bandstack160={3,1,bandstack_entries160};
 BANDSTACK bandstack80={3,1,bandstack_entries80};
@@ -231,8 +231,8 @@ BANDSTACK bandstack_xvtr_7={1,0,bandstack_entries_xvtr_7};
 
 
 BAND bands[BANDS+XVTRS] = 
-    {{"160",&bandstack160,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,1800000LL,1800000LL,0LL,0},
-     {"80",&bandstack80,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,3500000LL,3500000LL,0LL,0},
+    {{"160",&bandstack160,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,1800000LL,2000000LL,0LL,0},
+     {"80",&bandstack80,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,3500000LL,4000000LL,0LL,0},
      {"60",&bandstack60,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,5330500LL,5403500LL,0LL,0},
      {"40",&bandstack40,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,7000000LL,7300000LL,0LL,0},
      {"30",&bandstack30,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,10100000LL,10150000LL,0LL,0},
@@ -269,6 +269,15 @@ BAND bands[BANDS+XVTRS] =
     };
 
 
+BANDSTACK *bandstack_get_bandstack(int band) {
+    return bands[band].bandstack;
+}
+
+BANDSTACK_ENTRY *bandstack_get_bandstack_entry(int band,int entry) {
+    BANDSTACK *bandstack=bands[band].bandstack;
+    return &bandstack->entry[entry];
+}
+
 BANDSTACK_ENTRY *bandstack_entry_get_current() {
     BANDSTACK *bandstack=bands[band].bandstack;
     BANDSTACK_ENTRY *entry=&bandstack->entry[bandstack->current_entry];
@@ -385,7 +394,7 @@ void bandSaveState() {
             entry=bands[b].bandstack->entry;
             entry+=stack;
 
-            sprintf(value,"%lld",entry->frequencyA);
+            sprintf(value,"%lld",entry->frequency);
             sprintf(name,"band.%d.stack.%d.a",b,stack);
             setProperty(name,value);
 
@@ -502,7 +511,7 @@ fprintf(stderr,"bandRestoreState: restore bands\n");
 
             sprintf(name,"band.%d.stack.%d.a",b,stack);
             value=getProperty(name);
-            if(value) entry->frequencyA=atoll(value);
+            if(value) entry->frequency=atoll(value);
 
             sprintf(name,"band.%d.stack.%d.mode",b,stack);
             value=getProperty(name);
diff --git a/band.h b/band.h
index 5f99de71a2c4d52a0c895a446f790b2e9916d25c..36532946560449839a128ec011ef9ff96f9280d2 100644 (file)
--- a/band.h
+++ b/band.h
@@ -83,14 +83,17 @@ typedef struct _BAND BAND;
 int band;
 gboolean displayHF;
 
-int band_get_current();
-BAND *band_get_current_band();
-BAND *band_get_band(int b);
-BAND *band_set_current(int b);
-int get_band_from_frequency(long long f);
+extern int band_get_current();
+extern BAND *band_get_current_band();
+extern BAND *band_get_band(int b);
+extern BAND *band_set_current(int b);
+extern int get_band_from_frequency(long long f);
 
-BANDSTACK_ENTRY *bandstack_entry_next();
-BANDSTACK_ENTRY *bandstack_entry_previous();
-BANDSTACK_ENTRY *bandstack_entry_get_current();
+extern BANDSTACK *bandstack_get_bandstack(int band);
+extern BANDSTACK_ENTRY *bandstack_get_bandstack_entry(int band,int entry);
+
+extern BANDSTACK_ENTRY *bandstack_entry_next();
+extern BANDSTACK_ENTRY *bandstack_entry_previous();
+extern BANDSTACK_ENTRY *bandstack_entry_get_current();
 
 #endif
index b4d8c2d74c747fc2949e1de294d3c3027c532572..d55ceff8ae5f5a2599e6012d78ccdfe4800b44a5 100644 (file)
@@ -27,6 +27,7 @@
 #include "bandstack.h"
 #include "filter.h"
 #include "radio.h"
+#include "receiver.h"
 #include "vfo.h"
 #include "button_text.h"
 
@@ -48,33 +49,16 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat
 static gboolean band_select_cb (GtkWidget *widget, gpointer        data) {
   GtkWidget *label;
   int b=(int)data;
-  BANDSTACK_ENTRY *entry;
-  if(b==band_get_current()) {
-    entry=bandstack_entry_next();
-  } else {
-    BAND* band=band_set_current(b);
-    entry=bandstack_entry_get_current();
-    set_button_text_color(last_band,"black");
-    last_band=widget;
-    set_button_text_color(last_band,"orange");
-  }
-  setMode(entry->mode);
-  FILTER* band_filters=filters[entry->mode];
-  FILTER* band_filter=&band_filters[entry->filter];
-  setFilter(band_filter->low,band_filter->high);
-  setFrequency(entry->frequencyA);
-
-  BAND *band=band_get_current_band();
-  set_alex_rx_antenna(band->alexRxAntenna);
-  set_alex_tx_antenna(band->alexTxAntenna);
-  set_alex_attenuation(band->alexAttenuation);
-
-  vfo_update(NULL);
+  set_button_text_color(last_band,"black");
+  last_band=widget;
+  set_button_text_color(last_band,"orange");
 
-  setFrequency(entry->frequencyA);
+  vfo_band_changed(b);
+}
 
-  calcDriveLevel();
-  calcTuneDriveLevel();
+int band_update(void *data) {
+  band_select_cb(NULL,(gpointer)data);
+  return 0;
 }
 
 void band_menu(GtkWidget *parent) {
@@ -108,6 +92,11 @@ void band_menu(GtkWidget *parent) {
   g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
   gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
 
+  char label[32];
+  sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B");
+  GtkWidget *rx_label=gtk_label_new(label);
+  gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1);
+
   for(i=0;i<BANDS+XVTRS;i++) {
 #ifdef LIMESDR
     if(protocol!=LIMESDR_PROTOCOL) {
@@ -121,7 +110,8 @@ void band_menu(GtkWidget *parent) {
     if(strlen(band->title)>0) {
       GtkWidget *b=gtk_button_new_with_label(band->title);
       set_button_text_color(b,"black");
-      if(i==band_get_current()) {
+      //if(i==band_get_current()) {
+      if(i==vfo[active_receiver->id].band) {
         set_button_text_color(b,"orange");
         last_band=b;
       }
index f7b5a14f0b392fd7f84eb6ce49b20d8304cc8237..f77fc1a421985f50de9dfe946df6c44369dd5ed8 100644 (file)
@@ -18,3 +18,4 @@
 */
 
 void band_menu(GtkWidget *parent);
+int band_update(void *data);
index 9e8b30e5911961710e0457323dfadeedc9ff5952..2950b6c1c2c7fc271a51e4d5b5b52b5fe92fc94f 100644 (file)
@@ -25,8 +25,7 @@
 * @brief Bandstack definition
 */
 struct _BANDSTACK_ENTRY {
-    long long frequencyA;
-    long long frequencyB;
+    long long frequency;
     int mode;
     int filter;
     int var1Low;
index 4dc5f3c2b950fbbb089e78aaa25fc01e9611c8f8..001ea453c47f8124e9d305ee29df251b11c8bd84 100644 (file)
@@ -27,6 +27,7 @@
 #include "bandstack.h"
 #include "filter.h"
 #include "radio.h"
+#include "receiver.h"
 #include "vfo.h"
 #include "button_text.h"
 
@@ -47,31 +48,10 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat
 
 static gboolean bandstack_select_cb (GtkWidget *widget, gpointer        data) {
   int b=(int)data;
-  BAND *band=band_get_current_band();
-  BANDSTACK *bandstack=band->bandstack;
-
-  bandstack->current_entry=b;
-
   set_button_text_color(last_bandstack,"black");
   last_bandstack=widget;
   set_button_text_color(last_bandstack,"orange");
-
-  BANDSTACK_ENTRY *entry;
-  entry=&(bandstack->entry[b]);
-
-  setMode(entry->mode);
-  FILTER* band_filters=filters[entry->mode];
-  FILTER* band_filter=&band_filters[entry->filter];
-  setFilter(band_filter->low,band_filter->high);
-  setFrequency(entry->frequencyA);
-
-  set_alex_rx_antenna(band->alexRxAntenna);
-  set_alex_tx_antenna(band->alexTxAntenna);
-  set_alex_attenuation(band->alexAttenuation);
-
-  vfo_update(NULL);
-
-  setFrequency(entry->frequencyA);
+  vfo_bandstack_changed(b);
 }
 
 void bandstack_menu(GtkWidget *parent) {
@@ -104,18 +84,21 @@ void bandstack_menu(GtkWidget *parent) {
   g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
   gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
 
-  char label[16];
+  char label[32];
+  sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B");
+  GtkWidget *rx_label=gtk_label_new(label);
+  gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1);
 
-  BAND *band=band_get_current_band();
+  BAND *band=band_get_band(vfo[active_receiver->id].band);
   BANDSTACK *bandstack=band->bandstack;
 
   for(i=0;i<bandstack->entries;i++) {
     BANDSTACK_ENTRY *entry=&bandstack->entry[i];
-    sprintf(label,"%lld %s",entry->frequencyA,mode_string[entry->mode]);
+    sprintf(label,"%lld %s",entry->frequency,mode_string[entry->mode]);
     GtkWidget *b=gtk_button_new_with_label(label);
     set_button_text_color(b,"black");
     //gtk_widget_override_font(b, pango_font_description_from_string("Arial 20"));
-    if(i==bandstack->current_entry) {
+    if(i==vfo[active_receiver->id].bandstack) {
       set_button_text_color(b,"orange");
       last_bandstack=b;
     }
index c882cd4dc503b8390587dea985b0a2d324c8c304..688d7ea6d0f6eceb6b00da4713383dea2c66e48f 100644 (file)
 #include "main.h"
 #include "channel.h"
 #include "discovered.h"
-#include "radio.h"
+//#include "radio.h"
 #include "gpio.h"
 
+
 #ifdef GPIO
+
+static GtkWidget *dialog;
+
+static GtkWidget *b_enable_vfo_encoder;
+static   GtkWidget *vfo_a_label;
+static   GtkWidget *vfo_a;
+static   GtkWidget *vfo_b_label;
+static   GtkWidget *vfo_b;
+static   GtkWidget *b_enable_vfo_pullup;
+static GtkWidget *b_enable_E1_encoder;
+static   GtkWidget *E1_a_label;
+static   GtkWidget *E1_a;
+static   GtkWidget *E1_b_label;
+static   GtkWidget *E1_b;
+static   GtkWidget *b_enable_E1_pullup;
+static GtkWidget *b_enable_E2_encoder;
+static   GtkWidget *E2_a_label;
+static   GtkWidget *E2_a;
+static   GtkWidget *E2_b_label;
+static   GtkWidget *E2_b;
+static   GtkWidget *b_enable_E2_pullup;
+static GtkWidget *b_enable_E3_encoder;
+static   GtkWidget *E3_a_label;
+static   GtkWidget *E3_a;
+static   GtkWidget *E3_b_label;
+static   GtkWidget *E3_b;
+static   GtkWidget *b_enable_E3_pullup;
+static GtkWidget *b_enable_mox;
+static   GtkWidget *mox_label;
+static   GtkWidget *mox;
+
+static GtkWidget *b_enable_S1;
+static   GtkWidget *S1_label;
+static   GtkWidget *S1;
+
+static GtkWidget *b_enable_S2;
+static   GtkWidget *S2_label;
+static   GtkWidget *S2;
+
+static GtkWidget *b_enable_S3;
+static   GtkWidget *S3_label;
+static   GtkWidget *S3;
+
+static GtkWidget *b_enable_S4;
+static   GtkWidget *S4_label;
+static   GtkWidget *S4;
+
+static GtkWidget *b_enable_S5;
+static   GtkWidget *S5_label;
+static   GtkWidget *S5;
+
+static GtkWidget *b_enable_S6;
+static   GtkWidget *S6_label;
+static   GtkWidget *S6;
+
+static GtkWidget *b_enable_function;
+static   GtkWidget *function_label;
+static   GtkWidget *function;
+
+#ifdef LOCALCW
+static GtkWidget *cwl_label;
+static GtkWidget *cwl_gpio_label;
+static GtkWidget *cwl;
+static GtkWidget *cwr_label;
+static GtkWidget *cwr_gpio_label;
+static GtkWidget *cwr;
+#endif
+
+static gboolean save_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  if(dialog!=NULL) {
+    ENABLE_VFO_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_vfo_encoder))?1:0;
+    VFO_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(vfo_a));
+    VFO_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(vfo_b));
+    ENABLE_VFO_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_vfo_pullup))?1:0;
+
+    ENABLE_E1_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E1_encoder))?1:0;
+    E1_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E1_a));
+    E1_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E1_b));
+    ENABLE_E1_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E1_pullup))?1:0;
+
+    ENABLE_E2_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E2_encoder))?1:0;
+    E2_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E2_a));
+    E2_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E2_b));
+    ENABLE_E2_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E2_pullup))?1:0;
+
+    ENABLE_E3_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E3_encoder))?1:0;
+    E3_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E3_a));
+    E3_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E3_b));
+    ENABLE_E3_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E3_pullup))?1:0;
+
+    ENABLE_MOX_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_mox))?1:0;
+    MOX_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(mox));
+
+    ENABLE_S1_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S1))?1:0;
+    S1_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S1));
+
+    ENABLE_S2_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S2))?1:0;
+    S2_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S2));
+
+    ENABLE_S3_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S3))?1:0;
+    S3_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S3));
+
+    ENABLE_S4_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S4))?1:0;
+    S4_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S4));
+
+    ENABLE_S5_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S5))?1:0;
+    S5_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S5));
+
+    ENABLE_S6_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S6))?1:0;
+    S6_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S6));
+
+    ENABLE_FUNCTION_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_function))?1:0;
+    FUNCTION_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(function));
+#ifdef LOCALCW
+    CWL_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(cwl));
+    CWR_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(cwr));
+#endif
+
+    gpio_save_state();
+    gtk_widget_destroy(dialog);
+  }
+  return TRUE;
+}
+
+static gboolean cancel_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  if(dialog!=NULL) {
+    gtk_widget_destroy(dialog);
+  }
+  return TRUE;
+}
+
 void configure_gpio(GtkWidget *parent) {
   gpio_restore_state();
 
-  GtkWidget *dialog=gtk_dialog_new_with_buttons("Configure GPIO",GTK_WINDOW(parent),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+  dialog=gtk_dialog_new_with_buttons("Configure GPIO",GTK_WINDOW(parent),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
   GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
   GtkWidget *grid=gtk_grid_new();
   //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
   gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
 
+  int y=0;
 
-  GtkWidget *b_enable_vfo_encoder=gtk_check_button_new_with_label("Enable VFO");
+  b_enable_vfo_encoder=gtk_check_button_new_with_label("Enable VFO");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_vfo_encoder), ENABLE_VFO_ENCODER);
   gtk_widget_show(b_enable_vfo_encoder);
-  gtk_grid_attach(GTK_GRID(grid),b_enable_vfo_encoder,0,0,1,1);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_vfo_encoder,0,y,1,1);
 
-  GtkWidget *vfo_a_label=gtk_label_new("GPIO A:");
+  vfo_a_label=gtk_label_new("GPIO A:");
   gtk_widget_show(vfo_a_label);
-  gtk_grid_attach(GTK_GRID(grid),vfo_a_label,1,0,1,1);
+  gtk_grid_attach(GTK_GRID(grid),vfo_a_label,1,y,1,1);
 
-  GtkWidget *vfo_a=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  vfo_a=gtk_spin_button_new_with_range (0.0,100.0,1.0);
   gtk_spin_button_set_value (GTK_SPIN_BUTTON(vfo_a),VFO_ENCODER_A);
   gtk_widget_show(vfo_a);
-  gtk_grid_attach(GTK_GRID(grid),vfo_a,2,0,1,1);
+  gtk_grid_attach(GTK_GRID(grid),vfo_a,2,y,1,1);
 
-  GtkWidget *vfo_b_label=gtk_label_new("GPIO B:");
+  vfo_b_label=gtk_label_new("GPIO B:");
   gtk_widget_show(vfo_b_label);
-  gtk_grid_attach(GTK_GRID(grid),vfo_b_label,3,0,1,1);
+  gtk_grid_attach(GTK_GRID(grid),vfo_b_label,3,y,1,1);
 
-  GtkWidget *vfo_b=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  vfo_b=gtk_spin_button_new_with_range (0.0,100.0,1.0);
   gtk_spin_button_set_value (GTK_SPIN_BUTTON(vfo_b),VFO_ENCODER_B);
   gtk_widget_show(vfo_b);
-  gtk_grid_attach(GTK_GRID(grid),vfo_b,4,0,1,1);
+  gtk_grid_attach(GTK_GRID(grid),vfo_b,4,y,1,1);
 
-  GtkWidget *b_enable_vfo_pullup=gtk_check_button_new_with_label("Enable Pull-up");
+  b_enable_vfo_pullup=gtk_check_button_new_with_label("Enable Pull-up");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_vfo_pullup), ENABLE_VFO_PULLUP);
   gtk_widget_show(b_enable_vfo_pullup);
-  gtk_grid_attach(GTK_GRID(grid),b_enable_vfo_pullup,5,0,1,1);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_vfo_pullup,5,y,1,1);
 
 
+  y++;
 
-  GtkWidget *b_enable_af_encoder=gtk_check_button_new_with_label("Enable E1");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_af_encoder), ENABLE_E1_ENCODER);
-  gtk_widget_show(b_enable_af_encoder);
-  gtk_grid_attach(GTK_GRID(grid),b_enable_af_encoder,0,1,1,1);
+  b_enable_E1_encoder=gtk_check_button_new_with_label("Enable E1");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_E1_encoder), ENABLE_E1_ENCODER);
+  gtk_widget_show(b_enable_E1_encoder);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_E1_encoder,0,y,1,1);
 
-  GtkWidget *af_a_label=gtk_label_new("GPIO A:");
-  gtk_widget_show(af_a_label);
-  gtk_grid_attach(GTK_GRID(grid),af_a_label,1,1,1,1);
+  E1_a_label=gtk_label_new("GPIO A:");
+  gtk_widget_show(E1_a_label);
+  gtk_grid_attach(GTK_GRID(grid),E1_a_label,1,y,1,1);
 
-  GtkWidget *af_a=gtk_spin_button_new_with_range (0.0,100.0,1.0);
-  gtk_spin_button_set_value (GTK_SPIN_BUTTON(af_a),E1_ENCODER_A);
-  gtk_widget_show(af_a);
-  gtk_grid_attach(GTK_GRID(grid),af_a,2,1,1,1);
+  E1_a=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(E1_a),E1_ENCODER_A);
+  gtk_widget_show(E1_a);
+  gtk_grid_attach(GTK_GRID(grid),E1_a,2,y,1,1);
 
-  GtkWidget *af_b_label=gtk_label_new("GPIO B:");
-  gtk_widget_show(af_b_label);
-  gtk_grid_attach(GTK_GRID(grid),af_b_label,3,1,1,1);
+  E1_b_label=gtk_label_new("GPIO B:");
+  gtk_widget_show(E1_b_label);
+  gtk_grid_attach(GTK_GRID(grid),E1_b_label,3,y,1,1);
 
-  GtkWidget *af_b=gtk_spin_button_new_with_range (0.0,100.0,1.0);
-  gtk_spin_button_set_value (GTK_SPIN_BUTTON(af_b),E1_ENCODER_B);
-  gtk_widget_show(af_b);
-  gtk_grid_attach(GTK_GRID(grid),af_b,4,1,1,1);
+  E1_b=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(E1_b),E1_ENCODER_B);
+  gtk_widget_show(E1_b);
+  gtk_grid_attach(GTK_GRID(grid),E1_b,4,y,1,1);
 
-  GtkWidget *b_enable_af_pullup=gtk_check_button_new_with_label("Enable Pull-up");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_af_pullup), ENABLE_E1_PULLUP);
-  gtk_widget_show(b_enable_af_pullup);
-  gtk_grid_attach(GTK_GRID(grid),b_enable_af_pullup,5,1,1,1);
+  b_enable_E1_pullup=gtk_check_button_new_with_label("Enable Pull-up");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_E1_pullup), ENABLE_E1_PULLUP);
+  gtk_widget_show(b_enable_E1_pullup);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_E1_pullup,5,y,1,1);
 
 
+  y++;
 
-  GtkWidget *b_enable_rf_encoder=gtk_check_button_new_with_label("Enable RF");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_rf_encoder), ENABLE_E2_ENCODER);
-  gtk_widget_show(b_enable_rf_encoder);
-  gtk_grid_attach(GTK_GRID(grid),b_enable_rf_encoder,0,2,1,1);
+  b_enable_E2_encoder=gtk_check_button_new_with_label("Enable E2");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_E2_encoder), ENABLE_E2_ENCODER);
+  gtk_widget_show(b_enable_E2_encoder);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_E2_encoder,0,y,1,1);
 
-  GtkWidget *rf_a_label=gtk_label_new("GPIO A:");
-  gtk_widget_show(rf_a_label);
-  gtk_grid_attach(GTK_GRID(grid),rf_a_label,1,2,1,1);
+  E2_a_label=gtk_label_new("GPIO A:");
+  gtk_widget_show(E2_a_label);
+  gtk_grid_attach(GTK_GRID(grid),E2_a_label,1,y,1,1);
 
-  GtkWidget *rf_a=gtk_spin_button_new_with_range (0.0,100.0,1.0);
-  gtk_spin_button_set_value (GTK_SPIN_BUTTON(rf_a),E2_ENCODER_A);
-  gtk_widget_show(rf_a);
-  gtk_grid_attach(GTK_GRID(grid),rf_a,2,2,1,1);
+  E2_a=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(E2_a),E2_ENCODER_A);
+  gtk_widget_show(E2_a);
+  gtk_grid_attach(GTK_GRID(grid),E2_a,2,y,1,1);
 
-  GtkWidget *rf_b_label=gtk_label_new("GPIO B:");
-  gtk_widget_show(rf_b_label);
-  gtk_grid_attach(GTK_GRID(grid),rf_b_label,3,2,1,1);
+  E2_b_label=gtk_label_new("GPIO B:");
+  gtk_widget_show(E2_b_label);
+  gtk_grid_attach(GTK_GRID(grid),E2_b_label,3,y,1,1);
 
-  GtkWidget *rf_b=gtk_spin_button_new_with_range (0.0,100.0,1.0);
-  gtk_spin_button_set_value (GTK_SPIN_BUTTON(rf_b),E2_ENCODER_B);
-  gtk_widget_show(rf_b);
-  gtk_grid_attach(GTK_GRID(grid),rf_b,4,2,1,1);
+  E2_b=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(E2_b),E2_ENCODER_B);
+  gtk_widget_show(E2_b);
+  gtk_grid_attach(GTK_GRID(grid),E2_b,4,y,1,1);
 
-  GtkWidget *b_enable_rf_pullup=gtk_check_button_new_with_label("Enable Pull-up");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_rf_pullup), ENABLE_E2_PULLUP);
-  gtk_widget_show(b_enable_rf_pullup);
-  gtk_grid_attach(GTK_GRID(grid),b_enable_rf_pullup,5,2,1,1);
+  b_enable_E2_pullup=gtk_check_button_new_with_label("Enable Pull-up");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_E2_pullup), ENABLE_E2_PULLUP);
+  gtk_widget_show(b_enable_E2_pullup);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_E2_pullup,5,y,1,1);
 
 
+  y++;
 
-  GtkWidget *b_enable_agc_encoder=gtk_check_button_new_with_label("Enable AGC");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_agc_encoder), ENABLE_E3_ENCODER);
-  gtk_widget_show(b_enable_agc_encoder);
-  gtk_grid_attach(GTK_GRID(grid),b_enable_agc_encoder,0,3,1,1);
+  b_enable_E3_encoder=gtk_check_button_new_with_label("Enable E3");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_E3_encoder), ENABLE_E3_ENCODER);
+  gtk_widget_show(b_enable_E3_encoder);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_E3_encoder,0,y,1,1);
 
-  GtkWidget *agc_a_label=gtk_label_new("GPIO A:");
-  gtk_widget_show(agc_a_label);
-  gtk_grid_attach(GTK_GRID(grid),agc_a_label,1,3,1,1);
+  E3_a_label=gtk_label_new("GPIO A:");
+  gtk_widget_show(E3_a_label);
+  gtk_grid_attach(GTK_GRID(grid),E3_a_label,1,y,1,1);
 
-  GtkWidget *agc_a=gtk_spin_button_new_with_range (0.0,100.0,1.0);
-  gtk_spin_button_set_value (GTK_SPIN_BUTTON(agc_a),E3_ENCODER_A);
-  gtk_widget_show(agc_a);
-  gtk_grid_attach(GTK_GRID(grid),agc_a,2,3,1,1);
+  E3_a=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(E3_a),E3_ENCODER_A);
+  gtk_widget_show(E3_a);
+  gtk_grid_attach(GTK_GRID(grid),E3_a,2,y,1,1);
 
-  GtkWidget *agc_b_label=gtk_label_new("GPIO B:");
-  gtk_widget_show(agc_b_label);
-  gtk_grid_attach(GTK_GRID(grid),agc_b_label,3,3,1,1);
+  E3_b_label=gtk_label_new("GPIO B:");
+  gtk_widget_show(E3_b_label);
+  gtk_grid_attach(GTK_GRID(grid),E3_b_label,3,y,1,1);
 
-  GtkWidget *agc_b=gtk_spin_button_new_with_range (0.0,100.0,1.0);
-  gtk_spin_button_set_value (GTK_SPIN_BUTTON(agc_b),E3_ENCODER_B);
-  gtk_widget_show(agc_b);
-  gtk_grid_attach(GTK_GRID(grid),agc_b,4,3,1,1);
+  E3_b=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(E3_b),E3_ENCODER_B);
+  gtk_widget_show(E3_b);
+  gtk_grid_attach(GTK_GRID(grid),E3_b,4,y,1,1);
 
-  GtkWidget *b_enable_agc_pullup=gtk_check_button_new_with_label("Enable Pull-up");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_agc_pullup), ENABLE_E3_PULLUP);
-  gtk_widget_show(b_enable_agc_pullup);
-  gtk_grid_attach(GTK_GRID(grid),b_enable_agc_pullup,5,3,1,1);
+  b_enable_E3_pullup=gtk_check_button_new_with_label("Enable Pull-up");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_E3_pullup), ENABLE_E3_PULLUP);
+  gtk_widget_show(b_enable_E3_pullup);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_E3_pullup,5,y,1,1);
 
 
+  y++;
 
-  GtkWidget *b_enable_band=gtk_check_button_new_with_label("Enable Band");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_band), ENABLE_S1_BUTTON);
-  gtk_widget_show(b_enable_band);
-  gtk_grid_attach(GTK_GRID(grid),b_enable_band,0,4,1,1);
+  b_enable_mox=gtk_check_button_new_with_label("Enable MOX/TUN");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_mox), ENABLE_MOX_BUTTON);
+  gtk_widget_show(b_enable_mox);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_mox,0,y,1,1);
 
-  GtkWidget *band_label=gtk_label_new("GPIO:");
-  gtk_widget_show(band_label);
-  gtk_grid_attach(GTK_GRID(grid),band_label,1,4,1,1);
+  mox_label=gtk_label_new("GPIO:");
+  gtk_widget_show(mox_label);
+  gtk_grid_attach(GTK_GRID(grid),mox_label,1,y,1,1);
 
-  GtkWidget *band=gtk_spin_button_new_with_range (0.0,100.0,1.0);
-  gtk_spin_button_set_value (GTK_SPIN_BUTTON(band),S1_BUTTON);
-  gtk_widget_show(band);
-  gtk_grid_attach(GTK_GRID(grid),band,2,4,1,1);
+  mox=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(mox),MOX_BUTTON);
+  gtk_widget_show(mox);
+  gtk_grid_attach(GTK_GRID(grid),mox,2,y,1,1);
 
+  y++;
 
-  GtkWidget *b_enable_mode=gtk_check_button_new_with_label("Enable Mode");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_mode), ENABLE_S3_BUTTON);
-  gtk_widget_show(b_enable_mode);
-  gtk_grid_attach(GTK_GRID(grid),b_enable_mode,0,5,1,1);
+  b_enable_S1=gtk_check_button_new_with_label("Enable S1");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_S1), ENABLE_S1_BUTTON);
+  gtk_widget_show(b_enable_S1);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_S1,0,y,1,1);
 
-  GtkWidget *mode_label=gtk_label_new("GPIO:");
-  gtk_widget_show(mode_label);
-  gtk_grid_attach(GTK_GRID(grid),mode_label,1,5,1,1);
+  S1_label=gtk_label_new("GPIO:");
+  gtk_widget_show(S1_label);
+  gtk_grid_attach(GTK_GRID(grid),S1_label,1,y,1,1);
 
-  GtkWidget *mode=gtk_spin_button_new_with_range (0.0,100.0,1.0);
-  gtk_spin_button_set_value (GTK_SPIN_BUTTON(mode),S3_BUTTON);
-  gtk_widget_show(mode);
-  gtk_grid_attach(GTK_GRID(grid),mode,2,5,1,1);
+  S1=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(S1),S1_BUTTON);
+  gtk_widget_show(S1);
+  gtk_grid_attach(GTK_GRID(grid),S1,2,y,1,1);
 
 
-  GtkWidget *b_enable_filter=gtk_check_button_new_with_label("Enable Filter");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_filter), ENABLE_S4_BUTTON);
-  gtk_widget_show(b_enable_filter);
-  gtk_grid_attach(GTK_GRID(grid),b_enable_filter,0,6,1,1);
+  y++;
 
-  GtkWidget *filter_label=gtk_label_new("GPIO:");
-  gtk_widget_show(filter_label);
-  gtk_grid_attach(GTK_GRID(grid),filter_label,1,6,1,1);
+  b_enable_S2=gtk_check_button_new_with_label("Enable S2");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_S2), ENABLE_S2_BUTTON);
+  gtk_widget_show(b_enable_S2);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_S2,0,y,1,1);
 
-  GtkWidget *filter=gtk_spin_button_new_with_range (0.0,100.0,1.0);
-  gtk_spin_button_set_value (GTK_SPIN_BUTTON(filter),S4_BUTTON);
-  gtk_widget_show(filter);
-  gtk_grid_attach(GTK_GRID(grid),filter,2,6,1,1);
+  S2_label=gtk_label_new("GPIO:");
+  gtk_widget_show(S2_label);
+  gtk_grid_attach(GTK_GRID(grid),S2_label,1,y,1,1);
 
+  S2=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(S2),S2_BUTTON);
+  gtk_widget_show(S2);
+  gtk_grid_attach(GTK_GRID(grid),S2,2,y,1,1);
 
-  GtkWidget *b_enable_noise=gtk_check_button_new_with_label("Enable Noise");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_noise), ENABLE_S5_BUTTON);
-  gtk_widget_show(b_enable_noise);
-  gtk_grid_attach(GTK_GRID(grid),b_enable_noise,0,7,1,1);
+  y++;
 
-  GtkWidget *noise_label=gtk_label_new("GPIO:");
-  gtk_widget_show(noise_label);
-  gtk_grid_attach(GTK_GRID(grid),noise_label,1,7,1,1);
+  b_enable_S3=gtk_check_button_new_with_label("Enable S3");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_S3), ENABLE_S3_BUTTON);
+  gtk_widget_show(b_enable_S3);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_S3,0,y,1,1);
 
-  GtkWidget *noise=gtk_spin_button_new_with_range (0.0,100.0,1.0);
-  gtk_spin_button_set_value (GTK_SPIN_BUTTON(noise),S5_BUTTON);
-  gtk_widget_show(noise);
-  gtk_grid_attach(GTK_GRID(grid),noise,2,7,1,1);
+  S3_label=gtk_label_new("GPIO:");
+  gtk_widget_show(S3_label);
+  gtk_grid_attach(GTK_GRID(grid),S3_label,1,y,1,1);
 
+  S3=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(S3),S3_BUTTON);
+  gtk_widget_show(S3);
+  gtk_grid_attach(GTK_GRID(grid),S3,2,y,1,1);
 
-  GtkWidget *b_enable_agc=gtk_check_button_new_with_label("Enable AGC");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_agc), ENABLE_S6_BUTTON);
-  gtk_widget_show(b_enable_agc);
-  gtk_grid_attach(GTK_GRID(grid),b_enable_agc,0,8,1,1);
+  y++;
 
-  GtkWidget *agc_label=gtk_label_new("GPIO:");
-  gtk_widget_show(agc_label);
-  gtk_grid_attach(GTK_GRID(grid),agc_label,1,8,1,1);
+  b_enable_S4=gtk_check_button_new_with_label("Enable S4");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_S4), ENABLE_S4_BUTTON);
+  gtk_widget_show(b_enable_S4);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_S4,0,y,1,1);
 
-  GtkWidget *agc=gtk_spin_button_new_with_range (0.0,100.0,1.0);
-  gtk_spin_button_set_value (GTK_SPIN_BUTTON(agc),S6_BUTTON);
-  gtk_widget_show(agc);
-  gtk_grid_attach(GTK_GRID(grid),agc,2,8,1,1);
+  S4_label=gtk_label_new("GPIO:");
+  gtk_widget_show(S4_label);
+  gtk_grid_attach(GTK_GRID(grid),S4_label,1,y,1,1);
 
+  S4=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(S4),S4_BUTTON);
+  gtk_widget_show(S4);
+  gtk_grid_attach(GTK_GRID(grid),S4,2,y,1,1);
 
-  GtkWidget *b_enable_mox=gtk_check_button_new_with_label("Enable MOX");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_mox), ENABLE_MOX_BUTTON);
-  gtk_widget_show(b_enable_mox);
-  gtk_grid_attach(GTK_GRID(grid),b_enable_mox,0,9,1,1);
+  y++;
 
-  GtkWidget *mox_label=gtk_label_new("GPIO:");
-  gtk_widget_show(mox_label);
-  gtk_grid_attach(GTK_GRID(grid),mox_label,1,9,1,1);
+  b_enable_S5=gtk_check_button_new_with_label("Enable S5");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_S5), ENABLE_S5_BUTTON);
+  gtk_widget_show(b_enable_S5);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_S5,0,y,1,1);
 
-  GtkWidget *mox=gtk_spin_button_new_with_range (0.0,100.0,1.0);
-  gtk_spin_button_set_value (GTK_SPIN_BUTTON(mox),MOX_BUTTON);
-  gtk_widget_show(mox);
-  gtk_grid_attach(GTK_GRID(grid),mox,2,9,1,1);
+  S5_label=gtk_label_new("GPIO:");
+  gtk_widget_show(S5_label);
+  gtk_grid_attach(GTK_GRID(grid),S5_label,1,y,1,1);
+
+  S5=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(S5),S5_BUTTON);
+  gtk_widget_show(S5);
+  gtk_grid_attach(GTK_GRID(grid),S5,2,y,1,1);
+
+  y++;
 
+  b_enable_S6=gtk_check_button_new_with_label("Enable S6");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_S6), ENABLE_S6_BUTTON);
+  gtk_widget_show(b_enable_S6);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_S6,0,y,1,1);
 
-  GtkWidget *b_enable_function=gtk_check_button_new_with_label("Enable Function");
+  S6_label=gtk_label_new("GPIO:");
+  gtk_widget_show(S6_label);
+  gtk_grid_attach(GTK_GRID(grid),S6_label,1,y,1,1);
+
+  S6=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(S6),S6_BUTTON);
+  gtk_widget_show(S6);
+  gtk_grid_attach(GTK_GRID(grid),S6,2,y,1,1);
+
+  y++;
+
+  b_enable_function=gtk_check_button_new_with_label("Enable Function");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_function), ENABLE_FUNCTION_BUTTON);
   gtk_widget_show(b_enable_function);
-  gtk_grid_attach(GTK_GRID(grid),b_enable_function,0,10,1,1);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_function,0,y,1,1);
 
-  GtkWidget *function_label=gtk_label_new("GPIO:");
+  function_label=gtk_label_new("GPIO:");
   gtk_widget_show(function_label);
-  gtk_grid_attach(GTK_GRID(grid),function_label,1,10,1,1);
+  gtk_grid_attach(GTK_GRID(grid),function_label,1,y,1,1);
 
-  GtkWidget *function=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  function=gtk_spin_button_new_with_range (0.0,100.0,1.0);
   gtk_spin_button_set_value (GTK_SPIN_BUTTON(function),FUNCTION_BUTTON);
   gtk_widget_show(function);
-  gtk_grid_attach(GTK_GRID(grid),function,2,10,1,1);
+  gtk_grid_attach(GTK_GRID(grid),function,2,y,1,1);
+
+  y++;
 
 #ifdef LOCALCW
-  GtkWidget *cwl_label=gtk_label_new("CWL");
+  cwl_label=gtk_label_new("CWL");
   gtk_widget_show(cwl_label);
-  gtk_grid_attach(GTK_GRID(grid),cwl_label,0,11,1,1);
+  gtk_grid_attach(GTK_GRID(grid),cwl_label,0,y,1,1);
 
-  GtkWidget *cwl_gpio_label=gtk_label_new("GPIO:");
+  cwl_gpio_label=gtk_label_new("GPIO:");
   gtk_widget_show(cwl_gpio_label);
-  gtk_grid_attach(GTK_GRID(grid),cwl_gpio_label,1,11,1,1);
+  gtk_grid_attach(GTK_GRID(grid),cwl_gpio_label,1,y,1,1);
 
-  GtkWidget *cwl=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  cwl=gtk_spin_button_new_with_range (0.0,100.0,1.0);
   gtk_spin_button_set_value (GTK_SPIN_BUTTON(cwl),CWL_BUTTON);
   gtk_widget_show(cwl);
-  gtk_grid_attach(GTK_GRID(grid),cwl,2,11,1,1);
+  gtk_grid_attach(GTK_GRID(grid),cwl,2,y,1,1);
+
+  y++;
 
-  GtkWidget *cwr_label=gtk_label_new("CWR");
+  cwr_label=gtk_label_new("CWR");
   gtk_widget_show(cwr_label);
-  gtk_grid_attach(GTK_GRID(grid),cwr_label,0,12,1,1);
+  gtk_grid_attach(GTK_GRID(grid),cwr_label,0,y,1,1);
 
-  GtkWidget *cwr_gpio_label=gtk_label_new("GPIO:");
+  cwr_gpio_label=gtk_label_new("GPIO:");
   gtk_widget_show(cwr_gpio_label);
-  gtk_grid_attach(GTK_GRID(grid),cwr_gpio_label,1,12,1,1);
+  gtk_grid_attach(GTK_GRID(grid),cwr_gpio_label,1,y,1,1);
 
-  GtkWidget *cwr=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  cwr=gtk_spin_button_new_with_range (0.0,100.0,1.0);
   gtk_spin_button_set_value (GTK_SPIN_BUTTON(cwr),CWR_BUTTON);
   gtk_widget_show(cwr);
-  gtk_grid_attach(GTK_GRID(grid),cwr,2,12,1,1);
-#endif
+  gtk_grid_attach(GTK_GRID(grid),cwr,2,y,1,1);
 
+  y++;
+#endif
+  
+  GtkWidget *save_b=gtk_button_new_with_label("Save");
+  g_signal_connect (save_b, "button_press_event", G_CALLBACK(save_cb), NULL);
+  gtk_grid_attach(GTK_GRID(grid),save_b,4,y-1,1,1);
 
-  gtk_container_add(GTK_CONTAINER(content),grid);
+  GtkWidget *cancel_b=gtk_button_new_with_label("Cancel");
+  g_signal_connect (cancel_b, "button_press_event", G_CALLBACK(cancel_cb), NULL);
+  gtk_grid_attach(GTK_GRID(grid),cancel_b,5,y-1,1,1);
 
   gtk_container_add(GTK_CONTAINER(content),grid);
 
-  GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
+/*
+  GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Save",GTK_RESPONSE_OK);
   //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 20"));
+*/
   gtk_widget_show_all(dialog);
-
   int result=gtk_dialog_run(GTK_DIALOG(dialog));
 
+/*
   ENABLE_VFO_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_vfo_encoder))?1:0;
   VFO_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(vfo_a));
   VFO_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(vfo_b));
   ENABLE_VFO_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_vfo_pullup))?1:0;
-  ENABLE_E1_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_af_encoder))?1:0;
-  E1_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(af_a));
-  E1_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(af_b));
-  ENABLE_E1_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_af_pullup))?1:0;
-  ENABLE_E2_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_rf_encoder))?1:0;
-  E2_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(rf_a));
-  E2_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(rf_b));
-  ENABLE_E2_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_rf_pullup))?1:0;
-  ENABLE_E3_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_agc_encoder))?1:0;
-  E3_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(agc_a));
-  E3_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(agc_b));
-  ENABLE_E3_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_agc_pullup))?1:0;
-  ENABLE_S1_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_band))?1:0;
-  S1_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(band));
-  ENABLE_S2_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_band))?1:0;
-  S2_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(band));
-  ENABLE_S3_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_mode))?1:0;
-  S3_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(mode));
-  ENABLE_S4_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_filter))?1:0;
-  S4_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(filter));
-  ENABLE_S5_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_noise))?1:0;
-  S5_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(noise));
-  ENABLE_S6_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_agc))?1:0;
-  S6_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(agc));
+  ENABLE_E1_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E1_encoder))?1:0;
+  E1_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E1_a));
+  E1_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E1_b));
+  ENABLE_E1_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E1_pullup))?1:0;
+  ENABLE_E2_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E2_encoder))?1:0;
+  E2_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E2_a));
+  E2_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E2_b));
+  ENABLE_E2_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E2_pullup))?1:0;
+  ENABLE_E3_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S6_encoder))?1:0;
+  E3_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S6_a));
+  E3_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S6_b));
+  ENABLE_E3_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S6_pullup))?1:0;
+  ENABLE_S1_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S1))?1:0;
+  S1_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S1));
+  ENABLE_S2_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S2))?1:0;
+  S2_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S2));
+  ENABLE_S3_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S3))?1:0;
+  S3_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S3));
+  ENABLE_S4_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S4))?1:0;
+  S4_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S4));
+  ENABLE_S5_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S5))?1:0;
+  S5_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S5));
+  ENABLE_S6_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S6))?1:0;
+  S6_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S6));
   ENABLE_MOX_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_mox))?1:0;
   MOX_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(mox));
   ENABLE_FUNCTION_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_function))?1:0;
@@ -343,10 +516,12 @@ void configure_gpio(GtkWidget *parent) {
   CWL_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(cwl));
   CWR_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(cwr));
 #endif
+*/
 
   gtk_widget_destroy(dialog);
 
-  gpio_save_state();
+//  gpio_save_state();
+
 }
 #endif
 
index b1e263c4debd542dbbc5557c84e690cf11a18c07..176d1ec509823f2d2a8c8d5997b47791d12c4b77 100644 (file)
--- a/cw_menu.c
+++ b/cw_menu.c
@@ -28,6 +28,7 @@
 #include "bandstack.h"
 #include "filter.h"
 #include "radio.h"
+#include "receiver.h"
 
 static GtkWidget *parent_window=NULL;
 
@@ -91,12 +92,15 @@ static void cw_keyer_sidetone_level_value_changed_cb(GtkWidget *widget, gpointer
 
 static void cw_keyer_sidetone_frequency_value_changed_cb(GtkWidget *widget, gpointer data) {
   cw_keyer_sidetone_frequency=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
-  if(mode==modeCWL || mode==modeCWU) {
+/*
+  if(transmitter->mode==modeCWL || transmitter->mode==modeCWU) {
     BANDSTACK_ENTRY *entry=bandstack_entry_get_current();
     FILTER* band_filters=filters[entry->mode];
     FILTER* band_filter=&band_filters[entry->filter];
-    setFilter(band_filter->low,band_filter->high);
+    //setFilter(band_filter->low,band_filter->high);
+    set_filter(active_receiver,band_filter->low,band_filter->high);
   }
+*/
   cw_changed();
 }
 
index 28b41e0eb0cce507016af72132ca43c3c5b24a7a..d4f6322c182264cc6a217c8c7b2c372f99efc099 100644 (file)
 
 #define MAX_DEVICES 16
 
+
 #define DEVICE_METIS 0
 #define DEVICE_HERMES 1
 #define DEVICE_GRIFFIN 2
 #define DEVICE_ANGELIA 4
 #define DEVICE_ORION 5
 #define DEVICE_HERMES_LITE 6
+// 8000DLE uses 10 as the device type in old protocol
+#define DEVICE_ORION2 10 
+
+#ifdef USBOZY
+#define DEVICE_OZY 7
+#endif
 
 #define NEW_DEVICE_ATLAS 0
 #define NEW_DEVICE_HERMES 1
diff --git a/discovery.c b/discovery.c
new file mode 100644 (file)
index 0000000..3fc509d
--- /dev/null
@@ -0,0 +1,263 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <math.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <semaphore.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "discovered.h"
+#include "discovery.h"
+#include "main.h"
+#include "radio.h"
+#ifdef USBOZY
+#include "ozyio.h"
+#endif
+
+static GtkWidget *discovery_dialog;
+static DISCOVERED *d;
+
+int discovery(void *data);
+
+static gboolean start_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+fprintf(stderr,"start_cb: %p\n",data);
+  radio=(DISCOVERED *)data;
+  gtk_widget_destroy(discovery_dialog);
+  start_radio();
+  return TRUE;
+}
+
+#ifdef GPIO
+static gboolean gpio_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  configure_gpio(discovery_dialog);
+  return TRUE;
+}
+#endif
+
+static gboolean discover_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  gtk_widget_destroy(discovery_dialog);
+  g_idle_add(discovery,NULL);
+  return TRUE;
+}
+
+static gboolean exit_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  gtk_widget_destroy(discovery_dialog);
+  _exit(0);
+  return TRUE;
+}
+
+int discovery(void *data) {
+fprintf(stderr,"discovery\n");
+  selected_device=0;
+  devices=0;
+
+#ifdef USBOZY
+//
+// first: look on USB for an Ozy
+//
+  fprintf(stderr,"looking for USB based OZY devices\n");
+
+  if (ozy_discover() != 0)
+  {
+    discovered[devices].protocol = ORIGINAL_PROTOCOL;
+    discovered[devices].device = DEVICE_OZY;
+    discovered[devices].software_version = 10;              // we can't know yet so this isn't a real response
+    discovered[devices].status = STATE_AVAILABLE;
+    strcpy(discovered[devices].name,"Ozy on USB");
+
+    strcpy(discovered[devices].info.network.interface_name,"USB");
+    devices++;
+  }
+#endif
+
+
+  status_text("Old Protocol ... Discovering Devices");
+  old_discovery();
+
+  status_text("New Protocol ... Discovering Devices");
+  new_discovery();
+
+#ifdef LIMESDR
+  status_text("LimeSDR ... Discovering Devices");
+  lime_discovery();
+#endif
+
+
+  if(devices==0) {
+    gdk_window_set_cursor(gtk_widget_get_window(top_window),gdk_cursor_new(GDK_ARROW));
+    discovery_dialog = gtk_dialog_new();
+    gtk_window_set_transient_for(GTK_WINDOW(discovery_dialog),GTK_WINDOW(top_window));
+    gtk_window_set_decorated(GTK_WINDOW(discovery_dialog),FALSE);
+
+    gtk_widget_override_font(discovery_dialog, pango_font_description_from_string("FreeMono 16"));
+
+    GdkRGBA color;
+    color.red = 1.0;
+    color.green = 1.0;
+    color.blue = 1.0;
+    color.alpha = 1.0;
+    gtk_widget_override_background_color(discovery_dialog,GTK_STATE_FLAG_NORMAL,&color);
+
+    GtkWidget *content;
+
+    content=gtk_dialog_get_content_area(GTK_DIALOG(discovery_dialog));
+
+    GtkWidget *grid=gtk_grid_new();
+    gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
+    gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+    gtk_grid_set_row_spacing (GTK_GRID(grid),10);
+
+    GtkWidget *label=gtk_label_new("No devices found!");
+    gtk_grid_attach(GTK_GRID(grid),label,0,0,2,1);
+
+    GtkWidget *exit_b=gtk_button_new_with_label("Exit");
+    g_signal_connect (exit_b, "button-press-event", G_CALLBACK(exit_cb), NULL);
+    gtk_grid_attach(GTK_GRID(grid),exit_b,0,1,1,1);
+
+    GtkWidget *discover_b=gtk_button_new_with_label("Retry Discovery");
+    g_signal_connect (discover_b, "button-press-event", G_CALLBACK(discover_cb), NULL);
+    gtk_grid_attach(GTK_GRID(grid),discover_b,1,1,1,1);
+
+    gtk_container_add (GTK_CONTAINER (content), grid);
+    gtk_widget_show_all(discovery_dialog);
+  } else {
+    fprintf(stderr,"discovery: found %d devices\n", devices);
+    gdk_window_set_cursor(gtk_widget_get_window(top_window),gdk_cursor_new(GDK_ARROW));
+    discovery_dialog = gtk_dialog_new();
+    gtk_window_set_transient_for(GTK_WINDOW(discovery_dialog),GTK_WINDOW(top_window));
+    gtk_window_set_decorated(GTK_WINDOW(discovery_dialog),FALSE);
+
+    gtk_widget_override_font(discovery_dialog, pango_font_description_from_string("FreeMono 16"));
+
+    GdkRGBA color;
+    color.red = 1.0;
+    color.green = 1.0;
+    color.blue = 1.0;
+    color.alpha = 1.0;
+    gtk_widget_override_background_color(discovery_dialog,GTK_STATE_FLAG_NORMAL,&color);
+
+    GtkWidget *content;
+
+    content=gtk_dialog_get_content_area(GTK_DIALOG(discovery_dialog));
+
+    GtkWidget *grid=gtk_grid_new();
+    gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
+    gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+    gtk_grid_set_row_spacing (GTK_GRID(grid),10);
+
+    int i;
+    char version[16];
+    char text[128];
+    for(i=0;i<devices;i++) {
+      d=&discovered[i];
+fprintf(stderr,"%p protocol=%d name=%s\n",d,d->protocol,d->name);
+      if(d->protocol==ORIGINAL_PROTOCOL) {
+        sprintf(version,"%d.%d",
+                        d->software_version/10,
+                        d->software_version%10);
+      } else {
+        sprintf(version,"%d.%d",
+                        d->software_version/10,
+                        d->software_version%10);
+      }
+      switch(d->protocol) {
+        case ORIGINAL_PROTOCOL:
+        case NEW_PROTOCOL:
+#ifdef USBOZY
+          if(d->device==DEVICE_OZY) {
+            sprintf(text,"%s (%s) on USB /dev/ozy\n", d->name, d->protocol==ORIGINAL_PROTOCOL?"old":"new");
+          } else {
+#endif
+            sprintf(text,"%s (%s %s) %s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n",
+                          d->name,
+                          d->protocol==ORIGINAL_PROTOCOL?"old":"new",
+                          version,
+                          inet_ntoa(d->info.network.address.sin_addr),
+                          d->info.network.mac_address[0],
+                          d->info.network.mac_address[1],
+                          d->info.network.mac_address[2],
+                          d->info.network.mac_address[3],
+                          d->info.network.mac_address[4],
+                          d->info.network.mac_address[5],
+                          d->info.network.interface_name);
+#ifdef USBOZY
+          }
+#endif
+          break;
+#ifdef LIMESDR
+        case LIMESDR_PROTOCOL:
+          sprintf(text,"%s\n",
+                        d->name);
+          break;
+#endif
+      }
+
+      GtkWidget *label=gtk_label_new(text);
+      gtk_widget_override_font(label, pango_font_description_from_string("FreeMono 12"));
+      gtk_widget_show(label);
+      gtk_grid_attach(GTK_GRID(grid),label,0,i,3,1);
+
+      GtkWidget *start_button=gtk_button_new_with_label("Start");
+      gtk_widget_override_font(start_button, pango_font_description_from_string("FreeMono 18"));
+      gtk_widget_show(start_button);
+      gtk_grid_attach(GTK_GRID(grid),start_button,3,i,1,1);
+      g_signal_connect(start_button,"button_press_event",G_CALLBACK(start_cb),(gpointer)d);
+
+      // if not available then cannot start it
+      if(d->status!=STATE_AVAILABLE) {
+        gtk_button_set_label(GTK_BUTTON(start_button),"In Use");
+        gtk_widget_set_sensitive(start_button, FALSE);
+      }
+
+      // if not on the same subnet then cannot start it
+      if((d->info.network.interface_address.sin_addr.s_addr&d->info.network.interface_netmask.sin_addr.s_addr) != (d->info.network.address.sin_addr.s_addr&d->info.network.interface_netmask.sin_addr.s_addr)) {
+        gtk_button_set_label(GTK_BUTTON(start_button),"Subnet!");
+        gtk_widget_set_sensitive(start_button, FALSE);
+      }
+
+    }
+#ifdef GPIO
+    GtkWidget *gpio_b=gtk_button_new_with_label("Config GPIO");
+    g_signal_connect (gpio_b, "button-press-event", G_CALLBACK(gpio_cb), NULL);
+    gtk_grid_attach(GTK_GRID(grid),gpio_b,0,i,1,1);
+#endif
+    GtkWidget *discover_b=gtk_button_new_with_label("Discover");
+    g_signal_connect (discover_b, "button-press-event", G_CALLBACK(discover_cb), NULL);
+    gtk_grid_attach(GTK_GRID(grid),discover_b,1,i,1,1);
+
+    GtkWidget *exit_b=gtk_button_new_with_label("Exit");
+    g_signal_connect (exit_b, "button-press-event", G_CALLBACK(exit_cb), NULL);
+    gtk_grid_attach(GTK_GRID(grid),exit_b,2,i,1,1);
+
+    gtk_container_add (GTK_CONTAINER (content), grid);
+    gtk_widget_show_all(discovery_dialog);
+fprintf(stderr,"showing device dialog\n");
+  }
+
+  return 0;
+
+}
+
+
diff --git a/discovery.h b/discovery.h
new file mode 100644 (file)
index 0000000..74600f0
--- /dev/null
@@ -0,0 +1,20 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+int discovery(void *data);
index 1030325d669487c4ce5bc3be9daef5859f52bd79..027e0e49572de2046a3c8c4ee7f0550853c52bfd 100644 (file)
@@ -45,19 +45,17 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat
 
 static void detector_mode_cb(GtkWidget *widget, gpointer data) {
   display_detector_mode=(int)data;
-  SetDisplayDetectorMode(CHANNEL_RX0, 0, display_detector_mode);
+  SetDisplayDetectorMode(active_receiver->id, 0, display_detector_mode);
 }
 
 static void average_mode_cb(GtkWidget *widget, gpointer data) {
   display_average_mode=(int)data;
-  SetDisplayAverageMode(CHANNEL_RX0, 0, display_average_mode);
+  SetDisplayAverageMode(active_receiver->id, 0, display_average_mode);
 }
 
 static void time_value_changed_cb(GtkWidget *widget, gpointer data) {
   display_average_time=gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget));
-  calculate_display_average();
-  //SetDisplayAvBackmult(CHANNEL_RX0, 0, display_avb);
-  //SetDisplayNumAverage(CHANNEL_RX0, 0, display_average);
+  calculate_display_average(active_receiver);
 }
 
 static void filled_cb(GtkWidget *widget, gpointer data) {
@@ -66,54 +64,50 @@ static void filled_cb(GtkWidget *widget, gpointer data) {
 
 static void frames_per_second_value_changed_cb(GtkWidget *widget, gpointer data) {
   updates_per_second=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
-  calculate_display_average();
+  calculate_display_average(active_receiver);
 }
 
 static void panadapter_high_value_changed_cb(GtkWidget *widget, gpointer data) {
-  panadapter_high=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
+  active_receiver->panadapter_high=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
 }
 
 static void panadapter_low_value_changed_cb(GtkWidget *widget, gpointer data) {
-  panadapter_low=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
+  active_receiver->panadapter_low=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
 }
 
 static void waterfall_high_value_changed_cb(GtkWidget *widget, gpointer data) {
-  waterfall_high=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
+  active_receiver->waterfall_high=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
 }
 
 static void waterfall_low_value_changed_cb(GtkWidget *widget, gpointer data) {
-  waterfall_low=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
+  active_receiver->waterfall_low=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
 }
 
 static void waterfall_automatic_cb(GtkWidget *widget, gpointer data) {
-  waterfall_automatic=waterfall_automatic==1?0:1;
+  active_receiver->waterfall_automatic=active_receiver->waterfall_automatic==1?0:1;
 }
 
 static void display_panadapter_cb(GtkWidget *widget, gpointer data) {
-  display_panadapter=display_panadapter==1?0:1;
-  reconfigure_display();
+  active_receiver->display_panadapter=active_receiver->display_panadapter==1?0:1;
+  reconfigure_radio();
 }
 
 static void display_waterfall_cb(GtkWidget *widget, gpointer data) {
-  display_waterfall=display_waterfall==1?0:1;
-  reconfigure_display();
+  active_receiver->display_waterfall=active_receiver->display_waterfall==1?0:1;
+  reconfigure_radio();
 }
 
 static void display_sliders_cb(GtkWidget *widget, gpointer data) {
   display_sliders=display_sliders==1?0:1;
-  reconfigure_display();
+  reconfigure_radio();
 }
 
+/*
 static void display_toolbar_cb(GtkWidget *widget, gpointer data) {
   display_toolbar=display_toolbar==1?0:1;
-  reconfigure_display();
+  reconfigure_radio();
 }
-
-static void toolbar_dialog_buttons_cb(GtkWidget *widget, gpointer data) {
-  toolbar_dialog_buttons=toolbar_dialog_buttons==1?0:1;
-  update_toolbar_labels();
-}
-
+*/
 void display_menu(GtkWidget *parent) {
   int i;
 
@@ -169,7 +163,7 @@ void display_menu(GtkWidget *parent) {
 
   GtkWidget *panadapter_high_r=gtk_spin_button_new_with_range(-220.0,100.0,1.0);
   //gtk_widget_override_font(panadapter_high_r, pango_font_description_from_string("Arial 18"));
-  gtk_spin_button_set_value(GTK_SPIN_BUTTON(panadapter_high_r),(double)panadapter_high);
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON(panadapter_high_r),(double)active_receiver->panadapter_high);
   gtk_widget_show(panadapter_high_r);
   gtk_grid_attach(GTK_GRID(grid),panadapter_high_r,1,3,1,1);
   g_signal_connect(panadapter_high_r,"value_changed",G_CALLBACK(panadapter_high_value_changed_cb),NULL);
@@ -181,7 +175,7 @@ void display_menu(GtkWidget *parent) {
 
   GtkWidget *panadapter_low_r=gtk_spin_button_new_with_range(-220.0,100.0,1.0);
   //gtk_widget_override_font(panadapter_low_r, pango_font_description_from_string("Arial 18"));
-  gtk_spin_button_set_value(GTK_SPIN_BUTTON(panadapter_low_r),(double)panadapter_low);
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON(panadapter_low_r),(double)active_receiver->panadapter_low);
   gtk_widget_show(panadapter_low_r);
   gtk_grid_attach(GTK_GRID(grid),panadapter_low_r,1,4,1,1);
   g_signal_connect(panadapter_low_r,"value_changed",G_CALLBACK(panadapter_low_value_changed_cb),NULL);
@@ -193,7 +187,7 @@ void display_menu(GtkWidget *parent) {
 
   GtkWidget *waterfall_automatic_b=gtk_check_button_new();
   //gtk_widget_override_font(waterfall_automatic_b, pango_font_description_from_string("Arial 18"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (waterfall_automatic_b), waterfall_automatic);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (waterfall_automatic_b), active_receiver->waterfall_automatic);
   gtk_widget_show(waterfall_automatic_b);
   gtk_grid_attach(GTK_GRID(grid),waterfall_automatic_b,1,5,1,1);
   g_signal_connect(waterfall_automatic_b,"toggled",G_CALLBACK(waterfall_automatic_cb),NULL);
@@ -205,7 +199,7 @@ void display_menu(GtkWidget *parent) {
 
   GtkWidget *waterfall_high_r=gtk_spin_button_new_with_range(-220.0,100.0,1.0);
   //gtk_widget_override_font(waterfall_high_r, pango_font_description_from_string("Arial 18"));
-  gtk_spin_button_set_value(GTK_SPIN_BUTTON(waterfall_high_r),(double)waterfall_high);
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON(waterfall_high_r),(double)active_receiver->waterfall_high);
   gtk_widget_show(waterfall_high_r);
   gtk_grid_attach(GTK_GRID(grid),waterfall_high_r,1,6,1,1);
   g_signal_connect(waterfall_high_r,"value_changed",G_CALLBACK(waterfall_high_value_changed_cb),NULL);
@@ -217,7 +211,7 @@ void display_menu(GtkWidget *parent) {
 
   GtkWidget *waterfall_low_r=gtk_spin_button_new_with_range(-220.0,100.0,1.0);
   //gtk_widget_override_font(waterfall_low_r, pango_font_description_from_string("Arial 18"));
-  gtk_spin_button_set_value(GTK_SPIN_BUTTON(waterfall_low_r),(double)waterfall_low);
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON(waterfall_low_r),(double)active_receiver->waterfall_low);
   gtk_widget_show(waterfall_low_r);
   gtk_grid_attach(GTK_GRID(grid),waterfall_low_r,1,7,1,1);
   g_signal_connect(waterfall_low_r,"value_changed",G_CALLBACK(waterfall_low_value_changed_cb),NULL);
@@ -294,16 +288,18 @@ void display_menu(GtkWidget *parent) {
   gtk_grid_attach(GTK_GRID(grid),time_r,4,6,1,1);
   g_signal_connect(time_r,"value_changed",G_CALLBACK(time_value_changed_cb),NULL);
 
+/*
   GtkWidget *b_display_panadapter=gtk_check_button_new_with_label("Display Panadapter");
   //gtk_widget_override_font(b_display_panadapter, pango_font_description_from_string("Arial 18"));
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_display_panadapter), display_panadapter);
   gtk_widget_show(b_display_panadapter);
   gtk_grid_attach(GTK_GRID(grid),b_display_panadapter,0,8,1,1);
   g_signal_connect(b_display_panadapter,"toggled",G_CALLBACK(display_panadapter_cb),(gpointer *)NULL);
+*/
 
   GtkWidget *b_display_waterfall=gtk_check_button_new_with_label("Display Waterfall");
   //gtk_widget_override_font(b_display_waterfall, pango_font_description_from_string("Arial 18"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_display_waterfall), display_waterfall);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_display_waterfall), active_receiver->display_waterfall);
   gtk_widget_show(b_display_waterfall);
   gtk_grid_attach(GTK_GRID(grid),b_display_waterfall,1,8,1,1);
   g_signal_connect(b_display_waterfall,"toggled",G_CALLBACK(display_waterfall_cb),(gpointer *)NULL);
@@ -315,20 +311,14 @@ void display_menu(GtkWidget *parent) {
   gtk_grid_attach(GTK_GRID(grid),b_display_sliders,2,8,1,1);
   g_signal_connect(b_display_sliders,"toggled",G_CALLBACK(display_sliders_cb),(gpointer *)NULL);
 
+/*
   GtkWidget *b_display_toolbar=gtk_check_button_new_with_label("Display Toolbar");
   //gtk_widget_override_font(b_display_toolbar, pango_font_description_from_string("Arial 18"));
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_display_toolbar), display_toolbar);
   gtk_widget_show(b_display_toolbar);
   gtk_grid_attach(GTK_GRID(grid),b_display_toolbar,3,8,1,1);
   g_signal_connect(b_display_toolbar,"toggled",G_CALLBACK(display_toolbar_cb),(gpointer *)NULL);
-
-  GtkWidget *b_toolbar_dialog_buttons=gtk_check_button_new_with_label("Buttons Display Dialog");
-  //gtk_widget_override_font(b_toolbar_dialog_buttons, pango_font_description_from_string("Arial 18"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_toolbar_dialog_buttons), toolbar_dialog_buttons);
-  gtk_widget_show(b_toolbar_dialog_buttons);
-  gtk_grid_attach(GTK_GRID(grid),b_toolbar_dialog_buttons,0,9,1,1);
-  g_signal_connect(b_toolbar_dialog_buttons,"toggled",G_CALLBACK(toolbar_dialog_buttons_cb),(gpointer *)NULL);
-
+*/
   gtk_container_add(GTK_CONTAINER(content),grid);
 
   sub_menu=dialog;
index 1878d793096a869f6c9adf3a02e071db1a457c35..690a90e4fb086bbd85e3facaf3fb25d7ea5dc839 100644 (file)
@@ -27,6 +27,7 @@
 #include "agc.h"
 #include "channel.h"
 #include "radio.h"
+#include "receiver.h"
 #include "wdsp.h"
 
 static GtkWidget *parent_window=NULL;
@@ -45,35 +46,35 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat
 }
 
 static void agc_hang_threshold_value_changed_cb(GtkWidget *widget, gpointer data) {
-  agc_hang_threshold=(int)gtk_range_get_value(GTK_RANGE(widget));
-  if(agc==AGC_LONG || agc==AGC_SLOW) {
-    SetRXAAGCHangThreshold(CHANNEL_RX0, (int)agc_hang_threshold);
+  active_receiver->agc_hang_threshold=(int)gtk_range_get_value(GTK_RANGE(widget));
+  if(active_receiver->agc==AGC_LONG || active_receiver->agc==AGC_SLOW) {
+    SetRXAAGCHangThreshold(active_receiver->id, (int)active_receiver->agc_hang_threshold);
   }
 }
 
 static void pre_post_agc_cb(GtkWidget *widget, gpointer data) {
-  nr_agc=(int)data;
-  SetRXAEMNRPosition(CHANNEL_RX0, nr_agc);
+  active_receiver->nr_agc=(int)data;
+  SetRXAEMNRPosition(active_receiver->id, active_receiver->nr_agc);
 
 }
 
 static void nr2_gain_cb(GtkWidget *widget, gpointer data) {
-  nr2_gain_method==(int)data;
-  SetRXAEMNRgainMethod(CHANNEL_RX0, nr2_gain_method);
+  active_receiver->nr2_gain_method==(int)data;
+  SetRXAEMNRgainMethod(active_receiver->id, active_receiver->nr2_gain_method);
 }
 
 static void nr2_npe_method_cb(GtkWidget *widget, gpointer data) {
-  nr2_npe_method=(int)data;
-  SetRXAEMNRnpeMethod(CHANNEL_RX0, nr2_npe_method);
+  active_receiver->nr2_npe_method=(int)data;
+  SetRXAEMNRnpeMethod(active_receiver->id, active_receiver->nr2_npe_method);
 }
 
 static void ae_cb(GtkWidget *widget, gpointer data) {
   if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
-    nr2_ae=1;
+    active_receiver->nr2_ae=1;
   } else {
-    nr2_ae=0;
+    active_receiver->nr2_ae=0;
   }
-  SetRXAEMNRaeRun(CHANNEL_RX0, nr2_ae);
+  SetRXAEMNRaeRun(active_receiver->id, active_receiver->nr2_ae);
 }
 
 void dsp_menu(GtkWidget *parent) {
@@ -108,7 +109,7 @@ void dsp_menu(GtkWidget *parent) {
   gtk_widget_show(agc_hang_threshold_label);
   gtk_grid_attach(GTK_GRID(grid),agc_hang_threshold_label,0,1,1,1);
   GtkWidget *agc_hang_threshold_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0.0, 100.0, 1.0);
-  gtk_range_set_value (GTK_RANGE(agc_hang_threshold_scale),agc_hang_threshold);
+  gtk_range_set_value (GTK_RANGE(agc_hang_threshold_scale),active_receiver->agc_hang_threshold);
   gtk_widget_show(agc_hang_threshold_scale);
   gtk_grid_attach(GTK_GRID(grid),agc_hang_threshold_scale,1,1,2,1);
   g_signal_connect(G_OBJECT(agc_hang_threshold_scale),"value_changed",G_CALLBACK(agc_hang_threshold_value_changed_cb),NULL);
@@ -119,13 +120,13 @@ void dsp_menu(GtkWidget *parent) {
   gtk_grid_attach(GTK_GRID(grid),pre_post_agc_label,0,2,1,1);
 
   GtkWidget *pre_agc_b=gtk_radio_button_new_with_label(NULL,"Pre AGC");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pre_agc_b),nr_agc==0);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pre_agc_b),active_receiver->nr_agc==0);
   gtk_widget_show(pre_agc_b);
   gtk_grid_attach(GTK_GRID(grid),pre_agc_b,1,2,1,1);
   g_signal_connect(pre_agc_b,"pressed",G_CALLBACK(pre_post_agc_cb),(gpointer *)0);
 
   GtkWidget *post_agc_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(pre_agc_b),"Post AGC");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (post_agc_b), nr_agc==1);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (post_agc_b), active_receiver->nr_agc==1);
   gtk_widget_show(post_agc_b);
   gtk_grid_attach(GTK_GRID(grid),post_agc_b,2,2,1,1);
   g_signal_connect(post_agc_b,"pressed",G_CALLBACK(pre_post_agc_cb),(gpointer *)1);
@@ -136,19 +137,19 @@ void dsp_menu(GtkWidget *parent) {
   gtk_grid_attach(GTK_GRID(grid),nr2_gain_label,0,3,1,1);
 
   GtkWidget *linear_b=gtk_radio_button_new_with_label(NULL,"Linear");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (linear_b),nr2_gain_method==0);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (linear_b),active_receiver->nr2_gain_method==0);
   gtk_widget_show(linear_b);
   gtk_grid_attach(GTK_GRID(grid),linear_b,1,3,1,1);
   g_signal_connect(linear_b,"pressed",G_CALLBACK(nr2_gain_cb),(gpointer *)0);
 
   GtkWidget *log_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(linear_b),"Log");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (log_b), nr2_gain_method==1);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (log_b), active_receiver->nr2_gain_method==1);
   gtk_widget_show(log_b);
   gtk_grid_attach(GTK_GRID(grid),log_b,2,3,1,1);
   g_signal_connect(log_b,"pressed",G_CALLBACK(nr2_gain_cb),(gpointer *)1);
 
   GtkWidget *gamma_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(log_b),"Gamma");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gamma_b), nr2_gain_method==2);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gamma_b), active_receiver->nr2_gain_method==2);
   gtk_widget_show(gamma_b);
   gtk_grid_attach(GTK_GRID(grid),gamma_b,3,3,1,1);
   g_signal_connect(gamma_b,"pressed",G_CALLBACK(nr2_gain_cb),(gpointer *)2);
@@ -159,20 +160,20 @@ void dsp_menu(GtkWidget *parent) {
   gtk_grid_attach(GTK_GRID(grid),nr2_npe_method_label,0,4,1,1);
 
   GtkWidget *osms_b=gtk_radio_button_new_with_label(NULL,"OSMS");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (osms_b),nr2_npe_method==0);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (osms_b),active_receiver->nr2_npe_method==0);
   gtk_widget_show(osms_b);
   gtk_grid_attach(GTK_GRID(grid),osms_b,1,4,1,1);
   g_signal_connect(osms_b,"pressed",G_CALLBACK(nr2_npe_method_cb),(gpointer *)0);
 
   GtkWidget *mmse_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(osms_b),"MMSE");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mmse_b), nr2_npe_method==1);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mmse_b), active_receiver->nr2_npe_method==1);
   gtk_widget_show(mmse_b);
   gtk_grid_attach(GTK_GRID(grid),mmse_b,2,4,1,1);
   g_signal_connect(mmse_b,"pressed",G_CALLBACK(nr2_npe_method_cb),(gpointer *)1);
 
   GtkWidget *ae_b=gtk_check_button_new_with_label("NR2 AE Filter");
   //gtk_widget_override_font(ae_b, pango_font_description_from_string("Arial 18"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ae_b), nr2_ae);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ae_b), active_receiver->nr2_ae);
   gtk_widget_show(ae_b);
   gtk_grid_attach(GTK_GRID(grid),ae_b,0,5,1,1);
   g_signal_connect(ae_b,"toggled",G_CALLBACK(ae_cb),NULL);
diff --git a/encoder_menu.c b/encoder_menu.c
new file mode 100644 (file)
index 0000000..f2dabf7
--- /dev/null
@@ -0,0 +1,289 @@
+/* Copyright (C)
+* 2016 - John Melton, G0ORX/N6LYT
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "main.h"
+#include "new_menu.h"
+#include "agc_menu.h"
+#include "agc.h"
+#include "band.h"
+#include "channel.h"
+#include "radio.h"
+#include "receiver.h"
+#include "vfo.h"
+#include "button_text.h"
+#include "gpio.h"
+
+static GtkWidget *parent_window=NULL;
+
+static GtkWidget *dialog=NULL;
+
+static GtkWidget *b_af_gain;
+static GtkWidget *b_agc_gain;
+static GtkWidget *b_attenuation;
+static GtkWidget *b_mic_gain;
+static GtkWidget *b_drive;
+static GtkWidget *b_tune_drive;
+static GtkWidget *b_rit;
+static GtkWidget *b_cw_speed;
+static GtkWidget *b_cw_frequency;
+static GtkWidget *b_panadapter_high;
+static GtkWidget *b_panadapter_low;
+
+static int encoder;
+
+
+static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  if(dialog!=NULL) {
+    gtk_widget_destroy(dialog);
+    dialog=NULL;
+    sub_menu=NULL;
+  }
+  active_menu=NO_MENU;
+  return TRUE;
+}
+
+void encoder_select(int pos) {
+  int action;
+  GtkWidget *button;
+  switch(encoder) {
+    case 1:
+      if(pos>0) {
+        e1_encoder_action--;
+        if(e1_encoder_action<0) {
+          e1_encoder_action=ENCODER_LAST;
+        }
+      } if(pos<0) {
+        e1_encoder_action++;
+        if(e1_encoder_action>ENCODER_LAST) {
+          e1_encoder_action=0;
+        }
+      }
+      action=e1_encoder_action;
+      break;
+    case 2:
+      if(pos>0) {
+        e2_encoder_action--;
+        if(e2_encoder_action<0) {
+          e2_encoder_action=ENCODER_LAST;
+        }
+      } if(pos<0) {
+        e2_encoder_action++;
+        if(e2_encoder_action>ENCODER_LAST) {
+          e2_encoder_action=0;
+        }
+      }
+      action=e2_encoder_action;
+      break;
+    case 3:
+      if(pos>0) {
+        e3_encoder_action--;
+        if(e3_encoder_action<0) {
+          e3_encoder_action=ENCODER_LAST;
+        }
+      } if(pos<0) {
+        e3_encoder_action++;
+        if(e3_encoder_action>ENCODER_LAST) {
+          e3_encoder_action=0;
+        }
+      }
+      action=e3_encoder_action;
+      break;
+  }
+
+  switch(action) {
+    case ENCODER_AF_GAIN:
+      button=b_af_gain;
+      break;
+    case ENCODER_AGC_GAIN:
+      button=b_agc_gain;
+      break;
+    case ENCODER_ATTENUATION:
+      button=b_attenuation;
+      break;
+    case ENCODER_MIC_GAIN:
+      button=b_mic_gain;
+      break;
+    case ENCODER_DRIVE:
+      button=b_drive;
+      break;
+    case ENCODER_TUNE_DRIVE:
+      button=b_tune_drive;
+      break;
+    case ENCODER_RIT:
+      button=b_rit;
+      break;
+    case ENCODER_CW_SPEED:
+      button=b_cw_speed;
+      break;
+    case ENCODER_CW_FREQUENCY:
+      button=b_cw_frequency;
+      break;
+    case ENCODER_PANADAPTER_HIGH:
+      button=b_panadapter_high;
+      break;
+    case ENCODER_PANADAPTER_LOW:
+      button=b_panadapter_low;
+      break;
+  }
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
+
+}
+
+static gboolean action_select_cb (GtkWidget *widget, gpointer data) {
+  int action=(int)data;
+  switch(encoder) {
+    case 1:
+      e1_encoder_action=action;
+      break;
+    case 2:
+      e2_encoder_action=action;
+      break;
+    case 3:
+      e3_encoder_action=action;
+      break;
+  }
+}
+
+void encoder_menu(GtkWidget *parent,int e) {
+  GtkWidget *b;
+  int i;
+  BAND *band;
+
+  encoder=e;
+
+  int encoder_action;
+  switch(encoder) {
+    case 1:
+      encoder_action=e1_encoder_action;
+      break;
+    case 2:
+      encoder_action=e2_encoder_action;
+      break;
+    case 3:
+      encoder_action=e3_encoder_action;
+      break;
+  }
+  parent_window=parent;
+
+  dialog=gtk_dialog_new();
+  gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
+  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+
+  GdkRGBA color;
+  color.red = 1.0;
+  color.green = 1.0;
+  color.blue = 1.0;
+  color.alpha = 1.0;
+  gtk_widget_override_background_color(dialog,GTK_STATE_FLAG_NORMAL,&color);
+
+  GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+
+  GtkWidget *grid=gtk_grid_new();
+
+  gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+  gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
+  gtk_grid_set_column_spacing (GTK_GRID(grid),5);
+  gtk_grid_set_row_spacing (GTK_GRID(grid),5);
+
+  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);
+
+  char label_text[32];
+  sprintf(label_text,"Encoder E%d Action:",encoder);
+  GtkWidget *label=gtk_label_new(label_text);
+  gtk_grid_attach(GTK_GRID(grid),label,0,1,2,1);
+
+  b_af_gain=gtk_radio_button_new_with_label(NULL,"AF Gain");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_af_gain), encoder_action==ENCODER_AF_GAIN);
+  gtk_widget_show(b_af_gain);
+  gtk_grid_attach(GTK_GRID(grid),b_af_gain,0,2,2,1);
+  g_signal_connect(b_af_gain,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_AF_GAIN);
+
+  b_agc_gain=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_af_gain),"AGC Gain");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_agc_gain), encoder_action==ENCODER_AGC_GAIN);
+  gtk_widget_show(b_agc_gain);
+  gtk_grid_attach(GTK_GRID(grid),b_agc_gain,0,3,2,1);
+  g_signal_connect(b_agc_gain,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_AGC_GAIN);
+
+  b_attenuation=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_agc_gain),"Attenuation");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_attenuation), encoder_action==ENCODER_ATTENUATION);
+  gtk_widget_show(b_attenuation);
+  gtk_grid_attach(GTK_GRID(grid),b_attenuation,0,4,2,1);
+  g_signal_connect(b_attenuation,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_ATTENUATION);
+
+  b_mic_gain=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_attenuation),"Mic Gain");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_mic_gain), encoder_action==ENCODER_MIC_GAIN);
+  gtk_widget_show(b_mic_gain);
+  gtk_grid_attach(GTK_GRID(grid),b_mic_gain,0,5,2,1);
+  g_signal_connect(b_mic_gain,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_MIC_GAIN);
+
+  b_drive=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_mic_gain),"Drive");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_drive), encoder_action==ENCODER_DRIVE);
+  gtk_widget_show(b_drive);
+  gtk_grid_attach(GTK_GRID(grid),b_drive,0,6,2,1);
+  g_signal_connect(b_drive,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_DRIVE);
+
+  b_tune_drive=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_drive),"Tune Drive");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_tune_drive), encoder_action==ENCODER_TUNE_DRIVE);
+  gtk_widget_show(b_tune_drive);
+  gtk_grid_attach(GTK_GRID(grid),b_tune_drive,0,7,2,1);
+  g_signal_connect(b_tune_drive,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_TUNE_DRIVE);
+
+  b_rit=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_tune_drive),"RIT");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_rit), encoder_action==ENCODER_RIT);
+  gtk_widget_show(b_rit);
+  gtk_grid_attach(GTK_GRID(grid),b_rit,2,2,2,1);
+  g_signal_connect(b_rit,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_RIT);
+
+  b_cw_speed=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_rit),"CW Speed");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_cw_speed), encoder_action==ENCODER_CW_SPEED);
+  gtk_widget_show(b_cw_speed);
+  gtk_grid_attach(GTK_GRID(grid),b_cw_speed,2,3,2,1);
+  g_signal_connect(b_cw_speed,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_CW_SPEED);
+
+  b_cw_frequency=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_cw_speed),"CW Freq");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_cw_frequency), encoder_action==ENCODER_CW_FREQUENCY);
+  gtk_widget_show(b_cw_frequency);
+  gtk_grid_attach(GTK_GRID(grid),b_cw_frequency,2,4,2,1);
+  g_signal_connect(b_cw_frequency,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_CW_FREQUENCY);
+
+  b_panadapter_high=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_cw_frequency),"Panadapter High");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_panadapter_high), encoder_action==ENCODER_PANADAPTER_HIGH);
+  gtk_widget_show(b_panadapter_high);
+  gtk_grid_attach(GTK_GRID(grid),b_panadapter_high,2,6,2,1);
+  g_signal_connect(b_panadapter_high,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_PANADAPTER_HIGH);
+
+  b_panadapter_low=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_cw_frequency),"Panadapter Low");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_panadapter_low), encoder_action==ENCODER_PANADAPTER_LOW);
+  gtk_widget_show(b_panadapter_low);
+  gtk_grid_attach(GTK_GRID(grid),b_panadapter_low,2,7,2,1);
+  g_signal_connect(b_panadapter_low,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_PANADAPTER_LOW);
+
+  gtk_container_add(GTK_CONTAINER(content),grid);
+
+  sub_menu=dialog;
+
+  gtk_widget_show_all(dialog);
+
+}
diff --git a/encoder_menu.h b/encoder_menu.h
new file mode 100644 (file)
index 0000000..8b45595
--- /dev/null
@@ -0,0 +1,26 @@
+/* Copyright (C)
+* 2016 - John Melton, G0ORX/N6LYT
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#ifndef _ENCODER_MENU_H
+#define _ENCODER_MENU_H
+
+extern void encoder_menu(GtkWidget *parent,int e);
+
+extern void encoder_select(int pos);
+#endif
index c474baa4797dd86494e72fcbc8bad2d0bbba4c60..f2c7582e53f267d0fa2afd020e3947c1a7f5e13c 100644 (file)
@@ -76,10 +76,10 @@ static gboolean rx_rb_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat
 static gboolean enable_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   if(tx_menu) {
     enable_tx_equalizer=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
-    SetTXAEQRun(CHANNEL_TX, enable_tx_equalizer);
+    SetTXAEQRun(transmitter->id, enable_tx_equalizer);
   } else {
     enable_rx_equalizer=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
-    SetRXAEQRun(CHANNEL_RX0, enable_rx_equalizer);
+    SetRXAEQRun(active_receiver->id, enable_rx_equalizer);
   }
 }
 
@@ -87,10 +87,10 @@ static gboolean rx_value_changed_cb (GtkWidget *widget, GdkEventButton *event, g
   int i=(int)data;
   if(tx_menu) {
     tx_equalizer[i]=(int)gtk_range_get_value(GTK_RANGE(widget));
-    SetTXAGrphEQ(CHANNEL_TX, tx_equalizer);
+    SetTXAGrphEQ(transmitter->id, tx_equalizer);
   } else {
     rx_equalizer[i]=(int)gtk_range_get_value(GTK_RANGE(widget));
-    SetRXAGrphEQ(CHANNEL_RX0, rx_equalizer);
+    SetRXAGrphEQ(active_receiver->id, rx_equalizer);
   }
 }
 
index 84492adfe497c589ef152054eb79e5cd1af94e48..63d959c50137aa87bfbe4d7632d86850186b1358 100644 (file)
--- a/filter.c
+++ b/filter.c
@@ -17,7 +17,9 @@
 *
 */
 
+#include <stdio.h>
 #include "filter.h"
+#include "property.h"
 
 FILTER filterLSB[FILTERS]={
     {-5150,-150,"5.0k"},
@@ -29,9 +31,9 @@ FILTER filterLSB[FILTERS]={
     {-2550,-150,"2.4k"},
     {-2250,-150,"2.1k"},
     {-1950,-150,"1.8k"},
-    {-1150,-150,"1.0k"}/*,
+    {-1150,-150,"1.0k"},
     {-2850,-150,"Var1"},
-    {-2850,-150,"Var2"}*/
+    {-2850,-150,"Var2"}
     };
 
 FILTER filterDIGL[FILTERS]={
@@ -44,9 +46,9 @@ FILTER filterDIGL[FILTERS]={
     {-2550,-150,"2.4k"},
     {-2250,-150,"2.1k"},
     {-1950,-150,"1.8k"},
-    {-1150,-150,"1.0k"}/*,
+    {-1150,-150,"1.0k"},
     {-2850,-150,"Var1"},
-    {-2850,-150,"Var2"}*/
+    {-2850,-150,"Var2"}
     };
 
 FILTER filterUSB[FILTERS]={
@@ -59,9 +61,9 @@ FILTER filterUSB[FILTERS]={
     {150,2550,"2.4k"},
     {150,2250,"2.1k"},
     {150,1950,"1.8k"},
-    {150,1150,"1.0k"}/*,
+    {150,1150,"1.0k"},
     {150,2850,"Var1"},
-    {150,2850,"Var2"}*/
+    {150,2850,"Var2"}
     };
 
 FILTER filterDIGU[FILTERS]={
@@ -74,9 +76,9 @@ FILTER filterDIGU[FILTERS]={
     {150,2550,"2.4k"},
     {150,2250,"2.1k"},
     {150,1950,"1.8k"},
-    {150,1150,"1.0k"}/*,
+    {150,1150,"1.0k"},
     {150,2850,"Var1"},
-    {150,2850,"Var2"}*/
+    {150,2850,"Var2"}
     };
 
 FILTER filterCWL[FILTERS]={
@@ -89,9 +91,9 @@ FILTER filterCWL[FILTERS]={
     {125,125,"250"},
     {50,50,"100"},
     {25,25,"50"},
-    {13,13,"25"}/*,
+    {13,13,"25"},
     {250,250,"Var1"},
-    {250,250,"Var2"}*/
+    {250,250,"Var2"}
     };
 
 FILTER filterCWU[FILTERS]={
@@ -104,9 +106,9 @@ FILTER filterCWU[FILTERS]={
     {125,125,"250"},
     {50,50,"100"},
     {25,25,"50"},
-    {13,13,"25"}/*,
+    {13,13,"25"},
     {250,250,"Var1"},
-    {250,250,"Var2"}*/
+    {250,250,"Var2"}
     };
 
 FILTER filterAM[FILTERS]={
@@ -119,9 +121,9 @@ FILTER filterAM[FILTERS]={
     {-2000,2000,"4.0k"},
     {-1550,1550,"3.1k"},
     {-1450,1450,"2.9k"},
-    {-1200,1200,"2.4k"}/*,
+    {-1200,1200,"2.4k"},
     {-3300,3300,"Var1"},
-    {-3300,3300,"Var2"}*/
+    {-3300,3300,"Var2"}
     };
 
 FILTER filterSAM[FILTERS]={
@@ -134,9 +136,9 @@ FILTER filterSAM[FILTERS]={
     {-2000,2000,"4.0k"},
     {-1550,1550,"3.1k"},
     {-1450,1450,"2.9k"},
-    {-1200,1200,"2.4k"}/*,
+    {-1200,1200,"2.4k"},
     {-3300,3300,"Var1"},
-    {-3300,3300,"Var2"}*/
+    {-3300,3300,"Var2"}
     };
 
 FILTER filterFMN[FILTERS]={
@@ -149,9 +151,9 @@ FILTER filterFMN[FILTERS]={
     {-2000,2000,"4.0k"},
     {-1550,1550,"3.1k"},
     {-1450,1450,"2.9k"},
-    {-1200,1200,"2.4k"}/*,
+    {-1200,1200,"2.4k"},
     {-3300,3300,"Var1"},
-    {-3300,3300,"Var2"}*/
+    {-3300,3300,"Var2"}
     };
 
 FILTER filterDSB[FILTERS]={
@@ -164,9 +166,9 @@ FILTER filterDSB[FILTERS]={
     {-2000,2000,"4.0k"},
     {-1550,1550,"3.1k"},
     {-1450,1450,"2.9k"},
-    {-1200,1200,"2.4k"}/*,
+    {-1200,1200,"2.4k"},
     {-3300,3300,"Var1"},
-    {-3300,3300,"Var2"}*/
+    {-3300,3300,"Var2"}
     };
 
 FILTER filterSPEC[FILTERS]={
@@ -179,9 +181,9 @@ FILTER filterSPEC[FILTERS]={
     {-2000,2000,"4.0k"},
     {-1550,1550,"3.1k"},
     {-1450,1450,"2.9k"},
-    {-1200,1200,"2.4k"}/*,
+    {-1200,1200,"2.4k"},
     {-3300,3300,"Var1"},
-    {-3300,3300,"Var2"}*/
+    {-3300,3300,"Var2"}
     };
 
 FILTER filterDRM[FILTERS]={
@@ -194,9 +196,9 @@ FILTER filterDRM[FILTERS]={
     {-2000,2000,"4.0k"},
     {-1550,1550,"3.1k"},
     {-1450,1450,"2.9k"},
-    {-1200,1200,"2.4k"}/*,
+    {-1200,1200,"2.4k"},
     {-3300,3300,"Var1"},
-    {-3300,3300,"Var2"}*/
+    {-3300,3300,"Var2"}
     };
 
 #ifdef FREEDV
@@ -210,9 +212,9 @@ FILTER filterFREEDV[FILTERS]={
     {150,2550,"2.4k"},
     {150,2250,"2.1k"},
     {150,1950,"1.8k"},
-    {150,1150,"1.0k"}/*,
+    {150,1150,"1.0k"},
     {150,2850,"Var1"},
-    {150,2850,"Var2"}*/
+    {150,2850,"Var2"}
     };
 #endif
 
@@ -227,9 +229,9 @@ FILTER filterPSK[FILTERS]={
     {150,2550,"2.4k"},
     {150,2250,"2.1k"},
     {150,1950,"1.8k"},
-    {150,1150,"1.0k"}/*,
+    {150,1150,"1.0k"},
     {150,2850,"Var1"},
-    {150,2850,"Var2"}*/
+    {150,2850,"Var2"}
     };
 #endif
 
@@ -256,3 +258,194 @@ FILTER *filters[]={
 
 };
 
+void filterSaveState() {
+    char value[128];
+
+    // save the Var1 and Var2 settings
+    sprintf(value,"%d",filterLSB[filterVar1].low);
+    setProperty("filter.lsb.var1.low",value);
+    sprintf(value,"%d",filterLSB[filterVar1].high);
+    setProperty("filter.lsb.var1.high",value);
+    sprintf(value,"%d",filterLSB[filterVar2].low);
+    setProperty("filter.lsb.var2.low",value);
+    sprintf(value,"%d",filterLSB[filterVar2].high);
+    setProperty("filter.lsb.var2.high",value);
+    
+    sprintf(value,"%d",filterDIGL[filterVar1].low);
+    setProperty("filter.digl.var1.low",value);
+    sprintf(value,"%d",filterDIGL[filterVar1].high);
+    setProperty("filter.digl.var1.high",value);
+    sprintf(value,"%d",filterDIGL[filterVar2].low);
+    setProperty("filter.digl.var2.low",value);
+    sprintf(value,"%d",filterDIGL[filterVar2].high);
+    setProperty("filter.digl.var2.high",value);
+    
+    sprintf(value,"%d",filterCWL[filterVar1].low);
+    setProperty("filter.cwl.var1.low",value);
+    sprintf(value,"%d",filterCWL[filterVar1].high);
+    setProperty("filter.cwl.var1.high",value);
+    sprintf(value,"%d",filterCWL[filterVar2].low);
+    setProperty("filter.cwl.var2.low",value);
+    sprintf(value,"%d",filterCWL[filterVar2].high);
+    setProperty("filter.cwl.var2.high",value);
+    
+    sprintf(value,"%d",filterUSB[filterVar1].low);
+    setProperty("filter.usb.var1.low",value);
+    sprintf(value,"%d",filterUSB[filterVar1].high);
+    setProperty("filter.usb.var1.high",value);
+    sprintf(value,"%d",filterUSB[filterVar2].low);
+    setProperty("filter.usb.var2.low",value);
+    sprintf(value,"%d",filterUSB[filterVar2].high);
+    setProperty("filter.usb.var2.high",value);
+    
+    sprintf(value,"%d",filterDIGU[filterVar1].low);
+    setProperty("filter.digu.var1.low",value);
+    sprintf(value,"%d",filterDIGU[filterVar1].high);
+    setProperty("filter.digu.var1.high",value);
+    sprintf(value,"%d",filterDIGU[filterVar2].low);
+    setProperty("filter.digu.var2.low",value);
+    sprintf(value,"%d",filterDIGU[filterVar2].high);
+    setProperty("filter.digu.var2.high",value);
+    
+    sprintf(value,"%d",filterCWU[filterVar1].low);
+    setProperty("filter.cwu.var1.low",value);
+    sprintf(value,"%d",filterCWU[filterVar1].high);
+    setProperty("filter.cwu.var1.high",value);
+    sprintf(value,"%d",filterCWU[filterVar2].low);
+    setProperty("filter.cwu.var2.low",value);
+    sprintf(value,"%d",filterCWU[filterVar2].high);
+    setProperty("filter.cwu.var2.high",value);
+    
+    sprintf(value,"%d",filterAM[filterVar1].low);
+    setProperty("filter.am.var1.low",value);
+    sprintf(value,"%d",filterAM[filterVar1].high);
+    setProperty("filter.am.var1.high",value);
+    sprintf(value,"%d",filterAM[filterVar2].low);
+    setProperty("filter.am.var2.low",value);
+    sprintf(value,"%d",filterAM[filterVar2].high);
+    setProperty("filter.am.var2.high",value);
+    
+    sprintf(value,"%d",filterSAM[filterVar1].low);
+    setProperty("filter.sam.var1.low",value);
+    sprintf(value,"%d",filterSAM[filterVar1].high);
+    setProperty("filter.sam.var1.high",value);
+    sprintf(value,"%d",filterSAM[filterVar2].low);
+    setProperty("filter.sam.var2.low",value);
+    sprintf(value,"%d",filterSAM[filterVar2].high);
+    setProperty("filter.sam.var2.high",value);
+    
+    sprintf(value,"%d",filterFMN[filterVar1].low);
+    setProperty("filter.fmn.var1.low",value);
+    sprintf(value,"%d",filterFMN[filterVar1].high);
+    setProperty("filter.fmn.var1.high",value);
+    sprintf(value,"%d",filterFMN[filterVar2].low);
+    setProperty("filter.fmn.var2.low",value);
+    sprintf(value,"%d",filterFMN[filterVar2].high);
+    setProperty("filter.fmn.var2.high",value);
+    
+    sprintf(value,"%d",filterDSB[filterVar1].low);
+    setProperty("filter.dsb.var1.low",value);
+    sprintf(value,"%d",filterDSB[filterVar1].high);
+    setProperty("filter.dsb.var1.high",value);
+    sprintf(value,"%d",filterDSB[filterVar2].low);
+    setProperty("filter.dsb.var2.low",value);
+    sprintf(value,"%d",filterDSB[filterVar2].high);
+    setProperty("filter.dsb.var2.high",value);
+    
+}
+
+void filterRestoreState() {
+    char* value;
+
+    value=getProperty("filter.lsb.var1.low");
+    if(value) filterLSB[filterVar1].low=atoi(value);
+    value=getProperty("filter.lsb.var1.high");
+    if(value) filterLSB[filterVar1].high=atoi(value);
+    value=getProperty("filter.lsb.var2.low");
+    if(value) filterLSB[filterVar2].low=atoi(value);
+    value=getProperty("filter.lsb.var2.high");
+    if(value) filterLSB[filterVar2].high=atoi(value);
+
+    value=getProperty("filter.digl.var1.low");
+    if(value) filterDIGL[filterVar1].low=atoi(value);
+    value=getProperty("filter.digl.var1.high");
+    if(value) filterDIGL[filterVar1].high=atoi(value);
+    value=getProperty("filter.digl.var2.low");
+    if(value) filterDIGL[filterVar2].low=atoi(value);
+    value=getProperty("filter.digl.var2.high");
+    if(value) filterDIGL[filterVar2].high=atoi(value);
+
+    value=getProperty("filter.cwl.var1.low");
+    if(value) filterCWL[filterVar1].low=atoi(value);
+    value=getProperty("filter.cwl.var1.high");
+    if(value) filterCWL[filterVar1].high=atoi(value);
+    value=getProperty("filter.cwl.var2.low");
+    if(value) filterCWL[filterVar2].low=atoi(value);
+    value=getProperty("filter.cwl.var2.high");
+    if(value) filterCWL[filterVar2].high=atoi(value);
+
+    value=getProperty("filter.usb.var1.low");
+    if(value) filterUSB[filterVar1].low=atoi(value);
+    value=getProperty("filter.usb.var1.high");
+    if(value) filterUSB[filterVar1].high=atoi(value);
+    value=getProperty("filter.usb.var2.low");
+    if(value) filterUSB[filterVar2].low=atoi(value);
+    value=getProperty("filter.usb.var2.high");
+    if(value) filterUSB[filterVar2].high=atoi(value);
+
+    value=getProperty("filter.digu.var1.low");
+    if(value) filterDIGU[filterVar1].low=atoi(value);
+    value=getProperty("filter.digu.var1.high");
+    if(value) filterDIGU[filterVar1].high=atoi(value);
+    value=getProperty("filter.digu.var2.low");
+    if(value) filterDIGU[filterVar2].low=atoi(value);
+    value=getProperty("filter.digu.var2.high");
+    if(value) filterDIGU[filterVar2].high=atoi(value);
+
+    value=getProperty("filter.cwu.var1.low");
+    if(value) filterCWU[filterVar1].low=atoi(value);
+    value=getProperty("filter.cwu.var1.high");
+    if(value) filterCWU[filterVar1].high=atoi(value);
+    value=getProperty("filter.cwu.var2.low");
+    if(value) filterCWU[filterVar2].low=atoi(value);
+    value=getProperty("filter.cwu.var2.high");
+    if(value) filterCWU[filterVar2].high=atoi(value);
+
+    value=getProperty("filter.am.var1.low");
+    if(value) filterAM[filterVar1].low=atoi(value);
+    value=getProperty("filter.am.var1.high");
+    if(value) filterAM[filterVar1].high=atoi(value);
+    value=getProperty("filter.am.var2.low");
+    if(value) filterAM[filterVar2].low=atoi(value);
+    value=getProperty("filter.am.var2.high");
+    if(value) filterAM[filterVar2].high=atoi(value);
+
+    value=getProperty("filter.sam.var1.low");
+    if(value) filterSAM[filterVar1].low=atoi(value);
+    value=getProperty("filter.sam.var1.high");
+    if(value) filterSAM[filterVar1].high=atoi(value);
+    value=getProperty("filter.sam.var2.low");
+    if(value) filterSAM[filterVar2].low=atoi(value);
+    value=getProperty("filter.sam.var2.high");
+    if(value) filterSAM[filterVar2].high=atoi(value);
+
+    value=getProperty("filter.fmn.var1.low");
+    if(value) filterFMN[filterVar1].low=atoi(value);
+    value=getProperty("filter.fmn.var1.high");
+    if(value) filterFMN[filterVar1].high=atoi(value);
+    value=getProperty("filter.fmn.var2.low");
+    if(value) filterFMN[filterVar2].low=atoi(value);
+    value=getProperty("filter.fmn.var2.high");
+    if(value) filterFMN[filterVar2].high=atoi(value);
+
+    value=getProperty("filter.dsb.var1.low");
+    if(value) filterDSB[filterVar1].low=atoi(value);
+    value=getProperty("filter.dsb.var1.high");
+    if(value) filterDSB[filterVar1].high=atoi(value);
+    value=getProperty("filter.dsb.var2.low");
+    if(value) filterDSB[filterVar2].low=atoi(value);
+    value=getProperty("filter.dsb.var2.high");
+    if(value) filterDSB[filterVar2].high=atoi(value);
+
+}
+
index 8c91cfe8ada18384855b1df50ed42c68ebcf7051..ea950032babf1f0f8ee0a1d9a91fd85ada4c0123 100644 (file)
--- a/filter.h
+++ b/filter.h
@@ -22,8 +22,7 @@
 
 #include "mode.h"
 
-// disable Var1 and Var2 (change to 12 to enable)
-#define FILTERS 10
+#define FILTERS 12
 
 #define CW_PITCH 600
 
@@ -56,12 +55,8 @@ int filterHigh;
 int txFilterLowCut;
 int txFilterHighCut;
 
-int filterVar1Low;
-int filterVar1High;
-int filterVar2Low;
-int filterVar2High;
-
-
 FILTER *filters[MODES];
 
+void filterSaveState();
+void filterRestoreState();
 #endif
index 9b9b0dcfb3b92d62abd0684aaf095967789e1a98..f0aa005068e83b272324eaa822fa5db6b902a81b 100644 (file)
@@ -1,6 +1,4 @@
-/* Copyright (C)
-* 2016 - John Melton, G0ORX/N6LYT
-*
+/*
 * 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 2
@@ -28,9 +26,9 @@
 #include "filter.h"
 #include "mode.h"
 #include "radio.h"
+#include "receiver.h"
 #include "vfo.h"
 #include "button_text.h"
-#include "wdsp_init.h"
 
 static GtkWidget *parent_window=NULL;
 
@@ -47,38 +45,67 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat
   return TRUE;
 }
 
-static gboolean filter_select_cb (GtkWidget *widget, gpointer        data) {
+int filter_select(void *data) {
   int f=(int)data;
-  BANDSTACK_ENTRY *entry;
-  entry=bandstack_entry_get_current();
-  entry->filter=f;
-  FILTER* band_filters=filters[entry->mode];
-  FILTER* band_filter=&band_filters[entry->filter];
-  setFilter(band_filter->low,band_filter->high);
+  vfo_filter_changed(f);
+  return 0;
+}
+
+static gboolean filter_select_cb (GtkWidget *widget, gpointer        data) {
+  filter_select(data);
   set_button_text_color(last_filter,"black");
   last_filter=widget;
   set_button_text_color(last_filter,"orange");
-  vfo_update(NULL);
 }
 
-static gboolean deviation_select_cb (GtkWidget *widget, gpointer        data) {
+static gboolean deviation_select_cb (GtkWidget *widget, gpointer data) {
   deviation=(int)data;
   if(deviation==2500) {
-    setFilter(-4000,4000);
+    //setFilter(-4000,4000);
+    set_filter(active_receiver,-4000,4000);
   } else {
-    setFilter(-8000,8000);
+    //setFilter(-8000,8000);
+    set_filter(active_receiver,-8000,8000);
   }
-  wdsp_set_deviation((double)deviation);
+  set_deviation(active_receiver,(double)deviation);
   set_button_text_color(last_filter,"black");
   last_filter=widget;
   set_button_text_color(last_filter,"orange");
   vfo_update(NULL);
 }
 
+static void var_spin_low_cb (GtkWidget *widget, gpointer data) {
+  int f=(int)data;
+  int id=active_receiver->id;
+
+  FILTER *mode_filters=filters[vfo[id].mode];
+  FILTER *filter=&mode_filters[f];
+
+  filter->low=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
+  if(vfo[id].mode==modeCWL || vfo[id].mode==modeCWU) {
+    filter->high=filter->low;
+  }
+  if(f==vfo[id].filter) {
+    receiver_filter_changed(receiver[id]);
+  }
+}
+
+static void var_spin_high_cb (GtkWidget *widget, gpointer data) {
+  int f=(int)data;
+  int id=active_receiver->id;
+
+  FILTER *mode_filters=filters[vfo[id].mode];
+  FILTER *filter=&mode_filters[f];
+
+  filter->high=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
+  if(f==vfo[id].filter) {
+    receiver_filter_changed(receiver[id]);
+  }
+}
+
 void filter_menu(GtkWidget *parent) {
   GtkWidget *b;
   int i;
-  BAND *band;
 
   parent_window=parent;
 
@@ -106,8 +133,16 @@ void filter_menu(GtkWidget *parent) {
   g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
   gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
 
-  BANDSTACK_ENTRY *entry=bandstack_entry_get_current();
-  FILTER* band_filters=filters[entry->mode];
+  char label[32];
+  sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B");
+  GtkWidget *rx_label=gtk_label_new(label);
+  gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1);
+
+  BAND *band=band_get_band(vfo[active_receiver->id].band);
+  BANDSTACK *bandstack=band->bandstack;
+  BANDSTACK_ENTRY *entry=&bandstack->entry[vfo[active_receiver->id].bandstack];
+  FILTER* band_filters=filters[vfo[active_receiver->id].mode];
+  FILTER* band_filter=&band_filters[vfo[active_receiver->id].filter];
 
   switch(entry->mode) {
     case modeFMN:
@@ -138,10 +173,10 @@ void filter_menu(GtkWidget *parent) {
       break;
 
     default:
-      for(i=0;i<FILTERS;i++) {
+      for(i=0;i<FILTERS-2;i++) {
         FILTER* band_filter=&band_filters[i];
         GtkWidget *b=gtk_button_new_with_label(band_filters[i].title);
-        if(i==entry->filter) {
+        if(i==vfo[active_receiver->id].filter) {
           set_button_text_color(b,"orange");
           last_filter=b;
         } else {
@@ -150,6 +185,57 @@ void filter_menu(GtkWidget *parent) {
         gtk_grid_attach(GTK_GRID(grid),b,i%5,1+(i/5),1,1);
         g_signal_connect(b,"pressed",G_CALLBACK(filter_select_cb),(gpointer *)i);
       }
+
+      // last 2 are var1 and var2
+      int row=1+((i+4)/5);
+      FILTER* band_filter=&band_filters[i];
+      GtkWidget *b=gtk_button_new_with_label(band_filters[i].title);
+      if(i==vfo[active_receiver->id].filter) {
+        set_button_text_color(b,"orange");
+        last_filter=b;
+      } else {
+        set_button_text_color(b,"black");
+      }
+      gtk_grid_attach(GTK_GRID(grid),b,0,row,1,1);
+      g_signal_connect(b,"pressed",G_CALLBACK(filter_select_cb),(gpointer *)i);
+
+      GtkWidget *var1_spin_low=gtk_spin_button_new_with_range(-8000.0,+8000.0,1.0);
+      gtk_spin_button_set_value(GTK_SPIN_BUTTON(var1_spin_low),(double)band_filter->low);
+      gtk_grid_attach(GTK_GRID(grid),var1_spin_low,1,row,1,1);
+      g_signal_connect(var1_spin_low,"value-changed",G_CALLBACK(var_spin_low_cb),(gpointer *)i);
+
+      if(vfo[active_receiver->id].mode!=modeCWL && vfo[active_receiver->id].mode!=modeCWU) {
+        GtkWidget *var1_spin_high=gtk_spin_button_new_with_range(-8000.0,+8000.0,1.0);
+        gtk_spin_button_set_value(GTK_SPIN_BUTTON(var1_spin_high),(double)band_filter->high);
+        gtk_grid_attach(GTK_GRID(grid),var1_spin_high,2,row,1,1);
+        g_signal_connect(var1_spin_high,"value-changed",G_CALLBACK(var_spin_high_cb),(gpointer *)i);
+      }
+
+      row++;
+      i++;
+      band_filter=&band_filters[i];
+      b=gtk_button_new_with_label(band_filters[i].title);
+      if(i==vfo[active_receiver->id].filter) {
+        set_button_text_color(b,"orange");
+        last_filter=b;
+      } else {
+        set_button_text_color(b,"black");
+      }
+      gtk_grid_attach(GTK_GRID(grid),b,0,row,1,1);
+      g_signal_connect(b,"pressed",G_CALLBACK(filter_select_cb),(gpointer *)i);
+      
+      GtkWidget *var2_spin_low=gtk_spin_button_new_with_range(-8000.0,+8000.0,1.0);
+      gtk_spin_button_set_value(GTK_SPIN_BUTTON(var2_spin_low),(double)band_filter->low);
+      gtk_grid_attach(GTK_GRID(grid),var2_spin_low,1,row,1,1);
+      g_signal_connect(var2_spin_low,"value-changed",G_CALLBACK(var_spin_low_cb),(gpointer *)i);
+
+      if(vfo[active_receiver->id].mode!=modeCWL && vfo[active_receiver->id].mode!=modeCWU) {
+        GtkWidget *var2_spin_high=gtk_spin_button_new_with_range(-8000.0,+8000.0,1.0);
+        gtk_spin_button_set_value(GTK_SPIN_BUTTON(var2_spin_high),(double)band_filter->high);
+        gtk_grid_attach(GTK_GRID(grid),var2_spin_high,2,row,1,1);
+        g_signal_connect(var2_spin_high,"value-changed",G_CALLBACK(var_spin_high_cb),(gpointer *)i);
+      }
+
       break;
   }
 
index fbc39bef0876ca0dc37a716f33d3ed5a06e0eb37..057532ab6dc42e8ea9feccfc6e5a4aef255c3c14 100644 (file)
@@ -18,3 +18,4 @@
 */
 
 extern void filter_menu(GtkWidget *parent);
+extern int filter_select(void *data);
index 00d1d6cdbf2d40c9c2ecbd1af10112d8f0b0f011..d3d884792fc4a70e653dae7362d1351bd1f7fcd2 100644 (file)
--- a/fm_menu.c
+++ b/fm_menu.c
@@ -24,7 +24,7 @@
 #include "new_menu.h"
 #include "fm_menu.h"
 #include "radio.h"
-#include "wdsp_init.h"
+#include "transmitter.h"
 
 static GtkWidget *parent_window=NULL;
 
@@ -47,7 +47,7 @@ static gboolean emp_cb (GtkWidget *widget, gpointer data) {
   } else {
     pre_emphasize=0;
   }  
-  wdsp_set_pre_emphasize(pre_emphasize);
+  tx_set_pre_emphasize(transmitter,pre_emphasize);
 }
 
 void fm_menu(GtkWidget *parent) {
index 0b34ff0fdd9c0731bcdc7ad3df8747019698d7b8..987de813da3194af31bb21ef5d7405c97ffd880e 100644 (file)
@@ -27,6 +27,7 @@
 #include "filter.h"
 #include "mode.h"
 #include "radio.h"
+#include "receiver.h"
 #include "vfo.h"
 
 static GtkWidget *parent_window=NULL;
@@ -117,14 +118,17 @@ static gboolean freqent_select_cb (GtkWidget *widget, gpointer data) {
             if(b!=band_get_current()) {
               BAND *band=band_set_current(b);
               BANDSTACK_ENTRY *entry=bandstack_entry_get_current();
-              setMode(entry->mode);
+              //setMode(entry->mode);
+              set_mode(active_receiver,entry->mode);
               FILTER* band_filters=filters[entry->mode];
               FILTER* band_filter=&band_filters[entry->filter];
-              setFilter(band_filter->low,band_filter->high);
-              set_alex_rx_antenna(band->alexRxAntenna);
-              set_alex_tx_antenna(band->alexTxAntenna);
-              set_alex_attenuation(band->alexAttenuation);
-
+              //setFilter(band_filter->low,band_filter->high);
+              set_filter(active_receiver,band_filter->low,band_filter->high);
+              if(active_receiver->id==0) {
+                set_alex_rx_antenna(band->alexRxAntenna);
+                set_alex_tx_antenna(band->alexTxAntenna);
+                set_alex_attenuation(band->alexAttenuation);
+              }
             }
             setFrequency(f);
             vfo_update(NULL);
@@ -169,7 +173,12 @@ void freqent_menu(GtkWidget *parent) {
     label = gtk_label_new (NULL);
     gtk_label_set_markup (GTK_LABEL (label), "<big>0</big>");
     gtk_misc_set_alignment (GTK_MISC (label), 1, .5);
-    gtk_grid_attach(GTK_GRID(grid),label,1,0,1,1);
+    gtk_grid_attach(GTK_GRID(grid),label,1,0,2,1);
+
+    char label[32];
+    sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B");
+    GtkWidget *rx_label=gtk_label_new(label);
+    gtk_grid_attach(GTK_GRID(grid),rx_label,3,0,1,1);
 
     GtkWidget *step_rb=NULL;
     for (i=0; i<16; i++) {
index f3757df6d0f5320bc8496b7764c91510486dc2de..da5bb154f7e28e61c14bd3d1c0be69e4ea7f1eac 100644 (file)
@@ -27,6 +27,7 @@
 #include "band.h"
 #include "filter.h"
 #include "radio.h"
+#include "receiver.h"
 
 static GtkWidget *parent_window=NULL;
 
@@ -47,10 +48,12 @@ static void vfo_divisor_value_changed_cb(GtkWidget *widget, gpointer data) {
   vfo_encoder_divisor=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
 }
 
+/*
 static void toolbar_dialog_buttons_cb(GtkWidget *widget, gpointer data) {
   toolbar_dialog_buttons=toolbar_dialog_buttons==1?0:1;
   update_toolbar_labels();
 }
+*/
 
 static void ptt_cb(GtkWidget *widget, gpointer data) {
   mic_ptt_enabled=mic_ptt_enabled==1?0:1;
@@ -88,14 +91,18 @@ static void alex_cb(GtkWidget *widget, gpointer data) {
   if(filter_board==ALEX) {
     BAND *band=band_get_current_band();
     BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
-    setFrequency(entry->frequencyA);
-    setMode(entry->mode);
+    setFrequency(entry->frequency);
+    //setMode(entry->mode);
+    set_mode(active_receiver,entry->mode);
     FILTER* band_filters=filters[entry->mode];
     FILTER* band_filter=&band_filters[entry->filter];
-    setFilter(band_filter->low,band_filter->high);
-    set_alex_rx_antenna(band->alexRxAntenna);
-    set_alex_tx_antenna(band->alexTxAntenna);
-    set_alex_attenuation(band->alexAttenuation);
+    //setFilter(band_filter->low,band_filter->high);
+    set_filter(active_receiver,band_filter->low,band_filter->high);
+    if(active_receiver->id==0) {
+      set_alex_rx_antenna(band->alexRxAntenna);
+      set_alex_tx_antenna(band->alexTxAntenna);
+      set_alex_attenuation(band->alexAttenuation);
+    }
   }
 }
 
@@ -116,53 +123,18 @@ static void apollo_cb(GtkWidget *widget, gpointer data) {
   if(filter_board==APOLLO) {
     BAND *band=band_get_current_band();
     BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
-    setFrequency(entry->frequencyA);
-    setMode(entry->mode);
+    setFrequency(entry->frequency);
+    //setMode(entry->mode);
+    set_mode(active_receiver,entry->mode);
     FILTER* band_filters=filters[entry->mode];
     FILTER* band_filter=&band_filters[entry->filter];
-    setFilter(band_filter->low,band_filter->high);
-  }
-}
-/*
-static void apollo_tuner_cb(GtkWidget *widget, gpointer data) {
-  apollo_tuner=apollo_tuner==1?0:1;
-  if(protocol==NEW_PROTOCOL) {
-    tuner_changed();
-  }
-}
-
-static void pa_cb(GtkWidget *widget, gpointer data) {
-  pa=pa==1?0:1;
-  if(protocol==NEW_PROTOCOL) {
-    pa_changed();
-  }
-}
-*/
-
-static void rx_dither_cb(GtkWidget *widget, gpointer data) {
-  rx_dither=rx_dither==1?0:1;
-  if(protocol==NEW_PROTOCOL) {
-  }
-}
-
-static void rx_random_cb(GtkWidget *widget, gpointer data) {
-  rx_random=rx_random==1?0:1;
-  if(protocol==NEW_PROTOCOL) {
-  }
-}
-
-static void rx_preamp_cb(GtkWidget *widget, gpointer data) {
-  rx_preamp=rx_preamp==1?0:1;
-  if(protocol==NEW_PROTOCOL) {
+    //setFilter(band_filter->low,band_filter->high);
+    set_filter(active_receiver,band_filter->low,band_filter->high);
   }
 }
 
 static void sample_rate_cb(GtkWidget *widget, gpointer data) {
-  if(protocol==ORIGINAL_PROTOCOL) {
-    old_protocol_new_sample_rate((int)data);
-  } else {
-    new_protocol_new_sample_rate((int)data);
-  }
+  radio_change_sample_rate((int)data);
 }
 
 static void rit_cb(GtkWidget *widget,gpointer data) {
@@ -204,21 +176,11 @@ void general_menu(GtkWidget *parent) {
   g_signal_connect(vfo_divisor,"value_changed",G_CALLBACK(vfo_divisor_value_changed_cb),NULL);
 
   if(protocol==ORIGINAL_PROTOCOL || protocol==NEW_PROTOCOL) {
-    GtkWidget *rx_dither_b=gtk_check_button_new_with_label("Dither");
-    //gtk_widget_override_font(rx_dither_b, pango_font_description_from_string("Arial 18"));
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx_dither_b), rx_dither);
-    gtk_grid_attach(GTK_GRID(grid),rx_dither_b,1,4,1,1);
-    g_signal_connect(rx_dither_b,"toggled",G_CALLBACK(rx_dither_cb),NULL);
-
-    GtkWidget *rx_random_b=gtk_check_button_new_with_label("Random");
-    //gtk_widget_override_font(rx_random_b, pango_font_description_from_string("Arial 18"));
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx_random_b), rx_random);
-    gtk_grid_attach(GTK_GRID(grid),rx_random_b,1,5,1,1);
-    g_signal_connect(rx_random_b,"toggled",G_CALLBACK(rx_random_cb),NULL);
 
     if((protocol==NEW_PROTOCOL && device==NEW_DEVICE_ORION) ||
        (protocol==NEW_PROTOCOL && device==NEW_DEVICE_ORION2) ||
-       (protocol==ORIGINAL_PROTOCOL && device==DEVICE_ORION)) {
+       (protocol==ORIGINAL_PROTOCOL && device==DEVICE_ORION) ||
+       (protocol==ORIGINAL_PROTOCOL && device==DEVICE_ORION2)) {
 
       GtkWidget *ptt_ring_b=gtk_radio_button_new_with_label(NULL,"PTT On Ring, Mic and Bias on Tip");
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptt_ring_b), mic_ptt_tip_bias_ring==0);
@@ -289,7 +251,7 @@ void general_menu(GtkWidget *parent) {
         gtk_grid_attach(GTK_GRID(grid),sample_rate_1536,0,7,1,1);
       g_signal_connect(sample_rate_1536,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)1536000);
 
-#ifdef raspberrypi
+#ifdef GPIO
       gtk_widget_set_sensitive(sample_rate_768,FALSE);
       gtk_widget_set_sensitive(sample_rate_1536,FALSE);
 #endif
diff --git a/gpio.c b/gpio.c
index 9586924252ebc08022d45d3294f6cb761e3e5654..d3ec3034f4694f5c8da1f51e6b85984db5e72573 100644 (file)
--- a/gpio.c
+++ b/gpio.c
@@ -1,3 +1,4 @@
+#include <gtk/gtk.h>
 
 #ifdef GPIO
 #include <stdio.h>
 #include <fcntl.h>
 #include <poll.h>
 #include <sched.h>
-#include <pthread.h>
+//#include <pthread.h>
 #include <wiringPi.h>
 #include <semaphore.h>
-#ifdef raspberrypi
+#ifdef GPIO
 #include <pigpio.h>
 #endif
 #ifdef sx1509
 #ifdef PSK
 #include "psk.h"
 #endif
+#include "new_menu.h"
+#include "encoder_menu.h"
 
 #define SYSFS_GPIO_DIR  "/sys/class/gpio"
 
 int ENABLE_VFO_ENCODER=1;
 int ENABLE_VFO_PULLUP=1;
-int VFO_ENCODER_A=17;
-int VFO_ENCODER_B=18;
+int VFO_ENCODER_A=18;
+int VFO_ENCODER_B=17;
 #if defined odroid && !defined sx1509
 int VFO_ENCODER_A_PIN=0;
 int VFO_ENCODER_B_PIN=1;
@@ -51,11 +54,11 @@ int ENABLE_E1_ENCODER=1;
 int ENABLE_E1_PULLUP=0;
 int E1_ENCODER_A=20;
 int E1_ENCODER_B=26;
-#ifndef sx1509
+//#ifndef sx1509
 int E1_FUNCTION=25;
-#else
-int E1_FUNCTION=2; //RRK, was 25 now taken by waveshare LCD TS, disable i2c
-#endif
+//#else
+//int E1_FUNCTION=2; //RRK, was 25 now taken by waveshare LCD TS, disable i2c
+//#endif
 int ENABLE_E2_ENCODER=1;
 int ENABLE_E2_PULLUP=0;
 int E2_ENCODER_A=16;
@@ -65,11 +68,11 @@ int ENABLE_E3_ENCODER=1;
 int ENABLE_E3_PULLUP=0;
 int E3_ENCODER_A=4;
 int E3_ENCODER_B=21;
-#if defined sx1509
+//#if defined sx1509
 int E3_FUNCTION=7;
-#else
-int E3_FUNCTION=3; //RRK, was 7 now taken by waveshare LCD TS, disable i2c
-#endif
+//#else
+//int E3_FUNCTION=3; //RRK, was 7 now taken by waveshare LCD TS, disable i2c
+//#endif
 int ENABLE_S1_BUTTON=1;
 int S1_BUTTON=13;
 int ENABLE_S2_BUTTON=1;
@@ -87,10 +90,14 @@ int MOX_BUTTON=27;
 int ENABLE_FUNCTION_BUTTON=1;
 int FUNCTION_BUTTON=22;
 int ENABLE_E1_BUTTON=1;
+int ENABLE_E2_BUTTON=1;
+int ENABLE_E3_BUTTON=1;
 int ENABLE_CW_BUTTONS=1;
 // make sure to disable UART0 for next 2 gpios
+#ifdef LOCALCW
 int CWL_BUTTON=9;
 int CWR_BUTTON=10;
+#endif
 
 #ifdef sx1509
 /* Hardware Hookup:
@@ -153,10 +160,13 @@ int SX1509_INT_PIN=0;
 static volatile int vfoEncoderPos;
 static volatile int e1EncoderPos;
 static volatile int e1Function;
+int e1_encoder_action=ENCODER_AF_GAIN;
 static volatile int e2EncoderPos;
 static volatile int e2Function;
+int e2_encoder_action=ENCODER_DRIVE;
 static volatile int e3EncoderPos;
 static volatile int e3Function;
+int e3_encoder_action=ENCODER_ATTENUATION;
 static volatile int function_state;
 static volatile int band_state;
 static volatile int bandstack_state;
@@ -167,13 +177,17 @@ static volatile int agc_state;
 static volatile int mox_state;
 static volatile int lock_state;
 
-static void* rotary_encoder_thread(void *arg);
-static pthread_t rotary_encoder_thread_id;
+//static void* rotary_encoder_thread(void *arg);
+static gpointer rotary_encoder_thread(gpointer data);
+//static pthread_t rotary_encoder_thread_id;
+static GThread *rotary_encoder_thread_id;
 static int previous_function_button=0;
 static int e1_function=0;
 static int previous_e1_function=0;
 static int e2_function=0;
 static int previous_e2_function=0;
+static int e3_function=0;
+static int previous_e3_function=0;
 static int band_button=0;
 static int previous_band_button=0;
 static int bandstack_button=0;
@@ -188,68 +202,190 @@ static int agc_button=0;
 static int previous_agc_button=0;
 static int mox_button=0;
 static int previous_mox_button=0;
-static int lock_button=0;
-static int previous_lock_button=0;
 
-static int running=1;
+//static GMutex m_running;
+static int running=0;
+
+char *encoder_string[] = {
+"AF GAIN",
+"AGC GAIN",
+"ATTENUATION",
+"MIC GAIN",
+"DRIVE",
+"TUNE DRIVE",
+"RIT",
+"CW SPEED",
+"CW FREQUENCY",
+"PANADAPTER HIGH",
+"PANADAPTER LOW",
+};
 
-static void e1FunctionAlert(int gpio, int level, uint32_t tick) {
-    e1Function=(level==0);
+static int mox_pressed(void *data) {
+  if(running) sim_mox_cb(NULL,NULL);
+  return 0;
 }
 
-static void e3FunctionAlert(int gpio, int level, uint32_t tick) {
+static int s1_pressed(void *data) {
+  if(running) sim_s1_pressed_cb(NULL,NULL);
+  return 0;
+}
+
+static int s1_released(void *data) {
+  if(running) sim_s1_released_cb(NULL,NULL);
+  return 0;
+}
+
+static int s2_pressed(void *data) {
+  if(running) sim_s2_pressed_cb(NULL,NULL);
+  return 0;
+}
+
+static int s2_released(void *data) {
+  if(running) sim_s2_released_cb(NULL,NULL);
+  return 0;
+}
+
+static int s3_pressed(void *data) {
+  if(running) sim_s3_pressed_cb(NULL,NULL);
+  return 0;
+}
+
+static int s3_released(void *data) {
+  if(running) sim_s3_released_cb(NULL,NULL);
+  return 0;
+}
+
+static int s4_pressed(void *data) {
+  if(running) sim_s4_pressed_cb(NULL,NULL);
+  return 0;
+}
+
+static int s4_released(void *data) {
+  if(running) sim_s4_released_cb(NULL,NULL);
+  return 0;
+}
+
+static int s5_pressed(void *data) {
+  if(running) sim_s5_pressed_cb(NULL,NULL);
+  return 0;
+}
+
+static int s5_released(void *data) {
+  if(running) sim_s5_released_cb(NULL,NULL);
+  return 0;
+}
+
+static int s6_pressed(void *data) {
+  if(running) sim_s6_pressed_cb(NULL,NULL);
+  return 0;
+}
+
+static int s6_released(void *data) {
+  if(running) sim_s6_released_cb(NULL,NULL);
+  return 0;
+}
+
+static int function_pressed(void *data) {
+  if(running) sim_function_cb(NULL,NULL);
+  return 0;
+}
+
+static int e_function_pressed(void *data) {
+  int encoder=(int)data;
+  start_encoder(encoder);
+  return 0;
+}
+
+static void e1FunctionAlert(int gpio, int level, uint32_t tick) {
     if(level==0) {
-      e3Function=e3Function==0?1:0;
+      if(running) g_idle_add(e_function_pressed,(gpointer)1);
     }
 }
 
 static void e2FunctionAlert(int gpio, int level, uint32_t tick) {
-    e2Function=(level==0);
+    if(level==0) {
+      if(running) g_idle_add(e_function_pressed,(gpointer)2);
+    }
+}
+
+static void e3FunctionAlert(int gpio, int level, uint32_t tick) {
+    if(level==0) {
+      if(running) g_idle_add(e_function_pressed,(gpointer)3);
+    }
 }
 
 static void functionAlert(int gpio, int level, uint32_t tick) {
-    function_state=(level==0);
+    if(level==0) {
+      if(running) g_idle_add(function_pressed,NULL);
+    }
 }
 
-static void bandAlert(int gpio, int level, uint32_t tick) {
-    band_state=(level==0);
+
+static void s1Alert(int gpio, int level, uint32_t tick) {
+    if(level==0) {
+      g_idle_add(s1_pressed,NULL);
+    } else {
+      g_idle_add(s1_released,NULL);
+    }
 }
 
-static void bandstackAlert(int gpio, int level, uint32_t tick) {
-    bandstack_state=(level==0);
+static void s2Alert(int gpio, int level, uint32_t tick) {
+    if(level==0) {
+      g_idle_add(s2_pressed,NULL);
+    } else {
+      g_idle_add(s2_released,NULL);
+    }
 }
 
-static void modeAlert(int gpio, int level, uint32_t tick) {
-    mode_state=(level==0);
+static void s3Alert(int gpio, int level, uint32_t tick) {
+    if(level==0) {
+      g_idle_add(s3_pressed,NULL);
+    } else {
+      g_idle_add(s3_released,NULL);
+    }
 }
 
-static void filterAlert(int gpio, int level, uint32_t tick) {
-    filter_state=(level==0);
+static void s4Alert(int gpio, int level, uint32_t tick) {
+    if(level==0) {
+      g_idle_add(s4_pressed,NULL);
+    } else {
+      g_idle_add(s4_released,NULL);
+    }
 }
 
-static void noiseAlert(int gpio, int level, uint32_t tick) {
-    noise_state=(level==0);
+static void s5Alert(int gpio, int level, uint32_t tick) {
+    if(level==0) {
+      g_idle_add(s5_pressed,NULL);
+    } else {
+      g_idle_add(s5_released,NULL);
+    }
 }
 
-static void agcAlert(int gpio, int level, uint32_t tick) {
-    agc_state=(level==0);
+static void s6Alert(int gpio, int level, uint32_t tick) {
+    if(level==0) {
+      g_idle_add(s6_pressed,NULL);
+    } else {
+      g_idle_add(s6_released,NULL);
+    }
 }
 
 static void moxAlert(int gpio, int level, uint32_t tick) {
-    mox_state=(level==0);
+    if(level==0) {
+      g_idle_add(mox_pressed,(gpointer)NULL);
+    } else {
+    }
 }
 
 static void lockAlert(int gpio, int level, uint32_t tick) {
     lock_state=(level==0);
 }
 
-static void cwAlert(int gpio, int level, uint32_t tick) {
-fprintf(stderr,"cwAlert: gpio=%d level=%d internal=%d\n",gpio,level,cw_keyer_internal);
 #ifdef LOCALCW
+static void cwAlert(int gpio, int level, uint32_t tick) {
     if (cw_keyer_internal == 0 && (mode==modeCWL || mode==modeCWU))
        keyer_event(gpio, cw_active_level == 0 ? level : (level==0));
-#endif
 }
+#endif
 
 static void vfoEncoderPulse(int gpio, int level, unsigned int tick) {
    static int levA=0, levB=0, lastGpio = -1;
@@ -483,12 +619,29 @@ void gpio_restore_state() {
   value=getProperty("E1_FUNCTION");
   if(value) E1_FUNCTION=atoi(value);
 #endif
+
+  value=getProperty("ENABLE_E2_BUTTON");
+  if(value) ENABLE_E2_BUTTON=atoi(value);
+#ifndef sx1509
+  value=getProperty("E2_FUNCTION");
+  if(value) E2_FUNCTION=atoi(value);
+#endif
+
+  value=getProperty("ENABLE_E3_BUTTON");
+  if(value) ENABLE_E3_BUTTON=atoi(value);
+#ifndef sx1509
+  value=getProperty("E3_FUNCTION");
+  if(value) E3_FUNCTION=atoi(value);
+#endif
+
+#ifdef LOCALCW
   value=getProperty("ENABLE_CW_BUTTONS");
   if(value) ENABLE_CW_BUTTONS=atoi(value);
   value=getProperty("CWL_BUTTON");
   if(value) CWL_BUTTON=atoi(value);
   value=getProperty("CWR_BUTTON");
   if(value) CWR_BUTTON=atoi(value);
+#endif
 }
 
 void gpio_save_state() {
@@ -564,25 +717,54 @@ void gpio_save_state() {
   setProperty("ENABLE_MOX_BUTTON",value);
   sprintf(value,"%d",MOX_BUTTON);
   setProperty("MOX_BUTTON",value);
+
   sprintf(value,"%d",ENABLE_E1_BUTTON);
   setProperty("ENABLE_E1_BUTTON",value);
 #ifndef sx1509
   sprintf(value,"%d",E1_FUNCTION);
   setProperty("E1_FUNCTION",value);
 #endif
+
+  sprintf(value,"%d",ENABLE_E2_BUTTON);
+  setProperty("ENABLE_E2_BUTTON",value);
+#ifndef sx1509
+  sprintf(value,"%d",E2_FUNCTION);
+  setProperty("E2_FUNCTION",value);
+#endif
+
+  sprintf(value,"%d",ENABLE_E3_BUTTON);
+  setProperty("ENABLE_E3_BUTTON",value);
+#ifndef sx1509
+  sprintf(value,"%d",E3_FUNCTION);
+  setProperty("E3_FUNCTION",value);
+#endif
+
+#ifdef LOCALCW
   sprintf(value,"%d",ENABLE_CW_BUTTONS);
   setProperty("ENABLE_CW_BUTTONS",value);
   sprintf(value,"%d",CWL_BUTTON);
   setProperty("CWL_BUTTON",value);
   sprintf(value,"%d",CWR_BUTTON);
   setProperty("CWR_BUTTON",value);
+#endif
 
   saveProperties("gpio.props");
 }
 
+#define BUTTON_STEADY_TIME_US 5000
+static void setup_button(int button, gpioAlertFunc_t pAlert) {
+  gpioSetMode(button, PI_INPUT);
+  gpioSetPullUpDown(button,PI_PUD_UP);
+  // give time to settle to avoid false triggers
+  usleep(10000);
+  gpioSetAlertFunc(button, pAlert);
+  gpioGlitchFilter(button, BUTTON_STEADY_TIME_US);
+}
 
 int gpio_init() {
-fprintf(stderr,"encoder_init\n");
+  fprintf(stderr,"gpio_init\n");
+
+  //g_mutex_init(&m_running);
 
 #if defined odroid && !defined sx1509
   VFO_ENCODER_A=88;
@@ -590,22 +772,11 @@ fprintf(stderr,"encoder_init\n");
 #endif
 
   gpio_restore_state();
-#ifdef raspberrypi
-
-#define BUTTON_STEADY_TIME_US 5000
-
-  void setup_button(int button, gpioAlertFunc_t pAlert) {
-    gpioSetMode(button, PI_INPUT);
-    gpioSetPullUpDown(button,PI_PUD_UP);
-    // give time to settle to avoid false triggers
-    usleep(10000);
-    gpioSetAlertFunc(button, pAlert);
-    gpioGlitchFilter(button, BUTTON_STEADY_TIME_US);
-  }
+#ifdef GPIO
 
-    fprintf(stderr,"encoder_init: VFO_ENCODER_A=%d VFO_ENCODER_B=%d\n",VFO_ENCODER_A,VFO_ENCODER_B);
+    fprintf(stderr,"gpio_init: VFO_ENCODER_A=%d VFO_ENCODER_B=%d\n",VFO_ENCODER_A,VFO_ENCODER_B);
 
-    fprintf(stderr,"gpioInitialize\n");
+    fprintf(stderr,"gpioInitialise\n");
     if(gpioInitialise()<0) {
         fprintf(stderr,"Cannot initialize GPIO\n");
         return -1;
@@ -639,6 +810,7 @@ fprintf(stderr,"encoder_init\n");
   }
 
 
+fprintf(stderr,"setup_button: E1 %d\n",E1_FUNCTION);
   setup_button(E1_FUNCTION, e1FunctionAlert);
   e1Function=0;
 
@@ -657,13 +829,14 @@ fprintf(stderr,"encoder_init\n");
     e1EncoderPos=0;
   }
 
-    setup_button(E2_FUNCTION, e2FunctionAlert);
-    e2Function=0;
+fprintf(stderr,"setup_button: E2 %d\n",E2_FUNCTION);
+  setup_button(E2_FUNCTION, e2FunctionAlert);
+  e2Function=0;
 
   if(ENABLE_E2_ENCODER) {
     gpioSetMode(E2_ENCODER_A, PI_INPUT);
     gpioSetMode(E2_ENCODER_B, PI_INPUT);
-    if(ENABLE_E1_PULLUP) {
+    if(ENABLE_E2_PULLUP) {
       gpioSetPullUpDown(E2_ENCODER_A, PI_PUD_UP);
       gpioSetPullUpDown(E2_ENCODER_B, PI_PUD_UP);
     } else {
@@ -675,13 +848,14 @@ fprintf(stderr,"encoder_init\n");
     e2EncoderPos=0;
   }
 
+fprintf(stderr,"setup_button: E3 %d\n",E3_FUNCTION);
   setup_button(E3_FUNCTION, e3FunctionAlert);
   e3Function=0;
 
   if(ENABLE_E3_ENCODER) {
     gpioSetMode(E3_ENCODER_A, PI_INPUT);
     gpioSetMode(E3_ENCODER_B, PI_INPUT);
-    if(ENABLE_E1_PULLUP) {
+    if(ENABLE_E3_PULLUP) {
       gpioSetPullUpDown(E3_ENCODER_A, PI_PUD_UP);
       gpioSetPullUpDown(E3_ENCODER_B, PI_PUD_UP);
     } else {
@@ -695,39 +869,42 @@ fprintf(stderr,"encoder_init\n");
 
 
   if(ENABLE_S1_BUTTON) {
-    setup_button(S1_BUTTON, bandAlert);
+    setup_button(S1_BUTTON, s1Alert);
   }
  
   if(ENABLE_S2_BUTTON) {
-    setup_button(S2_BUTTON, bandstackAlert);
+    setup_button(S2_BUTTON, s2Alert);
   }
  
   if(ENABLE_S3_BUTTON) {
-    setup_button(S3_BUTTON, modeAlert);
+    setup_button(S3_BUTTON, s3Alert);
   }
  
   if(ENABLE_S4_BUTTON) {
-    setup_button(S4_BUTTON, filterAlert);
+    setup_button(S4_BUTTON, s4Alert);
   }
  
   if(ENABLE_S5_BUTTON) {
-    setup_button(S5_BUTTON, noiseAlert);
+    setup_button(S5_BUTTON, s5Alert);
   }
  
   if(ENABLE_S6_BUTTON) {
-    setup_button(S6_BUTTON, agcAlert);
+    setup_button(S6_BUTTON, s6Alert);
   }
  
   if(ENABLE_MOX_BUTTON) {
     setup_button(MOX_BUTTON, moxAlert);
   }
 
+/*
 #ifndef sx1509
   if(ENABLE_E1_BUTTON) {
     setup_button(E1_FUNCTION, lockAlert);
   }
 #endif
+*/
 
+#ifdef LOCALCW
 fprintf(stderr,"GPIO: ENABLE_CW_BUTTONS=%d  CWL_BUTTON=%d CWR_BUTTON=%d\n",ENABLE_CW_BUTTONS, CWL_BUTTON, CWR_BUTTON);
   if(ENABLE_CW_BUTTONS) {
     setup_button(CWL_BUTTON, cwAlert);
@@ -741,6 +918,7 @@ fprintf(stderr,"GPIO: ENABLE_CW_BUTTONS=%d  CWL_BUTTON=%d CWR_BUTTON=%d\n",ENABL
     gpioGlitchFilter(CWR_BUTTON, 5000);
 */
   }
+#endif
  
 #endif
 
@@ -755,7 +933,7 @@ fprintf(stderr,"GPIO: ENABLE_CW_BUTTONS=%d  CWL_BUTTON=%d CWR_BUTTON=%d\n",ENABL
   E3_ENCODER_A=14;
   E3_ENCODER_B=15;
 
-  fprintf(stderr,"sx1509 encoder_init: VFO_ENCODER_A=%d VFO_ENCODER_B=%d\n",VFO_ENCODER_A,VFO_ENCODER_B);
+  fprintf(stderr,"sx1509 gpio_init: VFO_ENCODER_A=%d VFO_ENCODER_B=%d\n",VFO_ENCODER_A,VFO_ENCODER_B);
 
   pSX1509 = newSX1509();
 
@@ -819,7 +997,7 @@ fprintf(stderr,"GPIO: ENABLE_CW_BUTTONS=%d  CWL_BUTTON=%d CWR_BUTTON=%d\n",ENABL
     //VFO_ENCODER_A_PIN=ODROID_VFO_ENCODER_A_PIN;
     //VFO_ENCODER_B_PIN=ODROID_VFO_ENCODER_B_PIN;
  
-    fprintf(stderr,"encoder_init: VFO_ENCODER_A=%d VFO_ENCODER_B=%d\n",VFO_ENCODER_A,VFO_ENCODER_B);
+    fprintf(stderr,"gpio_init: VFO_ENCODER_A=%d VFO_ENCODER_B=%d\n",VFO_ENCODER_A,VFO_ENCODER_B);
 
     fprintf(stderr,"wiringPiSetup\n");
     if (wiringPiSetup () < 0) {
@@ -854,22 +1032,33 @@ fprintf(stderr,"GPIO: ENABLE_CW_BUTTONS=%d  CWL_BUTTON=%d CWR_BUTTON=%d\n",ENABL
     }
 #endif
 
-  int rc=pthread_create(&rotary_encoder_thread_id, NULL, rotary_encoder_thread, NULL);
-  if(rc<0) {
-    fprintf(stderr,"pthread_create for rotary_encoder_thread failed %d\n",rc);
+  rotary_encoder_thread_id = g_thread_new( "rotary encoder", rotary_encoder_thread, NULL);
+  if( ! rotary_encoder_thread_id )
+  {
+    fprintf(stderr,"g_thread_new failed on rotary_encoder_thread\n");
+    exit( -1 );
   }
+  fprintf(stderr, "rotary_encoder_thread: id=%p\n",rotary_encoder_thread_id);
 
 
   return 0;
 }
 
 void gpio_close() {
+fprintf(stderr,"gpio_close: lock\n");
+    //g_mutex_lock(&m_running);
     running=0;
+#ifdef GPIO
+fprintf(stderr,"gpioTerminate\n");
+    gpioTerminate();
+#endif
+fprintf(stderr,"gpio_close: unlock\n");
+    //g_mutex_unlock(&m_running);
 #if defined odroid && !defined sx1509
     FILE *fp;
-    fp = popen("echo 97 > /sys/class/gpio/unexport\n", "r");
+    fp = popen("echo 87 > /sys/class/gpio/unexport\n", "r");
     pclose(fp);
-    fp = popen("echo 108 > /sys/class/gpio/unexport\n", "r");
+    fp = popen("echo 88 > /sys/class/gpio/unexport\n", "r");
     pclose(fp);
 #endif
 }
@@ -897,10 +1086,6 @@ int e1_encoder_get_pos() {
     return pos;
 }
 
-int e1_function_get_state() {
-    return e1Function;
-}
-
 int e2_encoder_get_pos() {
     int pos=e2EncoderPos;
     e2EncoderPos=0;
@@ -912,15 +1097,10 @@ int e3_encoder_get_pos() {
     e3EncoderPos=0;
     return pos;
 }
-
-int agc_function_get_state() {
+int e3_function_get_state() {
     return e3Function;
 }
 
-int e2_function_get_state() {
-    return e2Function;
-}
-
 int function_get_state() {
     return function_state;
 }
@@ -960,282 +1140,190 @@ int lock_get_state() {
 
 static int vfo_encoder_changed(void *data) {
   if(!locked) {
-    int pos=*(int*)data;
-
-    // VFO
-    BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
-    setFrequency(entry->frequencyA+ddsOffset+(pos*step));
-    vfo_update(NULL);
+    int pos=(int)data;
+    vfo_step(pos);
   }
-  free(data);
+  //free(data);
   return 0;
 }
 
-static int e1_encoder_changed(void *data) {
-  int pos=*(int*)data;
-  if(pos!=0) {
-    if(function || isTransmitting()) {
-      // mic gain
-      double gain=mic_gain;
+static encoder_changed(int action,int pos) {
+  double value;
+  switch(action) {
+    case ENCODER_AF_GAIN:
+      value=active_receiver->volume;
+      value+=(double)pos/100.0;
+      if(value<0.0) {
+        value=0.0;
+      } else if(value>1.0) {
+        value=1.0;
+      }
+      set_af_gain(value);
+      break;
+    case ENCODER_AGC_GAIN:
+      value=active_receiver->agc_gain;
+      value+=(double)pos;
+      if(value<-20.0) {
+        value=-20.0;
+      } else if(value>120.0) {
+        value=120.0;
+      }
+      set_agc_gain(value);
+      break;
+    case ENCODER_ATTENUATION:
+      value=active_receiver->attenuation;
+      value+=pos;
+      if(value<0) {
+        value=0;
+      } else if (value>31) {
+        value=31;
+      }
+      set_attenuation_value(value);
+      break;
+    case ENCODER_MIC_GAIN:
+      value=mic_gain;
       //gain+=(double)pos/100.0;
-      gain+=(double)pos;
-      if(gain<-10.0) {
-        gain=-10.0;
-      } else if(gain>50.0) {
-        gain=50.0;
+      value+=(double)pos;
+      if(value<-10.0) {
+        value=-10.0;
+      } else if(value>50.0) {
+        value=50.0;
       }
-      set_mic_gain(gain);
-    } else {
-      // af gain
-      double gain=volume;
-      gain+=(double)pos/100.0;
-      if(gain<0.0) {
-        gain=0.0;
-      } else if(gain>1.0) {
-        gain=1.0;
+      set_mic_gain(value);
+      break;
+    case ENCODER_DRIVE:
+      value=getDrive();
+      value+=(double)pos;
+      if(value<0.0) {
+        value=0.0;
+      } else if(value>100.0) {
+        value=100.0;
       }
-      set_af_gain(gain);
-    }
-  }
-  free(data);
-  return 0;
-}
-
-static int e2_encoder_changed(void *data) {
-  int pos=*(int*)data;
-  if(pos!=0) {
-    if(function || tune) {
-      // tune drive
-      double d=getTuneDrive();
-      d+=(double)pos;
-      if(d<0.0) {
-        d=0.0;
-      } else if(d>100.0) {
-        d=100.0;
+      set_drive(value);
+      break;
+    case ENCODER_TUNE_DRIVE:
+      value=getTuneDrive();
+      value+=(double)pos;
+      if(value<0.0) {
+        value=0.0;
+      } else if(value>100.0) {
+        value=100.0;
       }
-      set_tune(d);
-    } else {
-      // drive
-      double d=getDrive();
-      d+=(double)pos;
-      if(d<0.0) {
-        d=0.0;
-      } else if(d>100.0) {
-        d=100.0;
+      set_tune(value);
+      break;
+    case ENCODER_RIT:
+      value=(double)vfo[active_receiver->id].rit;
+      value+=(double)(pos*rit_increment);
+      if(value<-1000.0) {
+        value=-1000.0;
+      } else if(value>1000.0) {
+        value=1000.0;
       }
-      set_drive(d);
-    }
-  }
-  free(data);
-  return 0;
-}
-
-static int e3_encoder_changed(void *data) {
-  int pos=*(int*)data;
-  if(pos!=0) {
-    if(function) {
-      int att=attenuation;
-      att+=pos;
-      if(att<0) {
-        att=0;
-      } else if (att>31) {
-        att=31;
+      vfo[active_receiver->id].rit=(int)value;
+      vfo_update(NULL);
+      break;
+    case ENCODER_CW_SPEED:
+      value=(double)cw_keyer_speed;
+      value+=(double)pos;
+      if(value<1.0) {
+        value=1.0;
+      } else if(value>60.0) {
+        value=60.0;
       }
-      set_attenuation_value((double)att);
-    } else {
-      double gain=agc_gain;
-      gain+=(double)pos;
-      if(gain<-20.0) {
-        gain=-20.0;
-      } else if(gain>120.0) {
-        gain=120.0;
+      cw_keyer_speed=(int)value;
+      vfo_update(NULL);
+      break;
+    case ENCODER_CW_FREQUENCY:
+      value=(double)cw_keyer_sidetone_frequency;
+      value+=(double)pos;
+      if(value<0.0) {
+        value=0.0;
+      } else if(value>1000.0) {
+        value=1000.0;
       }
-      set_agc_gain(gain);
-    }
+      cw_keyer_sidetone_frequency=(int)value;
+      vfo_update(NULL);
+      break;
+    case ENCODER_PANADAPTER_HIGH:
+      value=(double)active_receiver->panadapter_high;
+      value+=(double)pos;
+      active_receiver->panadapter_high=(int)value;
+      break;
+    case ENCODER_PANADAPTER_LOW:
+      value=(double)active_receiver->panadapter_low;
+      value+=(double)pos;
+      active_receiver->panadapter_low=(int)value;
+      break;
   }
-  return 0;
-}
-
-static int band_pressed(void *data) {
-  sim_s1_pressed_cb(NULL,NULL);
-  return 0;
-}
-
-static int band_released(void *data) {
-  sim_s1_released_cb(NULL,NULL);
-  return 0;
-}
-
-static int bandstack_pressed(void *data) {
-  sim_s2_pressed_cb(NULL,NULL);
-  return 0;
 }
 
-static int bandstack_released(void *data) {
-  sim_s2_released_cb(NULL,NULL);
-  return 0;
-}
-
-static int function_pressed(void *data) {
-  sim_function_cb(NULL,NULL);
-  return 0;
-}
-
-static int mox_pressed(void *data) {
-  sim_mox_cb(NULL,NULL);
-  return 0;
-}
-
-static int lock_pressed(void *data) {
-  lock_cb((GtkWidget *)NULL, (gpointer)NULL);
+static int e1_encoder_changed(void *data) {
+  int pos=(int)data;
+  if(active_menu==E1_MENU) {
+    encoder_select(pos);
+  } else {
+    encoder_changed(e1_encoder_action,pos);
+  }
+  //free(data);
   return 0;
 }
 
-static int mode_pressed(void *data) {
-  sim_s3_cb(NULL,NULL);
+static int e2_encoder_changed(void *data) {
+  int pos=(int)data;
+  if(active_menu==E2_MENU) {
+    encoder_select(pos);
+  } else {
+    encoder_changed(e2_encoder_action,pos);
+  }
+  //free(data);
   return 0;
 }
 
-static int filter_pressed(void *data) {
-  sim_s4_cb(NULL,NULL);
+static int e3_encoder_changed(void *data) {
+  int pos=(int)data;
+  if(active_menu==E3_MENU) {
+    encoder_select(pos);
+  } else {
+    encoder_changed(e3_encoder_action,pos);
+  }
+  //free(data);
   return 0;
 }
 
-static int noise_pressed(void *data) {
-  sim_s5_cb(NULL,NULL);
-  return 0;
-}
+static gpointer rotary_encoder_thread(gpointer data) {
+    int pos;
 
-static int agc_pressed(void *data) {
-  sim_s6_cb(NULL,NULL);
-  return 0;
-}
+    // ignore startup glitches
+    sleep(2);
 
-static void* rotary_encoder_thread(void *arg) {
-    int pos;
+    //g_mutex_lock(&m_running);
     running=1;
-    while(running) {
-
-        int function_button=function_get_state();
-        if(function_button!=previous_function_button) {
-            previous_function_button=function_button;
-            if(function_button) {
-                g_idle_add(function_pressed,(gpointer)NULL);
-            }
-        }
+    //g_mutex_unlock(&m_running);
+    while(1) {
 
         pos=vfo_encoder_get_pos();
         if(pos!=0) {
-            int *p=malloc(sizeof(int));
-            *p=pos;
-            g_idle_add(vfo_encoder_changed,(gpointer)p);
+            g_idle_add(vfo_encoder_changed,(gpointer)pos);
         }
 
-/*
-        e1_function=e1_function_get_state();
-        if(e1_function!=previous_e1_function) {
-            previous_e1_function=e1_function;
-        }
-*/
         pos=e1_encoder_get_pos();
         if(pos!=0) {
-            int *p=malloc(sizeof(int));
-            *p=pos;
-            g_idle_add(e1_encoder_changed,(gpointer)p);
+            g_idle_add(e1_encoder_changed,(gpointer)pos);
         }
 
-/*
-        e2_function=e2_function_get_state();
-        if(e2_function!=previous_e2_function) {
-            previous_e2_function=e2_function;
-        }
-*/
         pos=e2_encoder_get_pos();
         if(pos!=0) {
-            int *p=malloc(sizeof(int));
-            *p=pos;
-            g_idle_add(e2_encoder_changed,(gpointer)p);
+            g_idle_add(e2_encoder_changed,(gpointer)pos);
         }
 
         pos=e3_encoder_get_pos();
         if(pos!=0) {
-            int *p=malloc(sizeof(int));
-            *p=pos;
-            g_idle_add(e3_encoder_changed,(gpointer)p);
-        }
-
-
-        int band_button=band_get_state();
-        if(band_button!=previous_band_button) {
-            previous_band_button=band_button;
-            if(band_button) {
-                g_idle_add(band_pressed,(gpointer)NULL);
-            } else {
-                g_idle_add(band_released,(gpointer)NULL);
-            }
-        }
-
-        int bandstack_button=bandstack_get_state();
-        if(bandstack_button!=previous_bandstack_button) {
-            previous_bandstack_button=bandstack_button;
-            if(bandstack_button) {
-                g_idle_add(bandstack_pressed,(gpointer)NULL);
-            } else {
-                g_idle_add(bandstack_released,(gpointer)NULL);
-            }
-        }
-
-        int mode_button=mode_get_state();
-        if(mode_button!=previous_mode_button) {
-            previous_mode_button=mode_button;
-            if(mode_button) {
-                g_idle_add(mode_pressed,(gpointer)NULL);
-            }
-        }
-
-        int filter_button=filter_get_state();
-        if(filter_button!=previous_filter_button) {
-            previous_filter_button=filter_button;
-            if(filter_button) {
-                g_idle_add(filter_pressed,(gpointer)NULL);
-            }
-        }
-
-        int noise_button=noise_get_state();
-        if(noise_button!=previous_noise_button) {
-            previous_noise_button=noise_button;
-            if(noise_button) {
-                g_idle_add(noise_pressed,(gpointer)NULL);
-            }
-        }
-
-        int agc_button=agc_get_state();
-        if(agc_button!=previous_agc_button) {
-            previous_agc_button=agc_button;
-            if(agc_button) {
-                g_idle_add(agc_pressed,(gpointer)NULL);
-            }
-        }
-
-        int mox_button=mox_get_state();
-        if(mox_button!=previous_mox_button) {
-            previous_mox_button=mox_button;
-            if(mox_button) {
-                g_idle_add(mox_pressed,(gpointer)NULL);
-            }
-        }
-
-        int lock_button=lock_get_state();
-        if(lock_button!=previous_lock_button) {
-            previous_lock_button=lock_button;
-            if(lock_button) {
-                g_idle_add(lock_pressed,(gpointer)NULL);
-            }
+            g_idle_add(e3_encoder_changed,(gpointer)pos);
         }
 
 #ifdef sx1509
         // buttons only generate interrupt when
-        // pushed on, so clear them now
+        // pushed onODER_AF_GAIN = 0,
         function_state = 0;
         band_state = 0;
         bandstack_state = 0;
@@ -1246,16 +1334,23 @@ static void* rotary_encoder_thread(void *arg) {
         mox_state = 0;
         lock_state = 0;
 #endif
-
-#ifdef raspberrypi
-          if(running) gpioDelay(100000); // 10 per second
+//fprintf(stderr,"gpio_thread: lock\n");
+        //g_mutex_lock(&m_running);
+        if(running==0) {
+fprintf(stderr,"gpio_thread: unlock (running==0)\n");
+          //g_mutex_unlock(&m_running);
+          g_thread_exit(NULL);
+        }
+#ifdef GPIO
+        usleep(100000);
+        //gpioDelay(100000); // 10 per second
 #endif
 #ifdef odroid
-          if(running) usleep(100000);
+        usleep(100000);
 #endif
+//fprintf(stderr,"gpio_thread: unlock (running==1)\n");
+        //g_mutex_unlock(&m_running);
     }
-#ifdef raspberrypi
-    gpioTerminate();
-#endif
+    return NULL;
 }
 #endif
diff --git a/gpio.h b/gpio.h
index cb8fcf32da80281b102cc0d4d3dd9cbf6d06b3e6..fb60859d83424c0c5c2789772288c012a56c0ecc 100644 (file)
--- a/gpio.h
+++ b/gpio.h
 #ifndef _GPIO_H
 #define _GPIO_H
 
+enum {
+  ENCODER_AF_GAIN=0,
+  ENCODER_AGC_GAIN,
+  ENCODER_ATTENUATION,
+  ENCODER_MIC_GAIN,
+  ENCODER_DRIVE,
+  ENCODER_TUNE_DRIVE,
+  ENCODER_RIT,
+  ENCODER_CW_SPEED,
+  ENCODER_CW_FREQUENCY,
+  ENCODER_PANADAPTER_HIGH,
+  ENCODER_PANADAPTER_LOW
+};
+
+
+#define ENCODER_LAST ENCODER_PANADAPTER_LOW
+
+extern char *encoder_string[ENCODER_LAST+1];
+
+extern int e1_encoder_action;
+extern int e2_encoder_action;
+extern int e3_encoder_action;
+
 extern int ENABLE_VFO_ENCODER;
 extern int ENABLE_VFO_PULLUP;
 extern int VFO_ENCODER_A;
index 45c8f9c4a8dc4fc6f9697f05316dfc319a41224e..8b054aef2847cbfdc2f616a693f0683d834998d6 100644 (file)
@@ -771,9 +771,9 @@ static int vfo_encoder_changed(void *data) {
   if(!locked) {
     int pos=*(int*)data;
     BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
-    //entry->frequencyA=entry->frequencyA+(pos*step);
-    //setFrequency(entry->frequencyA);
-    setFrequency(entry->frequencyA+ddsOffset+(pos*step));
+    //entry->frequency=entry->frequency+(pos*step);
+    //setFrequency(entry->frequency);
+    setFrequency(entry->frequency+ddsOffset+(pos*step));
     vfo_update(NULL);
   }
   free(data);
diff --git a/i2c.c b/i2c.c
new file mode 100644 (file)
index 0000000..d33dbec
--- /dev/null
+++ b/i2c.c
@@ -0,0 +1,258 @@
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <linux/i2c-dev.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <pthread.h>
+
+#include <gtk/gtk.h>
+#include "i2c.h"
+#include "band.h"
+#include "band_menu.h"
+#include "bandstack.h"
+#include "radio.h"
+#include "toolbar.h"
+#include "vfo.h"
+
+#define I2C_DEVICE "/dev/i2c-1"
+#define ADDRESS_1 0X20
+#define ADDRESS_2 0X23
+
+//static pthread_t i2c_thread_id;
+static GThread *i2c_thread_id;
+
+static int write_byte_data(unsigned char addr,unsigned char reg, unsigned char data) {
+  int fd;
+  int rc;
+
+  if((fd=open(I2C_DEVICE, O_RDWR))<0) {
+    fprintf(stderr,"cannot open %s: %s\n",I2C_DEVICE,strerror(errno));
+    return(-1);
+  }
+
+  if(ioctl(fd,I2C_SLAVE,addr)<0) {
+    fprintf(stderr,"cannot aquire access to I2C device at 0x%02X\n",addr);
+    return(-1);
+  }
+
+  rc=i2c_smbus_write_byte_data(fd,reg,data);
+  if(rc<0) {
+    fprintf(stderr,"i2c_smbus_write_byte_data failed: device=%02X 0x%02X to 0x%02X: %s\n",addr,data,reg,strerror(errno));
+    return(-1);
+  }
+
+  close(fd);
+  
+  return 0;
+}
+
+static unsigned char read_byte_data(unsigned char addr,unsigned char reg) {
+  int fd;
+  int rc;
+
+  if((fd=open(I2C_DEVICE, O_RDWR))<0) {
+    fprintf(stderr,"c$cannot open %s: %s\n",I2C_DEVICE,strerror(errno));
+    exit(1);
+  }
+
+  if(ioctl(fd,I2C_SLAVE,addr)<0) {
+    fprintf(stderr,"cannot aquire access to I2C device at 0x%x\n",addr);
+    exit(1);
+  }
+
+  rc=i2c_smbus_read_byte_data(fd,reg);
+  if(rc<0) {
+    fprintf(stderr,"i2c_smbus_read_byte_data failed: 0x%2X: %s\n",reg,strerror(errno));
+    exit(1);
+  }
+
+  close(fd);
+
+  return rc;
+}
+
+static void frequencyStep(int pos) {
+  BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
+  setFrequency(entry->frequency+ddsOffset+(pos*step));
+  vfo_update(NULL);
+}
+
+static void *i2c_thread(void *arg) {
+  int rc_1_a;
+  int rc_1_b;
+  int prev_rc_1_a=0;
+  int prev_rc_1_b=0;
+  int rc_2_a;
+  int rc_2_b;
+  int prev_rc_2_a=0;
+  int prev_rc_2_b=0;
+
+  while(1) {
+    rc_1_a=read_byte_data(ADDRESS_1,0x12);
+    if(rc_1_a!=0 && rc_1_a!=prev_rc_1_a) {
+      fprintf(stderr,"Dev 1: GPIOA: 0x%02X\n",rc_1_a);
+      switch(rc_1_a) {
+        case 0x01:
+          g_idle_add(band_update,(void *)band160);
+          break;
+        case 0x02:
+          g_idle_add(band_update,(void *)band80);
+          break;
+        case 0x04:
+          g_idle_add(band_update,(void *)band60);
+          break;
+        case 0x08:
+          g_idle_add(band_update,(void *)band40);
+          break;
+        case 0x10:
+          g_idle_add(band_update,(void *)band30);
+          break;
+        case 0x20:
+          g_idle_add(band_update,(void *)band20);
+          break;
+        case 0x40:
+          g_idle_add(band_update,(void *)band17);
+          break;
+        case 0x80:
+          g_idle_add(band_update,(void *)band15);
+          break;
+      }
+    }
+    prev_rc_1_a=rc_1_a;
+
+    rc_1_b=read_byte_data(ADDRESS_1,0x13);
+    if(rc_1_b!=0 && rc_1_b!=prev_rc_1_b) {
+      fprintf(stderr,"Dev 1: GPIOB: 0x%02X\n",rc_1_b);
+      switch(rc_1_b) {
+        case 0x01:
+          g_idle_add(band_update,(void *)band12);
+          break;
+        case 0x02:
+          g_idle_add(band_update,(void *)band10);
+          break;
+        case 0x04:
+          g_idle_add(band_update,(void *)band6);
+          break;
+        case 0x08:
+          g_idle_add(band_update,(void *)bandGen);
+          break;
+        case 0x10:
+          frequencyStep(+1);
+          break;
+        case 0x20:
+          break;
+        case 0x40:
+          break;
+        case 0x80:
+          frequencyStep(-1);
+          break;
+      }
+    }
+    prev_rc_1_b=rc_1_b;
+
+    rc_2_a=read_byte_data(ADDRESS_2,0x12);
+    if(rc_2_a!=0 && rc_2_a!=prev_rc_2_a) {
+      fprintf(stderr,"Dev 2: GPIOA: 0x%02X\n",rc_2_a);
+      switch(rc_2_a) {
+        case 0x01:
+          break;
+        case 0x02:
+          mox_cb(NULL,NULL);
+          break;
+        case 0x04:
+          tune_cb(NULL,NULL);
+          break;
+        case 0x08:
+          break;
+        case 0x10:
+          break;
+        case 0x20:
+          break;
+        case 0x40:
+          break;
+        case 0x80:
+          break;
+      }
+    }
+    prev_rc_2_a=rc_2_a;
+
+    rc_2_b=read_byte_data(ADDRESS_2,0x13);
+    if(rc_2_b!=0 && rc_2_b!=prev_rc_2_b) {
+      fprintf(stderr,"Dev 2: GPIOB: 0x%02X\n",rc_2_b);
+      switch(rc_2_b) {
+        case 0x01:
+          break;
+        case 0x02:
+          break;
+        case 0x04:
+          break;
+        case 0x08:
+          break;
+        case 0x10:
+          break;
+        case 0x20:
+          break;
+        case 0x40:
+          break;
+        case 0x80:
+          break;
+      }
+    }
+    prev_rc_2_b=rc_2_b;
+
+    usleep(200);
+  }
+
+}
+
+void i2c_init() {
+
+fprintf(stderr,"i2c_init\n");
+  // setup i2c
+  if(write_byte_data(ADDRESS_1,0x0A,0x22)<0) return;
+
+  // set GPIOA/B for input
+  if(write_byte_data(ADDRESS_1,0x00,0xFF)<0) return;
+  if(write_byte_data(ADDRESS_1,0x01,0xFF)<0) return;
+
+  // set GPIOA for pullups
+  if(write_byte_data(ADDRESS_1,0x0C,0xFF)<0) return;
+  if(write_byte_data(ADDRESS_1,0x0D,0xFF)<0) return;
+
+  // reverse polarity
+  if(write_byte_data(ADDRESS_1,0x02,0xFF)<0) return;
+  if(write_byte_data(ADDRESS_1,0x03,0xFF)<0) return;
+
+  // setup i2c
+  if(write_byte_data(ADDRESS_2,0x0A,0x22)<0) return;
+
+  // set GPIOA/B for input
+  if(write_byte_data(ADDRESS_2,0x00,0xFF)<0) return;
+  if(write_byte_data(ADDRESS_2,0x01,0xFF)<0) return;
+
+  // set GPIOA for pullups
+  if(write_byte_data(ADDRESS_2,0x0C,0xFF)<0) return;
+  if(write_byte_data(ADDRESS_2,0x0D,0xFF)<0) return;
+
+  // reverse polarity
+  if(write_byte_data(ADDRESS_2,0x02,0xFF)<0) return;
+  if(write_byte_data(ADDRESS_2,0x03,0xFF)<0) return;
+
+/*
+  int rc;
+  rc=pthread_create(&i2c_thread_id,NULL,i2c_thread,NULL);
+  if(rc != 0) {
+    fprintf(stderr,"i2c_init: pthread_create failed on i2c_thread: rc=%d\n", rc);
+  }
+*/
+  i2c_thread_id = g_thread_new( "i2c", i2c_thread, NULL);
+  if( ! i2c_thread_id )
+  {
+    fprintf(stderr,"g_thread_new failed on i2c_thread\n");
+  }
+
+
+}
diff --git a/i2c.h b/i2c.h
new file mode 100644 (file)
index 0000000..14ec886
--- /dev/null
+++ b/i2c.h
@@ -0,0 +1,2 @@
+
+void i2c_init();
diff --git a/libusbio.c b/libusbio.c
new file mode 100644 (file)
index 0000000..0f52c6b
--- /dev/null
@@ -0,0 +1,99 @@
+/* 
+ * File:   libusbio.c
+ * Author: jm57878
+ *
+ * Created on 18 February 2009, 21:16
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <libusb-1.0/libusb.h>
+
+#include "libusbio.h"
+
+/*
+ *  interface to libusb1.0
+ */
+
+#define OZY_PID (0x0007)
+#define OZY_VID (0xfffe)
+
+#define VRQ_SDR1K_CTL 0x0d
+#define SDR1KCTRL_READ_VERSION  0x7
+#define VRT_VENDOR_IN 0xC0
+
+#define OZY_IO_TIMEOUT 500
+
+static int init=0;
+static libusb_device_handle* ozy_handle;
+static libusb_context* context;
+
+int libusb_open_ozy(void) {
+    int rc;
+
+fprintf(stderr,"libusb_open_ozy\n");
+
+    if(init==0) {
+        rc=libusb_init(NULL);
+        if(rc<0) {
+            fprintf(stderr,"libusb_init failed: %d\n",rc);
+            return rc;
+        }
+        init=1;
+    }
+
+    ozy_handle=libusb_open_device_with_vid_pid(NULL, OZY_VID, OZY_PID);
+    if(ozy_handle==NULL) {
+        fprintf(stderr,"libusbio: cannot find ozy device\n");
+        return -1;
+    }
+
+    rc=libusb_claim_interface(ozy_handle,0);
+    if(rc<0) {
+        fprintf(stderr,"libusb_claim_interface failed: %d\n",rc);
+        return rc;
+    }
+
+fprintf(stderr,"libusb_open_ozy: SUCCESS\n");
+    return 0;
+
+}
+
+void libusb_close_ozy() {
+    libusb_close(ozy_handle);
+}
+
+int libusb_get_ozy_firmware_string(char* buffer,int buffersize) {
+    int rc;
+    rc=libusb_control_transfer(ozy_handle, VRT_VENDOR_IN, VRQ_SDR1K_CTL, SDR1KCTRL_READ_VERSION, 0, buffer, buffersize, OZY_IO_TIMEOUT);
+    if(rc<0) {
+        fprintf(stderr,"libusb_get_ozy_firmware failed: %d\n",rc);
+        return rc;
+    }
+    buffer[rc]=0x00;
+    return 0;
+}
+
+int libusb_write_ozy(int ep,void* buffer,int buffersize)
+{
+       int rc;
+        int bytes;
+       rc = libusb_bulk_transfer(ozy_handle, (unsigned char)ep, (unsigned char *)buffer, buffersize,&bytes, OZY_IO_TIMEOUT);
+        if(rc==0) {
+            rc=bytes;
+        }
+        return rc;
+}
+
+
+int  libusb_read_ozy(int ep,void* buffer,int buffersize)
+{
+       int rc;
+        int bytes;
+       rc = libusb_bulk_transfer(ozy_handle, (unsigned char)ep, (unsigned char *)buffer, buffersize,&bytes, OZY_IO_TIMEOUT);
+        if(rc==0) {
+            rc=bytes;
+        }
+       return rc;
+}
diff --git a/libusbio.h b/libusbio.h
new file mode 100644 (file)
index 0000000..eb3660b
--- /dev/null
@@ -0,0 +1,19 @@
+/** 
+* @file libusbio.h
+* @brief Header file for the USB I/O functions, interface to libusb1.0
+* @author 
+* @version 0.1
+* @date 2009-05-18
+*/
+
+#ifndef _LIBUSBIO_H
+#define _LIBUSBIO_H
+
+int libusb_open_ozy(void);
+void libusb_close_ozy();
+int libusb_get_ozy_firmware_string(char* buffer,int buffersize);
+int libusb_write_ozy(int ep,void* buffer,int buffersize);
+int libusb_read_ozy(int ep,void* buffer,int buffersize);
+
+#endif /* _LIBUSBIO_H */
+
diff --git a/main.c b/main.c
index c0fd576e9c308096173353ff18e58eaa59cba888..d340d05ec76bf9f66ea0a43060707c0b95629530 100644 (file)
--- a/main.c
+++ b/main.c
 #include <arpa/inet.h>
 
 #include "audio.h"
+#include "band.h"
+#include "bandstack.h"
 #include "main.h"
 #include "channel.h"
 #include "discovered.h"
 #include "configure.h"
 #include "gpio.h"
-#include "old_discovery.h"
-#include "new_discovery.h"
-#ifdef LIMESDR
-#include "lime_discovery.h"
-#endif
-#include "old_protocol.h"
-#include "new_protocol.h"
-#ifdef LIMESDR
-#include "lime_protocol.h"
-#endif
 #include "wdsp.h"
-#include "vfo.h"
-//#include "menu.h"
 #include "new_menu.h"
-#include "rit.h"
-#include "meter.h"
-#include "panadapter.h"
-#include "splash.h"
-#include "waterfall.h"
-#include "toolbar.h"
-#include "sliders.h"
 #include "radio.h"
-#include "rigctl.h"
-#include "wdsp_init.h"
 #include "version.h"
-#include "mode.h"
-#ifdef PSK
-#include "psk.h"
-#include "psk_waterfall.h"
-#endif
-
-#define DISPLAY_INCREMENT (display_height/32)
-#define VFO_HEIGHT (DISPLAY_INCREMENT*4)
-//#define VFO_HEIGHT (DISPLAY_INCREMENT*8)
-#define VFO_WIDTH ((display_width/32)*21)
-#define MENU_HEIGHT VFO_HEIGHT
-//#define MENU_HEIGHT (DISPLAY_INCREMENT*4)
-#define MENU_WIDTH ((display_width/32)*3)
-//#define RIT_WIDTH ((MENU_WIDTH/3)*2)
-#define METER_HEIGHT VFO_HEIGHT
-//#define METER_HEIGHT (DISPLAY_INCREMENT*4)
-#define METER_WIDTH ((display_width/32)*8)
-#define PANADAPTER_HEIGHT (DISPLAY_INCREMENT*8)
-#define SLIDERS_HEIGHT (DISPLAY_INCREMENT*6)
-#define TOOLBAR_HEIGHT (DISPLAY_INCREMENT*2)
-#define WATERFALL_HEIGHT (display_height-(VFO_HEIGHT+PANADAPTER_HEIGHT+SLIDERS_HEIGHT+TOOLBAR_HEIGHT))
-#ifdef PSK
-#define PSK_WATERFALL_HEIGHT (DISPLAY_INCREMENT*6)
-#define PSK_HEIGHT (display_height-(VFO_HEIGHT+PSK_WATERFALL_HEIGHT+SLIDERS_HEIGHT+TOOLBAR_HEIGHT))
+#include "button_text.h"
+#ifdef I2C
+#include "i2c.h"
 #endif
+#include "discovery.h"
 
 struct utsname unameData;
 
@@ -91,12 +52,6 @@ gint display_width;
 gint display_height;
 gint full_screen=1;
 
-static gint update_timer_id;
-
-static gint save_timer_id;
-
-static float *samples;
-
 static GtkWidget *discovery_dialog;
 
 static sem_t wisdom_sem;
@@ -104,189 +59,21 @@ static sem_t wisdom_sem;
 static GdkCursor *cursor_arrow;
 static GdkCursor *cursor_watch;
 
-static GdkWindow *splash_window;
-
-static GtkWidget *window;
-static GtkWidget *grid;
-static GtkWidget *fixed;
-static GtkWidget *vfo;
-static GtkWidget *rit_control;
-static GtkWidget *menu;
-static GtkWidget *meter;
-static GtkWidget *sliders;
-static GtkWidget *toolbar;
-static GtkWidget *panadapter;
-static GtkWidget *waterfall;
-#ifdef PSK
-static GtkWidget *psk;
-static GtkWidget *psk_waterfall;
-#endif
+static GtkWidget *splash;
+
+GtkWidget *top_window;
+GtkWidget *grid;
 
 static DISCOVERED* d;
 
-static void start_radio();
-static void discover_devices();
-
-gint update(gpointer data) {
-    int result;
-    double fwd;
-    double rev;
-    double exciter;
-    int channel=CHANNEL_RX0;
-#ifdef PSK
-    if(mode==modePSK) {
-      channel=CHANNEL_PSK;
-    }
-#endif
-    if(isTransmitting()) {
-      channel=CHANNEL_TX;
-    }
-    GetPixels(channel,0,samples,&result);
-    if(result==1) {
-        if(display_panadapter) {
-#ifdef PSK
-          if(mode==modePSK) {
-            psk_waterfall_update(samples);
-          } else {
-#endif
-            panadapter_update(samples,isTransmitting());
-#ifdef PSK
-          }
-#endif
-        }
-        if(!isTransmitting()) {
-#ifdef PSK
-          if(mode!=modePSK) {
-#endif
-            if(display_waterfall) {
-              waterfall_update(samples);
-            }
-#ifdef PSK
-          }
-#endif
-        }
-    }
-
-    if(!isTransmitting()) {
-        double m;
-        switch(mode) {
-#ifdef PSK
-            case modePSK:
-                m=(double)psk_get_signal_level();
-                meter_update(PSKMETER,m,0.0,0.0,0.0);
-                break;
-#endif
-            default:
-                m=GetRXAMeter(CHANNEL_RX0, smeter);
-                meter_update(SMETER,m,0.0,0.0,0.0);
-                break;
-        }
-    } else {
-
-        double alc=GetTXAMeter(CHANNEL_TX, alc);
-
-        DISCOVERED *d=&discovered[selected_device];
-
-        double constant1=3.3;
-        double constant2=0.095;
-
-        if(d->protocol==ORIGINAL_PROTOCOL) {
-            switch(d->device) {
-                case DEVICE_METIS:
-                    constant1=3.3;
-                    constant2=0.09;
-                    break;
-                case DEVICE_HERMES:
-                    constant1=3.3;
-                    constant2=0.095;
-                    break;
-                case DEVICE_ANGELIA:
-                    constant1=3.3;
-                    constant2=0.095;
-                    break;
-                case DEVICE_ORION:
-                    constant1=5.0;
-                    constant2=0.108;
-                    break;
-                case DEVICE_HERMES_LITE:
-                    break;
-            }
-
-            int power=alex_forward_power;
-            if(power==0) {
-                power=exciter_power;
-            }
-            double v1;
-            v1=((double)power/4095.0)*constant1;
-            fwd=(v1*v1)/constant2;
-
-            power=exciter_power;
-            v1=((double)power/4095.0)*constant1;
-            exciter=(v1*v1)/constant2;
-
-            rev=0.0;
-            if(alex_forward_power!=0) {
-                power=alex_reverse_power;
-                v1=((double)power/4095.0)*constant1;
-                rev=(v1*v1)/constant2;
-            }
-         
-        } else {
-            switch(d->device) {
-                case NEW_DEVICE_ATLAS:
-                    constant1=3.3;
-                    constant2=0.09;
-                    break;
-                case NEW_DEVICE_HERMES:
-                    constant1=3.3;
-                    constant2=0.09;
-                    break;
-                case NEW_DEVICE_HERMES2:
-                    constant1=3.3;
-                    constant2=0.095;
-                    break;
-                case NEW_DEVICE_ANGELIA:
-                    constant1=3.3;
-                    constant2=0.095;
-                    break;
-                case NEW_DEVICE_ORION:
-                    constant1=5.0;
-                    constant2=0.108;
-                    break;
-                case NEW_DEVICE_ORION2:
-                    constant1=5.0;
-                    constant2=0.108;
-                    break;
-                case NEW_DEVICE_HERMES_LITE:
-                    constant1=3.3;
-                    constant2=0.09;
-                    break;
-            }
-        
-            int power=alex_forward_power;
-            if(power==0) {
-                power=exciter_power;
-            }
-            double v1;
-            v1=((double)power/4095.0)*constant1;
-            fwd=(v1*v1)/constant2;
-
-            power=exciter_power;
-            v1=((double)power/4095.0)*constant1;
-            exciter=(v1*v1)/constant2;
-
-            rev=0.0;
-            if(alex_forward_power!=0) {
-                power=alex_reverse_power;
-                v1=((double)power/4095.0)*constant1;
-                rev=(v1*v1)/constant2;
-            }
-        }
-
-        meter_update(POWER,fwd,rev,exciter,alc);
-    }
+static GtkWidget *status;
 
-    return TRUE;
+void status_text(char *text) {
+  //fprintf(stderr,"splash_status: %s\n",text);
+  gtk_label_set_text(GTK_LABEL(status),text);
+  usleep(10000);
+  while (gtk_events_pending ())
+    gtk_main_iteration ();
 }
 
 static gint save_cb(gpointer data) {
@@ -297,7 +84,7 @@ static gint save_cb(gpointer data) {
 static pthread_t wisdom_thread_id;
 
 static void* wisdom_thread(void *arg) {
-  splash_status("Creating FFTW Wisdom file ...");
+  status_text("Creating FFTW Wisdom file ...");
   WDSPwisdom ((char *)arg);
   sem_post(&wisdom_sem);
 }
@@ -323,620 +110,45 @@ gboolean main_delete (GtkWidget *widget) {
   _exit(0);
 }
 
-static gboolean start_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
-fprintf(stderr,"start_cb: %p\n",data);
-  radio=(DISCOVERED *)data;
-  gtk_widget_destroy(discovery_dialog);
-  start_radio();
-  return TRUE;
-}
-
-#ifdef GPIO
-static gboolean gpio_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
-  configure_gpio(discovery_dialog);
-  return TRUE;
-}
-#endif
-
-static gboolean discover_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
-  gtk_widget_destroy(discovery_dialog);
-  discover_devices();
-  return TRUE;
-}
-
-static gboolean exit_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
-  gtk_widget_destroy(discovery_dialog);
-  _exit(0);
-  return TRUE;
-}
-
-static void discover_devices() {
-
-      gdk_window_set_cursor(splash_window,cursor_watch);
-      selected_device=0;
-      devices=0;
-      splash_status("Old Protocol ... Discovering Devices");
-      old_discovery();
-      splash_status("New Protocol ... Discovering Devices");
-      new_discovery();
-#ifdef LIMESDR
-      splash_status("LimeSDR ... Discovering Devices");
-      lime_discovery();
-#endif
-      splash_status("Discovery");
-      if(devices==0) {
-          gdk_window_set_cursor(splash_window,cursor_arrow);
-          fprintf(stderr,"No devices found!\n");
-          GtkDialogFlags flags = GTK_DIALOG_DESTROY_WITH_PARENT;
-/*
-          discovery_dialog = gtk_message_dialog_new (GTK_WINDOW(splash_screen),
-                                 flags,
-                                 GTK_MESSAGE_ERROR,
-                                 GTK_BUTTONS_OK_CANCEL,
-                                 "No devices found! Retry Discovery?");
-*/
-          discovery_dialog = gtk_dialog_new();
-          gtk_window_set_transient_for(GTK_WINDOW(discovery_dialog),GTK_WINDOW(splash_screen));
-          gtk_window_set_decorated(GTK_WINDOW(discovery_dialog),FALSE);
-
-          gtk_widget_override_font(discovery_dialog, pango_font_description_from_string("FreeMono 16"));
-
-          GdkRGBA color;
-          color.red = 1.0;
-          color.green = 1.0;
-          color.blue = 1.0;
-          color.alpha = 1.0;
-          gtk_widget_override_background_color(discovery_dialog,GTK_STATE_FLAG_NORMAL,&color);
-
-          GtkWidget *content;
-
-          content=gtk_dialog_get_content_area(GTK_DIALOG(discovery_dialog));
-
-          GtkWidget *grid=gtk_grid_new();
-          gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
-          gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
-          gtk_grid_set_row_spacing (GTK_GRID(grid),10);
-
-          GtkWidget *label=gtk_label_new("No devices found!");
-          gtk_grid_attach(GTK_GRID(grid),label,0,0,2,1);
-
-          GtkWidget *exit_b=gtk_button_new_with_label("Exit");
-          g_signal_connect (exit_b, "button-press-event", G_CALLBACK(exit_cb), NULL);
-          gtk_grid_attach(GTK_GRID(grid),exit_b,0,1,1,1);
-
-          GtkWidget *discover_b=gtk_button_new_with_label("Retry Discovery");
-          g_signal_connect (discover_b, "button-press-event", G_CALLBACK(discover_cb), NULL);
-          gtk_grid_attach(GTK_GRID(grid),discover_b,1,1,1,1);
-
-          gtk_container_add (GTK_CONTAINER (content), grid);
-          gtk_widget_show_all(discovery_dialog);
-      } else {
-          //fprintf(stderr,"%s: found %d devices.\n", (char *)arg, devices);
-          gdk_window_set_cursor(splash_window,cursor_arrow);
-/*
-          GtkDialogFlags flags=GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT;
-          discovery_dialog = gtk_dialog_new_with_buttons ("Discovered",
-                                      GTK_WINDOW(splash_window),
-                                      flags,
-#ifdef GPIO
-                                      "Configure GPIO",
-                                      GTK_RESPONSE_YES,
-#endif
-                                      "Discover",
-                                      GTK_RESPONSE_REJECT,
-                                      "Exit",
-                                      GTK_RESPONSE_CLOSE,
-                                      NULL);
-*/
-
-          discovery_dialog = gtk_dialog_new();
-          gtk_window_set_transient_for(GTK_WINDOW(discovery_dialog),GTK_WINDOW(splash_screen));
-          gtk_window_set_decorated(GTK_WINDOW(discovery_dialog),FALSE);
-
-          gtk_widget_override_font(discovery_dialog, pango_font_description_from_string("FreeMono 16"));
-
-          GdkRGBA color;
-          color.red = 1.0;
-          color.green = 1.0;
-          color.blue = 1.0;
-          color.alpha = 1.0;
-          gtk_widget_override_background_color(discovery_dialog,GTK_STATE_FLAG_NORMAL,&color);
-
-          GtkWidget *content;
-
-          content=gtk_dialog_get_content_area(GTK_DIALOG(discovery_dialog));
-
-          GtkWidget *grid=gtk_grid_new();
-          gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
-          gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
-          gtk_grid_set_row_spacing (GTK_GRID(grid),10);
-
-          int i;
-          char version[16];
-          char text[128];
-          for(i=0;i<devices;i++) {
-              d=&discovered[i];
-fprintf(stderr,"%p protocol=%d name=%s\n",d,d->protocol,d->name);
-              if(d->protocol==ORIGINAL_PROTOCOL) {
-                  sprintf(version,"%d.%d",
-                        d->software_version/10,
-                        d->software_version%10);
-              } else {
-                  sprintf(version,"%d.%d.%d",
-                        d->software_version/100,
-                        (d->software_version%100)/10,
-                        d->software_version%10);
-              }
-              switch(d->protocol) {
-                case ORIGINAL_PROTOCOL:
-                case NEW_PROTOCOL:
-                  sprintf(text,"%s (%s %s) %s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n",
-                        d->name,
-                        d->protocol==ORIGINAL_PROTOCOL?"old":"new",
-                        version,
-                        inet_ntoa(d->info.network.address.sin_addr),
-                        d->info.network.mac_address[0],
-                        d->info.network.mac_address[1],
-                        d->info.network.mac_address[2],
-                        d->info.network.mac_address[3],
-                        d->info.network.mac_address[4],
-                        d->info.network.mac_address[5],
-                        d->info.network.interface_name);
-                  break;
-#ifdef LIMESDR
-                case LIMESDR_PROTOCOL:
-/*
-                  sprintf(text,"%s (%s %s)\n",
-                        d->name,
-                        "lime",
-                        version);
-*/
-                  sprintf(text,"%s\n",
-                        d->name);
-                  break;
-#endif
-              }
-
-              GtkWidget *label=gtk_label_new(text);
-              gtk_widget_override_font(label, pango_font_description_from_string("FreeMono 12"));
-              gtk_widget_show(label);
-              gtk_grid_attach(GTK_GRID(grid),label,0,i,3,1);
-
-              GtkWidget *start_button=gtk_button_new_with_label("Start");
-              gtk_widget_override_font(start_button, pango_font_description_from_string("FreeMono 18"));
-              gtk_widget_show(start_button);
-              gtk_grid_attach(GTK_GRID(grid),start_button,3,i,1,1);
-              g_signal_connect(start_button,"button_press_event",G_CALLBACK(start_cb),(gpointer)d);
-
-              // if not available then cannot start it
-              if(d->status!=STATE_AVAILABLE) {
-                gtk_button_set_label(GTK_BUTTON(start_button),"In Use");
-                gtk_widget_set_sensitive(start_button, FALSE);
-              }
-
-              // if not on the same subnet then cannot start it
-              if((d->info.network.interface_address.sin_addr.s_addr&d->info.network.interface_netmask.sin_addr.s_addr) != (d->info.network.address.sin_addr.s_addr&d->info.network.interface_netmask.sin_addr.s_addr)) {
-                gtk_button_set_label(GTK_BUTTON(start_button),"Subnet!");
-                gtk_widget_set_sensitive(start_button, FALSE);
-              }
-
-          }
-
-#ifdef GPIO
-          GtkWidget *gpio_b=gtk_button_new_with_label("Config GPIO");
-          g_signal_connect (gpio_b, "button-press-event", G_CALLBACK(gpio_cb), NULL);
-          gtk_grid_attach(GTK_GRID(grid),gpio_b,0,i,1,1);
-#endif
-          GtkWidget *discover_b=gtk_button_new_with_label("Discover");
-          g_signal_connect (discover_b, "button-press-event", G_CALLBACK(discover_cb), NULL);
-          gtk_grid_attach(GTK_GRID(grid),discover_b,1,i,1,1);
-
-          GtkWidget *exit_b=gtk_button_new_with_label("Exit");
-          g_signal_connect (exit_b, "button-press-event", G_CALLBACK(exit_cb), NULL);
-          gtk_grid_attach(GTK_GRID(grid),exit_b,2,i,1,1);
-
-
-          gtk_container_add (GTK_CONTAINER (content), grid);
-          gtk_widget_show_all(discovery_dialog);
-      }
-}
-
-static gboolean minimize_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
-  gtk_window_iconify(GTK_WINDOW(window));
-  return TRUE;
-}
-
-static void start_radio() {
-  int y;
-fprintf(stderr,"start: selected radio=%p device=%d\n",radio,radio->device);
-  gdk_window_set_cursor(splash_window,cursor_watch);
-
-  splash_status("Initializing wdsp ...");
-  protocol=radio->protocol;
-  device=radio->device;
-
-  switch(radio->protocol) {
-    case ORIGINAL_PROTOCOL:
-    case NEW_PROTOCOL:
-      sprintf(property_path,"%02X-%02X-%02X-%02X-%02X-%02X.props",
-                        radio->info.network.mac_address[0],
-                        radio->info.network.mac_address[1],
-                        radio->info.network.mac_address[2],
-                        radio->info.network.mac_address[3],
-                        radio->info.network.mac_address[4],
-                        radio->info.network.mac_address[5]);
-      break;
-#ifdef LIMESDR
-    case LIMESDR_PROTOCOL:
-      sprintf(property_path,"limesdr.props");
-      break;
-#endif
-  }
-
-  radioRestoreState();
-
-  fprintf(stderr,"malloc samples\n");
-  if(radio->protocol==NEW_PROTOCOL) {
-    samples=malloc(display_width*sizeof(float)*2*4); // 192 -> 48
-  } else {
-    samples=malloc(display_width*sizeof(float)*2);
-  }
-
-  //splash_status("Initializing wdsp ...");
-  fprintf(stderr,"wdsp_init\n");
-  wdsp_init(0,display_width,radio->protocol);
-
-  switch(radio->protocol) {
-    case ORIGINAL_PROTOCOL:
-      splash_status("Initializing old protocol ...");
-  fprintf(stderr,"old_protocol_init\n");
-      old_protocol_init(0,display_width);
-      break;
-    case NEW_PROTOCOL:
-      splash_status("Initializing new protocol ...");
-  fprintf(stderr,"new_protocol_init\n");
-      new_protocol_init(display_width);
-      break;
-#ifdef LIMESDR
-    case LIMESDR_PROTOCOL:
-      splash_status("Initializing lime protocol ...");
-      lime_protocol_init(0,display_width);
-      break;
-#endif
-  }
-
-#ifdef GPIO
-  fprintf(stderr,"gpio_init\n");
-  splash_status("Initializing GPIO ...");
-  if(gpio_init()<0) {
-  }
-#ifdef LOCALCW
-  // init local keyer if enabled
-  else if (cw_keyer_internal == 0)
-    keyer_update();
-#endif
-#endif
-
-  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-  gtk_window_set_title (GTK_WINDOW (window), "pihpsdr");
-  gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER_ALWAYS);
-  gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
-  g_signal_connect (window, "delete-event", G_CALLBACK (main_delete), NULL);
-
-  fixed=gtk_fixed_new();
-  gtk_container_add(GTK_CONTAINER(window), fixed);
-  y=0;
-
-  vfo = vfo_init(VFO_WIDTH,VFO_HEIGHT,window);
-  gtk_fixed_put(GTK_FIXED(fixed),vfo,0,0);
-
-
-
-  //rit_control = rit_init(RIT_WIDTH,MENU_HEIGHT,window);
-  //gtk_fixed_put(GTK_FIXED(fixed),rit_control,VFO_WIDTH,y);
-
-  GtkWidget *minimize_b=gtk_button_new_with_label("Hide");
-  gtk_widget_override_font(minimize_b, pango_font_description_from_string("FreeMono Bold 10"));
-  gtk_widget_set_size_request (minimize_b, MENU_WIDTH, MENU_HEIGHT/2);
-  g_signal_connect (minimize_b, "button-press-event", G_CALLBACK(minimize_cb), NULL);
-  gtk_widget_show(minimize_b);
-  gtk_fixed_put(GTK_FIXED(fixed),minimize_b,VFO_WIDTH,y);
-
-  //menu = menu_init(MENU_WIDTH,MENU_HEIGHT,window);
-  menu = new_menu_init(MENU_WIDTH,MENU_HEIGHT/2,window);
-  gtk_fixed_put(GTK_FIXED(fixed),menu,VFO_WIDTH,y+(MENU_HEIGHT/2));
-
-  meter = meter_init(METER_WIDTH,METER_HEIGHT,window);
-  gtk_fixed_put(GTK_FIXED(fixed),meter,VFO_WIDTH+MENU_WIDTH,y);
-  y+=VFO_HEIGHT;
-
-  if(display_panadapter) {
-    int height=PANADAPTER_HEIGHT;
-    if(!display_waterfall) {
-      height+=WATERFALL_HEIGHT;
-      if(!display_sliders) {
-        height+=SLIDERS_HEIGHT;
-      }
-      if(!display_toolbar) {
-        height+=TOOLBAR_HEIGHT;
-      }
-    } else {
-      if(!display_sliders) {
-        height+=SLIDERS_HEIGHT/2;
-      }
-    }
-    panadapter = panadapter_init(display_width,height);
-    gtk_fixed_put(GTK_FIXED(fixed),panadapter,0,VFO_HEIGHT);
-    y+=height;
-  }
-
-  if(display_waterfall) {
-    int height=WATERFALL_HEIGHT;
-    if(!display_panadapter) {
-      height+=PANADAPTER_HEIGHT;
-    }
-    if(!display_sliders) {
-      if(display_panadapter) {
-        height+=SLIDERS_HEIGHT/2;
-      } else {
-        height+=SLIDERS_HEIGHT;
-      }
-    }
-    if(!display_toolbar) {
-      height+=TOOLBAR_HEIGHT;
-    }
-    waterfall = waterfall_init(display_width,height);
-    gtk_fixed_put(GTK_FIXED(fixed),waterfall,0,y);
-    y+=height;
-
-  }
-
-#ifdef PSK
-    int psk_height=PSK_WATERFALL_HEIGHT;
-    if(!display_sliders) {
-      psk_height+=SLIDERS_HEIGHT/2;
-    }
-    if(!display_toolbar) {
-      psk_height+=TOOLBAR_HEIGHT/2;
-    }
-    psk_waterfall = psk_waterfall_init(display_width,psk_height);
-    gtk_fixed_put(GTK_FIXED(fixed),psk_waterfall,0,VFO_HEIGHT);
-    psk = init_psk();
-    gtk_fixed_put(GTK_FIXED(fixed),psk,0,VFO_HEIGHT+psk_height);
-#endif
-
-  if(display_sliders) {
-    sliders = sliders_init(display_width,SLIDERS_HEIGHT,window);
-    gtk_fixed_put(GTK_FIXED(fixed),sliders,0,y);
-    y+=SLIDERS_HEIGHT;
-  }
-
-  if(display_toolbar) {
-    toolbar = toolbar_init(display_width,TOOLBAR_HEIGHT,window);
-    gtk_fixed_put(GTK_FIXED(fixed),toolbar,0,y);
-    y+=TOOLBAR_HEIGHT;
-  }
-
-  splash_close();
-
-  gtk_widget_show_all (window);
-
-  linein_changed();
-
-  if(full_screen) {
-    gtk_window_fullscreen(GTK_WINDOW(window));
-  }
-
-  GdkWindow *gdk_window = gtk_widget_get_window(window);
-  gdk_window_set_cursor(gdk_window,cursor_arrow);
-
-  // start the receiver
-  SetChannelState(CHANNEL_RX0,1,1);
-
-  //update_timer_id=gdk_threads_add_timeout(1000/updates_per_second, update, NULL);
-  update_timer_id=gdk_threads_add_timeout_full(G_PRIORITY_HIGH_IDLE,1000/updates_per_second, update, NULL, NULL);
-
-  // save every 30 seconds
-  save_timer_id=gdk_threads_add_timeout(30000, save_cb, NULL);
-
-
-  if(protocol!=NEW_PROTOCOL) {
-    setFrequency(getFrequency());
-  }
-
-#ifdef PSK
-  if(mode==modePSK) {
-    show_psk();
-  } else {
-    show_waterfall();
-  }
-#endif
-
-  launch_rigctl();
-
-  g_idle_add(vfo_update,(gpointer)NULL);
-
-}
-
-#ifdef PSK
-void show_psk() {
-  if(display_waterfall) {
-    gtk_widget_hide(waterfall);
-  }
-  if(display_panadapter) {
-    gtk_widget_hide(panadapter);
-  }
-  gtk_widget_show(psk);
-  gtk_widget_show(psk_waterfall);
-}
-
-void show_waterfall() {
-  gtk_widget_hide(psk_waterfall);
-  gtk_widget_hide(psk);
-  if(display_panadapter) {
-    gtk_widget_show(panadapter);
-  }
-  if(display_waterfall) {
-    gtk_widget_show(waterfall);
-  }
-}
-#endif
-
-void reconfigure_display() {
-  int y=VFO_HEIGHT;
-
-  // configure panadapter
-  if(display_panadapter) {
-    int height=PANADAPTER_HEIGHT;
-    if(!display_waterfall) {
-      height+=WATERFALL_HEIGHT;
-      if(!display_sliders) {
-        height+=SLIDERS_HEIGHT;
-      }
-      if(!display_toolbar) {
-        height+=TOOLBAR_HEIGHT;
-      }
-    } else {
-      if(!display_sliders) {
-        height+=SLIDERS_HEIGHT/2;
-      }
-      if(!display_toolbar) {
-        height+=TOOLBAR_HEIGHT/2;
-      }
-    }
-fprintf(stderr,"panadapter_height=%d\n",height);
-    if(panadapter==NULL) {
-fprintf(stderr,"reconfigure_display: panadapter_init: width:%d height:%d\n",display_width,height);
-      panadapter = panadapter_init(display_width,height);
-      gtk_fixed_put(GTK_FIXED(fixed),panadapter,0,y);
-    } else {
-      // set the size
-fprintf(stderr,"reconfigure_display: panadapter set_size_request: width:%d height:%d\n",display_width,height);
-      gtk_widget_set_size_request(panadapter, display_width, height);
-      // move the current one
-      gtk_fixed_move(GTK_FIXED(fixed),panadapter,0,y);
-    }
-    gtk_widget_show_all(panadapter);
-    y+=height;
-  } else {
-    gtk_widget_hide(panadapter);
-  }
-
-  // configure waterfall
-  if(display_waterfall) {
-    int height=WATERFALL_HEIGHT;
-
-    if(!display_panadapter) {
-      height+=PANADAPTER_HEIGHT;
-      if(!display_sliders) {
-        height+=SLIDERS_HEIGHT;
-      }
-      if(!display_toolbar) {
-        height+=TOOLBAR_HEIGHT;
-      }
-    } else {
-      if(!display_sliders) {
-        height+=SLIDERS_HEIGHT/2;
-      }
-      if(!display_toolbar) {
-        height+=TOOLBAR_HEIGHT/2;
-      }
-    }
-fprintf(stderr,"waterfall_height=%d\n",height);
-    if(waterfall==NULL) {
-fprintf(stderr,"reconfigure_display: waterfall_init: width:%d height:%d\n",display_width,height);
-      waterfall = waterfall_init(display_width,height);
-      gtk_fixed_put(GTK_FIXED(fixed),waterfall,0,y);
-    } else {
-      // set the size
-fprintf(stderr,"reconfigure_display: waterfall set_size_request: width:%d height:%d\n",display_width,height);
-      gtk_widget_set_size_request (waterfall, display_width, height);
-      // move the current one
-      gtk_fixed_move(GTK_FIXED(fixed),waterfall,0,y);
-    }
-    gtk_widget_show_all(waterfall);
-    y+=height;
-  } else {
-    gtk_widget_hide(waterfall);
-  }
-
-  if(display_sliders) {
-fprintf(stderr,"sliders_height=%d\n",SLIDERS_HEIGHT);
-    if(sliders==NULL) {
-fprintf(stderr,"reconfigure_display: sliders_init: width:%d height:%d\n",display_width,SLIDERS_HEIGHT);
-      sliders = sliders_init(display_width,SLIDERS_HEIGHT,window);
-      gtk_fixed_put(GTK_FIXED(fixed),sliders,0,y);
-    } else {
-      gtk_fixed_move(GTK_FIXED(fixed),sliders,0,y);
-      gtk_widget_show(sliders);
-    }
-    gtk_widget_show_all(sliders);
-    linein_changed();
-    y+=SLIDERS_HEIGHT;
-  } else {
-    gtk_widget_hide(sliders);
-  }
-
-  if(display_toolbar) {
-fprintf(stderr,"toolbar_height=%d\n",TOOLBAR_HEIGHT);
-    if(toolbar==NULL) {
-fprintf(stderr,"reconfigure_display: toolbar_init: width:%d height:%d\n",display_width,TOOLBAR_HEIGHT);
-      toolbar = toolbar_init(display_width,TOOLBAR_HEIGHT,window);
-      gtk_fixed_put(GTK_FIXED(fixed),toolbar,0,y);
-    } else {
-      gtk_fixed_move(GTK_FIXED(fixed),toolbar,0,y);
-      gtk_widget_show(toolbar);
-    }
-    gtk_widget_show_all(toolbar);
-    y+=TOOLBAR_HEIGHT;
-  } else {
-    gtk_widget_hide(toolbar);
-  }
-
-}
-
-gint init(void* arg) {
+static int init(void *data) {
   char *res;
   char wisdom_directory[1024];
   char wisdom_file[1024];
 
   fprintf(stderr,"init\n");
 
-  audio_get_cards(0);
-  audio_get_cards(1);
+  audio_get_cards();
 
   cursor_arrow=gdk_cursor_new(GDK_ARROW);
   cursor_watch=gdk_cursor_new(GDK_WATCH);
 
-  splash_window = gtk_widget_get_window(splash_screen);
-  gdk_window_set_cursor(splash_window,cursor_watch);
-
-  init_radio();
+  gdk_window_set_cursor(gtk_widget_get_window(top_window),cursor_watch);
 
   // check if wisdom file exists
   res=getcwd(wisdom_directory, sizeof(wisdom_directory));
   strcpy(&wisdom_directory[strlen(wisdom_directory)],"/");
   strcpy(wisdom_file,wisdom_directory);
   strcpy(&wisdom_file[strlen(wisdom_file)],"wdspWisdom");
-  splash_status("Checking FFTW Wisdom file ...");
+  status_text("Checking FFTW Wisdom file ...");
   if(access(wisdom_file,F_OK)<0) {
       int rc=sem_init(&wisdom_sem, 0, 0);
       rc=pthread_create(&wisdom_thread_id, NULL, wisdom_thread, (void *)wisdom_directory);
       while(sem_trywait(&wisdom_sem)<0) {
-        splash_status(wisdom_get_status());
+        status_text(wisdom_get_status());
         while (gtk_events_pending ())
           gtk_main_iteration ();
         usleep(100000); // 100ms
       }
   }
 
-  discover_devices();
-
+  g_idle_add(discovery,NULL);
   return 0;
 }
 
-int main (int   argc, char *argv[]) {
-  gtk_init (&argc, &argv);
+static void activate_pihpsdr(GtkApplication *app, gpointer data) {
+
+
+  //gtk_init (&argc, &argv);
 
   fprintf(stderr,"Build: %s %s\n",build_date,version);
 
@@ -964,13 +176,87 @@ fprintf(stderr,"width=%d height=%d\n", display_width, display_height);
     full_screen=0;
   }
 
-  fprintf(stderr,"display_width=%d display_height=%d\n", display_width, display_height);
+fprintf(stderr,"display_width=%d display_height=%d\n", display_width, display_height);
 
-  splash_show("hpsdr.png", display_width, display_height, full_screen);
+  fprintf(stderr,"create top level window\n");
+  top_window = gtk_application_window_new (app);
+  if(full_screen) {
+fprintf(stderr,"full screen\n");
+    gtk_window_fullscreen(GTK_WINDOW(top_window));
+  }
+  gtk_widget_set_size_request(top_window, display_width, display_height);
+  gtk_window_set_title (GTK_WINDOW (top_window), "pihpsdr");
+  gtk_window_set_position(GTK_WINDOW(top_window),GTK_WIN_POS_CENTER_ALWAYS);
+  gtk_window_set_resizable(GTK_WINDOW(top_window), FALSE);
+  g_signal_connect (top_window, "delete-event", G_CALLBACK (main_delete), NULL);
+  //g_signal_connect (top_window,"draw", G_CALLBACK (main_draw_cb), NULL);
+
+//fprintf(stderr,"create fixed container\n");
+  //fixed=gtk_fixed_new();
+  //gtk_container_add(GTK_CONTAINER(top_window), fixed);
+
+fprintf(stderr,"create grid\n");
+  grid = gtk_grid_new();
+  gtk_widget_set_size_request(grid, display_width, display_height);
+  gtk_grid_set_row_homogeneous(GTK_GRID(grid),FALSE);
+  gtk_grid_set_column_homogeneous(GTK_GRID(grid),FALSE);
+fprintf(stderr,"add grid\n");
+  gtk_container_add (GTK_CONTAINER (top_window), grid);
+
+fprintf(stderr,"create image\n");
+  GtkWidget  *image=gtk_image_new_from_file("hpsdr.png");
+fprintf(stderr,"add image to grid\n");
+  gtk_grid_attach(GTK_GRID(grid), image, 0, 0, 1, 4);
+
+fprintf(stderr,"create pi label\n");
+  char build[64];
+  sprintf(build,"build: %s %s",build_date, version);
+  GtkWidget *pi_label=gtk_label_new("pihpsdr by John Melton g0orx/n6lyt");
+  gtk_label_set_justify(GTK_LABEL(pi_label),GTK_JUSTIFY_LEFT);
+  gtk_widget_show(pi_label);
+fprintf(stderr,"add pi label to grid\n");
+  gtk_grid_attach(GTK_GRID(grid),pi_label,1,0,1,1);
+
+fprintf(stderr,"create build label\n");
+  GtkWidget *build_date_label=gtk_label_new(build);
+  gtk_label_set_justify(GTK_LABEL(build_date_label),GTK_JUSTIFY_LEFT);
+  gtk_widget_show(build_date_label);
+fprintf(stderr,"add build label to grid\n");
+  gtk_grid_attach(GTK_GRID(grid),build_date_label,1,1,1,1);
+
+fprintf(stderr,"create status\n");
+  status=gtk_label_new("");
+  gtk_label_set_justify(GTK_LABEL(status),GTK_JUSTIFY_LEFT);
+  gtk_widget_override_font(status, pango_font_description_from_string("FreeMono 18"));
+  gtk_widget_show(status);
+fprintf(stderr,"add status to grid\n");
+  gtk_grid_attach(GTK_GRID(grid), status, 1, 3, 1, 1);
 
-  g_idle_add(init,(void *)argv[0]);
+/*
+fprintf(stderr,"create exit button\n");
+  GtkWidget *button = gtk_button_new_with_label ("Exit");
+  //g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
+  g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), top_window);
+fprintf(stderr,"add exit button to grid\n");
+  gtk_grid_attach(GTK_GRID(grid), button, 1, 4, 1, 1);
+*/
 
-  gtk_main();
+  gtk_widget_show_all(top_window);
 
-  return 0;
+  g_idle_add(init,NULL);
+  //g_idle_add(discovery,NULL);
+
+
+}
+
+int main(int argc,char **argv) {
+  GtkApplication *pihpsdr;
+  int status;
+
+  pihpsdr=gtk_application_new("org.g0orx.pihpsdr", G_APPLICATION_FLAGS_NONE);
+  g_signal_connect(pihpsdr, "activate", G_CALLBACK(activate_pihpsdr), NULL);
+  status=g_application_run(G_APPLICATION(pihpsdr), argc, argv);
+fprintf(stderr,"exiting ...\n");
+  g_object_unref(pihpsdr);
+  return status;
 }
diff --git a/main.h b/main.h
index ba49d5ba98a33351b1de2e5fb2ab97797daacb6a..49a76c916ec4a83197f2e6042c552179c87e117f 100644 (file)
--- a/main.h
+++ b/main.h
 #ifndef _MAIN_H
 #define _MAIN_H
 
-#include <sys/utsname.h>
-extern struct utsname unameData;
-void reconfigure_display();
+#define DISPLAY_INCREMENT (display_height/32)
+#define MENU_HEIGHT (DISPLAY_INCREMENT*2)
+#define MENU_WIDTH ((display_width/32)*3)
+#define VFO_HEIGHT (DISPLAY_INCREMENT*4)
+#define VFO_WIDTH (display_width-METER_WIDTH-MENU_WIDTH)
+#define METER_HEIGHT (DISPLAY_INCREMENT*4)
+#define METER_WIDTH ((display_width/32)*8)
+#define PANADAPTER_HEIGHT (DISPLAY_INCREMENT*8)
+#define SLIDERS_HEIGHT (DISPLAY_INCREMENT*6)
+#define TOOLBAR_HEIGHT (DISPLAY_INCREMENT*2)
+#define WATERFALL_HEIGHT (display_height-(VFO_HEIGHT+PANADAPTER_HEIGHT+SLIDERS_HEIGHT+TOOLBAR_HEIGHT))
 #ifdef PSK
-void show_psk();
-void show_waterfall();
+#define PSK_WATERFALL_HEIGHT (DISPLAY_INCREMENT*6)
+#define PSK_HEIGHT (display_height-(VFO_HEIGHT+PSK_WATERFALL_HEIGHT+SLIDERS_HEIGHT+TOOLBAR_HEIGHT))
 #endif
 
+#include <sys/utsname.h>
+extern struct utsname unameData;
+
+extern gint display_width;
+extern gint display_height;
+extern gint full_screen;
+extern GtkWidget *top_window;
+extern GtkWidget *grid;
+extern void status_text(char *text);
+
 #endif
diff --git a/meter.c b/meter.c
index f95b790d250777dea2f2e9d10cb5d6ee687f7d93..426d1c09da7969a631430f491854362b1db7bf09 100644 (file)
--- a/meter.c
+++ b/meter.c
@@ -55,7 +55,7 @@ meter_clear_surface (void)
   cr = cairo_create (meter_surface);
 
   cairo_set_source_rgb (cr, 0, 0, 0);
-  cairo_paint (cr);
+  cairo_fill (cr);
 
   cairo_destroy (cr);
 }
@@ -64,9 +64,6 @@ meter_configure_event_cb (GtkWidget         *widget,
             GdkEventConfigure *event,
             gpointer           data)
 {
-fprintf(stderr,"meter_configure_event_cb: width=%d height=%d\n",
-                                       gtk_widget_get_allocated_width (widget),
-                                       gtk_widget_get_allocated_height (widget));
   if (meter_surface)
     cairo_surface_destroy (meter_surface);
 
@@ -76,7 +73,11 @@ fprintf(stderr,"meter_configure_event_cb: width=%d height=%d\n",
                                        gtk_widget_get_allocated_height (widget));
 
   /* Initialize the surface to black */
-  meter_clear_surface ();
+  cairo_t *cr;
+  cr = cairo_create (meter_surface);
+  cairo_set_source_rgb (cr, 0, 0, 0);
+  cairo_paint (cr);
+  cairo_destroy (cr);
 
   return TRUE;
 }
@@ -89,8 +90,7 @@ static gboolean
 meter_draw_cb (GtkWidget *widget, cairo_t   *cr, gpointer   data) {
   cairo_set_source_surface (cr, meter_surface, 0, 0);
   cairo_paint (cr);
-
-  return FALSE;
+  return TRUE;
 }
 
 /*
@@ -225,11 +225,13 @@ void meter_update(int meter_type,double value,double reverse,double exciter,doub
   cairo_select_font_face(cr, "FreeMono",
                 CAIRO_FONT_SLANT_NORMAL,
                 CAIRO_FONT_WEIGHT_BOLD);
-  cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
-  cairo_set_font_size(cr, 10);
+
+  cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
+  cairo_set_font_size(cr, 12);
   cairo_move_to(cr, 5, 15);
   cairo_show_text(cr, text);
 
+
   if(last_meter_type!=meter_type) {
     last_meter_type=meter_type;
     max_count=0;
@@ -321,7 +323,7 @@ void meter_update(int meter_type,double value,double reverse,double exciter,doub
       cairo_show_text(cr, sf);
 
 #ifdef FREEDV
-      if(mode==modeFREEDV) {
+      if(active_receiver->mode==modeFREEDV) {
         if(freedv_sync) {
           cairo_set_source_rgb(cr, 0, 1, 0);
         } else {
diff --git a/meter.h b/meter.h
index 44df10149562001e8fbde7467585e247e768040b..868dc6ca507580ff7c24bc645a043a575584c1a4 100644 (file)
--- a/meter.h
+++ b/meter.h
@@ -20,6 +20,8 @@
 #ifndef _METER_H
 #define _METER_H
 
+#include <gtk/gtk.h>
+
 #define SMETER 0
 #define POWER 1
 #ifdef PSK
index bccabdc0b5b84c617be59888f9d6c0b5b457e0af..e43361d41ef817fe1498cdaf65d2637be67688a8 100644 (file)
@@ -69,7 +69,7 @@ void meter_menu (GtkWidget *parent) {
   gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
   gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
 
-  GtkWidget *close_b=gtk_button_new_with_label("Close Meter");
+  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);
 
diff --git a/mode.c b/mode.c
index 7bb8cd0f97c5b9b4418eee73dfb6f2d484830a0a..37bd12b8ab97f32c2b326998f55288950553366e 100644 (file)
--- a/mode.c
+++ b/mode.c
@@ -38,3 +38,4 @@ char *mode_string[]={
 #endif
 };
 
+//int mode;
diff --git a/mode.h b/mode.h
index e2839d27e78e1ff49dbbeddae1940706bfa63df2..ec688105f16e73472c342e7c0fadf1457e2733fd 100644 (file)
--- a/mode.h
+++ b/mode.h
@@ -50,8 +50,7 @@
 #endif
 #endif
 
-int mode;
-
 char *mode_string[MODES];
 
+//extern int mode;
 #endif
index 0784302dae319584899c2d5cd0aa6f886dd34e10..de525c607405b375f6fcdb789500bacf06267160 100644 (file)
@@ -28,6 +28,7 @@
 #include "filter.h"
 #include "mode.h"
 #include "radio.h"
+#include "receiver.h"
 #include "vfo.h"
 #include "button_text.h"
 
@@ -48,17 +49,10 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat
 
 static gboolean mode_select_cb (GtkWidget *widget, gpointer        data) {
   int m=(int)data;
-  BANDSTACK_ENTRY *entry;
-  entry=bandstack_entry_get_current();
-  entry->mode=m;
-  setMode(entry->mode);
-  FILTER* band_filters=filters[entry->mode];
-  FILTER* band_filter=&band_filters[entry->filter];
-  setFilter(band_filter->low,band_filter->high);
   set_button_text_color(last_mode,"black");
   last_mode=widget;
   set_button_text_color(last_mode,"orange");
-  vfo_update(NULL);
+  vfo_mode_changed(m);
 }
 
 void mode_menu(GtkWidget *parent) {
@@ -92,11 +86,16 @@ void mode_menu(GtkWidget *parent) {
   g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
   gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
 
-  BANDSTACK_ENTRY *entry=bandstack_entry_get_current();
+  char label[32];
+  sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B");
+  GtkWidget *rx_label=gtk_label_new(label);
+  gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1);
+
+  int mode=vfo[active_receiver->id].mode;
 
   for(i=0;i<MODES;i++) {
     GtkWidget *b=gtk_button_new_with_label(mode_string[i]);
-    if(i==entry->mode) {
+    if(i==mode) {
       set_button_text_color(b,"orange");
       last_mode=b;
     } else {
index b8a21cab49027e92caa2cddd81e08a43c680310e..110d3ebf2930ff3c7d22533dd06cfdd1daec3e80 100644 (file)
@@ -17,6 +17,7 @@
 *
 */
 
+#include <gtk/gtk.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <sys/types.h>
@@ -48,8 +49,10 @@ static struct sockaddr_in discovery_addr;
 
 void new_discover(struct ifaddrs* iface);
 
-static pthread_t discover_thread_id;
-void* new_discover_receive_thread(void* arg);
+//static pthread_t discover_thread_id;
+static GThread *discover_thread_id;
+//void* new_discover_receive_thread(void* arg);
+gpointer new_discover_receive_thread(gpointer data);
 
 void print_device(int i) {
     fprintf(stderr,"discovery: found protocol=%d device=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n", 
@@ -121,7 +124,7 @@ void new_discover(struct ifaddrs* iface) {
     // bind to this interface and the discovery port
     interface_addr.sin_family = AF_INET;
     interface_addr.sin_addr.s_addr = sa->sin_addr.s_addr;
-    interface_addr.sin_port = htons(DISCOVERY_PORT);
+    interface_addr.sin_port = htons(0);
     if(bind(discovery_socket,(struct sockaddr*)&interface_addr,sizeof(interface_addr))<0) {
         perror("new_discover: bind socket failed for discovery_socket\n");
         exit(-1);
@@ -147,11 +150,21 @@ void new_discover(struct ifaddrs* iface) {
     to_addr.sin_addr.s_addr=htonl(INADDR_BROADCAST);
 
     // start a receive thread to collect discovery response packets
+/*
     rc=pthread_create(&discover_thread_id,NULL,new_discover_receive_thread,NULL);
     if(rc != 0) {
         fprintf(stderr,"pthread_create failed on new_discover_receive_thread: rc=%d\n", rc);
         exit(-1);
     }
+*/
+    discover_thread_id = g_thread_new( "new discover receive", new_discover_receive_thread, NULL);
+    if( ! discover_thread_id )
+    {
+        fprintf(stderr,"g_thread_new failed on new_discover_receive_thread\n");
+        exit( -1 );
+    }
+    fprintf(stderr,"new_disovery: thread_id=%p\n",discover_thread_id);
+
 
     // send discovery packet
     unsigned char buffer[60];
@@ -171,15 +184,19 @@ void new_discover(struct ifaddrs* iface) {
     }
 
     // wait for receive thread to complete
+/*
     void* status;
     pthread_join(discover_thread_id,&status);
+*/
+    g_thread_join(discover_thread_id);
 
     close(discovery_socket);
 
     fprintf(stderr,"new_discover: exiting discover for %s\n",iface->ifa_name);
 }
 
-void* new_discover_receive_thread(void* arg) {
+//void* new_discover_receive_thread(void* arg) {
+gpointer new_discover_receive_thread(gpointer data) {
     struct sockaddr_in addr;
     int len;
     unsigned char buffer[2048];
@@ -270,5 +287,6 @@ void* new_discover_receive_thread(void* arg) {
         }
     }
     fprintf(stderr,"new_discover: exiting new_discover_receive_thread\n");
-    pthread_exit(NULL);
+    //pthread_exit(NULL);
+    g_thread_exit(NULL);
 }
index 6be6ec20367694d99b7c0ebdb7e966c80e910fcb..9734c42e57b39852b61895b2ea4e7265e02682fa 100644 (file)
@@ -25,8 +25,8 @@
 #include "audio.h"
 #include "new_menu.h"
 #include "exit_menu.h"
-#include "general_menu.h"
-#include "audio_menu.h"
+#include "radio_menu.h"
+#include "rx_menu.h"
 #include "ant_menu.h"
 #include "display_menu.h"
 #include "dsp_menu.h"
 #include "filter_menu.h"
 #include "noise_menu.h"
 #include "agc_menu.h"
-#include "fm_menu.h"
 #include "test_menu.h"
 #include "vox_menu.h"
 #include "diversity_menu.h"
 #include "freqent_menu.h"
+#include "tx_menu.h"
+#ifdef GPIO
+#include "encoder_menu.h"
+#endif
+#include "vfo_menu.h"
+#include "main.h"
 
 
-static GtkWidget *parent_window=NULL;
-
 static GtkWidget *menu_b=NULL;
 
 static GtkWidget *dialog=NULL;
 
 GtkWidget *sub_menu=NULL;
 
+int active_menu=NO_MENU;
+
 static cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
@@ -70,6 +75,7 @@ static cleanup() {
     gtk_widget_destroy(sub_menu);
     sub_menu=NULL;
   }
+  active_menu=NO_MENU;
 }
 
 static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
@@ -80,81 +86,81 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat
 
 static gboolean exit_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   cleanup();
-  exit_menu(parent_window);
+  exit_menu(top_window);
   return TRUE;
 }
 
-static gboolean general_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static gboolean radio_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   cleanup();
-  general_menu(parent_window);
+  radio_menu(top_window);
   return TRUE;
 }
 
-static gboolean audio_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static gboolean rx_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   cleanup();
-  audio_menu(parent_window);
+  rx_menu(top_window);
   return TRUE;
 }
 
 static gboolean ant_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   cleanup();
-  ant_menu(parent_window);
+  ant_menu(top_window);
   return TRUE;
 }
 
 static gboolean display_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   cleanup();
-  display_menu(parent_window);
+  display_menu(top_window);
   return TRUE;
 }
 
 static gboolean dsp_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   cleanup();
-  dsp_menu(parent_window);
+  dsp_menu(top_window);
   return TRUE;
 }
 
 static gboolean pa_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   cleanup();
-  pa_menu(parent_window);
+  pa_menu(top_window);
   return TRUE;
 }
 
 static gboolean cw_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   cleanup();
-  cw_menu(parent_window);
+  cw_menu(top_window);
   return TRUE;
 }
 
 static gboolean oc_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   cleanup();
-  oc_menu(parent_window);
+  oc_menu(top_window);
   return TRUE;
 }
 
 #ifdef FREEDV
 static gboolean freedv_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   cleanup();
-  freedv_menu(parent_window);
+  freedv_menu(top_window);
   return TRUE;
 }
 #endif
 
 static gboolean xvtr_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   cleanup();
-  xvtr_menu(parent_window);
+  xvtr_menu(top_window);
   return TRUE;
 }
 
 static gboolean equalizer_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   cleanup();
-  equalizer_menu(parent_window);
+  equalizer_menu(top_window);
   return TRUE;
 }
 
 void start_step() {
   cleanup();
-  step_menu(parent_window);
+  step_menu(top_window);
 }
 
 static gboolean step_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
@@ -164,7 +170,7 @@ static gboolean step_cb (GtkWidget *widget, GdkEventButton *event, gpointer data
 
 void start_meter() {
   cleanup();
-  meter_menu(parent_window);
+  meter_menu(top_window);
 }
 
 static gboolean meter_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
@@ -173,8 +179,12 @@ static gboolean meter_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat
 }
 
 void start_band() {
+  int old_menu=active_menu;
   cleanup();
-  band_menu(parent_window);
+  if(old_menu!=BAND_MENU) {
+    band_menu(top_window);
+    active_menu=BAND_MENU;
+  }
 }
 
 static gboolean band_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
@@ -183,8 +193,12 @@ static gboolean band_cb (GtkWidget *widget, GdkEventButton *event, gpointer data
 }
 
 void start_bandstack() {
+  int old_menu=active_menu;
   cleanup();
-  bandstack_menu(parent_window);
+  if(old_menu!=BANDSTACK_MENU) {
+    bandstack_menu(top_window);
+    active_menu=BANDSTACK_MENU;
+  }
 }
 
 static gboolean bandstack_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
@@ -193,8 +207,12 @@ static gboolean bandstack_cb (GtkWidget *widget, GdkEventButton *event, gpointer
 }
 
 void start_mode() {
+  int old_menu=active_menu;
   cleanup();
-  mode_menu(parent_window);
+  if(old_menu!=MODE_MENU) {
+    mode_menu(top_window);
+    active_menu=MODE_MENU;
+  }
 }
 
 static gboolean mode_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
@@ -203,8 +221,12 @@ static gboolean mode_cb (GtkWidget *widget, GdkEventButton *event, gpointer data
 }
 
 void start_filter() {
+  int old_menu=active_menu;
   cleanup();
-  filter_menu(parent_window);
+  if(old_menu!=FILTER_MENU) {
+    filter_menu(top_window);
+    active_menu=FILTER_MENU;
+  }
 }
 
 static gboolean filter_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
@@ -213,8 +235,12 @@ static gboolean filter_cb (GtkWidget *widget, GdkEventButton *event, gpointer da
 }
 
 void start_noise() {
+  int old_menu=active_menu;
   cleanup();
-  noise_menu(parent_window);
+  if(old_menu!=NOISE_MENU) {
+    noise_menu(top_window);
+    active_menu=NOISE_MENU;
+  }
 }
 
 static gboolean noise_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
@@ -223,8 +249,12 @@ static gboolean noise_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat
 }
 
 void start_agc() {
+  int old_menu=active_menu;
   cleanup();
-  agc_menu(parent_window);
+  if(old_menu!=AGC_MENU) {
+    agc_menu(top_window);
+    active_menu=AGC_MENU;
+  }
 }
 
 static gboolean agc_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
@@ -232,29 +262,19 @@ static gboolean agc_cb (GtkWidget *widget, GdkEventButton *event, gpointer data)
   return TRUE;
 }
 
-void start_fm() {
-  cleanup();
-  fm_menu(parent_window);
-}
-
-static gboolean fm_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
-  start_fm();
-  return TRUE;
-}
-
 void start_vox() {
   cleanup();
-  vox_menu(parent_window);
+  vox_menu(top_window);
 }
 
-static gboolean vox_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static gboolean vox_b_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   start_vox();
   return TRUE;
 }
 
 void start_diversity() {
   cleanup();
-  diversity_menu(parent_window);
+  diversity_menu(top_window);
 }
 
 static gboolean diversity_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
@@ -264,7 +284,7 @@ static gboolean diversity_cb (GtkWidget *widget, GdkEventButton *event, gpointer
 
 void start_freqent() {
   cleanup();
-  freqent_menu(parent_window);
+  freqent_menu(top_window);
 }
 
 static gboolean freqent_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
@@ -272,9 +292,73 @@ static gboolean freqent_cb (GtkWidget *widget, GdkEventButton *event, gpointer d
   return TRUE;
 }
 
+void start_vfo() {
+  cleanup();
+  vfo_menu(top_window);
+}
+
+static gboolean vfo_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  start_vfo();
+  return TRUE;
+}
+
+void start_store() {
+  cleanup();
+  store_menu(top_window);
+}
+
+static gboolean store_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  start_store();
+  return TRUE;
+}
+
+void start_tx() {
+  cleanup();
+  tx_menu(top_window);
+}
+
+static gboolean tx_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  start_tx();
+  return TRUE;
+}
+
+#ifdef GPIO
+void start_encoder(int encoder) {
+  int old_menu=active_menu;
+fprintf(stderr,"start_encoder: encoder=%d active_menu=%d\n",encoder,active_menu);
+  cleanup();
+  switch(encoder) {
+    case 1:
+      if(old_menu!=E1_MENU) {
+        encoder_menu(top_window,encoder);
+        active_menu=E1_MENU;
+      }
+      break;
+    case 2:
+      if(old_menu!=E2_MENU) {
+        encoder_menu(top_window,encoder);
+        active_menu=E2_MENU;
+      }
+      break;
+    case 3:
+      if(old_menu!=E3_MENU) {
+        encoder_menu(top_window,encoder);
+        active_menu=E3_MENU;
+      }
+      break;
+  }
+}
+
+static gboolean encoder_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  int encoder=(int)data;
+  start_encoder(encoder);
+  return TRUE;
+}
+#endif
+
 void start_test() {
   cleanup();
-  test_menu(parent_window);
+  test_menu(top_window);
 }
 
 static gboolean test_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
@@ -282,13 +366,10 @@ static gboolean test_cb (GtkWidget *widget, GdkEventButton *event, gpointer data
   return TRUE;
 }
 
-static gboolean new_menu_pressed_event_cb (GtkWidget *widget,
-               GdkEventButton *event,
-               gpointer        data)
+void new_menu()
 {
   int i, j, id;
 
-
   if(dialog==NULL) {
 
     if(sub_menu!=NULL) {
@@ -297,7 +378,7 @@ static gboolean new_menu_pressed_event_cb (GtkWidget *widget,
     }
 
     dialog=gtk_dialog_new();
-    gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
+    gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(top_window));
     gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
 
     GdkRGBA color;
@@ -323,105 +404,93 @@ static gboolean new_menu_pressed_event_cb (GtkWidget *widget,
     g_signal_connect (exit_b, "button-press-event", G_CALLBACK(exit_cb), NULL);
     gtk_grid_attach(GTK_GRID(grid),exit_b,4,0,2,1);
 
-    GtkWidget *general_b=gtk_button_new_with_label("General");
-    g_signal_connect (general_b, "button-press-event", G_CALLBACK(general_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),general_b,0,1,1,1);
+    i=5;
 
-    GtkWidget *audio_b=gtk_button_new_with_label("Audio");
-    g_signal_connect (audio_b, "button-press-event", G_CALLBACK(audio_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),audio_b,1,1,1,1);
+    GtkWidget *radio_b=gtk_button_new_with_label("Radio");
+    g_signal_connect (radio_b, "button-press-event", G_CALLBACK(radio_cb), NULL);
+    gtk_grid_attach(GTK_GRID(grid),radio_b,(i%5),i/5,1,1);
+    i++;
 
-    GtkWidget *ant_b=gtk_button_new_with_label("Ant");
-    g_signal_connect (ant_b, "button-press-event", G_CALLBACK(ant_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),ant_b,2,1,1,1);
+    GtkWidget *rx_b=gtk_button_new_with_label("RX");
+    g_signal_connect (rx_b, "button-press-event", G_CALLBACK(rx_cb), NULL);
+    gtk_grid_attach(GTK_GRID(grid),rx_b,(i%5),i/5,1,1);
+    i++;
 
-    GtkWidget *display_b=gtk_button_new_with_label("Display");
-    g_signal_connect (display_b, "button-press-event", G_CALLBACK(display_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),display_b,3,1,1,1);
-
-    GtkWidget *dsp_b=gtk_button_new_with_label("DSP");
-    g_signal_connect (dsp_b, "button-press-event", G_CALLBACK(dsp_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),dsp_b,4,1,1,1);
+    GtkWidget *tx_b=gtk_button_new_with_label("TX");
+    g_signal_connect (tx_b, "button-press-event", G_CALLBACK(tx_cb), NULL);
+    gtk_grid_attach(GTK_GRID(grid),tx_b,(i%5),i/5,1,1);
+    i++;
 
     GtkWidget *pa_b=gtk_button_new_with_label("PA");
     g_signal_connect (pa_b, "button-press-event", G_CALLBACK(pa_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),pa_b,5,1,1,1);
+    gtk_grid_attach(GTK_GRID(grid),pa_b,(i%5),i/5,1,1);
+    i++;
 
     GtkWidget *cw_b=gtk_button_new_with_label("CW");
     g_signal_connect (cw_b, "button-press-event", G_CALLBACK(cw_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),cw_b,0,2,1,1);
+    gtk_grid_attach(GTK_GRID(grid),cw_b,(i%5),i/5,1,1);
+    i++;
+
+    GtkWidget *ant_b=gtk_button_new_with_label("Ant");
+    g_signal_connect (ant_b, "button-press-event", G_CALLBACK(ant_cb), NULL);
+    gtk_grid_attach(GTK_GRID(grid),ant_b,(i%5),i/5,1,1);
+    i++;
+
+    GtkWidget *dsp_b=gtk_button_new_with_label("DSP");
+    g_signal_connect (dsp_b, "button-press-event", G_CALLBACK(dsp_cb), NULL);
+    gtk_grid_attach(GTK_GRID(grid),dsp_b,(i%5),i/5,1,1);
+    i++;
 
     GtkWidget *oc_b=gtk_button_new_with_label("OC");
     g_signal_connect (oc_b, "button-press-event", G_CALLBACK(oc_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),oc_b,1,2,1,1);
+    gtk_grid_attach(GTK_GRID(grid),oc_b,(i%5),i/5,1,1);
+    i++;
 
 #ifdef FREEDV
     GtkWidget *freedv_b=gtk_button_new_with_label("FreeDV");
     g_signal_connect (freedv_b, "button-press-event", G_CALLBACK(freedv_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),freedv_b,2,2,1,1);
+    gtk_grid_attach(GTK_GRID(grid),freedv_b,(i%5),i/5,1,1);
+    i++;
 #endif
 
+    GtkWidget *display_b=gtk_button_new_with_label("Display");
+    g_signal_connect (display_b, "button-press-event", G_CALLBACK(display_cb), NULL);
+    gtk_grid_attach(GTK_GRID(grid),display_b,(i%5),i/5,1,1);
+    i++;
+
     GtkWidget *xvtr_b=gtk_button_new_with_label("XVTR");
     g_signal_connect (xvtr_b, "button-press-event", G_CALLBACK(xvtr_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),xvtr_b,3,2,1,1);
+    gtk_grid_attach(GTK_GRID(grid),xvtr_b,(i%5),i/5,1,1);
+    i++;
 
     GtkWidget *equalizer_b=gtk_button_new_with_label("Equalizer");
     g_signal_connect (equalizer_b, "button-press-event", G_CALLBACK(equalizer_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),equalizer_b,4,2,1,1);
-
-    GtkWidget *fm_b=gtk_button_new_with_label("FM");
-    g_signal_connect (fm_b, "button-press-event", G_CALLBACK(fm_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),fm_b,5,2,1,1);
+    gtk_grid_attach(GTK_GRID(grid),equalizer_b,(i%5),i/5,1,1);
+    i++;
 
     GtkWidget *step_b=gtk_button_new_with_label("Step");
     g_signal_connect (step_b, "button-press-event", G_CALLBACK(step_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),step_b,0,3,1,1);
+    gtk_grid_attach(GTK_GRID(grid),step_b,(i%5),i/5,1,1);
+    i++;
 
     GtkWidget *meter_b=gtk_button_new_with_label("Meter");
     g_signal_connect (meter_b, "button-press-event", G_CALLBACK(meter_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),meter_b,1,3,1,1);
+    gtk_grid_attach(GTK_GRID(grid),meter_b,(i%5),i/5,1,1);
+    i++;
 
     GtkWidget *vox_b=gtk_button_new_with_label("VOX");
-    g_signal_connect (vox_b, "button-press-event", G_CALLBACK(vox_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),vox_b,2,3,1,1);
-
-    GtkWidget *frequency_b=gtk_button_new_with_label("Frequency");
-    g_signal_connect (frequency_b, "button-press-event", G_CALLBACK(freqent_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),frequency_b,3,3,1,1);
+    g_signal_connect (vox_b, "button-press-event", G_CALLBACK(vox_b_cb), NULL);
+    gtk_grid_attach(GTK_GRID(grid),vox_b,(i%5),i/5,1,1);
+    i++;
 
+#ifdef DIVERSITY
     if(RECEIVERS==2) {
       GtkWidget *diversity_b=gtk_button_new_with_label("Diversity");
       g_signal_connect (diversity_b, "button-press-event", G_CALLBACK(diversity_cb), NULL);
-      gtk_grid_attach(GTK_GRID(grid),diversity_b,4,3,1,1);
+      gtk_grid_attach(GTK_GRID(grid),diversity_b,(i%5),i/5,1,1);
+      i++;
     }
-
-    GtkWidget *band_b=gtk_button_new_with_label("Band");
-    g_signal_connect (band_b, "button-press-event", G_CALLBACK(band_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),band_b,0,4,1,1);
-
-    GtkWidget *bandstack_b=gtk_button_new_with_label("Band Stack");
-    g_signal_connect (bandstack_b, "button-press-event", G_CALLBACK(bandstack_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),bandstack_b,1,4,1,1);
-
-    GtkWidget *mode_b=gtk_button_new_with_label("Mode");
-    g_signal_connect (mode_b, "button-press-event", G_CALLBACK(mode_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),mode_b,2,4,1,1);
-
-    GtkWidget *filter_b=gtk_button_new_with_label("Filter");
-    g_signal_connect (filter_b, "button-press-event", G_CALLBACK(filter_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),filter_b,3,4,1,1);
-
-    GtkWidget *noise_b=gtk_button_new_with_label("Noise");
-    g_signal_connect (noise_b, "button-press-event", G_CALLBACK(noise_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),noise_b,4,4,1,1);
-
-    GtkWidget *agc_b=gtk_button_new_with_label("AGC");
-    g_signal_connect (agc_b, "button-press-event", G_CALLBACK(agc_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),agc_b,5,4,1,1);
-
-    GtkWidget *test_b=gtk_button_new_with_label("Test");
-    g_signal_connect (test_b, "button-press-event", G_CALLBACK(test_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),test_b,0,5,1,1);
+#endif
 
     gtk_container_add(GTK_CONTAINER(content),grid);
 
@@ -432,18 +501,4 @@ static gboolean new_menu_pressed_event_cb (GtkWidget *widget,
     dialog=NULL;
   }
 
-  return TRUE;
-}
-
-GtkWidget* new_menu_init(int width,int height,GtkWidget *parent) {
-
-  parent_window=parent;
-
-  menu_b=gtk_button_new_with_label("Menu");
-  gtk_widget_override_font(menu_b, pango_font_description_from_string("FreeMono Bold 10"));
-  gtk_widget_set_size_request (menu_b, width, height);
-  g_signal_connect (menu_b, "button-press-event", G_CALLBACK(new_menu_pressed_event_cb), NULL);
-  gtk_widget_show(menu_b);
-
-  return menu_b;
 }
index 3caac57341d7720548837bfea22c1bc7b990b77e..ea2217979ae2ba62ae28e214d468be20e3efccc2 100644 (file)
@@ -1,11 +1,32 @@
 GtkWidget *sub_menu;
 
-GtkWidget* new_menu_init(int width,int height,GtkWidget *parent);
-
-void start_step();
-void start_meter();
-void start_band();
-void start_bandstack();
-void start_mode();
-void start_filter();
-void start_noise();
+extern void new_menu();
+
+/*
+extern GtkWidget* new_menu_init(int width,int height,GtkWidget *parent);
+*/
+extern void start_step();
+extern void start_meter();
+extern void start_band();
+extern void start_bandstack();
+extern void start_mode();
+extern void start_filter();
+extern void start_noise();
+extern void start_encoder();
+
+extern void encoder_step(int encoder,int step);
+
+enum {
+  NO_MENU = 0,
+  E1_MENU,
+  E2_MENU,
+  E3_MENU,
+  BAND_MENU,
+  BANDSTACK_MENU,
+  MODE_MENU,
+  FILTER_MENU,
+  NOISE_MENU,
+  AGC_MENU
+};
+
+extern int active_menu;
index 75972ef325cd1f9822879f045809a44aae396595..fa48079de7362f7f0275aab409f412644f0b574d 100644 (file)
 #include <net/if_arp.h>
 #include <net/if.h>
 #include <ifaddrs.h>
-#include <pthread.h>
 #include <semaphore.h>
 #include <math.h>
 
+#include <wdsp.h>
+
 #include "alex.h"
 #include "audio.h"
 #include "band.h"
 #include "new_protocol.h"
 #include "channel.h"
 #include "discovered.h"
-#include "wdsp.h"
 #include "mode.h"
 #include "filter.h"
 #include "radio.h"
+#include "receiver.h"
+#include "transmitter.h"
 #include "signal.h"
 #include "vfo.h"
 #include "toolbar.h"
-#include "wdsp_init.h"
 #ifdef FREEDV
 #include "freedv.h"
 #endif
@@ -89,11 +90,11 @@ static int audio_addr_length;
 static struct sockaddr_in iq_addr;
 static int iq_addr_length;
 
-static struct sockaddr_in data_addr[RECEIVERS];
-static int data_addr_length[RECEIVERS];
+static struct sockaddr_in data_addr[MAX_RECEIVERS];
+static int data_addr_length[MAX_RECEIVERS];
 
-static pthread_t new_protocol_thread_id;
-static pthread_t new_protocol_timer_thread_id;
+static GThread *new_protocol_thread_id;
+static GThread *new_protocol_timer_thread_id;
 
 static long rx_sequence = 0;
 
@@ -102,18 +103,18 @@ static long general_sequence = 0;
 static long rx_specific_sequence = 0;
 static long tx_specific_sequence = 0;
 
-static int buffer_size=BUFFER_SIZE;
-static int fft_size=4096;
+//static int buffer_size=BUFFER_SIZE;
+//static int fft_size=4096;
 static int dspRate=48000;
 static int outputRate=48000;
 
 static int micSampleRate=48000;
 static int micDspRate=48000;
 static int micOutputRate=192000;
-static int micoutputsamples=BUFFER_SIZE*4;  // 48000 in, 192000 out
+static int micoutputsamples;  // 48000 in, 192000 out
 
-static double micinputbuffer[BUFFER_SIZE*2]; // 48000
-static double iqoutputbuffer[BUFFER_SIZE*4*2]; //192000
+static double micinputbuffer[MAX_BUFFER_SIZE*2]; // 48000
+static double iqoutputbuffer[MAX_BUFFER_SIZE*4*2]; //192000
 
 static long tx_iq_sequence;
 static unsigned char iqbuffer[1444];
@@ -133,11 +134,10 @@ static int send_high_priority=0;
 static sem_t send_general_sem;
 static int send_general=0;
 
-static int samples[RECEIVERS];
-static int outputsamples=BUFFER_SIZE;
-
-static double iqinputbuffer[RECEIVERS][BUFFER_SIZE*2];
-static double audiooutputbuffer[BUFFER_SIZE*2];
+static int samples[MAX_RECEIVERS];
+#ifdef INCLUDED
+static int outputsamples;
+#endif
 
 static int leftaudiosample;
 static int rightaudiosample;
@@ -158,40 +158,48 @@ static int psk_samples=0;
 static int psk_resample=6;  // convert from 48000 to 8000
 #endif
 
+static struct sockaddr_in addr;
+static int length;
+static unsigned char buffer[2048];
+static int bytesread;
+
 static void new_protocol_high_priority(int run);
-static void* new_protocol_thread(void* arg);
-static void* new_protocol_timer_thread(void* arg);
-static void  process_iq_data(int rx,unsigned char *buffer);
+//static void* new_protocol_thread(void* arg);
+static gpointer new_protocol_thread(gpointer data);
+//static void* new_protocol_timer_thread(void* arg);
+static gpointer new_protocol_timer_thread(gpointer data);
+static void  process_iq_data(RECEIVER *rx,unsigned char *buffer);
 static void  process_command_response(unsigned char *buffer);
 static void  process_high_priority(unsigned char *buffer);
-static void  process_mic_data(unsigned char *buffer);
-static void full_rx_buffer();
+static void  process_mic_data(unsigned char *buffer,int bytes);
 static void full_tx_buffer();
 
+#ifdef INCLUDED
 static void new_protocol_calc_buffers() {
   switch(sample_rate) {
     case 48000:
-      outputsamples=BUFFER_SIZE;
+      outputsamples=buffer_size;
       break;
     case 96000:
-      outputsamples=BUFFER_SIZE/2;
+      outputsamples=buffer_size/2;
       break;
     case 192000:
-      outputsamples=BUFFER_SIZE/4;
+      outputsamples=buffer_size/4;
       break;
     case 384000:
-      outputsamples=BUFFER_SIZE/8;
+      outputsamples=buffer_size/8;
       break;
     case 768000:
-      outputsamples=BUFFER_SIZE/16;
+      outputsamples=buffer_size/16;
       break;
     case 1536000:
-      outputsamples=BUFFER_SIZE/32;
+      outputsamples=buffer_size/32;
       break;
   }
 }
+#endif
 
-void schedule_high_priority(int source) {
+void schedule_high_priority() {
     sem_wait(&send_high_priority_sem);
     send_high_priority=1;
     sem_post(&send_high_priority_sem);
@@ -229,42 +237,46 @@ void new_protocol_init(int pixels) {
     int rc;
     spectrumWIDTH=pixels;
 
-    fprintf(stderr,"new_protocol_init\n");
+    fprintf(stderr,"new_protocol_init: MIC_SAMPLES=%d\n",MIC_SAMPLES);
 
+#ifdef INCLUDED
+    outputsamples=buffer_size;
+#endif
+    micoutputsamples=buffer_size*4;
+
+#ifdef OLD_AUDIO
     if(local_audio) {
       if(audio_open_output()!=0) {
         fprintf(stderr,"audio_open_output failed\n");
         local_audio=0;
       }
     }
+#endif
 
-    if(local_microphone) {
+    if(transmitter->local_microphone) {
       if(audio_open_input()!=0) {
         fprintf(stderr,"audio_open_input failed\n");
-        local_microphone=0;
+        transmitter->local_microphone=0;
       }
     }
 
+#ifdef INCLUDED
     new_protocol_calc_buffers();
+#endif
 
     rc=sem_init(&response_sem, 0, 0);
     rc=sem_init(&send_high_priority_sem, 0, 1);
     rc=sem_init(&send_general_sem, 0, 1);
 
-    rc=pthread_create(&new_protocol_thread_id,NULL,new_protocol_thread,NULL);
-    if(rc != 0) {
-        fprintf(stderr,"pthread_create failed on new_protocol_thread: rc=%d\n", rc);
-        exit(-1);
+    new_protocol_thread_id = g_thread_new( "new protocol", new_protocol_thread, NULL);
+    if( ! new_protocol_thread_id )
+    {
+        fprintf(stderr,"g_thread_new failed on new_protocol_thread\n");
+        exit( -1 );
     }
+    fprintf(stderr, "new_protocol_thread: id=%p\n",new_protocol_thread_id);
 
-}
 
-void new_protocol_new_sample_rate(int rate) {
-  new_protocol_high_priority(0);
-  sample_rate=rate;
-  new_protocol_calc_buffers();
-  wdsp_new_sample_rate(rate);
-  new_protocol_high_priority(1);
 }
 
 static void new_protocol_general() {
@@ -291,13 +303,19 @@ static void new_protocol_general() {
     }
 
     if(filter_board==APOLLO) {
-        buffer[58]|=0x02; // enable APOLLO tuner
+      buffer[58]|=0x02; // enable APOLLO tuner
     }
 
     if(filter_board==ALEX) {
+      if(device==NEW_DEVICE_ORION2) {
+        buffer[59]=0x03;  // enable Alex 0 and 1
+      } else {
         buffer[59]=0x01;  // enable Alex 0
+      }
     }
 
+fprintf(stderr,"Alex Enable=%02X\n",buffer[59]);
+
     if(sendto(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&base_addr,base_addr_length)<0) {
         fprintf(stderr,"sendto socket failed for general\n");
         exit(1);
@@ -307,9 +325,13 @@ static void new_protocol_general() {
 }
 
 static void new_protocol_high_priority(int run) {
-    int r;
+    int i, r;
     unsigned char buffer[1444];
-    BAND *band=band_get_current_band();
+    BAND *band;
+    long long rxFrequency;
+    long long txFrequency;
+    long phase;
+    int mode;
 
     memset(buffer, 0, sizeof(buffer));
 
@@ -318,6 +340,11 @@ static void new_protocol_high_priority(int run) {
     buffer[2]=high_priority_sequence>>8;
     buffer[3]=high_priority_sequence;
 
+    if(split) {
+      mode=vfo[1].mode;
+    } else {
+      mode=vfo[0].mode;
+    }
     buffer[4]=run;
     if(mode==modeCWU || mode==modeCWL) {
       if(tune) {
@@ -340,28 +367,38 @@ static void new_protocol_high_priority(int run) {
       }
     }
 
-    long rxFrequency=ddsFrequency;
-    if(mode==modeCWU) {
-      rxFrequency-=cw_keyer_sidetone_frequency;
-    } else if(mode==modeCWL) {
-      rxFrequency+=cw_keyer_sidetone_frequency;
-    }
-    long phase=(long)((4294967296.0*(double)rxFrequency)/122880000.0);
-
 // rx
 
     for(r=0;r<receivers;r++) {
-      buffer[9+(r*4)]=phase>>24;
-      buffer[10+(r*4)]=phase>>16;
-      buffer[11+(r*4)]=phase>>8;
-      buffer[12+(r*4)]=phase;
+      //long long rxFrequency=ddsFrequency;
+      //rxFrequency=receiver[r]->dds_frequency;
+      int v=receiver[r]->id;
+      rxFrequency=vfo[v].frequency-vfo[v].lo+vfo[v].rit;
+
+      if(vfo[v].mode==modeCWU) {
+        rxFrequency-=cw_keyer_sidetone_frequency;
+      } else if(vfo[v].mode==modeCWL) {
+        rxFrequency+=cw_keyer_sidetone_frequency;
+      }
+      phase=(long)((4294967296.0*(double)rxFrequency)/122880000.0);
+
+      i=r;
+      //if(device==NEW_DEVICE_ORION2 && r==1) i=3;
+      buffer[9+(i*4)]=phase>>24;
+      buffer[10+(i*4)]=phase>>16;
+      buffer[11+(i*4)]=phase>>8;
+      buffer[12+(i*4)]=phase;
     }
 
-// tx (no split yet)
-    long long txFrequency=ddsFrequency;
-    if(ctun) {
-      txFrequency+=ddsOffset;
+    // tx
+    band=band_get_band(vfo[VFO_A].band);
+    rxFrequency=vfo[VFO_A].frequency-vfo[VFO_A].lo;
+    txFrequency=vfo[VFO_A].frequency-vfo[VFO_A].lo;
+    if(split) {
+      band=band_get_band(vfo[VFO_B].band);
+      txFrequency=vfo[VFO_B].frequency-vfo[VFO_B].lo;
     }
+
     phase=(long)((4294967296.0*(double)txFrequency)/122880000.0);
 
     buffer[329]=phase>>24;
@@ -381,21 +418,38 @@ static void new_protocol_high_priority(int run) {
     buffer[345]=power&0xFF;
 
     if(isTransmitting()) {
-      buffer[1401]=band->OCtx;
+
+      if(split) {
+        band=band_get_band(vfo[VFO_B].band);
+      } else {
+        band=band_get_band(vfo[VFO_A].band);
+      }
+      buffer[1401]=band->OCtx<<1;
       if(tune) {
         if(OCmemory_tune_time!=0) {
           struct timeval te;
           gettimeofday(&te,NULL);
           long long now=te.tv_sec*1000LL+te.tv_usec/1000;
           if(tune_timeout>now) {
-            buffer[1401]|=OCtune;
+            buffer[1401]|=OCtune<<1;
           }
         } else {
-          buffer[1401]|=OCtune;
+          buffer[1401]|=OCtune<<1;
         }
       }
     } else {
-      buffer[1401]=band->OCrx;
+      band=band_get_band(vfo[VFO_A].band);
+      buffer[1401]=band->OCrx<<1;
+    }
+
+    if((protocol==ORIGINAL_PROTOCOL && device==DEVICE_METIS) ||
+#ifdef USBOZY
+       (protocol==ORIGINAL_PROTOCOL && device==DEVICE_OZY) ||
+#endif
+       (protocol==NEW_PROTOCOL && device==NEW_DEVICE_ATLAS)) {
+      for(r=0;r<receivers;r++) {
+        buffer[1403]|=receiver[i]->preamp;
+      }
     }
 
 
@@ -405,59 +459,41 @@ static void new_protocol_high_priority(int run) {
       filters=0x08000000;
     }
 
-// Alex RX HPF filters
-/*
-if              (frequency <  1800000) HPF <= 6'b100000;        // bypass
-else if (frequency <  6500000) HPF <= 6'b010000;        // 1.5MHz HPF   
-else if (frequency <  9500000) HPF <= 6'b001000;        // 6.5MHz HPF
-else if (frequency < 13000000) HPF <= 6'b000100;        // 9.5MHz HPF
-else if (frequency < 20000000) HPF <= 6'b000001;        // 13MHz HPF
-else                                               HPF <= 6'b000010;    // 20MHz HPF
-*/
-
-    if(ddsFrequency<1800000L) {
+    if(rxFrequency<1800000L) {
         filters|=ALEX_BYPASS_HPF;
-    } else if(ddsFrequency<6500000L) {
+    } else if(rxFrequency<6500000L) {
         filters|=ALEX_1_5MHZ_HPF;
-    } else if(ddsFrequency<9500000L) {
+    } else if(rxFrequency<9500000L) {
         filters|=ALEX_6_5MHZ_HPF;
-    } else if(ddsFrequency<13000000L) {
+    } else if(rxFrequency<13000000L) {
         filters|=ALEX_9_5MHZ_HPF;
-    } else if(ddsFrequency<20000000L) {
+    } else if(rxFrequency<20000000L) {
         filters|=ALEX_13MHZ_HPF;
     } else {
         filters|=ALEX_20MHZ_HPF;
     }
 
-// Alex TX LPF filters
-/*
-if (frequency > 32000000)   LPF <= 7'b0010000;             // > 10m so use 6m LPF^M
-else if (frequency > 22000000) LPF <= 7'b0100000;       // > 15m so use 12/10m LPF^M
-else if (frequency > 15000000) LPF <= 7'b1000000;       // > 20m so use 17/15m LPF^M
-else if (frequency > 8000000)  LPF <= 7'b0000001;       // > 40m so use 30/20m LPF  ^M
-else if (frequency > 4500000)  LPF <= 7'b0000010;       // > 80m so use 60/40m LPF^M
-else if (frequency > 2400000)  LPF <= 7'b0000100;       // > 160m so use 80m LPF  ^M
-else LPF <= 7'b0001000;             // < 2.4MHz so use 160m LPF^M
-*/
+    if(rxFrequency>30000000L) {
+        filters|=ALEX_6M_PREAMP;
+    }
 
-    if(ddsFrequency>32000000) {
+    if(txFrequency>32000000) {
         filters|=ALEX_6_BYPASS_LPF;
-    } else if(ddsFrequency>22000000) {
+    } else if(txFrequency>22000000) {
         filters|=ALEX_12_10_LPF;
-    } else if(ddsFrequency>15000000) {
+    } else if(txFrequency>15000000) {
         filters|=ALEX_17_15_LPF;
-    } else if(ddsFrequency>8000000) {
+    } else if(txFrequency>8000000) {
         filters|=ALEX_30_20_LPF;
-    } else if(ddsFrequency>4500000) {
+    } else if(txFrequency>4500000) {
         filters|=ALEX_60_40_LPF;
-    } else if(ddsFrequency>2400000) {
+    } else if(txFrequency>2400000) {
         filters|=ALEX_80_LPF;
     } else {
         filters|=ALEX_160_LPF;
     }
 
-
-    switch(band->alexRxAntenna) {
+    switch(receiver[0]->alex_antenna) {
         case 0:  // ANT 1
           break;
         case 1:  // ANT 2
@@ -480,7 +516,7 @@ else LPF <= 7'b0001000;             // < 2.4MHz so use 160m LPF^M
     }
 
     if(isTransmitting()) {
-      switch(band->alexTxAntenna) {
+      switch(transmitter->alex_antenna) {
         case 0:  // ANT 1
           filters|=ALEX_TX_ANTENNA_1;
           break;
@@ -498,7 +534,7 @@ else LPF <= 7'b0001000;             // < 2.4MHz so use 160m LPF^M
          
       }
     } else {
-      switch(band->alexRxAntenna) {
+      switch(receiver[0]->alex_antenna) {
         case 0:  // ANT 1
           filters|=ALEX_TX_ANTENNA_1;
           break;
@@ -511,7 +547,7 @@ else LPF <= 7'b0001000;             // < 2.4MHz so use 160m LPF^M
         case 3:  // EXT 1
         case 4:  // EXT 2
         case 5:  // XVTR
-          switch(band->alexTxAntenna) {
+          switch(transmitter->alex_antenna) {
             case 0:  // ANT 1
               filters|=ALEX_TX_ANTENNA_1;
               break;
@@ -530,12 +566,44 @@ else LPF <= 7'b0001000;             // < 2.4MHz so use 160m LPF^M
     buffer[1433]=(filters>>16)&0xFF;
     buffer[1434]=(filters>>8)&0xFF;
     buffer[1435]=filters&0xFF;
+//fprintf(stderr,"HPF: 0: %02X %02X for %lld\n",buffer[1434],buffer[1435],rxFrequency);
+
+    filters=0x00000000;
+    rxFrequency=vfo[VFO_B].frequency-vfo[VFO_B].lo;
+    if(rxFrequency<1800000L) {
+        filters|=ALEX_BYPASS_HPF;
+    } else if(rxFrequency<6500000L) {
+        filters|=ALEX_1_5MHZ_HPF;
+    } else if(rxFrequency<9500000L) {
+        filters|=ALEX_6_5MHZ_HPF;
+    } else if(rxFrequency<13000000L) {
+        filters|=ALEX_9_5MHZ_HPF;
+    } else if(rxFrequency<20000000L) {
+        filters|=ALEX_13MHZ_HPF;
+    } else {
+        filters|=ALEX_20MHZ_HPF;
+    }
+
+    if(rxFrequency>30000000L) {
+        filters|=ALEX_6M_PREAMP;
+    }
 
-    //buffer[1442]=attenuation;
-    buffer[1443]=attenuation;
 
-//fprintf(stderr,"high_priority[4]=0x%02X\n", buffer[4]);
-//fprintf(stderr,"filters=%04X\n", filters);
+    buffer[1428]=(filters>>24)&0xFF;
+    buffer[1429]=(filters>>16)&0xFF;
+    buffer[1430]=(filters>>8)&0xFF;
+    buffer[1431]=filters&0xFF;
+
+//fprintf(stderr,"HPF: 1: %02X %02X for %lld\n",buffer[1430],buffer[1431],rxFrequency);
+// rx_frequency
+
+//fprintf(stderr,"new_protocol_high_priority: OC=%02X filters=%04X for frequency=%lld\n", buffer[1401], filters, rxFrequency);
+
+    for(r=0;r<receivers;r++) {
+      i=r;
+      //if(device==NEW_DEVICE_ORION2 && r==1) i=3;
+      buffer[1443-i]=receiver[r]->attenuation;
+    }
 
     if(sendto(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&high_priority_addr,high_priority_addr_length)<0) {
         fprintf(stderr,"sendto socket failed for high priority\n");
@@ -547,6 +615,7 @@ else LPF <= 7'b0001000;             // < 2.4MHz so use 160m LPF^M
 
 static void new_protocol_transmit_specific() {
     unsigned char buffer[60];
+    int mode;
 
     memset(buffer, 0, sizeof(buffer));
 
@@ -555,6 +624,11 @@ static void new_protocol_transmit_specific() {
     buffer[2]=tx_specific_sequence>>8;
     buffer[3]=tx_specific_sequence;
 
+    if(split) {
+      mode=vfo[1].mode;
+    } else {
+      mode=vfo[0].mode;
+    }
     buffer[4]=1; // 1 DAC
     buffer[5]=0; //  default no CW
     // may be using local pihpsdr OR hpsdr CW
@@ -581,10 +655,12 @@ static void new_protocol_transmit_specific() {
     }
 
     buffer[6]=cw_keyer_sidetone_volume; // sidetone off
-    buffer[7]=cw_keyer_sidetone_frequency>>8; buffer[8]=cw_keyer_sidetone_frequency; // sidetone frequency
+    buffer[7]=cw_keyer_sidetone_frequency>>8;
+    buffer[8]=cw_keyer_sidetone_frequency; // sidetone frequency
     buffer[9]=cw_keyer_speed; // cw keyer speed
     buffer[10]=cw_keyer_weight; // cw weight
-    buffer[11]=cw_keyer_hang_time>>8; buffer[12]=cw_keyer_hang_time; // cw hang delay
+    buffer[11]=cw_keyer_hang_time>>8;
+    buffer[12]=cw_keyer_hang_time; // cw hang delay
     buffer[13]=0; // rf delay
     buffer[50]=0;
     if(mic_linein) {
@@ -593,15 +669,15 @@ static void new_protocol_transmit_specific() {
     if(mic_boost) {
       buffer[50]|=0x02;
     }
-    if(mic_ptt_enabled==0) {
+    if(mic_ptt_enabled==0) {  // set if disabled
       buffer[50]|=0x04;
     }
-    if(mic_bias_enabled) {
-      buffer[50]|=0x10;
-    }
     if(mic_ptt_tip_bias_ring) {
       buffer[50]|=0x08;
     }
+    if(mic_bias_enabled) {
+      buffer[50]|=0x10;
+    }
 
     // 0..31
     buffer[51]=linein_gain;
@@ -627,34 +703,19 @@ static void new_protocol_receive_specific() {
     buffer[3]=rx_specific_sequence;
 
     buffer[4]=2; // 2 ADCs
-    buffer[5]=0; // dither off
-    if(lt2208Dither) {
-      for(i=0;i<receivers;i++) {
-        buffer[5]|=0x01<<i;
-      }
-    }
-    buffer[6]=0; // random off
-    if(lt2208Random) {
-      for(i=0;i<receivers;i++) {
-        buffer[6]|=0x01<<i;
-      }
-    }
-    buffer[7]=0x00;
-    for(i=0;i<receivers;i++) {
-      buffer[7]|=(1<<i);
-    }
-       
+
     for(i=0;i<receivers;i++) {
-      buffer[17+(i*6)]=adc[i];
+      int r=i;
+      //if(device==NEW_DEVICE_ORION2 && r==1) r=3;
+      buffer[5]|=receiver[i]->dither<<r; // dither enable
+      buffer[6]|=receiver[i]->random<<r; // random enable
+      buffer[7]|=(1<<r); // DDC enbale
+      buffer[17+(r*6)]=receiver[i]->adc;
+      buffer[18+(r*6)]=((receiver[i]->sample_rate/1000)>>8)&0xFF;
+      buffer[19+(r*6)]=(receiver[i]->sample_rate/1000)&0xFF;
+      buffer[22+(r*6)]=24;
     }
 
-    buffer[18]=((sample_rate/1000)>>8)&0xFF;
-    buffer[19]=(sample_rate/1000)&0xFF;
-    buffer[22]=24;
-
-    buffer[24]=((sample_rate/1000)>>8)&0xFF;
-    buffer[25]=(sample_rate/1000)&0xFF;
-    buffer[28]=24;
 
     if(sendto(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&receiver_addr,receiver_addr_length)<0) {
         fprintf(stderr,"sendto socket failed for start\n");
@@ -668,17 +729,23 @@ static void new_protocol_start() {
     running=1;
     new_protocol_transmit_specific();
     new_protocol_receive_specific();
-    int rc=pthread_create(&new_protocol_timer_thread_id,NULL,new_protocol_timer_thread,NULL);
-    if(rc != 0) {
-        fprintf(stderr,"pthread_create failed on new_protocol_timer_thread: %d\n", rc);
-        exit(-1);
+    new_protocol_timer_thread_id = g_thread_new( "new protocol timer", new_protocol_timer_thread, NULL);
+    if( ! new_protocol_timer_thread_id )
+    {
+        fprintf(stderr,"g_thread_new failed on new_protocol_timer_thread\n");
+        exit( -1 );
     }
+    fprintf(stderr, "new_protocol_timer_thread: id=%p\n",new_protocol_timer_thread_id);
+
 }
 
 void new_protocol_stop() {
     new_protocol_high_priority(0);
-    running=0;
-    sleep(1);
+    usleep(100000); // 100 ms
+}
+
+void new_protocol_run() {
+    new_protocol_high_priority(1);
 }
 
 double calibrate(int v) {
@@ -689,13 +756,10 @@ double calibrate(int v) {
     return (v1*v1)/0.095;
 }
 
-void* new_protocol_thread(void* arg) {
+//void* new_protocol_thread(void* arg) {
+static gpointer new_protocol_thread(gpointer data) {
 
     int i;
-    struct sockaddr_in addr;
-    int length;
-    unsigned char buffer[2048];
-    int bytesread;
     short sourceport;
 
 fprintf(stderr,"new_protocol_thread\n");
@@ -704,7 +768,6 @@ fprintf(stderr,"new_protocol_thread\n");
     iqindex=4;
 
 
-fprintf(stderr,"outputsamples=%d\n", outputsamples);
     data_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
     if(data_socket<0) {
         fprintf(stderr,"metis: create socket failed for data_socket\n");
@@ -745,7 +808,7 @@ fprintf(stderr,"outputsamples=%d\n", outputsamples);
     iq_addr.sin_port=htons(TX_IQ_FROM_HOST_PORT);
 
    
-    for(i=0;i<RECEIVERS;i++) {
+    for(i=0;i<MAX_RECEIVERS;i++) {
         memcpy(&data_addr[i],&radio->info.network.address,radio->info.network.address_length);
         data_addr_length[i]=radio->info.network.address_length;
         data_addr[i].sin_port=htons(RX_IQ_TO_HOST_PORT_0+i);
@@ -779,7 +842,11 @@ fprintf(stderr,"outputsamples=%d\n", outputsamples);
             case RX_IQ_TO_HOST_PORT_5:
             case RX_IQ_TO_HOST_PORT_6:
             case RX_IQ_TO_HOST_PORT_7:
-              process_iq_data(sourceport-RX_IQ_TO_HOST_PORT_0,buffer);
+              i=sourceport-RX_IQ_TO_HOST_PORT_0;
+              //if(device==NEW_DEVICE_ORION2 && i==3) {
+              //  i=1;
+              //}
+              process_iq_data(receiver[i],buffer);
               break;
             case COMMAND_RESPONCE_TO_HOST_PORT:
               process_command_response(buffer);
@@ -788,8 +855,8 @@ fprintf(stderr,"outputsamples=%d\n", outputsamples);
               process_high_priority(buffer);
               break;
             case MIC_LINE_TO_HOST_PORT:
-              if(!local_microphone) {
-                process_mic_data(buffer);
+              if(!transmitter->local_microphone) {
+                process_mic_data(buffer,bytesread);
               }
               break;
             default:
@@ -797,19 +864,19 @@ fprintf(stderr,"outputsamples=%d\n", outputsamples);
         }
 
         if(running) {
-           sem_wait(&send_general_sem);
-           if(send_general==1) {
-               new_protocol_general();
-               send_general=0;
-           }
-           sem_post(&send_general_sem);
-
            sem_wait(&send_high_priority_sem);
            if(send_high_priority==1) {
                new_protocol_high_priority(1);
                send_high_priority=0;
            }
            sem_post(&send_high_priority_sem);
+
+           sem_wait(&send_general_sem);
+           if(send_general==1) {
+               new_protocol_general();
+               send_general=0;
+           }
+           sem_post(&send_general_sem);
        }
         
     }
@@ -817,47 +884,39 @@ fprintf(stderr,"outputsamples=%d\n", outputsamples);
     close(data_socket);
 }
 
-static void process_iq_data(int rx,unsigned char *buffer) {
-    long sequence;
-    long long timestamp;
-    int bitspersample;
-    int samplesperframe;
-    int b;
-    int leftsample;
-    int rightsample;
-    double leftsampledouble;
-    double rightsampledouble;
-
-    sequence=((buffer[0]&0xFF)<<24)+((buffer[1]&0xFF)<<16)+((buffer[2]&0xFF)<<8)+(buffer[3]&0xFF);
-    timestamp=((long long)(buffer[4]&0xFF)<<56)+((long long)(buffer[5]&0xFF)<<48)+((long long)(buffer[6]&0xFF)<<40)+((long long)(buffer[7]&0xFF)<<32);
-    ((long long)(buffer[8]&0xFF)<<24)+((long long)(buffer[9]&0xFF)<<16)+((long long)(buffer[10]&0xFF)<<8)+(long long)(buffer[11]&0xFF);
-    bitspersample=((buffer[12]&0xFF)<<8)+(buffer[13]&0xFF);
-    samplesperframe=((buffer[14]&0xFF)<<8)+(buffer[15]&0xFF);
-
-    //if(!isTransmitting()) {
-        b=16;
-        int i;
-        for(i=0;i<samplesperframe;i++) {
-            leftsample   = (int)((signed char) buffer[b++]) << 16;
-            leftsample  += (int)((unsigned char)buffer[b++]) << 8;
-            leftsample  += (int)((unsigned char)buffer[b++]);
-            rightsample  = (int)((signed char) buffer[b++]) << 16;
-            rightsample += (int)((unsigned char)buffer[b++]) << 8;
-            rightsample += (int)((unsigned char)buffer[b++]);
-
-            leftsampledouble=(double)leftsample/8388607.0; // for 24 bits
-            rightsampledouble=(double)rightsample/8388607.0; // for 24 bits
-
-            iqinputbuffer[rx][samples[rx]*2]=leftsampledouble;
-            iqinputbuffer[rx][(samples[rx]*2)+1]=rightsampledouble;
-
-            samples[rx]++;
-            if(samples[rx]==BUFFER_SIZE) {
-                full_rx_buffer(rx);
-                samples[rx]=0;
-            }
-       }
-  //}
+static void process_iq_data(RECEIVER *rx,unsigned char *buffer) {
+  long sequence;
+  long long timestamp;
+  int bitspersample;
+  int samplesperframe;
+  int b;
+  int leftsample;
+  int rightsample;
+  double leftsampledouble;
+  double rightsampledouble;
+
+  sequence=((buffer[0]&0xFF)<<24)+((buffer[1]&0xFF)<<16)+((buffer[2]&0xFF)<<8)+(buffer[3]&0xFF);
+  timestamp=((long long)(buffer[4]&0xFF)<<56)+((long long)(buffer[5]&0xFF)<<48)+((long long)(buffer[6]&0xFF)<<40)+((long long)(buffer[7]&0xFF)<<32);
+  ((long long)(buffer[8]&0xFF)<<24)+((long long)(buffer[9]&0xFF)<<16)+((long long)(buffer[10]&0xFF)<<8)+(long long)(buffer[11]&0xFF);
+  bitspersample=((buffer[12]&0xFF)<<8)+(buffer[13]&0xFF);
+  samplesperframe=((buffer[14]&0xFF)<<8)+(buffer[15]&0xFF);
+
+//fprintf(stderr,"process_iq_data: rx=%d seq=%ld bitspersample=%d samplesperframe=%d\n",rx->id, sequence,bitspersample,samplesperframe);
+  b=16;
+  int i;
+  for(i=0;i<samplesperframe;i++) {
+    leftsample   = (int)((signed char) buffer[b++])<<16;
+    leftsample  |= (int)((((unsigned char)buffer[b++])<<8)&0xFF00);
+    leftsample  |= (int)((unsigned char)buffer[b++]&0xFF);
+    rightsample  = (int)((signed char)buffer[b++]) << 16;
+    rightsample |= (int)((((unsigned char)buffer[b++])<<8)&0xFF00);
+    rightsample |= (int)((unsigned char)buffer[b++]&0xFF);
+
+    leftsampledouble=(double)leftsample/8388607.0; // for 24 bits
+    rightsampledouble=(double)rightsample/8388607.0; // for 24 bits
+
+    add_iq_samples(rx, leftsampledouble,rightsampledouble);
+  }
 }
 
 static void process_command_response(unsigned char *buffer) {
@@ -907,361 +966,104 @@ if(dash!=previous_dash) {
 
 }
 
-static void process_mic_data(unsigned char *buffer) {
-    long sequence;
-    int b;
-    int micsample;
-    double micsampledouble;
-    double gain=pow(10, mic_gain/20.0);
-
-    sequence=((buffer[0]&0xFF)<<24)+((buffer[1]&0xFF)<<16)+((buffer[2]&0xFF)<<8)+(buffer[3]&0xFF);
-//    if(isTransmitting()) {
-        b=4;
-        int i,j,s;
-        for(i=0;i<MIC_SAMPLES;i++) {
-            micsample  = (int)((signed char) buffer[b++]) << 8;
-            micsample  |= (int)((unsigned char)buffer[b++] & 0xFF);
-            micsampledouble = (1.0 / 2147483648.0) * (double)(micsample<<16);
-#ifdef FREEDV
-            if(mode==modeFREEDV && isTransmitting()) {
-                if(freedv_samples==0) { // 48K to 8K
-                    int sample=(int)((double)micsample*pow(10.0, mic_gain / 20.0));
-                    int modem_samples=mod_sample_freedv(sample);
-                    if(modem_samples!=0) {
-                      for(s=0;s<modem_samples;s++) {
-                        for(j=0;j<freedv_resample;j++) {  // 8K to 48K
-                          micsample=mod_out[s];
-                          micsampledouble = (1.0 / 2147483648.0) * (double)(micsample<<16);
-                          micinputbuffer[micsamples*2]=micsampledouble;
-                          micinputbuffer[(micsamples*2)+1]=micsampledouble;
-                          micsamples++;
-                          if(micsamples==BUFFER_SIZE) {
-                            full_tx_buffer();
-                            micsamples=0;
-                          }
-                        }
-                      }
-                    }
-               }
-               freedv_samples++;
-               if(freedv_samples==freedv_resample) {
-                   freedv_samples=0;
-               }
-            } else {
-#endif
-               if(mode==modeCWL || mode==modeCWU || tune /*|| !isTransmitting()*/) {
-                   micinputbuffer[micsamples*2]=0.0;
-                   micinputbuffer[(micsamples*2)+1]=0.0;
-               } else {
-                   micinputbuffer[micsamples*2]=micsampledouble;
-                   micinputbuffer[(micsamples*2)+1]=micsampledouble;
-               }
-
-               micsamples++;
-
-               if(micsamples==BUFFER_SIZE) {
-                   full_tx_buffer();
-                   micsamples=0;
-               }
-#ifdef FREEDV
-           }
-#endif
-
-        }
-//    }
-
-}
-
-#ifdef FREEDV
-static void process_freedv_rx_buffer() {
-  int j;
-  int demod_samples;
-  for(j=0;j<outputsamples;j++) {
-    if(freedv_samples==0) {
-      leftaudiosample=(short)(audiooutputbuffer[j*2]*32767.0);
-      rightaudiosample=(short)(audiooutputbuffer[(j*2)+1]*32767.0);
-      demod_samples=demod_sample_freedv(leftaudiosample);
-      if(demod_samples!=0) {
-        int s;
-        int t;
-        for(s=0;s<demod_samples;s++) {
-          if(freedv_sync) {
-            leftaudiosample=rightaudiosample=(short)((double)speech_out[s]);
-          } else {
-            leftaudiosample=rightaudiosample=0;
-          }
-          for(t=0;t<6;t++) { // 8k to 48k
-            if(local_audio) {
-                audio_write(leftaudiosample,rightaudiosample);
-                leftaudiosample=0;
-                rightaudiosample=0;
-            }
-
-            audiobuffer[audioindex++]=leftaudiosample>>8;
-            audiobuffer[audioindex++]=leftaudiosample;
-            audiobuffer[audioindex++]=rightaudiosample>>8;
-            audiobuffer[audioindex++]=rightaudiosample;
-            
-            if(audioindex>=sizeof(audiobuffer)) {
-                // insert the sequence
-              audiobuffer[0]=audiosequence>>24;
-              audiobuffer[1]=audiosequence>>16;
-              audiobuffer[2]=audiosequence>>8;
-              audiobuffer[3]=audiosequence;
-              // send the buffer
-              if(sendto(data_socket,audiobuffer,sizeof(audiobuffer),0,(struct sockaddr*)&audio_addr,audio_addr_length)<0) {
-                fprintf(stderr,"sendto socket failed for audio\n");
-                exit(1);
-              }
-              audioindex=4;
-              audiosequence++;
-            }
-          }
-        }
-      }
-      freedv_samples++;
-      if(freedv_samples==freedv_resample) {
-        freedv_samples=0;
-      }
-    }
+static void process_mic_data(unsigned char *buffer,int bytes) {
+  long sequence;
+  int b;
+  short sample;
+
+  sequence=((buffer[0]&0xFF)<<24)+((buffer[1]&0xFF)<<16)+((buffer[2]&0xFF)<<8)+(buffer[3]&0xFF);
+  b=4;
+  int i;
+  for(i=0;i<MIC_SAMPLES;i++) {
+    sample=(short)((buffer[b++]<<8) | (buffer[b++]&0xFF));
+    add_mic_sample(transmitter,sample);
   }
 }
-#endif
 
-static void process_rx_buffer() {
-  int j;
-  for(j=0;j<outputsamples;j++) {
-    if(isTransmitting()) {
-      leftaudiosample=0;
-      rightaudiosample=0;
-    } else {
-      leftaudiosample=(short)(audiooutputbuffer[j*2]*32767.0);
-      rightaudiosample=(short)(audiooutputbuffer[(j*2)+1]*32767.0);
+void new_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right_audio_sample) {
+  int rc;
 
-#ifdef PSK
-      if(mode==modePSK) {
-        if(psk_samples==0) {
-          psk_demod((double)((leftaudiosample+rightaudiosample)/2));
-        }
-        psk_samples++;
-        if(psk_samples==psk_resample) {
-          psk_samples=0;
-        }
-      }
-#endif
-    }
-
-    if(local_audio) {
-      audio_write(leftaudiosample,rightaudiosample);
-    }
-
-    audiobuffer[audioindex++]=leftaudiosample>>8;
-    audiobuffer[audioindex++]=leftaudiosample;
-    audiobuffer[audioindex++]=rightaudiosample>>8;
-    audiobuffer[audioindex++]=rightaudiosample;
-
-    if(audioindex>=sizeof(audiobuffer)) {
-      // insert the sequence
-      audiobuffer[0]=audiosequence>>24;
-      audiobuffer[1]=audiosequence>>16;
-      audiobuffer[2]=audiosequence>>8;
-      audiobuffer[3]=audiosequence;
-      // send the buffer
-      if(sendto(data_socket,audiobuffer,sizeof(audiobuffer),0,(struct sockaddr*)&audio_addr,audio_addr_length)<0) {
-        fprintf(stderr,"sendto socket failed for audio\n");
-        exit(1);
-      }
-      audioindex=4;
-      audiosequence++;
-    }
-  }
-}
+  // insert the samples
+  audiobuffer[audioindex++]=left_audio_sample>>8;
+  audiobuffer[audioindex++]=left_audio_sample;
+  audiobuffer[audioindex++]=right_audio_sample>>8;
+  audiobuffer[audioindex++]=right_audio_sample;
+            
+  if(audioindex>=sizeof(audiobuffer)) {
 
-static void full_rx_buffer(int rx) {
-  int j;
-  int error;
+    // insert the sequence
+    audiobuffer[0]=audiosequence>>24;
+    audiobuffer[1]=audiosequence>>16;
+    audiobuffer[2]=audiosequence>>8;
+    audiobuffer[3]=audiosequence;
 
-  Spectrum0(1, CHANNEL_RX0, 0, 0, iqinputbuffer[rx]);
+    // send the buffer
 
-  if(rx==active_receiver) {
-    fexchange0(CHANNEL_RX0, iqinputbuffer[rx], audiooutputbuffer, &error);
-    if(error!=0) {
-      fprintf(stderr,"full_rx_buffer: fexchange0: error=%d\n",error);
-    }
-/*
-    switch(mode) {
-#ifdef PSK
-      case modePSK:
-        break;
-#endif
-      default:
-        Spectrum0(1, CHANNEL_RX0, 0, 0, iqinputbuffer[rx]);
-        break;
-    }
-*/
-    switch(mode) {
-#ifdef FREEDV
-      case modeFREEDV:
-        process_freedv_rx_buffer();
-        break;
-#endif
-      default:
-        process_rx_buffer();
-        break;
+    rc=sendto(data_socket,audiobuffer,sizeof(audiobuffer),0,(struct sockaddr*)&audio_addr,audio_addr_length);
+    if(rc!=sizeof(audiobuffer)) {
+      fprintf(stderr,"sendto socket failed for %d bytes of audio: %d\n",sizeof(audiobuffer),rc);
     }
+    audioindex=4;
+    audiosequence++;
   }
 }
 
-static void full_tx_buffer() {
-  long isample;
-  long qsample;
-  double gain=8388607.0;
-  int j;
-  int error;
-
-  if(vox_enabled) {
-    switch(mode) {
-      case modeLSB:
-      case modeUSB:
-      case modeDSB:
-      case modeFMN:
-      case modeAM:
-      case modeSAM:
-#ifdef FREEDV
-      case modeFREEDV:
-#endif
-        update_vox(micinputbuffer,BUFFER_SIZE);
-        break;
+void new_protocol_iq_samples(int isample,int qsample) {
+  iqbuffer[iqindex++]=isample>>16;
+  iqbuffer[iqindex++]=isample>>8;
+  iqbuffer[iqindex++]=isample;
+  iqbuffer[iqindex++]=qsample>>16;
+  iqbuffer[iqindex++]=qsample>>8;
+  iqbuffer[iqindex++]=qsample;
+
+  if(iqindex==sizeof(iqbuffer)) {
+    iqbuffer[0]=tx_iq_sequence>>24;
+    iqbuffer[1]=tx_iq_sequence>>16;
+    iqbuffer[2]=tx_iq_sequence>>8;
+    iqbuffer[3]=tx_iq_sequence;
+
+    // send the buffer
+    if(sendto(data_socket,iqbuffer,sizeof(iqbuffer),0,(struct sockaddr*)&iq_addr,iq_addr_length)<0) {
+      fprintf(stderr,"sendto socket failed for iq\n");
+      exit(1);
     }
+    iqindex=4;
+    tx_iq_sequence++;
   }
+}
 
-  fexchange0(CHANNEL_TX, micinputbuffer, iqoutputbuffer, &error);
-  Spectrum0(1, CHANNEL_TX, 0, 0, iqoutputbuffer);
-
-#ifdef FREEDV
-  if(mode==modeFREEDV) {
-    gain=8388607.0;
-  }
-#endif
-
-  if(radio->device==NEW_DEVICE_ATLAS && atlas_penelope) {
-    if(tune) {
-      gain=gain*tune_drive;
+void new_protocol_process_local_mic(unsigned char *buffer,int le) {
+  int b;
+  short micsample;
+  double micsampledouble;
+  double gain=pow(10.0, mic_gain / 20.0);
+
+  b=0;
+  int i,j,s;
+  for(i=0;i<MIC_SAMPLES;i++) {
+    if(le) {
+      micsample = (short)((buffer[b++]&0xFF) | (buffer[b++]<<8));
     } else {
-      gain=gain*(double)drive;
+      micsample = (short)((buffer[b++]<<8) | (buffer[b++]&0xFF));
     }
+    add_mic_sample(transmitter,micsample);
   }
 
-  for(j=0;j<micoutputsamples;j++) {
-    isample=(long)(iqoutputbuffer[j*2]*gain);
-    qsample=(long)(iqoutputbuffer[(j*2)+1]*gain);
-
-    iqbuffer[iqindex++]=isample>>16;
-    iqbuffer[iqindex++]=isample>>8;
-    iqbuffer[iqindex++]=isample;
-    iqbuffer[iqindex++]=qsample>>16;
-    iqbuffer[iqindex++]=qsample>>8;
-    iqbuffer[iqindex++]=qsample;
-
-    if(iqindex>=sizeof(iqbuffer)) {
-      // insert the sequence
-      iqbuffer[0]=tx_iq_sequence>>24;
-      iqbuffer[1]=tx_iq_sequence>>16;
-      iqbuffer[2]=tx_iq_sequence>>8;
-      iqbuffer[3]=tx_iq_sequence;
-
-      // send the buffer
-      if(sendto(data_socket,iqbuffer,sizeof(iqbuffer),0,(struct sockaddr*)&iq_addr,iq_addr_length)<0) {
-        fprintf(stderr,"sendto socket failed for iq\n");
-        exit(1);
-      }
-      iqindex=4;
-      tx_iq_sequence++;
-    }
-
-  }
-}
-
-void new_protocol_process_local_mic(unsigned char *buffer,int le) {
-    int b;
-    int micsample;
-    double micsampledouble;
-    double gain=pow(10.0, mic_gain / 20.0);
-
-//    if(isTransmitting()) {
-        b=0;
-        int i,j,s;
-        for(i=0;i<MIC_SAMPLES;i++) {
-            if(le) {
-              micsample  = (int)((unsigned char)buffer[b++] & 0xFF);
-              micsample  |= (int)((signed char) buffer[b++]) << 8;
-            } else {
-              micsample  = (int)((signed char) buffer[b++]) << 8;
-              micsample  |= (int)((unsigned char)buffer[b++] & 0xFF);
-            }
-            micsampledouble=(1.0 / 2147483648.0) * (double)(micsample<<16);
-#ifdef FREEDV
-            if(mode==modeFREEDV && isTransmitting()) {
-                if(freedv_samples==0) { // 48K to 8K
-                    int modem_samples=mod_sample_freedv(micsample*gain);
-                    if(modem_samples!=0) {
-                      for(s=0;s<modem_samples;s++) {
-                        for(j=0;j<freedv_resample;j++) {  // 8K to 48K
-                          micsample=mod_out[s];
-                          micsampledouble=(1.0 / 2147483648.0) * (double)(micsample<<16);
-                          micinputbuffer[micsamples*2]=micsampledouble;
-                          micinputbuffer[(micsamples*2)+1]=micsampledouble;
-                          micsamples++;
-                          if(micsamples==BUFFER_SIZE) {
-                            full_tx_buffer();
-                            micsamples=0;
-                          }
-                        }
-                      }
-                    }
-               }
-               freedv_samples++;
-               if(freedv_samples==freedv_resample) {
-                   freedv_samples=0;
-               }
-            } else {
-#endif
-               if(mode==modeCWL || mode==modeCWU || tune /*|| !isTransmitting()*/) {
-                   micinputbuffer[micsamples*2]=0.0;
-                   micinputbuffer[(micsamples*2)+1]=0.0;
-               } else {
-                   micinputbuffer[micsamples*2]=micsampledouble;
-                   micinputbuffer[(micsamples*2)+1]=micsampledouble;
-               }
-
-               micsamples++;
-
-               if(micsamples==BUFFER_SIZE) {
-                   full_tx_buffer();
-                   micsamples=0;
-               }
-#ifdef FREEDV
-           }
-#endif
-
-        }
-//    }
-
 }
 
 void* new_protocol_timer_thread(void* arg) {
-    int count=0;
+  int count=0;
 fprintf(stderr,"new_protocol_timer_thread\n");
-    while(running) {
-        usleep(100000); // 100ms
-        if(running) {
-            if(count==0) {
-                new_protocol_transmit_specific();
-                count=1;
-            } else {
-                new_protocol_receive_specific();
-                count=0;
-            }
-        }
+  while(running) {
+    usleep(100000); // 100ms
+    if(running) {
+      if(count==0) {
+        new_protocol_transmit_specific();
+        count=1;
+      } else {
+        new_protocol_receive_specific();
+        count=0;
+      }
     }
+  }
 }
index ed62293f4429723407ddb1357cd03efce09a4091..daf822875d1abe1a227a9110782d7d526949df2f 100644 (file)
@@ -20,6 +20,9 @@
 #ifndef _NEW_PROTOCOL_H
 #define _NEW_PROTOCOL_H
 
+#include <semaphore.h>
+#include "receiver.h"
+
 // port definitions from host
 #define GENERAL_REGISTERS_FROM_HOST_PORT 1024
 #define PROGRAMMING_FROM_HOST_PORT 1024
@@ -43,7 +46,7 @@
 #define RX_IQ_TO_HOST_PORT_6 1041
 #define RX_IQ_TO_HOST_PORT_7 1042
 
-#define BUFFER_SIZE 1024
+//#define BUFFER_SIZE 1024
 
 #ifdef SHORT_FRAMES
 #define MIC_SAMPLES 64
@@ -68,11 +71,12 @@ extern int send_high_priority;
 extern int send_general;
 */
 
-void schedule_high_priority(int source);
+void schedule_high_priority();
 void schedule_general();
 
 void new_protocol_init(int pixels);
 void new_protocol_stop();
+void new_protocol_run();
 
 void filter_board_changed();
 void pa_changed();
@@ -85,5 +89,7 @@ void setTune(int state);
 int getTune();
 int isTransmitting();
 
-void new_protocol_process_local_mic(unsigned char *buffer,int le);
+extern void new_protocol_process_local_mic(unsigned char *buffer,int le);
+extern void new_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right_audio_sample);
+extern void new_protocol_iq_samples(int isample,int qsample);
 #endif
index 52837592eef8b480028154f919a964e13cacd3b8..81ff5c0bda0c6ea10de0ae29ecd90da074aee693 100644 (file)
@@ -48,80 +48,30 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat
 }
 
 static void update_noise() {
-  SetRXAANRRun(CHANNEL_RX0, nr);
-  SetRXAEMNRRun(CHANNEL_RX0, nr2);
-  SetRXAANFRun(CHANNEL_RX0, anf);
-  SetRXASNBARun(CHANNEL_RX0, snb);
+  SetRXAANRRun(active_receiver->id, active_receiver->nr);
+  SetRXAEMNRRun(active_receiver->id, active_receiver->nr2);
+  SetRXAANFRun(active_receiver->id, active_receiver->anf);
+  SetRXASNBARun(active_receiver->id, active_receiver->snb);
   vfo_update(NULL);
 }
 
-static void nr_none_cb(GtkWidget *widget, gpointer data) {
-  nr=0;
-  nr2=0;
-  nb=0;
-  nb2=0;
-  anf=0;
-  snb=0;
-  update_noise();
-}
-
 static void nr_cb(GtkWidget *widget, gpointer data) {
-  nr=1;
-  nr2=0;
-  nb=0;
-  nb2=0;
-  anf=0;
-  snb=0;
+  active_receiver->nr=active_receiver->nr==1?0:1;
   update_noise();
 }
 
 static void nr2_cb(GtkWidget *widget, gpointer data) {
-  nr=0;
-  nr2=1;
-  nb=0;
-  nb2=0;
-  anf=0;
-  snb=0;
-  update_noise();
-}
-
-static void nb_cb(GtkWidget *widget, gpointer data) {
-  nr=0;
-  nr2=0;
-  nb=1;
-  nb2=0;
-  anf=0;
-  snb=0;
-  update_noise();
-}
-
-static void nb2_cb(GtkWidget *widget, gpointer data) {
-  nr=0;
-  nr2=0;
-  nb=0;
-  nb2=1;
-  anf=0;
-  snb=0;
+  active_receiver->nr2=active_receiver->nr2==1?0:1;
   update_noise();
 }
 
 static void anf_cb(GtkWidget *widget, gpointer data) {
-  nr=0;
-  nr2=0;
-  nb=0;
-  nb2=0;
-  anf=1;
-  snb=0;
+  active_receiver->anf=active_receiver->anf==1?0:1;
   update_noise();
 }
 
 static void snb_cb(GtkWidget *widget, gpointer data) {
-  nr=0;
-  nr2=0;
-  nb=0;
-  nb2=0;
-  anf=0;
-  snb=1;
+  active_receiver->snb=active_receiver->snb==1?0:1;
   update_noise();
 }
 
@@ -155,56 +105,35 @@ void noise_menu(GtkWidget *parent) {
   g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
   gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
 
-  GtkWidget *b_nr_none=gtk_radio_button_new_with_label(NULL,"None");
-  //gtk_widget_override_font(b_none, pango_font_description_from_string("Arial 16"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr_none), nr_none==1);
-  gtk_widget_show(b_nr_none);
-  gtk_grid_attach(GTK_GRID(grid),b_nr_none,0,1,2,1);
-  g_signal_connect(b_nr_none,"pressed",G_CALLBACK(nr_none_cb),NULL);
+  char label[32];
+  sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B");
+  GtkWidget *rx_label=gtk_label_new(label);
+  gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1);
 
-  GtkWidget *b_nr=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_nr_none),"NR");
-  //gtk_widget_override_font(b_nr, pango_font_description_from_string("Arial 16"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr), nr==1);
+  GtkWidget *b_nr=gtk_check_button_new_with_label("NR");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr), active_receiver->nr);
   gtk_widget_show(b_nr);
   gtk_grid_attach(GTK_GRID(grid),b_nr,0,2,2,1);
-  g_signal_connect(b_nr,"pressed",G_CALLBACK(nr_cb),NULL);
+  g_signal_connect(b_nr,"toggled",G_CALLBACK(nr_cb),NULL);
 
-  GtkWidget *b_nr2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_nr),"NR2");
-  //gtk_widget_override_font(b_nr2, pango_font_description_from_string("Arial 16"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr2), nr2==1);
+  GtkWidget *b_nr2=gtk_check_button_new_with_label("NR2");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr2), active_receiver->nr2);
   gtk_widget_show(b_nr2);
   gtk_grid_attach(GTK_GRID(grid),b_nr2,0,3,2,1);
-  g_signal_connect(b_nr2,"pressed",G_CALLBACK(nr2_cb),NULL);
-
-/*
-  GtkWidget *b_nb=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_nr2),"NB");
-  //gtk_widget_override_font(b_nb, pango_font_description_from_string("Arial 16"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nb), nb==1);
-  gtk_widget_show(b_nb);
-  gtk_grid_attach(GTK_GRID(grid),b_nb,0,4,2,1);
-  g_signal_connect(b_nb,"pressed",G_CALLBACK(nb_cb),NULL);
-
-  GtkWidget *b_nb2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_nb),"NB2");
-  //gtk_widget_override_font(b_nb2, pango_font_description_from_string("Arial 16"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nb2), nb2==1);
-  gtk_widget_show(b_nb2);
-  gtk_grid_attach(GTK_GRID(grid),b_nb2,0,5,2,1);
-  g_signal_connect(b_nb2,"pressed",G_CALLBACK(nb2_cb),NULL);
-*/
+  g_signal_connect(b_nr2,"toggled",G_CALLBACK(nr2_cb),NULL);
 
-  GtkWidget *b_anf=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_nr2),"ANF");
-  //gtk_widget_override_font(b_anf, pango_font_description_from_string("Arial 16"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_anf), anf==1);
+  GtkWidget *b_anf=gtk_check_button_new_with_label("ANF");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_anf), active_receiver->anf);
   gtk_widget_show(b_anf);
   gtk_grid_attach(GTK_GRID(grid),b_anf,0,4,2,1);
-  g_signal_connect(b_anf,"pressed",G_CALLBACK(anf_cb),NULL);
+  g_signal_connect(b_anf,"toggled",G_CALLBACK(anf_cb),NULL);
  
-  GtkWidget *b_snb=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_anf),"SNB");
+  GtkWidget *b_snb=gtk_check_button_new_with_label("SNB");
   //gtk_widget_override_font(b_snb, pango_font_description_from_string("Arial 16"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_snb), snb==1);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_snb), active_receiver->snb);
   gtk_widget_show(b_snb);
   gtk_grid_attach(GTK_GRID(grid),b_snb,0,5,2,1);
-  g_signal_connect(b_snb,"pressed",G_CALLBACK(snb_cb),NULL);
+  g_signal_connect(b_snb,"toggled",G_CALLBACK(snb_cb),NULL);
 
   gtk_container_add(GTK_CONTAINER(content),grid);
 
index b85aa389b17421f62398851e89a4f0b5d50252b2..73fc5677e1b7043eea5355ff352a2ac02c5641ba 100644 (file)
--- a/oc_menu.c
+++ b/oc_menu.c
@@ -48,29 +48,41 @@ static void oc_rx_cb(GtkWidget *widget, gpointer data) {
   int b=((int)data)>>4;
   int oc=((int)data)&0xF;
   BAND *band=band_get_band(b);
-  int mask=0x01<<oc;
+  int mask=0x01<<(oc-1);
+fprintf(stderr,"oc_rx_cb: band=%d oc=%d mask=%d\n",b,oc,mask);
   if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
     band->OCrx|=mask;
   } else {
     band->OCrx&=~mask;
   }
+
+  if(protocol==NEW_PROTOCOL) {
+    schedule_high_priority();
+  }
 }
 
 static void oc_tx_cb(GtkWidget *widget, gpointer data) {
   int b=((int)data)>>4;
   int oc=((int)data)&0xF;
   BAND *band=band_get_band(b);
-  int mask=0x01<<oc;
+  int mask=0x01<<(oc-1);
+
+fprintf(stderr,"oc_tx_cb: band=%d oc=%d mask=%d\n",b,oc,mask);
+
   if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
     band->OCtx|=mask;
   } else {
     band->OCtx&=~mask;
   }
+  if(protocol==NEW_PROTOCOL) {
+    schedule_high_priority();
+  }
 }
 
 static void oc_tune_cb(GtkWidget *widget, gpointer data) {
   int oc=((int)data)&0xF;
-  int mask=0x01<<oc;
+  int mask=0x01<<(oc-1);
+fprintf(stderr,"oc_tune_cb: oc=%d mask=%d\n",oc,mask);
   if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
     OCtune|=mask;
   } else {
@@ -157,7 +169,7 @@ void oc_menu(GtkWidget *parent) {
 
     int mask;
     for(j=1;j<8;j++) {
-      mask=0x01<<j;
+      mask=0x01<<(j-1);
       GtkWidget *oc_rx_b=gtk_check_button_new();
       //gtk_widget_override_font(oc_rx_b, pango_font_description_from_string("Arial 18"));
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (oc_rx_b), (band->OCrx&mask)==mask);
@@ -184,7 +196,7 @@ void oc_menu(GtkWidget *parent) {
     gtk_widget_show(oc_tune_title);
     gtk_grid_attach(GTK_GRID(grid),oc_tune_title,18,j+1,1,1);
 
-    mask=0x01<<j;
+    mask=0x01<<(j-1);
     GtkWidget *oc_tune_b=gtk_check_button_new();
     //gtk_widget_override_font(oc_tune_b, pango_font_description_from_string("Arial 18"));
     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (oc_tune_b), (OCtune&mask)==mask);
index 6a22fe1d4d9528266756c5d7989936bcf8be8e6d..33c44cb18ead7ed82e4dea8b402d43e4fcf70c84 100644 (file)
@@ -17,6 +17,7 @@
 *
 */
 
+#include <gtk/gtk.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <sys/types.h>
@@ -44,8 +45,10 @@ static int interface_length;
 static int discovery_socket;
 static struct sockaddr_in discovery_addr;
 
-static pthread_t discover_thread_id;
-static void* discover_receive_thread(void* arg);
+//static pthread_t discover_thread_id;
+//static void* discover_receive_thread(void* arg);
+static GThread *discover_thread_id;
+static gpointer discover_receive_thread(gpointer data);
 
 static void discover(struct ifaddrs* iface) {
     int rc;
@@ -96,11 +99,20 @@ static void discover(struct ifaddrs* iface) {
     to_addr.sin_addr.s_addr=htonl(INADDR_BROADCAST);
 
     // start a receive thread to collect discovery response packets
+/*
     rc=pthread_create(&discover_thread_id,NULL,discover_receive_thread,NULL);
     if(rc != 0) {
         fprintf(stderr,"pthread_create failed on discover_receive_thread: rc=%d\n", rc);
         exit(-1);
     }
+*/
+    discover_thread_id = g_thread_new( "old discover receive", discover_receive_thread, NULL);
+    if( ! discover_thread_id )
+    {
+        fprintf(stderr,"g_thread_new failed on discover_receive_thread\n");
+        exit( -1 );
+    }
+
 
 
     // send discovery packet
@@ -119,8 +131,11 @@ static void discover(struct ifaddrs* iface) {
     }
 
     // wait for receive thread to complete
+/*
     void* status;
     pthread_join(discover_thread_id,&status);
+*/
+    g_thread_join(discover_thread_id);
 
     close(discovery_socket);
 
@@ -128,7 +143,8 @@ static void discover(struct ifaddrs* iface) {
 
 }
 
-static void* discover_receive_thread(void* arg) {
+//static void *discover_receive_thread(void* arg) {
+static gpointer discover_receive_thread(gpointer data) {
     struct sockaddr_in addr;
     int len;
     unsigned char buffer[2048];
@@ -177,6 +193,9 @@ fprintf(stderr,"discover_receive_thread\n");
                         case DEVICE_HERMES_LITE:
                             strcpy(discovered[devices].name,"Hermes Lite");
                             break;
+                        case DEVICE_ORION2:
+                            strcpy(discovered[devices].name,"Orion 2");
+                            break;
                         default:
                             strcpy(discovered[devices].name,"Unknown");
                             break;
@@ -211,7 +230,8 @@ fprintf(stderr,"discover_receive_thread\n");
 
     }
     fprintf(stderr,"discovery: exiting discover_receive_thread\n");
-    pthread_exit(NULL);
+    //pthread_exit(NULL);
+    g_thread_exit(NULL);
 }
 
 void old_discovery() {
index 58cbd41e0468a553a9ba766700176f649524ecde..bccd04245a45348a523242e7b7f5963745123ca6 100644 (file)
@@ -30,7 +30,6 @@
 #include <net/if_arp.h>
 #include <net/if.h>
 #include <ifaddrs.h>
-#include <pthread.h>
 #include <semaphore.h>
 #include <string.h>
 #include <errno.h>
 #include "filter.h"
 #include "old_protocol.h"
 #include "radio.h"
+#include "receiver.h"
+#include "transmitter.h"
 #include "signal.h"
 #include "toolbar.h"
+#include "vfo.h"
 #ifdef FREEDV
 #include "freedv.h"
 #endif
@@ -70,7 +72,7 @@
 
 #define SYNC 0x7F
 #define OZY_BUFFER_SIZE 512
-#define OUTPUT_BUFFER_SIZE 1024
+//#define OUTPUT_BUFFER_SIZE 1024
 
 // ozy command and control
 #define MOX_DISABLED    0x00
 #define LT2208_RANDOM_OFF         0x00
 #define LT2208_RANDOM_ON          0x10
 
-static int buffer_size=BUFFER_SIZE;
+//static int buffer_size=BUFFER_SIZE;
 
-static int receiver;
 static int display_width;
 
 static int speed;
@@ -128,8 +129,11 @@ static double phase=0.0;
 static int running;
 static long ep4_sequence;
 
+static int current_rx=0;
+
 static int samples=0;
 static int mic_samples=0;
+static int mic_sample_divisor=1;
 #ifdef FREEDV
 static int freedv_samples=0;
 static int freedv_divisor=6;
@@ -141,22 +145,22 @@ static int psk_divisor=6;
 
 //static float left_input_buffer[BUFFER_SIZE];
 //static float right_input_buffer[BUFFER_SIZE];
-static double iqinputbuffer[RECEIVERS][BUFFER_SIZE*2];
+//static double iqinputbuffer[MAX_RECEIVERS][MAX_BUFFER_SIZE*2];
 
-//static float mic_left_buffer[BUFFER_SIZE];
-//static float mic_right_buffer[BUFFER_SIZE];
-static double micinputbuffer[BUFFER_SIZE*2];
+//static float mic_left_buffer[MAX_BUFFER_SIZE];
+//static float mic_right_buffer[MAX_BUFFER_SIZE];
+static double micinputbuffer[MAX_BUFFER_SIZE*2];
 
 //static float left_output_buffer[OUTPUT_BUFFER_SIZE];
 //static float right_output_buffer[OUTPUT_BUFFER_SIZE];
-static double audiooutputbuffer[BUFFER_SIZE*2];
+//static double audiooutputbuffer[MAX_BUFFER_SIZE*2];
 
 //static float left_subrx_output_buffer[OUTPUT_BUFFER_SIZE];
 //static float right_subrx_output_buffer[OUTPUT_BUFFER_SIZE];
 
 //static float left_tx_buffer[OUTPUT_BUFFER_SIZE];
 //static float right_tx_buffer[OUTPUT_BUFFER_SIZE];
-static double iqoutputbuffer[BUFFER_SIZE*2];
+//static double iqoutputbuffer[MAX_BUFFER_SIZE*2];
 
 static int left_rx_sample;
 static int right_rx_sample;
@@ -168,9 +172,9 @@ static int output_buffer_index=8;
 
 static int command=0;
 
-static pthread_t receive_thread_id;
+static GThread *receive_thread_id;
 static void start_receive_thread();
-static void *receive_thread(void* arg);
+static gpointer receive_thread(gpointer arg);
 static void process_ozy_input_buffer(char  *buffer);
 static void process_bandscope_buffer(char  *buffer);
 void ozy_send_buffer();
@@ -183,78 +187,76 @@ static int frequencyChanged=0;
 static sem_t frequency_changed_sem;
 
 static int metis_write(unsigned char ep,char* buffer,int length);
-static void metis_restart();
 static void metis_start_stop(int command);
 static void metis_send_buffer(char* buffer,int length);
-static void full_rx_buffer();
-static void full_tx_buffer();
+static void metis_restart();
+
+#define COMMON_MERCURY_FREQUENCY 0x80
+#define PENELOPE_MIC 0x80
+
+#ifdef USBOZY
+//
+// additional defines if we include USB Ozy support
+//
+#include "ozyio.h"
+
+static GThread *ozy_EP4_rx_thread_id;
+static GThread *ozy_EP6_rx_thread_id;
+static gpointer ozy_ep4_rx_thread(gpointer arg);
+static gpointer ozy_ep6_rx_thread(gpointer arg);
+static void start_usb_receive_threads();
+static int ozyusb_write(char* buffer,int length);
+#define EP6_IN_ID  0x86                         // end point = 6, direction toward PC
+#define EP2_OUT_ID  0x02                        // end point = 2, direction from PC
+#define EP6_BUFFER_SIZE 2048
+static unsigned char usb_output_buffer[EP6_BUFFER_SIZE];
+static unsigned char ep6_inbuffer[EP6_BUFFER_SIZE];
+static unsigned char usb_buffer_block = 0;
+#endif
 
 void schedule_frequency_changed() {
-//fprintf(stderr,"old_protocol: schedule_frequency_changed\n");
-    //sem_wait(&frequency_changed_sem);
     frequencyChanged=1;
-    //sem_post(&frequency_changed_sem);
 }
 
 void old_protocol_stop() {
   metis_start_stop(0);
-  running=FALSE;
 }
 
-void old_protocol_calc_buffers() {
-  switch(sample_rate) {
-    case 48000:
-      output_buffer_size=OUTPUT_BUFFER_SIZE;
-      break;
-    case 96000:
-      output_buffer_size=OUTPUT_BUFFER_SIZE/2;
-      break;
-    case 192000:
-      output_buffer_size=OUTPUT_BUFFER_SIZE/4;
-      break;
-    case 384000:
-      output_buffer_size=OUTPUT_BUFFER_SIZE/8;
-      break;
-    default:
-      fprintf(stderr,"Invalid sample rate: %d. Defaulting to 48K.\n",sample_rate);
-      break;
-  }
+void old_protocol_run() {
+  metis_restart();
 }
 
-void old_protocol_new_sample_rate(int rate) {
-  metis_start_stop(0);
-  sample_rate=rate;
-  old_protocol_calc_buffers();
-  wdsp_new_sample_rate(rate);
-  metis_restart();
+void old_protocol_set_mic_sample_rate(int rate) {
+  mic_sample_divisor=rate/48000;
 }
 
-void old_protocol_init(int rx,int pixels) {
+void old_protocol_init(int rx,int pixels,int rate) {
   int i;
 
   fprintf(stderr,"old_protocol_init\n");
 
-  //int result=sem_init(&frequency_changed_sem, 0, 1);
-
-  if(local_audio) {
-    if(audio_open_output()!=0) {
-      fprintf(stderr,"audio_open_output failed\n");
-      local_audio=0;
-    }
-  }
+  old_protocol_set_mic_sample_rate(rate);
 
-  if(local_microphone) {
+  if(transmitter->local_microphone) {
     if(audio_open_input()!=0) {
       fprintf(stderr,"audio_open_input failed\n");
-      local_microphone=0;
+      transmitter->local_microphone=0;
     }
   }
 
-  receiver=rx;
   display_width=pixels;
  
-  old_protocol_calc_buffers();
-
+#ifdef USBOZY
+//
+// if we have a USB interfaced Ozy device:
+//
+  if (device == DEVICE_OZY) {
+    fprintf(stderr,"old_protocol_init: initialise ozy on USB\n");
+    ozy_initialise();
+    start_usb_receive_threads();
+  }
+  else
+#endif
   start_receive_thread();
 
   fprintf(stderr,"old_protocol_init: prime radio\n");
@@ -266,6 +268,73 @@ void old_protocol_init(int rx,int pixels) {
 
 }
 
+#ifdef USBOZY
+//
+// starts the threads for USB receive
+// EP4 is the bandscope endpoint (not yet used)
+// EP6 is the "normal" USB frame endpoint
+//
+static void start_usb_receive_threads()
+{
+  int rc;
+
+  fprintf(stderr,"old_protocol starting USB receive thread: buffer_size=%d\n",buffer_size);
+
+  ozy_EP6_rx_thread_id = g_thread_new( "OZY EP6 RX", ozy_ep6_rx_thread, NULL);
+  if( ! ozy_EP6_rx_thread_id )
+  {
+    fprintf(stderr,"g_thread_new failed for ozy_ep6_rx_thread\n");
+    exit( -1 );
+  }
+}
+
+//
+// receive threat for USB EP4 (bandscope) not currently used.
+//
+static gpointer ozy_ep4_rx_thread(gpointer arg)
+{
+}
+
+//
+// receive threat for USB EP6 (512 byte USB Ozy frames)
+// this function loops reading 4 frames at a time through USB
+// then processes them one at a time.
+//
+static gpointer ozy_ep6_rx_thread(gpointer arg) {
+  int bytes;
+  unsigned char buffer[2048];
+
+  fprintf(stderr, "old_protocol: USB EP6 receive_thread\n");
+  running=1;
+  while (running)
+  {
+    bytes = ozy_read(EP6_IN_ID,ep6_inbuffer,EP6_BUFFER_SIZE); // read a 2K buffer at a time
+
+    if (bytes == 0)
+    {
+      fprintf(stderr,"old_protocol_ep6_read: ozy_read returned 0 bytes... retrying\n");
+      continue;
+    }
+    else if (bytes != EP6_BUFFER_SIZE)
+    {
+      fprintf(stderr,"old_protocol_ep6_read: OzyBulkRead failed %d bytes\n",bytes);
+      perror("ozy_read(EP6 read failed");
+      //exit(1);
+    }
+    else
+// process the received data normally
+    {
+      process_ozy_input_buffer(&ep6_inbuffer[0]);
+      process_ozy_input_buffer(&ep6_inbuffer[512]);
+      process_ozy_input_buffer(&ep6_inbuffer[1024]);
+      process_ozy_input_buffer(&ep6_inbuffer[1024+512]);
+    }
+
+  }
+}
+#endif
+
 static void start_receive_thread() {
   int i;
   int rc;
@@ -273,34 +342,44 @@ static void start_receive_thread() {
 
   fprintf(stderr,"old_protocol starting receive thread: buffer_size=%d output_buffer_size=%d\n",buffer_size,output_buffer_size);
 
-  data_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
-  if(data_socket<0) {
-    perror("old_protocol: create socket failed for data_socket\n");
-    exit(-1);
-  }
+  switch(device) {
+#ifdef USBOZY
+    case DEVICE_OZY:
+      break;
+#endif
+    default:
+      data_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
+      if(data_socket<0) {
+        perror("old_protocol: create socket failed for data_socket\n");
+        exit(-1);
+      }
 
-  int optval = 1;
-  setsockopt(data_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+      int optval = 1;
+      setsockopt(data_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
 
-  // bind to the interface
-  if(bind(data_socket,(struct sockaddr*)&radio->info.network.interface_address,radio->info.network.interface_length)<0) {
-    perror("old_protocol: bind socket failed for data_socket\n");
-    exit(-1);
-  }
+      // bind to the interface
+      if(bind(data_socket,(struct sockaddr*)&radio->info.network.interface_address,radio->info.network.interface_length)<0) {
+        perror("old_protocol: bind socket failed for data_socket\n");
+        exit(-1);
+      }
 
-  memcpy(&data_addr,&radio->info.network.address,radio->info.network.address_length);
-  data_addr_length=radio->info.network.address_length;
-  data_addr.sin_port=htons(DATA_PORT);
+      memcpy(&data_addr,&radio->info.network.address,radio->info.network.address_length);
+      data_addr_length=radio->info.network.address_length;
+      data_addr.sin_port=htons(DATA_PORT);
+      break;
+  }
 
-  rc=pthread_create(&receive_thread_id,NULL,receive_thread,NULL);
-  if(rc != 0) {
-    fprintf(stderr,"old_protocol: pthread_create failed on receive_thread: rc=%d\n", rc);
-    exit(-1);
+  receive_thread_id = g_thread_new( "old protocol", receive_thread, NULL);
+  if( ! receive_thread_id )
+  {
+    fprintf(stderr,"g_thread_new failed on receive_thread\n");
+    exit( -1 );
   }
+  fprintf(stderr, "receive_thread: id=%p\n",receive_thread_id);
 
 }
 
-static void *receive_thread(void* arg) {
+static gpointer receive_thread(gpointer arg) {
   struct sockaddr_in addr;
   int length;
   unsigned char buffer[2048];
@@ -313,56 +392,67 @@ static void *receive_thread(void* arg) {
 
   length=sizeof(addr);
   while(running) {
-    bytes_read=recvfrom(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&addr,&length);
-    if(bytes_read<0) {
-      perror("recvfrom socket failed for old_protocol: receive_thread");
-      exit(1);
-    }
 
-    if(buffer[0]==0xEF && buffer[1]==0xFE) {
-      switch(buffer[2]) {
-        case 1:
-          // get the end point
-          ep=buffer[3]&0xFF;
+    switch(device) {
+#ifdef USBOZY
+      case DEVICE_OZY:
+        // should not happen
+        break;
+#endif
 
-          // get the sequence number
-          sequence=((buffer[4]&0xFF)<<24)+((buffer[5]&0xFF)<<16)+((buffer[6]&0xFF)<<8)+(buffer[7]&0xFF);
+      default:
+        bytes_read=recvfrom(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&addr,&length);
+        if(bytes_read<0) {
+          perror("recvfrom socket failed for old_protocol: receive_thread");
+          exit(1);
+        }
 
-          switch(ep) {
-            case 6: // EP6
-              // process the data
-              process_ozy_input_buffer(&buffer[8]);
-              process_ozy_input_buffer(&buffer[520]);
-              break;
-            case 4: // EP4
+        if(buffer[0]==0xEF && buffer[1]==0xFE) {
+          switch(buffer[2]) {
+            case 1:
+              // get the end point
+              ep=buffer[3]&0xFF;
+
+              // get the sequence number
+              sequence=((buffer[4]&0xFF)<<24)+((buffer[5]&0xFF)<<16)+((buffer[6]&0xFF)<<8)+(buffer[7]&0xFF);
+
+              switch(ep) {
+                case 6: // EP6
+                  // process the data
+                  process_ozy_input_buffer(&buffer[8]);
+                  process_ozy_input_buffer(&buffer[520]);
+                  break;
+                case 4: // EP4
 /*
-              ep4_sequence++;
-              if(sequence!=ep4_sequence) {
-                ep4_sequence=sequence;
-              } else {
-                int seq=(int)(sequence%32L);
-                if((sequence%32L)==0L) {
-                  reset_bandscope_buffer_index();
-                }
-                process_bandscope_buffer(&buffer[8]);
-                process_bandscope_buffer(&buffer[520]);
-              }
+                  ep4_sequence++;
+                  if(sequence!=ep4_sequence) {
+                    ep4_sequence=sequence;
+                  } else {
+                    int seq=(int)(sequence%32L);
+                    if((sequence%32L)==0L) {
+                      reset_bandscope_buffer_index();
+                    }
+                    process_bandscope_buffer(&buffer[8]);
+                    process_bandscope_buffer(&buffer[520]);
+                  }
 */
+                  break;
+                default:
+                  fprintf(stderr,"unexpected EP %d length=%d\n",ep,bytes_read);
+                  break;
+              }
+              break;
+            case 2:  // response to a discovery packet
+              fprintf(stderr,"unexepected discovery response when not in discovery mode\n");
               break;
             default:
-              fprintf(stderr,"unexpected EP %d length=%d\n",ep,bytes_read);
+              fprintf(stderr,"unexpected packet type: 0x%02X\n",buffer[2]);
               break;
           }
-          break;
-        case 2:  // response to a discovery packet
-          fprintf(stderr,"unexepected discovery response when not in discovery mode\n");
-          break;
-        default:
-          fprintf(stderr,"unexpected packet type: 0x%02X\n",buffer[2]);
-          break;
-      }
-    } else {
-      fprintf(stderr,"received bad header bytes on data port %02X,%02X\n",buffer[0],buffer[1]);
+        } else {
+          fprintf(stderr,"received bad header bytes on data port %02X,%02X\n",buffer[0],buffer[1]);
+        }
+        break;
     }
   }
 }
@@ -378,9 +468,9 @@ static void process_ozy_input_buffer(char  *buffer) {
   int last_dash;
   int left_sample;
   int right_sample;
-  int mic_sample;
-  double left_sample_double[RECEIVERS];
-  double right_sample_double[RECEIVERS];
+  short mic_sample;
+  double left_sample_double;
+  double right_sample_double;
   double mic_sample_double;
   double gain=pow(10.0, mic_gain / 20.0);
 
@@ -437,84 +527,29 @@ static void process_ozy_input_buffer(char  *buffer) {
     }
 
 
-    int iq_samples = (512 -8) / ((RECEIVERS*6)+2);
+    int iq_samples=(512-8)/((RECEIVERS*6)+2);
 
     for(i=0;i<iq_samples;i++) {
-
       for(r=0;r<RECEIVERS;r++) {
-        left_sample   = (int)((signed char) buffer[b++]) << 16;
-        left_sample  += (int)((unsigned char)buffer[b++]) << 8;
-        left_sample  += (int)((unsigned char)buffer[b++]);
-        right_sample  = (int)((signed char) buffer[b++]) << 16;
-        right_sample += (int)((unsigned char)buffer[b++]) << 8;
-        right_sample += (int)((unsigned char)buffer[b++]);
-        left_sample_double[r]=(double)left_sample/8388607.0; // 24 bit sample 2^23-1
-        right_sample_double[r]=(double)right_sample/8388607.0; // 24 bit sample 2^23-1
-      }
-      mic_sample    = (int)((signed char) buffer[b++]) << 8;
-      mic_sample   |= (int)((unsigned char)buffer[b++]);
-      mic_sample_double = (1.0 / 2147483648.0) * (double)(mic_sample<<16);
+        left_sample   = (int)((signed char) buffer[b++])<<16;
+        left_sample  |= (int)((((unsigned char)buffer[b++])<<8)&0xFF00);
+        left_sample  |= (int)((unsigned char)buffer[b++]&0xFF);
+        right_sample  = (int)((signed char)buffer[b++]) << 16;
+        right_sample |= (int)((((unsigned char)buffer[b++])<<8)&0xFF00);
+        right_sample |= (int)((unsigned char)buffer[b++]&0xFF);
 
-      // add to buffer
-      if(isTransmitting() && !local_microphone) {
-#ifdef FREEDV
-        if(mode==modeFREEDV && !tune) {
-          if(freedv_samples==0) {
-            int sample=(int)((double)mic_sample*gain);
-            int modem_samples=mod_sample_freedv(sample);
-            if(modem_samples!=0) {
-              int s;
-              for(s=0;s<modem_samples;s++) {
-                for(j=0;j<freedv_divisor;j++) {
-                  mic_sample=mod_out[s];
-                  mic_sample_double = (1.0 / 2147483648.0) * (double)(mic_sample<<16);
-                  micinputbuffer[samples*2]=mic_sample_double;
-                  micinputbuffer[(samples*2)+1]=mic_sample_double;
-                  iqinputbuffer[0][samples*2]=0.0;
-                  iqinputbuffer[0][(samples*2)+1]=0.0;
-                  samples++;
-                  if(samples==buffer_size) {
-                    full_tx_buffer();
-                    samples=0;
-                  }
-                }
-              }
-            }
-          }
-          freedv_samples++;
-          if(freedv_samples==freedv_divisor) {
-            freedv_samples=0;
-          }
-        } else {
-#endif
-          if(mode==modeCWL || mode==modeCWU || tune) {
-            micinputbuffer[samples*2]=0.0;
-            micinputbuffer[(samples*2)+1]=0.0;
-          } else {
-            micinputbuffer[samples*2]=mic_sample_double;
-            micinputbuffer[(samples*2)+1]=mic_sample_double;
-          }
-          iqinputbuffer[0][samples*2]=0.0;
-          iqinputbuffer[0][(samples*2)+1]=0.0;
-          samples++;
-          if(samples==buffer_size) {
-            full_tx_buffer();
-            samples=0;
-          }
-#ifdef FREEDV
-        }
-#endif
-      } else {
-        if(!isTransmitting()) {
-          micinputbuffer[samples*2]=mic_sample_double;
-          micinputbuffer[(samples*2)+1]=mic_sample_double;
-          iqinputbuffer[0][samples*2]=left_sample_double[0];
-          iqinputbuffer[0][(samples*2)+1]=right_sample_double[0];
-          samples++;
-          if(samples==buffer_size) {
-            full_rx_buffer();
-            samples=0;
-          }
+        left_sample_double=(double)left_sample/8388607.0; // 24 bit sample 2^23-1
+        right_sample_double=(double)right_sample/8388607.0; // 24 bit sample 2^23-1
+
+        add_iq_samples(receiver[r], left_sample_double,right_sample_double);
+      }
+      mic_sample  = (short)(buffer[b++]<<8);
+      mic_sample |= (short)(buffer[b++]&0xFF);
+      if(!transmitter->local_microphone) {
+        mic_samples++;
+        if(mic_samples>=mic_sample_divisor) { // reduce to 48000
+          add_mic_sample(transmitter,mic_sample);
+          mic_samples=0;
         }
       }
     }
@@ -533,84 +568,16 @@ static void process_ozy_input_buffer(char  *buffer) {
   }
 }
 
-#ifdef FREEDV
-static void process_freedv_rx_buffer() {
-  int j;
-
-  int demod_samples;
-  for(j=0;j<output_buffer_size;j++) {
-    if(freedv_samples==0) {
-      left_rx_sample=(short)(audiooutputbuffer[j*2]*32767.0);
-      right_rx_sample=(short)(audiooutputbuffer[(j*2)+1]*32767.0);
-      demod_samples=demod_sample_freedv(left_rx_sample);
-      if(demod_samples!=0) {
-        int s;
-        int t;
-        for(s=0;s<demod_samples;s++) {
-          for(t=0;t<6;t++) { // 8k to 48k
-            if(freedv_sync) {
-              left_rx_sample=right_rx_sample=(short)((double)speech_out[s]);
-            } else {
-              left_rx_sample=right_rx_sample=0;
-            }
-            if(local_audio) {
-              audio_write(left_rx_sample,right_rx_sample);
-            }
-            output_buffer[output_buffer_index++]=left_rx_sample>>8;
-            output_buffer[output_buffer_index++]=left_rx_sample;
-            output_buffer[output_buffer_index++]=right_rx_sample>>8;
-            output_buffer[output_buffer_index++]=right_rx_sample;
-            left_tx_sample=right_tx_sample=0;
-            output_buffer[output_buffer_index++]=left_tx_sample>>8;
-            output_buffer[output_buffer_index++]=left_tx_sample;
-            output_buffer[output_buffer_index++]=right_tx_sample>>8;
-            output_buffer[output_buffer_index++]=right_tx_sample;
-            if(output_buffer_index>=OZY_BUFFER_SIZE) {
-              ozy_send_buffer();
-              output_buffer_index=8;
-            }
-          }
-        }
-      }
-    }
-    freedv_samples++;
-    if(freedv_samples==freedv_divisor) {
-      freedv_samples=0;
-    }
-  }
-}
-#endif
-
-static void process_rx_buffer() {
-  int j;
-
-  for(j=0;j<output_buffer_size;j++) {
-    left_rx_sample=(short)(audiooutputbuffer[j*2]*32767.0);
-    right_rx_sample=(short)(audiooutputbuffer[(j*2)+1]*32767.0);
-#ifdef PSK
-    if(mode==modePSK) {
-      if(psk_samples==0) {
-        psk_demod((double)((left_rx_sample+right_rx_sample)/2));
-      }
-      psk_samples++;
-      if(psk_samples==psk_divisor) {
-        psk_samples=0;
-      }
-    }
-#endif
-    if(local_audio) {
-      audio_write(left_rx_sample,right_rx_sample);
-    }
-    left_tx_sample=0;
-    right_tx_sample=0;
-    output_buffer[output_buffer_index++]=left_rx_sample>>8;
-    output_buffer[output_buffer_index++]=left_rx_sample;
-    output_buffer[output_buffer_index++]=right_rx_sample>>8;
-    output_buffer[output_buffer_index++]=right_rx_sample;
-    output_buffer[output_buffer_index++]=left_tx_sample>>8;
-    output_buffer[output_buffer_index++]=left_tx_sample;
-    output_buffer[output_buffer_index++]=right_tx_sample>>8;
-    output_buffer[output_buffer_index++]=right_tx_sample;
+void old_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right_audio_sample) {
+  if(!isTransmitting()) {
+    output_buffer[output_buffer_index++]=left_audio_sample>>8;
+    output_buffer[output_buffer_index++]=left_audio_sample;
+    output_buffer[output_buffer_index++]=right_audio_sample>>8;
+    output_buffer[output_buffer_index++]=right_audio_sample;
+    output_buffer[output_buffer_index++]=0;
+    output_buffer[output_buffer_index++]=0;
+    output_buffer[output_buffer_index++]=0;
+    output_buffer[output_buffer_index++]=0;
     if(output_buffer_index>=OZY_BUFFER_SIZE) {
       ozy_send_buffer();
       output_buffer_index=8;
@@ -618,164 +585,38 @@ static void process_rx_buffer() {
   }
 }
 
-static void full_rx_buffer() {
-  int j;
-  int error;
-
-  if(vox_enabled && !local_microphone) {
-    switch(mode) {
-      case modeLSB:
-      case modeUSB:
-      case modeDSB:
-      case modeFMN:
-      case modeAM:
-      case modeSAM:
-#ifdef FREEDV
-      case modeFREEDV:
-#endif
-        update_vox(micinputbuffer,BUFFER_SIZE);
-        break;
-    }
-  }
-
-  if(diversity_enabled) {
-    double *pin[2];
-    pin[0]=iqinputbuffer[0];
-    pin[1]=iqinputbuffer[1];
-
-    xdivEXT(0,BUFFER_SIZE,pin,iqinputbuffer[0]);
-  }
-
-  fexchange0(CHANNEL_RX0, iqinputbuffer[0], audiooutputbuffer, &error);
-
-#ifdef PSK
-  if(mode!=modePSK) {
-#endif
-    Spectrum0(1, CHANNEL_RX0, 0, 0, iqinputbuffer[0]);
-#ifdef PSK
-  }
-#endif
-
-#ifdef FREEDV
-  if(mode==modeFREEDV) {
-    process_freedv_rx_buffer();
-    return;
-  }
-#endif
-  process_rx_buffer();
-}
-
-static void full_tx_buffer() {
-  int j;
-  int error;
-  double gain=32767.0; // 2^16-1
-
-  if(vox_enabled && (vox || local_microphone)) {
-    update_vox(micinputbuffer,BUFFER_SIZE);
-  }
-
+void old_protocol_iq_samples(int isample,int qsample) {
   if(isTransmitting()) {
-    fexchange0(CHANNEL_TX, micinputbuffer, iqoutputbuffer, &error);
-    if(error!=0) {
-      fprintf(stderr,"full_tx_buffer: fexchange0: error=%d\n",error);
-    }
-    Spectrum0(1, CHANNEL_TX, 0, 0, iqoutputbuffer);
-
-    if(radio->device==DEVICE_METIS && atlas_penelope) {
-      if(tune) {
-        gain=gain*tune_drive;
-      } else {
-        gain=gain*drive;
-      }
-    }
-    for(j=0;j<output_buffer_size;j++) {
-      left_rx_sample=0;
-      right_rx_sample=0;
-      left_tx_sample=(int)(iqoutputbuffer[j*2]*gain);
-      right_tx_sample=(int)(iqoutputbuffer[(j*2)+1]*gain);
-  
-      output_buffer[output_buffer_index++]=0;
-      output_buffer[output_buffer_index++]=0;
-      output_buffer[output_buffer_index++]=0;
-      output_buffer[output_buffer_index++]=0;
-      output_buffer[output_buffer_index++]=left_tx_sample>>8;
-      output_buffer[output_buffer_index++]=left_tx_sample;
-      output_buffer[output_buffer_index++]=right_tx_sample>>8;
-      output_buffer[output_buffer_index++]=right_tx_sample;
-      if(output_buffer_index>=OZY_BUFFER_SIZE) {
-        ozy_send_buffer();
-        output_buffer_index=8;
-      }
+    output_buffer[output_buffer_index++]=0;
+    output_buffer[output_buffer_index++]=0;
+    output_buffer[output_buffer_index++]=0;
+    output_buffer[output_buffer_index++]=0;
+    output_buffer[output_buffer_index++]=isample>>8;
+    output_buffer[output_buffer_index++]=isample;
+    output_buffer[output_buffer_index++]=qsample>>8;
+    output_buffer[output_buffer_index++]=qsample;
+    if(output_buffer_index>=OZY_BUFFER_SIZE) {
+      ozy_send_buffer();
+      output_buffer_index=8;
     }
   }
 }
 
+
 void old_protocol_process_local_mic(unsigned char *buffer,int le) {
   int b;
-  int mic_sample;
-  double mic_sample_double;
-  double gain=pow(10.0, mic_gain / 20.0);
-
-  //if(isTransmitting()) {
-    b=0;
-    int i,j,s;
-    for(i=0;i<720;i++) {
-      if(le) {
-        mic_sample  = (int)((unsigned char)buffer[b++] & 0xFF);
-        mic_sample  |= (int)((signed char) buffer[b++]) << 8;
-      } else {
-        mic_sample  = (int)((signed char) buffer[b++]) << 8;
-        mic_sample  |= (int)((unsigned char)buffer[b++] & 0xFF);
-      }
-      mic_sample_double=(1.0 / 2147483648.0) * (double)(mic_sample<<16);
-#ifdef FREEDV
-      if(mode==modeFREEDV && !tune) {
-        if(freedv_samples==0) { // 48K to 8K
-          int modem_samples=mod_sample_freedv(mic_sample*gain);
-          if(modem_samples!=0) {
-            for(s=0;s<modem_samples;s++) {
-              for(j=0;j<freedv_divisor;j++) {  // 8K to 48K
-                mic_sample=mod_out[s];
-                mic_sample_double = (1.0 / 2147483648.0) * (double)(mic_sample<<16);
-                micinputbuffer[mic_samples*2]=mic_sample_double;
-                micinputbuffer[(mic_samples*2)+1]=mic_sample_double;
-                //iqinputbuffer[0][samples*2]=0.0;
-                //iqinputbuffer[0][(samples*2)+1]=0.0;
-                mic_samples++;
-                if(mic_samples==buffer_size) {
-                  full_tx_buffer();
-                  mic_samples=0;
-                }
-              }
-            }
-          }
-         }
-         freedv_samples++;
-         if(freedv_samples==freedv_divisor) {
-           freedv_samples=0;
-         }
-      } else {
-#endif
-         if(mode==modeCWL || mode==modeCWU || tune) {
-           micinputbuffer[mic_samples*2]=0.0;
-           micinputbuffer[(mic_samples*2)+1]=0.0;
-         } else {
-           micinputbuffer[mic_samples*2]=mic_sample_double;
-           micinputbuffer[(mic_samples*2)+1]=mic_sample_double;
-         }
-//         iqinputbuffer[0][samples*2]=0.0;
-//         iqinputbuffer[0][(samples*2)+1]=0.0;
-         mic_samples++;
-         if(mic_samples==buffer_size) {
-           full_tx_buffer();
-           mic_samples=0;
-         }
-#ifdef FREEDV
-       }
-#endif
-
+  short mic_sample;
+// always 48000 samples per second
+  b=0;
+  int i,j,s;
+  for(i=0;i<720;i++) {
+    if(le) {
+      mic_sample = (short)((buffer[b++]&0xFF) | (buffer[b++]<<8));
+    } else {
+      mic_sample = (short)((buffer[b++]<<8) | (buffer[b++]&0xFF));
     }
-  //}
+    add_mic_sample(transmitter,mic_sample);
+  }
 }
 
 /*
@@ -784,10 +625,13 @@ static void process_bandscope_buffer(char  *buffer) {
 */
 
 
-int current_rx=0;
 
 void ozy_send_buffer() {
 
+  int mode;
+  int i;
+  BAND *band;
+
   output_buffer[SYNC0]=SYNC;
   output_buffer[SYNC1]=SYNC;
   output_buffer[SYNC2]=SYNC;
@@ -795,12 +639,11 @@ void ozy_send_buffer() {
   switch(command) {
     case 0:
       {
-      BAND *band=band_get_current_band();
    
       output_buffer[C0]=0x00;
 
       output_buffer[C1]=0x00;
-      switch(sample_rate) {
+      switch(active_receiver->sample_rate) {
         case 48000:
           output_buffer[C1]|=SPEED_48K;
           break;
@@ -814,46 +657,62 @@ void ozy_send_buffer() {
           output_buffer[C1]|=SPEED_384K;
           break;
       }
-      if(radio->device==DEVICE_METIS) {
+
+// set more bits for Atlas based device
+// CONFIG_BOTH seems to be critical to getting ozy to respond
+#ifdef USBOZY
+      if ((device == DEVICE_OZY) || (device == DEVICE_METIS))
+#else
+      if (device == DEVICE_METIS)
+#endif
+      {
+        if (atlas_mic_source)
+          output_buffer[C1] |= PENELOPE_MIC;
+        output_buffer[C1] |= CONFIG_BOTH;
+        if (atlas_clock_source_128mhz)
+          output_buffer[C1] |= MERCURY_122_88MHZ_SOURCE;
+        output_buffer[C1] |= ((atlas_clock_source_10mhz & 3) << 2);
       }
 
       output_buffer[C2]=0x00;
       if(classE) {
         output_buffer[C2]|=0x01;
       }
+      band=band_get_band(vfo[VFO_A].band);
       if(isTransmitting()) {
-        output_buffer[C2]|=band->OCtx;
+        if(split) {
+          band=band_get_band(vfo[VFO_B].band);
+        }
+        output_buffer[C2]|=band->OCtx<<1;
         if(tune) {
           if(OCmemory_tune_time!=0) {
             struct timeval te;
             gettimeofday(&te,NULL);
             long long now=te.tv_sec*1000LL+te.tv_usec/1000;
             if(tune_timeout>now) {
-              output_buffer[C2]|=OCtune;
+              output_buffer[C2]|=OCtune<<1;
             }
           } else {
-            output_buffer[C2]|=OCtune;
+            output_buffer[C2]|=OCtune<<1;
           }
         }
       } else {
-        output_buffer[C2]|=band->OCrx;
+        output_buffer[C2]|=band->OCrx<<1;
       }
 
 // TODO - add Alex Attenuation and Alex Antenna
       output_buffer[C3]=0x00;
-      if(rx_random) {
+      if(active_receiver->random) {
         output_buffer[C3]|=LT2208_RANDOM_ON;
       }
-      if(rx_dither) {
+      if(active_receiver->dither) {
         output_buffer[C3]|=LT2208_DITHER_ON;
       }
-/*
-      if(rx_preamp) {
+      if(active_receiver->preamp) {
         output_buffer[C3]|=LT2208_GAIN_ON;
       }
-*/
 
-      switch(band->alexRxAntenna) {
+      switch(receiver[0]->alex_antenna) {
         case 0:  // ANT 1
           break;
         case 1:  // ANT 2
@@ -872,8 +731,6 @@ void ozy_send_buffer() {
           output_buffer[C3]|=0xE0;
           break;
         default:
-          // invalid - set to 0
-          band->alexRxAntenna=0;
           break;
       }
 
@@ -883,7 +740,7 @@ void ozy_send_buffer() {
       output_buffer[C4]|=(RECEIVERS-1)<<3;
     
       if(isTransmitting()) {
-        switch(band->alexTxAntenna) {
+        switch(transmitter->alex_antenna) {
           case 0:  // ANT 1
             output_buffer[C4]|=0x00;
             break;
@@ -894,12 +751,10 @@ void ozy_send_buffer() {
             output_buffer[C4]|=0x02;
             break;
           default:
-            // invalid - set to 0
-            band->alexRxAntenna=0;
             break;
         }
       } else {
-        switch(band->alexRxAntenna) {
+        switch(receiver[0]->alex_antenna) {
           case 0:  // ANT 1
             output_buffer[C4]|=0x00;
             break;
@@ -912,7 +767,7 @@ void ozy_send_buffer() {
           case 3:  // EXT 1
           case 4:  // EXT 2
           case 5:  // XVTR
-            switch(band->alexTxAntenna) {
+            switch(transmitter->alex_antenna) {
               case 0:  // ANT 1
                 output_buffer[C4]|=0x00;
                 break;
@@ -930,9 +785,11 @@ void ozy_send_buffer() {
       break;
     case 1: // tx frequency
       output_buffer[C0]=0x02;
-      long long txFrequency=ddsFrequency;
-      if(ctun) {
-        txFrequency+=ddsOffset;
+      long long txFrequency;
+      if(split) {
+        txFrequency=vfo[VFO_B].frequency-vfo[VFO_A].lo+vfo[VFO_B].offset;
+      } else {
+        txFrequency=vfo[VFO_A].frequency-vfo[VFO_B].lo+vfo[VFO_A].offset;
       }
       output_buffer[C1]=txFrequency>>24;
       output_buffer[C2]=txFrequency>>16;
@@ -940,19 +797,22 @@ void ozy_send_buffer() {
       output_buffer[C4]=txFrequency;
       break;
     case 2: // rx frequency
-      output_buffer[C0]=0x04+(current_rx*2);
-      long long rxFrequency=ddsFrequency+(long long)rit;
-      if(mode==modeCWU) {
-        rxFrequency-=(long long)cw_keyer_sidetone_frequency;
-      } else if(mode==modeCWL) {
-        rxFrequency+=(long long)cw_keyer_sidetone_frequency;
+      if(current_rx<receivers) {
+        output_buffer[C0]=0x04+(current_rx*2);
+        int v=receiver[current_rx]->id;
+        long long rxFrequency=vfo[v].frequency+vfo[v].rit;
+        if(vfo[active_receiver->id].mode==modeCWU) {
+          rxFrequency-=(long long)cw_keyer_sidetone_frequency;
+        } else if(vfo[active_receiver->id].mode==modeCWL) {
+          rxFrequency+=(long long)cw_keyer_sidetone_frequency;
+        }
+        output_buffer[C1]=rxFrequency>>24;
+        output_buffer[C2]=rxFrequency>>16;
+        output_buffer[C3]=rxFrequency>>8;
+        output_buffer[C4]=rxFrequency;
+        current_rx++;
       }
-      output_buffer[C1]=rxFrequency>>24;
-      output_buffer[C2]=rxFrequency>>16;
-      output_buffer[C3]=rxFrequency>>8;
-      output_buffer[C4]=rxFrequency;
-      current_rx++;
-      if(current_rx==RECEIVERS) {
+      if(current_rx>=receivers) {
         current_rx=0;
       }
       break;
@@ -996,6 +856,9 @@ void ozy_send_buffer() {
     case 4:
       output_buffer[C0]=0x14;
       output_buffer[C1]=0x00;
+      for(i=0;i<receivers;i++) {
+        output_buffer[C1]|=(receiver[i]->preamp<<i);
+      }
       if(mic_ptt_enabled==0) {
         output_buffer[C1]|=0x40;
       }
@@ -1008,8 +871,8 @@ void ozy_send_buffer() {
       output_buffer[C2]=linein_gain;
       output_buffer[C3]=0x00;
 
-      if(radio->device==DEVICE_HERMES || radio->device==DEVICE_ANGELIA || radio->device==DEVICE_ORION) {
-        output_buffer[C4]=0x20|attenuation;
+      if(radio->device==DEVICE_HERMES || radio->device==DEVICE_ANGELIA || radio->device==DEVICE_ORION || radio->device==DEVICE_ORION2) {
+        output_buffer[C4]=0x20|receiver[0]->attenuation;
       } else {
         output_buffer[C4]=0x00;
       }
@@ -1018,6 +881,11 @@ void ozy_send_buffer() {
       // need to add adc 2 and 3 attenuation
       output_buffer[C0]=0x16;
       output_buffer[C1]=0x00;
+      if(receivers==2) {
+        if(radio->device==DEVICE_HERMES || radio->device==DEVICE_ANGELIA || radio->device==DEVICE_ORION || radio->device==DEVICE_ORION2) {
+          output_buffer[C1]=0x20|receiver[1]->attenuation;
+        }
+      }
       output_buffer[C2]=0x00;
       if(cw_keys_reversed!=0) {
         output_buffer[C2]|=0x40;
@@ -1035,6 +903,11 @@ void ozy_send_buffer() {
       break;
     case 7:
       output_buffer[C0]=0x1E;
+      if(split) {
+        mode=vfo[1].mode;
+      } else {
+        mode=vfo[0].mode;
+      }
       if(mode!=modeCWU && mode!=modeCWL) {
         // output_buffer[C1]|=0x00;
       } else {
@@ -1075,6 +948,14 @@ void ozy_send_buffer() {
     }
   }
 
+#ifdef USBOZY
+//
+// if we have a USB interfaced Ozy device:
+//
+  if (device == DEVICE_OZY)
+        ozyusb_write(output_buffer,OZY_BUFFER_SIZE);
+  else
+#endif
   metis_write(0x02,output_buffer,OZY_BUFFER_SIZE);
 
   command++;
@@ -1086,6 +967,41 @@ void ozy_send_buffer() {
   //                output_buffer[C0],output_buffer[C1],output_buffer[C2],output_buffer[C3],output_buffer[C4]);
 }
 
+#ifdef USBOZY
+static int ozyusb_write(char* buffer,int length)
+{
+  int i;
+
+// batch up 4 USB frames (2048 bytes) then do a USB write
+  switch(usb_buffer_block++)
+  {
+    case 0:
+    default:
+      memcpy(usb_output_buffer, buffer, length);
+      break;
+
+    case 1:
+      memcpy(usb_output_buffer + 512, buffer, length);
+      break;
+
+    case 2:
+      memcpy(usb_output_buffer + 1024, buffer, length);
+      break;
+
+    case 3:
+      memcpy(usb_output_buffer + 1024 + 512, buffer, length);
+      usb_buffer_block = 0;           // reset counter
+// and write the 4 usb frames to the usb in one 2k packet
+      i = ozy_write(EP2_OUT_ID,usb_output_buffer,EP6_BUFFER_SIZE);
+      if(i != EP6_BUFFER_SIZE)
+      {
+        perror("old_protocol: OzyWrite ozy failed");
+      }
+      break;
+  }
+}
+#endif
+
 static int metis_write(unsigned char ep,char* buffer,int length) {
   int i;
 
@@ -1107,6 +1023,7 @@ static int metis_write(unsigned char ep,char* buffer,int length) {
     metis_buffer[6]=(send_sequence>>8)&0xFF;
     metis_buffer[7]=(send_sequence)&0xFF;
 
+
     // send the buffer
     metis_send_buffer(&metis_buffer[0],1032);
     metis_offset=8;
@@ -1135,6 +1052,11 @@ static void metis_start_stop(int command) {
   int i;
   unsigned char buffer[64];
     
+#ifdef USBOZY
+  if(device!=DEVICE_OZY)
+  {
+#endif
+
   buffer[0]=0xEF;
   buffer[1]=0xFE;
   buffer[2]=0x04;    // start/stop command
@@ -1145,6 +1067,9 @@ static void metis_start_stop(int command) {
   }
 
   metis_send_buffer(buffer,sizeof(buffer));
+#ifdef USBOZY
+  }
+#endif
 }
 
 static void metis_send_buffer(char* buffer,int length) {
index c38f554540017920f686c7e7f79c507341a2e6b2..45107ee8dc4d74c2709e5a8286810aec91208bb1 100644 (file)
 #ifndef _OLD_PROTOCOL_H
 #define _OLD_PROTOCOL_H
 
-#define BUFFER_SIZE 1024
-void old_protocol_stop();
-void old_protocol_init(int rx,int pixels);
-void old_protocol_new_sample_rate(int rate);
-void schedule_frequency_changed();
-void old_protocol_process_local_mic(unsigned char *buffer,int le);
+extern void old_protocol_stop();
+extern void old_protocol_run();
 
+extern void old_protocol_init(int rx,int pixels,int rate);
+extern void old_protocol_set_mic_sample_rate(int rate);
+
+extern void schedule_frequency_changed();
+extern void old_protocol_process_local_mic(unsigned char *buffer,int le);
+extern void old_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right_audio_sample);
+extern void old_protocol_iq_samples(int isample,int qsample);
 #endif
diff --git a/ozyio.c b/ozyio.c
new file mode 100644 (file)
index 0000000..c71121e
--- /dev/null
+++ b/ozyio.c
@@ -0,0 +1,707 @@
+/**
+* @file ozyio.c
+* @brief USB I/O with Ozy
+* @author John Melton, G0ORX/N6LYT
+* @version 0.1
+* @date 2009-10-13
+*/
+
+
+/* Copyright (C)
+* 2009 - John Melton, G0ORX/N6LYT
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+/*
+* modified by Bob Wisdom VK4YA May 2015 to create ozymetis
+* modified further Laurence Barker G8NJJ to add USB functionality to pihpsdr
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>    // tolower
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h> // for stat
+#include <unistd.h>   // for readlink, sleep, getcwd
+
+#include <libusb-1.0/libusb.h>
+
+#include "ozyio.h"
+
+#define OZY_PID (0x0007)
+#define OZY_VID (0xfffe)
+
+#define VRQ_SDR1K_CTL 0x0d
+#define SDR1KCTRL_READ_VERSION  0x7
+#define VRT_VENDOR_IN 0xC0
+
+#define VENDOR_REQ_TYPE_IN 0xc0
+#define VENDOR_REQ_TYPE_OUT 0x40
+
+#define        VRQ_I2C_WRITE (0x08)
+#define VRT_VENDOR_OUT (0x40)
+
+
+#define VENDOR_REQ_SET_LED 0x01
+#define VENDOR_REQ_FPGA_LOAD 0x02
+
+#define FL_BEGIN 0
+#define FL_XFER 1
+#define FL_END 2
+
+#define OZY_BUFFER_SIZE 512
+
+//#define OZY_IO_TIMEOUT 500
+#define OZY_IO_TIMEOUT 2000
+#define MAX_EPO_PACKET_SIZE 64
+
+static int init=0;
+extern unsigned char penny_fw, mercury_fw;
+extern unsigned short penny_fp, penny_rp, penny_alc;
+extern int adc_overflow;
+void writepenny(unsigned char mode);
+static libusb_device_handle* ozy_handle;
+//static libusb_context* context;
+
+
+static char ozy_firmware[64] = {0};
+static char ozy_fpga[64] = {0};
+static unsigned char ozy_firmware_version[9];
+static unsigned char ozy_output_buffer[OZY_BUFFER_SIZE];
+
+// variables accessed via ozy_i2c_readvars:
+unsigned char penny_fw =0, mercury_fw = 0;
+
+// variables accessed via ozy_i2c_readpwr
+unsigned short penny_fp =0, penny_rp = 0, penny_alc = 0;
+int adc_overflow;
+
+
+
+
+
+int ozy_open(void) {
+       int rc;
+
+       if(init==0) {
+               rc=libusb_init(NULL);
+               if(rc<0) {
+                       fprintf(stderr,"libusb_init failed: %d\n",rc);
+                       return rc;
+               }
+               init=1;
+       }
+
+       ozy_handle=libusb_open_device_with_vid_pid(NULL, OZY_VID, OZY_PID);
+       if(ozy_handle==NULL) {
+               fprintf(stderr,"libusbio: cannot find ozy device\n");
+               return -1;
+       }
+
+       rc=libusb_detach_kernel_driver(ozy_handle,0);
+       if(rc<0) {
+               //        fprintf(stderr,"libusb_detach_kernel_driver failed: %d\n",rc);
+       }
+
+       rc=libusb_claim_interface(ozy_handle,0);
+       if(rc<0) {
+               fprintf(stderr,"libusb_claim_interface failed: %d\n",rc);
+               return rc;
+       }
+
+       return 0;
+}
+
+int ozy_close() {
+       int rc;
+
+       rc=libusb_attach_kernel_driver(ozy_handle,0);
+       if(rc<0) {
+               //        fprintf(stderr,"libusb_attach_kernel_driver failed: %d\n",rc);
+       }
+
+       libusb_close(ozy_handle);
+
+       return 0;
+}
+
+int ozy_get_firmware_string(unsigned char* buffer,int buffer_size) {
+       int rc;
+
+       rc=libusb_control_transfer(ozy_handle, VRT_VENDOR_IN, VRQ_SDR1K_CTL, SDR1KCTRL_READ_VERSION, 0, buffer, buffer_size, OZY_IO_TIMEOUT);
+       if(rc<0) {
+               fprintf(stderr,"ozy__get_firmware_string failed: %d\n",rc);
+               return rc;
+       }
+       buffer[rc]='\0';
+
+       return 0;
+}
+
+int ozy_write(int ep,unsigned char* buffer,int buffer_size) {
+       int rc;
+       int bytes;
+
+       rc = libusb_bulk_transfer(ozy_handle,(unsigned char)ep,buffer,buffer_size,&bytes,OZY_IO_TIMEOUT);
+       if(rc==0) {
+               rc=bytes;
+       }
+
+       return rc;
+}
+
+int ozy_read(int ep,unsigned char* buffer,int buffer_size) {
+       int rc;
+       int bytes;
+
+       rc = libusb_bulk_transfer(ozy_handle,(unsigned char)ep,buffer,buffer_size,&bytes,OZY_IO_TIMEOUT);
+       if(rc==0) {
+               rc=bytes;
+       }
+
+       return rc;
+}
+
+int ozy_write_ram(int fx2_start_addr, unsigned char *bufp, int count) {
+       int pkt_size = MAX_EPO_PACKET_SIZE;
+       int len = count;
+       int bytes_written = 0;
+       int addr;
+       int bytes_written_this_write;
+       int nsize;
+
+       for ( addr = fx2_start_addr; addr < fx2_start_addr + len; addr += pkt_size, bufp += pkt_size ) {
+               nsize = len + fx2_start_addr - addr;
+               if ( nsize > pkt_size ) nsize = pkt_size;
+               bytes_written_this_write = libusb_control_transfer(ozy_handle, 0x40, 0xa0, addr, 0, bufp, nsize, OZY_IO_TIMEOUT);
+               if ( bytes_written_this_write >= 0  ) {
+                       bytes_written += bytes_written_this_write;
+               }
+               else {
+                       return bytes_written_this_write;
+               }
+       }
+       return bytes_written;
+}
+
+int ozy_reset_cpu(int reset) {
+       unsigned char write_buf;
+
+       if ( reset ) write_buf = 1;
+       else write_buf = 0;
+
+       if ( ozy_write_ram(0xe600, &write_buf, 1) != 1 ) return 0;
+       else return 1;
+
+}
+
+static unsigned int hexitToUInt(char c) {
+       c = tolower(c);
+       if ( c >= '0' && c <= '9' ) {
+               return c - '0';
+       }
+       else if ( c >= 'a' && c <= 'f' ) {
+               return 10 + (c - 'a');
+       }
+       return 0;
+}
+
+static int ishexit(unsigned char c) {
+       c = tolower(c);
+       if ( c >= '0' && c <= '9' ) return 1;
+       if ( c >= 'a' && c <= 'f' ) return 1;
+       return 0;
+}
+
+static int hexitsToUInt(char *p, int count) {
+       unsigned int result = 0;
+       int i;
+       char c;
+       unsigned int this_hex;
+       for ( i = 0; i < count; i++ ) {
+               c = *p;
+               ++p;
+               if ( !ishexit(c) ) {
+                       return -1;
+               }
+               this_hex = hexitToUInt(c);
+               result *= 16;
+               result += this_hex;
+       }
+       return result;
+}
+
+int ozy_load_firmware(char *fnamep) {
+       FILE *ifile;
+       int linecount = 0;
+       int length;
+       int addr;
+       int type;
+       char readbuf[1030];
+       unsigned char wbuf[256];
+       unsigned char my_cksum;
+       unsigned char cksum;
+       int this_val;
+       int i;
+
+       fprintf(stderr,"loading ozy firmware: %s\n",fnamep);
+
+       ifile = fopen(fnamep, "r");
+       if ( ifile == NULL ) {
+               fprintf(stderr, "Could not open: \'%s\'\n", fnamep);
+               return 0;
+       }
+
+       while (  fgets(readbuf, sizeof(readbuf), ifile) != NULL ) {
+               ++linecount;
+               if ( readbuf[0] != ':' ) {
+                       fprintf(stderr, "ozy_upload_firmware: bad record\n");
+                       return 0;
+               }
+               length = hexitsToUInt(readbuf+1, 2);
+               addr = hexitsToUInt(readbuf+3, 4);
+               type = hexitsToUInt(readbuf+7, 2);
+               if ( length < 0 || addr < 0 || type < 0 ) {
+                       fprintf(stderr, "ozy_upload_firmware: bad length, addr or type\n");
+                       return 0;
+               }
+               switch ( type ) {
+                       case 0: /* record */
+                       my_cksum = (unsigned char)(length + (addr & 0xff) + ((addr >> 8) + type));
+                       for ( i = 0; i < length; i++ ) {
+                               this_val = hexitsToUInt(readbuf+9+(i*2),2);
+                               #if 0
+                               printf("i: %d val: 0x%02x\n", i, this_val);
+                               #endif
+
+                               if ( this_val < 0 ) {
+                                       fprintf(stderr, "ozy_upload_firmware: bad record data\n");
+                                       return 0;
+                               }
+                               wbuf[i] = (unsigned char)this_val;
+                               my_cksum += wbuf[i];
+                       }
+
+                       this_val = hexitsToUInt(readbuf+9+(length*2),2);
+                       if ( this_val < 0 ) {
+                               fprintf(stderr, "ozy_upload_firmware: bad checksum data\n");
+                               return 0;
+                       }
+                       cksum = (unsigned char)this_val;
+                       #if 0
+                       printf("\n%s", readbuf);
+                       printf("len: %d (0x%02x) addr: 0x%04x mychk: 0x%02x chk: 0x%02x",
+                                  length, length, addr, my_cksum, cksum);
+                       #endif
+
+                       if ( ((cksum + my_cksum) & 0xff) != 0 ) {
+                               fprintf(stderr, "ozy_upload_firmware: bad checksum\n");
+                               return 0;
+                       }
+                       if ( ozy_write_ram(addr, wbuf, length) < 1 ) {
+                               fprintf(stderr, "ozy_upload_firmware: bad write\n");
+                               return 0;
+                       }
+                       break;
+
+                       case 1: /* EOF */
+                       break;
+
+                       default: /* invalid */
+                       fprintf(stderr, "ozy_upload_firmware: invalid type\n");
+                       return 0;
+
+               }
+       }
+       //        fprintf(stderr, "ozy_upload_firmware: Processed %d lines.\n", linecount);
+       return linecount;
+}
+
+int ozy_set_led(int which, int on) {
+       int rc;
+       int val;
+
+       if ( on ) {
+               val = 1;
+       }
+       else {
+               val = 0;
+       }
+
+       rc = libusb_control_transfer(ozy_handle, VENDOR_REQ_TYPE_OUT, VENDOR_REQ_SET_LED,
+                                                                val, which, NULL, 0, OZY_IO_TIMEOUT);
+
+       if ( rc < 0 ) {
+               return 0;
+       }
+       return 1;
+}
+
+int ozy_load_fpga(char *rbf_fnamep) {
+
+       FILE *rbffile;
+       unsigned char buf[MAX_EPO_PACKET_SIZE];
+       int bytes_read;
+       int total_bytes_xferd = 0;
+       int rc;
+
+       fprintf(stderr,"loading ozy fpga: %s\n",rbf_fnamep);
+
+       rbffile = fopen(rbf_fnamep, "rb");
+       if ( rbffile == NULL ) {
+               fprintf(stderr, "Failed to open: \'%s\'\n", rbf_fnamep);
+               return 0;
+       }
+
+       rc = libusb_control_transfer(ozy_handle, VENDOR_REQ_TYPE_OUT, VENDOR_REQ_FPGA_LOAD,
+                                                                0, FL_BEGIN, NULL, 0, OZY_IO_TIMEOUT);
+
+       if ( rc < 0 ) {
+               fprintf(stderr, "ozy_load_fpga: failed @ FL_BEGIN rc=%d\n",rc);
+               fclose(rbffile);
+               return 0;
+       }
+
+       /*
+         *  read the rbf and send it over the wire, 64 bytes at a time
+         */
+       while ( (bytes_read = fread(buf, 1, sizeof(buf), rbffile)) > 0 ) {
+               rc = libusb_control_transfer(ozy_handle, VENDOR_REQ_TYPE_OUT, VENDOR_REQ_FPGA_LOAD,
+                                                                        0, FL_XFER, buf, bytes_read, OZY_IO_TIMEOUT);
+               total_bytes_xferd += bytes_read;
+               if ( rc < 0 ) {
+                       fprintf(stderr, "ozy_load_fpga: failed @ FL_XFER\n");
+                       fclose(rbffile);
+                       return 0;
+               }
+       }
+       printf("%d bytes transferred.\n", total_bytes_xferd);
+       fclose(rbffile);
+       rc = libusb_control_transfer(ozy_handle, VENDOR_REQ_TYPE_OUT, VENDOR_REQ_FPGA_LOAD,
+                                                                0, FL_END, NULL, 0, OZY_IO_TIMEOUT);
+       if ( rc < 0 ) {
+               fprintf(stderr, "ozy_load_fpga: failed @ FL_END\n");
+               return 0;
+       }      
+
+       return 1;
+}
+
+int ozy_i2c_write(unsigned char* buffer,int buffer_size, unsigned char cmd) {
+       int rc;
+
+       rc=libusb_control_transfer(ozy_handle, VRT_VENDOR_OUT, VRQ_I2C_WRITE, cmd, 0, buffer, buffer_size, OZY_IO_TIMEOUT);
+       if(rc<0) {
+               fprintf(stderr,"ozy_i2c_write failed: %d\n",rc);
+               return rc;
+       }
+       return rc;
+}
+
+int ozy_i2c_read(unsigned char* buffer,int buffer_size, unsigned char cmd) {
+       int rc;
+
+       rc=libusb_control_transfer(ozy_handle, VRT_VENDOR_IN, VRQ_I2C_READ, cmd, 0, buffer, buffer_size, OZY_IO_TIMEOUT);
+       if(rc<0) {
+               fprintf(stderr,"ozy_i2c_read failed: %d\n",rc);
+               return rc;
+       }
+       return rc;
+}
+
+
+void ozy_i2c_readpwr(int addr) {
+       int rc = 0;
+       unsigned char buffer[8];
+
+       switch (addr) {
+               case I2C_PENNY_ALC:
+               rc = ozy_i2c_read(buffer,2,I2C_PENNY_ALC);      
+               if(rc<0) {
+                       perror("ozy_i2c_init4: failed");
+                       //exit(1);
+               }
+               penny_alc = (buffer[0] << 8) + buffer[1];
+               break;
+
+               case I2C_PENNY_FWD:
+               rc = ozy_i2c_read(buffer,2,I2C_PENNY_FWD);      
+               if(rc<0) {
+                       perror("ozy_i2c_init5: failed");
+                       //exit(1);
+               }
+               penny_fp = (buffer[0] << 8) + buffer[1];
+               break;
+
+               case I2C_PENNY_REV:
+               rc = ozy_i2c_read(buffer,2,I2C_PENNY_REV);      
+               if(rc<0) {
+                       perror("ozy_i2c_init6: failed");
+                       //exit(1);
+               }
+               penny_rp = (buffer[0] << 8) + buffer[1];
+               break;
+
+               case I2C_ADC_OFS:
+               // adc overload
+               rc = ozy_i2c_read(buffer,2,I2C_ADC_OFS);        // adc1 overflow status
+               if(rc<0) {
+                       perror("ozy_i2c_init6: failed");
+                       //exit(1);
+               }
+               if (buffer[0] == 0) {           // its overloaded
+                       adc_overflow = 2000;    // counts down to give hold time to client
+               }
+               break;
+
+               default:
+               break;
+       }
+}
+
+void ozy_i2c_readvars() {
+       int rc = 0;
+       unsigned char buffer[8];
+
+
+       fprintf(stderr,"ozy_i2c_init: starting\n");     
+
+       if (rc != 0) {
+               fprintf(stderr,"ozy_i2c_init: failed open %d\n",rc);
+       }
+
+       rc = ozy_i2c_read(buffer,2,I2C_MERC1_FW);       
+       if(rc<0) {
+               perror("ozy_i2c_init2: failed");
+               //exit(1);
+       }
+       mercury_fw = buffer[1];
+       fprintf(stderr,"mercury firmware=%d\n",(int)buffer[1]);
+
+       rc = ozy_i2c_read(buffer,2,I2C_PENNY_FW);       
+       if(rc<0) {
+               perror("ozy_i2c_init3: failed");
+               //exit(1);
+       }
+       penny_fw = buffer[1];
+       fprintf(stderr,"penny firmware=%d\n",(int)buffer[1]);   
+
+       writepenny((unsigned char)1);
+}
+
+void writepenny(unsigned char mode)
+{
+       unsigned char Penny_TLV320[2];
+       unsigned char *Penny_TLV320_data;       // 16 byte
+       int x;
+       // This is used to set the MicGain and Line in when Ozy/Magister is used
+       // The I2C settings are as follows:
+
+       //    For mic input and boost on/off
+       //    1E 00 - Reset chip
+       //    12 01 - set digital interface active
+       //    08 15 - D/A on, mic input, mic 20dB boost
+       //    08 14 - ditto but no mic boost
+       //    0C 00 - All chip power on
+       //    0E 02 - Slave, 16 bit, I2S
+       //    10 00 - 48k, Normal mode
+       //    0A 00 - turn D/A mute off
+       //    00 00 - set Line in gain to 0
+
+       //    For line input
+       //    1E 00 - Reset chip
+       //    12 01 - set digital interface active
+       //    08 10 - D/A on, line input
+       //    0C 00 - All chip power on
+       //    0E 02 - Slave, 16 bit, I2S
+       //    10 00 - 48k, Normal mode
+       //    0A 00 - turn D/A mute off
+       //    00 00 - set Line in gain to 0
+       fprintf(stderr,"write Penny\n");
+
+       // update mic gain on Penny or PennyLane TLV320
+
+       // need to select the config data depending on the Mic Gain (20dB) selected
+       if (mode == 0x01)
+               Penny_TLV320_data = (unsigned char []) { 0x1e, 0x00, 0x12, 0x01, 0x08, 0x15, 0x0c, 0x00, 0x0e, 0x02, 0x10, 0x00, 0x0a, 0x00, 0x00, 0x00 };              // mic in 20db gain
+       else if (mode & 2)      // line in
+               Penny_TLV320_data = (unsigned char []) { 0x1e, 0x00, 0x12, 0x01, 0x08, 0x10, 0x0c, 0x00, 0x0e, 0x02, 0x10, 0x00, 0x0a, 0x00, 0x00, 0x00 };              // line in
+       else
+               Penny_TLV320_data = (unsigned char []) { 0x1e, 0x00, 0x12, 0x01, 0x08, 0x14, 0x0c, 0x00, 0x0e, 0x02, 0x10, 0x00, 0x0a, 0x00, 0x00, 0x00 };              // mic in not 20db gain
+
+       //              // set the I2C interface speed to 400kHZ
+       //              if (!(OZY.Set_I2C_Speed(hdev, 1)))
+       //              {
+       //                      fprintf(stderr,"Unable to set I2C speed to 400kHz", "System Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
+       //                      return;
+
+       // send the configuration data to the TLV320 on Penelope or PennyLane
+       for (x = 0; x < 16; x += 2)
+       {
+               Penny_TLV320[0] = Penny_TLV320_data[x]; Penny_TLV320[1] = Penny_TLV320_data[x + 1];
+               int ozy_write_i2c(int ep,unsigned char* buffer,int buffer_size); 
+               if (!(ozy_i2c_write(Penny_TLV320,2, 0x1b)))
+               {
+                       fprintf(stderr,"Unable to configure TLV320 on Penelope via I2C\n");
+                       // break out of the configuration loop
+                       break;
+               }
+       }
+       fprintf(stderr,"write Penny done..\n");
+}
+
+
+
+static int file_exists (const char * fileName)
+{
+       struct stat buf;
+       int i = stat ( fileName, &buf );
+       return ( i == 0 ) ? 1 : 0 ;
+}
+
+#ifdef __linux__
+int filePath (char *sOut, const char *sIn) {
+       int rc = 0;
+
+       if ((rc = file_exists (sIn))) {
+               strcpy (sOut, sIn); 
+               rc = 1;
+       } else {
+               char cwd[PATH_MAX];
+               char s[PATH_MAX];
+               char xPath [PATH_MAX] = {0};
+               char *p;
+
+               int  rc = readlink ("/proc/self/exe", xPath, sizeof(xPath));
+
+               // try to detect the directory from which the executable has been loaded
+               if (rc >= 0) {
+
+                       if ( (p = strrchr (xPath, '/')) ) *(p+1) = '\0';
+                       fprintf (stderr, "%d, Path of executable: [%s]\n", rc, xPath);
+
+                       strcpy (s, xPath); strcat (s, sIn);
+
+                       if ((rc = file_exists (s))) {
+                               // found in the same dir of executable
+                               fprintf (stderr, "File: [%s]\n", s);
+                               strcpy(sOut, s);
+                       } else { 
+                               if (getcwd(cwd, sizeof(cwd)) != NULL) {
+                                       fprintf(stdout, "Current working dir: %s\n", cwd);
+
+                                       strcpy (s, cwd); strcat (s, "/"); strcat (s, sIn);
+                                       if ((rc = file_exists (s))) {
+                                               fprintf (stderr, "File: [%s]\n", s);
+                                               strcpy(sOut, s);
+                                       }
+                               }
+                       }
+               } else {
+                       fprintf (stderr, "%d: %s\n", errno, strerror(errno));
+               }
+       }
+       return rc;
+}
+#endif
+
+
+
+//
+// initialise a USB ozy device. 
+// renamed as "initialise" and combined with the "ozyinit" code
+//
+int ozy_initialise() 
+{
+       int rc;
+
+       if (strlen(ozy_firmware) == 0) filePath (ozy_firmware,"ozyfw-sdr1k.hex");
+       if (strlen(ozy_fpga) == 0)     filePath (ozy_fpga,"Ozy_Janus.rbf");
+
+// open ozy
+       rc = ozy_open();
+       if (rc != 0) {
+               fprintf(stderr,"Cannot locate Ozy\n");
+               //exit(1);
+       }
+// load Ozy FW
+       ozy_reset_cpu(1);
+       ozy_load_firmware(ozy_firmware);
+       ozy_reset_cpu(0);
+       ozy_close();
+       sleep(4);
+       ozy_open();
+       ozy_set_led(1,1);
+       ozy_load_fpga(ozy_fpga);
+       ozy_set_led(1,0);
+       ozy_close();
+       ozy_open();
+       rc=ozy_get_firmware_string(ozy_firmware_version,8);
+       fprintf(stderr,"Ozy FX2 version: %s\n",ozy_firmware_version);
+               
+       ozy_i2c_readvars();
+       ozy_close();
+       sleep(1);
+       ozy_open();             
+       return 0;
+}
+
+
+
+//
+// modified from "ozy_open" code: just finds out if there is a USB
+// ozy on the bus. Closes the connection after discovering.
+// returns 1 if a device found on USB
+//
+//
+int ozy_discover(void)
+{
+       int success = 0;                        // function return code
+       int rc;
+
+       if(init==0)
+       {
+               rc=libusb_init(NULL);
+               if(rc<0)
+               {
+                       fprintf(stderr,"libusb_init failed: %d\n",rc);
+                       return success;
+               }
+               init=1;
+       }
+//
+// do a trial open with thr PID and VID of ozy
+//
+       ozy_handle=libusb_open_device_with_vid_pid(NULL, OZY_VID, OZY_PID);
+       if(ozy_handle==NULL) 
+       {
+               fprintf(stderr,"libusbio: cannot find ozy device\n");
+               return success;
+       }
+       else
+       {
+                       success = 1;
+                       fprintf(stderr,"libusbio: ozy device found on USB port\n");
+       }
+//
+// if we get this far, we have an ozy on the bus so discover successful.
+// we don't know that it will be selected for use, so close it again
+// for now; re-open if the user selects Ozy
+//     
+       libusb_close(ozy_handle);
+       return success;
+}
diff --git a/ozyio.h b/ozyio.h
new file mode 100644 (file)
index 0000000..b643cfe
--- /dev/null
+++ b/ozyio.h
@@ -0,0 +1,86 @@
+/**
+* @file ozyio.h
+* @brief USB I/O with Ozy
+* @author John Melton, G0ORX/N6LYT
+* @version 0.1
+* @date 2009-10-13
+*/
+
+/* Copyright (C)
+* 2009 - John Melton, G0ORX/N6LYT
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+/*
+* modified by Bob Wisdom VK4YA May 2015 to create ozymetis
+* modified further Laurence Barker G8NJJ to add USB functionality to pihpsdr
+*/
+
+
+/*
+ * code modified from that in Ozy_Metis_RPI_Gateway
+ * Laurence Barker, G8NJJ December 2016
+ * this gathers all Ozy functionality in one file (merging code 
+ * from ozy.c).
+ * Further modified to add a "discover" function
+ * 
+*/
+
+#if !defined __OZYIO_H__
+#define __OZYIO_H__
+
+//
+// penelope forward, reverse power and ALC settings
+//
+extern unsigned short penny_fp, penny_rp, penny_alc;
+extern int adc_overflow;
+
+int ozy_open(void);
+int ozy_close();
+int ozy_get_firmware_string(unsigned char* buffer,int buffer_size);
+int ozy_write(int ep,unsigned char* buffer,int buffer_size);
+int ozy_read(int ep,unsigned char* buffer,int buffer_size);
+
+void ozy_load_fw();
+int ozy_load_fpga(char *rbf_fnamep);
+int ozy_set_led(int which, int on);
+int ozy_reset_cpu(int reset);
+int ozy_load_firmware(char *fnamep);
+int ozy_initialise();
+int ozy_discover(void);                // returns 1 if a device found on USB
+void ozy_i2c_readpwr(int addr); // sets local variables
+
+
+
+// Ozy I2C commands for polling firmware versions, power levels, ADC overload.
+#define I2C_MERC1_FW  0x10 // Mercury1 firmware version
+#define I2C_MERC2_FW  0x11 // Mercury2 firmware version
+#define I2C_MERC3_FW  0x12 // Mercury3 firmware version
+#define I2C_MERC4_FW  0x13 // Mercury4 firmware version
+
+#define I2C_MERC1_ADC_OFS 0x10 // adc1 overflow status
+#define I2C_MERC2_ADC_OFS 0x11 // adc2 overflow status
+#define I2C_MERC3_ADC_OFS 0x12 // adc3 overflow status
+#define I2C_MERC4_ADC_OFS 0x13 // adc4 overflow status
+
+#define I2C_PENNY_FW  0x15 // Penny firmware version
+#define I2C_PENNY_ALC 0x16 // Penny forward power
+#define I2C_PENNY_FWD 0x17 // Penny forward power from Alex
+#define I2C_PENNY_REV 0x18 // Penny reverse power from Alex
+#define I2C_ADC_OFS (0x10)     // ADC overload status
+#define        VRQ_I2C_READ    0x81    // i2c address; length; how much to read
+
+#endif
index 00882fcc168f2e1bcd29abfe5cd104dc4ad18dc7..67cb6e64d9443334db7907a97862ce1f119c6316 100644 (file)
--- a/pa_menu.c
+++ b/pa_menu.c
@@ -26,6 +26,7 @@
 #include "pa_menu.h"
 #include "band.h"
 #include "radio.h"
+#include "vfo.h"
 
 static GtkWidget *parent_window=NULL;
 
@@ -45,8 +46,14 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat
 static void pa_value_changed_cb(GtkWidget *widget, gpointer data) {
   BAND *band=(BAND *)data;
   band->pa_calibration=gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget));
-  calcDriveLevel();
-  calcTuneDriveLevel();
+  int v=VFO_A;
+  if(split) v=VFO_B;
+  int b=vfo[v].band;
+  BAND *current=band_get_band(b);
+  if(band==current) {
+    calcDriveLevel();
+    calcTuneDriveLevel();
+  }
 }
 
 static void tx_out_of_band_cb(GtkWidget *widget, gpointer data) {
diff --git a/panadapter.c b/panadapter.c
deleted file mode 100644 (file)
index 181c547..0000000
+++ /dev/null
@@ -1,490 +0,0 @@
-/* Copyright (C)
-* 2015 - John Melton, G0ORX/N6LYT
-*
-* 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 2
-* 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, write to the Free Software
-* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-*
-*/
-
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
-#include <math.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <semaphore.h>
-#include "agc.h"
-#include "band.h"
-#include "channel.h"
-#include "discovered.h"
-#include "radio.h"
-#include "panadapter.h"
-#include "vfo.h"
-#include "mode.h"
-#ifdef FREEDV
-#include "freedv.h"
-#endif
-#include "wdsp_init.h"
-
-static GtkWidget *panadapter;
-static cairo_surface_t *panadapter_surface = NULL;
-
-static float* samples;
-
-static gint last_x;
-static gboolean has_moved=FALSE;
-static gboolean pressed=FALSE;
-
-//static float panadapter_max=-60.0;
-//static float panadapter_min=-160.0;
-
-static gfloat hz_per_pixel;
-static gfloat filter_left;
-static gfloat filter_right;
-
-static int display_width;
-static int display_height;
-
-/* Create a new surface of the appropriate size to store our scribbles */
-static gboolean
-panadapter_configure_event_cb (GtkWidget         *widget,
-            GdkEventConfigure *event,
-            gpointer           data)
-{
-  display_width=gtk_widget_get_allocated_width (widget);
-  display_height=gtk_widget_get_allocated_height (widget);
-
-fprintf(stderr,"panadapter_configure_event_cb: width:%d height:%d\n",display_width,display_height);
-  if (panadapter_surface)
-    cairo_surface_destroy (panadapter_surface);
-
-  panadapter_surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget),
-                                       CAIRO_CONTENT_COLOR,
-                                       display_width,
-                                       display_height);
-
-  cairo_t *cr=cairo_create(panadapter_surface);
-  cairo_set_source_rgb(cr, 0, 0, 0);
-  cairo_paint(cr);
-  cairo_destroy(cr);
-
-  return TRUE;
-}
-
-/* Redraw the screen from the surface. Note that the ::draw
- * signal receives a ready-to-be-used cairo_t that is already
- * clipped to only draw the exposed areas of the widget
- */
-static gboolean
-panadapter_draw_cb (GtkWidget *widget,
- cairo_t   *cr,
- gpointer   data)
-{
-  cairo_set_source_surface (cr, panadapter_surface, 0, 0);
-  cairo_paint (cr);
-
-  return FALSE;
-}
-
-static gboolean
-panadapter_button_press_event_cb (GtkWidget      *widget,
-               GdkEventButton *event,
-               gpointer        data)
-{
-  int x=(int)event->x;
-  if (event->button == 1) {
-    last_x=(int)event->x;
-    has_moved=FALSE;
-    pressed=TRUE;
-  }
-  return TRUE;
-}
-
-static gboolean
-panadapter_button_release_event_cb (GtkWidget      *widget,
-               GdkEventButton *event,
-               gpointer        data)
-{
-  if(pressed) {
-    int x=(int)event->x;
-    if (event->button == 1) {
-      if(has_moved) {
-        // drag
-        vfo_move((int)((float)(x-last_x)*hz_per_pixel));
-      } else {
-        // move to this frequency
-        vfo_move_to((int)((float)(x-(display_width/2))*hz_per_pixel));
-      }
-      last_x=x;
-      pressed=FALSE;
-    }
-  }
-  return TRUE;
-}
-
-static gboolean
-panadapter_motion_notify_event_cb (GtkWidget      *widget,
-                GdkEventMotion *event,
-                gpointer        data)
-{
-  int x, y;
-  GdkModifierType state;
-  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((int)((float)moved*hz_per_pixel));
-    last_x=x;
-    has_moved=TRUE;
-  }
-
-  return TRUE;
-}
-
-static gboolean
-panadapter_scroll_event_cb (GtkWidget      *widget,
-               GdkEventScroll *event,
-               gpointer        data)
-{
-  if(event->direction==GDK_SCROLL_UP) {
-    vfo_move(step);
-  } else {
-    vfo_move(-step);
-  }
-}
-
-static void
-close_window (void)
-{
-  if (panadapter_surface)
-    cairo_surface_destroy (panadapter_surface);
-
-  gtk_main_quit ();
-}
-
-void panadapter_update(float *data,int tx) {
-    int i;
-    int result;
-    
-    float saved_max;
-    float saved_min;
-    gfloat saved_hz_per_pixel;
-    cairo_text_extents_t extents;
-
-    hz_per_pixel=(double)getSampleRate()/(double)display_width;
-    samples=data;
-    //if(result==1) {
-        if(panadapter_surface) {
-
-            if(tx) {
-                saved_max=panadapter_high;
-                saved_min=panadapter_low;
-                saved_hz_per_pixel=hz_per_pixel;
-
-                panadapter_high=20;
-                panadapter_low=-80;
-                //if(protocol==ORIGINAL_PROTOCOL) {
-                    hz_per_pixel=48000.0/(double)display_width;
-                //} else {
-                //    hz_per_pixel=192000.0/(double)display_width;
-                //}
-            }
-
-            //clear_panadater_surface();
-            cairo_t *cr;
-            cr = cairo_create (panadapter_surface);
-            cairo_set_source_rgb (cr, 0, 0, 0);
-            cairo_paint (cr);
-
-            // filter
-            cairo_set_source_rgb (cr, 0.25, 0.25, 0.25);
-            if(ctun && isTransmitting()) {
-              filter_left=(double)display_width/2.0+((double)getFilterLow()/hz_per_pixel);
-              filter_right=(double)display_width/2.0+((double)getFilterHigh()/hz_per_pixel);
-            } else {
-              filter_left=(double)display_width/2.0+(((double)getFilterLow()+ddsOffset)/hz_per_pixel);
-              filter_right=(double)display_width/2.0+(((double)getFilterHigh()+ddsOffset)/hz_per_pixel);
-            }
-            cairo_rectangle(cr, filter_left, 0.0, filter_right-filter_left, (double)display_height);
-            cairo_fill(cr);
-
-            // plot the levels
-            int V = (int)(panadapter_high - panadapter_low);
-            int numSteps = V / 20;
-            for (i = 1; i < numSteps; i++) {
-                int num = panadapter_high - i * 20;
-                int y = (int)floor((panadapter_high - num) * display_height / V);
-
-                cairo_set_source_rgb (cr, 0, 1, 1);
-                cairo_set_line_width(cr, 1.0);
-                cairo_move_to(cr,0.0,(double)y);
-                cairo_line_to(cr,(double)display_width,(double)y);
-
-                cairo_set_source_rgb (cr, 0, 1, 1);
-                cairo_select_font_face(cr, "FreeMono",
-                    CAIRO_FONT_SLANT_NORMAL,
-                    CAIRO_FONT_WEIGHT_BOLD);
-                cairo_set_font_size(cr, 12);
-                char v[32];
-                sprintf(v,"%d dBm",num);
-                cairo_move_to(cr, 1, (double)y);  
-                cairo_show_text(cr, v);
-            }
-            cairo_stroke(cr);
-
-            // plot frequency markers
-            long f;
-            long divisor=20000;
-            long half=(long)getSampleRate()/2L;
-            long long frequency=displayFrequency;
-            if(ctun && isTransmitting()) {
-              frequency+=ddsOffset;
-            }
-            switch(sample_rate) {
-              case 48000:
-                divisor=5000L;
-                break;
-              case 96000:
-              case 100000:
-                divisor=10000L;
-                break;
-              case 192000:
-                divisor=20000L;
-                break;
-              case 384000:
-                divisor=25000L;
-                break;
-              case 768000:
-                divisor=50000L;
-                break;
-              case 1048576:
-              case 1536000:
-              case 2097152:
-                divisor=100000L;
-                break;
-            }
-            for(i=0;i<display_width;i++) {
-                f = frequency - half + (long) (hz_per_pixel * i);
-                if (f > 0) {
-                    if ((f % divisor) < (long) hz_per_pixel) {
-                        cairo_set_source_rgb (cr, 0, 1, 1);
-                        cairo_set_line_width(cr, 1.0);
-                        //cairo_move_to(cr,(double)i,0.0);
-                        cairo_move_to(cr,(double)i,10.0);
-                        cairo_line_to(cr,(double)i,(double)display_height);
-
-                        cairo_set_source_rgb (cr, 0, 1, 1);
-                        cairo_select_font_face(cr, "FreeMono",
-                            CAIRO_FONT_SLANT_NORMAL,
-                            CAIRO_FONT_WEIGHT_BOLD);
-                        cairo_set_font_size(cr, 12);
-                        char v[32];
-                        sprintf(v,"%0ld.%03ld",f/1000000,(f%1000000)/1000);
-                        //cairo_move_to(cr, (double)i, (double)(display_height-10));  
-                        cairo_text_extents(cr, v, &extents);
-                        cairo_move_to(cr, (double)i-(extents.width/2.0), 10.0);  
-                        cairo_show_text(cr, v);
-                    }
-                }
-            }
-            cairo_stroke(cr);
-
-            // band edges
-            long long min_display=frequency-half;
-            long long max_display=frequency+half;
-            BAND *band=band_get_current_band();
-            if(band->frequencyMin!=0LL) {
-                cairo_set_source_rgb (cr, 1, 0, 0);
-                cairo_set_line_width(cr, 2.0);
-                if((min_display<band->frequencyMin)&&(max_display>band->frequencyMin)) {
-                    i=(band->frequencyMin-min_display)/(long long)hz_per_pixel;
-                    cairo_move_to(cr,(double)i,0.0);
-                    cairo_line_to(cr,(double)i,(double)display_height);
-                    cairo_stroke(cr);
-                }
-                if((min_display<band->frequencyMax)&&(max_display>band->frequencyMax)) {
-                    i=(band->frequencyMax-min_display)/(long long)hz_per_pixel;
-                    cairo_move_to(cr,(double)i,0.0);
-                    cairo_line_to(cr,(double)i,(double)display_height);
-                    cairo_stroke(cr);
-                }
-            }
-            
-            // agc
-            if(agc!=AGC_OFF && !tx) {
-                double hang=0.0;
-                double thresh=0;
-
-                GetRXAAGCHangLevel(CHANNEL_RX0, &hang);
-                GetRXAAGCThresh(CHANNEL_RX0, &thresh, 4096.0, (double)sample_rate);
-
-                double knee_y=thresh+(double)get_attenuation();
-                knee_y = floor((panadapter_high - knee_y)
-                        * (double) display_height
-                        / (panadapter_high - panadapter_low));
-
-                double hang_y=hang+(double)get_attenuation();
-                hang_y = floor((panadapter_high - hang_y)
-                        * (double) display_height
-                        / (panadapter_high - panadapter_low));
-
-//fprintf(stderr,"hang=%f thresh=%f hang_y=%f knee_y=%f\n",rx1_hang,rx1_thresh,hang_y,knee_y);
-                if(agc!=AGC_MEDIUM && agc!=AGC_FAST) {
-                    cairo_set_source_rgb (cr, 1.0, 1.0, 0.0);
-                    cairo_move_to(cr,40.0,hang_y-8.0);
-                    cairo_rectangle(cr, 40, hang_y-8.0,8.0,8.0);
-                    cairo_fill(cr);
-                    cairo_move_to(cr,40.0,hang_y);
-                    cairo_line_to(cr,(double)display_width-40.0,hang_y);
-                    cairo_stroke(cr);
-                    cairo_move_to(cr,48.0,hang_y);
-                    cairo_show_text(cr, "-H");
-                }
-
-                cairo_set_source_rgb (cr, 0.0, 1.0, 0.0);
-                cairo_move_to(cr,40.0,knee_y-8.0);
-                cairo_rectangle(cr, 40, knee_y-8.0,8.0,8.0);
-                cairo_fill(cr);
-                cairo_move_to(cr,40.0,knee_y);
-                cairo_line_to(cr,(double)display_width-40.0,knee_y);
-                cairo_stroke(cr);
-                cairo_move_to(cr,48.0,knee_y);
-                cairo_show_text(cr, "-G");
-            }
-
-
-            // cursor
-            cairo_set_source_rgb (cr, 1, 0, 0);
-            cairo_set_line_width(cr, 1.0);
-            cairo_move_to(cr,(double)(display_width/2.0)+(ddsOffset/hz_per_pixel),0.0);
-            cairo_line_to(cr,(double)(display_width/2.0)+(ddsOffset/hz_per_pixel),(double)display_height);
-            cairo_stroke(cr);
-
-            // signal
-            double s1,s2;
-            samples[0]=-200.0;
-            samples[display_width-1]=-200.0;
-
-            if(tx && protocol==NEW_PROTOCOL) {
-              int offset=1200;
-              s1=(double)samples[0+offset]+(double)get_attenuation();
-              s1 = floor((panadapter_high - s1)
-                          * (double) display_height
-                          / (panadapter_high - panadapter_low));
-              cairo_move_to(cr, 0.0, s1);
-              for(i=1;i<display_width;i++) {
-                  s2=(double)samples[i+offset]+(double)get_attenuation();
-                  s2 = floor((panadapter_high - s2)
-                              * (double) display_height
-                              / (panadapter_high - panadapter_low));
-                  cairo_line_to(cr, (double)i, s2);
-              }
-            } else {
-              s1=(double)samples[0]+(double)get_attenuation();
-              s1 = floor((panadapter_high - s1)
-                          * (double) display_height
-                          / (panadapter_high - panadapter_low));
-              cairo_move_to(cr, 0.0, s1);
-              for(i=1;i<display_width;i++) {
-                  s2=(double)samples[i]+(double)get_attenuation();
-                  s2 = floor((panadapter_high - s2)
-                              * (double) display_height
-                              / (panadapter_high - panadapter_low));
-                  cairo_line_to(cr, (double)i, s2);
-              }
-            }
-            if(display_filled) {
-              cairo_close_path (cr);
-              cairo_set_source_rgba(cr, 1, 1, 1,0.5);
-              cairo_fill_preserve (cr);
-            }
-            cairo_set_source_rgb(cr, 1, 1, 1);
-            cairo_set_line_width(cr, 1.0);
-            cairo_stroke(cr);
-
-#ifdef FREEDV
-            if(mode==modeFREEDV) {
-              if(tx) {
-                cairo_set_source_rgb(cr, 1, 0, 0);
-              } else {
-                cairo_set_source_rgb(cr, 0, 1, 0);
-              }
-              cairo_set_font_size(cr, 16);
-              cairo_text_extents(cr, freedv_text_data, &extents);
-              cairo_move_to(cr, (double)display_width/2.0-(extents.width/2.0),(double)display_height-2.0);
-              cairo_show_text(cr, freedv_text_data);
-            }
-#endif
-
-
-            cairo_destroy (cr);
-            gtk_widget_queue_draw (panadapter);
-
-            if(tx) {
-              panadapter_high=saved_max;
-              panadapter_low=saved_min;
-              hz_per_pixel=saved_hz_per_pixel;
-            } /* else if(mode==modeFREEDV) {
-              panadapter_high=saved_max;
-              panadapter_low=saved_min;
-              hz_per_pixel=saved_hz_per_pixel;
-            } */
-        }
-    //}
-}
-
-GtkWidget* panadapter_init(int width,int height) {
-
-  display_width=width;
-  display_height=height;
-
-  samples=malloc(display_width*sizeof(float));
-  hz_per_pixel=(double)getSampleRate()/(double)display_width;
-
-  panadapter = gtk_drawing_area_new ();
-  gtk_widget_set_size_request (panadapter, width, height);
-
-  /* Signals used to handle the backing surface */
-  g_signal_connect (panadapter, "draw",
-            G_CALLBACK (panadapter_draw_cb), NULL);
-  g_signal_connect (panadapter,"configure-event",
-            G_CALLBACK (panadapter_configure_event_cb), NULL);
-
-  /* Event signals */
-  g_signal_connect (panadapter, "motion-notify-event",
-            G_CALLBACK (panadapter_motion_notify_event_cb), NULL);
-  g_signal_connect (panadapter, "button-press-event",
-            G_CALLBACK (panadapter_button_press_event_cb), NULL);
-  g_signal_connect (panadapter, "button-release-event",
-            G_CALLBACK (panadapter_button_release_event_cb), NULL);
-  g_signal_connect(panadapter,"scroll_event",
-            G_CALLBACK(panadapter_scroll_event_cb),NULL);
-
-  /* Ask to receive events the drawing area doesn't normally
-   * subscribe to. In particular, we need to ask for the
-   * button press and motion notify events that want to handle.
-   */
-  gtk_widget_set_events (panadapter, gtk_widget_get_events (panadapter)
-                     | GDK_BUTTON_PRESS_MASK
-                     | GDK_BUTTON_RELEASE_MASK
-                     | GDK_BUTTON1_MOTION_MASK
-                     | GDK_SCROLL_MASK
-                     | GDK_POINTER_MOTION_MASK
-                     | GDK_POINTER_MOTION_HINT_MASK);
-
-  return panadapter;
-}
diff --git a/panadapter.h b/panadapter.h
deleted file mode 100644 (file)
index 61717d0..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Copyright (C)
-* 2015 - John Melton, G0ORX/N6LYT
-*
-* 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 2
-* 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, write to the Free Software
-* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-*
-*/
-
-#ifndef _PANADAPTER_H
-#define _PANADAPTER_H
-
-void panadapter_update(float* data,int tx);
-
-GtkWidget* panadapter_init(int width,int height);
-
-
-#endif
index 4aabfc145acfdec6883514f0dcbc8c1e94ebc387..d960b1873ab955f0dacbb0614b17cdbdcd461243 100644 (file)
@@ -24,6 +24,8 @@
 
 PROPERTY* properties;
 
+static double version=0.0;
+
 /* --------------------------------------------------------------------------*/
 /**
 * @brief Load Properties
@@ -52,11 +54,18 @@ void loadProperties(char* filename) {
                 strcpy(property->value,value);
                 property->next_property=properties;
                 properties=property;
+                if(strcmp(name,"property_version")==0) {
+                  version=atof(value);
+                }
             }
         }
         fclose(f);
     }
-    fprintf(stderr,"loadProperties: done\n");
+
+    if(version!=PROPERTY_VERSION) {
+      properties=NULL;
+      fprintf(stderr,"loadProperties: version=%f expected version=%f ignoring\n",version,PROPERTY_VERSION);
+    }
 }
 
 /* --------------------------------------------------------------------------*/
@@ -75,8 +84,8 @@ void saveProperties(char* filename) {
         return;
     }
 
-    sprintf(version,"%0.2f", PROPERTY_VERSION);
-    setProperty("property_version",version);
+    sprintf(line,"%s=%0.2f\n","property_version",PROPERTY_VERSION);
+    fwrite(line,1,strlen(line),f);
     while(property) {
         sprintf(line,"%s=%s\n",property->name,property->value);
         fwrite(line,1,strlen(line),f);
index 883025b55f693d38026db4e69725cd4d9a2e38d7..3fb103af6b22324ba3c5f584581f6f5fca3e8e9e 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef _PROPERTY_H
 #define _PROPERTY_H
 
-#define PROPERTY_VERSION 1.0
+#define PROPERTY_VERSION 2.0
 
 typedef struct _PROPERTY PROPERTY;
 
diff --git a/psk.c b/psk.c
index a3905e5e636fe6cee71be3a09fd2c1b89fea6e98..a2b8280cc61ad2c71ca2b8906d76be021a6ba3e5 100644 (file)
--- a/psk.c
+++ b/psk.c
@@ -8,7 +8,6 @@
 #include "psk.h"
 #include "radio.h"
 #include "channel.h"
-#include "wdsp_init.h"
 
 static void *detector;
 
index 5572b9f7b52515599887b2c84a495171d46893a6..ba03e50518b45552b4cc27997452989dbd0d57c8 100644 (file)
@@ -29,6 +29,7 @@
 #include "vfo.h"
 #include "psk.h"
 #include "psk_waterfall.h"
+#include "receiver.h"
 
 static GtkWidget *waterfall;
 static GdkPixbuf *pixbuf = NULL;
@@ -130,10 +131,10 @@ waterfall_button_release_event_cb (GtkWidget      *widget,
   if (event->button == 1) {
     if(has_moved) {
       // drag
-      vfo_move((int)((float)(x-last_x)*hz_per_pixel));
+      vfo_move((long long)((float)(x-last_x)*hz_per_pixel));
     } else {
       // move to this frequency
-      vfo_move_to((int)((float)(x-(display_width/2))*hz_per_pixel));
+      vfo_move_to((long long)((float)(x-(display_width/2))*hz_per_pixel));
     }
     last_x=x;
     pressed=FALSE;
@@ -157,7 +158,7 @@ waterfall_motion_notify_event_cb (GtkWidget      *widget,
                                 &state);
   if((state & GDK_BUTTON1_MASK == GDK_BUTTON1_MASK) || pressed) {
     int moved=last_x-x;
-    vfo_move((int)((float)moved*hz_per_pixel));
+    vfo_move((long long)((float)moved*hz_per_pixel));
     last_x=x;
     has_moved=TRUE;
   }
@@ -180,7 +181,7 @@ waterfall_scroll_event_cb (GtkWidget      *widget,
   return TRUE;
 }
 
-void psk_waterfall_update(float *data) {
+void psk_waterfall_update(RECEIVER *rx) {
 
   int i;
 
index abdf8aea4b07bb804dc2f8de32446583bb47a67b..648ef3434d99fa778c835d15c30d3239142759e8 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef _PSK_WATERFALL_H
 #define _PSK_WATERFALL_H
 
-void psk_waterfall_update(float *data);
+void psk_waterfall_update(RECEIVER *rx);
 GtkWidget* psk_waterfall_init(int width,int height);
 
 #endif
diff --git a/radio.c b/radio.c
index 4698dd72e17dca132da0a9741ca8f1f4ddb4a5d8..e4a55d560e14e16749ed89ad4cdeb2dcb29797b0 100644 (file)
--- a/radio.c
+++ b/radio.c
 *
 */
 
+#include <gtk/gtk.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <semaphore.h>
 #include <math.h>
 
+#include <wdsp.h>
+
 #include "audio.h"
 #include "discovered.h"
 //#include "discovery.h"
+#include "filter.h"
+#include "main.h"
 #include "mode.h"
 #include "radio.h"
+#include "receiver.h"
+#include "transmitter.h"
 #include "channel.h"
 #include "agc.h"
 #include "band.h"
 #include "property.h"
 #include "new_protocol.h"
+#include "old_protocol.h"
+#include "store.h"
 #ifdef LIMESDR
 #include "lime_protocol.h"
 #endif
-#include "wdsp.h"
 #ifdef FREEDV
 #include "freedv.h"
 #endif
+#ifdef GPIO
+#include "gpio.h"
+#endif
+#include "vfo.h"
+#include "meter.h"
+#include "rx_panadapter.h"
+#include "tx_panadapter.h"
+#include "waterfall.h"
+#include "sliders.h"
+#include "toolbar.h"
 
 #define min(x,y) (x<y?x:y)
 #define max(x,y) (x<y?y:x)
 
+#define DISPLAY_INCREMENT (display_height/32)
+#define MENU_HEIGHT (DISPLAY_INCREMENT*2)
+#define MENU_WIDTH ((display_width/32)*3)
+#define VFO_HEIGHT (DISPLAY_INCREMENT*4)
+#define VFO_WIDTH (display_width-METER_WIDTH-MENU_WIDTH)
+#define METER_HEIGHT (DISPLAY_INCREMENT*4)
+#define METER_WIDTH ((display_width/32)*8)
+#define PANADAPTER_HEIGHT (DISPLAY_INCREMENT*8)
+#define SLIDERS_HEIGHT (DISPLAY_INCREMENT*6)
+#define TOOLBAR_HEIGHT (DISPLAY_INCREMENT*2)
+#define WATERFALL_HEIGHT (display_height-(VFO_HEIGHT+PANADAPTER_HEIGHT+SLIDERS_HEIGHT+TOOLBAR_HEIGHT))
+#ifdef PSK
+#define PSK_WATERFALL_HEIGHT (DISPLAY_INCREMENT*6)
+#define PSK_HEIGHT (display_height-(VFO_HEIGHT+PSK_WATERFALL_HEIGHT+SLIDERS_HEIGHT+TOOLBAR_HEIGHT))
+#endif
+
+static GtkWidget *fixed;
+static GtkWidget *vfo_panel;
+static GtkWidget *meter;
+static GtkWidget *menu;
+static GtkWidget *sliders;
+static GtkWidget *toolbar;
+static GtkWidget *panadapter;
+static GtkWidget *waterfall;
+#ifdef PSK
+static GtkWidget *psk;
+static GtkWidget *psk_waterfall;
+#endif
+
+#ifdef GPIO
+static GtkWidget *encoders;
+static cairo_surface_t *encoders_surface = NULL;
+#endif
+
+int echo=0;
+
+static gint save_timer_id;
+
 DISCOVERED *radio;
 
 char property_path[128];
 sem_t property_sem;
 
+RECEIVER *receiver[MAX_RECEIVERS];
+RECEIVER *active_receiver;
+TRANSMITTER *transmitter;
+
+int buffer_size=1024; // 64, 128, 256, 512, 1024
+int fft_size=4096; // 1024, 2048, 4096, 8192, 16384
+
 int atlas_penelope=0;
 int atlas_clock_source_10mhz=0;
 int atlas_clock_source_128mhz=0;
@@ -65,14 +128,12 @@ int tx_leveler=0;
 
 double tone_level=0.0;
 
-int sample_rate=48000;
 int filter_board=ALEX;
 //int pa=PA_ENABLED;
 //int apollo_tuner=0;
 
 int updates_per_second=10;
 
-int display_panadapter=1;
 int panadapter_high=-40;
 int panadapter_low=-140;
 
@@ -82,23 +143,16 @@ int display_average_mode=AVERAGE_MODE_LOG_RECURSIVE;
 double display_average_time=120.0;
 
 
-int display_waterfall=1;
 int waterfall_high=-100;
 int waterfall_low=-150;
 int waterfall_automatic=1;
 
 int display_sliders=1;
-int display_toolbar=1;
-int toolbar_dialog_buttons=1;
 
-double volume=0.2;
+//double volume=0.2;
 double mic_gain=0.0;
 int binaural=0;
 
-int rx_dither=0;
-int rx_random=0;
-int rx_preamp=0;
-
 int mic_linein=0;
 int linein_gain=16; // 0..31
 int mic_boost=0;
@@ -106,24 +160,6 @@ int mic_bias_enabled=0;
 int mic_ptt_enabled=0;
 int mic_ptt_tip_bias_ring=0;
 
-int agc=AGC_MEDIUM;
-double agc_gain=80.0;
-double agc_slope=35.0;
-double agc_hang_threshold=0.0;
-
-int nr_none=1;
-int nr=0;
-int nr2=0;
-int nb=0;
-int nb2=0;
-int anf=0;
-int snb=0;
-
-int nr_agc=0; // 0=pre AGC 1=post AGC
-int nr2_gain_method=2; // 0=Linear 1=Log 2=gamma
-int nr2_npe_method=0; // 0=OSMS 1=MMSE
-int nr2_ae=1; // 0=disable 1=enable
-
 double tune_drive=10;
 double drive=50;
 
@@ -131,15 +167,12 @@ int drive_level=0;
 int tune_drive_level=0;
 
 int receivers=RECEIVERS;
-int active_receiver=0;
-
-int adc[2]={0,1};
 
 int locked=0;
 
-int step=100;
+long long step=100;
 
-int rit=0;
+//int rit=0;
 int rit_increment=10;
 
 int lt2208Dither = 0;
@@ -186,10 +219,18 @@ unsigned int IO3;
 int supply_volts;
 int mox;
 int tune;
+int memory_tune=0;
+int full_tune=0;
+
+//long long displayFrequency=14250000;
+//long long ddsFrequency=14250000;
+//long long ddsOffset=0;
 
-long long displayFrequency=14250000;
-long long ddsFrequency=14250000;
-long long ddsOffset=0;
+long long frequencyB=14250000;
+int modeB=modeUSB;
+int filterB=5;
+
+int split=0;
 
 unsigned char OCtune=0;
 int OCfull_tune_time=2800; // ms
@@ -205,16 +246,15 @@ int local_microphone=0;
 int eer_pwm_min=100;
 int eer_pwm_max=800;
 
-int tx_filter_low=200;
-int tx_filter_high=3100;
+int tx_filter_low=150;
+int tx_filter_high=2850;
 
 #ifdef FREEDV
 char freedv_tx_text_data[64];
 #endif
 
-static int pre_tune_mode;
-
-int ctun=0;
+static int pre_tune_filter_low;
+static int pre_tune_filter_high;
 
 int enable_tx_equalizer=0;
 int tx_equalizer[4]={0,0,0,0};
@@ -225,6 +265,7 @@ int rx_equalizer[4]={0,0,0,0};
 int deviation=2500;
 int pre_emphasize=0;
 
+int vox_setting=0;
 int vox_enabled=0;
 double vox_threshold=0.001;
 double vox_gain=10.0;
@@ -235,44 +276,328 @@ int diversity_enabled=0;
 double i_rotate[2]={1.0,1.0};
 double q_rotate[2]={0.0,0.0};
 
-void init_radio() {
+void reconfigure_radio() {
+  int i;
+  int y;
+  int rx_height=display_height-VFO_HEIGHT-TOOLBAR_HEIGHT;
+  if(display_sliders) {
+    rx_height-=SLIDERS_HEIGHT;
+  }
+  y=VFO_HEIGHT;
+  for(i=0;i<receivers;i++) {
+    reconfigure_receiver(receiver[i],rx_height/receivers);
+    gtk_fixed_move(GTK_FIXED(fixed),receiver[i]->panel,0,y);
+    y+=rx_height/receivers;
+  }
+
+  if(display_sliders) {
+    if(sliders==NULL) {
+      sliders = sliders_init(display_width,SLIDERS_HEIGHT);
+      gtk_fixed_put(GTK_FIXED(fixed),sliders,0,y);
+    } else {
+      gtk_fixed_move(GTK_FIXED(fixed),sliders,0,y);
+    }
+    gtk_widget_show_all(sliders);
+    // force change of sliders for mic or linein
+    g_idle_add(linein_changed,NULL);
+  } else {
+    if(sliders!=NULL) {
+      gtk_container_remove(GTK_CONTAINER(fixed),sliders); 
+      sliders=NULL;
+    }
+  }
+
+  reconfigure_transmitter(transmitter,rx_height);
+
+}
+
+static gboolean save_cb(gpointer data) {
+    radioSaveState();
+    return TRUE;
+}
+
+static gboolean minimize_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  gtk_window_iconify(GTK_WINDOW(top_window));
+  return TRUE;
+}
+
+static gboolean menu_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  new_menu(top_window);
+  return TRUE;
+}
+
+void start_radio() {
+  int i;
+  int x;
+  int y;
+fprintf(stderr,"start_radio: selected radio=%p device=%d\n",radio,radio->device);
+  gdk_window_set_cursor(gtk_widget_get_window(top_window),gdk_cursor_new(GDK_WATCH));
+
   int rc;
   rc=sem_init(&property_sem, 0, 0);
   if(rc!=0) {
-    fprintf(stderr,"init_radio: sem_init failed for property_sem: %d\n", rc);
+    fprintf(stderr,"start_radio: sem_init failed for property_sem: %d\n", rc);
     exit(-1);
   }
   sem_post(&property_sem);
+
+  status_text("starting radio ...");
+  protocol=radio->protocol;
+  device=radio->device;
+
+  switch(radio->protocol) {
+    case ORIGINAL_PROTOCOL:
+    case NEW_PROTOCOL:
+      switch(radio->device) {
+#ifdef USBOZY
+        case DEVICE_OZY:
+          sprintf(property_path,"ozy.props");
+          break;
+#endif
+        default:
+          sprintf(property_path,"%02X-%02X-%02X-%02X-%02X-%02X.props",
+                        radio->info.network.mac_address[0],
+                        radio->info.network.mac_address[1],
+                        radio->info.network.mac_address[2],
+                        radio->info.network.mac_address[3],
+                        radio->info.network.mac_address[4],
+                        radio->info.network.mac_address[5]);
+          break;
+      }
+      break;
+#ifdef LIMESDR
+    case LIMESDR_PROTOCOL:
+      sprintf(property_path,"limesdr.props");
+      break;
+#endif
+  }
+
+  radioRestoreState();
+
+  y=0;
+
+  fixed=gtk_fixed_new();
+  gtk_container_remove(GTK_CONTAINER(top_window),grid);
+  gtk_container_add(GTK_CONTAINER(top_window), fixed);
+
+fprintf(stderr,"radio: vfo_init\n");
+  vfo_panel = vfo_init(VFO_WIDTH,VFO_HEIGHT,top_window);
+  gtk_fixed_put(GTK_FIXED(fixed),vfo_panel,0,y);
+
+fprintf(stderr,"radio: meter_init\n");
+  meter = meter_init(METER_WIDTH,METER_HEIGHT,top_window);
+  gtk_fixed_put(GTK_FIXED(fixed),meter,VFO_WIDTH,y);
+
+
+  GtkWidget *minimize_b=gtk_button_new_with_label("Hide");
+  gtk_widget_override_font(minimize_b, pango_font_description_from_string("FreeMono Bold 10"));
+  gtk_widget_set_size_request (minimize_b, MENU_WIDTH, MENU_HEIGHT);
+  g_signal_connect (minimize_b, "button-press-event", G_CALLBACK(minimize_cb), NULL) ;
+  gtk_fixed_put(GTK_FIXED(fixed),minimize_b,VFO_WIDTH+METER_WIDTH,y);
+  y+=MENU_HEIGHT;
+
+  GtkWidget *menu_b=gtk_button_new_with_label("Menu");
+  gtk_widget_override_font(menu_b, pango_font_description_from_string("FreeMono Bold 10"));
+  gtk_widget_set_size_request (menu_b, MENU_WIDTH, MENU_HEIGHT);
+  g_signal_connect (menu_b, "button-press-event", G_CALLBACK(menu_cb), NULL) ;
+  gtk_fixed_put(GTK_FIXED(fixed),menu_b,VFO_WIDTH+METER_WIDTH,y);
+  y+=MENU_HEIGHT;
+
+
+  int rx_height=display_height-VFO_HEIGHT-TOOLBAR_HEIGHT;
+  if(display_sliders) {
+    rx_height-=SLIDERS_HEIGHT;
+  }
+  int tx_height=rx_height;
+  rx_height=rx_height/receivers;
+
+
+fprintf(stderr,"Create %d receivers: height=%d\n",receivers,rx_height);
+  for(i=0;i<MAX_RECEIVERS;i++) {
+    receiver[i]=create_receiver(i, buffer_size, fft_size, display_width, updates_per_second, display_width, rx_height);
+    g_object_ref((gpointer)receiver[i]->panel);
+    if(i<receivers) {
+      gtk_fixed_put(GTK_FIXED(fixed),receiver[i]->panel,0,y);
+fprintf(stderr,"receiver %d: height=%d y=%d\n",receiver[i]->id,rx_height,y);
+      set_displaying(receiver[i],1);
+      y+=rx_height;
+    } else {
+      set_displaying(receiver[i],0);
+    }
+  }
+  active_receiver=receiver[0];
+
+  fprintf(stderr,"Create transmitter\n");
+  transmitter=create_transmitter(CHANNEL_TX, buffer_size, fft_size, updates_per_second, display_width, tx_height);
+  g_object_ref((gpointer)transmitter->panel);
+
+  switch(radio->protocol) {
+    case ORIGINAL_PROTOCOL:
+      old_protocol_init(0,display_width,receiver[0]->sample_rate);
+      break;
+    case NEW_PROTOCOL:
+      new_protocol_init(display_width);
+      break;
+#ifdef LIMESDR
+    case LIMESDR_PROTOCOL:
+      lime_protocol_init(0,display_width);
+      break;
+#endif
+  }
+
+#ifdef GPIO
+  if(gpio_init()<0) {
+    fprintf(stderr,"GPIO failed to initialize\n");
+  }
+#ifdef LOCALCW
+  // init local keyer if enabled
+  else if (cw_keyer_internal == 0)
+    keyer_update();
+#endif
+#endif
+
+#ifdef I2C
+  i2c_init();
+#endif
+
+  if(display_sliders) {
+fprintf(stderr,"create sliders\n");
+    sliders = sliders_init(display_width,SLIDERS_HEIGHT);
+    gtk_fixed_put(GTK_FIXED(fixed),sliders,0,y);
+    y+=SLIDERS_HEIGHT;
+  }
+
+  toolbar = toolbar_init(display_width,TOOLBAR_HEIGHT,top_window);
+  gtk_fixed_put(GTK_FIXED(fixed),toolbar,0,y);
+  y+=TOOLBAR_HEIGHT;
+
+  gtk_widget_show_all (fixed);
+
+  // force change of sliders for mic or linein
+  g_idle_add(linein_changed,NULL);
+
+  // save every 30 seconds
+fprintf(stderr,"start save timer\n");
+  save_timer_id=gdk_threads_add_timeout(30000, save_cb, NULL);
+
+#ifdef PSK
+  if(active_receiver->mode==modePSK) {
+    show_psk();
+  } else {
+    show_waterfall();
+  }
+#endif
+
+  launch_rigctl();
+
+  calcDriveLevel();
+  calcTuneDriveLevel();
+
+  if(protocol==NEW_PROTOCOL) {
+    schedule_high_priority();
+  }
+
+  g_idle_add(vfo_update,(gpointer)NULL);
+
+fprintf(stderr,"set cursor\n");
+  gdk_window_set_cursor(gtk_widget_get_window(top_window),gdk_cursor_new(GDK_ARROW));
+
+for(i=0;i<MAX_VFOS;i++) {
+  fprintf(stderr,"start_radio: vfo %d band=%d bandstack=%d frequency=%lld mode=%d filter=%d rit=%lld lo=%%ld offset=%lld\n",
+    i,
+    vfo[i].band,
+    vfo[i].bandstack,
+    vfo[i].frequency,
+    vfo[i].mode,
+    vfo[i].filter,
+    vfo[i].rit,
+    vfo[i].lo,
+    vfo[i].offset);
 }
+}
+
 
-void setSampleRate(int rate) {
-    sample_rate=rate;
+void radio_change_receivers(int r) {
+  switch(r) {
+    case 1:
+      if(receivers==2) {
+        set_displaying(receiver[1],0);
+        gtk_container_remove(GTK_CONTAINER(fixed),receiver[1]->panel);
+      }
+      receivers=1;
+      break;
+    case 2:
+      gtk_fixed_put(GTK_FIXED(fixed),receiver[1]->panel,0,0);
+      set_displaying(receiver[1],1);
+      receivers=2;
+      break;
+  }
+  reconfigure_radio();
+  active_receiver=receiver[0];
 }
 
-int getSampleRate() {
-    return sample_rate;
+void radio_change_sample_rate(int rate) {
+  int i;
+  switch(protocol) {
+    case ORIGINAL_PROTOCOL:
+      old_protocol_stop();
+      for(i=0;i<receivers;i++) {
+        receiver_change_sample_rate(receiver[i],rate);
+      }
+      old_protocol_set_mic_sample_rate(rate);
+      old_protocol_run();
+      break;
+#ifdef LIMESDR
+    case LIMESDR_PROTOCOL:
+      break;
+#endif
+  }
 }
 
 static void rxtx(int state) {
+  int i;
+  int y=VFO_HEIGHT;
+
   if(state) {
     // switch to tx
-    SetChannelState(CHANNEL_RX0,0,1);
-    if(protocol==NEW_PROTOCOL) {
-      schedule_high_priority(3);
+    for(i=0;i<receivers;i++) {
+      SetChannelState(receiver[i]->id,0,i==(receivers-1));
+      set_displaying(receiver[i],0);
+      if(protocol==NEW_PROTOCOL) {
+        schedule_high_priority();
+      }
+      gtk_container_remove(GTK_CONTAINER(fixed),receiver[i]->panel);
     }
-    SetChannelState(CHANNEL_TX,1,0);
+    gtk_fixed_put(GTK_FIXED(fixed),transmitter->panel,0,y);
+    SetChannelState(transmitter->id,1,0);
+    tx_set_displaying(transmitter,1);
 #ifdef FREEDV
-    if(mode==modeFREEDV) {
+    if(active_receiver->mode==modeFREEDV) {
       freedv_reset_tx_text_index();
     }
 #endif
   } else {
-    SetChannelState(CHANNEL_TX,0,1);
+    SetChannelState(transmitter->id,0,1);
     if(protocol==NEW_PROTOCOL) {
-      schedule_high_priority(3);
+      schedule_high_priority();
+    }
+    tx_set_displaying(transmitter,0);
+    gtk_container_remove(GTK_CONTAINER(fixed),transmitter->panel);
+    int rx_height=display_height-VFO_HEIGHT-TOOLBAR_HEIGHT;
+    if(display_sliders) {
+      rx_height-=SLIDERS_HEIGHT;
+    }
+    for(i=0;i<receivers;i++) {
+      SetChannelState(receiver[i]->id,1,0);
+      set_displaying(receiver[i],1);
+      gtk_fixed_put(GTK_FIXED(fixed),receiver[i]->panel,0,y);
+      y+=(rx_height/receivers);
     }
-    SetChannelState(CHANNEL_RX0,1,0);
   }
+
+  gtk_widget_show_all(fixed);
+  g_idle_add(linein_changed,NULL);
 }
 
 void setMox(int state) {
@@ -298,47 +623,99 @@ void setVox(int state) {
 }
 
 void setTune(int state) {
+  int i;
+
   if(tune!=state) {
     tune=state;
     if(vox_enabled && vox) {
       vox_cancel();
     }
     if(tune) {
-      if(OCmemory_tune_time!=0) {
-        struct timeval te;
-        gettimeofday(&te,NULL);
-        tune_timeout=(te.tv_sec*1000LL+te.tv_usec/1000)+(long long)OCmemory_tune_time;
+      if(full_tune) {
+        if(OCfull_tune_time!=0) {
+          struct timeval te;
+          gettimeofday(&te,NULL);
+          tune_timeout=(te.tv_sec*1000LL+te.tv_usec/1000)+(long long)OCfull_tune_time;
+        }
+      }
+      if(memory_tune) {
+        if(OCmemory_tune_time!=0) {
+          struct timeval te;
+          gettimeofday(&te,NULL);
+          tune_timeout=(te.tv_sec*1000LL+te.tv_usec/1000)+(long long)OCmemory_tune_time;
+        }
       }
     }
     if(protocol==NEW_PROTOCOL) {
-      schedule_high_priority(4);
+      schedule_high_priority();
       //schedule_general();
     }
     if(tune) {
-      SetChannelState(CHANNEL_RX0,0,1);
-      pre_tune_mode = mode;
-      if(mode==modeCWL) {
-        setMode(modeLSB);
-      } else if(mode==modeCWU) {
-        setMode(modeUSB);
+      for(i=0;i<receivers;i++) {
+        SetChannelState(receiver[i]->id,0,i==(receivers-1));
+        set_displaying(receiver[i],0);
+        if(protocol==NEW_PROTOCOL) {
+          schedule_high_priority();
+        }
       }
-      SetTXAPostGenMode(CHANNEL_TX,0);
-      if(mode==modeLSB || mode==modeCWL || mode==modeDIGL) {
-        SetTXAPostGenToneFreq(CHANNEL_TX,-(double)cw_keyer_sidetone_frequency);
-      } else {
-        SetTXAPostGenToneFreq(CHANNEL_TX,(double)cw_keyer_sidetone_frequency);
+
+      int mode=vfo[VFO_A].mode;;
+      if(split) {
+        mode=vfo[VFO_B].mode;
       }
-      SetTXAPostGenToneMag(CHANNEL_TX,0.99999);
-      SetTXAPostGenRun(CHANNEL_TX,1);
-      SetChannelState(CHANNEL_TX,1,0);
-    } else {
-      SetChannelState(CHANNEL_TX,0,1);
-      SetTXAPostGenRun(CHANNEL_TX,0);
-      if(pre_tune_mode==modeCWL || pre_tune_mode==modeCWU) {
-        setMode(pre_tune_mode);
+      double freq=(double)cw_keyer_sidetone_frequency;
+      
+      pre_tune_filter_low=transmitter->filter_low;
+      pre_tune_filter_high=transmitter->filter_high;
+
+      switch(mode) {
+        case modeUSB:
+        case modeCWU:
+        case modeDIGU:
+          SetTXAPostGenToneFreq(transmitter->id,(double)cw_keyer_sidetone_frequency);
+          transmitter->filter_low=cw_keyer_sidetone_frequency-100;
+          transmitter->filter_high=cw_keyer_sidetone_frequency+100;
+          freq=(double)(cw_keyer_sidetone_frequency+100);
+          break;
+        case modeLSB:
+        case modeCWL:
+        case modeDIGL:
+          SetTXAPostGenToneFreq(transmitter->id,-(double)cw_keyer_sidetone_frequency);
+          transmitter->filter_low=-cw_keyer_sidetone_frequency-100;
+          transmitter->filter_high=-cw_keyer_sidetone_frequency+100;
+          freq=(double)(-cw_keyer_sidetone_frequency-100);
+          break;
+        case modeDSB:
+          SetTXAPostGenToneFreq(transmitter->id,(double)cw_keyer_sidetone_frequency);
+          transmitter->filter_low=cw_keyer_sidetone_frequency-100;
+          transmitter->filter_high=cw_keyer_sidetone_frequency+100;
+          freq=(double)(cw_keyer_sidetone_frequency+100);
+          break;
+        case modeAM:
+        case modeSAM:
+        case modeFMN:
+          SetTXAPostGenToneFreq(transmitter->id,(double)cw_keyer_sidetone_frequency);
+          transmitter->filter_low=cw_keyer_sidetone_frequency-100;
+          transmitter->filter_high=cw_keyer_sidetone_frequency+100;
+          freq=(double)(cw_keyer_sidetone_frequency+100);
+          break;
       }
-      SetChannelState(CHANNEL_RX0,1,0);
+
+      SetTXABandpassFreqs(transmitter->id,transmitter->filter_low,transmitter->filter_high);
+
+      
+      SetTXAMode(transmitter->id,modeDIGU);
+      SetTXAPostGenMode(transmitter->id,0);
+      SetTXAPostGenToneMag(transmitter->id,0.99999);
+      SetTXAPostGenRun(transmitter->id,1);
+    } else {
+      SetTXAPostGenRun(transmitter->id,0);
+      SetTXAMode(transmitter->id,transmitter->mode);
+      transmitter->filter_low=pre_tune_filter_low;
+      transmitter->filter_high=pre_tune_filter_high;
+      SetTXABandpassFreqs(transmitter->id,transmitter->filter_low,transmitter->filter_high);
     }
+    rxtx(tune);
   }
 }
 
@@ -353,30 +730,32 @@ int isTransmitting() {
 void setFrequency(long long f) {
   BAND *band=band_get_current_band();
   BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
+  int v=active_receiver->id;
 
   switch(protocol) {
     case NEW_PROTOCOL:
     case ORIGINAL_PROTOCOL:
-      if(ctun) {
-        long long minf=entry->frequencyA-(long long)(sample_rate/2);
-        long long maxf=entry->frequencyA+(long long)(sample_rate/2);
+      if(vfo[v].ctun) {
+        long long minf=vfo[v].frequency-(long long)(active_receiver->sample_rate/2);
+        long long maxf=vfo[v].frequency+(long long)(active_receiver->sample_rate/2);
         if(f<minf) f=minf;
         if(f>maxf) f=maxf;
-        ddsOffset=f-entry->frequencyA;
-        wdsp_set_offset(ddsOffset);
+        vfo[v].offset=f-vfo[v].frequency;
+        set_offset(active_receiver,vfo[v].offset);
         return;
       } else {
-        entry->frequencyA=f;
+        //entry->frequency=f;
+        vfo[v].frequency=f;
       }
       break;
 #ifdef LIMESDR
     case LIMESDR_PROTOCOL:
       {
-      long long minf=entry->frequencyA-(long long)(sample_rate/2);
-      long long maxf=entry->frequencyA+(long long)(sample_rate/2);
+      long long minf=entry->frequency-(long long)(active_receiver->sample_rate/2);
+      long long maxf=entry->frequency+(long long)(active_receiver->sample_rate/2);
       if(f<minf) f=minf;
       if(f>maxf) f=maxf;
-      ddsOffset=f-entry->frequencyA;
+      ddsOffset=f-entry->frequency;
       wdsp_set_offset(ddsOffset);
       return;
       }
@@ -384,14 +763,9 @@ void setFrequency(long long f) {
 #endif
   }
 
-  displayFrequency=f;
-  ddsFrequency=f;
-  if(band->frequencyLO!=0LL) {
-    ddsFrequency=f-band->frequencyLO;
-  }
   switch(protocol) {
     case NEW_PROTOCOL:
-      schedule_high_priority(5);
+      schedule_high_priority();
       break;
     case ORIGINAL_PROTOCOL:
       schedule_frequency_changed();
@@ -407,7 +781,7 @@ void setFrequency(long long f) {
 }
 
 long long getFrequency() {
-    return ddsFrequency;
+    return vfo[active_receiver->id].frequency;
 }
 
 double getDrive() {
@@ -416,28 +790,31 @@ double getDrive() {
 
 static int calcLevel(double d) {
   int level=0;
-  BAND *band=band_get_current_band();
+  int v=VFO_A;
+  if(split) v=VFO_B;
+
+  BAND *band=band_get_band(vfo[v].band);
   double target_dbm = 10.0 * log10(d * 1000.0);
   double gbb=band->pa_calibration;
   target_dbm-=gbb;
   double target_volts = sqrt(pow(10, target_dbm * 0.1) * 0.05);
   double volts=min((target_volts / 0.8), 1.0);
-  double v=volts*(1.0/0.98);
+  double actual_volts=volts*(1.0/0.98);
 
-  if(v<0.0) {
-    v=0.0;
-  } else if(v>1.0) {
-    v=1.0;
+  if(actual_volts<0.0) {
+    actual_volts=0.0;
+  } else if(actual_volts>1.0) {
+    actual_volts=1.0;
   }
 
-  level=(int)(v*255.0);
+  level=(int)(actual_volts*255.0);
   return level;
 }
 
 void calcDriveLevel() {
     drive_level=calcLevel(drive);
     if(mox && protocol==NEW_PROTOCOL) {
-      schedule_high_priority(6);
+      schedule_high_priority();
     }
 }
 
@@ -453,7 +830,7 @@ double getTuneDrive() {
 void calcTuneDriveLevel() {
     tune_drive_level=calcLevel(tune_drive);
     if(tune  && protocol==NEW_PROTOCOL) {
-      schedule_high_priority(7);
+      schedule_high_priority();
     }
 }
 
@@ -463,10 +840,9 @@ void setTuneDrive(double value) {
 }
 
 void set_attenuation(int value) {
-    //attenuation=value;
     switch(protocol) {
       case NEW_PROTOCOL:
-        schedule_high_priority(8);
+        schedule_high_priority();
         break;
 #ifdef LIMESDR
       case LIMESDR_PROTOCOL:
@@ -477,13 +853,15 @@ void set_attenuation(int value) {
 }
 
 int get_attenuation() {
-    return attenuation;
+    return active_receiver->attenuation;
 }
 
 void set_alex_rx_antenna(int v) {
-    //alex_rx_antenna=v;
-    if(protocol==NEW_PROTOCOL) {
-        schedule_high_priority(1);
+    if(active_receiver->id==0) {
+      active_receiver->alex_antenna=v;
+      if(protocol==NEW_PROTOCOL) {
+          schedule_high_priority();
+      }
     }
 #ifdef LIMESDR
     if(protocol==LIMESDR_PROTOCOL) {
@@ -493,16 +871,18 @@ void set_alex_rx_antenna(int v) {
 }
 
 void set_alex_tx_antenna(int v) {
-    //alex_tx_antenna=v;
+    transmitter->alex_antenna=v;
     if(protocol==NEW_PROTOCOL) {
-        schedule_high_priority(2);
+        schedule_high_priority();
     }
 }
 
 void set_alex_attenuation(int v) {
-    //alex_attenuation=v;
-    if(protocol==NEW_PROTOCOL) {
-        schedule_high_priority(0);
+    if(active_receiver->id==0) {
+      active_receiver->alex_attenuation=v;
+      if(protocol==NEW_PROTOCOL) {
+          schedule_high_priority();
+      }
     }
 }
 
@@ -513,12 +893,14 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path);
     sem_wait(&property_sem);
     loadProperties(property_path);
 
+    value=getProperty("buffer_size");
+    if(value) buffer_size=atoi(value);
+    value=getProperty("fft_size");
+    if(value) fft_size=atoi(value);
     value=getProperty("atlas_penelope");
     if(value) atlas_penelope=atoi(value);
     value=getProperty("tx_out_of_band");
     if(value) tx_out_of_band=atoi(value);
-    value=getProperty("sample_rate");
-    if(value) sample_rate=atoi(value);
     value=getProperty("filter_board");
     if(value) filter_board=atoi(value);
 /*
@@ -529,8 +911,6 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path);
 */
     value=getProperty("updates_per_second");
     if(value) updates_per_second=atoi(value);
-    value=getProperty("display_panadapter");
-    if(value) display_panadapter=atoi(value);
     value=getProperty("display_filled");
     if(value) display_filled=atoi(value);
     value=getProperty("display_detector_mode");
@@ -543,22 +923,20 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path);
     if(value) panadapter_high=atoi(value);
     value=getProperty("panadapter_low");
     if(value) panadapter_low=atoi(value);
-    value=getProperty("display_waterfall");
-    if(value) display_waterfall=atoi(value);
     value=getProperty("display_sliders");
     if(value) display_sliders=atoi(value);
+/*
     value=getProperty("display_toolbar");
     if(value) display_toolbar=atoi(value);
-    value=getProperty("toolbar_dialog_buttons");
-    if(value) toolbar_dialog_buttons=atoi(value);
+*/
     value=getProperty("waterfall_high");
     if(value) waterfall_high=atoi(value);
     value=getProperty("waterfall_low");
     if(value) waterfall_low=atoi(value);
     value=getProperty("waterfall_automatic");
     if(value) waterfall_automatic=atoi(value);
-    value=getProperty("volume");
-    if(value) volume=atof(value);
+//    value=getProperty("volume");
+//    if(value) volume=atof(value);
     value=getProperty("drive");
     if(value) drive=atof(value);
     value=getProperty("tune_drive");
@@ -577,38 +955,14 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path);
     if(value) mic_bias_enabled=atof(value);
     value=getProperty("mic_ptt_tip_bias_ring");
     if(value) mic_ptt_tip_bias_ring=atof(value);
-    value=getProperty("nr_none");
-    if(value) nr_none=atoi(value);
-    value=getProperty("nr");
-    if(value) nr=atoi(value);
-    value=getProperty("nr2");
-    if(value) nr2=atoi(value);
-    value=getProperty("nb");
-    if(value) nb=atoi(value);
-    value=getProperty("nb2");
-    if(value) nb2=atoi(value);
-    value=getProperty("anf");
-    if(value) anf=atoi(value);
-    value=getProperty("snb");
-    if(value) snb=atoi(value);
-    value=getProperty("nr_agc");
-    if(value) nr_agc=atoi(value);
-    value=getProperty("nr2_gain_method");
-    if(value) nr2_gain_method=atoi(value);
-    value=getProperty("nr2_npe_method");
-    if(value) nr2_npe_method=atoi(value);
-    value=getProperty("nr2_ae");
-    if(value) nr2_ae=atoi(value);
-    value=getProperty("agc");
-    if(value) agc=atoi(value);
-    value=getProperty("agc_gain");
-    if(value) agc_gain=atof(value);
-    value=getProperty("agc_slope");
-    if(value) agc_slope=atof(value);
-    value=getProperty("agc_hang_threshold");
-    if(value) agc_hang_threshold=atof(value);
+
+    value=getProperty("tx_filter_low");
+    if(value) tx_filter_low=atoi(value);
+    value=getProperty("tx_filter_high");
+    if(value) tx_filter_high=atoi(value);
+
     value=getProperty("step");
-    if(value) step=atoi(value);
+    if(value) step=atoll(value);
     value=getProperty("cw_keys_reversed");
     if(value) cw_keys_reversed=atoi(value);
     value=getProperty("cw_keyer_speed");
@@ -643,14 +997,6 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path);
     if(value) OCfull_tune_time=atoi(value);
     value=getProperty("OCmemory_tune_time");
     if(value) OCmemory_tune_time=atoi(value);
-    value=getProperty("attenuation");
-    if(value) attenuation=atoi(value);
-    value=getProperty("rx_dither");
-    if(value) rx_dither=atoi(value);
-    value=getProperty("rx_random");
-    if(value) rx_random=atoi(value);
-    value=getProperty("rx_preamp");
-    if(value) rx_preamp=atoi(value);
 #ifdef FREEDV
     strcpy(freedv_tx_text_data,"NO TEXT DATA");
     value=getProperty("freedv_tx_text_data");
@@ -660,14 +1006,16 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path);
     if(value) smeter=atoi(value);
     value=getProperty("alc");
     if(value) alc=atoi(value);
+#ifdef OLD_AUDIO
     value=getProperty("local_audio");
     if(value) local_audio=atoi(value);
     value=getProperty("n_selected_output_device");
     if(value) n_selected_output_device=atoi(value);
+#endif
     value=getProperty("local_microphone");
     if(value) local_microphone=atoi(value);
-    value=getProperty("n_selected_input_device");
-    if(value) n_selected_input_device=atoi(value);
+//    value=getProperty("n_selected_input_device");
+//    if(value) n_selected_input_device=atoi(value);
     value=getProperty("enable_tx_equalizer");
     if(value) enable_tx_equalizer=atoi(value);
     value=getProperty("tx_equalizer.0");
@@ -709,21 +1057,50 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path);
     value=getProperty("binaural");
     if(value) binaural=atoi(value);
 
+    value=getProperty("frequencyB");
+    if(value) frequencyB=atol(value);
+
+    value=getProperty("modeB");
+    if(value) modeB=atoi(value);
+
+    value=getProperty("filterB");
+    if(value) filterB=atoi(value);
+
+#ifdef GPIO
+    value=getProperty("e1_encoder_action");
+    if(value) e1_encoder_action=atoi(value);
+    value=getProperty("e2_encoder_action");
+    if(value) e2_encoder_action=atoi(value);
+    value=getProperty("e3_encoder_action");
+    if(value) e3_encoder_action=atoi(value);
+#endif
+
+    value=getProperty("receivers");
+    if(value) receivers=atoi(value);
+
+    filterRestoreState();
     bandRestoreState();
+    memRestoreState();
+    vfo_restore_state();
 
     sem_post(&property_sem);
 }
 
 void radioSaveState() {
+    int i;
     char value[80];
 
     sem_wait(&property_sem);
+    sprintf(value,"%d",buffer_size);
+    setProperty("buffer_size",value);
+    sprintf(value,"%d",fft_size);
+    setProperty("fft_size",value);
     sprintf(value,"%d",atlas_penelope);
     setProperty("atlas_penelope",value);
-    sprintf(value,"%d",sample_rate);
-    setProperty("sample_rate",value);
     sprintf(value,"%d",filter_board);
     setProperty("filter_board",value);
+    sprintf(value,"%d",tx_out_of_band);
+    setProperty("tx_out_of_band",value);
 /*
     sprintf(value,"%d",apollo_tuner);
     setProperty("apollo_tuner",value);
@@ -732,8 +1109,6 @@ void radioSaveState() {
 */
     sprintf(value,"%d",updates_per_second);
     setProperty("updates_per_second",value);
-    sprintf(value,"%d",display_panadapter);
-    setProperty("display_panadapter",value);
     sprintf(value,"%d",display_filled);
     setProperty("display_filled",value);
     sprintf(value,"%d",display_detector_mode);
@@ -746,22 +1121,20 @@ void radioSaveState() {
     setProperty("panadapter_high",value);
     sprintf(value,"%d",panadapter_low);
     setProperty("panadapter_low",value);
-    sprintf(value,"%d",display_waterfall);
-    setProperty("display_waterfall",value);
     sprintf(value,"%d",display_sliders);
     setProperty("display_sliders",value);
+/*
     sprintf(value,"%d",display_toolbar);
     setProperty("display_toolbar",value);
-    sprintf(value,"%d",toolbar_dialog_buttons);
-    setProperty("toolbar_dialog_buttons",value);
+*/
     sprintf(value,"%d",waterfall_high);
     setProperty("waterfall_high",value);
     sprintf(value,"%d",waterfall_low);
     setProperty("waterfall_low",value);
     sprintf(value,"%d",waterfall_automatic);
     setProperty("waterfall_automatic",value);
-    sprintf(value,"%f",volume);
-    setProperty("volume",value);
+//    sprintf(value,"%f",volume);
+//    setProperty("volume",value);
     sprintf(value,"%f",mic_gain);
     setProperty("mic_gain",value);
     sprintf(value,"%f",drive);
@@ -780,37 +1153,12 @@ void radioSaveState() {
     setProperty("mic_bias_enabled",value);
     sprintf(value,"%d",mic_ptt_tip_bias_ring);
     setProperty("mic_ptt_tip_bias_ring",value);
-    sprintf(value,"%d",nr_none);
-    setProperty("nr_none",value);
-    sprintf(value,"%d",nr);
-    setProperty("nr",value);
-    sprintf(value,"%d",nr2);
-    setProperty("nr2",value);
-    sprintf(value,"%d",nb);
-    setProperty("nb",value);
-    sprintf(value,"%d",nb2);
-    setProperty("nb2",value);
-    sprintf(value,"%d",anf);
-    setProperty("anf",value);
-    sprintf(value,"%d",snb);
-    setProperty("snb",value);
-    sprintf(value,"%d",nr_agc);
-    setProperty("nr_agc",value);
-    sprintf(value,"%d",nr2_gain_method);
-    setProperty("nr2_gain_method",value);
-    sprintf(value,"%d",nr2_npe_method);
-    setProperty("nr2_npe_method",value);
-    sprintf(value,"%d",nr2_ae);
-    setProperty("nr2_ae",value);
-    sprintf(value,"%d",agc);
-    setProperty("agc",value);
-    sprintf(value,"%f",agc_gain);
-    setProperty("agc_gain",value);
-    sprintf(value,"%f",agc_slope);
-    setProperty("agc_slope",value);
-    sprintf(value,"%f",agc_hang_threshold);
-    setProperty("agc_hang_threshold",value);
-    sprintf(value,"%d",step);
+    sprintf(value,"%d",tx_filter_low);
+    setProperty("tx_filter_low",value);
+    sprintf(value,"%d",tx_filter_high);
+    setProperty("tx_filter_high",value);
+
+    sprintf(value,"%lld",step);
     setProperty("step",value);
     sprintf(value,"%d",cw_keys_reversed);
     setProperty("cw_keys_reversed",value);
@@ -844,14 +1192,6 @@ void radioSaveState() {
     setProperty("OCfull_tune_time",value);
     sprintf(value,"%d",OCmemory_tune_time);
     setProperty("OCmemory_tune_time",value);
-    sprintf(value,"%d",attenuation);
-    setProperty("attenuation",value);
-    sprintf(value,"%d",rx_dither);
-    setProperty("rx_dither",value);
-    sprintf(value,"%d",rx_random);
-    setProperty("rx_random",value);
-    sprintf(value,"%d",rx_preamp);
-    setProperty("rx_preamp",value);
 #ifdef FREEDV
     if(strlen(freedv_tx_text_data)>0) {
       setProperty("freedv_tx_text_data",freedv_tx_text_data);
@@ -861,14 +1201,16 @@ void radioSaveState() {
     setProperty("smeter",value);
     sprintf(value,"%d",alc);
     setProperty("alc",value);
+#ifdef OLD_AUDIO
     sprintf(value,"%d",local_audio);
     setProperty("local_audio",value);
     sprintf(value,"%d",n_selected_output_device);
     setProperty("n_selected_output_device",value);
+#endif
     sprintf(value,"%d",local_microphone);
     setProperty("local_microphone",value);
-    sprintf(value,"%d",n_selected_input_device);
-    setProperty("n_selected_input_device",value);
+//    sprintf(value,"%d",n_selected_input_device);
+//    setProperty("n_selected_input_device",value);
 
     sprintf(value,"%d",enable_tx_equalizer);
     setProperty("enable_tx_equalizer",value);
@@ -911,19 +1253,45 @@ void radioSaveState() {
     sprintf(value,"%d",binaural);
     setProperty("binaural",value);
 
-    bandSaveState();
+    sprintf(value,"%lld",frequencyB);
+    setProperty("frequencyB",value);
+    sprintf(value,"%d",modeB);
+    setProperty("modeB",value);
+    sprintf(value,"%d",filterB);
+    setProperty("filterB",value);
+
+#ifdef GPIO
+    sprintf(value,"%d",e1_encoder_action);
+    setProperty("e1_encoder_action",value);
+    sprintf(value,"%d",e2_encoder_action);
+    setProperty("e2_encoder_action",value);
+    sprintf(value,"%d",e3_encoder_action);
+    setProperty("e3_encoder_action",value);
+#endif
 
+
+    vfo_save_state();
+    sprintf(value,"%d",receivers);
+    setProperty("receivers",value);
+    for(i=0;i<receivers;i++) {
+      receiver_save_state(receiver[i]);
+    }
+    transmitter_save_state(transmitter);
+
+    filterSaveState();
+    bandSaveState();
+    memSaveState();
     saveProperties(property_path);
     sem_post(&property_sem);
 }
 
-void calculate_display_average() {
+void calculate_display_average(RECEIVER *rx) {
   double display_avb;
   int display_average;
 
   double t=0.001*display_average_time;
-  display_avb = exp(-1.0 / ((double)updates_per_second * t));
-  display_average = max(2, (int)min(60, (double)updates_per_second * t));
-  SetDisplayAvBackmult(CHANNEL_RX0, 0, display_avb);
-  SetDisplayNumAverage(CHANNEL_RX0, 0, display_average);
+  display_avb = exp(-1.0 / ((double)rx->fps * t));
+  display_average = max(2, (int)min(60, (double)rx->fps * t));
+  SetDisplayAvBackmult(rx->id, 0, display_avb);
+  SetDisplayNumAverage(rx->id, 0, display_average);
 }
diff --git a/radio.h b/radio.h
index 90089611143bbbfe3129a94f02f5796ff3e306e5..0c41d568770198c5e8b73352df97beacba14809b 100644 (file)
--- a/radio.h
+++ b/radio.h
@@ -21,6 +21,8 @@
 #define _RADIO_H
 
 #include "discovered.h"
+#include "receiver.h"
+#include "transmitter.h"
 
 #define NEW_MIC_IN 0x00
 #define NEW_LINE_IN 0x01
@@ -51,8 +53,14 @@ extern char property_path[];
 #define ALEX 1
 #define APOLLO 2
 
-// soecify how many receivers (only 1 or 2 for now)
-#define RECEIVERS 1
+// specify how many receivers (only 1 or 2 for now)
+#define MAX_RECEIVERS 2
+#define RECEIVERS 2
+
+extern RECEIVER *receiver[];
+extern RECEIVER *active_receiver;
+
+extern TRANSMITTER *transmitter;
 
 /*
 #define PA_DISABLED 0
@@ -64,9 +72,12 @@ extern char property_path[];
 #define KEYER_MODE_A 1
 #define KEYER_MODE_B 2
 
-extern int rx_dither;
-extern int rx_random;
-extern int rx_preamp;
+extern int echo;
+
+#define MAX_BUFFER_SIZE 2048
+
+extern int buffer_size;
+extern int fft_size;
 
 extern int atlas_penelope;
 extern int atlas_clock_source_10mhz;
@@ -84,7 +95,6 @@ extern int tx_leveler;
 
 extern double tone_level;
 
-extern int sample_rate;
 extern int filter_board;
 extern int pa;
 extern int apollo_tuner;
@@ -107,28 +117,9 @@ extern int waterfall_automatic;
 
 extern int display_sliders;
 extern int display_toolbar;
-extern int toolbar_dialog_buttons;
 
-extern double volume;
 extern double mic_gain;
 extern int binaural;
-extern int agc;
-extern double agc_gain;
-extern double agc_slope;
-extern double agc_hang_threshold;
-
-extern int nr_none;
-extern int nr;
-extern int nr2;
-extern int nb;
-extern int nb2;
-extern int anf;
-extern int snb;
-
-extern int nr_agc;
-extern int nr2_gain_method;
-extern int nr2_npe_method;
-extern int nr2_ae;
 
 extern int mic_linein;
 extern int linein_gain;
@@ -144,14 +135,13 @@ extern int tune_drive_level;
 extern int drive_level;
 
 int receivers;
-int active_receiver;
 
 int adc[2];
 
 int locked;
 
-extern int step;
-extern int rit;
+extern long long step;
+//extern int rit;
 extern int rit_increment;
 
 extern int lt2208Dither;
@@ -183,6 +173,8 @@ extern int mercury_software_version;
 extern int penelope_software_version;
 extern int mox;
 extern int tune;
+extern int memory_tune;
+extern int full_tune;
 extern int ptt;
 extern int dot;
 extern int dash;
@@ -199,9 +191,15 @@ extern unsigned int AIN4;
 extern unsigned int AIN6;
 extern int supply_volts;
 
-extern long long displayFrequency;
-extern long long ddsFrequency;
-extern long long ddsOffset;
+//extern long long displayFrequency;
+//extern long long ddsFrequency;
+//extern long long ddsOffset;
+
+extern long long frequencyB;
+extern int modeB;
+extern int filterB;
+
+extern int split;
 
 extern unsigned char OCtune;
 extern int OCfull_tune_time;
@@ -215,8 +213,8 @@ extern char freedv_tx_text_data[64];
 extern int smeter;
 extern int alc;
 
-extern int local_audio;
-extern int local_microphone;
+//extern int local_audio;
+//extern int local_microphone;
 
 extern int eer_pwm_min;
 extern int eer_pwm_max;
@@ -235,6 +233,7 @@ extern int rx_equalizer[4];
 extern int deviation;
 extern int pre_emphasize;
 
+extern int vox_setting;
 extern int vox_enabled;
 extern double vox_threshold;
 extern double vox_gain;
@@ -245,9 +244,11 @@ extern int diversity_enabled;
 extern double i_rotate[2];
 extern double q_rotate[2];
 
+extern void reconfigure_radio();
+extern void start_radio();
 extern void init_radio();
-extern void setSampleRate(int rate);
-extern int getSampleRate();
+extern void radio_change_receivers(int r);
+extern void radio_change_sample_rate(int rate);
 extern void setMox(int state);
 extern int getMox();
 extern void setTune(int state);
diff --git a/radio_menu.c b/radio_menu.c
new file mode 100644 (file)
index 0000000..8e62c11
--- /dev/null
@@ -0,0 +1,407 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#include <gtk/gtk.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "new_menu.h"
+#include "radio_menu.h"
+#include "band.h"
+#include "filter.h"
+#include "radio.h"
+#include "receiver.h"
+
+static GtkWidget *parent_window=NULL;
+
+static GtkWidget *menu_b=NULL;
+
+static GtkWidget *dialog=NULL;
+
+static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  if(dialog!=NULL) {
+    gtk_widget_destroy(dialog);
+    dialog=NULL;
+    sub_menu=NULL;
+  }
+  return TRUE;
+}
+
+static void vfo_divisor_value_changed_cb(GtkWidget *widget, gpointer data) {
+  vfo_encoder_divisor=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
+}
+
+/*
+static void toolbar_dialog_buttons_cb(GtkWidget *widget, gpointer data) {
+  toolbar_dialog_buttons=toolbar_dialog_buttons==1?0:1;
+  update_toolbar_labels();
+}
+*/
+
+static void ptt_cb(GtkWidget *widget, gpointer data) {
+  mic_ptt_enabled=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+}
+
+static void ptt_ring_cb(GtkWidget *widget, gpointer data) {
+  if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
+    mic_ptt_tip_bias_ring=0;
+  }
+}
+
+static void ptt_tip_cb(GtkWidget *widget, gpointer data) {
+  if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
+    mic_ptt_tip_bias_ring=1;
+  }
+}
+
+static void bias_cb(GtkWidget *widget, gpointer data) {
+  mic_bias_enabled=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+}
+
+static void apollo_cb(GtkWidget *widget, gpointer data);
+
+static void alex_cb(GtkWidget *widget, gpointer data) {
+  if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
+    if(filter_board==ALEX) {
+      filter_board=NONE;
+    } else if(filter_board==NONE) {
+      filter_board=ALEX;
+    } else if(filter_board==APOLLO) {
+      GtkWidget *w=(GtkWidget *)data;
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), FALSE);
+      filter_board=ALEX;
+    }
+
+    if(protocol==NEW_PROTOCOL) {
+      filter_board_changed();
+    }
+
+    if(filter_board==ALEX) {
+      BAND *band=band_get_current_band();
+      BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
+      setFrequency(entry->frequency);
+      //setMode(entry->mode);
+      set_mode(active_receiver,entry->mode);
+      FILTER* band_filters=filters[entry->mode];
+      FILTER* band_filter=&band_filters[entry->filter];
+      //setFilter(band_filter->low,band_filter->high);
+      set_filter(active_receiver,band_filter->low,band_filter->high);
+      if(active_receiver->id==0) {
+        set_alex_rx_antenna(band->alexRxAntenna);
+        set_alex_tx_antenna(band->alexTxAntenna);
+        set_alex_attenuation(band->alexAttenuation);
+      }
+    }
+  }
+}
+
+static void apollo_cb(GtkWidget *widget, gpointer data) {
+  if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
+    if(filter_board==APOLLO) {
+      filter_board=NONE;
+    } else if(filter_board==NONE) {
+      filter_board=APOLLO;
+    } else if(filter_board==ALEX) {
+      GtkWidget *w=(GtkWidget *)data;
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), FALSE);
+      filter_board=APOLLO;
+    }
+    if(protocol==NEW_PROTOCOL) {
+      filter_board_changed();
+    }
+
+    if(filter_board==APOLLO) {
+      BAND *band=band_get_current_band();
+      BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
+      setFrequency(entry->frequency);
+      //setMode(entry->mode);
+      set_mode(active_receiver,entry->mode);
+      FILTER* band_filters=filters[entry->mode];
+      FILTER* band_filter=&band_filters[entry->filter];
+      //setFilter(band_filter->low,band_filter->high);
+      set_filter(active_receiver,band_filter->low,band_filter->high);
+    }
+  }
+}
+
+static void sample_rate_cb(GtkWidget *widget, gpointer data) {
+  radio_change_sample_rate((int)data);
+}
+
+static void receivers_cb(GtkWidget *widget, gpointer data) {
+  radio_change_receivers((int)data);
+}
+
+static void rit_cb(GtkWidget *widget,gpointer data) {
+  rit_increment=(int)data;
+}
+
+static void ck10mhz_cb(GtkWidget *widget, gpointer data) {
+  atlas_clock_source_10mhz = (int)data;
+}
+
+static void ck128mhz_cb(GtkWidget *widget, gpointer data) {
+  atlas_clock_source_128mhz=atlas_clock_source_128mhz==1?0:1;
+}
+
+static void micsource_cb(GtkWidget *widget, gpointer data) {
+  atlas_mic_source=atlas_mic_source==1?0:1;
+}
+
+static void penelopetx_cb(GtkWidget *widget, gpointer data) {
+  atlas_penelope=atlas_penelope==1?0:1;
+}
+
+void radio_menu(GtkWidget *parent) {
+  parent_window=parent;
+
+  dialog=gtk_dialog_new();
+  gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
+  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+
+  GdkRGBA color;
+  color.red = 1.0;
+  color.green = 1.0;
+  color.blue = 1.0;
+  color.alpha = 1.0;
+  gtk_widget_override_background_color(dialog,GTK_STATE_FLAG_NORMAL,&color);
+
+  GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+
+  GtkWidget *grid=gtk_grid_new();
+  gtk_grid_set_column_spacing (GTK_GRID(grid),10);
+  //gtk_grid_set_row_spacing (GTK_GRID(grid),10);
+  //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
+  //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+
+  GtkWidget *close_b=gtk_button_new_with_label("Close");
+  g_signal_connect (close_b, "button_press_event", G_CALLBACK(close_cb), NULL);
+  gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
+
+  int x=0;
+
+  GtkWidget *receivers_label=gtk_label_new("Receivers: ");
+  gtk_grid_attach(GTK_GRID(grid),receivers_label,x,1,1,1);
+  
+  GtkWidget *receivers_1=gtk_radio_button_new_with_label(NULL,"1");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (receivers_1), receivers==1);
+  gtk_grid_attach(GTK_GRID(grid),receivers_1,x,2,1,1);
+  g_signal_connect(receivers_1,"pressed",G_CALLBACK(receivers_cb),(gpointer *)1);
+
+  GtkWidget *receivers_2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(receivers_1),"2");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (receivers_2), receivers==2);
+  gtk_grid_attach(GTK_GRID(grid),receivers_2,x,3,1,1);
+  g_signal_connect(receivers_2,"pressed",G_CALLBACK(receivers_cb),(gpointer *)2);
+
+  x++;
+
+  switch(protocol) {
+    case ORIGINAL_PROTOCOL:
+      {
+      GtkWidget *sample_rate_label=gtk_label_new("Sample Rate:");
+      gtk_grid_attach(GTK_GRID(grid),sample_rate_label,x,1,1,1);
+
+      GtkWidget *sample_rate_48=gtk_radio_button_new_with_label(NULL,"48000");
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_48), active_receiver->sample_rate==48000);
+      gtk_grid_attach(GTK_GRID(grid),sample_rate_48,x,2,1,1);
+      g_signal_connect(sample_rate_48,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)48000);
+
+      GtkWidget *sample_rate_96=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_48),"96000");
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_96), active_receiver->sample_rate==96000);
+      gtk_grid_attach(GTK_GRID(grid),sample_rate_96,x,3,1,1);
+      g_signal_connect(sample_rate_96,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)96000);
+
+      GtkWidget *sample_rate_192=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_96),"192000");
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_192), active_receiver->sample_rate==192000);
+      gtk_grid_attach(GTK_GRID(grid),sample_rate_192,x,4,1,1);
+      g_signal_connect(sample_rate_192,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)192000);
+
+      GtkWidget *sample_rate_384=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_192),"384000");
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_384), active_receiver->sample_rate==384000);
+      gtk_grid_attach(GTK_GRID(grid),sample_rate_384,x,5,1,1);
+      g_signal_connect(sample_rate_384,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)384000);
+
+      if(protocol==NEW_PROTOCOL) {
+        GtkWidget *sample_rate_768=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_384),"768000");
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_768), active_receiver->sample_rate==768000);
+        gtk_grid_attach(GTK_GRID(grid),sample_rate_768,x,6,1,1);
+        g_signal_connect(sample_rate_768,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)768000);
+  
+        GtkWidget *sample_rate_1536=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_768),"1536000");
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_1536), active_receiver->sample_rate==1536000);
+          gtk_grid_attach(GTK_GRID(grid),sample_rate_1536,x,7,1,1);
+        g_signal_connect(sample_rate_1536,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)1536000);
+  
+  #ifdef GPIO
+        gtk_widget_set_sensitive(sample_rate_768,FALSE);
+        gtk_widget_set_sensitive(sample_rate_1536,FALSE);
+  #endif
+      }
+      x++;
+      }
+      break;
+  
+#ifdef LIMESDR
+    case LIMESDR_PROTOCOL:
+      {
+      GtkWidget *sample_rate_label=gtk_label_new("Sample Rate:");
+      gtk_grid_attach(GTK_GRID(grid),sample_rate_label,x,1,1,1);
+
+      GtkWidget *sample_rate_1M=gtk_radio_button_new_with_label(NULL,"1000000");
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_1M), active_receiver->sample_rate==1000000);
+      gtk_grid_attach(GTK_GRID(grid),sample_rate_1M,x,2,1,1);
+      g_signal_connect(sample_rate_1M,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)1000000);
+  
+      GtkWidget *sample_rate_2M=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_1M),"2000000");
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_2M), active_receiver->sample_rate==2000000);
+      gtk_grid_attach(GTK_GRID(grid),sample_rate_2M,x,3,1,1);
+      g_signal_connect(sample_rate_2M,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)2000000);
+      x++;
+      }
+      break;
+#endif
+     
+
+  }
+
+
+  if(protocol==ORIGINAL_PROTOCOL || protocol==NEW_PROTOCOL) {
+
+    if((protocol==NEW_PROTOCOL && device==NEW_DEVICE_ORION) ||
+       (protocol==NEW_PROTOCOL && device==NEW_DEVICE_ORION2) ||
+       (protocol==ORIGINAL_PROTOCOL && device==DEVICE_ORION) ||
+       (protocol==ORIGINAL_PROTOCOL && device==DEVICE_ORION2)) {
+
+      GtkWidget *ptt_ring_b=gtk_radio_button_new_with_label(NULL,"PTT On Ring, Mic and Bias on Tip");
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptt_ring_b), mic_ptt_tip_bias_ring==0);
+      gtk_grid_attach(GTK_GRID(grid),ptt_ring_b,x,1,1,1);
+      g_signal_connect(ptt_ring_b,"toggled",G_CALLBACK(ptt_ring_cb),NULL);
+
+      GtkWidget *ptt_tip_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ptt_ring_b),"PTT On Tip, Mic and Bias on Ring");
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptt_tip_b), mic_ptt_tip_bias_ring==1);
+      gtk_grid_attach(GTK_GRID(grid),ptt_tip_b,x,2,1,1);
+      g_signal_connect(ptt_tip_b,"toggled",G_CALLBACK(ptt_tip_cb),NULL);
+
+      GtkWidget *ptt_b=gtk_check_button_new_with_label("PTT Enabled");
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptt_b), mic_ptt_enabled);
+      gtk_grid_attach(GTK_GRID(grid),ptt_b,x,3,1,1);
+      g_signal_connect(ptt_b,"toggled",G_CALLBACK(ptt_cb),NULL);
+
+      GtkWidget *bias_b=gtk_check_button_new_with_label("BIAS Enabled");
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bias_b), mic_bias_enabled);
+      gtk_grid_attach(GTK_GRID(grid),bias_b,x,4,1,1);
+      g_signal_connect(bias_b,"toggled",G_CALLBACK(bias_cb),NULL);
+
+      x++;
+    }
+
+    GtkWidget *alex_b=gtk_check_button_new_with_label("ALEX");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (alex_b), filter_board==ALEX);
+    gtk_grid_attach(GTK_GRID(grid),alex_b,x,1,1,1);
+
+    GtkWidget *apollo_b=gtk_check_button_new_with_label("APOLLO");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (apollo_b), filter_board==APOLLO);
+    gtk_grid_attach(GTK_GRID(grid),apollo_b,x,2,1,1);
+
+    g_signal_connect(alex_b,"toggled",G_CALLBACK(alex_cb),apollo_b);
+    g_signal_connect(apollo_b,"toggled",G_CALLBACK(apollo_cb),alex_b);
+
+    x++;
+  }
+
+
+  GtkWidget *rit_label=gtk_label_new("RIT step: ");
+  gtk_grid_attach(GTK_GRID(grid),rit_label,x,1,1,1);
+
+  GtkWidget *rit_1=gtk_radio_button_new_with_label(NULL,"1 Hz");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rit_1), rit_increment==1);
+  gtk_grid_attach(GTK_GRID(grid),rit_1,x,2,1,1);
+  g_signal_connect(rit_1,"pressed",G_CALLBACK(rit_cb),(gpointer *)1);
+
+  GtkWidget *rit_10=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(rit_1),"10");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rit_10), rit_increment==10);
+  gtk_grid_attach(GTK_GRID(grid),rit_10,x,3,1,1);
+  g_signal_connect(rit_10,"pressed",G_CALLBACK(rit_cb),(gpointer *)10);
+
+  GtkWidget *rit_100=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(rit_10),"100");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rit_100), rit_increment==100);
+  gtk_grid_attach(GTK_GRID(grid),rit_100,x,4,1,1);
+  g_signal_connect(rit_100,"pressed",G_CALLBACK(rit_cb),(gpointer *)100);
+
+  x++;
+
+  GtkWidget *vfo_divisor_label=gtk_label_new("VFO Encoder Divisor: ");
+  gtk_grid_attach(GTK_GRID(grid),vfo_divisor_label,x,1,1,1);
+
+  GtkWidget *vfo_divisor=gtk_spin_button_new_with_range(1.0,60.0,1.0);
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON(vfo_divisor),(double)vfo_encoder_divisor);
+  gtk_grid_attach(GTK_GRID(grid),vfo_divisor,x,2,1,1);
+  g_signal_connect(vfo_divisor,"value_changed",G_CALLBACK(vfo_divisor_value_changed_cb),NULL);
+
+  x++;
+
+#ifdef USBOZY
+  if (protocol==ORIGINAL_PROTOCOL && (device == DEVICE_OZY) || (device == DEVICE_METIS))
+#else
+  if (protocol==ORIGINAL_PROTOCOL && radio->device == DEVICE_METIS)
+#endif
+  {
+    GtkWidget *atlas_label=gtk_label_new("Atlas bus: ");
+    gtk_grid_attach(GTK_GRID(grid),atlas_label,x,1,1,1);
+
+    GtkWidget *ck10mhz_1=gtk_radio_button_new_with_label(NULL,"10MHz clock=Atlas");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ck10mhz_1), atlas_clock_source_10mhz==0);
+    gtk_grid_attach(GTK_GRID(grid),ck10mhz_1,x,2,1,1);
+    g_signal_connect(ck10mhz_1,"toggled",G_CALLBACK(ck10mhz_cb),(gpointer *)0);
+
+    GtkWidget *ck10mhz_2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ck10mhz_1),"10MHz clock=Penelope");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ck10mhz_2), atlas_clock_source_10mhz==1);
+    gtk_grid_attach(GTK_GRID(grid),ck10mhz_2,x,3,1,1);
+    g_signal_connect(ck10mhz_2,"toggled",G_CALLBACK(ck10mhz_cb),(gpointer *)1);
+
+    GtkWidget *ck10mhz_3=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ck10mhz_2),"10MHz clock=Mercury");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ck10mhz_3), atlas_clock_source_10mhz==2);
+    gtk_grid_attach(GTK_GRID(grid),ck10mhz_3,x,4,1,1);
+    g_signal_connect(ck10mhz_3,"toggled",G_CALLBACK(ck10mhz_cb),(gpointer *)2);
+
+    GtkWidget *ck128_b=gtk_check_button_new_with_label("122.88MHz ck=Mercury");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ck128_b), atlas_clock_source_128mhz);
+    gtk_grid_attach(GTK_GRID(grid),ck128_b,x,5,1,1);
+    g_signal_connect(ck128_b,"toggled",G_CALLBACK(ck128mhz_cb),NULL);
+
+    GtkWidget *mic_src_b=gtk_check_button_new_with_label("Mic src=Penelope");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mic_src_b), atlas_mic_source);
+    gtk_grid_attach(GTK_GRID(grid),mic_src_b,x,6,1,1);
+    g_signal_connect(mic_src_b,"toggled",G_CALLBACK(micsource_cb),NULL);
+
+    GtkWidget *pene_tx_b=gtk_check_button_new_with_label("Penelope TX");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pene_tx_b), atlas_penelope);
+    gtk_grid_attach(GTK_GRID(grid),pene_tx_b,x,7,1,1);
+    g_signal_connect(pene_tx_b,"toggled",G_CALLBACK(penelopetx_cb),NULL);
+  }
+
+  gtk_container_add(GTK_CONTAINER(content),grid);
+
+  sub_menu=dialog;
+
+  gtk_widget_show_all(dialog);
+
+}
+
diff --git a/radio_menu.h b/radio_menu.h
new file mode 100644 (file)
index 0000000..9cd8b93
--- /dev/null
@@ -0,0 +1,20 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+extern void general_menu(GtkWidget *parent);
diff --git a/receiver.c b/receiver.c
new file mode 100644 (file)
index 0000000..cbec540
--- /dev/null
@@ -0,0 +1,1029 @@
+/* Copyright (C)
+* 2017 - John Melton, G0ORX/N6LYT
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#include <gtk/gtk.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <wdsp.h>
+
+#include "agc.h"
+#include "band.h"
+#include "bandstack.h"
+#include "discovered.h"
+#include "filter.h"
+#include "main.h"
+#include "meter.h"
+#include "mode.h"
+#include "new_protocol.h"
+#include "old_protocol.h"
+#include "property.h"
+#include "radio.h"
+#include "receiver.h"
+#include "vfo.h"
+#include "meter.h"
+#include "rx_panadapter.h"
+#include "sliders.h"
+#include "waterfall.h"
+#ifdef FREEDV
+#include "freedv.h"
+#endif
+
+
+#define min(x,y) (x<y?x:y)
+#define max(x,y) (x<y?y:x)
+
+#ifdef FREEDV
+static int freedv_samples=0;
+static int freedv_resample=6;  // convert from 48000 to 8000
+#endif
+#ifdef PSK
+static int psk_samples=0;
+static int psk_resample=6;  // convert from 48000 to 8000
+#endif
+
+static gint last_x;
+static gboolean has_moved=FALSE;
+static gboolean pressed=FALSE;
+static gboolean making_active=FALSE;
+
+gboolean receiver_button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  RECEIVER *rx=(RECEIVER *)data;
+  if(rx==active_receiver) {
+    int x=(int)event->x;
+    if (event->button == 1) {
+      last_x=(int)event->x;
+      has_moved=FALSE;
+      pressed=TRUE;
+    }
+  } else {
+    making_active=TRUE;
+  }
+  return TRUE;
+}
+
+gboolean receiver_button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  RECEIVER *rx=(RECEIVER *)data;
+  if(making_active) {
+    active_receiver=rx;
+    making_active=FALSE;
+    g_idle_add(vfo_update,NULL);
+    g_idle_add(active_receiver_changed,NULL);
+  } else {
+    int display_width=gtk_widget_get_allocated_width (rx->panadapter);
+    int display_height=gtk_widget_get_allocated_height (rx->panadapter);
+    if(pressed) {
+      int x=(int)event->x;
+      if (event->button == 1) {
+        if(has_moved) {
+          // drag
+          vfo_move((long long)((float)(x-last_x)*rx->hz_per_pixel));
+        } else {
+          // move to this frequency
+          vfo_move_to((long long)((float)(x-(display_width/2))*rx->hz_per_pixel));
+        }
+        last_x=x;
+        pressed=FALSE;
+      }
+    }
+  }
+  return TRUE;
+}
+
+gboolean receiver_motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data) {
+  int x, y;
+  GdkModifierType state;
+  RECEIVER *rx=(RECEIVER *)data;
+  if(!making_active) {
+    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*rx->hz_per_pixel));
+      last_x=x;
+      has_moved=TRUE;
+    }
+  }
+
+  return TRUE;
+}
+
+gboolean receiver_scroll_event(GtkWidget *widget, GdkEventScroll *event, gpointer data) {
+  if(event->direction==GDK_SCROLL_UP) {
+    if(vfo[active_receiver->id].ctun) {
+      vfo_move(-step);
+    } else {
+      vfo_move(step);
+    }
+  } else {
+    if(vfo[active_receiver->id].ctun) {
+      vfo_move(step);
+    } else {
+      vfo_move(-step);
+    }
+  }
+  return TRUE;
+}
+
+void receiver_save_state(RECEIVER *rx) {
+  char name[128];
+  char value[128];
+
+  sprintf(name,"receiver.%d.sample_rate",rx->id);
+  sprintf(value,"%d",rx->sample_rate);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.adc",rx->id);
+  sprintf(value,"%d",rx->adc);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.filter_low",rx->id);
+  sprintf(value,"%d",rx->filter_low);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.filter_high",rx->id);
+  sprintf(value,"%d",rx->filter_high);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.fps",rx->id);
+  sprintf(value,"%d",rx->fps);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.panadapter_low",rx->id);
+  sprintf(value,"%d",rx->panadapter_low);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.panadapter_high",rx->id);
+  sprintf(value,"%d",rx->panadapter_high);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.display_waterfall",rx->id);
+  sprintf(value,"%d",rx->display_waterfall);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.waterfall_low",rx->id);
+  sprintf(value,"%d",rx->waterfall_low);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.waterfall_high",rx->id);
+  sprintf(value,"%d",rx->waterfall_high);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.waterfall_automatic",rx->id);
+  sprintf(value,"%d",rx->waterfall_automatic);
+  setProperty(name,value);
+  
+  sprintf(name,"receiver.%d.alex_antenna",rx->id);
+  sprintf(value,"%d",rx->alex_antenna);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.alex_attenuation",rx->id);
+  sprintf(value,"%d",rx->alex_attenuation);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.volume",rx->id);
+  sprintf(value,"%f",rx->volume);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.agc",rx->id);
+  sprintf(value,"%d",rx->agc);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.agc_gain",rx->id);
+  sprintf(value,"%f",rx->agc_gain);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.agc_slope",rx->id);
+  sprintf(value,"%f",rx->agc_slope);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.agc_hang_threshold",rx->id);
+  sprintf(value,"%f",rx->agc_hang_threshold);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.attenuation",rx->id);
+  sprintf(value,"%d",rx->attenuation);
+  setProperty(name,value);
+
+  sprintf(name,"receiver.%d.dither",rx->id);
+  sprintf(value,"%d",rx->dither);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.random",rx->id);
+  sprintf(value,"%d",rx->random);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.preamp",rx->id);
+  sprintf(value,"%d",rx->preamp);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.nr",rx->id);
+  sprintf(value,"%d",rx->nr);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.nr2",rx->id);
+  sprintf(value,"%d",rx->nr2);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.anf",rx->id);
+  sprintf(value,"%d",rx->anf);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.snb",rx->id);
+  sprintf(value,"%d",rx->snb);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.nr_agc",rx->id);
+  sprintf(value,"%d",rx->nr_agc);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.nr2_gain_method",rx->id);
+  sprintf(value,"%d",rx->nr2_gain_method);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.nr2_npe_method",rx->id);
+  sprintf(value,"%d",rx->nr2_npe_method);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.nr2_ae",rx->id);
+  sprintf(value,"%d",rx->nr2_ae);
+  setProperty(name,value);
+
+  sprintf(name,"receiver.%d.audio_channel",rx->id);
+  sprintf(value,"%d",rx->audio_channel);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.local_audio",rx->id);
+  sprintf(value,"%d",rx->local_audio);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.audio_device",rx->id);
+  sprintf(value,"%d",rx->audio_device);
+  setProperty(name,value);
+
+}
+
+void receiver_restore_state(RECEIVER *rx) {
+  char name[128];
+  char *value;
+
+fprintf(stderr,"receiver_restore_state: id=%d\n",rx->id);
+  sprintf(name,"receiver.%d.sample_rate",rx->id);
+  value=getProperty(name);
+  if(value) rx->sample_rate=atoi(value);
+  sprintf(name,"receiver.%d.adc",rx->id);
+  value=getProperty(name);
+  if(value) rx->adc=atoi(value);
+  sprintf(name,"receiver.%d.filter_low",rx->id);
+  value=getProperty(name);
+  if(value) rx->filter_low=atoi(value);
+  sprintf(name,"receiver.%d.filter_high",rx->id);
+  value=getProperty(name);
+  if(value) rx->filter_high=atoi(value);
+  sprintf(name,"receiver.%d.fps",rx->id);
+  value=getProperty(name);
+  if(value) rx->fps=atoi(value);
+/*
+  sprintf(name,"receiver.%d.frequency",rx->id);
+  value=getProperty(name);
+  if(value) rx->frequency=atoll(value);
+  sprintf(name,"receiver.%d.display_frequency",rx->id);
+  value=getProperty(name);
+  if(value) rx->display_frequency=atoll(value);
+  sprintf(name,"receiver.%d.dds_frequency",rx->id);
+  value=getProperty(name);
+  if(value) rx->dds_frequency=atoll(value);
+  sprintf(name,"receiver.%d.dds_offset",rx->id);
+  value=getProperty(name);
+  if(value) rx->dds_offset=atoll(value);
+  sprintf(name,"receiver.%d.rit",rx->id);
+  value=getProperty(name);
+  if(value) rx->rit=atoi(value);
+*/
+  sprintf(name,"receiver.%d.panadapter_low",rx->id);
+  value=getProperty(name);
+  if(value) rx->panadapter_low=atoi(value);
+  sprintf(name,"receiver.%d.panadapter_high",rx->id);
+  value=getProperty(name);
+  if(value) rx->panadapter_high=atoi(value);
+  sprintf(name,"receiver.%d.display_waterfall",rx->id);
+  value=getProperty(name);
+  if(value) rx->display_waterfall=atoi(value);
+  sprintf(name,"receiver.%d.waterfall_low",rx->id);
+  value=getProperty(name);
+  if(value) rx->waterfall_low=atoi(value);
+  sprintf(name,"receiver.%d.waterfall_high",rx->id);
+  value=getProperty(name);
+  if(value) rx->waterfall_high=atoi(value);
+  sprintf(name,"receiver.%d.waterfall_automatic",rx->id);
+  value=getProperty(name);
+  if(value) rx->waterfall_automatic=atoi(value);
+
+  sprintf(name,"receiver.%d.alex_antenna",rx->id);
+  value=getProperty(name);
+  if(value) rx->alex_antenna=atoi(value);
+  sprintf(name,"receiver.%d.alex_attenuation",rx->id);
+  value=getProperty(name);
+  if(value) rx->alex_attenuation=atoi(value);
+  sprintf(name,"receiver.%d.volume",rx->id);
+  value=getProperty(name);
+  if(value) rx->volume=atof(value);
+  sprintf(name,"receiver.%d.agc",rx->id);
+  value=getProperty(name);
+  if(value) rx->agc=atoi(value);
+  sprintf(name,"receiver.%d.agc_gain",rx->id);
+  value=getProperty(name);
+  if(value) rx->agc_gain=atof(value);
+  sprintf(name,"receiver.%d.agc_slope",rx->id);
+  value=getProperty(name);
+  if(value) rx->agc_slope=atof(value);
+  sprintf(name,"receiver.%d.hang_threshold",rx->id);
+  value=getProperty(name);
+  if(value) rx->agc_hang_threshold=atof(value);
+  sprintf(name,"receiver.%d.attenuation",rx->id);
+  value=getProperty(name);
+  if(value) rx->attenuation=atoi(value);
+
+  sprintf(name,"receiver.%d.dither",rx->id);
+  value=getProperty(name);
+  if(value) rx->dither=atoi(value);
+  sprintf(name,"receiver.%d.random",rx->id);
+  value=getProperty(name);
+  if(value) rx->random=atoi(value);
+  sprintf(name,"receiver.%d.preamp",rx->id);
+  value=getProperty(name);
+  if(value) rx->preamp=atoi(value);
+  sprintf(name,"receiver.%d.nr",rx->id);
+  value=getProperty(name);
+  if(value) rx->nr=atoi(value);
+  sprintf(name,"receiver.%d.nr2",rx->id);
+  value=getProperty(name);
+  if(value) rx->nr2=atoi(value);
+  sprintf(name,"receiver.%d.anf",rx->id);
+  value=getProperty(name);
+  if(value) rx->anf=atoi(value);
+  sprintf(name,"receiver.%d.snb",rx->id);
+  value=getProperty(name);
+  if(value) rx->snb=atoi(value);
+  sprintf(name,"receiver.%d.nr_agc",rx->id);
+  value=getProperty(name);
+  if(value) rx->nr_agc=atoi(value);
+  sprintf(name,"receiver.%d.nr2_gain_method",rx->id);
+  value=getProperty(name);
+  if(value) rx->nr2_gain_method=atoi(value);
+  sprintf(name,"receiver.%d.nr2_npe_method",rx->id);
+  value=getProperty(name);
+  if(value) rx->nr2_npe_method=atoi(value);
+  sprintf(name,"receiver.%d.ae",rx->id);
+  value=getProperty(name);
+  if(value) rx->nr2_ae=atoi(value);
+
+  sprintf(name,"receiver.%d.audio_channel",rx->id);
+  value=getProperty(name);
+  if(value) rx->audio_channel=atoi(value);
+  sprintf(name,"receiver.%d.local_audio",rx->id);
+  value=getProperty(name);
+  if(value) rx->local_audio=atoi(value);
+  sprintf(name,"receiver.%d.audio_device",rx->id);
+  value=getProperty(name);
+  if(value) rx->audio_device=atoi(value);
+}
+
+void reconfigure_receiver(RECEIVER *rx,int height) {
+  int y=0;
+
+  rx->height=height;
+
+  if(rx->display_panadapter) {
+    int height=rx->height;
+    if(rx->display_waterfall) {
+      height=height/2;
+    }
+    if(rx->panadapter==NULL) {
+fprintf(stderr,"reconfigure_receiver: panadapter_init: width:%d height:%d\n",rx->width,height);
+      rx_panadapter_init(rx, rx->width,height);
+      gtk_fixed_put(GTK_FIXED(rx->panel),rx->panadapter,0,y);
+    } else {
+       // set the size
+fprintf(stderr,"reconfigure_receiver: panadapter set_size_request: width:%d height:%d\n",rx->width,height);
+      gtk_widget_set_size_request(rx->panadapter, rx->width, height);
+      // move the current one
+      gtk_fixed_move(GTK_FIXED(rx->panel),rx->panadapter,0,y);
+    }
+    y+=height;
+  } else {
+    if(rx->panadapter!=NULL) {
+      gtk_container_remove(GTK_CONTAINER(rx->panel),rx->panadapter);
+      gtk_widget_destroy(rx->panadapter);
+      rx->panadapter=NULL;
+    }
+  }
+
+  if(rx->display_waterfall) {
+    int height=rx->height;
+    if(rx->display_panadapter) {
+      height=height/2;
+    }
+    if(rx->waterfall==NULL) {
+fprintf(stderr,"reconfigure_receiver: waterfall_init: width:%d height:%d\n",rx->width,height);
+      waterfall_init(rx,rx->width,height);
+      gtk_fixed_put(GTK_FIXED(rx->panel),rx->waterfall,0,y);
+    } else {
+      // set the size
+fprintf(stderr,"reconfigure_receiver: waterfall set_size_request: width:%d height:%d\n",rx->width,height);
+      gtk_widget_set_size_request(rx->waterfall, rx->width, height);
+      // move the current one
+      gtk_fixed_move(GTK_FIXED(rx->panel),rx->waterfall,0,y);
+    }
+  } else {
+    if(rx->waterfall!=NULL) {
+      gtk_container_remove(GTK_CONTAINER(rx->panel),rx->waterfall);
+      gtk_widget_destroy(rx->waterfall);
+      rx->waterfall=NULL;
+    }
+  }
+
+  gtk_widget_show_all(rx->panel);
+}
+
+static gint update_display(gpointer data) {
+  RECEIVER *rx=(RECEIVER *)data;
+  int rc;
+
+  if(rx->displaying) {
+    GetPixels(rx->id,0,rx->pixel_samples,&rc);
+    if(rc) {
+      if(rx->display_panadapter) {
+        switch(vfo[rx->id].mode) {
+#ifdef PSK
+          case modePSK:
+            psk_waterfall_update(rx);
+            break;
+#endif
+          default:
+            rx_panadapter_update(rx);
+            break;
+        }
+      }
+      if(rx->display_waterfall) {
+        waterfall_update(rx);
+      }
+    }
+
+    if(active_receiver==rx) {
+      double m=GetRXAMeter(rx->id,smeter);
+      meter_update(SMETER,m,0.0,0.0,0.0);
+    }
+    return TRUE;
+  }
+  return FALSE;
+}
+
+void set_displaying(RECEIVER *rx,int state) {
+  rx->displaying=state;
+  if(state) {
+    rx->update_timer_id=gdk_threads_add_timeout_full(G_PRIORITY_HIGH_IDLE,1000/rx->fps, update_display, rx, NULL);
+  }
+}
+
+void set_mode(RECEIVER *rx,int m) {
+  int local_mode=m;
+#ifdef FREEDV
+  if(vfo[rx->d].mode!=modeFREEDV && m==modeFREEDV) {
+    local_mode=modeUSB;
+    init_freedv();
+  } else if(vfo[rx->id].mode==modeFREEDV && m!=modeFREEDV) {
+    close_freedv();
+  }
+#endif
+#ifdef PSK
+  if(vfo[rx->id].mode!=modePSK && m==modePSK) {
+    local_mode=modeUSB;
+    //init_psk();
+    show_psk();
+  } else if(vfo[rx->id].mode==modePSK && m!=modePSK) {
+    //close_psk();
+    show_waterfall();
+  }
+#endif
+  vfo[rx->id].mode=m;
+  SetRXAMode(rx->id, vfo[rx->id].mode);
+}
+
+void set_filter(RECEIVER *rx,int low,int high) {
+  if(vfo[rx->id].mode==modeCWL) {
+    rx->filter_low=-cw_keyer_sidetone_frequency-low;
+    rx->filter_high=-cw_keyer_sidetone_frequency+high;
+  } else if(vfo[rx->id].mode==modeCWU) {
+    rx->filter_low=cw_keyer_sidetone_frequency-low;
+    rx->filter_high=cw_keyer_sidetone_frequency+high;
+  } else {
+    rx->filter_low=low;
+    rx->filter_high=high;
+  }
+
+  RXASetPassband(rx->id,(double)rx->filter_low,(double)rx->filter_high);
+}
+
+void set_deviation(RECEIVER *rx,double deviation) {
+  SetRXAFMDeviation(rx->id, deviation);
+}
+
+void set_agc(RECEIVER *rx, int agc) {
+  SetRXAAGCMode(rx->id, agc);
+  //SetRXAAGCThresh(rx->id, agc_thresh_point, 4096.0, rx->sample_rate);
+  SetRXAAGCSlope(rx->id,rx->agc_slope);
+  SetRXAAGCTop(rx->id,rx->agc_gain);
+  switch(agc) {
+    case AGC_OFF:
+      break;
+    case AGC_LONG:
+      SetRXAAGCAttack(rx->id,2);
+      SetRXAAGCHang(rx->id,2000);
+      SetRXAAGCDecay(rx->id,2000);
+      SetRXAAGCHangThreshold(rx->id,(int)rx->agc_hang_threshold);
+      break;
+    case AGC_SLOW:
+      SetRXAAGCAttack(rx->id,2);
+      SetRXAAGCHang(rx->id,1000);
+      SetRXAAGCDecay(rx->id,500);
+      SetRXAAGCHangThreshold(rx->id,(int)rx->agc_hang_threshold);
+      break;
+    case AGC_MEDIUM:
+      SetRXAAGCAttack(rx->id,2);
+      SetRXAAGCHang(rx->id,0);
+      SetRXAAGCDecay(rx->id,250);
+      SetRXAAGCHangThreshold(rx->id,100);
+      break;
+    case AGC_FAST:
+      SetRXAAGCAttack(rx->id,2);
+      SetRXAAGCHang(rx->id,0);
+      SetRXAAGCDecay(rx->id,50);
+      SetRXAAGCHangThreshold(rx->id,100);
+      break;
+  }
+}
+
+void set_offset(RECEIVER *rx,long long offset) {
+fprintf(stderr,"set_offset: id=%d ofset=%lld\n",rx->id,offset);
+fprintf(stderr,"set_offset: frequency=%lld ctun_freqeuncy=%lld offset=%lld\n",vfo[rx->id].frequency,vfo[rx->id].ctun_frequency,vfo[rx->id].offset);
+  if(offset==0) {
+    SetRXAShiftFreq(rx->id, (double)offset);
+    RXANBPSetShiftFrequency(rx->id, (double)offset);
+    SetRXAShiftRun(rx->id, 0);
+  } else {
+    SetRXAShiftFreq(rx->id, (double)offset);
+    RXANBPSetShiftFrequency(rx->id, (double)offset);
+    SetRXAShiftRun(rx->id, 1);
+  }
+}
+
+static void init_analyzer(RECEIVER *rx) {
+    int flp[] = {0};
+    double keep_time = 0.1;
+    int n_pixout=1;
+    int spur_elimination_ffts = 1;
+    int data_type = 1;
+    int fft_size = 8192;
+    int window_type = 4;
+    double kaiser_pi = 14.0;
+    int overlap = 2048;
+    int clip = 0;
+    int span_clip_l = 0;
+    int span_clip_h = 0;
+    int pixels=rx->pixels;
+    int stitches = 1;
+    int avm = 0;
+    double tau = 0.001 * 120.0;
+    int calibration_data_set = 0;
+    double span_min_freq = 0.0;
+    double span_max_freq = 0.0;
+
+    int max_w = fft_size + (int) min(keep_time * (double) rx->fps, keep_time * (double) fft_size * (double) rx->fps);
+
+    overlap = (int)max(0.0, ceil(fft_size - (double)rx->sample_rate / (double)rx->fps));
+
+    fprintf(stderr,"SetAnalyzer id=%d buffer_size=%d overlap=%d\n",rx->id,rx->buffer_size,overlap);
+
+
+    SetAnalyzer(rx->id,
+            n_pixout,
+            spur_elimination_ffts, //number of LO frequencies = number of ffts used in elimination
+            data_type, //0 for real input data (I only); 1 for complex input data (I & Q)
+            flp, //vector with one elt for each LO frequency, 1 if high-side LO, 0 otherwise
+            fft_size, //size of the fft, i.e., number of input samples
+            rx->buffer_size, //number of samples transferred for each OpenBuffer()/CloseBuffer()
+            window_type, //integer specifying which window function to use
+            kaiser_pi, //PiAlpha parameter for Kaiser window
+            overlap, //number of samples each fft (other than the first) is to re-use from the previous
+            clip, //number of fft output bins to be clipped from EACH side of each sub-span
+            span_clip_l, //number of bins to clip from low end of entire span
+            span_clip_h, //number of bins to clip from high end of entire span
+            pixels, //number of pixel values to return.  may be either <= or > number of bins
+            stitches, //number of sub-spans to concatenate to form a complete span
+            calibration_data_set, //identifier of which set of calibration data to use
+            span_min_freq, //frequency at first pixel value8192
+            span_max_freq, //frequency at last pixel value
+            max_w //max samples to hold in input ring buffers
+    );
+
+
+}
+
+static void create_visual(RECEIVER *rx) {
+  int y=0;
+
+fprintf(stderr,"receiver: create_visual: id=%d width=%d height=%d\n",rx->id, rx->width, rx->height);
+  rx->panel=gtk_fixed_new();
+  gtk_widget_set_size_request (rx->panel, rx->width, rx->height);
+
+  rx->panadapter=NULL;
+  rx->waterfall=NULL;
+
+  int height=rx->height;
+  if(rx->display_waterfall) {
+    height=height/2;
+  }
+
+fprintf(stderr,"receiver: panadapter_init: height=%d y=%d\n",height,y);
+  rx_panadapter_init(rx, rx->width,height);
+  gtk_fixed_put(GTK_FIXED(rx->panel),rx->panadapter,0,y);
+  y+=height;
+
+  if(rx->display_waterfall) {
+fprintf(stderr,"receiver: waterfall_init: height=%d y=%d\n",height,y);
+    waterfall_init(rx,rx->width,height);
+    gtk_fixed_put(GTK_FIXED(rx->panel),rx->waterfall,0,y);
+  }
+}
+
+RECEIVER *create_receiver(int id, int buffer_size, int fft_size, int pixels, int fps, int width, int height) {
+fprintf(stderr,"create_receiver: id=%d buffer_size=%d fft_size=%d pixels=%d fps=%d\n",id,buffer_size, fft_size, pixels, fps);
+  RECEIVER *rx=malloc(sizeof(RECEIVER));
+  rx->id=id;
+  switch(id) {
+    case 0:
+      rx->adc=0;
+      break;
+    default:
+      switch(protocol) {
+        case ORIGINAL_PROTOCOL:
+          switch(device) {
+            case DEVICE_METIS:
+            case DEVICE_HERMES:
+            case DEVICE_HERMES_LITE:
+              rx->adc=0;
+              break;
+            default:
+              rx->adc=1;
+              break;
+          }
+          break;
+        default:
+          switch(device) {
+            case NEW_DEVICE_ATLAS:
+            case NEW_DEVICE_HERMES:
+              rx->adc=0;
+              break;
+            default:
+              rx->adc=1;
+              break;
+          }
+          break;
+      }
+  }
+fprintf(stderr,"create_receiver: id=%d default adc=%d\n",rx->id, rx->adc);
+  rx->sample_rate=48000;
+  rx->buffer_size=buffer_size;
+  rx->fft_size=fft_size;
+  rx->pixels=pixels;
+  rx->fps=fps;
+
+  BAND *b=band_get_band(vfo[rx->id].band);
+
+//  rx->dds_offset=0;
+//  rx->rit=0;
+
+  rx->width=width;
+  rx->height=height;
+  rx->display_panadapter=1;
+  rx->display_waterfall=1;
+
+  // allocate buffers
+  rx->iq_input_buffer=malloc(sizeof(double)*2*rx->buffer_size);
+  rx->audio_buffer=malloc(AUDIO_BUFFER_SIZE);
+  rx->audio_sequence=0L;
+  rx->pixel_samples=malloc(sizeof(float)*pixels);
+
+  rx->samples=0;
+  rx->displaying=0;
+  rx->display_panadapter=1;
+  rx->display_waterfall=1;
+
+  rx->panadapter_high=-40;
+  rx->panadapter_low=-140;
+
+  rx->volume=0.2;
+  rx->attenuation=0;
+
+  rx->dither=0;
+  rx->random=0;
+  rx->preamp=0;
+
+  rx->nr=0;
+  rx->nr2=0;
+  rx->anf=0;
+  rx->snb=0;
+
+  rx->nr_agc=0;
+  rx->nr2_gain_method=2;
+  rx->nr2_npe_method=0;
+  rx->nr2_ae=1;
+  
+  rx->alex_antenna=b->alexRxAntenna;
+  rx->alex_attenuation=b->alexAttenuation;
+
+  rx->agc=AGC_MEDIUM;
+  rx->agc_gain=80.0;
+  rx->agc_slope=35.0;
+  rx->agc_hang_threshold=0.0;
+  
+  rx->playback_handle=NULL;
+  rx->local_audio=0;
+  rx->audio_channel=STEREO;
+  rx->audio_device=-1;
+
+  receiver_restore_state(rx);
+
+  int scale=rx->sample_rate/48000;
+  rx->output_samples=rx->buffer_size/scale;
+  rx->audio_output_buffer=malloc(sizeof(double)*2*rx->output_samples);
+fprintf(stderr,"create_receiver: id=%d output_samples=%d\n",rx->id,rx->output_samples);
+
+  rx->hz_per_pixel=(double)rx->sample_rate/(double)rx->width;
+  // setup wdsp for this receiver
+
+fprintf(stderr,"create_receiver: id=%d after restore adc=%d\n",rx->id, rx->adc);
+
+fprintf(stderr,"create_receiver: OpenChannel id=%d buffer_size=%d fft_size=%d sample_rate=%d\n",rx->id,rx->buffer_size, rx->fft_size, rx->sample_rate);
+  OpenChannel(rx->id,
+              rx->buffer_size,
+              rx->fft_size,
+              rx->sample_rate,
+              48000, // dsp rate
+              48000, // output rate
+              0, // receive
+              1, // run
+              0.010, 0.025, 0.0, 0.010, 0);
+
+  b=band_get_band(vfo[rx->id].band);
+  BANDSTACK *bs=b->bandstack;
+  BANDSTACK_ENTRY *entry=&bs->entry[vfo[rx->id].bandstack];
+  FILTER *band_filters=filters[vfo[rx->id].mode];
+  FILTER *band_filter=&band_filters[vfo[rx->id].filter];
+  set_filter(rx,band_filter->low,band_filter->high);
+  
+  SetRXAFMDeviation(rx->id,(double)deviation);
+
+  set_agc(rx, rx->agc);
+
+  SetRXAAMDSBMode(rx->id, 0);
+  SetRXAShiftRun(rx->id, 0);
+
+  SetRXAEMNRPosition(rx->id, rx->nr_agc);
+  SetRXAEMNRgainMethod(rx->id, rx->nr2_gain_method);
+  SetRXAEMNRnpeMethod(rx->id, rx->nr2_npe_method);
+  SetRXAEMNRRun(rx->id, rx->nr2);
+  SetRXAEMNRaeRun(rx->id, rx->nr2_ae);
+
+  SetRXAANRVals(rx->id, 64, 16, 16e-4, 10e-7); // defaults
+  SetRXAANRRun(rx->id, rx->nr);
+  SetRXAANFRun(rx->id, rx->anf);
+  SetRXASNBARun(rx->id, rx->snb);
+
+  SetRXAPanelGain1(rx->id, rx->volume);
+  SetRXAPanelBinaural(rx->id, binaural);
+  SetRXAPanelRun(rx->id, 1);
+
+  if(enable_rx_equalizer) {
+    SetRXAGrphEQ(rx->id, rx_equalizer);
+    SetRXAEQRun(rx->id, 1);
+  } else {
+    SetRXAEQRun(rx->id, 0);
+  }
+
+  // setup for diversity
+  create_divEXT(0,0,2,rx->buffer_size);
+  SetEXTDIVRotate(0, 2, &i_rotate, &q_rotate);
+  SetEXTDIVRun(0,diversity_enabled);
+  
+
+  int result;
+  XCreateAnalyzer(rx->id, &result, 262144, 1, 1, "");
+  if(result != 0) {
+    fprintf(stderr, "XCreateAnalyzer id=%d failed: %d\n", rx->id, result);
+  } else {
+    init_analyzer(rx);
+  }
+
+  SetDisplayDetectorMode(rx->id, 0, display_detector_mode);
+  SetDisplayAverageMode(rx->id, 0,  display_average_mode);
+   
+  calculate_display_average(rx);
+
+  create_visual(rx);
+
+  if(rx->local_audio) {
+    audio_open_output(rx);
+  }
+
+  return rx;
+}
+
+void receiver_change_adc(RECEIVER *rx,int adc) {
+  rx->adc=adc;
+}
+
+void receiver_change_sample_rate(RECEIVER *rx,int sample_rate) {
+
+  rx->sample_rate=sample_rate;
+
+  SetChannelState(rx->id,0,1);
+
+  int scale=rx->sample_rate/48000;
+  rx->output_samples=rx->buffer_size/scale;
+  free(rx->audio_output_buffer);
+  rx->audio_output_buffer=malloc(sizeof(double)*2*rx->output_samples);
+  rx->audio_buffer=malloc(AUDIO_BUFFER_SIZE);
+  rx->hz_per_pixel=(double)rx->sample_rate/(double)rx->width;
+
+  SetInputSamplerate(rx->id, sample_rate);
+
+  init_analyzer(rx);
+
+fprintf(stderr,"receiver_change_sample_rate: id=%d rate=%d buffer_size=%d output_samples=%d\n",rx->id, rx->sample_rate, rx->buffer_size, rx->output_samples);
+  SetChannelState(rx->id,1,0);
+}
+
+void receiver_frequency_changed(RECEIVER *rx) {
+  int id=rx->id;
+
+  if(vfo[id].ctun) {
+    vfo[id].offset=vfo[id].ctun_frequency-vfo[id].frequency;
+    set_offset(rx,vfo[id].offset);
+  } else if(protocol==NEW_PROTOCOL) {
+    schedule_high_priority(); // send new frequency
+  }
+}
+
+void receiver_mode_changed(RECEIVER *rx) {
+  set_mode(rx,vfo[rx->id].mode);
+}
+
+void receiver_filter_changed(RECEIVER *rx) {
+  FILTER *mode_filters=filters[vfo[rx->id].mode];
+  FILTER *filter=&mode_filters[vfo[rx->id].filter];
+  set_filter(rx,filter->low,filter->high);
+}
+
+void receiver_vfo_changed(RECEIVER *rx) {
+  receiver_frequency_changed(rx);
+  receiver_mode_changed(rx);
+  receiver_filter_changed(rx);
+}
+
+#ifdef FREEDV
+static void process_freedv_rx_buffer(RECEIVER *rx) {
+  short left_audio_sample;
+  short right_audio_sample;
+  int i;
+  int demod_samples;
+  for(i=0;i<rx->output_samples;i++) {
+    if(freedv_samples==0) {
+      left_audio_sample=(short)(rx->audio_output_buffer[i*2]*32767.0);
+      right_audio_sample=(short)(rx->audio_output_buffer[(i*2)+1]*32767.0);
+      demod_samples=demod_sample_freedv(left_audio_sample);
+      if(demod_samples!=0) {
+        int s;
+        int t;
+        for(s=0;s<demod_samples;s++) {
+          if(freedv_sync) {
+            left_audio_sample=right_audio_sample=(short)((double)speech_out[s]);
+          } else {
+            left_audio_sample=right_audio_sample=0;
+          }
+          for(t=0;t<6;t++) { // 8k to 48k
+            if(local_audio) {
+                audio_write(left_audio_sample,right_audio_sample);
+                left_audio_sample=0;
+                right_audio_sample=0;
+            }
+
+            switch(protocol) {
+              case ORIGINAL_PROTOCOL:
+                old_protocol_audio_samples(left_audio_sample,right_audio_sample);
+                break;
+              case NEW_PROTOCOL:
+                new_protocol_audio_samples(left_audio_sample,right_audio_sample);
+                break;
+#ifdef LIMESDR
+              case LIMESDR_PROTOCOL:
+                break;
+#endif
+            }
+          }
+        }
+      }
+      freedv_samples++;
+      if(freedv_samples==freedv_resample) {
+        freedv_samples=0;
+      }
+    }
+  }
+}
+#endif
+
+static void process_rx_buffer(RECEIVER *rx) {
+  short left_audio_sample;
+  short right_audio_sample;
+  int i;
+  for(i=0;i<rx->output_samples;i++) {
+    if(isTransmitting()) {
+      left_audio_sample=0;
+      right_audio_sample=0;
+    } else {
+      left_audio_sample=(short)(rx->audio_output_buffer[i*2]*32767.0);
+      right_audio_sample=(short)(rx->audio_output_buffer[(i*2)+1]*32767.0);
+#ifdef PSK
+      if(vfo[rx->id].mode==modePSK) {
+        if(psk_samples==0) {
+          psk_demod((double)((left_audio_sample+right_audio_sample)/2));
+        }
+        psk_samples++;
+        if(psk_samples==psk_resample) {
+          psk_samples=0;
+        }
+      }
+#endif
+    }
+
+    if(rx->local_audio) {
+      switch(rx->audio_channel) {
+        case STEREO:
+          audio_write(rx,left_audio_sample,right_audio_sample);
+          break;
+        case LEFT:
+          audio_write(rx,left_audio_sample,0);
+          break;
+        case RIGHT:
+          audio_write(rx,0,right_audio_sample);
+          break;
+      }
+    }
+
+    if(rx==active_receiver) {
+      switch(protocol) {
+        case ORIGINAL_PROTOCOL:
+          old_protocol_audio_samples(rx,left_audio_sample,right_audio_sample);
+          break;
+        case NEW_PROTOCOL:
+          if(!(echo&&isTransmitting())) {
+            new_protocol_audio_samples(rx,left_audio_sample,right_audio_sample);
+          }
+          break;
+#ifdef LIMESDR
+        case LIMESDR_PROTOCOL:
+          break;
+#endif
+      }
+    }
+
+  }
+}
+
+void full_rx_buffer(RECEIVER *rx) {
+  int j;
+  int error;
+
+  fexchange0(rx->id, rx->iq_input_buffer, rx->audio_output_buffer, &error);
+  if(error!=0) {
+    fprintf(stderr,"full_rx_buffer: id=%d fexchange0: error=%d\n",rx->id,error);
+  }
+
+  if(rx->displaying) {
+    Spectrum0(1, rx->id, 0, 0, rx->iq_input_buffer);
+  }
+
+  switch(vfo[rx->id].mode) {
+#ifdef FREEDV
+    case modeFREEDV:
+      process_freedv_rx_buffer(rx);
+      break;
+#endif
+    default:
+      process_rx_buffer(rx);
+      break;
+  }
+}
+
+void add_iq_samples(RECEIVER *rx, double i_sample,double q_sample) {
+  rx->iq_input_buffer[rx->samples*2]=i_sample;
+  rx->iq_input_buffer[(rx->samples*2)+1]=q_sample;
+  rx->samples=rx->samples+1;
+  if(rx->samples==rx->buffer_size) {
+    full_rx_buffer(rx);
+    rx->samples=0;
+  }
+}
index 1d91a7e97cfaeb2784cb6d7fe2506236c9a5e0b8..75e36a786fbe6c0bcefa372ae13a4877d31adb96 100644 (file)
-#define MAX_RECEIVERS 2
+/* Copyright (C)
+* 2017 - John Melton, G0ORX/N6LYT
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+#ifndef _RECEIVER_H
+#define _RECEIVER_H
 
-struct _receiver {
+#include <gtk/gtk.h>
+#include <alsa/asoundlib.h>
+
+#define AUDIO_BUFFER_SIZE 260
+
+enum _audio_t {
+    STEREO=0,
+    LEFT,
+    RIGHT
+};
+
+typedef enum _audio_t audio_t;
+
+typedef struct _receiver {
+  int id;
+
+  int adc;
+
+  double volume;
+  int agc;
+  double agc_gain;
+  double agc_slope;
+  double agc_hang_threshold;
+  int fps;
+  int displaying;
+  audio_t audio_channel;
   int sample_rate;
   int buffer_size;
-  int band;
-  int bandstack;
-  int mode;
-  int filter;
-  int audio;
-} rx[MAX_RECEIVERS];
+  int fft_size;
+  int pixels;
+  int samples;
+  int output_samples;
+  double *iq_input_buffer;
+  double *audio_output_buffer;
+  unsigned char *audio_buffer;
+  int audio_index;
+  long audio_sequence;
+  float *pixel_samples;
+  int display_panadapter;
+  int display_waterfall;
+  gint update_timer_id;
+
+  double hz_per_pixel;
+
+//  long long frequency;
+//  long long display_frequency;
+//  long long dds_frequency;
+//  long long dds_offset;
+
+//  int rit;
+
+  int dither;
+  int random;
+  int preamp;
+
+  int nr;
+  int nr2;
+  int anf;
+  int snb;
+
+  int nr_agc;
+  int nr2_gain_method;
+  int nr2_npe_method;
+  int nr2_ae;
+
+
+  int attenuation;
+  int alex_antenna;
+  int alex_attenuation;
+
+  int filter_low;
+  int filter_high;
+
+  int width;
+  int height;
+
+  GtkWidget *panel;
+  GtkWidget *panadapter;
+  GtkWidget *waterfall;
+
+  int panadapter_low;
+  int panadapter_high;
+
+  int waterfall_low;
+  int waterfall_high;
+  int waterfall_automatic;
+
+  cairo_surface_t *panadapter_surface;
+  GdkPixbuf *pixbuf;
+
+  int local_audio;
+  int audio_device;
+  snd_pcm_t *playback_handle;
+  int playback_offset;
+  unsigned char *playback_buffer;
+
+} RECEIVER;
+
+extern RECEIVER *create_receiver(int id, int buffer_size, int fft_size, int pixels, int fps, int width, int height);
+extern void receiver_change_sample_rate(RECEIVER *rx,int sample_rate);
+extern void receiver_frequency_changed(RECEIVER *rx);
+extern void receiver_mode_changed(RECEIVER *rx);
+extern void receiver_filter_changed(RECEIVER *rx);
+extern void receiver_vfo_changed(RECEIVER *rx);
+
+extern void set_mode(RECEIVER* rx,int m);
+extern void set_filter(RECEIVER *rx,int low,int high);
+extern void set_agc(RECEIVER *rx, int agc);
+extern void set_offset(RECEIVER *rx, long long offset);
+extern void set_deviation(RECEIVER *rx, double deviation);
+
+extern void add_iq_samples(RECEIVER *rx, double i_sample,double q_sample);
+
+extern void reconfigure_receiver(RECEIVER *rx,int height);
+
+extern void receiver_save_state(RECEIVER *rx);
 
+extern gboolean receiver_button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data);
+extern gboolean receiver_button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer data);
+extern gboolean receiver_motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data);
+extern gboolean receiver_scroll_event(GtkWidget *widget, GdkEventScroll *event, gpointer data);
 
+#endif
index b1f76092763e68b1e177597b54a3e12b80dbd073..90b76dd27b84209ea4dbe4513d7d5c0008d3cb0f 100644 (file)
--- a/rigctl.c
+++ b/rigctl.c
-\r
-/* S-2000 emulation via TCP\r
- * Copyright (C) 2016 Steve Wilson <wevets@gmail.com>\r
- * This program is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU General Public License as\r
- * published by the Free Software Foundation, either version 2 of the\r
- * License, or (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-\r
-/*\r
- * PiHPSDR RigCtl by Steve KA6S Oct 16 2016\r
- * \r
- */\r
-#include <gtk/gtk.h>\r
-#include <gdk/gdk.h>\r
-#include <unistd.h>\r
-#include <semaphore.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include "toolbar.h"\r
-#include "sliders.h"\r
-#include "rigctl.h"\r
-#include "radio.h"\r
-#include "channel.h"\r
-#include "filter.h"\r
-#include <string.h>\r
-#include "mode.h"\r
-#include "filter.h"\r
-#include "wdsp_init.h"\r
-#include "band.h"\r
-#include "bandstack.h"\r
-#include "vfo.h"\r
-#include "sliders.h"\r
-#include <pthread.h>\r
-#include <wdsp.h>\r
-\r
-// IP stuff below\r
-#include<sys/socket.h>\r
-#include<arpa/inet.h> //inet_addr\r
-\r
-#undef RIGCTL_DEBUG\r
-\r
-// the port client will be connecting to\r
-#define TELNET_PORT 19090  // This is the HAMLIB port\r
-// max number of bytes we can get at once\r
-#define MAXDATASIZE 300\r
-\r
-int init_server ();\r
-\r
-int rigctlGetFilterLow();\r
-int rigctlGetFilterHigh();\r
-int rigctlSetFilterLow(int val);\r
-int rigctlSetFilterHigh(int val);\r
-int new_level;\r
-void parse_cmd ( char *,int );\r
-\r
-extern int enable_tx_equalizer;\r
-\r
-typedef struct com_list {\r
-     char  cmd_string[80];\r
-     struct com_list * next_ent; \r
- } com_list_t;\r
-com_list_t  cmd_list;\r
-char cmd_save[80];\r
-\r
-char  cmd_input[MAXDATASIZE] ;\r
-char * wptr;\r
-com_list_t * work_input; \r
-com_list_t * work_list; \r
-com_list_t * follow_list; \r
-com_list_t * com_head = NULL;\r
-com_list_t * cur_ent;\r
-int cmdlistcnt;\r
-int retcode = 1;\r
-char workvar[100];\r
-\r
-char command[80];\r
-char msg[80];\r
-char msg2[80];\r
-char * newf;\r
-\r
-FILE * TTYFILE;\r
-FILE * out;\r
-int  output;\r
-FILTER * band_filter;\r
-\r
-static pthread_t rigctl_thread_id;\r
-static void * rigctl (void * arg);\r
-\r
-int squelch=100; //local sim of squelch level\r
-// This stuff from the telnet server\r
-int sockfd, numbytes;\r
-char buf[MAXDATASIZE];\r
-struct hostent *he;\r
-\r
-// connector’s address information\r
-struct sockaddr_in their_addr;\r
-\r
-int socket_desc , client_sock , c , read_size;\r
-struct sockaddr_in server , client;\r
-char client_message[MAXDATASIZE];\r
-\r
-int freq_flag;  // Determines if we are in the middle of receiving frequency info\r
-\r
-int digl_offset = 0;\r
-int digl_pol = 0;\r
-int digu_offset = 0;\r
-int digu_pol = 0;\r
-double new_vol = 0;\r
-\r
-// Radio functions - \r
-// Memory channel stuff and things that aren't \r
-// implemented - but here for a more complete emulation\r
-int ctcss_tone;  // Numbers 01-38 are legal values - set by CN command, read by CT command\r
-int ctcss_mode;  // Numbers 0/1 - on off.\r
-\r
-// Now my stuff\r
-//\r
-// Looks up entry INDEX_NUM in the command structure and\r
-// returns the command string\r
-//\r
-\r
-void send_resp (char * msg) {\r
-    #ifdef  RIGCTL_DEBUG\r
-        fprintf(stderr,"RIGCTL: RESP=%s\n",msg);\r
-    #endif\r
-    write(client_sock, msg, strlen(msg));\r
-}\r
-\r
-char * cmd_lookup (int index_num) {\r
-    com_list_t * lcl_p;\r
-    lcl_p = com_head;\r
-    if(index_num == 0)  {\r
-       return(lcl_p->cmd_string);\r
-    } else {\r
-      while((lcl_p->next_ent != (com_list_t * ) NULL) && (index_num != 0)) {\r
-          lcl_p = lcl_p->next_ent;\r
-          index_num--;\r
-      }\r
-    }\r
-    if(index_num == 0)  {\r
-      return(lcl_p->cmd_string);\r
-    } else {\r
-      return ((char *) NULL);\r
-    } \r
-}\r
-\r
-static void * rigctl (void * arg) {\r
-   int len;\r
-   init_server();\r
-   int save_flag = 0; // Used to concatenate two cmd lines together\r
-   int semi_number = 0;\r
-   int i;\r
-   char * work_ptr;\r
-   char work_buf[MAXDATASIZE];\r
-\r
-  for(;;) {\r
-    fprintf(stderr,"RIGCTL - New run\n");\r
-    while((numbytes=recv(client_sock , cmd_input , MAXDATASIZE-2 , 0)) > 0 ) {\r
-         //cmd_input[numbytes+1]='\0'; // Turn into a C string\r
-         //i=strlen(cmd_input);\r
-         //#ifdef RIGCTL_DEBUG\r
-         //fprintf(stderr,"RIGCTL: RCVD=%s  NB=%d LEN=%d\n",cmd_input,numbytes,i);\r
-         //#endif\r
-         for(i=0;i<numbytes;i++)  { work_buf[i] = cmd_input[i]; }\r
-         work_buf[i+1] = '\0';\r
-         #ifdef RIGCTL_DEBUG\r
-         fprintf(stderr,"RIGCTL: RCVD=%s<-\n",work_buf);\r
-         #endif\r
-\r
-        // Need to handle two cases\r
-        // 1. Command is short, i.e. no semicolon - that will set save_flag=1 and\r
-        //    read another line..\r
-        // 2. 1 to N commands per line. Turns out N1MM sends multiple commands per line\r
-         \r
-        if(save_flag == 0) { // Count the number of semicolons if we aren't already in mode 1.\r
-          semi_number = 0;\r
-          for(i=0;i<numbytes;i++) {\r
-             if(cmd_input[i] == ';') { semi_number++;};\r
-          } \r
-        }\r
-        if((save_flag == 0) && (semi_number == 0)) {\r
-           cmd_input[numbytes] = '\0';      // Turn it into a C string\r
-           strcpy(cmd_save,cmd_input);      // And save a copy of it till next time through\r
-           save_flag = 1;\r
-        } else if(save_flag == 1) {\r
-           save_flag = 0;\r
-           cmd_input[numbytes] = '\0';      // Turn it into a C string\r
-           strcat(cmd_save,cmd_input);\r
-           strcpy(cmd_input,cmd_save);      // Cat them together and replace cmd_input\r
-           numbytes = strlen(cmd_input);\r
-        } \r
-        if(save_flag != 1) {\r
-           work_ptr = strtok(cmd_input,";");\r
-           while(work_ptr != NULL) {\r
-               parse_cmd(work_ptr,strlen(work_ptr));\r
-               work_ptr = strtok(NULL,";");\r
-           }\r
-           for(i=0;i<MAXDATASIZE;i++){\r
-                cmd_input[i] = '\0'; \r
-                work_buf[i]  = '\0';  // Clear the input buffer\r
-           }\r
-        }\r
-       // Got here because pipe closed \r
-    }\r
-    if(numbytes == 0) {\r
-         fprintf(stderr,"RIGCTL: Client disconnected\n");\r
-         close(client_sock);\r
-         sleep(1);\r
-         client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);\r
-    }\r
- }\r
-}\r
-\r
-void parse_cmd ( char * cmd_input,int len) {\r
-        int work_int;     \r
-        int new_low, new_high;\r
-        double meter;\r
-        BANDSTACK_ENTRY *entry;\r
-        // Parse the cmd_input\r
-        //int space = command.indexOf(' ');\r
-        //char cmd_char = com_head->cmd_string[0]; // Assume the command is first thing!\r
-        char cmd_str[3];\r
-        cmd_str[0] = cmd_input[0];\r
-        cmd_str[1] = cmd_input[1];\r
-        cmd_str[2] = '\0';\r
-        if(strcmp(cmd_str,"AC")==0)       { // Sets or reads the internal antenna tuner status\r
-                                                   // P1 0:RX-AT Thru, 1: RX-AT IN\r
-                                                   // P2 0: TX-AT Thru 1: TX-AT In\r
-                                                   // \r
-                                             if(len <= 2) {\r
-                                               send_resp("AC000;");\r
-                                             }\r
-                                          }\r
-        else if(strcmp(cmd_str,"AG")==0) {  // Set Audio Gain - \r
-                                            // AG123; Value of 0-\r
-                                            // AG1 = Sub receiver - what is the value set\r
-                                            // Response - AG<0/1>123; Where 123 is 0-260\r
-                                            if(len>4) { // Set Audio Gain\r
-                                               volume = (double) atoi(&cmd_input[3])/260; \r
-                                               g_idle_add(update_af_gain,NULL);               \r
-                                            } else { // Read Audio Gain\r
-                                              sprintf(msg,"AG0%03d;",(int) (2.6 * volume));\r
-                                              send_resp(msg);\r
-                                              #ifdef RIGCTL_DEBUG\r
-                                              fprintf(stderr,":%s\n",msg);\r
-                                              #endif\r
-                                            }\r
-                                          }\r
-        else if(strcmp(cmd_str,"AI")==0)  {  // Allow rebroadcast of set frequency after set - not supported\r
-                                             if(len <=2) {\r
-                                                send_resp("AI0;");\r
-                                             } \r
-                                          }\r
-        else if(strcmp(cmd_str,"AL")==0)  {  // Set/Reads the auto Notch level \r
-                                             if(len <=2) {\r
-                                                send_resp("AL000;");\r
-                                             } \r
-                                          }\r
-        else if(strcmp(cmd_str,"AM")==0)  {  // Sets or reads the Auto Mode\r
-                                             if(len <=2) {\r
-                                                send_resp("AM0;");\r
-                                             } \r
-                                          }\r
-        else if(strcmp(cmd_str,"AN")==0)  {  // Selects the antenna connector (ANT1/2)\r
-                                             if(len <=2) {\r
-                                                send_resp("AN0;");\r
-                                             } \r
-                                          }\r
-        else if(strcmp(cmd_str,"AR")==0)  {  // Sets or reads the ASC function on/off\r
-                                             if(len <=2) {\r
-                                                send_resp("AR0;");\r
-                                             } \r
-                                          }\r
-        else if(strcmp(cmd_str,"AS")==0)  {  // Sets/reads automode function parameters\r
-                                             // AS<P1><2xP2><11P3><P4>;\r
-                                             // AS<P1><2xP2><11P3><P4>;\r
-                                             if(len < 6) {  \r
-                                                sprintf(msg,"AS%1d%02d%011lld%01d;",\r
-                                                             0, // P1\r
-                                                             0, // Automode \r
-                                                             getFrequency(),\r
-                                                             rigctlGetMode());\r
-                                                send_resp(msg);\r
-                               \r
-                                             } \r
-                                          }\r
-        else if(strcmp(cmd_str,"BC")==0)  {  // Beat Cancellor OFF\r
-                                             if(len <=2) {\r
-                                                send_resp("BC0;");\r
-                                             } \r
-                                          }\r
-        else if(strcmp(cmd_str,"BD")==0)  {  // Moves down the frequency band\r
-                                             // No response \r
-                                          }\r
-        else if(strcmp(cmd_str,"BP")==0)  {  // Reads the manual beat canceller frequency setting\r
-                                             if(len <=2) {\r
-                                                send_resp("BP000;");\r
-                                             } \r
-                                          }\r
-        else if(strcmp(cmd_str,"BS")==0)  {  // Sets or reads Beat Canceller status\r
-                                             if(len <=2) {\r
-                                                send_resp("BS0;");\r
-                                             } \r
-                                          }\r
-        else if(strcmp(cmd_str,"BU")==0)  {  // Moves Up the frequency band\r
-                                             // No response \r
-                                          }\r
-        else if(strcmp(cmd_str,"BY")==0)  {  // Read the busy signal status\r
-                                             if(len <=2) {\r
-                                                send_resp("BY00;");\r
-                                             } \r
-                                          }\r
-        else if(strcmp(cmd_str,"CA")==0)  {  // Sets/reads cw auto tune function status\r
-                                             if(len <=2) {\r
-                                                send_resp("CA0;");\r
-                                             } \r
-                                          }\r
-        else if(strcmp(cmd_str,"CG")==0)  {  // Sets/reads the carrier gain status\r
-                                             // 0-100 legal values\r
-                                             if(len <=2) {\r
-                                                send_resp("CG000;");\r
-                                             } \r
-                                          }\r
-        else if(strcmp(cmd_str,"CH")==0)  {  // Sets the current frequency to call Channel\r
-                                             // No response\r
-                                          }\r
-        else if(strcmp(cmd_str,"CI")==0)  {  // While in VFO mode or memory recall mode, sets freq to the call channel\r
-                                             // No response\r
-                                          }\r
-        else if(strcmp(cmd_str,"CM")==0)  {  // Sets or reads the packet cluster tune f(x) on/off\r
-                                             // 0-100 legal values\r
-                                             if(len <=2) {\r
-                                                send_resp("CM0;");\r
-                                             } \r
-                                          }\r
-        else if(strcmp(cmd_str,"CN")==0)  {  // Sets and reads CTSS function - 01-38 legal values\r
-                                             // Stored locally in rigctl - not used.\r
-                                             if(len <=2) {\r
-                                                sprintf(msg,"CN%02d;",ctcss_tone);\r
-                                                send_resp(msg);\r
-                                             } else {\r
-                                                ctcss_tone = atoi(&cmd_input[2]);\r
-                                             }\r
-                                          }\r
-        else if(strcmp(cmd_str,"CT")==0)  {  // Sets and reads CTSS function status\r
-                                             // Stored locally in rigctl - not used.\r
-                                             if(len <=2) {\r
-                                                sprintf(msg,"CT%01d;",ctcss_mode);\r
-                                                send_resp(msg);\r
-                                             } else {\r
-                                                ctcss_mode = atoi(&cmd_input[2]);\r
-                                             }\r
-                                          }\r
-        else if(strcmp(cmd_str,"DC")==0)  {  // Sets/Reads TX band status\r
-                                             if(len <=2) {\r
-                                                send_resp("DC00;");\r
-                                             } \r
-                                          }\r
-        else if(strcmp(cmd_str,"DN")==0)  {  // Emulate Mic down key \r
-                                          }\r
-        else if(strcmp(cmd_str,"DQ")==0)  {  // ETs/and reads the DCS function status\r
-                                             if(len <=2) {\r
-                                                send_resp("DQ0;");\r
-                                             } \r
-                                          }\r
-        else if(strcmp(cmd_str,"EX")==0)  {  // Set/reads the extension menu\r
-                                             cmd_input[9] = '\0'; // Make sure we have a C string\r
-                                             sprintf(msg,"EX%s0;",&cmd_input[2]);\r
-                                             send_resp(msg);\r
-                                          }\r
-        else if(strcmp(cmd_str,"FA")==0) {  // VFO A frequency\r
-                                            // LEN=7 - set frequency\r
-                                            // Next data will be rest of freq\r
-                                            if(len == 13) { //We are receiving freq info\r
-                                               long long new_freqA = atoll(&cmd_input[2]);\r
-                                               set_band(new_freqA);\r
-                                               //setFrequency(new_freqA);\r
-                                               //g_idle_add(vfo_update,NULL);\r
-                                            } else {\r
-                                               if(len==2) {\r
-                                                  sprintf(msg,"FA%011lld;",getFrequency());\r
-                                                  send_resp(msg);\r
-                                               }\r
-                                            }\r
-                                         }\r
-        else if(strcmp(cmd_str,"FB")==0) {  // VFO B frequency\r
-                                            if(len==13) { //We are receiving freq info\r
-                                               long long new_freqA = atoll(&cmd_input[2]); \r
-                                               set_band(new_freqA);\r
-                                               //setFrequency(new_freqA);\r
-                                               //g_idle_add(vfo_update,NULL);\r
-                                            } else if(len == 2) {\r
-                                               sprintf(msg,"FB%011lld;",getFrequency());\r
-                                               send_resp(msg);\r
-                                            }\r
-                                         }\r
-        else if(strcmp(cmd_str,"FC")==0) {  // Set Sub receiver freq\r
-                                            // LEN=7 - set frequency\r
-                                            // Next data will be rest of freq\r
-                                            // Len<7 - frequency?\r
-                                            if(len>4) { //We are receiving freq info\r
-                                               long long new_freqA = atoll(&cmd_input[2]);              \r
-                                               //setFrequency(new_freqA);\r
-                                            } else {\r
-                                               sprintf(msg,"FC%011lld;",getFrequency());\r
-/*\r
-                                               send_resp(msg);\r
-*/\r
-                                            }\r
-                                         }\r
-        else if(strcmp(cmd_str,"FD")==0)  {  // Read the filter display dot pattern\r
-                                              send_resp("FD00000000;");\r
-                                          }\r
-        else if(strcmp(cmd_str,"FR")==0)  {  // Set/reads the extension menu\r
-                                             if(len <=2) {\r
-                                                send_resp("FR0;");\r
-                                             } \r
-                                          }\r
-        else if(strcmp(cmd_str,"FS")==0)  {  // Set/reads fine funct status\r
-                                             if(len <=2) {\r
-                                                send_resp("FS0;");\r
-                                             } \r
-                                          }\r
-        else if(strcmp(cmd_str,"FT")==0)  { // Sel or reads the transmitters VFO, M, ch or Call comm   \r
-                                             if(len <=2) {\r
-                                                send_resp("FT0;");\r
-                                             } \r
-                                          }  \r
-        else if(strcmp(cmd_str,"FW")==0)  { // Sets/Reas DSP receive filter width in hz 0-9999hz \r
-                                             // CW - legal values  50  80  100 150 200 300 400 500 600 1000 2000\r
-                                             //      PiHPSDR map   50  100 100 100 250 250 400 500 600 1000\r
-                                             //                    25                                   750\r
-                                             entry= (BANDSTACK_ENTRY *) \r
-                                                         bandstack_entry_get_current();\r
-                                             FILTER* band_filters=filters[entry->mode];\r
-                                             FILTER* band_filter=&band_filters[entry->filter];\r
-                                             if(len <=2) {\r
-                                                // CW filter high and low are always the same and the filter value is 2*filter val\r
-                                                int filter_val = band_filter->high * 2;\r
-                                                switch(filter_val) {\r
-                                                 case 25:  \r
-                                                 case 50:\r
-                                                        work_int = 50;\r
-                                                        break;\r
-                                                 case 100:\r
-                                                        work_int = 100; \r
-                                                        break;\r
-                                                 case 250:\r
-                                                        work_int = 300; \r
-                                                        break;\r
-                                                 case 400:\r
-                                                        work_int = 400; \r
-                                                        break;\r
-                                                 case 500:\r
-                                                        work_int = 500; \r
-                                                        break;\r
-                                                 case 600:\r
-                                                        work_int = 600; \r
-                                                        break;\r
-                                                 case 750:\r
-                                                        work_int = 1000; \r
-                                                        break;\r
-                                                 case 800:\r
-                                                        work_int = 1000; \r
-                                                        break;\r
-                                                 case 1000:\r
-                                                        work_int = 1000; \r
-                                                        break;\r
-                                                 default: work_int = 500; \r
-                                                        break;\r
-                                                } \r
-                                                sprintf(msg,"FW%04d;",work_int);\r
-                                                #ifdef  RIGCTL_DEBUG\r
-                                                    fprintf(stderr,"RIGCTL: FW Filter Act=%d work_int=%d\n",band_filter->high,work_int);\r
-                                                #endif\r
-                                                send_resp(msg);\r
-                                             } else {\r
-                                               // Try to set filters here!\r
-                                               // CW - legal values  50  80  100 150 200 300 400 500 600 1000 2000\r
-                                               //      PiHPSDR map   50  100 100 100 250 250 400 500 600 1000\r
-                                               //                    25                                   750\r
-                                               work_int = atoi(&cmd_input[2]);\r
-                                               switch (work_int) {\r
-\r
-                                                    case 50:  new_low = 25; new_high = 25; break;\r
-                                                    case 80:  new_low = 50; new_high = 50; break;\r
-                                                    case 100:  new_low = 50; new_high = 50; break;\r
-                                                    case 150:  new_low = 50; new_high = 50; break;\r
-                                                    case 200:  new_low = 125; new_high = 125; break;\r
-                                                    case 300:  new_low = 125; new_high = 125; break;\r
-                                                    case 400:  new_low = 200; new_high = 200; break;\r
-                                                    case 500:  new_low = 250; new_high = 250; break;\r
-                                                    case 600:  new_low = 300; new_high = 300; break;\r
-                                                    case 1000:  new_low = 500; new_high = 500; break;\r
-                                                    case 2000:  new_low = 500; new_high = 500; break;\r
-                                                    default: new_low  = band_filter->low;\r
-                                                             new_high = band_filter->high;\r
-\r
-                                               }\r
-                                               #ifdef  RIGCTL_DEBUG\r
-                                                   fprintf(stderr,"RIGCTL: FW Filter new_low=%d new_high=%d\n",new_low,new_high);\r
-                                               #endif\r
-                                               // entry->filter = new_low * 2 ;\r
-                                               setFilter(new_low,new_high);\r
-                                               g_idle_add(vfo_update,NULL);\r
-                                             }\r
-                                          }  \r
-        else if(strcmp(cmd_str,"GT")==0)  { // Sets/Reas AGC constant status\r
-                                             if(len <=2) {\r
-                                                send_resp("GT000;");\r
-                                             } \r
-                                          }  \r
-        else if(strcmp(cmd_str,"ID")==0)  { // Read ID - Default to TS-2000 which is type 019.\r
-                                            sprintf(msg,"ID019;");\r
-                                            send_resp(msg);\r
-                                          }\r
-        else if(strcmp(cmd_str,"IF")==0) {  // Reads Transceiver status\r
-                                            // IFFFFFFFFFFFF - Frequency \r
-                                            //   OFFS        - 4 chars Offset in powers of 10\r
-                                            //   RITRIT      - 6 chars RIT/XIT Frequency - Not supported =0\r
-                                            //   R           - 1 char  RIT Status = 0 is off\r
-                                            //   X           - 1 char  XIT Status = 0 is off\r
-                                            //   0           - 1 char  Channel Bank number - not used\r
-                                            //   00          - 2 char  Channel Bank number - not used\r
-                                            //   C           - 1 char  Mox Status 0=off, 1=on\r
-                                            //   M           - 1 char Operating mode - align with MD commands\r
-                                            //   V           - 1 char VFO Split status - not supported  \r
-                                            //   0           - 1 char Scan status - not supported\r
-                                            //   A           - 1 char - same as FT command\r
-                                            //   0           - 1 char - CTCSS tone - not used\r
-                                            //   00          - 2 char - More tone control\r
-                                            //   0           - 1 char - Shift status\r
-                                            sprintf(msg,"IF%011lld%04d%06d%1d%1d%1d%02d%01d%01d%01d%01d%01d%01d%02d%01d;",\r
-                                                         getFrequency(),\r
-                                                         step,  // Shift Offset\r
-                                                         0,  // Rit Freq\r
-                                                         0,  // Rit Status\r
-                                                         0,  // XIT Status\r
-                                                         0,  // Channel Bank num\r
-                                                         0,  // Channel Bank num\r
-                                                         0,  // Mox Status\r
-                                                         rigctlGetMode(),  // Mode Status - same as MD Command\r
-                                                         0,  // VFO Status\r
-                                                         0,  // Scan status\r
-                                                         0,  // FT command \r
-                                                         ctcss_tone,  // CTSS Tone\r
-                                                         0,  // More tone control\r
-                                                         0); // Shift status\r
-                                            send_resp(msg);\r
-                                         }\r
-        else if(strcmp(cmd_str,"IS")==0)  { // Sets/Reas IF shift funct status\r
-                                             if(len <=2) {\r
-                                                send_resp("IS00000;");\r
-                                             } \r
-                                          }  \r
-        else if(strcmp(cmd_str,"KS")==0)  { // Sets/Reads keying freq - 0-060 max\r
-                                             if(len <=2) {\r
-                                                sprintf(msg,"KS%03d;",cw_keyer_speed);\r
-                                                send_resp(msg);\r
-                                             } else {\r
-                                                int key_speed;\r
-                                                key_speed = atoi(&cmd_input[2]);\r
-                                                if(key_speed >1 && key_speed <= 60) {\r
-                                                   cw_keyer_speed=key_speed;\r
-                                                   g_idle_add(vfo_update,NULL);\r
-                                                } \r
-                                            }\r
-                                          }  \r
-        else if(strcmp(cmd_str,"KY")==0)  { // Convert char to morse code\r
-                                             if(len <=2) {\r
-                                                send_resp("KY0;");\r
-                                             } \r
-                                          }  \r
-        else if(strcmp(cmd_str,"LK")==0)  { // Set/read key lock function status\r
-                                             if(len <=2) {\r
-                                                sprintf(msg,"LK%01d%01d;",locked,locked);\r
-                                                send_resp(msg);\r
-                                             }  else {\r
-                                                  if(cmd_input[3] == '0') {\r
-                                                      locked = 0;\r
-                                                  } else if(cmd_input[3] == '1') {\r
-                                                      locked = 1;\r
-                                                  }\r
-                                                  g_idle_add(vfo_update,NULL);\r
-                                             }\r
-                                          }  \r
-        else if(strcmp(cmd_str,"LM")==0)  { // Set/read DRU 3A unit or elect keyer recording status\r
-                                             if(len <=2) {\r
-                                                send_resp("LM0;");\r
-                                             } \r
-                                          }  \r
-        else if(strcmp(cmd_str,"LT")==0)  { // Set/read Alt function\r
-                                             if(len <=2) {\r
-                                                send_resp("LT0;");\r
-                                             } \r
-                                          }  \r
-        else if(strcmp(cmd_str,"MC")==0) {  // Recalls or reads memory channel\r
-                                             if(len <=2) {\r
-                                               send_resp("MC000;"); // Link this to band stack at some point\r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"MD")==0) {  // Mode - digit selects mode\r
-                                            // 1 = LSB\r
-                                            // 2 = USB\r
-                                            // 3 = CWU\r
-                                            // 4 = FM\r
-                                            // 5 = AM\r
-                                            // 6 = DIGL\r
-                                            // 7 = CWL\r
-                                            // 9 = DIGU \r
-                                            int new_mode;\r
-                                            if(len > 2) { // Set Mode\r
-                                               switch(atoi(&cmd_input[2])) {   \r
-                                                 case 1:  \r
-                                                     new_mode = modeLSB;\r
-                                                     break;\r
-                                                 case 2:  \r
-                                                     new_mode = modeUSB;\r
-                                                     break;\r
-                                                 case 3:  \r
-                                                     new_mode = modeCWU;\r
-                                                     break;\r
-                                                 case 4:  \r
-                                                     new_mode = modeFMN;\r
-                                                     break;\r
-                                                 case 5:  \r
-                                                     new_mode = modeAM;\r
-                                                     break;\r
-                                                 case 6:  \r
-                                                     new_mode = modeDIGL;\r
-                                                     break;\r
-                                                 case 7:  \r
-                                                     new_mode = modeCWL;\r
-                                                     break;\r
-                                                 case 9:  \r
-                                                     new_mode = modeDIGU;\r
-                                                     break;\r
-                                                 default:\r
-                                                     break;\r
-                                                     #ifdef RIGCTL_DEBUG\r
-                                                     fprintf(stderr,"MD command Unknown\n");\r
-                                                     #endif\r
-                                               }\r
-                                            // Other stuff to switch modes goes here..\r
-                                            // since new_mode has the interpreted command in \r
-                                            // in it now.\r
-                                            entry= (BANDSTACK_ENTRY *) \r
-                                                  bandstack_entry_get_current();\r
-                                            entry->mode=new_mode;\r
-                                            //  BUG - kills the system when there is some\r
-                                            // GPIO activity and Mode sets occur. Used twittling the\r
-                                           // frequency along with setting mode between USB/LSB with\r
-                                           // flrig. Tried doing the g_idle_add trick - but don't know the\r
-                                           // the magic to get that to compile without warnings \r
-                                            setMode(entry->mode);\r
-                                            // Moved the vfo_update down after filter updated. (John G0ORX)\r
-                                            //g_idle_add(vfo_update,NULL);\r
-                                            \r
-                                            FILTER* band_filters=filters[entry->mode];\r
-                                            FILTER* band_filter=&band_filters[entry->filter];\r
-                                            setFilter(band_filter->low,band_filter->high);\r
-                                            /* Need a way to update VFO info here..*/\r
-                                            g_idle_add(vfo_update,NULL);\r
-                                            }  else {     // Read Mode\r
-                                               int curr_mode;\r
-                                               switch (mode) {\r
-                                                  case modeLSB: curr_mode = 1; \r
-                                                          break;   \r
-                                                  case modeUSB: curr_mode = 2;\r
-                                                          break;\r
-                                                  case modeCWL: curr_mode = 7; // CWL\r
-                                                          break;\r
-                                                  case modeCWU: curr_mode = 3; // CWU\r
-                                                          break;\r
-                                                  case modeFMN: curr_mode = 4; // FMN\r
-                                                          break;\r
-                                                  case modeAM: curr_mode = 5; // AM\r
-                                                          break;\r
-                                                  case modeDIGU: curr_mode = 9; // DIGU\r
-                                                          break;\r
-                                                  case modeDIGL: curr_mode = 6; // DIGL\r
-                                                          break;\r
-                                                  default: \r
-                                                          #ifdef RIGCTL_DEBUG\r
-                                                            fprintf(stderr,\r
-                                                            "RIGCTL: MD command doesn't support %d\n",\r
-                                                            mode);\r
-                                                          #endif\r
-                                                          break;\r
-                                               }\r
-                                               sprintf(msg,"MD%1d;",curr_mode);\r
-                                               send_resp(msg);\r
-                                            }\r
-                                         }\r
-        else if(strcmp(cmd_str,"MF")==0) {  // Set/read menu A/B\r
-                                             if(len <=2) {\r
-                                               send_resp("MF0;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"MG")==0) {  // Mike Gain - 3 digit value \r
-                                            if(len <=2) {\r
-                                               work_int = (int) ((mic_gain +10.0)* 100.0/60.0);\r
-                                               sprintf(msg,"MG%03d;",work_int);\r
-                                               send_resp(msg);\r
-                                            } else {\r
-                                               int tval = atoi(&cmd_input[2]);                \r
-                                               new_vol = (double) (tval * 60/100) - 10; \r
-                                               //set_mic_gain(new_vol); \r
-                                               double *p_mic_gain=malloc(sizeof(double));\r
-                                               *p_mic_gain=new_vol;\r
-                                               g_idle_add(update_mic_gain,(void *)p_mic_gain);\r
-                                            }\r
-                                         }\r
-        else if(strcmp(cmd_str,"ML")==0) {  // Set/read the monitor function level\r
-                                             if(len <=2) {\r
-                                               send_resp("ML000;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"MO")==0) {  // Set Monitor on/off\r
-                                             if(len <=2) {\r
-                                               send_resp("MO0;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"MR")==0) {  // Read Memory Channel data\r
-                                             sprintf(msg,"MR%1d%02d%02d%011lld%1d%1d%1d%02d%02d%03d%1d%1d%09d%02d%1d%08d;",\r
-                                                      0, // P1 - Rx Freq - 1 Tx Freq\r
-                                                      0, // P2 Bankd and channel number -- see MC comment\r
-                                                      0, // P3 - see MC comment \r
-                                                      getFrequency(), // P4 - frequency\r
-                                                      rigctlGetMode(), // P5 - Mode\r
-                                                      locked, // P6 - Locked status\r
-                                                      0, // P7 - O-off, 1-tone, 2-CTCSS, 3 =DCS\r
-                                                      0, // P8 - Tone Number - see page 35\r
-                                                      ctcss_tone, // P9 - CTCSS tone number - see CN command\r
-                                                      0, // P10 - DCS code - see QC command \r
-                                                      0, // P11 - Reverse status\r
-                                                      0, // P12 - Shift status - see OS command\r
-                                                      0, // P13 - Offset freq - see OS command\r
-                                                      0, // P14 - Step Size - see ST command\r
-                                                      0, // P15 - Memory Group Number (0-9)\r
-                                                      0);  // P16 - Memory Name - 8 char max\r
-                                               send_resp(msg);\r
-                                         }\r
-        else if(strcmp(cmd_str,"MU")==0) {  // Set/Read Memory Group Data\r
-                                             if(len <=2) {\r
-                                               send_resp("MU0000000000;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"MW")==0) {  // Store Data to Memory Channel\r
-                                         }\r
-        else if(strcmp(cmd_str,"NB")==0) {  // Set/Read Noise Blanker func status (on/off)\r
-                                             if(len <=2) {\r
-                                               sprintf(msg,"NB%1d;",snb);\r
-                                               send_resp(msg);\r
-                                             } else {\r
-                                               if(cmd_input[2]=='0') { // Turn off ANF\r
-                                                  snb=0;\r
-                                               } else { // Turn on ANF\r
-                                                  snb=1;\r
-                                               }\r
-                                               // Update ALL the filters\r
-                                               SetRXAANRRun(CHANNEL_RX0, nr);\r
-                                               SetRXAEMNRRun(CHANNEL_RX0, nr2);\r
-                                               SetRXAANFRun(CHANNEL_RX0, anf);\r
-                                               SetRXASNBARun(CHANNEL_RX0, snb);\r
-                                               g_idle_add(vfo_update,NULL);\r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"NL")==0) {  // Set/Read Noise Reduction  Level\r
-                                             if(len <=2) {\r
-                                               send_resp("NL000;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"NR")==0) {  // Set/Read Noise Reduction function status\r
-                                             if(len <=2) {\r
-                                               if(nr_none == 1) {\r
-                                                   send_resp("NR0;"); \r
-                                               } else if ((nr_none == 0) && (nr==1)) { \r
-                                                   send_resp("NR1;"); \r
-                                               } else if (nr2 == 1) { \r
-                                                   send_resp("NR2;"); \r
-                                               } else {\r
-                                                   send_resp("NR0;"); \r
-                                               }\r
-                                             } else {\r
-                                               if(cmd_input[2] == '0') {\r
-                                                  nr_none = 1;\r
-                                                  nr = 0;\r
-                                                  nr2 = 0;\r
-                                               } else if(cmd_input[2] == '1') {\r
-                                                  nr_none = 0;\r
-                                                  nr = 1;\r
-                                                  nr2 = 0;\r
-                                               } else if(cmd_input[2] == '2') {\r
-                                                  nr_none = 0;\r
-                                                  nr = 0;\r
-                                                  nr2 = 1;\r
-                                             } \r
-                                             SetRXAANRRun(CHANNEL_RX0, nr_none);\r
-                                             SetRXAEMNRRun(CHANNEL_RX0, nr2);\r
-                                             SetRXAANFRun(CHANNEL_RX0, anf);\r
-                                             SetRXASNBARun(CHANNEL_RX0, snb);\r
-                                             g_idle_add(vfo_update,NULL);\r
-                                            }\r
-                                         }\r
-        else if(strcmp(cmd_str,"NT")==0) {  // Set/Read autonotch function\r
-                                             if(len <=2) {\r
-                                               sprintf(msg,"NT%1d;",anf);\r
-                                               send_resp(msg);\r
-                                             } else {\r
-                                               if(cmd_input[2] == '0') { // Clear ANF\r
-                                                 anf = 0;\r
-                                               } else { // Set ANF\r
-                                                 anf = 1;\r
-                                               }\r
-                                             }\r
-                                             SetRXAANRRun(CHANNEL_RX0, nr_none);\r
-                                             SetRXAEMNRRun(CHANNEL_RX0, nr2);\r
-                                             SetRXAANFRun(CHANNEL_RX0, anf);\r
-                                             SetRXASNBARun(CHANNEL_RX0, snb);\r
-                                             g_idle_add(vfo_update,NULL);\r
-                                         }\r
-        else if(strcmp(cmd_str,"OF")==0) {  // Set/Read Offset freq (9 digits - hz)\r
-                                             if(len <=2) {\r
-                                               send_resp("OF000000000;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"OI")==0) {  // Read Memory Channel Data\r
-                                             if(len <=2) {\r
-                                               sprintf(msg,"OI%011lld%04d%06d%1d%1d%1d%02d%1d%1d%1d%1d%1d%1d%02d%1d;",\r
-                                                  getFrequency(),\r
-                                                  0, // P2 - Freq Step size\r
-                                                  0, // P3 - Rit/Xit Freq \r
-                                                  0, // P4 - RIT off/Rit On\r
-                                                  0, // P5 - XIT off/on\r
-                                                  0, // P6 - Channel\r
-                                                  0, // P7 - Bank\r
-                                                  0, // P8 - 0RX, 1TX\r
-                                                  rigctlGetMode(),  // P10 - MD\r
-                                                  0, // P11 - SC command\r
-                                                  0, // P12 Split op - SP command\r
-                                                  0, // P13 Off, 1, 2, \r
-                                                  0,// P14 Tone freq - See TN command\r
-                                                  0,0);\r
-                                               send_resp(msg);\r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"OS")==0) {  // Set/Read Offset freq (9 digits - hz)\r
-                                             if(len <=2) {\r
-                                               send_resp("OS0;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"PA")==0) {  // Set/Read Preamp function status\r
-                                             if(len <=2) {\r
-                                               sprintf(msg,"PA0%1d;",enable_tx_equalizer);\r
-                                               send_resp(msg);\r
-                                             } else {\r
-                                                if(cmd_input[2] =='0') {\r
-                                                  enable_tx_equalizer=0;\r
-                                                  SetTXAEQRun(CHANNEL_TX, enable_tx_equalizer);\r
-                                                } else {\r
-                                                  enable_tx_equalizer=1;\r
-                                                  SetTXAEQRun(CHANNEL_TX, enable_tx_equalizer);\r
-                                                }\r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"PB")==0) {  // Set/Read DRU-3A Playback status\r
-                                             if(len <=2) {\r
-                                               send_resp("PB0;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"PC")==0) {  // Set/Read Drive Power output\r
-                                            if(len<=2) {\r
-                                              sprintf(msg,"PC%03d;",(int) drive);\r
-                                              send_resp(msg); \r
-                                            } else {\r
-                                               // Power Control - 3 digit number- 0 to 100\r
-                                               //Scales to 0.00-1.00\r
-                                                \r
-                                               double drive_val = \r
-                                                   (double)(atoi(&cmd_input[2])); \r
-                                               // setDrive(drive_val);\r
-                                               double *p_drive=malloc(sizeof(double));\r
-                                               *p_drive=drive_val;\r
-                                               g_idle_add(update_drive,(gpointer)p_drive);\r
-                                               //set_drive(drive_val);\r
-                                            }\r
-                                         }\r
-        else if(strcmp(cmd_str,"PI")==0) {  // STore the programmable memory channel\r
-                                         }\r
-        else if(strcmp(cmd_str,"PK")==0) {  // Reads the packet cluster data\r
-                                               send_resp("PK000000000000000000000000000000000000000000000000;"); \r
-                                         }\r
-        else if(strcmp(cmd_str,"PL")==0) {  // Set/Read Speech processor level\r
-                                            // P1 000 - min-100 max\r
-                                            // P2 000 - min - 100 max\r
-                                             if(len <=2) {\r
-                                               send_resp("PL000000;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"PM")==0) {  // Recalls the Programmable memory\r
-                                             if(len <=2) {\r
-                                               send_resp("PM0;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"PR")==0) {  // Sets/reads the speech processor function on/off\r
-                                            // 0 - off, 1=on\r
-                                             if(len <=2) {\r
-                                               send_resp("PR0;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"PS")==0) {  // Sets/reads Power on/off state\r
-                                            // 0 - off, 1=on\r
-                                             if(len <=2) {\r
-                                               send_resp("PS1;"); // Lets pretend we're powered up ;-) \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"PS")==0) {  // Sets/reads DCS code\r
-                                            // Codes numbered from 000 to 103.\r
-                                             if(len <=2) {\r
-                                               send_resp("QC000;"); // Lets pretend we're powered up ;-) \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"QI")==0) {  // Store the settings in quick memory\r
-                                         }\r
-        else if(strcmp(cmd_str,"QR")==0) {  // Send the Quick memory channel data\r
-                                            // P1 - Quick mem off, 1 quick mem on\r
-                                            // P2 - Quick mem channel number\r
-                                             if(len <=2) {\r
-                                               send_resp("QR00;"); // Lets pretend we're powered up ;-) \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"RA")==0) {  // Sets/reads Attenuator function status\r
-                                            // 00-off, 1-99 -on - Main and sub receivers reported\r
-                                             if(len <=2) {\r
-                                               send_resp("RA0000;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"RC")==0) {  // Clears the RIT offset freq\r
-                                         }\r
-        else if(strcmp(cmd_str,"RD")==0) {  // Move the RIT offset freq down, slow down the scan speed in scan mode\r
-                                             if(len <=2) {\r
-                                               send_resp("RD0;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"RG")==0) {  // RF Gain - 3 digit number\r
-                                            // RG123; 0-255 value\r
-                                            // Scale from -20 - 120\r
-                                            if(len>4) { // Set Audio Gain\r
-                                               int base_value = atoi(&cmd_input[2]);\r
-                                               double new_gain = ((((double) base_value)/255) * 140) - 20; \r
-                                               //set_agc_gain(new_gain);               \r
-                                               double *p_gain=malloc(sizeof(double));\r
-                                               *p_gain=new_gain;\r
-                                               g_idle_add(update_agc_gain,(gpointer)p_gain);\r
-                                            } else { // Read Audio Gain\r
-                                              sprintf(msg,"RG%03d;",((256 * (int) agc_gain)/140)+36);\r
-                                              send_resp(msg);\r
-                                            }\r
-                                         }\r
-        else if(strcmp(cmd_str,"RL")==0) {  // Set/read Noise reduction level\r
-                                             if(len <=2) {\r
-                                               send_resp("RL00;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"RM")==0) {  // Set/read Meter function\r
-                                            // P1- 0, unsel, 1 SWR, 2 Comp, 3 ALC\r
-                                            // P2 - 4 dig - Meter value in dots - 000-0030\r
-                                             if(len <=2) {\r
-                                               send_resp("RM00000;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"RT")==0) {  // Set/read the RIT function status\r
-                                             if(len <=2) {\r
-                                               send_resp("RT0;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"RU")==0) {  // Set/move RIT frequency up\r
-                                             if(len <=2) {\r
-                                               send_resp("RU0;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"RX")==0) {  // Unkey Xmitter\r
-                                            setMox(0);\r
-                                            // 0-main, 1=sub\r
-                                             if(len <=2) {\r
-                                               send_resp("RX0;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"SA")==0) {  // Set/reads satellite mode status\r
-                                            // 0-main, 1=sub\r
-                                             if(len <=2) {\r
-                                               send_resp("SA000000000000000;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"SB")==0) {  // Set/read the SUB TF-W status\r
-                                             if(len <=2) {\r
-                                               send_resp("SB0;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"SC")==0) {  // Set/read the Scan function status\r
-                                             if(len <=2) {\r
-                                               send_resp("SC0;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"SD")==0) {  // Set/read CW break-in time delay\r
-                                            // 0000-1000 ms (in steps of 50 ms) 0000 is full break in\r
-                                             if(len <=2) {\r
-                                               send_resp("SD0000;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"SH")==0) {  // Set/read the DSP filter settings\r
-                                             if(len <=2) {\r
-                                               send_resp("SH00;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"SI")==0) {  // Enters the satellite memory name\r
-                                         }\r
-        else if(strcmp(cmd_str,"SL")==0) {  // Set/read the DSP filter settings - this appears twice? See SH\r
-                                             if(len <=2) {\r
-                                               send_resp("SL00;");\r
-                                             } \r
-                                         }\r
-        else if(strcmp(cmd_str,"SM")==0) {  // Read SMETER\r
-                                            // SMx;  x=0 RX1, x=1 RX2 \r
-                                            // meter is in dbm - value will be 0<260\r
-                                            // Translate to 00-30 for main, 0-15 fo sub\r
-                                            // Resp= SMxAABB; \r
-                                            //  Received range from the SMeter can be -127 for S0, S9 is -73, and S9+60=-13.;\r
-                                            //  PowerSDR returns S9=0015 code. \r
-                                            //  Let's make S9 half scale or a value of 70.  \r
-                                            double level;\r
-                                            level = GetRXAMeter(CHANNEL_RX0, smeter); \r
-                                            // Determine how high above 127 we are..making a range of 114 from S0 to S9+60db\r
-                                            // 5 is a fugdge factor that shouldn't be there - but seems to get us to S9=SM015\r
-                                            level =  abs(127+(level + (double) get_attenuation()))+5;\r
-                                         \r
-                                            // Clip the value just in case\r
-                                            if(cmd_input[2] == '0') { \r
-                                               new_level = (int) ((level * 30.0)/114.0);\r
-                                               // Do saturation check\r
-                                               if(new_level < 0) { new_level = 0; }\r
-                                               if(new_level > 30) { new_level = 30;}\r
-                                            } else { //Assume we are using sub receiver where range is 0-15\r
-                                               new_level = (int) ((level * 15.0)/114.0);\r
-                                               // Do saturation check\r
-                                               if(new_level < 0) { new_level = 0; }\r
-                                               if(new_level > 15) { new_level = 15;}\r
-                                            }\r
-                                            sprintf(msg,"SM%1c%04d;",\r
-                                                cmd_input[2],new_level);\r
-                                            send_resp(msg);\r
-                                         }   \r
-        else if(strcmp(cmd_str,"SQ")==0) {  // Set/read the squelch level\r
-                                            // P1 - 0- main, 1=sub\r
-                                            // P2 - 0-255\r
-                                             if(len <=3) {\r
-                                               sprintf(msg,"SQ%04d;",squelch);\r
-                                               send_resp(msg);\r
-                                             } else {\r
-                                                squelch = atoi(&cmd_input[2]);\r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"SR")==0) {  // Resets the transceiver\r
-                                         }\r
-        else if(strcmp(cmd_str,"SS")==0) {  // Set/read Scan pause freq\r
-                                             if(len <=2) {\r
-                                               send_resp("SS0;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"ST")==0) {  // Set/read the multi/ch control freq steps\r
-                                            // SSB/CW/FSK - values 00-03\r
-                                            // 00: 1KHz, 01: 2.5Khz 02:5KHz 03: 10Khz\r
-                                            // AM/FM mode 00-09\r
-                                            // 00: 5KHz, \r
-                                            // 01: 6.25KHz, \r
-                                            // 02:10Khz, \r
-                                            // 03: 12.5Khz,\r
-                                            // 04: 15Khz, \r
-                                            // 05: 20Khz, \r
-                                            // 06: 25KHz\r
-                                            // 07: 30Khz\r
-                                            // 08: 50Khz\r
-                                            // 09: 100Khz \r
-                                             int coded_step_val;\r
-                                             entry= (BANDSTACK_ENTRY *) \r
-                                                bandstack_entry_get_current();\r
-                                             if(len <=2) {\r
-                                                 switch(entry->mode) {\r
-                                                     case modeLSB: \r
-                                                     case modeUSB: \r
-                                                     case modeCWL: \r
-                                                     case modeCWU: \r
-                                                     case modeDIGU: \r
-                                                     case modeDIGL: \r
-                                                        if(step >0 && step <= 1000)  {\r
-                                                          coded_step_val = 0; \r
-                                                        } else if (step >1000 && step <=2500) {\r
-                                                          coded_step_val = 1; \r
-                                                        } else if (step >2500 && step <=5000) {\r
-                                                          coded_step_val = 2; \r
-                                                        } else {\r
-                                                          coded_step_val = 3; \r
-                                                        }\r
-                                                        break;\r
-                                                     case modeFMN: \r
-                                                     case modeAM:  \r
-                                                        if(step >0 && step <= 5000)  {\r
-                                                          coded_step_val = 0; \r
-                                                        } else if (step >5000 && step <=6250) {\r
-                                                          coded_step_val = 1; \r
-                                                        } else if (step >6250 && step <=10000) {\r
-                                                          coded_step_val = 2; \r
-                                                        } else if (step >10000 && step <=12500) {\r
-                                                          coded_step_val = 3; \r
-                                                        } else if (step >12500 && step <=15000) {\r
-                                                          coded_step_val = 4; \r
-                                                        } else if (step >15000 && step <=20000) {\r
-                                                          coded_step_val = 5; \r
-                                                        } else if (step >20000 && step <=25000) {\r
-                                                          coded_step_val = 6; \r
-                                                        } else if (step >25000 && step <=30000) {\r
-                                                          coded_step_val = 7; \r
-                                                        } else if (step >30000 && step <=50000) {\r
-                                                          coded_step_val = 8; \r
-                                                        } else if (step >50000 && step <=100000) {\r
-                                                          coded_step_val = 9; \r
-                                                        } else {\r
-                                                          coded_step_val = 0; \r
-                                                        }\r
-                                                        break;\r
-                                                 } \r
-                                                 sprintf(msg,"ST%02d;",coded_step_val);\r
-                                                 send_resp(msg); \r
-                                             } else {\r
-                                                 coded_step_val = atoi(&cmd_input[2]);   \r
-                                                 switch(entry->mode) {\r
-                                                     case modeLSB: \r
-                                                     case modeUSB: \r
-                                                     case modeCWL: \r
-                                                     case modeCWU: \r
-                                                     case modeDIGU: \r
-                                                     case modeDIGL: \r
-                                                        if(coded_step_val==0) { step = 1000;}\r
-                                                        if(coded_step_val==1) { step = 2500;}\r
-                                                        if(coded_step_val==2) { step = 5000;}\r
-                                                        if(coded_step_val==3) { step = 10000;}\r
-                                                        break; \r
-                                                     case modeFMN: \r
-                                                     case modeAM:  \r
-                                                         switch(coded_step_val) {\r
-                                                            case 0: step = 5000; break;\r
-                                                            case 1: step = 6250; break;\r
-                                                            case 2: step = 10000; break;\r
-                                                            case 3: step = 12500; break;\r
-                                                            case 4: step = 15000; break;\r
-                                                            case 5: step = 20000; break;\r
-                                                            case 6: step = 25000; break;\r
-                                                            case 7: step = 30000; break;\r
-                                                            case 8: step = 50000; break;\r
-                                                            case 9: step = 100000; break;\r
-                                                            default: break; // No change if not a valid number\r
-                                                         } \r
-                                                     default: break; // No change if not a valid number\r
-                                                 } \r
-                                                 g_idle_add(vfo_update,NULL);\r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"SU")==0) {  // Set/read the scan pause freq\r
-                                             if(len <=2) {\r
-                                               send_resp("SU00000000000;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"SV")==0) {  // Execute the memory transfer function\r
-                                         }\r
-        else if(strcmp(cmd_str,"TC")==0) {  // Set/read the internal TNC mode\r
-                                             if(len <=2) {\r
-                                               send_resp("TC00;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"TD")==0) {  // Sends the DTMF memory channel\r
-                                         }\r
-        else if(strcmp(cmd_str,"TI")==0) {  // Reads the TNC LED status\r
-                                             if(len <=2) {\r
-                                               send_resp("TI00;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"TN")==0) {  // Set/Read sub tone freq\r
-                                             if(len <=2) {\r
-                                               send_resp("TN00;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"TO")==0) {  // Set/Read tone function\r
-                                             if(len <=2) {\r
-                                               send_resp("TO0;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"TS")==0) {  // Set/Read TF Set function status\r
-                                             if(len <=2) {\r
-                                               send_resp("TS0;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"TX")==0) {  // Key Xmitter - P1 - transmit on main/sub freq\r
-                                            setMox(1);\r
-                                             if(len <=2) {\r
-                                               send_resp("TS0;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"TY")==0) {  // Set/Read uP firmware type\r
-                                             if(len <=2) {\r
-                                               send_resp("TY000;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"UL")==0) {  // Detects the PLL unlock status - this should never occur - xmit only\r
-                                             if(len <=2) {\r
-                                               send_resp("UL0;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"UP")==0) {  // Emulates the mic up key\r
-                                         }\r
-        else if(strcmp(cmd_str,"VD")==0) {  // Sets/Reads VOX dleay time - 0000-3000ms in steps of 150\r
-                                            // We want vox_hang variable in PiHPSDR\r
-                                            // Max value in variable in ms... so 250 = 250ms\r
-                                            #ifdef RIGCTL_DEBUG\r
-                                            fprintf(stderr,"RIGCTL: Vox hang=%0.20f\n",vox_hang);\r
-                                            #endif\r
-                                             if(len <=2) {\r
-                                               work_int = (int) vox_hang;\r
-                                               sprintf(msg,"VD%04d;",work_int); \r
-                                               send_resp(msg);\r
-                                             } else {\r
-                                                  work_int = atoi(&cmd_input[2]);\r
-                                                  // Bounds check for legal values for PiHPSDR\r
-                                                  if(work_int > 1000) { work_int = 1000; }\r
-                                                  if(work_int < 0) { work_int = 0; }\r
-                                                  vox_hang = (double) work_int;\r
-                                                  #ifdef RIGCTL_DEBUG\r
-                                                  fprintf(stderr,"RIGCTL: Vox hang=%0.20f\n",vox_hang);\r
-                                                  #endif\r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"VG")==0) {  // Sets/Reads VOX gain 000-009\r
-                                            // We want vox_threshold variable in PiHPSDR\r
-                                            // Max value in variable 0.1 \r
-                                            // 3 char 000-009 valid ranges\r
-                                            #ifdef RIGCTL_DEBUG\r
-                                            fprintf(stderr,"RIGCTL: Vox thesh=%0.20f\n",vox_threshold);\r
-                                            #endif\r
-                                             if(len <=2) {\r
-                                               work_int = (int) ((vox_threshold) * 100.0);\r
-                                               sprintf(msg,"VG00%1d;",work_int);\r
-                                               send_resp(msg);\r
-                                             } else {\r
-                                                  // Set the threshold here\r
-                                                  work_int = atoi(&cmd_input[2]);\r
-                                                  vox_threshold = ((double) work_int)/100.0;\r
-                                                  #ifdef RIGCTL_DEBUG\r
-                                                  fprintf(stderr,"RIGCTL: Vox thresh=%0.20f\n",vox_threshold);\r
-                                                  #endif\r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"VR")==0) {  // Emulates the voice 1/2 key\r
-                                         }\r
-        else if(strcmp(cmd_str,"VX")==0) {  // Sets/reads vox f(x) state\r
-                                             if(len <=2) {\r
-                                               sprintf(msg,"VX%1d;",vox_enabled); \r
-                                               send_resp(msg);\r
-                                             } else {\r
-                                               work_int = atoi(&cmd_input[2]);\r
-                                               if(work_int>1) { vox_enabled = 1; vox= 1;}\r
-                                               if(work_int<1) { vox_enabled = 0; vox=0; }\r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"XT")==0) {  // Sets/reads the XIT f(x) state\r
-                                             if(len <=2) {\r
-                                               send_resp("XT0;"); \r
-                                             }\r
-                                         }\r
-        else if(strcmp(cmd_str,"XX")==0) {  // \r
-                                            // Format RL01234: First dig 0=neg, 1=pos number\r
-                                            //                 1-4- digital offset in hertz.\r
-                                            if(len > 4) { // It is set instead of a read\r
-                                               digl_pol = (cmd_input[2]=='0') ? -1 : 1;\r
-                                               digl_offset = atoi(&cmd_input[3]); \r
-                                               #ifdef RIGCTL_DEBUG\r
-                                               fprintf(stderr,"RIGCTL:RL set %d %d\n",digl_pol,digl_offset); \r
-                                               #endif\r
-                                            } else {\r
-                                               if(digl_pol==1) { // Nah - its a read\r
-                                                 sprintf(msg,"RL1%04d;",0);\r
-                                               } else {\r
-                                                 sprintf(msg,"RL0%04d;",0);\r
-                                               }         \r
-                                               send_resp(msg);\r
-                                               #ifdef RIGCTL_DEBUG\r
-                                               fprintf(stderr,":%s\n",msg);\r
-                                               #endif\r
-                                            }\r
-                                         }\r
-        else if(strcmp(cmd_str,"XY")==0) {  // set/read RTTY DIGL offset frequency - Not available - just store values\r
-                                            // Format RL01234: First dig 0=neg, 1=pos number\r
-                                            //                 1-4- digital offset in hertz.\r
-                                            if(len > 4) { // It is set instead of a read\r
-                                               digl_pol = (cmd_input[2]=='0') ? -1 : 1;\r
-                                               digl_offset = atoi(&cmd_input[3]); \r
-                                               #ifdef RIGCTL_DEBUG\r
-                                               fprintf(stderr,"RIGCTL:RL set %d %d\n",digl_pol,digl_offset); \r
-                                               #endif\r
-                                            } else {\r
-                                               if(digl_pol==1) { // Nah - its a read\r
-                                                 sprintf(msg,"RL1%04d;",0);\r
-                                               } else {\r
-                                                 sprintf(msg,"RL0%04d;",0);\r
-                                               }         \r
-                                               send_resp(msg);\r
-                                               #ifdef RIGCTL_DEBUG\r
-                                               fprintf(stderr,":%s\n",msg);\r
-                                               #endif\r
-                                            }\r
-                                         }\r
-        else                             {\r
-                                            fprintf(stderr,"RIGCTL: UNKNOWN=%s\n",cmd_str);\r
-                                         }\r
-}\r
-//\r
-// End of Parser\r
-// \r
-/*\r
-char * rigctlGetFilter()\r
-{\r
-   \r
-    char * m = mode_string[mode];\r
-\r
-    if (strcmp(m,"CWU") == 0){\r
-       return (char *) (getFilterHigh() + getFilterLow());\r
-    }\r
-    else\r
-    if (strcmp(m,"CWL") == 0){\r
-       return (char *) (getFilterHigh() + getFilterLow());\r
-    }\r
-    else\r
-    return (char *) (getFilterHigh() - getFilterLow());\r
-}\r
-*/\r
-\r
-void launch_rigctl () {\r
-   int err;\r
-   fprintf(stderr, "LAUNCHING RIGCTL!!\n");\r
-   // This routine encapsulates the pthread call\r
-   err = pthread_create (&rigctl_thread_id,NULL,rigctl,NULL);\r
-   if(err != 0) {\r
-       fprintf(stderr, "pthread_create failed on rigctl launch\n");\r
-   }  \r
-}\r
-\r
-//\r
-// Telnet Server Code below:\r
-//\r
-    // max number of bytes we can get at once\r
-    #define MAXDATASIZE 300\r
-\r
-int init_server () {\r
-\r
-    //Create socket\r
-    socket_desc = socket(AF_INET , SOCK_STREAM , 0);\r
-    if (socket_desc == -1)\r
-    {\r
-        fprintf(stderr,"RIGCTL: Could not create socket");\r
-    }\r
-    fprintf(stderr, "RIGCTL: Socket created\n");\r
-     \r
-    //Prepare the sockaddr_in structure\r
-    server.sin_family = AF_INET;\r
-    server.sin_addr.s_addr = INADDR_ANY;\r
-    server.sin_port = htons( TELNET_PORT );\r
-     \r
-    //Bind\r
-    if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)\r
-    {\r
-        //print the error message\r
-        fprintf(stderr,"RIGCLT: bind failed. Error\n");\r
-        return 1;\r
-    }\r
-    fprintf(stderr,"RIGCTL: bind done\n");\r
-     \r
-    //Listen\r
-    listen(socket_desc , 3);\r
-     \r
-    //Accept and incoming connection\r
-    fprintf(stderr,"RIGCTL: Waiting for incoming connections...\n");\r
-    c = sizeof(struct sockaddr_in);\r
-     \r
-    //accept connection from an incoming client\r
-    client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);\r
-    if (client_sock < 0)\r
-    {\r
-        fprintf(stderr,"RIGCTL: Accept failed\n");\r
-        return 1;\r
-    }\r
-    fprintf(stderr,"RIGCTL: Connection accepted\n");\r
-}\r
-/*\r
-int rigctlGetFilterLow() {\r
-   int lookup;\r
-   int rval;\r
-\r
-   BANDSTACK_ENTRY *entry;\r
-   entry = (BANDSTACK_ENTRY *) bandstack_entry_get_current();\r
-\r
-   FILTER* band_filters=filters[entry->mode];\r
-   FILTER* band_filter=&band_filters[entry->filter];\r
-   rval = 0;\r
-   for(lookup = 0; lookup<=9; lookup++) {\r
-      if(band_filter[lookup].low == -150) {\r
-          rval = lookup;\r
-          break;\r
-      }      \r
-   }\r
-   return rval;\r
-}\r
-\r
-int rigctlGetFilterHigh() {\r
-   int lookup;\r
-   int rval;\r
-\r
-   BANDSTACK_ENTRY *entry;\r
-   entry = (BANDSTACK_ENTRY *) bandstack_entry_get_current();\r
-\r
-   FILTER* band_filters=filters[entry->mode];\r
-   FILTER* band_filter=&band_filters[entry->filter];\r
-   rval = 0;\r
-   for(lookup = 0; lookup<=9; lookup++) {\r
-      if(band_filter[lookup].high == -150) {\r
-          rval = lookup;\r
-          break;\r
-      }      \r
-   }\r
-   return rval;\r
-}\r
-*/\r
-int rigctlGetMode()  {\r
-        BANDSTACK_ENTRY *entry;\r
-        entry= (BANDSTACK_ENTRY *) \r
-        bandstack_entry_get_current();\r
-        switch(entry->mode) {\r
-           case modeLSB: return(1); // LSB\r
-           case modeUSB: return(2); // USB\r
-           case modeCWL: return(7); // CWL\r
-           case modeCWU: return(3); // CWU\r
-           case modeFMN: return(4); // FMN\r
-           case modeAM:  return(5); // AM\r
-           case modeDIGU: return(9); // DIGU\r
-           case modeDIGL: return(6); // DIGL\r
-           default: return(0);\r
-        }\r
-}\r
-\r
-int rigctlSetFilterLow(int val){\r
-};\r
-int rigctlSetFilterHigh(int val){\r
-};\r
-\r
-void set_band(long long new_freqA) {      \r
-\r
-   BANDSTACK_ENTRY *entry;\r
-   int b = get_band_from_frequency(new_freqA);\r
-   if(b == -1) { // Out of ham bands...\r
-      setFrequency(new_freqA);\r
-      g_idle_add(vfo_update,NULL);\r
-      return;\r
-   }   \r
-\r
-   if(b==band_get_current()) {\r
-      entry = bandstack_entry_next(); \r
-      setFrequency(new_freqA);\r
-      g_idle_add(vfo_update,NULL);\r
-      return;\r
-   } else {\r
-    BAND* band=band_set_current(b);\r
-    entry=bandstack_entry_get_current();\r
-   }\r
-  setMode(entry->mode);\r
-  FILTER* band_filters=filters[entry->mode];\r
-  FILTER* band_filter=&band_filters[entry->filter];\r
-  setFilter(band_filter->low,band_filter->high);\r
-  setFrequency(new_freqA);\r
-\r
-  BAND *band=band_get_current_band();\r
-  set_alex_rx_antenna(band->alexRxAntenna);\r
-  set_alex_tx_antenna(band->alexTxAntenna);\r
-  set_alex_attenuation(band->alexAttenuation);\r
-\r
-  setFrequency(new_freqA);\r
-  g_idle_add(vfo_update,NULL);\r
-\r
-\r
-  calcDriveLevel();\r
-  calcTuneDriveLevel();\r
-}\r
+
+/* TS-2000 emulation via TCP
+ * Copyright (C) 2016 Steve Wilson <wevets@gmail.com>
+ * 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 2 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/>.
+ */
+
+/*
+ * PiHPSDR RigCtl by Steve KA6S Oct 16 2016
+ * With a kindly assist from Jae, K5JAE who has helped
+ * greatly with hamlib integration!
+ */
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <unistd.h>
+//#include <semaphore.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "toolbar.h"
+#include "sliders.h"
+#include "rigctl.h"
+#include "radio.h"
+#include "receiver.h"
+#include "channel.h"
+#include "filter.h"
+#include <string.h>
+#include "mode.h"
+#include "filter.h"
+#include "band.h"
+#include "bandstack.h"
+#include "vfo.h"
+#include "sliders.h"
+#include <pthread.h>
+#include "agc.h"
+#include <wdsp.h>
+#include "store.h"
+
+// IP stuff below
+#include <sys/socket.h>
+#include <arpa/inet.h> //inet_addr
+
+//#undef RIGCTL_DEBUG
+#define RIGCTL_DEBUG
+
+// the port client will be connecting to
+// 2-26-17 K5JAE - Changed the defines to const ints to allow use via pointers.
+static const int TelnetPortA = 19090;
+static const int TelnetPortB = 19091;
+static const int TelnetPortC = 19092;
+
+// max number of bytes we can get at once
+#define MAXDATASIZE 300
+
+int init_server ();
+void parse_cmd ();
+
+int rigctlGetFilterLow();
+int rigctlGetFilterHigh();
+int rigctlSetFilterLow(int val);
+int rigctlSetFilterHigh(int val);
+int new_level;
+int active_transmitter = 0;
+
+int cat_control;
+
+extern int enable_tx_equalizer;
+
+/*
+pthread_mutex_t mutex_a = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t mutex_b = PTHREAD_MUTEX_INITIALIZER;
+*/
+typedef struct {GMutex m; } GT_MUTEX;
+GT_MUTEX * mutex_a;
+GT_MUTEX * mutex_b;
+
+FILE * out;
+int  output;
+FILTER * band_filter;
+
+//static pthread_t rigctl_a_thread_id, rigctl_b_thread_id, rigctl_c_thread_id;
+static GThread *rigctl_a_thread_id, *rigctl_b_thread_id, *rigctl_c_thread_id;
+
+int squelch=100; //local sim of squelch level
+
+
+int read_size;
+
+int freq_flag;  // Determines if we are in the middle of receiving frequency info
+
+int digl_offset = 0;
+int digl_pol = 0;
+int digu_offset = 0;
+int digu_pol = 0;
+double new_vol = 0;
+int  lcl_cmd=0;
+long long new_freqA = 0;
+long long new_freqB = 0;
+long long orig_freqA = 0;
+long long orig_freqB = 0;
+int  lcl_split = 0;
+int  mox_state = 0;
+// Radio functions - 
+// Memory channel stuff and things that aren't 
+// implemented - but here for a more complete emulation
+int ctcss_tone;  // Numbers 01-38 are legal values - set by CN command, read by CT command
+int ctcss_mode;  // Numbers 0/1 - on off.
+
+int vfo_sm=0;   // VFO State Machine - this keeps track of
+
+// Now my stuff
+//
+
+// This looks up the frequency of the Active receiver with 
+// protection for 1 versus 2 receivers
+long long rigctl_getFrequency() {
+   if(receivers == 1) {
+      return vfo[VFO_A].frequency;
+   } else {
+      return vfo[active_receiver->id].frequency;
+   } 
+}
+// Looks up entry INDEX_NUM in the command structure and
+// returns the command string
+//
+void send_resp (int client_sock,char * msg) {
+    #ifdef  RIGCTL_DEBUG
+        fprintf(stderr,"RIGCTL: RESP=%s\n",msg);
+    #endif
+    write(client_sock, msg, strlen(msg));
+}
+
+//
+// 2-25-17 - K5JAE - removed duplicate rigctl
+//
+
+//static void * rigctl_a (void * arg) {
+static gpointer rigctl (gpointer data) {
+   int len;
+   int c;
+   int socket_desc; 
+   struct sockaddr_in client;
+   struct sockaddr_in server;
+
+   // user data void* is really an int* of the port
+   int port = *((int*) data);
+   int client_sock = init_server(&socket_desc, &client, &server, port);
+
+   g_mutex_lock(&mutex_a->m);
+   cat_control++;
+//#ifdef RIGCTL_DEBUG
+fprintf(stderr,"RIGCTL: CTLA INC cat_contro=%d\n",cat_control);
+//#endif
+   g_mutex_unlock(&mutex_a->m);
+   g_idle_add(vfo_update,NULL);
+
+   int save_flag = 0; // Used to concatenate two cmd lines together
+   int semi_number = 0;
+   int i;
+   char * work_ptr;
+   char work_buf[MAXDATASIZE];
+   int numbytes;
+   char  cmd_input[MAXDATASIZE] ;
+   char cmd_save[80];
+
+  for(;;) {
+    fprintf(stderr,"RIGCTL - New run on server port: %d\n", port);
+    while((numbytes=recv(client_sock , cmd_input , MAXDATASIZE-2 , 0)) > 0 ) {
+         for(i=0;i<numbytes;i++)  { work_buf[i] = cmd_input[i]; }
+         work_buf[i+1] = '\0';
+         #ifdef RIGCTL_DEBUG
+         fprintf(stderr,"RIGCTL: RCVD=%s<-\n",work_buf);
+         #endif
+
+        // Need to handle two cases
+        // 1. Command is short, i.e. no semicolon - that will set save_flag=1 and
+        //    read another line..
+        // 2. 1 to N commands per line. Turns out N1MM sends multiple commands per line
+         
+        if(save_flag == 0) { // Count the number of semicolons if we aren't already in mode 1.
+          semi_number = 0;
+          for(i=0;i<numbytes;i++) {
+             if(cmd_input[i] == ';') { semi_number++;};
+          } 
+        }
+        if((save_flag == 0) && (semi_number == 0)) {
+           cmd_input[numbytes] = '\0';      // Turn it into a C string
+           strcpy(cmd_save,cmd_input);      // And save a copy of it till next time through
+           save_flag = 1;
+        } else if(save_flag == 1) {
+           save_flag = 0;
+           cmd_input[numbytes] = '\0';      // Turn it into a C string
+           strcat(cmd_save,cmd_input);
+           strcpy(cmd_input,cmd_save);      // Cat them together and replace cmd_input
+           numbytes = strlen(cmd_input);
+        } 
+        if(save_flag != 1) {
+           work_ptr = strtok(cmd_input,";");
+           while(work_ptr != NULL) {
+               /*
+               pthread_mutex_lock (& mutex_b);
+               */
+               g_mutex_lock(&mutex_b->m);
+               parse_cmd(work_ptr,strlen(work_ptr),client_sock);
+               /*
+               pthread_mutex_unlock (& mutex_b);
+               */
+               g_mutex_unlock(&mutex_b->m);
+               work_ptr = strtok(NULL,";");
+           }
+           for(i=0;i<MAXDATASIZE;i++){
+                cmd_input[i] = '\0'; 
+                work_buf[i]  = '\0';  // Clear the input buffer
+           }
+        }
+       // Got here because socket closed 
+    }
+    if(numbytes == 0) {
+         fprintf(stderr,"RIGCTL: Client disconnected\n");
+         close(client_sock);
+
+         // Decrement CAT_CONTROL
+         g_mutex_lock(&mutex_a->m);
+         cat_control--;
+#ifdef RIGCTL_DEBUG
+fprintf(stderr,"RIGCTL: CTLA DEC - cat_control=%d\n",cat_control);
+#endif
+         g_mutex_unlock(&mutex_a->m);
+         g_idle_add(vfo_update,NULL);
+
+         //sleep(1);
+         c = sizeof(struct sockaddr_in);
+         client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);
+
+         // Increment CAT_CONTROL
+         g_mutex_lock(&mutex_a->m);
+         cat_control++;
+#ifdef RIGCTL_DEBUG
+fprintf(stderr,"RIGCTL: CTLA INC - cat_control=%d\n",cat_control);
+#endif
+         g_mutex_unlock(&mutex_a->m);
+         g_idle_add(vfo_update,NULL);
+
+         //sleep(1);
+    }
+ }
+}
+
+// 
+// FT command intepret vfo_sm state - used by IF command
+//
+int ft_read() {
+   return(active_transmitter);
+}
+// 
+// Determines RIT state - used by IF command
+//
+int rit_on () {
+  if(receivers == 1) { // Worry about 1 versus 2 radios
+      if(vfo[VFO_A].rit != 0) {
+         return 1;
+      } else {
+         return 0;
+      }  
+  } else { // Well - we have two so use active_reciever->id
+      if(vfo[active_receiver->id].rit != 0) {
+          return 1 ;
+      } else {
+          return 0;
+      }
+  }
+}
+void parse_cmd ( char * cmd_input,int len,int client_sock) {
+        int work_int;     
+        int new_low, new_high;
+        double meter;
+        char msg[80];
+        char buf[80];
+        BANDSTACK_ENTRY *entry;
+        // Parse the cmd_input
+        //int space = command.indexOf(' ');
+        //char cmd_char = com_head->cmd_string[0]; // Assume the command is first thing!
+        char cmd_str[3];
+        cmd_str[0] = cmd_input[0];
+        cmd_str[1] = cmd_input[1];
+        cmd_str[2] = '\0';
+        if(strcmp(cmd_str,"AC")==0)       { // Sets or reads the internal antenna tuner status
+                                                   // P1 0:RX-AT Thru, 1: RX-AT IN
+                                                   // P2 0: TX-AT Thru 1: TX-AT In
+                                                   // 
+                                             if(len <= 2) {
+                                               send_resp(client_sock,"AC000;");
+                                             }
+                                          }
+        else if(strcmp(cmd_str,"AG")==0) {  // Set Audio Gain - 
+                                            // AG123; Value of 0-
+                                            // AG1 = Sub receiver - what is the value set
+                                            // Response - AG<0/1>123; Where 123 is 0-260
+                                            int lcl_receiver;
+                                            if(receivers == 1) {
+                                                lcl_receiver = 0;
+                                            } else {
+                                                lcl_receiver = active_receiver->id;
+                                            }
+                                            if(len>4) { // Set Audio Gain
+                                               active_receiver->volume = (double) atoi(&cmd_input[3])/260; 
+                                               g_idle_add(update_af_gain,NULL);               
+                                            } else { // Read Audio Gain
+                                              sprintf(msg,"AG%1d%03d;",lcl_receiver,(int) (2.6 * active_receiver->volume));
+                                              send_resp(client_sock,msg);
+                                            }
+                                          }
+        else if(strcmp(cmd_str,"AI")==0)  {  // Allow rebroadcast of set frequency after set - not supported
+                                             if(len <=2) {
+                                                //send_resp(client_sock,"AI0;");
+                                                send_resp(client_sock,"?;");
+                                             } 
+                                          }
+        else if(strcmp(cmd_str,"AL")==0)  {  // Set/Reads the auto Notch level 
+                                             if(len <=2) {
+                                                //send_resp(client_sock,"AL000;");
+                                                send_resp(client_sock,"?;");
+                                             } 
+                                          }
+        else if(strcmp(cmd_str,"AM")==0)  {  // Sets or reads the Auto Mode
+                                             if(len <=2) {
+                                                //send_resp(client_sock,"AM0;");
+                                                send_resp(client_sock,"?;");
+                                             } 
+                                          }
+        else if(strcmp(cmd_str,"AN")==0)  {  // Selects the antenna connector (ANT1/2)
+                                             if(len <=2) {
+                                                //send_resp(client_sock,"AN0;");
+                                                send_resp(client_sock,"?;");
+                                             } 
+                                          }
+        else if(strcmp(cmd_str,"AR")==0)  {  // Sets or reads the ASC function on/off
+                                             if(len <=2) {
+                                                //send_resp(client_sock,"AR0;");
+                                                send_resp(client_sock,"?;");
+                                             } 
+                                          }
+        else if(strcmp(cmd_str,"AS")==0)  {  // Sets/reads automode function parameters
+                                             // AS<P1><2xP2><11P3><P4>;
+                                             // AS<P1><2xP2><11P3><P4>;
+                                             if(len < 6) {  
+                                             /*   sprintf(msg,"AS%1d%02d%011lld%01d;",
+                                                             0, // P1
+                                                             0, // Automode 
+                                                             getFrequency(),
+                                                             rigctlGetMode());
+                                                send_resp(client_sock,msg);*/
+                                                send_resp(client_sock,"?;");
+                               
+                                             } 
+                                          }
+        else if(strcmp(cmd_str,"BC")==0)  {  // Beat Cancellor OFF
+                                             if(len <=2) {
+                                                //send_resp(client_sock,"BC0;");
+                                                send_resp(client_sock,"?;");
+                                             } 
+                                          }
+        else if(strcmp(cmd_str,"BD")==0)  {  // Moves down the frequency band
+                                             // No response 
+                                          }
+        else if(strcmp(cmd_str,"BP")==0)  {  // Reads the manual beat canceller frequency setting
+                                             if(len <=2) {
+                                                //send_resp(client_sock,"BP000;");
+                                                send_resp(client_sock,"?;");
+                                             } 
+                                          }
+        else if(strcmp(cmd_str,"BS")==0)  {  // Sets or reads Beat Canceller status
+                                             if(len <=2) {
+                                                //send_resp(client_sock,"BS0;");
+                                                send_resp(client_sock,"?;");
+                                             } 
+                                          }
+        else if(strcmp(cmd_str,"BU")==0)  {  // Moves Up the frequency band
+                                             // No response 
+                                          }
+        else if(strcmp(cmd_str,"BY")==0)  {  // Read the busy signal status
+                                             if(len <=2) {
+                                                //send_resp(client_sock,"BY00;");
+                                                send_resp(client_sock,"?;");
+                                             } 
+                                          }
+        else if(strcmp(cmd_str,"CA")==0)  {  // Sets/reads cw auto tune function status
+                                             if(len <=2) {
+                                                //send_resp(client_sock,"CA0;");
+                                                send_resp(client_sock,"?;");
+                                             } 
+                                          }
+        else if(strcmp(cmd_str,"CG")==0)  {  // Sets/reads the carrier gain status
+                                             // 0-100 legal values
+                                             if(len <=2) {
+                                                //send_resp(client_sock,"CG000;");
+                                                send_resp(client_sock,"?;");
+                                             } 
+                                          }
+        else if(strcmp(cmd_str,"CH")==0)  {  // Sets the current frequency to call Channel
+                                             // No response
+                                          }
+        else if(strcmp(cmd_str,"CI")==0)  {  // While in VFO mode or memory recall mode, sets freq to the call channel
+                                             // No response
+                                          }
+        else if(strcmp(cmd_str,"CM")==0)  {  // Sets or reads the packet cluster tune f(x) on/off
+                                             // 0-100 legal values
+                                             if(len <=2) {
+                                                //send_resp(client_sock,"CM0;");
+                                                send_resp(client_sock,"?;");
+                                             } 
+                                          }
+        else if(strcmp(cmd_str,"CN")==0)  {  // Sets and reads CTSS function - 01-38 legal values
+                                             // Stored locally in rigctl - not used.
+                                             if(len <=2) {
+                                                sprintf(msg,"CN%02d;",ctcss_tone);
+                                                send_resp(client_sock,msg);
+                                                send_resp(client_sock,"?;");
+                                             } else {
+                                                ctcss_tone = atoi(&cmd_input[2]);
+                                             }
+                                          }
+        else if(strcmp(cmd_str,"CT")==0)  {  // Sets and reads CTSS function status
+                                             // Stored locally in rigctl - not used.
+                                             if(len <=2) {
+                                                sprintf(msg,"CT%01d;",ctcss_mode);
+                                                send_resp(client_sock,msg);
+                                             } else {
+                                                ctcss_mode = atoi(&cmd_input[2]);
+                                             }
+                                          }
+        else if(strcmp(cmd_str,"DC")==0)  {  // Sets/Reads TX band status
+                                             if(len <=2) {
+                                                //send_resp(client_sock,"DC00;");
+                                                send_resp(client_sock,"?;");
+                                             } 
+                                          }
+        else if(strcmp(cmd_str,"DN")==0)  {  // Emulate Mic down key 
+                                          }
+        else if(strcmp(cmd_str,"DQ")==0)  {  // ETs/and reads the DCS function status
+                                             if(len <=2) {
+                                                //send_resp(client_sock,"DQ0;");
+                                                send_resp(client_sock,"?;");
+                                             } 
+                                          }
+        else if(strcmp(cmd_str,"EX")==0)  {  // Set/reads the extension menu
+                                             // This routine only can look up specific information;
+                                             // And only performs reads at this point..
+                                             // EX P1 P1 P1 P2 P2 P3 P4 ; - Read command                                      
+                                             int p5=0;
+                                             strncpy(buf,cmd_input,9); // Get the front of the response
+                                             if(len == 10) {  // Read command                                                
+                                                 // CW Sidetone frequendcy
+                                                 if(strncmp(&cmd_input[2],"031",3) == 0) {
+                                                   if(cw_keyer_sidetone_frequency <=400) {
+                                                     p5 = 0; 
+                                                   } else if (cw_keyer_sidetone_frequency <=450) {
+                                                     p5 = 1; 
+                                                   } else if (cw_keyer_sidetone_frequency <=500) {
+                                                     p5 = 2; 
+                                                   } else if (cw_keyer_sidetone_frequency <=550) {
+                                                     p5 = 3; 
+                                                   } else if (cw_keyer_sidetone_frequency <=600) {
+                                                     p5 = 4; 
+                                                   } else if (cw_keyer_sidetone_frequency <=650) {
+                                                     p5 = 5; 
+                                                   } else if (cw_keyer_sidetone_frequency <=700) {
+                                                     p5 = 6; 
+                                                   } else if (cw_keyer_sidetone_frequency <=750) {
+                                                     p5 = 7; 
+                                                   } else if (cw_keyer_sidetone_frequency <=800) {
+                                                     p5 = 8; 
+                                                   } else if (cw_keyer_sidetone_frequency <=850) {
+                                                     p5 = 9; 
+                                                   }     
+                                                   sprintf(msg,"%s%01d;",buf,p5); 
+                                                   send_resp(client_sock,msg);
+                                                  // SPLIT
+                                                 } else if(strncmp(&cmd_input[2],"06A",3) == 0) {
+                                                   sprintf(msg,"%s%01d;",buf,split); 
+                                                   send_resp(client_sock,msg);
+                                                } else  { 
+                                                   send_resp(client_sock,"?;");
+                                                }
+                                            }
+                                          }
+        else if(strcmp(cmd_str,"FA")==0) {  // VFO A frequency
+                                            // LEN=7 - set frequency
+                                            // Next data will be rest of freq
+                                            if(len == 13) { //We are receiving freq info
+                                               new_freqA = atoll(&cmd_input[2]);
+                                               set_band(new_freqA,(int)-1);
+                                               //setFrequency(new_freqA);
+                                               //g_idle_add(vfo_update,NULL);
+                                            } else {
+                                               if(len==2) {
+                                                  //sprintf(msg,"FA%011lld;",getFrequency());
+                                                  sprintf(msg,"FA%011lld;",vfo[VFO_A].frequency);
+                                                  send_resp(client_sock,msg);
+                                               }
+                                            }
+                                         }
+        else if(strcmp(cmd_str,"FB")==0) {  // VFO B frequency
+                                            if(len==13) { //We are receiving freq info
+                                               new_freqB = atoll(&cmd_input[2]); 
+                                               set_freqB(new_freqB);
+                                               //setFrequency(new_freqA);
+                                               //g_idle_add(vfo_update,NULL);
+                                            } else if(len == 2) {
+                                               sprintf(msg,"FB%011lld;",vfo[VFO_B].frequency);
+                                               send_resp(client_sock,msg);
+                                            }
+                                         }
+        /* Not supported */
+        else if(strcmp(cmd_str,"FC")==0) {  // Set Sub receiver freq
+                                            // LEN=7 - set frequency
+                                            // Next data will be rest of freq
+                                            // Len<7 - frequency?
+                                            if(len>4) { //We are receiving freq info
+                                               long long new_freqA = atoll(&cmd_input[2]);              
+                                               //setFrequency(new_freqA);
+                                            } else {
+                                               sprintf(msg,"FC%011lld;",rigctl_getFrequency());
+                                               send_resp(client_sock,"?;");
+                                            }
+                                         }
+        else if(strcmp(cmd_str,"FD")==0)  {  // Read the filter display dot pattern
+                                              send_resp(client_sock,"FD00000000;");
+                                          }
+        else if(strcmp(cmd_str,"FR")==0)  {  // Set/reads the extension menu
+                                             if(len <=2) {
+                                                if(receivers == 1) {
+                                                   sprintf(msg,"FR0;");
+                                                } else {
+                                                   sprintf(msg,"FR%1d;",active_receiver->id);
+                                                }
+                                                send_resp(client_sock,msg); 
+                                             }  else if (receivers != 1)  {
+                                                 lcl_cmd = atoi(&cmd_input[2]);                
+                                                 if(active_transmitter != lcl_cmd) {
+                                                     split = 1;
+                                                 } 
+                                                 if(active_receiver->id != lcl_cmd) {
+                                                    //active_receiver->id = lcl_cmd; 
+                                                    active_receiver = receiver[lcl_cmd];
+                                                    g_idle_add(vfo_update,NULL);
+                                                    g_idle_add(active_receiver_changed,NULL);
+                                                 } 
+                                             }
+                                          }
+        else if(strcmp(cmd_str,"FS")==0)  {  // Set/reads fine funct status
+                                             if(len <=2) {
+                                                send_resp(client_sock,"FS0;");
+                                             } 
+                                          }
+        else if(strcmp(cmd_str,"FT")==0)  { // Sel or reads the transmitters VFO, M, ch or Call comm   
+                                             if(len <=2) {
+                                                   sprintf(msg,"FT%1d",active_transmitter);
+                                                   send_resp(client_sock,msg); 
+                                             } else {
+                                                 lcl_cmd = atoi(&cmd_input[2]);                
+                                                 if(lcl_cmd != active_receiver->id) {
+                                                     split = 1;
+                                                 } else {
+                                                     split = 0;
+                                                 }
+                                                 active_transmitter = lcl_cmd;
+                                                 g_idle_add(vfo_update,NULL);
+                                             } 
+                                          }  
+        else if(strcmp(cmd_str,"FW")==0)  { // Sets/Reas DSP receive filter width in hz 0-9999hz 
+                                             // CW - legal values  50  80  100 150 200 300 400 500 600 1000 2000
+                                             //      PiHPSDR map   50  100 100 100 250 250 400 500 600 1000
+                                             //                    25                                   750
+                                             entry= (BANDSTACK_ENTRY *) 
+                                                         bandstack_entry_get_current();
+                                             FILTER* band_filters=filters[entry->mode];
+                                             FILTER* band_filter=&band_filters[entry->filter];
+                                             if(len <=2) {
+                                                // CW filter high and low are always the same and the filter value is 2*filter val
+                                                int filter_val = band_filter->high * 2;
+                                                switch(filter_val) {
+                                                 case 25:  
+                                                 case 50:
+                                                        work_int = 50;
+                                                        break;
+                                                 case 100:
+                                                        work_int = 100; 
+                                                        break;
+                                                 case 250:
+                                                        work_int = 300; 
+                                                        break;
+                                                 case 400:
+                                                        work_int = 400; 
+                                                        break;
+                                                 case 500:
+                                                        work_int = 500; 
+                                                        break;
+                                                 case 600:
+                                                        work_int = 600; 
+                                                        break;
+                                                 case 750:
+                                                        work_int = 1000; 
+                                                        break;
+                                                 case 800:
+                                                        work_int = 1000; 
+                                                        break;
+                                                 case 1000:
+                                                        work_int = 1000; 
+                                                        break;
+                                                 default: work_int = 500; 
+                                                        break;
+                                                } 
+                                                sprintf(msg,"FW%04d;",work_int);
+                                                #ifdef  RIGCTL_DEBUG
+                                                    fprintf(stderr,"RIGCTL: FW Filter Act=%d work_int=%d\n",band_filter->high,work_int);
+                                                #endif
+                                                send_resp(client_sock,msg);
+                                             } else {
+                                               // Try to set filters here!
+                                               // CW - legal values  50  80  100 150 200 300 400 500 600 1000 2000
+                                               //      PiHPSDR map   50  100 100 100 250 250 400 500 600 1000
+                                               //                    25                                   750
+                                               work_int = atoi(&cmd_input[2]);
+                                               switch (work_int) {
+
+                                                    case 50:  new_low = 25; new_high = 25; break;
+                                                    case 80:  new_low = 50; new_high = 50; break;
+                                                    case 100:  new_low = 50; new_high = 50; break;
+                                                    case 150:  new_low = 50; new_high = 50; break;
+                                                    case 200:  new_low = 125; new_high = 125; break;
+                                                    case 300:  new_low = 125; new_high = 125; break;
+                                                    case 400:  new_low = 200; new_high = 200; break;
+                                                    case 500:  new_low = 250; new_high = 250; break;
+                                                    case 600:  new_low = 300; new_high = 300; break;
+                                                    case 1000:  new_low = 500; new_high = 500; break;
+                                                    case 2000:  new_low = 500; new_high = 500; break;
+                                                    default: new_low  = band_filter->low;
+                                                             new_high = band_filter->high;
+
+                                               }
+                                               #ifdef  RIGCTL_DEBUG
+                                                   fprintf(stderr,"RIGCTL: FW Filter new_low=%d new_high=%d\n",new_low,new_high);
+                                               #endif
+                                               // entry->filter = new_low * 2 ;
+                                               //setFilter(new_low,new_high);
+                                               set_filter(active_receiver,new_low,new_high);
+                                               g_idle_add(vfo_update,NULL);
+                                             }
+                                          }  
+        else if(strcmp(cmd_str,"GT")==0)  { // Sets/Read AGC constant status 000-020
+                                            // Map 000 - Off, 001-4 - Fast, 4-9 - Medium 10-14 Slow 15-20 Long
+                                             //fprintf(stderr,"GT command seen\n");
+                                             int agc_resp = 0;
+                                             if(len <=2) {
+                                                
+                                                switch(active_receiver->agc) {
+                                                   case AGC_OFF :   agc_resp = 0; break;
+                                                   case AGC_FAST:   agc_resp = 5; break;
+                                                   case AGC_MEDIUM: agc_resp = 10; break;
+                                                   case AGC_SLOW:   agc_resp = 15; break;
+                                                   case AGC_LONG:   agc_resp = 20; break;
+                                                   default: agc_resp = 0;
+                                                }
+                                               
+                                                sprintf(msg,"GT%03d;",agc_resp);
+                                                send_resp(client_sock,msg);
+                                             } else {
+                                                //fprintf(stderr,"GT command Set\n");
+                                                agc_resp = atoi(&cmd_input[2]);
+                                                
+                                                // AGC powers of 84 is broken Hamlib... 
+                                                // Hamlib TS-2000 is broken here
+                    
+                                                if(agc_resp == 0) {
+                                                   active_receiver->agc = AGC_OFF;
+                                                } else if(agc_resp >0 && agc_resp <= 5 || (agc_resp == 84)) {
+                                                   active_receiver->agc = AGC_FAST;
+                                                  //  fprintf(stderr,"GT command FAST\n");
+                                                } else if(agc_resp >6 && agc_resp <= 10 || (agc_resp == 2*84)) {
+                                                   active_receiver->agc = AGC_MEDIUM;
+                                                  // fprintf(stderr,"GT command MED\n");
+                                                } else if(agc_resp >11 && agc_resp <= 15 || (agc_resp == 3*84)) {
+                                                   active_receiver->agc = AGC_SLOW;
+                                                   //fprintf(stderr,"GT command SLOW\n");
+                                                } else if(agc_resp >16 && agc_resp <= 20 || (agc_resp == 4*84)) {
+                                                   active_receiver->agc = AGC_LONG;
+                                                   // fprintf(stderr,"GT command LONG\n");
+                                                }
+                                                g_idle_add(vfo_update,NULL);
+
+                                             }
+                                          }  
+        else if(strcmp(cmd_str,"ID")==0)  { // Read ID - Default to TS-2000 which is type 019.
+                                            sprintf(msg,"ID019;");
+                                            send_resp(client_sock,msg);
+                                          }
+        else if(strcmp(cmd_str,"IF")==0) {  // Reads Transceiver status
+                                            // IF
+                                            //  P1: FFFFFFFFFFF -11 chars : Frequency in Hz (blanks are "0")
+                                            //  P2: OFFS        - 4 chars : Offset in powers of 10
+                                            //  P3: RITXIT      - 6 chars : RIT/XIT Frequency, Not supported = "000000"
+                                            //  P4: R           - 1 char  : RIT Status "1"= On, "0"= off
+                                            //  P5: X           - 1 char  : XIT Status "1"= On, "0"= off
+                                            //  P6: 0           - 1 char  : Channel Bank number - not used (see MC command)
+                                            //  P7: 00          - 2 chars : Channel Bank number - not used
+                                            //  P8: C           - 1 char  : Mox Status "1"= TX, "0"= RX
+                                            //  P9: M           - 1 char  : Operating mode (see MD command)
+                                            // P10: V           - 1 char  : VFO Split status - not supported
+                                            // P11: 0           - 1 char  : Scan status - not supported
+                                            // P12: A           - 1 char  : same as FT command
+                                            // P13: 0           - 1 char  : CTCSS tone - not used
+                                            // P14: 00          - 2 chars : More tone control
+                                            // P15: 0           - 1 char  : Shift status
+
+                                            // convert first half of the msg
+                                                      // IF     P1    P2  P3  P4  P5  P6
+                                            sprintf(msg,"IF%011lld%04lld%06d%01d%01d%01d",
+                                                         //getFrequency(),
+                                                         rigctl_getFrequency(), // P1
+                                                         step,  // P2
+                                                         vfo[active_receiver->id].rit,  // P3
+                                                         rit_on(), // P4
+                                                         rit_on(), // P5
+                                                         0  // P6
+                                                         );
+
+                                            // convert second half of the msg
+                                                         //   P7  P8  P9 P10 P11 P12 P13 P14 P15;
+                                            sprintf(msg+26,"%02d%01d%01d%01d%01d%01d%01d%02d%01d;",
+                                                         0,  // P7
+                                                         mox,  // P8
+                                                         rigctlGetMode(),  // P9
+                                                         0,  // P10
+                                                         0,  // P11
+                                                         ft_read(), // P12
+                                                         ctcss_tone,  // P13
+                                                         0,  // P14
+                                                         0); // P15
+                                            send_resp(client_sock,msg);
+                                         }
+        else if(strcmp(cmd_str,"IS")==0)  { // Sets/Reas IF shift funct status
+                                             if(len <=2) {
+                                                send_resp(client_sock,"IS00000;");
+                                             } 
+                                          }  
+        else if(strcmp(cmd_str,"KS")==0)  { // Sets/Reads keying freq - 0-060 max
+                                             if(len <=2) {
+                                                sprintf(msg,"KS%03d;",cw_keyer_speed);
+                                                send_resp(client_sock,msg);
+                                             } else {
+                                                int key_speed;
+                                                key_speed = atoi(&cmd_input[2]);
+                                                if(key_speed >1 && key_speed <= 60) {
+                                                   cw_keyer_speed=key_speed;
+                                                   g_idle_add(vfo_update,NULL);
+                                                } 
+                                            }
+                                          }  
+        else if(strcmp(cmd_str,"KY")==0)  { // Convert char to morse code
+                                             if(len <=2) {
+                                                send_resp(client_sock,"KY0;");
+                                             } 
+                                          }  
+        else if(strcmp(cmd_str,"LK")==0)  { // Set/read key lock function status
+                                             if(len <=2) {
+                                                sprintf(msg,"LK%01d%01d;",locked,locked);
+                                                send_resp(client_sock,msg);
+                                             }  else {
+                                                  if(cmd_input[3] == '0') {
+                                                      locked = 0;
+                                                  } else if(cmd_input[3] == '1') {
+                                                      locked = 1;
+                                                  }
+                                                  g_idle_add(vfo_update,NULL);
+                                             }
+                                          }  
+        else if(strcmp(cmd_str,"LM")==0)  { // Set/read DRU 3A unit or elect keyer recording status
+                                             if(len <=2) {
+                                                send_resp(client_sock,"LM0;");
+                                             } 
+                                          }  
+        else if(strcmp(cmd_str,"LT")==0)  { // Set/read Alt function
+                                             if(len <=2) {
+                                                send_resp(client_sock,"LT0;");
+                                             } 
+                                          }  
+        else if(strcmp(cmd_str,"MC")==0) {  // Recalls or reads memory channel
+                                             if(len <=2) {
+                                               send_resp(client_sock,"MC000;"); // Link this to band stack at some point
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"MD")==0) {  // Mode - digit selects mode
+                                            // 1 = LSB
+                                            // 2 = USB
+                                            // 3 = CWU
+                                            // 4 = FM
+                                            // 5 = AM
+                                            // 6 = DIGL
+                                            // 7 = CWL
+                                            // 9 = DIGU 
+                                            int new_mode;
+                                            if(len > 2) { // Set Mode
+                                               switch(atoi(&cmd_input[2])) {   
+                                                 case 1:  
+                                                     new_mode = modeLSB;
+                                                     break;
+                                                 case 2:  
+                                                     new_mode = modeUSB;
+                                                     break;
+                                                 case 3:  
+                                                     new_mode = modeCWU;
+                                                     break;
+                                                 case 4:  
+                                                     new_mode = modeFMN;
+                                                     break;
+                                                 case 5:  
+                                                     new_mode = modeAM;
+                                                     break;
+                                                 case 6:  
+                                                     new_mode = modeDIGL;
+                                                     break;
+                                                 case 7:  
+                                                     new_mode = modeCWL;
+                                                     break;
+                                                 case 9:  
+                                                     new_mode = modeDIGU;
+                                                     break;
+                                                 default:
+                                                     break;
+                                                     #ifdef RIGCTL_DEBUG
+                                                     fprintf(stderr,"MD command Unknown\n");
+                                                     #endif
+                                               }
+                                            // Other stuff to switch modes goes here..
+                                            // since new_mode has the interpreted command in 
+                                            // in it now.
+                                            entry= (BANDSTACK_ENTRY *) 
+                                                  bandstack_entry_get_current();
+                                            entry->mode=new_mode;
+                                            //  BUG - kills the system when there is some
+                                            // GPIO activity and Mode sets occur. Used twittling the
+                                           // frequency along with setting mode between USB/LSB with
+                                           // flrig. Tried doing the g_idle_add trick - but don't know the
+                                           // the magic to get that to compile without warnings 
+                                            //setMode(entry->mode);
+                                            set_mode(active_receiver,entry->mode);
+                                            // Moved the vfo_update down after filter updated. (John G0ORX)
+                                            //g_idle_add(vfo_update,NULL);
+                                            
+                                            FILTER* band_filters=filters[entry->mode];
+                                            FILTER* band_filter=&band_filters[entry->filter];
+                                            //setFilter(band_filter->low,band_filter->high);
+                                            set_filter(active_receiver,band_filter->low,band_filter->high);
+                                            /* Need a way to update VFO info here..*/
+                                            g_idle_add(vfo_update,NULL);
+                                            }  else {     // Read Mode
+                                               int curr_mode;
+                                               switch (vfo[active_receiver->id].mode) {
+                                                  case modeLSB: curr_mode = 1; 
+                                                          break;   
+                                                  case modeUSB: curr_mode = 2;
+                                                          break;
+                                                  case modeCWL: curr_mode = 7; // CWL
+                                                          break;
+                                                  case modeCWU: curr_mode = 3; // CWU
+                                                          break;
+                                                  case modeFMN: curr_mode = 4; // FMN
+                                                          break;
+                                                  case modeAM: curr_mode = 5; // AM
+                                                          break;
+                                                  case modeDIGU: curr_mode = 9; // DIGU
+                                                          break;
+                                                  case modeDIGL: curr_mode = 6; // DIGL
+                                                          break;
+                                                  default: 
+                                                          #ifdef RIGCTL_DEBUG
+                                                            fprintf(stderr,
+                                                            "RIGCTL: MD command doesn't support %d\n",
+                                                            vfo[active_receiver->id].mode);
+                                                          #endif
+                                                          break;
+                                               }
+                                               sprintf(msg,"MD%1d;",curr_mode);
+                                               send_resp(client_sock,msg);
+                                            }
+                                         }
+        else if(strcmp(cmd_str,"MF")==0) {  // Set/read menu A/B
+                                             if(len <=2) {
+                                               send_resp(client_sock,"MF0;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"MG")==0) {  // Mike Gain - 3 digit value 
+                                            if(len <=2) {
+                                               work_int = (int) ((mic_gain +10.0)* 100.0/60.0);
+                                               sprintf(msg,"MG%03d;",work_int);
+                                               send_resp(client_sock,msg);
+                                            } else {
+                                               int tval = atoi(&cmd_input[2]);                
+                                               new_vol = (double) (tval * 60/100) - 10; 
+                                               //set_mic_gain(new_vol); 
+                                               double *p_mic_gain=malloc(sizeof(double));
+                                               *p_mic_gain=new_vol;
+                                               g_idle_add(update_mic_gain,(void *)p_mic_gain);
+                                            }
+                                         }
+        else if(strcmp(cmd_str,"ML")==0) {  // Set/read the monitor function level
+                                             if(len <=2) {
+                                               send_resp(client_sock,"ML000;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"MO")==0) {  // Set Monitor on/off
+                                             if(len <=2) {
+                                               send_resp(client_sock,"MO0;"); 
+                                             }
+                                         }
+        /* Not supported */
+        else if(strcmp(cmd_str,"MR")==0) {  // Read Memory Channel data
+                                             sprintf(msg,"MR%1d%02d%02d%011lld%1d%1d%1d%02d%02d%03d%1d%1d%09d%02d%1d%08d;",
+                                                      0, // P1 - Rx Freq - 1 Tx Freq
+                                                      0, // P2 Bankd and channel number -- see MC comment
+                                                      0, // P3 - see MC comment 
+                                                      rigctl_getFrequency(), // P4 - frequency
+                                                      rigctlGetMode(), // P5 - Mode
+                                                      locked, // P6 - Locked status
+                                                      0, // P7 - O-off, 1-tone, 2-CTCSS, 3 =DCS
+                                                      0, // P8 - Tone Number - see page 35
+                                                      ctcss_tone, // P9 - CTCSS tone number - see CN command
+                                                      0, // P10 - DCS code - see QC command 
+                                                      0, // P11 - Reverse status
+                                                      0, // P12 - Shift status - see OS command
+                                                      0, // P13 - Offset freq - see OS command
+                                                      0, // P14 - Step Size - see ST command
+                                                      0, // P15 - Memory Group Number (0-9)
+                                                      0);  // P16 - Memory Name - 8 char max
+                                               //send_resp(client_sock,msg);
+                                               send_resp(client_sock,"?;");
+                                         }
+        else if(strcmp(cmd_str,"MU")==0) {  // Set/Read Memory Group Data
+                                             if(len <=2) {
+                                               send_resp(client_sock,"MU0000000000;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"MW")==0) {  // Store Data to Memory Channel
+                                         }
+        else if(strcmp(cmd_str,"NB")==0) {  // Set/Read Noise Blanker func status (on/off)
+                                             if(len <=2) {
+                                               sprintf(msg,"NB%1d;",active_receiver->snb);
+                                               send_resp(client_sock,msg);
+                                             } else {
+                                               if(cmd_input[2]=='0') { // Turn off ANF
+                                                  active_receiver->snb=0;
+                                               } else { // Turn on ANF
+                                                  active_receiver->snb=1;
+                                               }
+                                               // Update filters
+                                               SetRXASNBARun(active_receiver->id, active_receiver->snb);
+                                               g_idle_add(vfo_update,NULL);
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"NL")==0) {  // Set/Read Noise Reduction  Level
+                                             if(len <=2) {
+                                               send_resp(client_sock,"NL000;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"NR")==0) {  // Set/Read Noise Reduction function status
+                                            if(len <=2) {
+/*
+                                              if(nr_none == 1) {
+                                                  send_resp(client_sock,"NR0;"); 
+                                              } else if ((nr_none == 0) && (nr==1)) { 
+                                                  send_resp(client_sock,"NR1;"); 
+                                              } else if (nr2 == 1) { 
+                                                  send_resp(client_sock,"NR2;"); 
+                                              } else {
+                                                  send_resp(client_sock,"NR0;"); 
+                                              }
+*/
+
+                                              // FIX now allow multiple set
+                                              if (active_receiver->nr==1) { 
+                                                send_resp(client_sock,"NR1;"); 
+                                              } else {
+                                                send_resp(client_sock,"NR0;"); 
+                                              }
+                                            } else {
+                                               if(cmd_input[2] == '0') {
+                                                  active_receiver->nr = 0;
+                                                  active_receiver->nr2 = 0;
+                                               } else if(cmd_input[2] == '1') {
+                                                  active_receiver->nr = 1;
+                                               } else if(cmd_input[2] == '2') {
+                                                  active_receiver->nr2 = 1;
+                                               }
+                                               SetRXAANRRun(active_receiver->id, active_receiver->nr);
+                                               SetRXAEMNRRun(active_receiver->id, active_receiver->nr2);
+                                               g_idle_add(vfo_update,NULL);
+                                            } 
+                                         }
+        else if(strcmp(cmd_str,"NT")==0) {  // Set/Read autonotch function
+                                             if(len <=2) {
+                                               sprintf(msg,"NT%1d;",active_receiver->anf);
+                                               send_resp(client_sock,msg);
+                                             } else {
+                                               if(cmd_input[2] == '0') { // Clear ANF
+                                                 active_receiver->anf = 0;
+                                               } else { // Set ANF
+                                                 active_receiver->anf = 1;
+                                               }
+                                             }
+                                             SetRXAANFRun(active_receiver->id, active_receiver->anf);
+                                             g_idle_add(vfo_update,NULL);
+                                         }
+        else if(strcmp(cmd_str,"OF")==0) {  // Set/Read Offset freq (9 digits - hz)
+                                             if(len <=2) {
+                                               send_resp(client_sock,"OF000000000;"); 
+                                             }
+                                         }
+        /* Not Supported */
+        else if(strcmp(cmd_str,"OI")==0) {  // Read Memory Channel Data
+                                             if(len <=2) {
+                                               sprintf(msg,"OI%011lld%04d%06d%1d%1d%1d%02d%1d%1d%1d%1d%1d%1d%02d%1d;",
+                                                  rigctl_getFrequency(),
+                                                  0, // P2 - Freq Step size
+                                                  0, // P3 - Rit/Xit Freq 
+                                                  0, // P4 - RIT off/Rit On
+                                                  0, // P5 - XIT off/on
+                                                  0, // P6 - Channel
+                                                  0, // P7 - Bank
+                                                  0, // P8 - 0RX, 1TX
+                                                  rigctlGetMode(),  // P10 - MD
+                                                  0, // P11 - SC command
+                                                  0, // P12 Split op - SP command
+                                                  0, // P13 Off, 1, 2, 
+                                                  0,// P14 Tone freq - See TN command
+                                                  0,0);
+                                               send_resp(client_sock,"?;");
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"OS")==0) {  // Set/Read Offset freq (9 digits - hz)
+                                             if(len <=2) {
+                                               //send_resp(client_sock,"OS0;"); 
+                                               send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"PA")==0) {  // Set/Read Preamp function status
+                                             if(len <=2) {
+                                               sprintf(msg,"PA0%1d;",enable_tx_equalizer);
+                                               send_resp(client_sock,msg);
+                                             } else {
+                                                if(cmd_input[2] =='0') {
+                                                  enable_tx_equalizer=0;
+                                                  SetTXAEQRun(transmitter->id, enable_tx_equalizer);
+                                                } else {
+                                                  enable_tx_equalizer=1;
+                                                  SetTXAEQRun(transmitter->id, enable_tx_equalizer);
+                                                }
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"PB")==0) {  // Set/Read DRU-3A Playback status
+                                             if(len <=2) {
+                                               send_resp(client_sock,"PB0;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"PC")==0) {  // Set/Read Drive Power output
+                                            if(len<=2) {
+                                              sprintf(msg,"PC%03d;",(int) drive);
+                                              send_resp(client_sock,msg); 
+                                            } else {
+                                               // Power Control - 3 digit number- 0 to 100
+                                               //Scales to 0.00-1.00
+                                                
+                                               double drive_val = 
+                                                   (double)(atoi(&cmd_input[2])); 
+                                               // setDrive(drive_val);
+                                               double *p_drive=malloc(sizeof(double));
+                                               *p_drive=drive_val;
+                                               g_idle_add(update_drive,(gpointer)p_drive);
+                                               //set_drive(drive_val);
+                                            }
+                                         }
+        else if(strcmp(cmd_str,"PI")==0) {  // STore the programmable memory channel
+                                         }
+        else if(strcmp(cmd_str,"PK")==0) {  // Reads the packet cluster data
+                                             //  send_resp(client_sock,"PK000000000000000000000000000000000000000000000000;"); 
+                                             send_resp(client_sock,"?;"); 
+                                            
+                                         }
+        else if(strcmp(cmd_str,"PL")==0) {  // Set/Read Speech processor level
+                                            // P1 000 - min-100 max
+                                            // P2 000 - min - 100 max
+                                             if(len <=2) {
+                                             //  send_resp(client_sock,"PL000000;"); 
+                                                send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"PM")==0) {  // Recalls the Programmable memory
+                                             if(len <=2) {
+                                               //send_resp(client_sock,"PM0;"); 
+                                               send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"PR")==0) {  // Sets/reads the speech processor function on/off
+                                            // 0 - off, 1=on
+                                             if(len <=2) {
+                                               //send_resp(client_sock,"PR0;"); 
+                                               send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"PS")==0) {  // Sets/reads Power on/off state
+                                            // 0 - off, 1=on
+                                             if(len <=2) {
+                                               send_resp(client_sock,"PS1;"); // Lets pretend we're powered up ;-) 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"QC")==0) {  // Sets/reads DCS code
+                                            // Codes numbered from 000 to 103.
+                                             if(len <=2) {
+                                               //send_resp(client_sock,"QC000;"); // Lets pretend we're powered up ;-) 
+                                               send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"QI")==0) {  // Store the settings in quick memory
+                                         }
+        else if(strcmp(cmd_str,"QR")==0) {  // Send the Quick memory channel data
+                                            // P1 - Quick mem off, 1 quick mem on
+                                            // P2 - Quick mem channel number
+                                             if(len <=2) {
+                                               //send_resp(client_sock,"QR00;"); // Lets pretend we're powered up ;-) 
+                                               send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"RA")==0) {  // Sets/reads Attenuator function status
+                                            // 00-off, 1-99 -on - Main and sub receivers reported
+                                             if(len <=2) {
+                                               //send_resp(client_sock,"RA0000;"); 
+                                               send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"RC")==0) {  // Clears the RIT offset freq
+                                         }
+        else if(strcmp(cmd_str,"RD")==0) {  // Move the RIT offset freq down, slow down the scan speed in scan mode
+                                             if(len <=2) {
+                                               vfo[active_receiver->id].rit = vfo[active_receiver->id].rit-rit_increment;
+                                               sprintf(msg,"RD%1d;",rit_on());
+                                               send_resp(client_sock,msg);
+                                             } else {
+                                                if(len > 3) {
+                                                   // Non scan mode when RDxxxxx; - 
+                                                   vfo[active_receiver->id].rit = vfo[active_receiver->id].rit-rit_increment;
+                                                } 
+                                             }
+                                             g_idle_add(vfo_update,NULL);
+                                         }
+        else if(strcmp(cmd_str,"RG")==0) {  // RF Gain - 3 digit number
+                                            // RG123; 0-255 value
+                                            // Scale from -20 - 120
+                                            if(len>4) { // Set Audio Gain
+                                               int base_value = atoi(&cmd_input[2]);
+                                               double new_gain = ((((double) base_value)/255) * 140) - 20; 
+                                               //set_agc_gain(new_gain);               
+                                               double *p_gain=malloc(sizeof(double));
+                                               *p_gain=new_gain;
+                                               g_idle_add(update_agc_gain,(gpointer)p_gain);
+                                            } else { // Read Audio Gain
+                                              sprintf(msg,"RG%03d;",((256 * (int) active_receiver->agc_gain)/140)+36);
+                                              send_resp(client_sock,msg);
+                                            }
+                                         }
+        else if(strcmp(cmd_str,"RL")==0) {  // Set/read Noise reduction level
+                                             if(len <=2) {
+                                               //send_resp(client_sock,"RL00;"); 
+                                               send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"RM")==0) {  // Set/read Meter function
+                                            // P1- 0, unsel, 1 SWR, 2 Comp, 3 ALC
+                                            // P2 - 4 dig - Meter value in dots - 000-0030
+                                             if(len <=2) {
+                                               //send_resp(client_sock,"RM00000;"); 
+                                               send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"RT")==0) {  // Set/read the RIT function status
+                                             if(len <=2) {
+                                               sprintf(msg,"RT%01d;",rit_on());
+                                               send_resp(client_sock,msg); 
+                                             } else {
+                                                if(atoi(&cmd_input[2]) == 0) {
+                                                   vfo[active_receiver->id].rit = 0;
+                                                }
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"RU")==0) {  // Set/move RIT frequency up
+                                             if(len <=2) {
+                                               vfo[active_receiver->id].rit = vfo[active_receiver->id].rit+rit_increment;
+                                               sprintf(msg,"RU%01d;",rit_on());
+                                               send_resp(client_sock,msg);
+                                             } else {
+                                                if(len > 3) {
+                                                   vfo[active_receiver->id].rit = vfo[active_receiver->id].rit+rit_increment;
+                                                } 
+                                             }
+                                             g_idle_add(vfo_update,NULL);
+                                         }
+        else if(strcmp(cmd_str,"RX")==0) {  // Unkey Xmitter
+                                            //setMox(0);
+                                            mox_state=0;
+                                            g_idle_add(mox_update,(gpointer)mox_state); 
+                                            g_idle_add(vfo_update,NULL);
+                                         }
+        else if(strcmp(cmd_str,"SA")==0) {  // Set/reads satellite mode status
+                                            // 0-main, 1=sub
+                                             if(len <=2) {
+                                               //send_resp(client_sock,"SA000000000000000;"); 
+                                               send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"SB")==0) {  // Set/read the SUB TF-W status
+                                             if(len <=2) {
+                                               //send_resp(client_sock,"SB0;"); 
+                                               send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"SC")==0) {  // Set/read the Scan function status
+                                             if(len <=2) {
+                                               //send_resp(client_sock,"SC0;"); 
+                                               send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"SD")==0) {  // Set/read CW break-in time delay
+                                            // 0000-1000 ms (in steps of 50 ms) 0000 is full break in
+                                             int local_cw_breakin=cw_keyer_hang_time;
+                                             // Limit report value to 1000 for TS-2000
+                                             if(local_cw_breakin > 1000) { local_cw_breakin = 1000; }
+                                             if(len <=2) {
+                                               sprintf(msg,"SD%04d;",local_cw_breakin);
+                                               send_resp(client_sock,msg);
+                                             } else {
+                                               local_cw_breakin = atoi(&cmd_input[2]); 
+                                               if(cw_keyer_hang_time <= 1000) {
+                                                  if(local_cw_breakin==0) {
+                                                      cw_breakin = 1;
+                                                  }  else {
+                                                      cw_breakin = 0;
+                                                  } 
+                                                  cw_keyer_hang_time = local_cw_breakin; 
+                                               }
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"SH")==0) {  // Set/read the DSP filter settings
+                                             if(len <=2) {
+                                              // send_resp(client_sock,"SH00;"); 
+                                               send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"SI")==0) {  // Enters the satellite memory name
+                                         }
+        else if(strcmp(cmd_str,"SL")==0) {  // Set/read the DSP filter settings - this appears twice? See SH
+                                             if(len <=2) {
+                                               //send_resp(client_sock,"SL00;");
+                                               send_resp(client_sock,"?;"); 
+                                             } 
+                                         }
+        else if(strcmp(cmd_str,"SM")==0) {  // Read SMETER
+                                            // SMx;  x=0 RX1, x=1 RX2 
+                                            // meter is in dbm - value will be 0<260
+                                            // Translate to 00-30 for main, 0-15 fo sub
+                                            // Resp= SMxAABB; 
+                                            //  Received range from the SMeter can be -127 for S0, S9 is -73, and S9+60=-13.;
+                                            //  PowerSDR returns S9=0015 code. 
+                                            //  Let's make S9 half scale or a value of 70.  
+                                            double level=0.0;
+
+                                            if(cmd_input[2] == '0') { 
+                                              level = GetRXAMeter(receiver[0]->id, smeter); 
+                                            } else if(cmd_input[2] == '1') { 
+                                              if(receivers==2) {
+                                                level = GetRXAMeter(receiver[1]->id, smeter); 
+                                              }
+                                            }
+
+
+                                            level = GetRXAMeter(active_receiver->id, smeter); 
+                                            // Determine how high above 127 we are..making a range of 114 from S0 to S9+60db
+                                            // 5 is a fugdge factor that shouldn't be there - but seems to get us to S9=SM015
+                                            level =  abs(127+(level + (double) get_attenuation()))+5;
+                                         
+                                            // Clip the value just in case
+                                            if(cmd_input[2] == '0') { 
+                                               new_level = (int) ((level * 30.0)/114.0);
+                                               // Do saturation check
+                                               if(new_level < 0) { new_level = 0; }
+                                               if(new_level > 30) { new_level = 30;}
+                                            } else { //Assume we are using sub receiver where range is 0-15
+                                               new_level = (int) ((level * 15.0)/114.0);
+                                               // Do saturation check
+                                               if(new_level < 0) { new_level = 0; }
+                                               if(new_level > 15) { new_level = 15;}
+                                            }
+                                            sprintf(msg,"SM%1c%04d;",
+                                                cmd_input[2],new_level);
+                                            send_resp(client_sock,msg);
+                                         }   
+        else if(strcmp(cmd_str,"SQ")==0) {  // Set/read the squelch level
+                                            // P1 - 0- main, 1=sub
+                                            // P2 - 0-255
+                                             if(len <=3) {
+                                               sprintf(msg,"SQ%04d;",squelch);
+                                               send_resp(client_sock,msg);
+                                             } else {
+                                                squelch = atoi(&cmd_input[2]);
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"SR")==0) {  // Resets the transceiver
+                                         }
+        else if(strcmp(cmd_str,"SS")==0) {  // Set/read Scan pause freq
+                                             if(len <=2) {
+                                               //send_resp(client_sock,"SS0;"); 
+                                               send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"ST")==0) {  // Set/read the multi/ch control freq steps
+                                            // SSB/CW/FSK - values 00-03
+                                            // 00: 1KHz, 01: 2.5Khz 02:5KHz 03: 10Khz
+                                            // AM/FM mode 00-09
+                                            // 00: 5KHz, 
+                                            // 01: 6.25KHz, 
+                                            // 02:10Khz, 
+                                            // 03: 12.5Khz,
+                                            // 04: 15Khz, 
+                                            // 05: 20Khz, 
+                                            // 06: 25KHz
+                                            // 07: 30Khz
+                                            // 08: 50Khz
+                                            // 09: 100Khz 
+                                             int coded_step_val;
+                                             entry= (BANDSTACK_ENTRY *) 
+                                                bandstack_entry_get_current();
+                                             if(len <=2) {
+                                                 switch(entry->mode) {
+                                                     case modeLSB: 
+                                                     case modeUSB: 
+                                                     case modeCWL: 
+                                                     case modeCWU: 
+                                                     case modeDIGU: 
+                                                     case modeDIGL: 
+                                                        if(step >0 && step <= 1000)  {
+                                                          coded_step_val = 0; 
+                                                        } else if (step >1000 && step <=2500) {
+                                                          coded_step_val = 1; 
+                                                        } else if (step >2500 && step <=5000) {
+                                                          coded_step_val = 2; 
+                                                        } else {
+                                                          coded_step_val = 3; 
+                                                        }
+                                                        break;
+                                                     case modeFMN: 
+                                                     case modeAM:  
+                                                        if(step >0 && step <= 5000)  {
+                                                          coded_step_val = 0; 
+                                                        } else if (step >5000 && step <=6250) {
+                                                          coded_step_val = 1; 
+                                                        } else if (step >6250 && step <=10000) {
+                                                          coded_step_val = 2; 
+                                                        } else if (step >10000 && step <=12500) {
+                                                          coded_step_val = 3; 
+                                                        } else if (step >12500 && step <=15000) {
+                                                          coded_step_val = 4; 
+                                                        } else if (step >15000 && step <=20000) {
+                                                          coded_step_val = 5; 
+                                                        } else if (step >20000 && step <=25000) {
+                                                          coded_step_val = 6; 
+                                                        } else if (step >25000 && step <=30000) {
+                                                          coded_step_val = 7; 
+                                                        } else if (step >30000 && step <=50000) {
+                                                          coded_step_val = 8; 
+                                                        } else if (step >50000 && step <=100000) {
+                                                          coded_step_val = 9; 
+                                                        } else {
+                                                          coded_step_val = 0; 
+                                                        }
+                                                        break;
+                                                 } 
+                                                 sprintf(msg,"ST%02d;",coded_step_val);
+                                                 send_resp(client_sock,msg); 
+                                             } else {
+                                                 coded_step_val = atoi(&cmd_input[2]);   
+                                                 switch(entry->mode) {
+                                                     case modeLSB: 
+                                                     case modeUSB: 
+                                                     case modeCWL: 
+                                                     case modeCWU: 
+                                                     case modeDIGU: 
+                                                     case modeDIGL: 
+                                                        if(coded_step_val==0) { step = 1000;}
+                                                        if(coded_step_val==1) { step = 2500;}
+                                                        if(coded_step_val==2) { step = 5000;}
+                                                        if(coded_step_val==3) { step = 10000;}
+                                                        break; 
+                                                     case modeFMN: 
+                                                     case modeAM:  
+                                                         switch(coded_step_val) {
+                                                            case 0: step = 5000; break;
+                                                            case 1: step = 6250; break;
+                                                            case 2: step = 10000; break;
+                                                            case 3: step = 12500; break;
+                                                            case 4: step = 15000; break;
+                                                            case 5: step = 20000; break;
+                                                            case 6: step = 25000; break;
+                                                            case 7: step = 30000; break;
+                                                            case 8: step = 50000; break;
+                                                            case 9: step = 100000; break;
+                                                            default: break; // No change if not a valid number
+                                                         } 
+                                                     default: break; // No change if not a valid number
+                                                 } 
+                                                 g_idle_add(vfo_update,NULL);
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"SU")==0) {  // Set/read the scan pause freq
+                                             if(len <=2) {
+                                               //send_resp(client_sock,"SU00000000000;"); 
+                                               send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"SV")==0) {  // Execute the memory transfer function
+                                         }
+        else if(strcmp(cmd_str,"TC")==0) {  // Set/read the internal TNC mode
+                                             if(len <=2) {
+                                               //send_resp(client_sock,"TC00;"); 
+                                               send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"TD")==0) {  // Sends the DTMF memory channel
+                                         }
+        else if(strcmp(cmd_str,"TI")==0) {  // Reads the TNC LED status
+                                             if(len <=2) {
+                                               //send_resp(client_sock,"TI00;"); 
+                                               send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"TN")==0) {  // Set/Read sub tone freq
+                                             if(len <=2) {
+                                               //send_resp(client_sock,"TN00;"); 
+                                               send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"TO")==0) {  // Set/Read tone function
+                                             if(len <=2) {
+                                               //send_resp(client_sock,"TO0;"); 
+                                               send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"TS")==0) {  // Set/Read TF Set function status
+                                             if(len <=2) {
+                                               //send_resp(client_sock,"TS0;"); 
+                                               send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"TX")==0) {  // Key Xmitter - P1 - transmit on main/sub freq
+
+                                             /*if(len >=3) { 
+                                               // K5JAE: The TS-2000 real hardware does not respond 
+                                               // to this command, thus hamlib is not expecting response.
+                                               //send_resp(client_sock,"TX0;"); 
+                                             }*/
+                                            mox_state=1;
+                                            g_idle_add(mox_update,(gpointer)mox_state); 
+                                            g_idle_add(vfo_update,NULL);
+                                         }
+        else if(strcmp(cmd_str,"TY")==0) {  // Set/Read uP firmware type
+                                             if(len <=2) {
+                                               send_resp(client_sock,"TY000;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"UL")==0) {  // Detects the PLL unlock status - this should never occur - xmit only
+                                             if(len <=2) {
+                                               //send_resp(client_sock,"UL0;"); 
+                                               send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"UP")==0) {  // Emulates the mic up key
+                                         }
+        else if(strcmp(cmd_str,"VD")==0) {  // Sets/Reads VOX dleay time - 0000-3000ms in steps of 150
+                                            // We want vox_hang variable in PiHPSDR
+                                            // Max value in variable in ms... so 250 = 250ms
+                                             if(len <=2) {
+                                               work_int = (int) vox_hang;
+                                               sprintf(msg,"VD%04d;",work_int); 
+                                               send_resp(client_sock,msg);
+                                             } else {
+                                                  work_int = atoi(&cmd_input[2]);
+                                                  // Bounds check for legal values for PiHPSDR
+                                                  if(work_int > 1000) { work_int = 1000; }
+                                                  if(work_int < 0) { work_int = 0; }
+                                                  vox_hang = (double) work_int;
+                                                  #ifdef RIGCTL_DEBUG
+                                                  fprintf(stderr,"RIGCTL: Vox hang=%0.20f\n",vox_hang);
+                                                  #endif
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"VG")==0) {  // Sets/Reads VOX gain 000-009
+                                            // We want vox_threshold variable in PiHPSDR
+                                            // Max value in variable 0.1 
+                                            // 3 char 000-009 valid ranges
+                                             if(len <=2) {
+                                               work_int = (int) ((vox_threshold) * 100.0);
+                                               sprintf(msg,"VG00%1d;",work_int);
+                                               send_resp(client_sock,msg);
+                                             } else {
+                                                  // Set the threshold here
+                                                  work_int = atoi(&cmd_input[2]);
+                                                  vox_threshold = ((double) work_int)/100.0;
+                                                  #ifdef RIGCTL_DEBUG
+                                                  fprintf(stderr,"RIGCTL: Vox thresh=%0.20f\n",vox_threshold);
+                                                  #endif
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"VR")==0) {  // Emulates the voice 1/2 key
+                                         }
+        else if(strcmp(cmd_str,"VX")==0) {  // Sets/reads vox f(x) state
+                                             if(len <=2) {
+                                               sprintf(msg,"VX%1d;",vox_enabled); 
+                                               send_resp(client_sock,msg);
+                                             } else {
+                                               work_int = atoi(&cmd_input[2]);
+                                               if(work_int>1) { vox_enabled = 1; vox= 1;}
+                                               if(work_int<1) { vox_enabled = 0; vox=0; }
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"XT")==0) {  // Sets/reads the XIT f(x) state
+                                             if(len <=2) {
+                                               //send_resp(client_sock,"XT0;"); 
+                                               send_resp(client_sock,"?;"); 
+                                             }
+                                         }
+        else if(strcmp(cmd_str,"XX")==0) {  // 
+                                            // Format RL01234: First dig 0=neg, 1=pos number
+                                            //                 1-4- digital offset in hertz.
+                                            if(len > 4) { // It is set instead of a read
+                                               digl_pol = (cmd_input[2]=='0') ? -1 : 1;
+                                               digl_offset = atoi(&cmd_input[3]); 
+                                               #ifdef RIGCTL_DEBUG
+                                               fprintf(stderr,"RIGCTL:RL set %d %d\n",digl_pol,digl_offset); 
+                                               #endif
+                                            } else {
+                                               if(digl_pol==1) { // Nah - its a read
+                                                 sprintf(msg,"RL1%04d;",0);
+                                               } else {
+                                                 sprintf(msg,"RL0%04d;",0);
+                                               }         
+                                               send_resp(client_sock,msg);
+                                               #ifdef RIGCTL_DEBUG
+                                               fprintf(stderr,":%s\n",msg);
+                                               #endif
+                                            }
+                                         }
+        else if(strcmp(cmd_str,"XY")==0) {  // set/read RTTY DIGL offset frequency - Not available - just store values
+                                            // Format RL01234: First dig 0=neg, 1=pos number
+                                            //                 1-4- digital offset in hertz.
+                                            if(len > 4) { // It is set instead of a read
+                                               digl_pol = (cmd_input[2]=='0') ? -1 : 1;
+                                               digl_offset = atoi(&cmd_input[3]); 
+                                               #ifdef RIGCTL_DEBUG
+                                               fprintf(stderr,"RIGCTL:RL set %d %d\n",digl_pol,digl_offset); 
+                                               #endif
+                                            } else {
+                                               if(digl_pol==1) { // Nah - its a read
+                                                 sprintf(msg,"RL1%04d;",0);
+                                               } else {
+                                                 sprintf(msg,"RL0%04d;",0);
+                                               }         
+                                               send_resp(client_sock,msg);
+                                               #ifdef RIGCTL_DEBUG
+                                               fprintf(stderr,":%s\n",msg);
+                                               #endif
+                                            }
+                                         }
+        else                             {
+                                            fprintf(stderr,"RIGCTL: UNKNOWN=%s\n",cmd_str);
+                                         }
+}
+//
+// End of Parser
+// 
+
+
+//
+// 2-25-17 - K5JAE - create each thread with the pointer to the port number  
+//                   (Port numbers now const ints instead of defines..) 
+//
+void launch_rigctl () {
+   int err;
+   fprintf(stderr, "LAUNCHING RIGCTL!!\n");
+
+   mutex_a = g_new(GT_MUTEX,1);
+   g_mutex_init(&mutex_a->m);
+
+   mutex_b = g_new(GT_MUTEX,1);
+   g_mutex_init(&mutex_b->m);
+   
+   // This routine encapsulates the pthread call
+/*
+   err = pthread_create (&rigctl_a_thread_id,NULL,rigctl_a,NULL);
+   if(err != 0) {
+       fprintf(stderr, "pthread_create failed on rigctl_a launch\n");
+   }  
+*/
+
+   rigctl_a_thread_id = g_thread_new( "rigctl a", rigctl, (gpointer)&TelnetPortA);
+   if( ! rigctl_a_thread_id )
+   {
+     fprintf(stderr,"g_thread_new failed on rigctl_a\n");
+   }
+
+
+/*
+   err = pthread_create (&rigctl_b_thread_id,NULL,rigctl_b,NULL);
+   if(err != 0) {
+       fprintf(stderr, "pthread_create failed on rigctl_b launch\n");
+   }  
+*/
+
+   rigctl_b_thread_id = g_thread_new( "rigctl b", rigctl, (gpointer)&TelnetPortB);
+   if( ! rigctl_b_thread_id )
+   {
+     fprintf(stderr,"g_thread_new failed on rigctl_b\n");
+   }
+
+/*
+   err = pthread_create (&rigctl_c_thread_id,NULL,rigctl_c,NULL);
+   if(err != 0) {
+       fprintf(stderr, "pthread_create failed on rigctl_c launch\n");
+   }  
+*/
+
+   rigctl_c_thread_id = g_thread_new( "rigctl c", rigctl, (gpointer)&TelnetPortC);
+   if( ! rigctl_c_thread_id )
+   {
+     fprintf(stderr,"g_thread_new failed on rigctl_c\n");
+   }
+
+}
+
+
+// Telnet Server launch code below
+// max number of bytes we can get at once
+#define MAXDATASIZE 300
+
+//
+// 2-25-17 - K5JAE - removed duplicate init servers.
+//
+
+
+int init_server ( int * socket_desc_ptr, struct sockaddr_in * client, struct sockaddr_in * server, int telnet_port) {
+    int client_sock;
+    int c;
+    //Create socket
+    *socket_desc_ptr = socket(AF_INET , SOCK_STREAM , 0);
+
+    if (*socket_desc_ptr == -1)
+    {
+        fprintf(stderr,"RIGCTL: Could not create socket");
+    }
+    fprintf(stderr, "RIGCTL: Socket created\n");
+     
+    //Prepare the sockaddr_in structure
+    server->sin_family = AF_INET;
+    server->sin_addr.s_addr = INADDR_ANY;
+    server->sin_port = htons( telnet_port );
+     
+    //Bind
+    if( bind(*socket_desc_ptr,(struct sockaddr *) server , sizeof(struct sockaddr_in)) < 0)
+    {
+        //print the error message
+        fprintf(stderr,"RIGCTL: bind failed. Error\n");
+        return 1;
+    }
+    fprintf(stderr,"RIGCTL: Bind done on port %d\n",telnet_port);
+     
+    //Listen
+    listen(*socket_desc_ptr, 3);
+     
+    //Accept and incoming connection
+    fprintf(stderr,"RIGCTL: Waiting for incoming connections...\n");
+    c = sizeof(struct sockaddr_in);
+     
+    //accept connection from an incoming client
+    client_sock = accept(*socket_desc_ptr,(struct sockaddr *)client, (socklen_t*)&c);
+    if (client_sock < 0)
+    {
+        fprintf(stderr,"RIGCTL: Accept failed\n");
+    }
+    fprintf(stderr,"RIGCTL: Connection accepted\n");
+
+    return client_sock;
+}
+
+int rigctlGetMode()  {
+        switch(vfo[active_receiver->id].mode) {
+           case modeLSB: return(1); // LSB
+           case modeUSB: return(2); // USB
+           case modeCWL: return(7); // CWL
+           case modeCWU: return(3); // CWU
+           case modeFMN: return(4); // FMN
+           case modeAM:  return(5); // AM
+           case modeDIGU: return(9); // DIGU
+           case modeDIGL: return(6); // DIGL
+           default: return(0);
+        }
+}
+
+int rigctlSetFilterLow(int val){
+};
+int rigctlSetFilterHigh(int val){
+};
+
+void set_band(long long new_freqA, int ctl) {      
+
+   fprintf(stderr,"set_band: f=%11lld ctl=%d\n",new_freqA,ctl );
+   BANDSTACK_ENTRY *entry;
+   BAND *band;
+   FILTER* band_filters;
+   FILTER* band_filter;
+
+   int b = get_band_from_frequency(new_freqA);
+
+   if(b == -1) { // Out of ham bands...
+      fprintf(stderr,"set_band: out of ham bands\n");
+      setFrequency(new_freqA);
+      g_idle_add(vfo_update,NULL);
+      return;
+   }   
+
+   band=band_set_current(b);
+
+   entry=bandstack_entry_next();
+   entry->mode = vfo[VFO_A].mode;
+   set_mode(active_receiver,entry->mode); // From current band setting
+   
+
+   band_filters=filters[entry->mode];
+   band_filter=&band_filters[entry->filter];
+
+  set_filter(active_receiver,band_filter->low,band_filter->high);
+  setFrequency(new_freqA);
+
+  // BAND *band=band_get_current_band();
+  band=band_set_current(b);
+  if(active_receiver->id==0) {
+    set_alex_rx_antenna(band->alexRxAntenna);
+    set_alex_tx_antenna(band->alexTxAntenna);
+    set_alex_attenuation(band->alexAttenuation);
+  }
+
+  //setFrequency(new_freqA);
+  g_idle_add(vfo_update,NULL);
+
+  calcDriveLevel();
+  calcTuneDriveLevel();
+}
+
+void set_freqB(long long new_freqB) {      
+
+   //BANDSTACK_ENTRY *bandstack = bandstack_entry_get_current();
+   //bandstack->frequencyB = new_freqB;
+   //frequencyB = new_freqB;
+   vfo[VFO_B].frequency = new_freqB;   
+   g_idle_add(vfo_update,NULL);
+}
index 2d3ec1a62d763be7bf90124f16b85f99f7266e9c..51e59ed386bac45eca3fb06e130eb29c53a25047 100644 (file)
--- a/rigctl.h
+++ b/rigctl.h
@@ -2,9 +2,10 @@
 #define RIGCTL_H
 
 void launch_rigctl ();
-void parse_cmd(char *,int);
 int   rigctlGetMode();
 char * rigctlGetFilter();
-void set_band(long long);
+void set_freqB(long long);
+void set_band(long long, int);
+extern int cat_control;
 
 #endif // RIGCTL_H
diff --git a/rit.c b/rit.c
index da598f922d6152f72441b08397505219bdd7bf1e..e9091b6227f0ab9e7dc35994b80f0100b0205283 100644 (file)
--- a/rit.c
+++ b/rit.c
@@ -57,23 +57,22 @@ static gboolean ctun_pressed_event_cb (GtkWidget *widget, GdkEventButton *event,
     set_button_text_color(ctun_b,"red");
   } else {
     set_button_text_color(ctun_b,"black");
-    if(ddsOffset!=0) {
-      ddsOffset=0;
-      wdsp_set_offset(ddsOffset);
-      vfo_update(NULL);
-    }
+    vfo[active_receiver->id].offset=0;
+    set_offset(active_receiver,0);
+    vfo_update(NULL);
   }
   return TRUE;
 }
 
 static gboolean rit_timer_cb(gpointer data) {
+  int v=active_receiver->id;
   if((GtkWidget*)data==rit_plus_b) {
-    rit+=rit_increment;
+    vfo[v].rit+=rit_increment;
   } else {
-    rit-=rit_increment;
+    vfo[v].rit-=rit_increment;
   }
-  if(rit>1000) rit=1000;
-  if(rit<-1000) rit=-1000;
+  if(vfo[v].rit>1000) vfo[v].rit=1000;
+  if(vfo[v].rit<-1000) vfo[v].rit=-1000;
   vfo_update(NULL);
   return TRUE;
 }
@@ -82,7 +81,7 @@ static gboolean rit_pressed_event_cb (GtkWidget *widget, GdkEventButton *event,
   if(rit_enabled) {
     rit_enabled=FALSE;
     set_button_text_color(rit_b,"black");
-    rit=0;
+    vfo[active_receiver->id].offset=0;
     gtk_widget_set_sensitive(rit_plus_b,FALSE);
     gtk_widget_set_sensitive(rit_minus_b,FALSE);
   } else {
@@ -95,13 +94,14 @@ static gboolean rit_pressed_event_cb (GtkWidget *widget, GdkEventButton *event,
 }
 
 static gboolean rit_step_pressed_event_cb (GtkWidget *widget, GdkEventButton *event, gpointer        data) {
+  int v=active_receiver->id;
   if(widget==rit_plus_b) {
-    rit+=rit_increment;
+    vfo[v].rit+=rit_increment;
   } else {
-    rit-=rit_increment;
+    vfo[v].rit-=rit_increment;
   }
-  if(rit>1000) rit=1000;
-  if(rit<-1000) rit=-1000;
+  if(vfo[v].rit>1000) vfo[v].rit=1000;
+  if(vfo[v].rit<-1000) vfo[v].rit=-1000;
   vfo_update(NULL);
   rit_timer=g_timeout_add(200,rit_timer_cb,widget);
   return TRUE;
diff --git a/rx_menu.c b/rx_menu.c
new file mode 100644 (file)
index 0000000..3d1318d
--- /dev/null
+++ b/rx_menu.c
@@ -0,0 +1,333 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#include <gtk/gtk.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "audio.h"
+#include "new_menu.h"
+#include "rx_menu.h"
+#include "band.h"
+#include "discovered.h"
+#include "filter.h"
+#include "radio.h"
+#include "receiver.h"
+
+static GtkWidget *parent_window=NULL;
+
+static GtkWidget *menu_b=NULL;
+
+static GtkWidget *dialog=NULL;
+
+static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  if(dialog!=NULL) {
+    gtk_widget_destroy(dialog);
+    dialog=NULL;
+    sub_menu=NULL;
+  }
+  return TRUE;
+}
+
+static void dither_cb(GtkWidget *widget, gpointer data) {
+  active_receiver->dither=active_receiver->dither==1?0:1;
+}
+
+static void random_cb(GtkWidget *widget, gpointer data) {
+  active_receiver->random=active_receiver->random==1?0:1;
+}
+
+static void preamp_cb(GtkWidget *widget, gpointer data) {
+  active_receiver->preamp=active_receiver->preamp==1?0:1;
+}
+
+static void sample_rate_cb(GtkWidget *widget, gpointer data) {
+  receiver_change_sample_rate(active_receiver,(int)data);
+}
+
+static void adc_cb(GtkWidget *widget, gpointer data) {
+  receiver_change_adc(active_receiver,(int)data);
+}
+
+static void local_audio_cb(GtkWidget *widget, gpointer data) {
+  if(gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+    if(audio_open_output(active_receiver)==0) {
+      active_receiver->local_audio=1;
+    } else {
+      active_receiver->local_audio=0;
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
+    }
+  } else {
+    if(active_receiver->local_audio) {
+      active_receiver->local_audio=0;
+      audio_close_output(active_receiver);
+    }
+  }
+}
+
+static void local_output_changed_cb(GtkWidget *widget, gpointer data) {
+  active_receiver->audio_device=(int)(long)data;
+  if(active_receiver->local_audio) {
+    audio_close_output(active_receiver);
+    if(audio_open_output(active_receiver)==0) {
+      active_receiver->local_audio=1;
+    }
+  }
+}
+
+static void audio_channel_cb(GtkWidget *widget, gpointer data) {
+  if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
+    active_receiver->audio_channel=(int)data;
+  }
+}
+
+void rx_menu(GtkWidget *parent) {
+  char label[32];
+  GtkWidget *adc_b;
+  int i;
+  parent_window=parent;
+
+  dialog=gtk_dialog_new();
+  gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
+  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+
+  GdkRGBA color;
+  color.red = 1.0;
+  color.green = 1.0;
+  color.blue = 1.0;
+  color.alpha = 1.0;
+  gtk_widget_override_background_color(dialog,GTK_STATE_FLAG_NORMAL,&color);
+
+  GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+
+  GtkWidget *grid=gtk_grid_new();
+  gtk_grid_set_column_spacing (GTK_GRID(grid),10);
+  //gtk_grid_set_row_spacing (GTK_GRID(grid),10);
+  //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
+  //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+
+  GtkWidget *close_b=gtk_button_new_with_label("Close RX");
+  g_signal_connect (close_b, "button_press_event", G_CALLBACK(close_cb), NULL);
+  gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
+
+  sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B");
+  GtkWidget *rx_label=gtk_label_new(label);
+  gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1);
+
+  int x=0;
+
+  switch(protocol) {
+    case NEW_PROTOCOL:
+      {
+      GtkWidget *sample_rate_label=gtk_label_new("Sample Rate");
+      gtk_grid_attach(GTK_GRID(grid),sample_rate_label,x,1,1,1);
+
+      GtkWidget *sample_rate_48=gtk_radio_button_new_with_label(NULL,"48000");
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_48), active_receiver->sample_rate==48000);
+      gtk_grid_attach(GTK_GRID(grid),sample_rate_48,x,2,1,1);
+      g_signal_connect(sample_rate_48,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)48000);
+
+      GtkWidget *sample_rate_96=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_48),"96000");
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_96), active_receiver->sample_rate==96000);
+      gtk_grid_attach(GTK_GRID(grid),sample_rate_96,x,3,1,1);
+      g_signal_connect(sample_rate_96,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)96000);
+  
+      GtkWidget *sample_rate_192=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_96),"192000");
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_192), active_receiver->sample_rate==192000);
+      gtk_grid_attach(GTK_GRID(grid),sample_rate_192,x,4,1,1);
+      g_signal_connect(sample_rate_192,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)192000);
+
+      GtkWidget *sample_rate_384=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_192),"384000");
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_384), active_receiver->sample_rate==384000);
+      gtk_grid_attach(GTK_GRID(grid),sample_rate_384,x,5,1,1);
+      g_signal_connect(sample_rate_384,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)384000);
+
+#ifndef GPIO
+      GtkWidget *sample_rate_768=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_384),"768000");
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_768), active_receiver->sample_rate==768000);
+      gtk_grid_attach(GTK_GRID(grid),sample_rate_768,x,6,1,1);
+      g_signal_connect(sample_rate_768,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)768000);
+
+      GtkWidget *sample_rate_1536=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_768),"1536000");
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_1536), active_receiver->sample_rate==1536000);
+      gtk_grid_attach(GTK_GRID(grid),sample_rate_1536,x,7,1,1);
+      g_signal_connect(sample_rate_1536,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)1536000);
+#endif
+      }
+      x++;
+      break;
+
+#ifdef LIMESDR
+    case LIMESDR_PROTOCOL:
+      {
+      GtkWidget *sample_rate_label=gtk_label_new("Sample Rate");
+      gtk_grid_attach(GTK_GRID(grid),sample_rate_label,x,1,1,1);
+
+      GtkWidget *sample_rate_1M=gtk_radio_button_new_with_label(NULL,"1000000");
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_1M), active_receiver->sample_rate==1000000);
+      gtk_grid_attach(GTK_GRID(grid),sample_rate_1M,x,2,1,1);
+      g_signal_connect(sample_rate_1M,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)1000000);
+
+      GtkWidget *sample_rate_2M=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_1M),"2000000");
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_2M), active_receiver->sample_rate==2000000);
+      gtk_grid_attach(GTK_GRID(grid),sample_rate_2M,x,3,1,1);
+      g_signal_connect(sample_rate_2M,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)2000000);
+      }
+      x++;
+      break;
+#endif
+  }
+
+  switch(protocol) {
+    case ORIGINAL_PROTOCOL:
+    case NEW_PROTOCOL: 
+      {
+      GtkWidget *dither_b=gtk_check_button_new_with_label("Dither");
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dither_b), active_receiver->dither);
+      gtk_grid_attach(GTK_GRID(grid),dither_b,x,2,1,1);
+      g_signal_connect(dither_b,"toggled",G_CALLBACK(dither_cb),NULL);
+
+      GtkWidget *random_b=gtk_check_button_new_with_label("Random");
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (random_b), active_receiver->random);
+      gtk_grid_attach(GTK_GRID(grid),random_b,x,3,1,1);
+      g_signal_connect(random_b,"toggled",G_CALLBACK(random_cb),NULL);
+
+      if((protocol==ORIGINAL_PROTOCOL && device==DEVICE_METIS) ||
+#ifdef USBOZY
+         (protocol==ORIGINAL_PROTOCOL && device==DEVICE_OZY) ||
+#endif
+         (protocol==NEW_PROTOCOL && device==NEW_DEVICE_ATLAS)) {
+
+        GtkWidget *preamp_b=gtk_check_button_new_with_label("Preamp");
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (preamp_b), active_receiver->preamp);
+        gtk_grid_attach(GTK_GRID(grid),preamp_b,x,4,1,1);
+        g_signal_connect(preamp_b,"toggled",G_CALLBACK(preamp_cb),NULL);
+      }
+      }
+      x++;
+      break;
+    default:
+      break;
+  }
+
+  int n_adc=1;
+  switch(protocol) {
+    case ORIGINAL_PROTOCOL:
+      switch(device) {
+        case DEVICE_METIS:
+          n_adc=1;  // FIX for multiple Mercury cards
+          break;
+        case DEVICE_HERMES:
+        case DEVICE_HERMES_LITE:
+          n_adc=1;
+          break;
+        default: 
+          n_adc=2;
+          break;
+      }
+      break;
+    case NEW_PROTOCOL:
+      switch(device) {
+        case NEW_DEVICE_ATLAS:
+          n_adc=1; // FIX for multiple Mercury cards
+          break;
+        case NEW_DEVICE_HERMES:
+        case NEW_DEVICE_HERMES2:
+        case NEW_DEVICE_HERMES_LITE:
+          n_adc=1;
+          break;
+        default:
+          n_adc=2;
+          break;
+      }
+      break;
+    default:
+      break;
+  }
+
+  if(n_adc>1) {
+    for(i=0;i<n_adc;i++) {
+      sprintf(label,"ADC-%d",i);
+      if(i==0) {
+        adc_b=gtk_radio_button_new_with_label(NULL,label);
+      } else {
+        adc_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(adc_b),label);
+      }
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (adc_b), active_receiver->adc==i);
+      gtk_grid_attach(GTK_GRID(grid),adc_b,x,2+i,1,1);
+      g_signal_connect(adc_b,"pressed",G_CALLBACK(adc_cb),(gpointer *)i);
+    }
+    x++;
+  }
+
+
+  int row=0;
+  if(n_output_devices>0) {
+    GtkWidget *local_audio_b=gtk_check_button_new_with_label("Local Audio Output");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (local_audio_b), active_receiver->local_audio);
+    gtk_widget_show(local_audio_b);
+    gtk_grid_attach(GTK_GRID(grid),local_audio_b,x,++row,1,1);
+    g_signal_connect(local_audio_b,"toggled",G_CALLBACK(local_audio_cb),NULL);
+
+    if(active_receiver->audio_device==-1) active_receiver->audio_device=0;
+
+    for(i=0;i<n_output_devices;i++) {
+      GtkWidget *output;
+      if(i==0) {
+        output=gtk_radio_button_new_with_label(NULL,output_devices[i]);
+      } else {
+        output=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(output),output_devices[i]);
+      }
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (output), active_receiver->audio_device==i);
+      gtk_widget_show(output);
+      gtk_grid_attach(GTK_GRID(grid),output,x,++row,1,1);
+      g_signal_connect(output,"pressed",G_CALLBACK(local_output_changed_cb),(gpointer *)i);
+    }
+
+    row=0;
+    x++;
+
+    GtkWidget *stereo_b=gtk_radio_button_new_with_label(NULL,"Stereo");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (stereo_b), active_receiver->audio_channel==STEREO);
+    gtk_widget_show(stereo_b);
+    gtk_grid_attach(GTK_GRID(grid),stereo_b,x,++row,1,1);
+    g_signal_connect(stereo_b,"toggled",G_CALLBACK(audio_channel_cb),(gpointer)STEREO);
+
+    GtkWidget *left_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(stereo_b),"Left");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (left_b), active_receiver->audio_channel==LEFT);
+    gtk_widget_show(left_b);
+    gtk_grid_attach(GTK_GRID(grid),left_b,x,++row,1,1);
+    g_signal_connect(left_b,"toggled",G_CALLBACK(audio_channel_cb),(gpointer)LEFT);
+
+    GtkWidget *right_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(left_b),"Right");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (right_b), active_receiver->audio_channel==RIGHT);
+    gtk_widget_show(right_b);
+    gtk_grid_attach(GTK_GRID(grid),right_b,x,++row,1,1);
+    g_signal_connect(right_b,"toggled",G_CALLBACK(audio_channel_cb),(gpointer)RIGHT);
+  }
+  
+  gtk_container_add(GTK_CONTAINER(content),grid);
+
+  sub_menu=dialog;
+
+  gtk_widget_show_all(dialog);
+
+}
+
diff --git a/rx_menu.h b/rx_menu.h
new file mode 100644 (file)
index 0000000..5206614
--- /dev/null
+++ b/rx_menu.h
@@ -0,0 +1,20 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+extern void rx_menu(GtkWidget *parent);
diff --git a/rx_panadapter.c b/rx_panadapter.c
new file mode 100644 (file)
index 0000000..45f956d
--- /dev/null
@@ -0,0 +1,410 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <math.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <semaphore.h>
+#include "agc.h"
+#include "band.h"
+#include "channel.h"
+#include "discovered.h"
+#include "radio.h"
+#include "receiver.h"
+#include "transmitter.h"
+#include "rx_panadapter.h"
+#include "vfo.h"
+#include "mode.h"
+#ifdef FREEDV
+#include "freedv.h"
+#endif
+#include "gpio.h"
+
+//static float panadapter_max=-60.0;
+//static float panadapter_min=-160.0;
+
+static gfloat filter_left;
+static gfloat filter_right;
+
+/* Create a new surface of the appropriate size to store our scribbles */
+static gboolean
+panadapter_configure_event_cb (GtkWidget         *widget,
+            GdkEventConfigure *event,
+            gpointer           data)
+{
+
+  RECEIVER *rx=(RECEIVER *)data;
+
+  int display_width=gtk_widget_get_allocated_width (widget);
+  int display_height=gtk_widget_get_allocated_height (widget);
+
+  if (rx->panadapter_surface)
+    cairo_surface_destroy (rx->panadapter_surface);
+
+  rx->panadapter_surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget),
+                                       CAIRO_CONTENT_COLOR,
+                                       display_width,
+                                       display_height);
+
+  cairo_t *cr=cairo_create(rx->panadapter_surface);
+  cairo_set_source_rgb(cr, 0, 0, 0);
+  cairo_paint(cr);
+  cairo_destroy(cr);
+  return TRUE;
+}
+
+/* Redraw the screen from the surface. Note that the ::draw
+ * signal receives a ready-to-be-used cairo_t that is already
+ * clipped to only draw the exposed areas of the widget
+ */
+static gboolean
+panadapter_draw_cb (GtkWidget *widget,
+ cairo_t   *cr,
+ gpointer   data)
+{
+  RECEIVER *rx=(RECEIVER *)data;
+  if(rx->panadapter_surface) {
+    cairo_set_source_surface (cr, rx->panadapter_surface, 0, 0);
+    cairo_paint (cr);
+  }
+
+  return TRUE;
+}
+
+static gboolean panadapter_button_press_event_cb(GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  return receiver_button_press_event(widget,event,data);
+}
+
+static gboolean panadapter_button_release_event_cb(GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  return receiver_button_release_event(widget,event,data);
+}
+
+static gboolean panadapter_motion_notify_event_cb(GtkWidget *widget, GdkEventMotion *event, gpointer data) {
+  return receiver_motion_notify_event(widget,event,data);
+}
+
+static gboolean panadapter_scroll_event_cb(GtkWidget *widget, GdkEventScroll *event, gpointer data) {
+  return receiver_scroll_event(widget,event,data);
+}
+
+void rx_panadapter_update(RECEIVER *rx) {
+  int i;
+  int result;
+  float *samples;
+  float saved_max;
+  float saved_min;
+  cairo_text_extents_t extents;
+
+  gboolean active=active_receiver==rx;
+
+  int display_width=gtk_widget_get_allocated_width (rx->panadapter);
+  int display_height=gtk_widget_get_allocated_height (rx->panadapter);
+
+  samples=rx->pixel_samples;
+
+  //clear_panadater_surface();
+  cairo_t *cr;
+  cr = cairo_create (rx->panadapter_surface);
+  cairo_set_source_rgb (cr, 0, 0, 0);
+  cairo_rectangle(cr,0,0,display_width,display_height);
+  cairo_fill(cr);
+  //cairo_paint (cr);
+
+  // filter
+  cairo_set_source_rgb (cr, 0.25, 0.25, 0.25);
+  filter_left=(double)display_width/2.0+(((double)rx->filter_low+vfo[rx->id].offset)/rx->hz_per_pixel);
+  filter_right=(double)display_width/2.0+(((double)rx->filter_high+vfo[rx->id].offset)/rx->hz_per_pixel);
+  cairo_rectangle(cr, filter_left, 0.0, filter_right-filter_left, (double)display_height);
+  cairo_fill(cr);
+
+  // plot the levels
+  if(active) {
+    cairo_set_source_rgb (cr, 0, 1, 1);
+  } else {
+    cairo_set_source_rgb (cr, 0, 0.5, 0.5);
+  }
+
+  double dbm_per_line=(double)display_height/((double)rx->panadapter_high-(double)rx->panadapter_low);
+  cairo_set_line_width(cr, 1.0);
+  cairo_select_font_face(cr, "FreeMono", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
+  cairo_set_font_size(cr, 12);
+  char v[32];
+
+  for(i=rx->panadapter_high;i>=rx->panadapter_low;i--) {
+    int mod=abs(i)%20;
+    if(mod==0) {
+      double y = (double)(rx->panadapter_high-i)*dbm_per_line;
+      cairo_move_to(cr,0.0,y);
+      cairo_line_to(cr,(double)display_width,y);
+
+      sprintf(v,"%d dBm",i);
+      cairo_move_to(cr, 1, y);  
+      cairo_show_text(cr, v);
+    }
+  }
+  cairo_stroke(cr);
+
+  // plot frequency markers
+  long long f;
+  long divisor=20000;
+  long half=(long)rx->sample_rate/2L;
+  long long frequency=vfo[rx->id].frequency;
+  switch(rx->sample_rate) {
+    case 48000:
+      divisor=5000L;
+      break;
+    case 96000:
+    case 100000:
+      divisor=10000L;
+      break;
+    case 192000:
+      divisor=20000L;
+      break;
+    case 384000:
+      divisor=25000L;
+      break;
+    case 768000:
+      divisor=50000L;
+      break;
+    case 1048576:
+    case 1536000:
+    case 2097152:
+      divisor=100000L;
+      break;
+  }
+  for(i=0;i<display_width;i++) {
+    f = frequency - half + (long) (rx->hz_per_pixel * i);
+    if (f > 0) {
+      if ((f % divisor) < (long) rx->hz_per_pixel) {
+        cairo_set_line_width(cr, 1.0);
+        //cairo_move_to(cr,(double)i,0.0);
+        cairo_move_to(cr,(double)i,10.0);
+        cairo_line_to(cr,(double)i,(double)display_height);
+
+        cairo_select_font_face(cr, "FreeMono",
+                            CAIRO_FONT_SLANT_NORMAL,
+                            CAIRO_FONT_WEIGHT_BOLD);
+        cairo_set_font_size(cr, 12);
+        char v[32];
+        sprintf(v,"%0lld.%03lld",f/1000000,(f%1000000)/1000);
+        //cairo_move_to(cr, (double)i, (double)(display_height-10));  
+        cairo_text_extents(cr, v, &extents);
+        cairo_move_to(cr, (double)i-(extents.width/2.0), 10.0);  
+        cairo_show_text(cr, v);
+      }
+    }
+  }
+  cairo_stroke(cr);
+
+  // band edges
+  long long min_display=frequency-half;
+  long long max_display=frequency+half;
+  BAND *band=band_get_band(vfo[rx->id].band);
+  if(band->frequencyMin!=0LL) {
+    cairo_set_source_rgb (cr, 1, 0, 0);
+    cairo_set_line_width(cr, 2.0);
+    if((min_display<band->frequencyMin)&&(max_display>band->frequencyMin)) {
+      i=(band->frequencyMin-min_display)/(long long)rx->hz_per_pixel;
+      cairo_move_to(cr,(double)i,0.0);
+      cairo_line_to(cr,(double)i,(double)display_height);
+      cairo_stroke(cr);
+    }
+    if((min_display<band->frequencyMax)&&(max_display>band->frequencyMax)) {
+      i=(band->frequencyMax-min_display)/(long long)rx->hz_per_pixel;
+      cairo_move_to(cr,(double)i,0.0);
+      cairo_line_to(cr,(double)i,(double)display_height);
+      cairo_stroke(cr);
+    }
+  }
+            
+  // agc
+  if(rx->agc!=AGC_OFF) {
+    double hang=0.0;
+    double thresh=0;
+
+    GetRXAAGCHangLevel(rx->id, &hang);
+    GetRXAAGCThresh(rx->id, &thresh, 4096.0, (double)rx->sample_rate);
+
+    double knee_y=thresh+(double)get_attenuation();
+    knee_y = floor((rx->panadapter_high - knee_y)
+                        * (double) display_height
+                        / (rx->panadapter_high - rx->panadapter_low));
+
+    double hang_y=hang+(double)get_attenuation();
+    hang_y = floor((rx->panadapter_high - hang_y)
+                        * (double) display_height
+                        / (rx->panadapter_high - rx->panadapter_low));
+
+//fprintf(stderr,"hang=%f thresh=%f hang_y=%f knee_y=%f\n",rx1_hang,rx1_thresh,hang_y,knee_y);
+    if(rx->agc!=AGC_MEDIUM && rx->agc!=AGC_FAST) {
+      if(active) {
+        cairo_set_source_rgb (cr, 1.0, 1.0, 0.0);
+      } else {
+        cairo_set_source_rgb (cr, 0.5, 0.5, 0.0);
+      }
+      cairo_move_to(cr,40.0,hang_y-8.0);
+      cairo_rectangle(cr, 40, hang_y-8.0,8.0,8.0);
+      cairo_fill(cr);
+      cairo_move_to(cr,40.0,hang_y);
+      cairo_line_to(cr,(double)display_width-40.0,hang_y);
+      cairo_stroke(cr);
+      cairo_move_to(cr,48.0,hang_y);
+      cairo_show_text(cr, "-H");
+    }
+
+    if(active) {
+      cairo_set_source_rgb (cr, 0.0, 1.0, 0.0);
+    } else {
+      cairo_set_source_rgb (cr, 0.0, 0.5, 0.0);
+    }
+    cairo_move_to(cr,40.0,knee_y-8.0);
+    cairo_rectangle(cr, 40, knee_y-8.0,8.0,8.0);
+    cairo_fill(cr);
+    cairo_move_to(cr,40.0,knee_y);
+    cairo_line_to(cr,(double)display_width-40.0,knee_y);
+    cairo_stroke(cr);
+    cairo_move_to(cr,48.0,knee_y);
+    cairo_show_text(cr, "-G");
+  }
+
+
+  // cursor
+  if(active) {
+    cairo_set_source_rgb (cr, 1, 0, 0);
+  } else {
+    cairo_set_source_rgb (cr, 0.5, 0, 0);
+  }
+  cairo_set_line_width(cr, 1.0);
+  cairo_move_to(cr,(double)(display_width/2.0)+(vfo[rx->id].offset/rx->hz_per_pixel),0.0);
+  cairo_line_to(cr,(double)(display_width/2.0)+(vfo[rx->id].offset/rx->hz_per_pixel),(double)display_height);
+  cairo_stroke(cr);
+
+  // signal
+  double s1,s2;
+  samples[0]=-200.0;
+  samples[display_width-1]=-200.0;
+
+  s1=(double)samples[0]+(double)get_attenuation();
+  s1 = floor((rx->panadapter_high - s1)
+                        * (double) display_height
+                        / (rx->panadapter_high - rx->panadapter_low));
+  cairo_move_to(cr, 0.0, s1);
+  for(i=1;i<display_width;i++) {
+    s2=(double)samples[i]+(double)get_attenuation();
+    s2 = floor((rx->panadapter_high - s2)
+                            * (double) display_height
+                            / (rx->panadapter_high - rx->panadapter_low));
+    cairo_line_to(cr, (double)i, s2);
+  }
+
+  if(display_filled) {
+    cairo_close_path (cr);
+    if(active) {
+      cairo_set_source_rgba(cr, 1, 1, 1,0.5);
+    } else {
+      cairo_set_source_rgba(cr, 0.5, 0.5, 0.5,0.5);
+    }
+    cairo_fill_preserve (cr);
+  }
+  if(active) {
+    cairo_set_source_rgb(cr, 1, 1, 1);
+  } else {
+    cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
+  }
+  cairo_set_line_width(cr, 1.0);
+  cairo_stroke(cr);
+
+#ifdef FREEDV
+  int mode=rx->mode;
+  if(mode==modeFREEDV) {
+    cairo_set_source_rgb(cr, 0, 1, 0);
+    cairo_set_font_size(cr, 16);
+    cairo_text_extents(cr, freedv_text_data, &extents);
+    cairo_move_to(cr, (double)display_width/2.0-(extents.width/2.0),(double)display_height-2.0);
+    cairo_show_text(cr, freedv_text_data);
+  }
+#endif
+
+#ifdef GPIO
+  if(active) {
+    cairo_set_source_rgb(cr,1,1,0);
+    cairo_set_font_size(cr,12);
+    if(ENABLE_E1_ENCODER) {
+      cairo_move_to(cr, display_width-100,20);
+      cairo_show_text(cr, encoder_string[e1_encoder_action]);
+    }
+
+    if(ENABLE_E2_ENCODER) {
+      cairo_move_to(cr, display_width-100,40);
+      cairo_show_text(cr, encoder_string[e2_encoder_action]);
+    }
+
+    if(ENABLE_E3_ENCODER) {
+      cairo_move_to(cr, display_width-100,60);
+      cairo_show_text(cr, encoder_string[e3_encoder_action]);
+    }
+  }
+#endif
+
+  cairo_destroy (cr);
+  gtk_widget_queue_draw (rx->panadapter);
+
+}
+
+void rx_panadapter_init(RECEIVER *rx, int width,int height) {
+
+  int display_width=width;
+  int display_height=height;
+
+  rx->panadapter_surface=NULL;
+  rx->panadapter = gtk_drawing_area_new ();
+  gtk_widget_set_size_request (rx->panadapter, width, height);
+
+  /* Signals used to handle the backing surface */
+  g_signal_connect (rx->panadapter, "draw",
+            G_CALLBACK (panadapter_draw_cb), rx);
+  g_signal_connect (rx->panadapter,"configure-event",
+            G_CALLBACK (panadapter_configure_event_cb), rx);
+
+  /* Event signals */
+  g_signal_connect (rx->panadapter, "motion-notify-event",
+            G_CALLBACK (panadapter_motion_notify_event_cb), rx);
+  g_signal_connect (rx->panadapter, "button-press-event",
+            G_CALLBACK (panadapter_button_press_event_cb), rx);
+  g_signal_connect (rx->panadapter, "button-release-event",
+            G_CALLBACK (panadapter_button_release_event_cb), rx);
+  g_signal_connect(rx->panadapter,"scroll_event",
+            G_CALLBACK(panadapter_scroll_event_cb),rx);
+
+  /* Ask to receive events the drawing area doesn't normally
+   * subscribe to. In particular, we need to ask for the
+   * button press and motion notify events that want to handle.
+   */
+  gtk_widget_set_events (rx->panadapter, gtk_widget_get_events (rx->panadapter)
+                     | GDK_BUTTON_PRESS_MASK
+                     | GDK_BUTTON_RELEASE_MASK
+                     | GDK_BUTTON1_MOTION_MASK
+                     | GDK_SCROLL_MASK
+                     | GDK_POINTER_MOTION_MASK
+                     | GDK_POINTER_MOTION_HINT_MASK);
+
+}
diff --git a/rx_panadapter.h b/rx_panadapter.h
new file mode 100644 (file)
index 0000000..3481d8a
--- /dev/null
@@ -0,0 +1,28 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#ifndef _PANADAPTER_H
+#define _PANADAPTER_H
+
+void rx_panadapter_update(RECEIVER* rx);
+
+void rx_panadapter_init(RECEIVER *rx,int width,int height);
+
+
+#endif
index d33cf947973e03bf31a14569324df886907898c9..4b0290466bee0b3a383d85ec6dd4d78ff24048f7 100644 (file)
--- a/sliders.c
+++ b/sliders.c
 #include "channel.h"
 #include "wdsp.h"
 #include "radio.h"
+#include "receiver.h"
 #include "property.h"
+#include "main.h"
 
 static int width;
 static int height;
 
-static GtkWidget *parent_window;
 static GtkWidget *sliders;
 
 #define NONE 0
@@ -76,7 +77,7 @@ static GtkWidget *dummy_label;
 static GdkRGBA white;
 static GdkRGBA gray;
 
-void linein_changed() {
+int linein_changed(void *data) {
   if(display_sliders) {
     if(mic_linein) {
       gtk_widget_hide(mic_gain_label);
@@ -90,6 +91,15 @@ void linein_changed() {
       gtk_widget_show(mic_gain_scale);
     }
   }
+  return 0;
+}
+
+int active_receiver_changed(void *data) {
+  if(display_sliders) {
+    gtk_range_set_value(GTK_RANGE(af_gain_scale),active_receiver->volume*100.0);
+    gtk_range_set_value (GTK_RANGE(agc_scale),active_receiver->agc_gain);
+    gtk_range_set_value (GTK_RANGE(attenuation_scale),active_receiver->attenuation);
+  }
 }
 
 int scale_timeout_cb(gpointer data) {
@@ -99,14 +109,14 @@ int scale_timeout_cb(gpointer data) {
 }
 
 static void attenuation_value_changed_cb(GtkWidget *widget, gpointer data) {
-  attenuation=(int)gtk_range_get_value(GTK_RANGE(attenuation_scale));
-  set_attenuation(attenuation);
+  active_receiver->attenuation=(int)gtk_range_get_value(GTK_RANGE(attenuation_scale));
+  set_attenuation(active_receiver->attenuation);
 }
 
 void set_attenuation_value(double value) {
-  attenuation=(int)value;
+  active_receiver->attenuation=(int)value;
   if(display_sliders) {
-    gtk_range_set_value (GTK_RANGE(attenuation_scale),attenuation);
+    gtk_range_set_value (GTK_RANGE(attenuation_scale),active_receiver->attenuation);
   } else {
     if(scale_status!=ATTENUATION) {
       if(scale_status!=NONE) {
@@ -117,11 +127,11 @@ void set_attenuation_value(double value) {
     }
     if(scale_status==NONE) {
       scale_status=ATTENUATION;
-      scale_dialog=gtk_dialog_new_with_buttons("Attenuation (dB)",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+      scale_dialog=gtk_dialog_new_with_buttons("Attenuation (dB)",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
       GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
       attenuation_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 31.0, 1.00);
       gtk_widget_set_size_request (attenuation_scale, 400, 30);
-      gtk_range_set_value (GTK_RANGE(attenuation_scale),attenuation);
+      gtk_range_set_value (GTK_RANGE(attenuation_scale),active_receiver->attenuation);
       gtk_widget_show(attenuation_scale);
       gtk_container_add(GTK_CONTAINER(content),attenuation_scale);
       scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
@@ -129,23 +139,23 @@ void set_attenuation_value(double value) {
       int result=gtk_dialog_run(GTK_DIALOG(scale_dialog));
     } else {
       g_source_remove(scale_timer);
-      gtk_range_set_value (GTK_RANGE(attenuation_scale),attenuation);
+      gtk_range_set_value (GTK_RANGE(attenuation_scale),active_receiver->attenuation);
       scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
     }
   }
-  set_attenuation(attenuation);
+  set_attenuation(active_receiver->attenuation);
 }
 
 static void agcgain_value_changed_cb(GtkWidget *widget, gpointer data) {
-  agc_gain=gtk_range_get_value(GTK_RANGE(agc_scale));
-  SetRXAAGCTop(CHANNEL_RX0, agc_gain);
+  active_receiver->agc_gain=gtk_range_get_value(GTK_RANGE(agc_scale));
+  SetRXAAGCTop(active_receiver->id, active_receiver->agc_gain);
 }
 
 void set_agc_gain(double value) {
-  agc_gain=value;
-  SetRXAAGCTop(CHANNEL_RX0, agc_gain);
+  active_receiver->agc_gain=value;
+  SetRXAAGCTop(active_receiver->id, active_receiver->agc_gain);
   if(display_sliders) {
-    gtk_range_set_value (GTK_RANGE(agc_scale),agc_gain);
+    gtk_range_set_value (GTK_RANGE(agc_scale),active_receiver->agc_gain);
   } else {
     if(scale_status!=AGC_GAIN) {
       if(scale_status!=NONE) {
@@ -156,11 +166,11 @@ void set_agc_gain(double value) {
     }
     if(scale_status==NONE) {
       scale_status=AGC_GAIN;
-      scale_dialog=gtk_dialog_new_with_buttons("AGC Gain",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+      scale_dialog=gtk_dialog_new_with_buttons("AGC Gain",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
       GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
       agc_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,-20.0, 120.0, 1.00);
       gtk_widget_set_size_request (agc_scale, 400, 30);
-      gtk_range_set_value (GTK_RANGE(agc_scale),agc_gain);
+      gtk_range_set_value (GTK_RANGE(agc_scale),active_receiver->agc_gain);
       gtk_widget_show(agc_scale);
       gtk_container_add(GTK_CONTAINER(content),agc_scale);
       scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
@@ -168,7 +178,7 @@ void set_agc_gain(double value) {
       int result=gtk_dialog_run(GTK_DIALOG(scale_dialog));
     } else {
       g_source_remove(scale_timer);
-      gtk_range_set_value (GTK_RANGE(agc_scale),agc_gain);
+      gtk_range_set_value (GTK_RANGE(agc_scale),active_receiver->agc_gain);
       scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
     }
   }
@@ -181,20 +191,20 @@ int update_agc_gain(void *data) {
 }
 
 static void afgain_value_changed_cb(GtkWidget *widget, gpointer data) {
-    volume=gtk_range_get_value(GTK_RANGE(af_gain_scale))/100.0;
-    SetRXAPanelGain1 (CHANNEL_RX0, volume);
+    active_receiver->volume=gtk_range_get_value(GTK_RANGE(af_gain_scale))/100.0;
+    SetRXAPanelGain1 (active_receiver->id, active_receiver->volume);
 }
 
 int update_af_gain(void *data) {
-  set_af_gain(volume);
+  set_af_gain(active_receiver->volume);
   return 0;
 }
 
 void set_af_gain(double value) {
-  volume=value;
-  SetRXAPanelGain1 (CHANNEL_RX0, volume);
+  active_receiver->volume=value;
+  SetRXAPanelGain1 (active_receiver->id, active_receiver->volume);
   if(display_sliders) {
-    gtk_range_set_value (GTK_RANGE(af_gain_scale),volume*100.0);
+    gtk_range_set_value (GTK_RANGE(af_gain_scale),active_receiver->volume*100.0);
   } else {
     if(scale_status!=AF_GAIN) {
       if(scale_status!=NONE) {
@@ -205,11 +215,11 @@ void set_af_gain(double value) {
     }
     if(scale_status==NONE) {
       scale_status=AF_GAIN;
-      scale_dialog=gtk_dialog_new_with_buttons("AF Gain",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+      scale_dialog=gtk_dialog_new_with_buttons("AF Gain",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
       GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
       af_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 100.0, 1.00);
       gtk_widget_set_size_request (af_gain_scale, 400, 30);
-      gtk_range_set_value (GTK_RANGE(af_gain_scale),volume*100.0);
+      gtk_range_set_value (GTK_RANGE(af_gain_scale),active_receiver->volume*100.0);
       gtk_widget_show(af_gain_scale);
       gtk_container_add(GTK_CONTAINER(content),af_gain_scale);
       scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
@@ -217,7 +227,7 @@ void set_af_gain(double value) {
       int result=gtk_dialog_run(GTK_DIALOG(scale_dialog));
     } else {
       g_source_remove(scale_timer);
-      gtk_range_set_value (GTK_RANGE(af_gain_scale),volume*100.0);
+      gtk_range_set_value (GTK_RANGE(af_gain_scale),active_receiver->volume*100.0);
       scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
     }
   }
@@ -226,13 +236,13 @@ void set_af_gain(double value) {
 static void micgain_value_changed_cb(GtkWidget *widget, gpointer data) {
     mic_gain=gtk_range_get_value(GTK_RANGE(widget));
     double gain=pow(10.0, mic_gain / 20.0);
-    SetTXAPanelGain1(CHANNEL_TX,gain);
+    SetTXAPanelGain1(transmitter->id,gain);
 }
 
 void set_mic_gain(double value) {
   mic_gain=value;
   double gain=pow(10.0, mic_gain / 20.0);
-  SetTXAPanelGain1(CHANNEL_TX,gain);
+  SetTXAPanelGain1(transmitter->id,gain);
   if(display_sliders) {
     gtk_range_set_value (GTK_RANGE(mic_gain_scale),mic_gain);
   } else {
@@ -245,7 +255,7 @@ void set_mic_gain(double value) {
     }
     if(scale_status==NONE) {
       scale_status=MIC_GAIN;
-      scale_dialog=gtk_dialog_new_with_buttons("Mic Gain (dB)",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+      scale_dialog=gtk_dialog_new_with_buttons("Mic Gain (dB)",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
       GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
       mic_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,-10.0, 50.0, 1.00);
       gtk_widget_set_size_request (mic_gain_scale, 400, 30);
@@ -288,7 +298,7 @@ void set_linein_gain(int value) {
     }
     if(scale_status==NONE) {
       scale_status=LINEIN_GAIN;
-      scale_dialog=gtk_dialog_new_with_buttons("Linein Gain",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+      scale_dialog=gtk_dialog_new_with_buttons("Linein Gain",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
       GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
       linein_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 31.0, 1.00);
       gtk_widget_set_size_request (linein_gain_scale, 400, 30);
@@ -327,7 +337,7 @@ void set_drive(double value) {
     }
     if(scale_status==NONE) {
       scale_status=DRIVE;
-      scale_dialog=gtk_dialog_new_with_buttons("Drive",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+      scale_dialog=gtk_dialog_new_with_buttons("Drive",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
       GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
       drive_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 100.0, 1.00);
       gtk_widget_set_size_request (drive_scale, 400, 30);
@@ -369,7 +379,7 @@ void set_tune(double value) {
     }
     if(scale_status==NONE) {
       scale_status=TUNE_DRIVE;
-      scale_dialog=gtk_dialog_new_with_buttons("Tune Drive",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+      scale_dialog=gtk_dialog_new_with_buttons("Tune Drive",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
       GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
       tune_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 100.0, 1.00);
       gtk_widget_set_size_request (tune_scale, 400, 30);
@@ -391,10 +401,9 @@ static void tune_value_changed_cb(GtkWidget *widget, gpointer data) {
   setTuneDrive(gtk_range_get_value(GTK_RANGE(tune_scale)));
 }
 
-GtkWidget *sliders_init(int my_width, int my_height, GtkWidget* parent) {
+GtkWidget *sliders_init(int my_width, int my_height) {
     width=my_width;
     height=my_height;
-    parent_window=parent;
 
     fprintf(stderr,"sliders_init: width=%d height=%d\n", width,height);
 
@@ -409,7 +418,7 @@ GtkWidget *sliders_init(int my_width, int my_height, GtkWidget* parent) {
   gtk_grid_attach(GTK_GRID(sliders),af_gain_label,0,0,1,1);
 
   af_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 100.0, 1.00);
-  gtk_range_set_value (GTK_RANGE(af_gain_scale),volume*100.0);
+  gtk_range_set_value (GTK_RANGE(af_gain_scale),active_receiver->volume*100.0);
   gtk_widget_show(af_gain_scale);
   gtk_grid_attach(GTK_GRID(sliders),af_gain_scale,1,0,2,1);
   g_signal_connect(G_OBJECT(af_gain_scale),"value_changed",G_CALLBACK(afgain_value_changed_cb),NULL);
@@ -420,7 +429,7 @@ GtkWidget *sliders_init(int my_width, int my_height, GtkWidget* parent) {
   gtk_grid_attach(GTK_GRID(sliders),agc_gain_label,3,0,1,1);
 
   agc_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,-20.0, 120.0, 1.0);
-  gtk_range_set_value (GTK_RANGE(agc_scale),agc_gain);
+  gtk_range_set_value (GTK_RANGE(agc_scale),active_receiver->agc_gain);
   gtk_widget_show(agc_scale);
   gtk_grid_attach(GTK_GRID(sliders),agc_scale,4,0,2,1);
   g_signal_connect(G_OBJECT(agc_scale),"value_changed",G_CALLBACK(agcgain_value_changed_cb),NULL);
@@ -431,7 +440,7 @@ GtkWidget *sliders_init(int my_width, int my_height, GtkWidget* parent) {
   gtk_grid_attach(GTK_GRID(sliders),attenuation_label,6,0,1,1);
 
   attenuation_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 31.0, 1.0);
-  gtk_range_set_value (GTK_RANGE(attenuation_scale),attenuation);
+  gtk_range_set_value (GTK_RANGE(attenuation_scale),active_receiver->attenuation);
   gtk_widget_show(attenuation_scale);
   gtk_grid_attach(GTK_GRID(sliders),attenuation_scale,7,0,2,1);
   g_signal_connect(G_OBJECT(attenuation_scale),"value_changed",G_CALLBACK(attenuation_value_changed_cb),NULL);
index 1601753b126113d6a63adfd3560cab186360628c..17aa927166c8b2520a579639e19a998f7a4dc9cd 100644 (file)
--- a/sliders.h
+++ b/sliders.h
 #ifndef _SLIDERS_H
 #define _SLIDERS_H
 
-extern void linein_changed();
+extern int linein_changed(void *data);
+extern int active_receiver_changed(void *data);
 extern int update_agc_gain(void *);
 extern int update_af_gain(void *);
 extern int update_mic_gain(void *);
 extern int update_drive(void *);
 
-void set_agc_gain(double value);
-void set_af_gain(double value);
-void set_mic_gain(double value);
-void set_drive(double drive);
-void set_tune(double tune);
-void set_attenuation_value(double attenuation);
-GtkWidget *sliders_init(int my_width, int my_height, GtkWidget* parent);
+extern void set_agc_gain(double value);
+extern void set_af_gain(double value);
+extern void set_mic_gain(double value);
+extern void set_drive(double drive);
+extern void set_tune(double tune);
+extern void set_attenuation_value(double attenuation);
+extern GtkWidget *sliders_init(int my_width, int my_height);
 
 #endif
diff --git a/soundio.c b/soundio.c
new file mode 100644 (file)
index 0000000..622d54a
--- /dev/null
+++ b/soundio.c
@@ -0,0 +1,477 @@
+/* Copyright (C)
+* 2016 - John Melton, G0ORX/N6LYT
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+
+#include <gtk/gtk.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <sched.h>
+#include <semaphore.h>
+
+#include <soundio/soundio.h>
+
+#include "new_protocol.h"
+#include "old_protocol.h"
+#include "radio.h"
+#include "receiver.h"
+#include "audio.h"
+
+int audio = 0;
+int audio_buffer_size = 256; // samples (both left and right)
+int mic_buffer_size = 720; // samples (both left and right)
+
+//static snd_pcm_t *playback_handle=NULL;
+static snd_pcm_t *record_handle=NULL;
+
+// each buffer contains 63 samples of left and right audio at 16 bits
+#define AUDIO_SAMPLES 63
+#define AUDIO_SAMPLE_SIZE 2
+#define AUDIO_CHANNELS 2
+#define AUDIO_BUFFERS 10
+#define OUTPUT_BUFFER_SIZE (AUDIO_SAMPLE_SIZE*AUDIO_CHANNELS*audio_buffer_size)
+
+#define MIC_BUFFER_SIZE (AUDIO_SAMPLE_SIZE*AUDIO_CHANNELS*mic_buffer_size)
+
+//static unsigned char *audio_buffer=NULL;
+//static int audio_offset=0;
+
+static unsigned char *mic_buffer=NULL;
+
+static GThread *mic_read_thread_id;
+
+static int running=FALSE;
+
+static void *mic_read_thread(void *arg);
+
+char *input_devices[16];
+int n_input_devices=0;
+int n_selected_input_device=-1;
+
+char *output_devices[16];
+int n_output_devices=0;
+//int n_selected_output_device=-1;
+
+static double seconds_offset=0.0;
+static int want_pause=0;
+
+#define BUFFER_SIZE 8192
+
+static struct SoundIo *soundio;
+static struct SoundIoDevice *audio_device;
+static struct SoundIoOutStream *outstream;
+
+static short output_left_buffer[BUFFER_SIZE];
+static short output_right_buffer[BUFFER_SIZE];
+static int insert_index=0;
+static int remove_index=0;
+static int frames=0;
+
+static void write_callback(struct SoundIoOutStream *outstream, int frame_count_min, int frame_count_max) {
+//fprintf(stderr,"write_callback: min=%d max=%d frames=%d insert_index=%d remove_index=%d\n",frame_count_min, frame_count_max, frames, insert_index, remove_index);
+  double float_sample_rate = outstream->sample_rate;
+  double seconds_per_frame = 1.0 / float_sample_rate;
+  struct SoundIoChannelArea *areas;
+  int err;
+  int frame;
+  int channel;
+
+  if(frames!=0) {
+    int frames_left = frames;
+    if(frames>frame_count_max) {
+      frames_left=frame_count_max;
+    }
+    if ((err = soundio_outstream_begin_write(outstream, &areas, &frames_left))) {
+      fprintf(stderr, "unrecoverable stream error: %s\n", soundio_strerror(err));
+      exit(1);
+    }
+
+    const struct SoundIoChannelLayout *layout = &outstream->layout;
+
+    for (frame=0; frame < frames_left; frame += 1) {
+      for (channel = 0; channel < layout->channel_count; channel += 1) {
+        int16_t *s=(int16_t *)areas[channel].ptr;
+        if(channel==0) {
+          *s=output_left_buffer[remove_index];
+        } else {
+          *s=output_right_buffer[remove_index];
+        }
+        areas[channel].ptr += areas[channel].step;
+      } 
+      frames--;
+      remove_index++;
+      if(remove_index==BUFFER_SIZE) {
+        remove_index=0;
+      }
+    }
+    //seconds_offset += seconds_per_frame * frame_count;
+
+    if ((err = soundio_outstream_end_write(outstream))) {
+      if (err == SoundIoErrorUnderflow)
+         return;
+      fprintf(stderr, "unrecoverable stream error: %s\n", soundio_strerror(err));
+      exit(1);
+    }
+  } else {
+    //fprintf(stderr,"audio.c: write_callback: underflow: frames=%d insert_index=%d remove_index=%d\n",frames,insert_index,remove_index);
+  }
+}
+
+static void underflow_callback(struct SoundIoOutStream *outstream) {
+    static int count = 0;
+    //fprintf(stderr, "underflow %d\n", count++);
+}
+
+int audio_open_output(RECEIVER *rx) {
+
+  int err;
+
+fprintf(stderr,"audio_open_output: id=%d device=%d\n", rx->id,rx->audio_device);
+  soundio = soundio_create();
+  if (!soundio) {
+    fprintf(stderr, "audio_open_output: soundio_create failed\n");
+    return -1;
+  }
+
+  soundio_connect(soundio);
+
+  soundio_flush_events(soundio);
+
+  audio_device = soundio_get_output_device(soundio, rx->audio_device);
+  if(!audio_device) {
+    fprintf(stderr, "audio_open_output: soundio_get_output_device failed\n");
+    return -1;
+  }
+
+  if (audio_device->probe_error) {
+    fprintf(stderr, "audio_open_output: Cannot probe audio_device: %s\n", soundio_strerror(audio_device->probe_error));
+    return -1;
+  }
+
+  outstream = soundio_outstream_create(audio_device);
+  outstream->write_callback = write_callback;
+  outstream->underflow_callback = underflow_callback;
+  outstream->name = "pihpsdr:out";
+  outstream->software_latency = 0.0;
+  outstream->sample_rate = 48000;
+
+  if (soundio_device_supports_format(audio_device, SoundIoFormatS16LE)) {
+    outstream->format = SoundIoFormatS16LE;
+  } else {
+    fprintf(stderr,"audio_open_output: audio_device does not support S16LE\n");
+    return -1;
+  }
+
+  if ((err = soundio_outstream_open(outstream))) {
+    fprintf(stderr, "audio_open_output: unable to open audio_device: %s", soundio_strerror(err));
+    return -1;
+  }
+  fprintf(stderr, "audio_open_output: Software latency: %f\n", outstream->software_latency);
+
+  if (outstream->layout_error) {
+    fprintf(stderr, "audio_open_output: unable to set channel layout: %s\n", soundio_strerror(outstream->layout_error));
+  }
+
+  if ((err = soundio_outstream_start(outstream))) {
+    fprintf(stderr, "audio_open_output: unable to start audio_device: %s\n", soundio_strerror(err));
+    return -1;
+  }
+
+  return 0;
+}
+       
+int audio_open_input() {
+/*
+  int err;
+  snd_pcm_hw_params_t *hw_params;
+  int rate=48000;
+  int dir=0;
+
+fprintf(stderr,"audio_open_input: %d\n",n_selected_input_device);
+  if(n_selected_input_device<0 || n_selected_input_device>=n_input_devices) {
+    n_selected_input_device=-1;
+    return -1;
+  }
+
+  int i;
+  char hw[16];
+  char *selected=input_devices[n_selected_input_device];
+  fprintf(stderr,"audio_open_input: selected=%d:%s\n",n_selected_input_device,selected);
+  
+  switch(protocol) {
+    case ORIGINAL_PROTOCOL:
+      mic_buffer_size = 720;
+      break;
+    case NEW_PROTOCOL:
+      mic_buffer_size = 64;
+      break;
+    default:
+      break;
+  }
+  
+  fprintf(stderr,"audio_open_input: mic_buffer_size=%d\n",mic_buffer_size);
+  i=0;
+  while(selected[i]!=' ') {
+    hw[i]=selected[i];
+    i++;
+  }
+  hw[i]='\0';
+
+  fprintf(stderr,"audio_open_input: hw=%s\n",hw);
+
+  if ((err = snd_pcm_open (&record_handle, hw, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
+    fprintf (stderr, "audio_open_input: cannot open audio device %s (%s)\n",
+            hw,
+            snd_strerror (err));
+    return -1;
+  }
+
+  if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
+    fprintf (stderr, "audio_open_input: cannot allocate hardware parameter structure (%s)\n",
+            snd_strerror (err));
+    return -1;
+  }
+
+  if ((err = snd_pcm_hw_params_any (record_handle, hw_params)) < 0) {
+    fprintf (stderr, "audio_open_input: cannot initialize hardware parameter structure (%s)\n",
+            snd_strerror (err));
+    return -1;
+  }
+
+  if ((err = snd_pcm_hw_params_set_access (record_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+    fprintf (stderr, "audio_open_input: cannot set access type (%s)\n",
+            snd_strerror (err));
+    return -1;
+}
+
+  if ((err = snd_pcm_hw_params_set_format (record_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
+    fprintf (stderr, "audio_open_input: cannot set sample format (%s)\n",
+            snd_strerror (err));
+    return -1;
+  }
+
+  if ((err = snd_pcm_hw_params_set_rate_near (record_handle, hw_params, &rate, &dir)) < 0) {
+    fprintf (stderr, "audio_open_input: cannot set sample rate (%s)\n",
+            snd_strerror (err));
+    return -1;
+  }
+
+  if ((err = snd_pcm_hw_params_set_channels (record_handle, hw_params, 1)) < 0) {
+    fprintf (stderr, "audio_open_input: cannot set channel count (%s)\n",
+            snd_strerror (err));
+    return -1;
+  }
+
+  if ((err = snd_pcm_hw_params (record_handle, hw_params)) < 0) {
+    fprintf (stderr, "audio_open_input: cannot set parameters (%s)\n",
+            snd_strerror (err));
+    return -1;
+  }
+
+  snd_pcm_hw_params_free (hw_params);
+
+  mic_buffer=(unsigned char *)malloc(MIC_BUFFER_SIZE);
+
+  running=TRUE;
+  mic_read_thread_id = g_thread_new( "local mic", mic_read_thread, NULL);
+  if(!mic_read_thread_id )
+  {
+    fprintf(stderr,"g_thread_new failed on mic_read_thread\n");
+  }
+
+*/
+  return 0;
+}
+
+void audio_close_output(RECEIVER *rx) {
+  soundio_outstream_destroy(outstream);
+  soundio_device_unref(audio_device);
+  soundio_destroy(soundio);
+/*
+  if(rx->playback_handle!=NULL) {
+    snd_pcm_close (rx->playback_handle);
+    rx->playback_handle=NULL;
+  }
+  if(rx->playback_buffer!=NULL) {
+    free(rx->playback_buffer);
+    rx->playback_buffer=NULL;
+  }
+*/
+}
+
+void audio_close_input() {
+/*
+  running=FALSE;
+  if(record_handle!=NULL) {
+    snd_pcm_close (record_handle);
+    record_handle=NULL;
+  }
+  if(mic_buffer!=NULL) {
+    free(mic_buffer);
+    mic_buffer=NULL;
+  }
+*/
+}
+
+int audio_write(RECEIVER *rx,short left_sample,short right_sample) {
+//fprintf(stderr,"audio_write: id=%d frames=%d insert_index=%d remove_index=%d\n",rx->id, frames, insert_index,remove_index);
+  if(frames<(BUFFER_SIZE-2)) {
+    output_left_buffer[insert_index]=left_sample;
+    output_right_buffer[insert_index]=right_sample;
+    insert_index++;
+    if(insert_index==BUFFER_SIZE) {
+      insert_index=0;
+    }
+    frames++;
+  } else {
+    fprintf(stderr,"audio_write: buffer_full: frames=%d insert_index-%d remove_index=%d\n",frames,insert_index,remove_index);
+  }
+
+/*
+  snd_pcm_sframes_t delay;
+  int error;
+  long trim;
+
+  if(rx->playback_handle!=NULL && rx->playback_buffer!=NULL) {
+    rx->playback_buffer[rx->playback_offset++]=right_sample;
+    rx->playback_buffer[rx->playback_offset++]=right_sample>>8;
+    rx->playback_buffer[rx->playback_offset++]=left_sample;
+    rx->playback_buffer[rx->playback_offset++]=left_sample>>8;
+
+    if(rx->playback_offset==OUTPUT_BUFFER_SIZE) {
+
+      trim=0;
+
+      if(snd_pcm_delay(rx->playback_handle,&delay)==0) {
+        if(delay>2048) {
+          trim=delay-2048;
+//fprintf(stderr,"audio delay=%ld trim=%ld\n",delay,trim);
+        }
+      }
+
+      if ((error = snd_pcm_writei (rx->playback_handle, rx->playback_buffer, audio_buffer_size-trim)) != audio_buffer_size-trim) {
+        if(error==-EPIPE) {
+          if ((error = snd_pcm_prepare (rx->playback_handle)) < 0) {
+            fprintf (stderr, "audio_write: cannot prepare audio interface for use (%s)\n",
+                    snd_strerror (error));
+            return -1;
+          }
+          if ((error = snd_pcm_writei (rx->playback_handle, rx->playback_buffer, audio_buffer_size-trim)) != audio_buffer_size) {
+            fprintf (stderr, "audio_write: write to audio interface failed (%s)\n",
+                    snd_strerror (error));
+            return -1;
+          }
+        }
+      }
+      rx->playback_offset=0;
+    }
+  }
+*/
+  return 0;
+}
+
+static gpointer mic_read_thread(gpointer arg) {
+/*
+  int rc;
+  if ((rc = snd_pcm_prepare (record_handle)) < 0) {
+    fprintf (stderr, "mic_read_thread: cannot prepare audio interface for use (%s)\n",
+            snd_strerror (rc));
+    return;
+  }
+fprintf(stderr,"mic_read_thread: mic_buffer_size=%d\n",mic_buffer_size);
+  while(running) {
+    if ((rc = snd_pcm_readi (record_handle, mic_buffer, mic_buffer_size)) != mic_buffer_size) {
+      if(running) {
+        if(rc<0) {
+          fprintf (stderr, "mic_read_thread: read from audio interface failed (%s)\n",
+                  snd_strerror (rc));
+          running=FALSE;
+        } else {
+          fprintf(stderr,"mic_read_thread: read %d\n",rc);
+        }
+      }
+    } else {
+      // process the mic input
+      switch(protocol) {
+        case ORIGINAL_PROTOCOL:
+          old_protocol_process_local_mic(mic_buffer,1);
+          break;
+        case NEW_PROTOCOL:
+          new_protocol_process_local_mic(mic_buffer,1);
+          break;
+        default:
+          break;
+      }
+    }
+  }
+fprintf(stderr,"mic_read_thread: exiting\n");
+*/
+}
+
+void audio_get_cards() {
+  int i;
+
+  for(i=0;i<n_input_devices;i++) {
+      free(input_devices[i]);
+  }
+  for(i=0;i<n_output_devices;i++) {
+    free(output_devices[i]);
+  }
+
+  struct SoundIo *soundio = soundio_create();
+  if (!soundio) {
+    fprintf(stderr, "audio_get_cards: soundio_create failed\n");
+    return;
+  }
+
+  soundio_connect(soundio);
+
+  soundio_flush_events(soundio);
+
+  n_output_devices = soundio_output_device_count(soundio);
+  n_input_devices = soundio_input_device_count(soundio);
+  int default_output = soundio_default_output_device_index(soundio);
+  int default_input = soundio_default_input_device_index(soundio);
+
+
+  for(i=0;i<n_output_devices;i++) {
+    struct SoundIoDevice *device = soundio_get_output_device(soundio, i);
+fprintf(stderr,"output: %d: id=%s name=%s\n",i,device->id,device->name);
+    char *device_id=malloc(64);
+    strncpy(device_id,device->id,64);
+    output_devices[i]=device_id;
+    soundio_device_unref(device);
+  }
+
+  for(i=0;i<n_input_devices;i++) {
+    struct SoundIoDevice *device = soundio_get_input_device(soundio, i);
+fprintf(stderr,"input: %d: id=%s name=%s\n",i,device->id,device->name);
+    char *device_id=malloc(64);
+    strncpy(device_id,device->id,64);
+    input_devices[i]=device_id;
+    soundio_device_unref(device);
+  }
+
+  soundio_destroy(soundio);
+}
diff --git a/soundio.h b/soundio.h
new file mode 100644 (file)
index 0000000..ee4dcfe
--- /dev/null
+++ b/soundio.h
@@ -0,0 +1,39 @@
+/* Copyright (C)
+* 2016 - John Melton, G0ORX/N6LYT
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#ifndef _AUDIO_H
+#define _AUDIO_H
+
+#include "receiver.h"
+
+extern char *input_devices[];
+extern int n_input_devices;
+extern int n_selected_input_device;
+
+extern char *output_devices[];
+extern int n_output_devices;
+//extern int n_selected_output_device;
+
+extern int audio_open_input();
+extern void audio_close_input();
+extern int audio_open_output(RECEIVER *rx);
+extern void audio_close_output(RECEIVER *rx);
+extern int audio_write(RECEIVER *rx,short left_sample,short right_sample);
+extern void audio_get_cards();
+#endif
index 9dded3e14a36541173af3ec16ace03db80e4b854..0520d5b18eb46a9dc3d2055a6031b5e23c0a1d67 100644 (file)
--- a/splash.c
+++ b/splash.c
 #include <gtk/gtk.h>
 #include "version.h"
 
-GtkWidget *splash_screen;
+GtkWidget *grid;
 GtkWidget *status;
 static cairo_surface_t *splash_surface = NULL;
 
+
 /* Close the splash screen */
 void splash_close()
 {
-  gtk_widget_destroy(splash_screen);
-}
-
-static gboolean splash_configure_event_cb (GtkWidget         *widget,
-            GdkEventConfigure *event,
-            gpointer           data)
-{
-  if (splash_surface)
-    cairo_surface_destroy (splash_surface);
-
-  splash_surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget),
-                                       CAIRO_CONTENT_COLOR,
-                                       gtk_widget_get_allocated_width (widget),
-                                       gtk_widget_get_allocated_height (widget));
-
-  return TRUE;
+  gtk_widget_destroy(grid);
 }
 
-
-void splash_show(char* image_name,int width,int height,int full_screen)
+GtkWidget *splash_create(char* image_name,int width,int height)
 {
   GtkWidget  *image;
-  splash_screen = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-  if(full_screen) {
-    gtk_window_fullscreen(GTK_WINDOW(splash_screen));
-  }
-  gtk_widget_set_size_request(splash_screen, width, height);
-  gtk_window_set_position(GTK_WINDOW(splash_screen),GTK_WIN_POS_CENTER_ALWAYS);
-  gtk_window_set_resizable(GTK_WINDOW(splash_screen), FALSE);
-
 
-  GtkWidget *grid = gtk_grid_new();
+  grid = gtk_grid_new();
+  gtk_widget_set_size_request(grid, width, height);
   gtk_grid_set_row_homogeneous(GTK_GRID(grid),FALSE);
   gtk_grid_set_column_homogeneous(GTK_GRID(grid),FALSE);
 
   image=gtk_image_new_from_file(image_name);
-  //gtk_container_add(GTK_CONTAINER(splash_screen), image);
   gtk_grid_attach(GTK_GRID(grid), image, 0, 0, 1, 4);
-  g_signal_connect (splash_screen,"configure-event",
-            G_CALLBACK (splash_configure_event_cb), NULL);
 
   char build[64];
   sprintf(build,"build: %s %s",build_date, version);
@@ -84,11 +59,9 @@ void splash_show(char* image_name,int width,int height,int full_screen)
   gtk_label_set_justify(GTK_LABEL(status),GTK_JUSTIFY_LEFT);
   gtk_widget_override_font(status, pango_font_description_from_string("FreeMono 18"));
   gtk_widget_show(status);
-  //gtk_container_add(GTK_CONTAINER(splash_screen), status);
   gtk_grid_attach(GTK_GRID(grid), status, 1, 3, 1, 1);
 
-  gtk_container_add(GTK_CONTAINER(splash_screen), grid);
-  gtk_widget_show_all (splash_screen);
+  return grid;
 }
 
 void splash_status(char *text) {
index 8c6e1ad0e750f00f7888fa73bcb6639832d498bd..ada65a92b76259a8e63ab8da002729bb7d363a67 100644 (file)
--- a/splash.h
+++ b/splash.h
 #ifndef _SPLASH_H
 #define _SPLASH_H
 
-extern GtkWidget* splash_screen;
 
 void splash_close(void);
-void splash_show(char *image_name,int time,int width,int height);
+GtkWidget *splash_create(char *image_name,int width,int height);
 void splash_status(char *text);
 
 #endif
diff --git a/store.c b/store.c
new file mode 100644 (file)
index 0000000..0b6bb47
--- /dev/null
+++ b/store.c
@@ -0,0 +1,140 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+* 2016 - Steve Wilson, KA6S
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "bandstack.h"
+#include "band.h"
+#include "filter.h"
+#include "mode.h"
+#include "alex.h"
+#include "property.h"
+#include "store.h"
+#include "store_menu.h"
+
+
+/*
+struct MEM {
+    char title[16];     // Begin BAND Struct
+    BANDSTACK *bandstack;
+    unsigned char OCrx;
+    unsigned char OCtx;
+    int preamp;
+    int alexRxAntenna;
+    int alexTxAntenna;
+    int alexAttenuation;
+    double pa_calibration;
+    long long frequencyMin;
+    long long frequencyMax;
+    long long frequencyLO;
+    int disablePA;
+    long long frequency; // Begin BANDSTACK_ENTRY
+    int mode;
+    int filter;
+    int var1Low;
+    int var1High;
+    int var2Low;
+    int var2High;
+}*/
+MEM mem[NUM_OF_MEMORYS];  // This makes it a compile time option
+
+/*                                           */
+/* Memory uses the same format as Band Stack */
+/* Implement NUM_OF_MEMORYS memory locations for now... */
+
+void memSaveState() {
+    char name[128];
+    char value[128];
+    int current;
+    BANDSTACK_ENTRY* entry;
+    int workvar;
+    int b;
+    int stack;
+
+    for(b=0;b<NUM_OF_MEMORYS;b++) {
+      if(strlen(mem[b].title)>0) {
+        sprintf(name,"mem.%d.title",b);
+        setProperty(name,mem[b].title);
+
+        sprintf(value,"%lld",mem[b].frequency);
+        sprintf(name,"mem.%d.freqA",b);
+        setProperty(name,value);
+
+        sprintf(value,"%d",mem[b].mode);
+        sprintf(name,"mem.%d.mode",b);
+        setProperty(name,value);
+
+        sprintf(value,"%d",mem[b].filter);
+        sprintf(name,"mem.%d.filter",b);
+        setProperty(name,value);
+      }
+    }
+
+    //sprintf(value,"%d",band);
+    //setProperty("band",value);
+}
+
+void memRestoreState() {
+    char* value;
+    int b;
+    int stack;
+    char name[128];
+    BANDSTACK_ENTRY* entry;
+    int current;
+
+    // Initialize the array with default values
+    // Allows this to be a compile time option..
+    for(b=0; b<NUM_OF_MEMORYS; b++) {
+       strcpy(mem[b].title,"10");  
+       mem[b].frequency = 28010000LL;
+       mem[b].mode = modeCWU;
+       mem[b].filter = filterF0;
+    }
+
+    fprintf(stderr,"memRestoreState: restore memory\n");
+
+    for(b=0;b<NUM_OF_MEMORYS;b++) {
+        sprintf(name,"mem.%d.title",b);
+        value=getProperty(name);
+        if(value) strcpy(mem[b].title,value);
+        fprintf(stderr,"RESTORE: index=%d title=%s\n",b,value);
+
+        sprintf(name,"mem.%d.freqA",b);
+        value=getProperty(name);
+        if(value) mem[b].frequency=atoll(value);
+        fprintf(stderr,"RESTORE MEM:Mem %d=FreqA %11lld\n",b,mem[b].frequency);
+
+        sprintf(name,"mem.%d.mode",b);
+        value=getProperty(name);
+        if(value) mem[b].mode=atoi(value);
+        fprintf(stderr,"RESTORE: index=%d mode=%d\n",b,mem[b].mode);
+
+        sprintf(name,"mem.%d.filter",b);
+        value=getProperty(name);
+        if(value) mem[b].filter=atoi(value);
+        fprintf(stderr,"RESTORE: index=%d filter=%d\n",b,mem[b].filter);
+    }
+
+    //value=getProperty("band");
+    //if(value) band=atoi(value);
+}
+
diff --git a/store.h b/store.h
new file mode 100644 (file)
index 0000000..2bcb9e2
--- /dev/null
+++ b/store.h
@@ -0,0 +1,45 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+* 2016 - Steve Wilson, KA6S
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#ifndef _STORE_H
+#define _STORE_H
+
+#include <gtk/gtk.h>
+#include "bandstack.h"
+
+
+/* --------------------------------------------------------------------------*/
+/**
+* @brief Band definition
+*/
+struct _MEM_STORE {
+    char title[16];     // Begin BAND Struct
+    long long frequency; // Begin BANDSTACK_ENTRY
+    int mode;
+    int filter;
+};
+
+typedef struct _MEM_STORE MEM; 
+
+extern MEM mem[];
+void memRestoreState(); 
+void memSaveState(); 
+
+#endif
diff --git a/store_menu.c b/store_menu.c
new file mode 100644 (file)
index 0000000..a91cada
--- /dev/null
@@ -0,0 +1,140 @@
+/* Copyright (C)
+* 2016 - John Melton, G0ORX/N6LYT
+* 2016 - Steve Wilson, KA6S
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "new_menu.h"
+#include "store_menu.h"
+#include "band.h"
+#include "bandstack.h"
+#include "filter.h"
+#include "mode.h"
+#include "radio.h"
+#include "rigctl.h"
+#include "band.h"
+#include "vfo.h"
+#include "button_text.h"
+#include "store.h"
+
+static GtkWidget *parent_window=NULL;
+
+static GtkWidget *dialog=NULL;
+
+static gboolean store_close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  if(dialog!=NULL) {
+    gtk_widget_destroy(dialog);
+    dialog=NULL;
+    sub_menu=NULL;
+  }
+  return TRUE;
+}
+
+static gboolean store_select_cb (GtkWidget *widget, gpointer data) {
+   int index = (int) data;
+   fprintf(stderr,"STORE BUTTON PUSHED=%d\n",index);
+   char workstr[16];
+     
+   /* Update mem[data] with current info  */
+
+   mem[index].frequency = vfo[active_receiver->id].frequency; // Store current frequency
+   mem[index].mode = vfo[active_receiver->id].mode;
+   mem[index].filter=vfo[active_receiver->id].filter;
+
+    fprintf(stderr,"store_select_cb: Index=%d\n",index);
+    fprintf(stderr,"store_select_cb: freqA=%11lld\n",mem[index].frequency);
+    fprintf(stderr,"store_select_cb: mode=%d\n",mem[index].mode);
+    fprintf(stderr,"store_select_cb: filter=%d\n",mem[index].filter);
+
+   // Save in the file now..
+   memSaveState();
+}
+
+static gboolean recall_select_cb (GtkWidget *widget, gpointer data) {
+    int index = (int) data;
+    long long new_freq;
+    
+    //new_freq = mem[index].frequency;
+    strcpy(mem[index].title,"Active");
+    new_freq = mem[index].frequency;
+    fprintf(stderr,"recall_select_cb: Index=%d\n",index);
+    fprintf(stderr,"recall_select_cb: freqA=%11lld\n",new_freq);
+    fprintf(stderr,"recall_select_cb: mode=%d\n",mem[index].mode);
+    fprintf(stderr,"recall_select_cb: filter=%d\n",mem[index].filter);
+    
+    //set_band(mem[index].frequency,index);
+    vfo[active_receiver->id].frequency = new_freq;
+    vfo[active_receiver->id].band = get_band_from_frequency(new_freq);
+    vfo[active_receiver->id].mode = mem[index].mode;
+    vfo[active_receiver->id].filter = mem[index].filter;
+    vfo_band_changed(vfo[active_receiver->id].band);
+}
+
+void store_menu(GtkWidget *parent) {
+  GtkWidget *b;
+  int i;
+  BAND *band;
+  char label_str[20];
+
+  parent_window=parent;
+
+  dialog=gtk_dialog_new();
+  gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
+  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+
+  GdkRGBA color;
+  color.red = 1.0;
+  color.green = 1.0;
+  color.blue = 1.0;
+  color.alpha = 1.0;
+  gtk_widget_override_background_color(dialog,GTK_STATE_FLAG_NORMAL,&color);
+
+  GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+
+  GtkWidget *grid=gtk_grid_new();
+
+  gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+  gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
+  gtk_grid_set_column_spacing (GTK_GRID(grid),5);
+  gtk_grid_set_row_spacing (GTK_GRID(grid),5);
+
+  GtkWidget *close_b=gtk_button_new_with_label("Close Store");
+  g_signal_connect (close_b, "pressed", G_CALLBACK(store_close_cb), NULL);
+  gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
+
+  for(i=0;i<NUM_OF_MEMORYS;i++) {
+     sprintf(label_str,"Store M%d",i); 
+     b=gtk_button_new_with_label(label_str);
+     g_signal_connect(b,"pressed",G_CALLBACK(store_select_cb),(gpointer *) i);
+     gtk_grid_attach(GTK_GRID(grid),b,2,i,1,1);
+
+     sprintf(label_str,"Recall M%d",i); 
+     b=gtk_button_new_with_label(label_str);
+     g_signal_connect(b,"pressed",G_CALLBACK(recall_select_cb),(gpointer *) i);
+     gtk_grid_attach(GTK_GRID(grid),b,3,i,1,1);
+  }
+
+  gtk_container_add(GTK_CONTAINER(content),grid);
+
+  sub_menu=dialog;
+
+  gtk_widget_show_all(dialog);
+}
diff --git a/store_menu.h b/store_menu.h
new file mode 100644 (file)
index 0000000..4f2d1d8
--- /dev/null
@@ -0,0 +1,20 @@
+/* Copyright (C)
+* 2016 - Steve Wilson, KA6S
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+#define NUM_OF_MEMORYS 5
+extern void store_menu(GtkWidget *parent);
index 4409e3a6feed5a5be651b6ad2e378a1b8be14e09..27019901b36f4b59cd9e922ccbc62596794a36c7 100644 (file)
--- a/toolbar.c
+++ b/toolbar.c
 #include "channel.h"
 #include "wdsp.h"
 #include "radio.h"
+#include "receiver.h"
 #include "property.h"
 #include "new_menu.h"
+#include "button_text.h"
 
+#define MAX_FUNCTION 3
 int function=0;
 
 static int width;
@@ -71,54 +74,76 @@ static GdkRGBA gray;
 
 static gint rit_timer;
 
-static void set_button_text_color(GtkWidget *widget,char *color) {
-  GtkStyleContext *style_context;
-  GtkCssProvider *provider = gtk_css_provider_new ();
-  gchar tmp[64];
-  style_context = gtk_widget_get_style_context(widget);
-  gtk_style_context_add_provider(style_context, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
-  g_snprintf(tmp, sizeof tmp, "GtkButton, GtkLabel { color: %s; }", color);
-  gtk_css_provider_load_from_data(GTK_CSS_PROVIDER(provider), tmp, -1, NULL);
-  g_object_unref (provider);
+static gboolean rit_timer_cb(gpointer data) {
+  int i=(int)data;
+  vfo[active_receiver->id].rit+=(i*rit_increment);
+  if(vfo[active_receiver->id].rit>1000) vfo[active_receiver->id].rit=1000;
+  if(vfo[active_receiver->id].rit<-1000) vfo[active_receiver->id].rit=-1000;
+  vfo_update(NULL);
+  return TRUE;
 }
 
 void update_toolbar_labels() {
-  if(toolbar_dialog_buttons) {
-      if(function) {
-        gtk_button_set_label(GTK_BUTTON(sim_mox),"Tune");
-        gtk_button_set_label(GTK_BUTTON(sim_s1),"RIT+");
-        gtk_button_set_label(GTK_BUTTON(sim_s2),"RIT-");
-        gtk_button_set_label(GTK_BUTTON(sim_s3),"CTUN");
-        gtk_button_set_label(GTK_BUTTON(sim_s4),"");
-        gtk_button_set_label(GTK_BUTTON(sim_s5),"");
-        gtk_button_set_label(GTK_BUTTON(sim_s6),"Lock");
-      } else {
-        gtk_button_set_label(GTK_BUTTON(sim_mox),"Mox");
-        gtk_button_set_label(GTK_BUTTON(sim_s1),"Band");
-        gtk_button_set_label(GTK_BUTTON(sim_s2),"BStack");
-        gtk_button_set_label(GTK_BUTTON(sim_s3),"Mode");
-        gtk_button_set_label(GTK_BUTTON(sim_s4),"Filter");
-        gtk_button_set_label(GTK_BUTTON(sim_s5),"Noise");
-        gtk_button_set_label(GTK_BUTTON(sim_s6),"AGC");
+  switch(function) {
+    case 0:
+      gtk_button_set_label(GTK_BUTTON(sim_mox),"Mox");
+      gtk_button_set_label(GTK_BUTTON(sim_s1),"Band");
+      gtk_button_set_label(GTK_BUTTON(sim_s2),"BStack");
+      gtk_button_set_label(GTK_BUTTON(sim_s3),"Mode");
+      gtk_button_set_label(GTK_BUTTON(sim_s4),"Filter");
+      gtk_button_set_label(GTK_BUTTON(sim_s5),"Noise");
+      gtk_button_set_label(GTK_BUTTON(sim_s6),"AGC");
+      set_button_text_color(sim_s1,"black");
+      set_button_text_color(sim_s2,"black");
+      break;
+
+    case 1:
+      gtk_button_set_label(GTK_BUTTON(sim_mox),"Mox");
+      gtk_button_set_label(GTK_BUTTON(sim_s1),"Lock");
+      gtk_button_set_label(GTK_BUTTON(sim_s2),"CTUN");
+      gtk_button_set_label(GTK_BUTTON(sim_s3),"A>B");
+      gtk_button_set_label(GTK_BUTTON(sim_s4),"A<B");
+      gtk_button_set_label(GTK_BUTTON(sim_s5),"A<>B");
+      gtk_button_set_label(GTK_BUTTON(sim_s6),"Split");
+      break;
+    case 2:
+      gtk_button_set_label(GTK_BUTTON(sim_mox),"Mox");
+      gtk_button_set_label(GTK_BUTTON(sim_s1),"Freq");
+      gtk_button_set_label(GTK_BUTTON(sim_s2),"Mem");
+      gtk_button_set_label(GTK_BUTTON(sim_s3),"Vox");
+      gtk_button_set_label(GTK_BUTTON(sim_s4),"RIT+");
+      gtk_button_set_label(GTK_BUTTON(sim_s5),"RIT-");
+      gtk_button_set_label(GTK_BUTTON(sim_s6),"");
+      if(full_tune) {
+        set_button_text_color(sim_s1,"red");
       }
-  } else {
-    if(function) {
-      gtk_button_set_label(GTK_BUTTON(sim_s1),"Band v");
-      gtk_button_set_label(GTK_BUTTON(sim_s2),"BStack v");
-      gtk_button_set_label(GTK_BUTTON(sim_s3),"Mode v");
-      gtk_button_set_label(GTK_BUTTON(sim_s4),"Filter v");
-      gtk_button_set_label(GTK_BUTTON(sim_s5),"Noise v");
-      gtk_button_set_label(GTK_BUTTON(sim_s6),"AGC v");
+      if(memory_tune) {
+        set_button_text_color(sim_s2,"red");
+      }
+      break;
+    case 3:
       gtk_button_set_label(GTK_BUTTON(sim_mox),"Tune");
-    } else {
-      gtk_button_set_label(GTK_BUTTON(sim_s1),"Band ^");
-      gtk_button_set_label(GTK_BUTTON(sim_s2),"BStack ^");
-      gtk_button_set_label(GTK_BUTTON(sim_s3),"Mode ^");
-      gtk_button_set_label(GTK_BUTTON(sim_s4),"Filter ^");
-      gtk_button_set_label(GTK_BUTTON(sim_s5),"Noise ^");
-      gtk_button_set_label(GTK_BUTTON(sim_s6),"AGC ^");
-      gtk_button_set_label(GTK_BUTTON(sim_mox),"Mox");
-    }
+      if(OCtune!=0 && OCfull_tune_time!=0) {
+        gtk_button_set_label(GTK_BUTTON(sim_s1),"Full");
+      } else {
+        gtk_button_set_label(GTK_BUTTON(sim_s1),"");
+      }
+      if(OCtune!=0 && OCmemory_tune_time!=0) {
+        gtk_button_set_label(GTK_BUTTON(sim_s2),"Memory");
+      } else {
+        gtk_button_set_label(GTK_BUTTON(sim_s2),"");
+      }
+      gtk_button_set_label(GTK_BUTTON(sim_s3),"");
+      gtk_button_set_label(GTK_BUTTON(sim_s4),"");
+      gtk_button_set_label(GTK_BUTTON(sim_s5),"");
+      gtk_button_set_label(GTK_BUTTON(sim_s6),"");
+      if(full_tune) {
+        set_button_text_color(sim_s1,"red");
+      }
+      if(memory_tune) {
+        set_button_text_color(sim_s2,"red");
+      }
+      break;
   }
 }
 
@@ -127,539 +152,83 @@ static void close_cb(GtkWidget *widget, gpointer data) {
   last_dialog=NULL;
 }
 
-/*
-static void band_select_cb(GtkWidget *widget, gpointer data) {
-  GtkWidget *label;
-  int b=(int)data;
-  BANDSTACK_ENTRY *entry;
-  if(b==band_get_current()) {
-    entry=bandstack_entry_next();
-  } else {
-    BAND* band=band_set_current(b);
-    entry=bandstack_entry_get_current();
-    set_button_text_color(last_band,"black");
-    last_band=widget;
-    set_button_text_color(last_band,"orange");
-  }
-  setMode(entry->mode);
-  FILTER* band_filters=filters[entry->mode];
-  FILTER* band_filter=&band_filters[entry->filter];
-  setFilter(band_filter->low,band_filter->high);
-  setFrequency(entry->frequencyA);
-
-  BAND *band=band_get_current_band();
-  set_alex_rx_antenna(band->alexRxAntenna);
-  set_alex_tx_antenna(band->alexTxAntenna);
-  set_alex_attenuation(band->alexAttenuation);
-
-  vfo_update(NULL);
-
-  setFrequency(entry->frequencyA);
-
-  calcDriveLevel();
-  calcTuneDriveLevel();
-}
-*/
-
 void band_cb(GtkWidget *widget, gpointer data) {
   start_band();
-/*
-  BAND* band;
-  int show=1;
-  if(last_dialog!=NULL) {
-    if(strcmp(gtk_window_get_title(GTK_WINDOW(last_dialog)),"Band")==0) {
-      show=0;
-    }
-    gtk_widget_destroy(last_dialog);
-    last_dialog=NULL;
-  }
-  if(show) {
-    GtkWidget *dialog=gtk_dialog_new_with_buttons("Band",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
-    GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
-    GtkWidget *grid=gtk_grid_new();
-    gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
-    gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
-    GtkWidget *b;
-    int i;
-    for(i=0;i<BANDS+XVTRS;i++) {
-#ifdef LIMESDR
-      if(protocol!=LIMESDR_PROTOCOL) {
-        if(i>=band70 && i<=band3400) {
-          continue;
-        }
-      }
-#endif
-      
-      band=(BAND*)band_get_band(i);
-      if(strlen(band->title)>0) {
-        GtkWidget *b=gtk_button_new_with_label(band->title);
-        set_button_text_color(b,"black");
-        //gtk_widget_override_font(b, pango_font_description_from_string("Arial 20"));
-        if(i==band_get_current()) {
-          set_button_text_color(b,"orange");
-          last_band=b;
-        }
-        gtk_widget_show(b);
-        gtk_grid_attach(GTK_GRID(grid),b,i%5,i/5,1,1);
-        g_signal_connect(b,"clicked",G_CALLBACK(band_select_cb),(gpointer *)i);
-      }
-    }
-
-    gtk_container_add(GTK_CONTAINER(content),grid);
-
-    GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
-    //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 20"));
-    g_signal_connect(close_button,"clicked",G_CALLBACK(close_cb),(gpointer *)NULL);
-
-    gtk_widget_show_all(dialog);
-    last_dialog=dialog;
-    int result=gtk_dialog_run(GTK_DIALOG(dialog));
-  }
-*/
-}
-
-/*
-static void bandstack_select_cb(GtkWidget *widget, gpointer data) {
-  int b=(int)data;
-  BAND *band=band_get_current_band();
-  BANDSTACK *bandstack=band->bandstack;
-
-  bandstack->current_entry=b;
-
-  set_button_text_color(last_bandstack,"black");
-  last_bandstack=widget;
-  set_button_text_color(last_bandstack,"orange");
-
-  BANDSTACK_ENTRY *entry;
-  entry=&(bandstack->entry[b]);
-
-  setMode(entry->mode);
-  FILTER* band_filters=filters[entry->mode];
-  FILTER* band_filter=&band_filters[entry->filter];
-  setFilter(band_filter->low,band_filter->high);
-  setFrequency(entry->frequencyA);
-
-  set_alex_rx_antenna(band->alexRxAntenna);
-  set_alex_tx_antenna(band->alexTxAntenna);
-  set_alex_attenuation(band->alexAttenuation);
-
-  vfo_update(NULL);
-
-  setFrequency(entry->frequencyA);
 }
-*/
 
 void bandstack_cb(GtkWidget *widget, gpointer data) {
   start_bandstack();
-/*
-  int show=1;
-  if(last_dialog!=NULL) {
-    if(strcmp(gtk_window_get_title(GTK_WINDOW(last_dialog)),"Band Stack")==0) {
-      show=0;
-    }
-    gtk_widget_destroy(last_dialog);
-    last_dialog=NULL;
-  }
-  if(show) {
-    GtkWidget *dialog=gtk_dialog_new_with_buttons("Band Stack",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
-    GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
-    GtkWidget *grid=gtk_grid_new();
-    gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
-    gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
-    GtkWidget *b;
-    int i;
-
-    char label[16];
-
-    BAND *band=band_get_current_band();
-    BANDSTACK *bandstack=band->bandstack;
-
-    for(i=0;i<bandstack->entries;i++) {
-      BANDSTACK_ENTRY *entry=&bandstack->entry[i];
-      sprintf(label,"%lld %s",entry->frequencyA,mode_string[entry->mode]);
-      GtkWidget *b=gtk_button_new_with_label(label);
-      set_button_text_color(b,"black");
-      //gtk_widget_override_font(b, pango_font_description_from_string("Arial 20"));
-      if(i==bandstack->current_entry) {
-        set_button_text_color(b,"orange");
-        last_bandstack=b;
-      }
-      gtk_widget_show(b);
-      gtk_grid_attach(GTK_GRID(grid),b,i/5,i%5,1,1);
-      g_signal_connect(b,"clicked",G_CALLBACK(bandstack_select_cb),(gpointer *)i);
-    }
-
-    gtk_container_add(GTK_CONTAINER(content),grid);
-
-    GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
-    //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 20"));
-    g_signal_connect(close_button,"clicked",G_CALLBACK(close_cb),(gpointer *)NULL);
-    gtk_widget_show_all(dialog);
-
-    last_dialog=dialog;
-
-    int result=gtk_dialog_run(GTK_DIALOG(dialog));
-  }
-*/
 }
 
-void function_cb(GtkWidget *widget, gpointer data) {
-  function=function==1?0:1;
-  update_toolbar_labels();
-  vfo_update(NULL);
-}
-
-/*
-static void mode_select_cb(GtkWidget *widget, gpointer data) {
-  int m=(int)data;
-  BANDSTACK_ENTRY *entry;
-  entry=bandstack_entry_get_current();
-  entry->mode=m;
-  setMode(entry->mode);
-  FILTER* band_filters=filters[entry->mode];
-  FILTER* band_filter=&band_filters[entry->filter];
-  setFilter(band_filter->low,band_filter->high);
-  set_button_text_color(last_mode,"black");
-  last_mode=widget;
-  set_button_text_color(last_mode,"orange");
-  vfo_update(NULL);
-}
-*/
-
 void mode_cb(GtkWidget *widget, gpointer data) {
   start_mode();
-/*
-  int show=1;
-  if(last_dialog!=NULL) {
-    if(strcmp(gtk_window_get_title(GTK_WINDOW(last_dialog)),"Mode")==0) {
-      show=0;
-    }
-    gtk_widget_destroy(last_dialog);
-    last_dialog=NULL;
-  }
-  if(show) {
-    BANDSTACK_ENTRY *entry=bandstack_entry_get_current();
-    GtkWidget *dialog=gtk_dialog_new_with_buttons("Mode",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
-    GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
-    GtkWidget *grid=gtk_grid_new();
-    gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
-    gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
-
-    GtkWidget *b;
-    int i;
-    for(i=0;i<MODES;i++) {
-      GtkWidget *b=gtk_button_new_with_label(mode_string[i]);
-      if(i==entry->mode) {
-        set_button_text_color(b,"orange");
-        last_mode=b;
-      } else {
-        set_button_text_color(b,"black");
-      }
-      //gtk_widget_override_font(b, pango_font_description_from_string("Arial 20"));
-      gtk_widget_show(b);
-      gtk_grid_attach(GTK_GRID(grid),b,i%5,i/5,1,1);
-      g_signal_connect(b,"pressed",G_CALLBACK(mode_select_cb),(gpointer *)i);
-    }
-    gtk_container_add(GTK_CONTAINER(content),grid);
-    GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
-    //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 20"));
-    g_signal_connect(close_button,"clicked",G_CALLBACK(close_cb),(gpointer *)NULL);
-    gtk_widget_show_all(dialog);
-
-    last_dialog=dialog;
-    int result=gtk_dialog_run(GTK_DIALOG(dialog));
-
-  }
-*/
 }
 
-/*
-static void filter_select_cb(GtkWidget *widget, gpointer data) {
-  int f=(int)data;
-  BANDSTACK_ENTRY *entry;
-  entry=bandstack_entry_get_current();
-  entry->filter=f;
-  FILTER* band_filters=filters[entry->mode];
-  FILTER* band_filter=&band_filters[entry->filter];
-  setFilter(band_filter->low,band_filter->high);
-  set_button_text_color(last_filter,"black");
-  last_filter=widget;
-  set_button_text_color(last_filter,"orange");
-  vfo_update(NULL);
-}
-*/
 void filter_cb(GtkWidget *widget, gpointer data) {
   start_filter();
-/*
-  int show=1;
-  if(last_dialog!=NULL) {
-    if(strcmp(gtk_window_get_title(GTK_WINDOW(last_dialog)),"Filter")==0) {
-      show=0;
-    }
-    gtk_widget_destroy(last_dialog);
-    last_dialog=NULL;
-  }
-  if(show) {
-    BANDSTACK_ENTRY *entry=bandstack_entry_get_current();
-    FILTER* band_filters=filters[entry->mode];
-    GtkWidget *dialog=gtk_dialog_new_with_buttons("Filter",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
-    GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
-    GtkWidget *grid=gtk_grid_new();
-    gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
-    gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
-
-    GtkWidget *b;
-    int i;
-    for(i=0;i<FILTERS;i++) {
-      FILTER* band_filter=&band_filters[i];
-      GtkWidget *b=gtk_button_new_with_label(band_filters[i].title);
-      //gtk_widget_override_font(b, pango_font_description_from_string("Arial 20"));
-      if(i==entry->filter) {
-        set_button_text_color(b,"orange");
-        last_filter=b;
-      } else {
-        set_button_text_color(b,"black");
-      }
-      gtk_widget_show(b);
-      gtk_grid_attach(GTK_GRID(grid),b,i%5,i/5,1,1);
-      g_signal_connect(b,"pressed",G_CALLBACK(filter_select_cb),(gpointer *)i);
-    }
-    gtk_container_add(GTK_CONTAINER(content),grid);
-    GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
-    //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 20"));
-    g_signal_connect(close_button,"clicked",G_CALLBACK(close_cb),(gpointer *)NULL);
-    gtk_widget_show_all(dialog);
-
-    last_dialog=dialog;
-    int result=gtk_dialog_run(GTK_DIALOG(dialog));
-
-  }
-*/
 }
 
-/*
-static void agc_select_cb(GtkWidget *widget, gpointer data) {
-  agc=(int)data;
-  wdsp_set_agc(CHANNEL_RX0, agc);
-  //SetRXAAGCMode(CHANNEL_RX0, agc);
+void agc_cb(GtkWidget *widget, gpointer data) {
+  start_agc();
 }
-*/
 
-/*
-static void update_noise() {
-  SetRXAANRRun(CHANNEL_RX0, nr);
-  SetRXAEMNRRun(CHANNEL_RX0, nr2);
-  SetRXAANFRun(CHANNEL_RX0, anf);
-  SetRXASNBARun(CHANNEL_RX0, snb);
-  vfo_update(NULL);
+void noise_cb(GtkWidget *widget, gpointer data) {
+  start_noise();
 }
 
-static void nr_none_cb(GtkWidget *widget, gpointer data) {
-  nr=0;
-  nr2=0;
-  nb=0;
-  nb2=0;
-  anf=0;
-  snb=0;
-  update_noise();
+void ctun_cb (GtkWidget *widget, gpointer data) {
+  int id=active_receiver->id;
+  vfo[id].ctun=vfo[id].ctun==1?0:1;
+  if(!vfo[id].ctun) {
+    vfo[id].offset=0;
+  }
+  vfo[id].ctun_frequency=vfo[id].frequency;
+  set_offset(active_receiver,vfo[id].offset);
+  vfo_update(NULL);
 }
 
-static void nr_cb(GtkWidget *widget, gpointer data) {
-  nr=1;
-  nr2=0;
-  nb=0;
-  nb2=0;
-  anf=0;
-  snb=0;
-  update_noise();
+static void atob_cb (GtkWidget *widget, gpointer data) {
+  vfo_a_to_b();
 }
 
-static void nr2_cb(GtkWidget *widget, gpointer data) {
-  nr=0;
-  nr2=1;
-  nb=0;
-  nb2=0;
-  anf=0;
-  snb=0;
-  update_noise();
+static void btoa_cb (GtkWidget *widget, gpointer data) {
+  vfo_b_to_a();
 }
 
-static void nb_cb(GtkWidget *widget, gpointer data) {
-  nr=0;
-  nr2=0;
-  nb=1;
-  nb2=0;
-  anf=0;
-  snb=0;
-  update_noise();
+static void aswapb_cb (GtkWidget *widget, gpointer data) {
+  vfo_a_swap_b();
 }
 
-static void nb2_cb(GtkWidget *widget, gpointer data) {
-  nr=0;
-  nr2=0;
-  nb=0;
-  nb2=1;
-  anf=0;
-  snb=0;
-  update_noise();
+static void split_cb (GtkWidget *widget, gpointer data) {
+  split=split==1?0:1;
+  if(split) {
+    tx_set_mode(transmitter,vfo[VFO_B].mode);
+  } else {
+    tx_set_mode(transmitter,vfo[VFO_A].mode);
+  }
+  vfo_update(NULL);
 }
 
-static void anf_cb(GtkWidget *widget, gpointer data) {
-  nr=0;
-  nr2=0;
-  nb=0;
-  nb2=0;
-  anf=1;
-  snb=0;
-  update_noise();
+static void rit_cb(GtkWidget *widget, gpointer data) {
+  int i=(int)data;
+  vfo[active_receiver->id].rit+=i*rit_increment;
+  if(vfo[active_receiver->id].rit>1000) vfo[active_receiver->id].rit=1000;
+  if(vfo[active_receiver->id].rit<-1000) vfo[active_receiver->id].rit=-1000;
+  vfo_update(NULL);
+  rit_timer=g_timeout_add(200,rit_timer_cb,(void *)i);
 }
 
-static void snb_cb(GtkWidget *widget, gpointer data) {
-  nr=0;
-  nr2=0;
-  nb=0;
-  nb2=0;
-  anf=0;
-  snb=1;
-  update_noise();
+static void freq_cb(GtkWidget *widget, gpointer data) {
+  start_vfo();
 }
-*/
 
-void agc_cb(GtkWidget *widget, gpointer data) {
-  start_agc();
-/*
-  int show=1;
-  if(last_dialog!=NULL) {
-    if(strcmp(gtk_window_get_title(GTK_WINDOW(last_dialog)),"AGC")==0) {
-      show=0;
-    }
-    gtk_widget_destroy(last_dialog);
-    last_dialog=NULL;
-  }
-  if(show) {
-    GtkWidget *dialog=gtk_dialog_new_with_buttons("AGC",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
-
-    GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
-    GtkWidget *grid=gtk_grid_new();
-
-    gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
-    gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
-
-    GtkWidget *b_off=gtk_radio_button_new_with_label(NULL,"Off"); 
-    //gtk_widget_override_font(b_off, pango_font_description_from_string("Arial 16"));
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_off), agc==AGC_OFF);
-    gtk_widget_show(b_off);
-    gtk_grid_attach(GTK_GRID(grid),b_off,0,0,2,1);
-    g_signal_connect(b_off,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_OFF);
-
-    GtkWidget *b_long=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_off),"Long"); 
-    //gtk_widget_override_font(b_long, pango_font_description_from_string("Arial 16"));
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_long), agc==AGC_LONG);
-    gtk_widget_show(b_long);
-    gtk_grid_attach(GTK_GRID(grid),b_long,0,1,2,1);
-    g_signal_connect(b_long,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_LONG);
-
-    GtkWidget *b_slow=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_long),"Slow"); 
-    //gtk_widget_override_font(b_slow, pango_font_description_from_string("Arial 16"));
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_slow), agc==AGC_SLOW);
-    gtk_widget_show(b_slow);
-    gtk_grid_attach(GTK_GRID(grid),b_slow,0,2,2,1);
-    g_signal_connect(b_slow,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_SLOW);
-
-    GtkWidget *b_medium=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_slow),"Medium"); 
-    //gtk_widget_override_font(b_medium, pango_font_description_from_string("Arial 16"));
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_medium), agc==AGC_MEDIUM);
-    gtk_widget_show(b_medium);
-    gtk_grid_attach(GTK_GRID(grid),b_medium,0,3,2,1);
-    g_signal_connect(b_medium,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_MEDIUM);
-
-    GtkWidget *b_fast=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_medium),"Fast"); 
-    //gtk_widget_override_font(b_fast, pango_font_description_from_string("Arial 16"));
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_fast), agc==AGC_FAST);
-    gtk_widget_show(b_fast);
-    gtk_grid_attach(GTK_GRID(grid),b_fast,0,4,2,1);
-    g_signal_connect(b_fast,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_FAST);
-  
-    gtk_container_add(GTK_CONTAINER(content),grid);
-
-    GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
-    //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 16"));
-    g_signal_connect(close_button,"clicked",G_CALLBACK(close_cb),(gpointer *)NULL);
-    gtk_widget_show_all(dialog);
-    last_dialog=dialog;
-    int result=gtk_dialog_run(GTK_DIALOG(dialog));
-  }
-*/
+static void mem_cb(GtkWidget *widget, gpointer data) {
+  start_store();
 }
 
-void noise_cb(GtkWidget *widget, gpointer data) {
-  start_noise();
-/*
-  int show=1;
-  if(last_dialog!=NULL) {
-    if(strcmp(gtk_window_get_title(GTK_WINDOW(last_dialog)),"Noise")==0) {
-      show=0;
-    }
-    gtk_widget_destroy(last_dialog);
-    last_dialog=NULL;
-  }
-  if(show) {
-    GtkWidget *dialog=gtk_dialog_new_with_buttons("Noise",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
-
-    GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
-    GtkWidget *grid=gtk_grid_new();
-
-    gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
-    gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
-
-    GtkWidget *b_nr_none=gtk_radio_button_new_with_label(NULL,"None");
-    //gtk_widget_override_font(b_none, pango_font_description_from_string("Arial 16"));
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr_none), nr_none==1);
-    gtk_widget_show(b_nr_none);
-    gtk_grid_attach(GTK_GRID(grid),b_nr_none,0,0,2,1);
-    g_signal_connect(b_nr_none,"pressed",G_CALLBACK(nr_none_cb),NULL);
-
-    GtkWidget *b_nr=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_nr_none),"NR");
-    //gtk_widget_override_font(b_nr, pango_font_description_from_string("Arial 16"));
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr), nr==1);
-    gtk_widget_show(b_nr);
-    gtk_grid_attach(GTK_GRID(grid),b_nr,0,1,2,1);
-    g_signal_connect(b_nr,"pressed",G_CALLBACK(nr_cb),NULL);
-
-    GtkWidget *b_nr2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_nr),"NR2");
-    //gtk_widget_override_font(b_nr2, pango_font_description_from_string("Arial 16"));
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr2), nr2==1);
-    gtk_widget_show(b_nr2);
-    gtk_grid_attach(GTK_GRID(grid),b_nr2,0,2,2,1);
-    g_signal_connect(b_nr2,"pressed",G_CALLBACK(nr2_cb),NULL);
-
-    GtkWidget *b_anf=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_nr2),"ANF");
-    //gtk_widget_override_font(b_anf, pango_font_description_from_string("Arial 16"));
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_anf), anf==1);
-    gtk_widget_show(b_anf);
-    gtk_grid_attach(GTK_GRID(grid),b_anf,0,3,2,1);
-    g_signal_connect(b_anf,"pressed",G_CALLBACK(anf_cb),NULL);
-  
-    GtkWidget *b_snb=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_anf),"SNB");
-    //gtk_widget_override_font(b_snb, pango_font_description_from_string("Arial 16"));
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_snb), snb==1);
-    gtk_widget_show(b_snb);
-    gtk_grid_attach(GTK_GRID(grid),b_snb,0,4,2,1);
-    g_signal_connect(b_snb,"pressed",G_CALLBACK(snb_cb),NULL);
-
-    gtk_container_add(GTK_CONTAINER(content),grid);
-
-    GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
-    //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 16"));
-    g_signal_connect(close_button,"clicked",G_CALLBACK(close_cb),(gpointer *)NULL);
-    gtk_widget_show_all(dialog);
-
-    last_dialog=dialog;
-
-    int result=gtk_dialog_run(GTK_DIALOG(dialog));
-
-    }
-*/
+static void vox_cb(GtkWidget *widget, gpointer data) {
+  vox=vox==1?0:1;
+  vfo_update(NULL);
 }
 
 static void stop() {
@@ -954,37 +523,12 @@ static void cw_cb(GtkWidget *widget, gpointer data) {
   int result=gtk_dialog_run(GTK_DIALOG(dialog));
 }
 
-/*
-static void adc_cb(GtkWidget *widget, gpointer data) {
-  int adc0=adc[0];
-  adc[0]=adc[1];
-  adc[1]=adc0;
-
-  char label[16];
-  gtk_grid_remove_row(GTK_GRID(toolbar_top_1),0);
-  
-  sprintf(label,"RX0=%d",adc[0]);
-  GtkWidget *rx0=gtk_label_new(label);
-  //gtk_widget_override_font(rx0, pango_font_description_from_string("Arial 16"));
-  gtk_widget_show(rx0);
-  gtk_grid_attach(GTK_GRID(toolbar_top_1),rx0,0,0,1,1);
-  
-  sprintf(label,"RX1=%d",adc[1]);
-  GtkWidget *rx1=gtk_label_new(label);
-  //gtk_widget_override_font(rx1, pango_font_description_from_string("Arial 16"));
-  gtk_widget_show(rx1);
-  gtk_grid_attach(GTK_GRID(toolbar_top_1),rx1,1,0,1,1);
-}
-*/
-
 void lock_cb(GtkWidget *widget, gpointer data) {
   locked=locked==1?0:1;
   vfo_update(NULL);
 }
 
 void mox_cb(GtkWidget *widget, gpointer data) {
-
-
   if(getTune()==1) {
     setTune(0);
   }
@@ -996,17 +540,31 @@ void mox_cb(GtkWidget *widget, gpointer data) {
   } else if(canTransmit() || tx_out_of_band) {
     setMox(1);
   }
-  vfo_update(NULL);
+  g_idle_add(vfo_update,NULL);
+}
+
+int mox_update(void *data) {
+  if(getTune()==1) {
+    setTune(0);
+  }
+  setMox((int)data);
+  return 0;
 }
 
 int ptt_update(void *data) {
+  int mode;
+  if(split) {
+    mode=vfo[1].mode;
+  } else {
+    mode=vfo[0].mode;
+  }
   if(protocol==NEW_PROTOCOL || (mode!=modeCWU && mode!=modeCWL)) {
     mox_cb(NULL,NULL);
   }
   return 0;
 }
 
-static void tune_cb(GtkWidget *widget, gpointer data) {
+void tune_cb(GtkWidget *widget, gpointer data) {
   if(getMox()==1) {
     setMox(0);
   }
@@ -1018,270 +576,217 @@ static void tune_cb(GtkWidget *widget, gpointer data) {
   vfo_update(NULL);
 }
 
-static gboolean rit_timer_cb(gpointer data) {
-  if((int)data==1) {
-    rit+=rit_increment;
-  } else {
-    rit-=rit_increment;
-  }
-  if(rit>1000) rit=1000;
-  if(rit<-1000) rit=-1000;
-  vfo_update(NULL);
-  return TRUE;
-}
-
 void sim_s1_pressed_cb(GtkWidget *widget, gpointer data) {
-  if(function) {
-    rit+=rit_increment;
-    if(rit>1000) rit=1000;
-    vfo_update(NULL);
-    rit_timer=g_timeout_add(200,rit_timer_cb,(gpointer)1);
-  } else {
-    BAND* band;
-    BANDSTACK_ENTRY *entry;
-    if(toolbar_dialog_buttons) {
+  switch(function) {
+    case 0:
       band_cb(widget,data);
-    } else {
-      int b=band_get_current();
-      if(function) {
-        b--;
-        if(b<0) {
-          b=BANDS-1;
-        }
-#ifdef LIMESDR
-        if(protocol!=LIMESDR_PROTOCOL) {
-          if(b==band3400) {
-            b=band6;
-          }
-        }
-#endif
+      break;
+    case 1:
+      lock_cb(widget,data);
+      break;
+    case 2:
+      freq_cb(widget,data);
+      break;
+    case 3:
+      full_tune=full_tune==1?0:1;
+      if(full_tune) {
+        set_button_text_color(sim_s2,"black");
+        set_button_text_color(sim_s1,"red");
       } else {
-        b++;
-        if(b>=BANDS) {
-          b=0;
-        }
-#ifdef LIMESDR
-        if(protocol!=LIMESDR_PROTOCOL) {
-          if(b==band70) { 
-            b=bandGen;
-          }
-        }
-#endif
+        set_button_text_color(sim_s1,"black");
       }
-      band=band_set_current(b);
-      entry=bandstack_entry_get_current();
-
-      setFrequency(entry->frequencyA);
-      setMode(entry->mode);
-      FILTER* band_filters=filters[entry->mode];
-      FILTER* band_filter=&band_filters[entry->filter];
-      setFilter(band_filter->low,band_filter->high);
-
-      band=band_get_current_band();
-      set_alex_rx_antenna(band->alexRxAntenna);
-      set_alex_tx_antenna(band->alexTxAntenna);
-      set_alex_attenuation(band->alexAttenuation);
-      vfo_update(NULL);
-  
-      calcDriveLevel();
-      calcTuneDriveLevel();
-    }
+      break;
   }
 }
 
 void sim_s1_released_cb(GtkWidget *widget, gpointer data) {
-  if(function) {
-    g_source_remove(rit_timer);
+  switch(function) {
+    case 0:
+      break;
+    case 1:
+      break;
+    case 2:
+      break;
+    case 3:
+      break;
   }
 }
 
 void sim_s2_pressed_cb(GtkWidget *widget, gpointer data) {
-  if(function) {
-    rit-=rit_increment;
-    if(rit<-1000) rit=-1000;
-    vfo_update(NULL);
-    rit_timer=g_timeout_add(200,rit_timer_cb,(gpointer)-1);
-  } else {
-    BANDSTACK_ENTRY *entry;
-    if(toolbar_dialog_buttons) {
+  switch(function) {
+    case 0:
       bandstack_cb(widget,data);
-    } else {
-      if(function) {
-        entry=bandstack_entry_previous();
+      break;
+    case 1:
+      ctun_cb(widget,data);
+      break;
+    case 2:
+      mem_cb(widget,data);
+      break;
+    case 3:
+      memory_tune=memory_tune==1?0:1;
+      if(memory_tune) {
+        set_button_text_color(sim_s1,"black");
+        set_button_text_color(sim_s2,"red");
       } else {
-        entry=bandstack_entry_next();
+        set_button_text_color(sim_s2,"black");
       }
-      setFrequency(entry->frequencyA);
-      setMode(entry->mode);
-      FILTER* band_filters=filters[entry->mode];
-      FILTER* band_filter=&band_filters[entry->filter];
-      setFilter(band_filter->low,band_filter->high);
-      vfo_update(NULL);
-    }
+      break;
   }
 }
 
 void sim_s2_released_cb(GtkWidget *widget, gpointer data) {
-  if(function) {
-    g_source_remove(rit_timer);
+  switch(function) {
+    case 0:
+      break;
+    case 1:
+      break;
+    case 2:
+      break;
+    case 3:
+      break;
   }
 }
 
 
-void sim_s3_cb(GtkWidget *widget, gpointer data) {
-  if(function) {
-    ctun=ctun==1?0:1;
-    if(!ctun) {
-      ddsOffset=0;
-      wdsp_set_offset(ddsOffset);
-    }
-    vfo_update(NULL);
-  } else {
-    BAND* band;
-    BANDSTACK_ENTRY *entry;
-  
-    if(toolbar_dialog_buttons) {
+void sim_s3_pressed_cb(GtkWidget *widget, gpointer data) {
+  switch(function) {
+    case 0:
       mode_cb(widget,data);
-    } else {
-        band=band_get_current_band();
-      entry=bandstack_entry_get_current();
-      if(function) {
-        entry->mode--;
-        if(entry->mode<0) {
-          entry->mode=MODES-1;
-        }
-      } else {
-        entry->mode++;
-        if(entry->mode>=MODES) {
-          entry->mode=0;
-        }
-      }
-      setMode(entry->mode);
-
-      FILTER* band_filters=filters[entry->mode];
-      FILTER* band_filter=&band_filters[entry->filter];
-      setFilter(band_filter->low,band_filter->high);
-
-      vfo_update(NULL);
-    }
+      break;
+    case 1:
+      // A>B
+      atob_cb(widget,data);
+      break;
+    case 2:
+      vox_cb(widget,data);
+      break;
+    case 3:
+      break;
   }
 }
 
-void sim_s4_cb(GtkWidget *widget, gpointer data) {
-  BAND* band;
-  BANDSTACK_ENTRY *entry;
+void sim_s3_released_cb(GtkWidget *widget, gpointer data) {
+  switch(function) {
+    case 0:
+      break;
+    case 1:
+      break;
+    case 2:
+      break;
+    case 3:
+      break;
+  }
+}
 
-  if(toolbar_dialog_buttons) {
-    if(function) {
-    } else {
+void sim_s4_pressed_cb(GtkWidget *widget, gpointer data) {
+  switch(function) {
+    case 0:
       filter_cb(widget,data);
-    }
-  } else {
-    band=band_get_current_band();
-    entry=bandstack_entry_get_current();
-    // note order of filter reversed (largest first)
-    if(function) {
-      entry->filter++;
-      if(entry->filter>=FILTERS) {
-        entry->filter=0;
-      }
-    } else {
-      entry->filter--;
-      if(entry->filter<0) {
-        entry->filter=FILTERS-1;
-      }
-    }
-
-    FILTER* band_filters=filters[entry->mode];
-    FILTER* band_filter=&band_filters[entry->filter];
-    setFilter(band_filter->low,band_filter->high);
-  
-    vfo_update(NULL);
+      break;
+    case 1:
+      // A<B
+      btoa_cb(widget,data);
+      break;
+    case 2:
+      rit_cb(widget,(void *)1);
+      break;
+    case 3:
+      break;
   }
+}
 
+void sim_s4_released_cb(GtkWidget *widget, gpointer data) {
+  switch(function) {
+    case 0:
+      break;
+    case 1:
+      break;
+    case 2:
+      g_source_remove(rit_timer);
+      break;
+    case 3:
+      break;
+  }
 }
 
-void sim_s5_cb(GtkWidget *widget, gpointer data) {
-  if(toolbar_dialog_buttons) {
-    if(function) {
-    } else {
+void sim_s5_pressed_cb(GtkWidget *widget, gpointer data) {
+  switch(function) {
+    case 0:
       noise_cb(widget,data);
-    }
-  } else {
-    if(function) {
-      if(nr) {
-        nr=0;
-      } else if(nr2) {
-        nr2=0;
-        nr=1;
-      } else if(anf) {
-        anf=0;
-        nr2=1;
-      } else if(snb) {
-        snb=0;
-        anf=1;
-      } else {
-        snb=1;
-      }
-    } else {
-      if(nr) {
-        nr=0;
-        nr2=1;
-      } else if(nr2) {
-        nr2=0;
-        anf=1;
-      } else if(anf) {
-        anf=0;
-        snb=1;
-      } else if(snb) {
-        snb=0;
-      } else {
-        nr=1;
-      }
-    }
-    SetRXAANRRun(CHANNEL_RX0, nr);
-    SetRXAEMNRRun(CHANNEL_RX0, nr2);
-    SetRXAANFRun(CHANNEL_RX0, anf);
-    SetRXASNBARun(CHANNEL_RX0, snb);
-    vfo_update(NULL);
+      break;
+    case 1:
+      // A<>B
+      aswapb_cb(widget,data);
+      break;
+    case 2:
+      rit_cb(widget,(void *)-1);
+      break;
+    case 3:
+      break;
   }
 }
 
-void sim_s6_cb(GtkWidget *widget, gpointer data) {
-  if(toolbar_dialog_buttons) {
-    if(function) {
-      lock_cb(widget,data);
-    } else {
+void sim_s5_released_cb(GtkWidget *widget, gpointer data) {
+  switch(function) {
+    case 0:
+      break;
+    case 1:
+      break;
+    case 2:
+      g_source_remove(rit_timer);
+      break;
+    case 3:
+      break;
+  }
+}
+
+void sim_s6_pressed_cb(GtkWidget *widget, gpointer data) {
+  switch(function) {
+    case 0:
       agc_cb(widget,data);
-    }
-  } else {
-    if(function) {
-      agc--;
-      if(agc<0) {
-        agc=3;
-      }
-    } else {
-      agc++;
-      if(agc>=4) {
-        agc=0;
-      }
-    }
-    SetRXAAGCMode(CHANNEL_RX0, agc);
-    vfo_update(NULL);
+      break;
+    case 1:
+      split_cb(widget,data);
+      break;
+    case 2:
+      break;
+    case 3:
+      break;
+  }
+}
+
+void sim_s6_released_cb(GtkWidget *widget, gpointer data) {
+  switch(function) {
+    case 0:
+      break;
+    case 1:
+      break;
+    case 2:
+      break;
+    case 3:
+      break;
   }
 }
 
 void sim_mox_cb(GtkWidget *widget, gpointer data) {
-  if(function) {
-    tune_cb((GtkWidget *)NULL, (gpointer)NULL);
-  } else {
-    mox_cb((GtkWidget *)NULL, (gpointer)NULL);
+  switch(function) {
+    case 0:
+    case 1:
+    case 2:
+      mox_cb((GtkWidget *)NULL, (gpointer)NULL);
+      break;
+    case 3:
+      tune_cb((GtkWidget *)NULL, (gpointer)NULL);
+      break;
   }
-  //vfo_update(NULL);
 }
 
 void sim_function_cb(GtkWidget *widget, gpointer data) {
-  function=function==1?0:1;
+  function++;
+  if(function>MAX_FUNCTION) {
+    function=0;
+  }
   update_toolbar_labels();
   vfo_update(NULL);
 }
@@ -1314,46 +819,50 @@ GtkWidget *toolbar_init(int my_width, int my_height, GtkWidget* parent) {
     g_signal_connect(G_OBJECT(sim_mox),"clicked",G_CALLBACK(sim_mox_cb),NULL);
     gtk_grid_attach(GTK_GRID(toolbar),sim_mox,0,0,4,1);
 
-    sim_s1=gtk_button_new_with_label("Band ^");
+    sim_s1=gtk_button_new_with_label("Band");
     gtk_widget_set_size_request (sim_s1, button_width, 0);
     //gtk_widget_override_font(sim_s1, pango_font_description_from_string("Arial 16"));
     g_signal_connect(G_OBJECT(sim_s1),"pressed",G_CALLBACK(sim_s1_pressed_cb),NULL);
     g_signal_connect(G_OBJECT(sim_s1),"released",G_CALLBACK(sim_s1_released_cb),NULL);
     gtk_grid_attach(GTK_GRID(toolbar),sim_s1,4,0,4,1);
 
-    sim_s2=gtk_button_new_with_label("BStack ^");
+    sim_s2=gtk_button_new_with_label("BStack");
     gtk_widget_set_size_request (sim_s2, button_width, 0);
     //gtk_widget_override_font(sim_s2, pango_font_description_from_string("Arial 16"));
     g_signal_connect(G_OBJECT(sim_s2),"pressed",G_CALLBACK(sim_s2_pressed_cb),NULL);
     g_signal_connect(G_OBJECT(sim_s2),"released",G_CALLBACK(sim_s2_released_cb),NULL);
     gtk_grid_attach(GTK_GRID(toolbar),sim_s2,8,0,4,1);
 
-    sim_s3=gtk_button_new_with_label("Mode ^");
+    sim_s3=gtk_button_new_with_label("Mode");
     //gtk_widget_override_font(sim_s3, pango_font_description_from_string("Arial 16"));
-    g_signal_connect(G_OBJECT(sim_s3),"clicked",G_CALLBACK(sim_s3_cb),NULL);
+    g_signal_connect(G_OBJECT(sim_s3),"pressed",G_CALLBACK(sim_s3_pressed_cb),NULL);
+    g_signal_connect(G_OBJECT(sim_s3),"released",G_CALLBACK(sim_s3_released_cb),NULL);
     gtk_grid_attach(GTK_GRID(toolbar),sim_s3,12,0,4,1);
 
-    sim_s4=gtk_button_new_with_label("Filter ^");
+    sim_s4=gtk_button_new_with_label("Filter");
     //gtk_widget_override_font(sim_s4, pango_font_description_from_string("Arial 16"));
-    g_signal_connect(G_OBJECT(sim_s4),"clicked",G_CALLBACK(sim_s4_cb),NULL);
+    g_signal_connect(G_OBJECT(sim_s4),"pressed",G_CALLBACK(sim_s4_pressed_cb),NULL);
+    g_signal_connect(G_OBJECT(sim_s4),"released",G_CALLBACK(sim_s4_released_cb),NULL);
     gtk_grid_attach(GTK_GRID(toolbar),sim_s4,16,0,4,1);
 
-    sim_s5=gtk_button_new_with_label("Noise ^");
+    sim_s5=gtk_button_new_with_label("Noise");
     //gtk_widget_override_font(sim_s5, pango_font_description_from_string("Arial 16"));
-    g_signal_connect(G_OBJECT(sim_s5),"clicked",G_CALLBACK(sim_s5_cb),NULL);
+    g_signal_connect(G_OBJECT(sim_s5),"pressed",G_CALLBACK(sim_s5_pressed_cb),NULL);
+    g_signal_connect(G_OBJECT(sim_s5),"released",G_CALLBACK(sim_s5_released_cb),NULL);
     gtk_grid_attach(GTK_GRID(toolbar),sim_s5,20,0,4,1);
 
-    sim_s6=gtk_button_new_with_label("AGC ^");
+    sim_s6=gtk_button_new_with_label("AGC");
     //gtk_widget_override_font(sim_s6, pango_font_description_from_string("Arial 16"));
-    g_signal_connect(G_OBJECT(sim_s6),"clicked",G_CALLBACK(sim_s6_cb),NULL);
+    g_signal_connect(G_OBJECT(sim_s6),"pressed",G_CALLBACK(sim_s6_pressed_cb),NULL);
+    g_signal_connect(G_OBJECT(sim_s6),"released",G_CALLBACK(sim_s6_released_cb),NULL);
     gtk_grid_attach(GTK_GRID(toolbar),sim_s6,24,0,4,1);
 
     sim_function=gtk_button_new_with_label("Function");
     //gtk_widget_override_font(sim_function, pango_font_description_from_string("Arial 16"));
-    g_signal_connect(G_OBJECT(sim_function),"clicked",G_CALLBACK(function_cb),NULL);
+    g_signal_connect(G_OBJECT(sim_function),"clicked",G_CALLBACK(sim_function_cb),NULL);
     gtk_grid_attach(GTK_GRID(toolbar),sim_function,28,0,4,1);
 
-    update_toolbar_labels();
+    //update_toolbar_labels();
 
     last_dialog=NULL;
 
index 54cbf33209e59e8369612794fad19e5c16a0b904..203b606884a7cf035ab0a5fd7f2201b281473f29 100644 (file)
--- a/toolbar.h
+++ b/toolbar.h
 
 extern int function;
 
+
 void update_toolbar_labels();
 int ptt_update(void *data);
-void lock_cb(GtkWidget *widget, gpointer data);
-
+int mox_update(void *data);
+void tune_cb(GtkWidget *widget, gpointer data);
 
 void sim_mox_cb(GtkWidget *widget, gpointer data);
 void sim_s1_pressed_cb(GtkWidget *widget, gpointer data);
 void sim_s1_released_cb(GtkWidget *widget, gpointer data);
 void sim_s2_pressed_cb(GtkWidget *widget, gpointer data);
 void sim_s2_released_cb(GtkWidget *widget, gpointer data);
-void sim_s3_cb(GtkWidget *widget, gpointer data);
-void sim_s4_cb(GtkWidget *widget, gpointer data);
-void sim_s5_cb(GtkWidget *widget, gpointer data);
-void sim_s6_cb(GtkWidget *widget, gpointer data);
+void sim_s3_pressed_cb(GtkWidget *widget, gpointer data);
+void sim_s3_released_cb(GtkWidget *widget, gpointer data);
+void sim_s4_pressed_cb(GtkWidget *widget, gpointer data);
+void sim_s4_released_cb(GtkWidget *widget, gpointer data);
+void sim_s5_pressed_cb(GtkWidget *widget, gpointer data);
+void sim_s5_released_cb(GtkWidget *widget, gpointer data);
+void sim_s6_pressed_cb(GtkWidget *widget, gpointer data);
+void sim_s6_released_cb(GtkWidget *widget, gpointer data);
 void sim_function_cb(GtkWidget *widget, gpointer data);
 
 GtkWidget *toolbar_init(int my_width, int my_height, GtkWidget* parent);
diff --git a/transmitter.c b/transmitter.c
new file mode 100644 (file)
index 0000000..f4a7812
--- /dev/null
@@ -0,0 +1,626 @@
+/* Copyright (C)
+* 2017 - John Melton, G0ORX/N6LYT
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#include <gtk/gtk.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <wdsp.h>
+
+#include "alex.h"
+#include "band.h"
+#include "bandstack.h"
+#include "channel.h"
+#include "main.h"
+#include "meter.h"
+#include "mode.h"
+#include "property.h"
+#include "radio.h"
+#include "vfo.h"
+#include "meter.h"
+#include "tx_panadapter.h"
+#include "waterfall.h"
+#include "transmitter.h"
+
+#define min(x,y) (x<y?x:y)
+#define max(x,y) (x<y?y:x)
+
+static int filterLow;
+static int filterHigh;
+
+void reconfigure_transmitter(TRANSMITTER *tx,int height) {
+  gtk_widget_set_size_request(tx->panadapter, tx->width, height);
+}
+
+void transmitter_save_state(TRANSMITTER *tx) {
+  char name[128];
+  char value[128];
+
+  sprintf(name,"transmitter.%d.fps",tx->id);
+  sprintf(value,"%d",tx->fps);
+  setProperty(name,value);
+  sprintf(name,"transmitter.%d.filter_low",tx->id);
+  sprintf(value,"%d",tx->filter_low);
+  setProperty(name,value);
+  sprintf(name,"transmitter.%d.filter_high",tx->id);
+  sprintf(value,"%d",tx->filter_high);
+  setProperty(name,value);
+  sprintf(name,"transmitter.%d.alex_antenna",tx->id);
+  sprintf(value,"%d",tx->alex_antenna);
+  setProperty(name,value);
+
+  sprintf(name,"transmitter.%d.local_microphone",tx->id);
+  sprintf(value,"%d",tx->local_microphone);
+  setProperty(name,value);
+  sprintf(name,"transmitter.%d.input_device",tx->id);
+  sprintf(value,"%d",tx->input_device);
+  setProperty(name,value);
+
+}
+
+void transmitter_restore_state(TRANSMITTER *tx) {
+  char name[128];
+  char *value;
+
+  sprintf(name,"transmitter.%d.fps",tx->id);
+  value=getProperty(name);
+  if(value) tx->fps=atoi(value);
+  sprintf(name,"transmitter.%d.filter_low",tx->id);
+  value=getProperty(name);
+  if(value) tx->filter_low=atoi(value);
+  sprintf(name,"transmitter.%d.filter_high",tx->id);
+  value=getProperty(name);
+  if(value) tx->filter_high=atoi(value);
+  sprintf(name,"transmitter.%d.alex_antenna",tx->id);
+  value=getProperty(name);
+  if(value) tx->alex_antenna=atoi(value);
+
+  sprintf(name,"transmitter.%d.local_microphone",tx->id);
+  value=getProperty(name);
+  if(value) tx->local_microphone=atoi(value);
+  sprintf(name,"transmitter.%d.input_device",tx->id);
+  value=getProperty(name);
+  if(value) tx->input_device=atoi(value);
+}
+
+static gint update_display(gpointer data) {
+  TRANSMITTER *tx=(TRANSMITTER *)data;
+  int rc;
+  double fwd;
+  double rev;
+  double exciter;
+
+  if(tx->displaying) {
+    GetPixels(tx->id,0,tx->pixel_samples,&rc);
+    if(rc) {
+      tx_panadapter_update(tx);
+    } else {
+//fprintf(stderr,"tx: update_display: GetPixels: id=%d returned %d\n",tx->id,rc);
+    }
+
+    double alc=GetTXAMeter(tx->id, alc);
+    double constant1=3.3;
+    double constant2=0.095;
+
+    if(protocol==ORIGINAL_PROTOCOL) {
+      switch(device) {
+        case DEVICE_METIS:
+          constant1=3.3;
+          constant2=0.09;
+          break;
+        case DEVICE_HERMES:
+          constant1=3.3;
+          constant2=0.095;
+          break;
+        case DEVICE_ANGELIA:
+          constant1=3.3;
+          constant2=0.095;
+          break;
+        case DEVICE_ORION:
+          constant1=5.0;
+          constant2=0.108;
+          break;
+        case DEVICE_ORION2:
+          constant1=5.0;
+          constant2=0.108;
+          break;
+        case DEVICE_HERMES_LITE:
+          break;
+      }
+
+      int power=alex_forward_power;
+      if(power==0) {
+        power=exciter_power;
+      }
+      double v1;
+      v1=((double)power/4095.0)*constant1;
+      fwd=(v1*v1)/constant2;
+
+      power=exciter_power;
+      v1=((double)power/4095.0)*constant1;
+      exciter=(v1*v1)/constant2;
+
+      rev=0.0;
+      if(alex_forward_power!=0) {
+        power=alex_reverse_power;
+        v1=((double)power/4095.0)*constant1;
+        rev=(v1*v1)/constant2;
+      }
+    } else {
+      switch(device) {
+        case NEW_DEVICE_ATLAS:
+          constant1=3.3;
+          constant2=0.09;
+          break;
+        case NEW_DEVICE_HERMES:
+          constant1=3.3;
+          constant2=0.09;
+          break;
+        case NEW_DEVICE_HERMES2:
+          constant1=3.3;
+          constant2=0.095;
+          break;
+        case NEW_DEVICE_ANGELIA:
+          constant1=3.3;
+          constant2=0.095;
+          break;
+        case NEW_DEVICE_ORION:
+          constant1=5.0;
+          constant2=0.108;
+          break;
+        case NEW_DEVICE_ORION2:
+          constant1=5.0;
+          constant2=0.108;
+          break;
+        case NEW_DEVICE_HERMES_LITE:
+          constant1=3.3;
+          constant2=0.09;
+          break;
+      }
+
+      int power=alex_forward_power;
+      if(power==0) {
+        power=exciter_power;
+      }
+      double v1;
+      v1=((double)power/4095.0)*constant1;
+      fwd=(v1*v1)/constant2;
+
+      power=exciter_power;
+      v1=((double)power/4095.0)*constant1;
+      exciter=(v1*v1)/constant2;
+
+      rev=0.0;
+      if(alex_forward_power!=0) {
+        power=alex_reverse_power;
+        v1=((double)power/4095.0)*constant1;
+        rev=(v1*v1)/constant2;
+      }
+    } 
+
+    meter_update(POWER,fwd,rev,exciter,alc);
+
+    return TRUE; // keep going
+  }
+  return FALSE; // no more timer events
+}
+
+
+static void init_analyzer(TRANSMITTER *tx) {
+    int flp[] = {0};
+    double keep_time = 0.1;
+    int n_pixout=1;
+    int spur_elimination_ffts = 1;
+    int data_type = 1;
+    int fft_size = 8192;
+    int window_type = 4;
+    double kaiser_pi = 14.0;
+    int overlap = 2048;
+    int clip = 0;
+    int span_clip_l = 0;
+    int span_clip_h = 0;
+    int pixels=tx->pixels;
+    int stitches = 1;
+    int avm = 0;
+    double tau = 0.001 * 120.0;
+    int calibration_data_set = 0;
+    double span_min_freq = 0.0;
+    double span_max_freq = 0.0;
+
+    int max_w = fft_size + (int) min(keep_time * (double) tx->fps, keep_time * (double) fft_size * (double) tx->fps);
+
+    overlap = (int)max(0.0, ceil(fft_size - (double)tx->mic_sample_rate / (double)tx->fps));
+
+    fprintf(stderr,"SetAnalyzer id=%d buffer_size=%d overlap=%d\n",tx->id,tx->output_samples,overlap);
+
+
+    SetAnalyzer(tx->id,
+            n_pixout,
+            spur_elimination_ffts, //number of LO frequencies = number of ffts used in elimination
+            data_type, //0 for real input data (I only); 1 for complex input data (I & Q)
+            flp, //vector with one elt for each LO frequency, 1 if high-side LO, 0 otherwise
+            fft_size, //size of the fft, i.e., number of input samples
+            tx->output_samples, //number of samples transferred for each OpenBuffer()/CloseBuffer()
+            window_type, //integer specifying which window function to use
+            kaiser_pi, //PiAlpha parameter for Kaiser window
+            overlap, //number of samples each fft (other than the first) is to re-use from the previous
+            clip, //number of fft output bins to be clipped from EACH side of each sub-span
+            span_clip_l, //number of bins to clip from low end of entire span
+            span_clip_h, //number of bins to clip from high end of entire span
+            pixels, //number of pixel values to return.  may be either <= or > number of bins
+            stitches, //number of sub-spans to concatenate to form a complete span
+            calibration_data_set, //identifier of which set of calibration data to use
+            span_min_freq, //frequency at first pixel value8192
+            span_max_freq, //frequency at last pixel value
+            max_w //max samples to hold in input ring buffers
+    );
+
+}
+
+#ifdef INCLUDED
+void transmitter_change_sample_rate(TRANSMITTER *tx,int sample_rate) {
+  SetChannelState(tx->id,0,1);
+  tx->mic_sample_rate=sample_rate;
+  tx->output_samples=tx->buffer_size/(tx->mic_sample_rate/48000);
+  free(tx->mic_input_buffer);
+  tx->mic_input_buffer=malloc(sizeof(double)*2*tx->buffer_size);
+  init_analyzer(tx);
+fprintf(stderr,"transmitter_change_sample_rate: id=%d rate=%d output_samples=%d\n",tx->id, tx->mic_sample_rate, tx->output_samples);
+  SetChannelState(tx->id,1,0);
+}
+#endif
+
+static void create_visual(TRANSMITTER *tx) {
+  fprintf(stderr,"transmitter: create_visual: id=%d\n",tx->id);
+
+  tx->panel=gtk_fixed_new();
+  gtk_widget_set_size_request (tx->panel, tx->width, tx->height);
+
+  if(tx->display_panadapter) {
+    tx_panadapter_init(tx,tx->width,tx->height);
+    gtk_fixed_put(GTK_FIXED(tx->panel),tx->panadapter,0,0);
+  }
+
+}
+
+TRANSMITTER *create_transmitter(int id, int buffer_size, int fft_size, int fps, int width, int height) {
+  int rc;
+
+  TRANSMITTER *tx=malloc(sizeof(TRANSMITTER));
+  tx->id=id;
+  tx->buffer_size=buffer_size;
+  tx->fft_size=fft_size;
+  tx->fps=fps;
+  if(protocol==ORIGINAL_PROTOCOL) {
+    tx->mic_sample_rate=48000;
+//    tx->mic_sample_rate=receiver[0]->sample_rate;
+    tx->mic_dsp_rate=48000;
+    tx->iq_output_rate=48000;
+//    tx->output_samples=tx->buffer_size/(tx->mic_sample_rate/48000);
+    tx->output_samples=tx->buffer_size;
+    tx->pixels=width;
+  } else {
+    tx->mic_sample_rate=48000;
+    tx->mic_dsp_rate=48000;
+    tx->iq_output_rate=192000;
+    tx->output_samples=tx->buffer_size*4;
+    tx->pixels=width*4; // to allow 192k to 48k conversion
+  }
+
+  tx->width=width;
+  tx->height=height;
+  tx->display_panadapter=1;
+  tx->display_waterfall=0;
+
+  tx->panadapter_high=20;
+  tx->panadapter_low=-80;
+
+  tx->displaying=0;
+  
+  tx->alex_antenna=ALEX_TX_ANTENNA_1;
+
+fprintf(stderr,"create_transmitter: id=%d buffer_size=%d mic_sample_rate=%d mic_dsp_rate=%d iq_output_rate=%d output_samples=%d fps=%d\n",tx->id, tx->buffer_size, tx->mic_sample_rate, tx->mic_dsp_rate, tx->iq_output_rate, tx->output_samples,tx->fps);
+
+  tx->filter_low=tx_filter_low;
+  tx->filter_high=tx_filter_high;
+
+  transmitter_restore_state(tx);
+
+  if(split) {
+    tx->mode=vfo[VFO_B].mode;
+  } else {
+    tx->mode=vfo[VFO_A].mode;
+  }
+
+  // allocate buffers
+fprintf(stderr,"transmitter: allocate buffers: mic_input_buffer=%d iq_output_buffer=%d pixels=%d\n",tx->buffer_size,tx->output_samples,tx->pixels);
+  tx->mic_input_buffer=malloc(sizeof(double)*2*tx->buffer_size);
+  tx->iq_output_buffer=malloc(sizeof(double)*2*tx->output_samples);
+  tx->samples=0;
+  tx->pixel_samples=malloc(sizeof(float)*tx->pixels);
+
+  fprintf(stderr,"create_transmitter: OpenChannel id=%d buffer_size=%d fft_size=%d sample_rate=%d dspRate=%d outputRate=%d\n",
+              tx->id,
+              tx->buffer_size,
+              tx->fft_size,
+              tx->mic_sample_rate,
+              tx->mic_dsp_rate,
+              tx->iq_output_rate);
+
+  OpenChannel(tx->id,
+              tx->buffer_size,
+              tx->fft_size,
+              tx->mic_sample_rate,
+              tx->mic_dsp_rate,
+              tx->iq_output_rate,
+              1, // transmit
+              0, // run
+              0.010, 0.025, 0.0, 0.010, 0);
+
+  SetTXAMode(tx->id, tx->mode);
+  tx_set_filter(tx,tx_filter_low,tx_filter_high);
+  SetTXABandpassWindow(tx->id, 1);
+  SetTXABandpassRun(tx->id, 1);
+
+  SetTXAFMDeviation(tx->id,(double)deviation);
+  SetTXAFMEmphPosition(tx->id,pre_emphasize);
+
+  SetTXACFIRRun(tx->id, protocol==NEW_PROTOCOL?1:0); // turned on if new protocol
+  if(enable_tx_equalizer) {
+    SetTXAGrphEQ(tx->id, tx_equalizer);
+    SetTXAEQRun(tx->id, 1);
+  } else {
+    SetTXAEQRun(tx->id, 0);
+  }
+  SetTXACTCSSRun(tx->id, 0);
+  SetTXAAMSQRun(tx->id, 0);
+  SetTXACompressorRun(tx->id, 0);
+  SetTXAosctrlRun(tx->id, 0);
+
+  SetTXAALCAttack(tx->id, 1);
+  SetTXAALCDecay(tx->id, 10);
+  SetTXAALCSt(tx->id, tx_alc);
+
+  SetTXALevelerAttack(tx->id, 1);
+  SetTXALevelerDecay(tx->id, 500);
+  SetTXALevelerTop(tx->id, 5.0);
+  SetTXALevelerSt(tx->id, tx_leveler);
+
+  SetTXAPreGenMode(tx->id, 0);
+  SetTXAPreGenToneMag(tx->id, 0.0);
+  SetTXAPreGenToneFreq(tx->id, 0.0);
+  SetTXAPreGenRun(tx->id, 0);
+
+  SetTXAPostGenMode(tx->id, 0);
+  SetTXAPostGenToneMag(tx->id, tone_level);
+  SetTXAPostGenToneFreq(tx->id, 0.0);
+  SetTXAPostGenRun(tx->id, 0);
+
+  double gain=pow(10.0, mic_gain / 20.0);
+  SetTXAPanelGain1(tx->id,gain);
+  SetTXAPanelRun(tx->id, 1);
+
+  XCreateAnalyzer(tx->id, &rc, 262144, 1, 1, "");
+  if (rc != 0) {
+    fprintf(stderr, "XCreateAnalyzer id=%d failed: %d\n",tx->id,rc);
+  } else {
+    init_analyzer(tx);
+  }
+
+  create_visual(tx);
+
+  return tx;
+}
+
+void tx_set_mode(TRANSMITTER* tx,int mode) {
+  if(tx!=NULL) {
+    tx->mode=mode;
+    SetTXAMode(tx->id, tx->mode);
+    tx_set_filter(tx,tx_filter_low,tx_filter_high);
+  }
+}
+
+void tx_set_filter(TRANSMITTER *tx,int low,int high) {
+  int mode;
+  if(split) {
+    mode=vfo[1].mode;
+  } else {
+    mode=vfo[0].mode;
+  }
+  switch(mode) {
+    case modeLSB:
+    case modeCWL:
+    case modeDIGL:
+      tx->filter_low=-high;
+      tx->filter_high=-low;
+      break;
+    case modeUSB:
+    case modeCWU:
+    case modeDIGU:
+      tx->filter_low=low;
+      tx->filter_high=high;
+      break;
+    case modeDSB:
+    case modeAM:
+    case modeSAM:
+      tx->filter_low=-high;
+      tx->filter_high=high;
+      break;
+    case modeFMN:
+      if(deviation==2500) {
+        tx->filter_low=-4000;
+        tx->filter_high=4000;
+      } else {
+        tx->filter_low=-8000;
+        tx->filter_high=8000;
+      }
+      break;
+    case modeDRM:
+      tx->filter_low=7000;
+      tx->filter_high=17000;
+      break;
+  }
+
+  double fl=tx->filter_low;
+  double fh=tx->filter_high;
+
+  if(split) {
+    fl+=vfo[VFO_B].offset;
+    fh+=vfo[VFO_B].offset;
+  } else {
+    fl+=vfo[VFO_A].offset;
+    fh+=vfo[VFO_A].offset;
+  }
+  SetTXABandpassFreqs(tx->id, fl,fh);
+}
+
+void tx_set_pre_emphasize(TRANSMITTER *tx,int state) {
+  SetTXAFMEmphPosition(tx->id,state);
+}
+
+static void full_tx_buffer(TRANSMITTER *tx) {
+  long isample;
+  long qsample;
+  double gain;
+  int j;
+  int error;
+  int mode;
+
+  switch(protocol) {
+    case ORIGINAL_PROTOCOL:
+      gain=32767.0;  // 16 bit
+      break;
+    case NEW_PROTOCOL:
+      gain=8388607.0; // 24 bit
+      break;
+  }
+
+  if(vox_enabled || vox_setting) {
+    if(split) {
+      mode=vfo[1].mode;
+    } else {
+      mode=vfo[0].mode;
+    }
+    switch(mode) {
+      case modeLSB:
+      case modeUSB:
+      case modeDSB:
+      case modeFMN:
+      case modeAM:
+      case modeSAM:
+#ifdef FREEDV
+      case modeFREEDV:
+#endif
+        update_vox(tx);
+        break;
+    }
+  }
+
+  fexchange0(tx->id, tx->mic_input_buffer, tx->iq_output_buffer, &error);
+  if(error!=0) {
+    fprintf(stderr,"full_tx_buffer: id=%d fexchange0: error=%d\n",tx->id,error);
+  }
+
+  if(tx->displaying) {
+    Spectrum0(1, tx->id, 0, 0, tx->iq_output_buffer);
+  }
+
+if(isTransmitting()) {
+#ifdef FREEDV
+  int mode;
+  if(split) {
+    mode=vfo[VFO_B].mode;
+  } else {
+    mode=vfo[VFO_A].mode;
+  }
+
+  if(mode==modeFREEDV) {
+    gain=8388607.0;
+  }
+#endif
+
+  if(radio->device==NEW_DEVICE_ATLAS && atlas_penelope) {
+    if(tune) {
+      gain=gain*tune_drive;
+    } else {
+      gain=gain*(double)drive;
+    }
+  }
+
+  for(j=0;j<tx->output_samples;j++) {
+    isample=(long)(tx->iq_output_buffer[j*2]*gain);
+    qsample=(long)(tx->iq_output_buffer[(j*2)+1]*gain);
+    switch(protocol) {
+      case ORIGINAL_PROTOCOL:
+        old_protocol_iq_samples(isample,qsample);
+        break;
+      case NEW_PROTOCOL:
+        new_protocol_iq_samples(isample,qsample);
+        break;
+    }
+  }
+  }
+
+}
+
+void add_mic_sample(TRANSMITTER *tx,short mic_sample) {
+  double mic_sample_double;
+  int mode;
+  long sample;
+
+  if(split) {
+    mode=vfo[1].mode;
+  } else {
+    mode=vfo[0].mode;
+  }
+
+  switch(mode) {
+#ifdef FREEDV
+    case modeFREEDV:
+      break;
+#endif
+    default:
+      if(mode==modeCWL || mode==modeCWU || tune) {
+        mic_sample_double=0.0;
+      } else {
+        sample=mic_sample<<16;
+        mic_sample_double=(1.0 / 2147483648.0) * (double)(sample);
+      }
+//fprintf(stderr,"add_mic_sample: id=%d sample=%f (%d,%ld)\n",tx->id,mic_sample_double,mic_sample,sample);
+      tx->mic_input_buffer[tx->samples*2]=mic_sample_double;
+      tx->mic_input_buffer[(tx->samples*2)+1]=mic_sample_double;
+      tx->samples++;
+      if(tx->samples==tx->buffer_size) {
+        full_tx_buffer(tx);
+        tx->samples=0;
+      }
+      break;
+  }
+}
+
+void tx_set_displaying(TRANSMITTER *tx,int state) {
+  tx->displaying=state;
+  if(state) {
+fprintf(stderr,"start tx display update timer: %d\n", 1000/tx->fps);
+    tx->update_timer_id=gdk_threads_add_timeout_full(G_PRIORITY_HIGH_IDLE,1000/tx->fps, update_display, tx, NULL);
+  }
+}
+
diff --git a/transmitter.h b/transmitter.h
new file mode 100644 (file)
index 0000000..fec966d
--- /dev/null
@@ -0,0 +1,86 @@
+/* Copyright (C)
+* 2017 - John Melton, G0ORX/N6LYT
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#ifndef _TRANSMITTER_H
+#define _TRANSMITTER_H
+
+#include <gtk/gtk.h>
+
+#define AUDIO_BUFFER_SIZE 260
+
+typedef struct _transmitter {
+  int id;
+  int fps;
+  int displaying;
+  int mic_sample_rate;
+  int mic_dsp_rate;
+  int iq_output_rate;
+  int buffer_size;
+  int fft_size;
+  int pixels;
+  int samples;
+  int output_samples;
+  double *mic_input_buffer;
+  double *iq_output_buffer;
+
+  float *pixel_samples;
+  int display_panadapter;
+  int display_waterfall;
+  gint update_timer_id;
+
+  int mode;
+  int filter_low;
+  int filter_high;
+
+/*
+  long long frequency;
+  long long display_frequency;
+  long long dds_frequency;
+  long long dds_offset;
+*/
+  int alex_antenna;
+
+  int width;
+  int height;
+
+  GtkWidget *panel;
+  GtkWidget *panadapter;
+
+  int panadapter_low;
+  int panadapter_high;
+
+  cairo_surface_t *panadapter_surface;
+
+  int local_microphone;
+  int input_device;
+
+} TRANSMITTER;
+
+extern TRANSMITTER *create_transmitter(int id, int buffer_size, int fft_size, int fps, int width, int height);
+
+void reconfigure_transmitter(TRANSMITTER *tx,int height);
+
+extern void tx_set_mode(TRANSMITTER* tx,int m);
+extern void tx_set_filter(TRANSMITTER *tx,int low,int high);
+extern void tx_set_pre_emphasize(TRANSMITTER *tx,int state);
+
+extern void add_mic_sample(TRANSMITTER *tx,short mic_sample);
+
+extern void transmitter_save_state(TRANSMITTER *tx);
+#endif
diff --git a/tx_menu.c b/tx_menu.c
new file mode 100644 (file)
index 0000000..e6bdfd3
--- /dev/null
+++ b/tx_menu.c
@@ -0,0 +1,223 @@
+/*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "audio.h"
+#include "new_menu.h"
+#include "radio.h"
+#include "sliders.h"
+#include "transmitter.h"
+
+static GtkWidget *parent_window=NULL;
+
+static GtkWidget *dialog=NULL;
+
+static GtkWidget *last_filter;
+
+static GtkWidget *linein_b;
+static GtkWidget *micboost_b;
+
+static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  if(dialog!=NULL) {
+    gtk_widget_destroy(dialog);
+    dialog=NULL;
+    sub_menu=NULL;
+  }
+  return TRUE;
+}
+
+static void tx_spin_low_cb (GtkWidget *widget, gpointer data) {
+  tx_filter_low=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
+  tx_set_filter(transmitter,tx_filter_low,tx_filter_high);
+}
+
+static void tx_spin_high_cb (GtkWidget *widget, gpointer data) {
+  tx_filter_high=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
+  tx_set_filter(transmitter,tx_filter_low,tx_filter_high);
+}
+
+static void micboost_cb(GtkWidget *widget, gpointer data) {
+  mic_boost=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+}
+
+static void linein_cb(GtkWidget *widget, gpointer data) {
+  mic_linein=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+  g_idle_add(linein_changed,NULL);
+}
+
+static void local_microphone_cb(GtkWidget *widget, gpointer data) {
+  if(gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+    if(audio_open_input()==0) {
+      transmitter->local_microphone=1;
+      gtk_widget_hide(linein_b);
+      gtk_widget_hide(micboost_b);
+    } else {
+      transmitter->local_microphone=0;
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
+      gtk_widget_show(linein_b);
+      gtk_widget_show(micboost_b);
+    }
+  } else {
+    if(transmitter->local_microphone) {
+      transmitter->local_microphone=0;
+      audio_close_input();
+      gtk_widget_show(linein_b);
+      gtk_widget_show(micboost_b);
+    }
+  }
+}
+
+static void local_input_changed_cb(GtkWidget *widget, gpointer data) {
+  transmitter->input_device=(int)(long)data;
+  if(transmitter->local_microphone) {
+    audio_close_input();
+    if(audio_open_input()==0) {
+      transmitter->local_microphone=1;
+    } else {
+      transmitter->local_microphone=0;
+    }
+  }
+}
+
+static gboolean emp_cb (GtkWidget *widget, gpointer data) {
+  pre_emphasize=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+  tx_set_pre_emphasize(transmitter,pre_emphasize);
+}
+
+void tx_menu(GtkWidget *parent) {
+  GtkWidget *b;
+  int i;
+
+  parent_window=parent;
+
+  dialog=gtk_dialog_new();
+  gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
+  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+
+  GdkRGBA color;
+  color.red = 1.0;
+  color.green = 1.0;
+  color.blue = 1.0;
+  color.alpha = 1.0;
+  gtk_widget_override_background_color(dialog,GTK_STATE_FLAG_NORMAL,&color);
+
+  GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+
+  GtkWidget *grid=gtk_grid_new();
+
+  gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+  gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
+  gtk_grid_set_column_spacing (GTK_GRID(grid),5);
+  gtk_grid_set_row_spacing (GTK_GRID(grid),5);
+
+  int row=0;
+  int col=0;
+
+  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,col,row,1,1);
+
+  col++;
+
+  GtkWidget *label=gtk_label_new("Transmit");
+  gtk_grid_attach(GTK_GRID(grid),label,col,row,1,1);
+
+  row++;
+  col=0;
+
+
+  label=gtk_label_new("Filter: ");
+  gtk_grid_attach(GTK_GRID(grid),label,col,row,1,1);
+
+  col++;
+
+  GtkWidget *tx_spin_low=gtk_spin_button_new_with_range(0.0,8000.0,1.0);
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON(tx_spin_low),(double)tx_filter_low);
+  gtk_grid_attach(GTK_GRID(grid),tx_spin_low,col,row,1,1);
+  g_signal_connect(tx_spin_low,"value-changed",G_CALLBACK(tx_spin_low_cb),NULL);
+
+  col++;
+
+  GtkWidget *tx_spin_high=gtk_spin_button_new_with_range(0.0,8000.0,1.0);
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON(tx_spin_high),(double)tx_filter_high);
+  gtk_grid_attach(GTK_GRID(grid),tx_spin_high,col,row,1,1);
+  g_signal_connect(tx_spin_high,"value-changed",G_CALLBACK(tx_spin_high_cb),NULL);
+
+  row++;
+  col=0;
+
+
+  if(protocol==ORIGINAL_PROTOCOL || protocol==NEW_PROTOCOL) {
+    linein_b=gtk_check_button_new_with_label("Mic Line In (ACC connector)");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (linein_b), mic_linein);
+    gtk_grid_attach(GTK_GRID(grid),linein_b,col,++row,3,1);
+    g_signal_connect(linein_b,"toggled",G_CALLBACK(linein_cb),NULL);
+
+    micboost_b=gtk_check_button_new_with_label("Mic Boost (radio only)");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (micboost_b), mic_boost);
+    gtk_grid_attach(GTK_GRID(grid),micboost_b,col,++row,3,1);
+    g_signal_connect(micboost_b,"toggled",G_CALLBACK(micboost_cb),NULL);
+
+  }
+
+  if(n_input_devices>0) {
+    GtkWidget *local_microphone_b=gtk_check_button_new_with_label("Local Microphone Input");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (local_microphone_b), transmitter->local_microphone);
+    gtk_widget_show(local_microphone_b);
+    gtk_grid_attach(GTK_GRID(grid),local_microphone_b,col,++row,3,1);
+    g_signal_connect(local_microphone_b,"toggled",G_CALLBACK(local_microphone_cb),NULL);
+
+    if(transmitter->input_device==-1) transmitter->input_device=0;
+
+    for(i=0;i<n_input_devices;i++) {
+      GtkWidget *input;
+      if(i==0) {
+        input=gtk_radio_button_new_with_label(NULL,input_devices[i]);
+      } else {
+        input=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(input),input_devices[i]);
+      }
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (input), transmitter->input_device==i);
+      gtk_widget_show(input);
+      gtk_grid_attach(GTK_GRID(grid),input,col,++row,3,1);
+      g_signal_connect(input,"pressed",G_CALLBACK(local_input_changed_cb),(gpointer *)i);
+    }
+  }
+
+  row++;
+  col=0;
+
+  GtkWidget *emp_b=gtk_check_button_new_with_label("FM TX Pre-emphasize before limiting");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (emp_b), pre_emphasize);
+  gtk_widget_show(emp_b);
+  gtk_grid_attach(GTK_GRID(grid),emp_b,col,row,3,1);
+  g_signal_connect(emp_b,"toggled",G_CALLBACK(emp_cb),NULL);
+
+  gtk_container_add(GTK_CONTAINER(content),grid);
+
+  sub_menu=dialog;
+
+  gtk_widget_show_all(dialog);
+
+  if(transmitter->local_microphone && (protocol==ORIGINAL_PROTOCOL || protocol==NEW_PROTOCOL)) {
+    gtk_widget_hide(linein_b);
+    gtk_widget_hide(micboost_b);
+  }
+
+}
diff --git a/tx_menu.h b/tx_menu.h
new file mode 100644 (file)
index 0000000..40408c6
--- /dev/null
+++ b/tx_menu.h
@@ -0,0 +1,18 @@
+/*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+void tx_menu(GtkWidget *parent);
diff --git a/tx_panadapter.c b/tx_panadapter.c
new file mode 100644 (file)
index 0000000..0ec9fcf
--- /dev/null
@@ -0,0 +1,420 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <math.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <semaphore.h>
+#include "agc.h"
+#include "band.h"
+#include "channel.h"
+#include "discovered.h"
+#include "radio.h"
+#include "receiver.h"
+#include "transmitter.h"
+#include "tx_panadapter.h"
+#include "vfo.h"
+#include "mode.h"
+#ifdef FREEDV
+#include "freedv.h"
+#endif
+#include "gpio.h"
+
+
+static gint last_x;
+static gboolean has_moved=FALSE;
+static gboolean pressed=FALSE;
+
+static gfloat hz_per_pixel;
+static gfloat filter_left;
+static gfloat filter_right;
+
+
+/* Create a new surface of the appropriate size to store our scribbles */
+static gboolean
+panadapter_configure_event_cb (GtkWidget         *widget,
+            GdkEventConfigure *event,
+            gpointer           data)
+{
+  TRANSMITTER *tx=(TRANSMITTER *)data;
+  int display_width=gtk_widget_get_allocated_width (tx->panadapter);
+  int display_height=gtk_widget_get_allocated_height (tx->panadapter);
+
+  if (tx->panadapter_surface)
+    cairo_surface_destroy (tx->panadapter_surface);
+
+  tx->panadapter_surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget),
+                                       CAIRO_CONTENT_COLOR,
+                                       display_width,
+                                       display_height);
+
+  cairo_t *cr=cairo_create(tx->panadapter_surface);
+  cairo_set_source_rgb(cr, 0, 0, 0);
+  cairo_paint(cr);
+  cairo_destroy(cr);
+  return TRUE;
+}
+
+/* Redraw the screen from the surface. Note that the ::draw
+ * signal receives a ready-to-be-used cairo_t that is already
+ * clipped to only draw the exposed areas of the widget
+ */
+static gboolean
+panadapter_draw_cb (GtkWidget *widget,
+ cairo_t   *cr,
+ gpointer   data)
+{
+  TRANSMITTER *tx=(TRANSMITTER *)data;
+  if(tx->panadapter_surface) {
+    cairo_set_source_surface (cr, tx->panadapter_surface, 0, 0);
+    cairo_paint (cr);
+  }
+  return TRUE;
+}
+
+static gboolean
+panadapter_button_press_event_cb (GtkWidget      *widget,
+               GdkEventButton *event,
+               gpointer        data)
+{
+  int x=(int)event->x;
+  if (event->button == 1) {
+    last_x=(int)event->x;
+    has_moved=FALSE;
+    pressed=TRUE;
+  }
+  return TRUE;
+}
+
+static gboolean
+panadapter_button_release_event_cb (GtkWidget      *widget,
+               GdkEventButton *event,
+               gpointer        data)
+{
+  TRANSMITTER *tx=(TRANSMITTER *)data;
+  int display_width=gtk_widget_get_allocated_width (tx->panadapter);
+  int display_height=gtk_widget_get_allocated_height (tx->panadapter);
+
+  if(pressed) {
+    int x=(int)event->x;
+    if (event->button == 1) {
+      if(has_moved) {
+        // drag
+        vfo_move((long long)((float)(x-last_x)*hz_per_pixel));
+      } else {
+        // move to this frequency
+        vfo_move_to((long long)((float)(x-(display_width/2))*hz_per_pixel));
+      }
+      last_x=x;
+      pressed=FALSE;
+    }
+  }
+  return TRUE;
+}
+
+static gboolean
+panadapter_motion_notify_event_cb (GtkWidget      *widget,
+                GdkEventMotion *event,
+                gpointer        data)
+{
+  int x, y;
+  GdkModifierType state;
+  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;
+  }
+
+  return TRUE;
+}
+
+static gboolean
+panadapter_scroll_event_cb (GtkWidget      *widget,
+               GdkEventScroll *event,
+               gpointer        data)
+{
+  if(event->direction==GDK_SCROLL_UP) {
+    vfo_move(step);
+  } else {
+    vfo_move(-step);
+  }
+}
+
+void tx_panadapter_update(TRANSMITTER *tx) {
+  int i;
+  int result;
+  float *samples;
+  float saved_max;
+  float saved_min;
+  gfloat saved_hz_per_pixel;
+  cairo_text_extents_t extents;
+
+  int display_width=gtk_widget_get_allocated_width (tx->panadapter);
+  int display_height=gtk_widget_get_allocated_height (tx->panadapter);
+
+  samples=tx->pixel_samples;
+  //hz_per_pixel=(double)tx->output_rate/(double)display_width;
+  hz_per_pixel=48000.0/(double)display_width;
+
+  //clear_panadater_surface();
+  cairo_t *cr;
+  cr = cairo_create (tx->panadapter_surface);
+  cairo_set_source_rgb (cr, 0, 0, 0);
+  cairo_paint (cr);
+
+  // filter
+  cairo_set_source_rgb (cr, 0.25, 0.25, 0.25);
+  filter_left=(double)display_width/2.0+((double)tx->filter_low/hz_per_pixel);
+  filter_right=(double)display_width/2.0+((double)tx->filter_high/hz_per_pixel);
+  cairo_rectangle(cr, filter_left, 0.0, filter_right-filter_left, (double)display_height);
+  cairo_fill(cr);
+
+  // plot the levels
+  int V = (int)(tx->panadapter_high - tx->panadapter_low);
+  int numSteps = V / 20;
+  for (i = 1; i < numSteps; i++) {
+    int num = tx->panadapter_high - i * 20;
+    int y = (int)floor((tx->panadapter_high - num) * display_height / V);
+    cairo_set_source_rgb (cr, 0, 1, 1);
+    cairo_set_line_width(cr, 1.0);
+    cairo_move_to(cr,0.0,(double)y);
+    cairo_line_to(cr,(double)display_width,(double)y);
+
+    cairo_set_source_rgb (cr, 0, 1, 1);
+    cairo_select_font_face(cr, "FreeMono", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
+    cairo_set_font_size(cr, 12);
+    char v[32];
+    sprintf(v,"%d dBm",num);
+    cairo_move_to(cr, 1, (double)y);  
+    cairo_show_text(cr, v);
+    cairo_stroke(cr);
+  }
+
+  // plot frequency markers
+  long long f;
+  long long divisor=20000;
+  long long half=24000LL; //(long long)(tx->output_rate/2);
+  long long frequency;
+  if(split) {
+    frequency=vfo[VFO_B].frequency+vfo[VFO_B].offset;
+  } else {
+    frequency=vfo[VFO_A].frequency+vfo[VFO_A].offset;
+  }
+  divisor=5000LL;
+/*
+  switch(tx->output_rate) {
+    case 48000:
+      divisor=5000L;
+      break;
+    case 96000:
+    case 100000:
+      divisor=10000L;
+      break;
+    case 192000:
+      divisor=20000L;
+      break;
+    case 384000:
+      divisor=25000L;
+      break;
+    case 768000:
+      divisor=50000L;
+      break;
+    case 1048576:
+    case 1536000:
+    case 2097152:
+      divisor=100000L;
+      break;
+  }
+*/
+//fprintf(stderr,"tx_panadapter_update: frequency=%lld divisor=%lld split=%d\n",frequency,divisor,split);
+  for(i=0;i<display_width;i++) {
+    f = frequency - half + (long) (hz_per_pixel * i);
+    if (f > 0) {
+      if ((f % divisor) < (long) hz_per_pixel) {
+        cairo_set_source_rgb (cr, 0, 1, 1);
+        cairo_set_line_width(cr, 1.0);
+        cairo_move_to(cr,(double)i,10.0);
+        cairo_line_to(cr,(double)i,(double)display_height);
+
+        cairo_set_source_rgb (cr, 0, 1, 1);
+        cairo_select_font_face(cr, "FreeMono",
+                            CAIRO_FONT_SLANT_NORMAL,
+                            CAIRO_FONT_WEIGHT_BOLD);
+        cairo_set_font_size(cr, 12);
+        char v[32];
+        sprintf(v,"%0lld.%03lld",f/1000000,(f%1000000)/1000);
+        //cairo_move_to(cr, (double)i, (double)(display_height-10));  
+        cairo_text_extents(cr, v, &extents);
+        cairo_move_to(cr, (double)i-(extents.width/2.0), 10.0);  
+        cairo_show_text(cr, v);
+      }
+    }
+  }
+  cairo_stroke(cr);
+
+  // 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;
+  }
+  BAND *band=band_get_band(b);
+  if(band->frequencyMin!=0LL) {
+    cairo_set_source_rgb (cr, 1, 0, 0);
+    cairo_set_line_width(cr, 2.0);
+    if((min_display<band->frequencyMin)&&(max_display>band->frequencyMin)) {
+      i=(band->frequencyMin-min_display)/(long long)hz_per_pixel;
+      cairo_move_to(cr,(double)i,0.0);
+      cairo_line_to(cr,(double)i,(double)display_height);
+      cairo_stroke(cr);
+    }
+    if((min_display<band->frequencyMax)&&(max_display>band->frequencyMax)) {
+      i=(band->frequencyMax-min_display)/(long long)hz_per_pixel;
+      cairo_move_to(cr,(double)i,0.0);
+      cairo_line_to(cr,(double)i,(double)display_height);
+      cairo_stroke(cr);
+    }
+  }
+            
+  // cursor
+  cairo_set_source_rgb (cr, 1, 0, 0);
+  cairo_set_line_width(cr, 1.0);
+//fprintf(stderr,"cursor: x=%f\n",(double)(display_width/2.0)+(vfo[tx->id].offset/hz_per_pixel));
+  cairo_move_to(cr,(double)(display_width/2.0)+(vfo[tx->id].offset/hz_per_pixel),0.0);
+  cairo_line_to(cr,(double)(display_width/2.0)+(vfo[tx->id].offset/hz_per_pixel),(double)display_height);
+  cairo_stroke(cr);
+
+  // signal
+  double s1,s2;
+  samples[0]=-200.0;
+  samples[display_width-1]=-200.0;
+
+  int offset=0;
+
+  if(protocol==NEW_PROTOCOL) {
+    offset=1200;
+  }
+  s1=(double)samples[0+offset]+(double)get_attenuation();
+  s1 = floor((tx->panadapter_high - s1)
+                        * (double) display_height
+                        / (tx->panadapter_high - tx->panadapter_low));
+  cairo_move_to(cr, 0.0, s1);
+  for(i=1;i<display_width;i++) {
+    s2=(double)samples[i+offset]+(double)get_attenuation();
+    s2 = floor((tx->panadapter_high - s2)
+                            * (double) display_height
+                            / (tx->panadapter_high - tx->panadapter_low));
+    cairo_line_to(cr, (double)i, s2);
+  }
+
+  if(display_filled) {
+    cairo_close_path (cr);
+    cairo_set_source_rgba(cr, 1, 1, 1,0.5);
+    cairo_fill_preserve (cr);
+  }
+  cairo_set_source_rgb(cr, 1, 1, 1);
+  cairo_set_line_width(cr, 1.0);
+  cairo_stroke(cr);
+
+#ifdef FREEDV
+  int mode;
+  mode=tx->mode;
+  if(mode==modeFREEDV) {
+    cairo_set_source_rgb(cr, 1, 0, 0);
+    cairo_set_font_size(cr, 16);
+    cairo_text_extents(cr, freedv_text_data, &extents);
+    cairo_move_to(cr, (double)display_width/2.0-(extents.width/2.0),(double)display_height-2.0);
+    cairo_show_text(cr, freedv_text_data);
+  }
+#endif
+
+#ifdef GPIO
+  cairo_set_source_rgb(cr,1,1,0);
+  cairo_set_font_size(cr,12);
+  if(ENABLE_E1_ENCODER) {
+    cairo_move_to(cr, display_width-100,30);
+    cairo_show_text(cr, encoder_string[e1_encoder_action]);
+  }
+
+  if(ENABLE_E2_ENCODER) {
+    cairo_move_to(cr, display_width-100,50);
+    cairo_show_text(cr, encoder_string[e2_encoder_action]);
+  }
+
+  if(ENABLE_E3_ENCODER) {
+    cairo_move_to(cr, display_width-100,70);
+    cairo_show_text(cr, encoder_string[e3_encoder_action]);
+  }
+#endif
+
+  cairo_destroy (cr);
+  gtk_widget_queue_draw (tx->panadapter);
+
+}
+
+void tx_panadapter_init(TRANSMITTER *tx, int width,int height) {
+
+  int display_width=width;
+  int display_height=height;
+
+  tx->panadapter_surface=NULL;
+  tx->panadapter=gtk_drawing_area_new ();
+  gtk_widget_set_size_request (tx->panadapter, width, height);
+
+  /* Signals used to handle the backing surface */
+  g_signal_connect (tx->panadapter, "draw",
+            G_CALLBACK (panadapter_draw_cb), tx);
+  g_signal_connect (tx->panadapter,"configure-event",
+            G_CALLBACK (panadapter_configure_event_cb), tx);
+
+  /* Event signals */
+  g_signal_connect (tx->panadapter, "motion-notify-event",
+            G_CALLBACK (panadapter_motion_notify_event_cb), tx);
+  g_signal_connect (tx->panadapter, "button-press-event",
+            G_CALLBACK (panadapter_button_press_event_cb), tx);
+  g_signal_connect (tx->panadapter, "button-release-event",
+            G_CALLBACK (panadapter_button_release_event_cb), tx);
+  g_signal_connect(tx->panadapter,"scroll_event",
+            G_CALLBACK(panadapter_scroll_event_cb),tx);
+
+  /* Ask to receive events the drawing area doesn't normally
+   * subscribe to. In particular, we need to ask for the
+   * button press and motion notify events that want to handle.
+   */
+  gtk_widget_set_events (tx->panadapter, gtk_widget_get_events (tx->panadapter)
+                     | GDK_BUTTON_PRESS_MASK
+                     | GDK_BUTTON_RELEASE_MASK
+                     | GDK_BUTTON1_MOTION_MASK
+                     | GDK_SCROLL_MASK
+                     | GDK_POINTER_MOTION_MASK
+                     | GDK_POINTER_MOTION_HINT_MASK);
+
+}
diff --git a/tx_panadapter.h b/tx_panadapter.h
new file mode 100644 (file)
index 0000000..dfa8071
--- /dev/null
@@ -0,0 +1,28 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#ifndef _PANADAPTER_H
+#define _PANADAPTER_H
+
+void tx_panadapter_update(TRANSMITTER *tx);
+
+void tx_panadapter_init(TRANSMITTER *tx,int width,int height);
+
+
+#endif
index ef4a5ed6e9832c9aad4153b667f792dbfdbce1cd..444a7ab5efc2d449e4f5ae0aacdd83ec73749f53 100644 (file)
--- a/update.h
+++ b/update.h
@@ -1,4 +1,4 @@
-char new_version[];
+extern char new_version[];
 
 extern int check_update();
 extern int load_update();
diff --git a/vfo.c b/vfo.c
index 5e4ffda86747d609bf682a88fee0d926ae370639..5bc739744ff0a6045eb3b8a61f713be41734714f 100644 (file)
--- a/vfo.c
+++ b/vfo.c
 #include "band.h"
 #include "frequency.h"
 #include "new_protocol.h"
+#include "property.h"
 #include "radio.h"
+#include "receiver.h"
 #include "vfo.h"
 #include "channel.h"
 #include "toolbar.h"
 #include "wdsp.h"
-#include "wdsp_init.h"
 #include "new_menu.h"
+#include "rigctl.h"
 
 static GtkWidget *parent_window;
 static int my_width;
 static int my_height;
 
-static GtkWidget *vfo;
+static GtkWidget *vfo_panel;
 static cairo_surface_t *vfo_surface = NULL;
 
 int steps[]={1,10,25,50,100,250,500,1000,2500,5000,6250,9000,10000,12500,15000,20000,25000,30000,50000,100000,0};
@@ -62,57 +64,399 @@ char *step_labels[]={"1Hz","10Hz","25Hz","50Hz","100Hz","250Hz","500Hz","1kHz","
 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->frequency=vfo[0].frequency;
+  entry->mode=vfo[0].mode;
+  entry->filter=vfo[0].filter;
+}
+
+void vfo_save_state() {
+  int i;
+  char name[80];
+  char value[80];
+
+  vfo_save_bandstack();
+
+  for(i=0;i<MAX_VFOS;i++) {
+    sprintf(name,"vfo.%d.band",i);
+    sprintf(value,"%d",vfo[i].band);
+    setProperty(name,value);
+    sprintf(name,"vfo.%d.frequency",i);
+    sprintf(value,"%lld",vfo[i].frequency);
+    setProperty(name,value);
+    sprintf(name,"vfo.%d.ctun",i);
+    sprintf(value,"%d",vfo[i].ctun);
+    setProperty(name,value);
+    sprintf(name,"vfo.%d.rit",i);
+    sprintf(value,"%lld",vfo[i].rit);
+    setProperty(name,value);
+    sprintf(name,"vfo.%d.lo",i);
+    sprintf(value,"%lld",vfo[i].lo);
+    setProperty(name,value);
+    sprintf(name,"vfo.%d.ctun_frequency",i);
+    sprintf(value,"%lld",vfo[i].ctun_frequency);
+    setProperty(name,value);
+    sprintf(name,"vfo.%d.offset",i);
+    sprintf(value,"%lld",vfo[i].offset);
+    setProperty(name,value);
+    sprintf(name,"vfo.%d.mode",i);
+    sprintf(value,"%d",vfo[i].mode);
+    setProperty(name,value);
+    sprintf(name,"vfo.%d.filter",i);
+    sprintf(value,"%d",vfo[i].filter);
+    setProperty(name,value);
+  }
+}
+
+void vfo_restore_state() {
+  int i;
+  char name[80];
+  char *value;
+
+  for(i=0;i<MAX_VFOS;i++) {
+
+    vfo[i].band=band20;
+    vfo[i].bandstack=0;
+    vfo[i].frequency=14010000;
+    vfo[i].mode=modeCWU;
+    vfo[i].filter=6;
+    vfo[i].lo=0;
+    vfo[i].offset=0;
+    vfo[i].rit=0;
+    vfo[i].ctun=0;
+
+    sprintf(name,"vfo.%d.band",i);
+    value=getProperty(name);
+    if(value) vfo[i].band=atoi(value);
+    sprintf(name,"vfo.%d.frequency",i);
+    value=getProperty(name);
+    if(value) vfo[i].frequency=atoll(value);
+    sprintf(name,"vfo.%d.ctun",i);
+    value=getProperty(name);
+    if(value) vfo[i].ctun=atoi(value);
+    sprintf(name,"vfo.%d.ctun_frequency",i);
+    value=getProperty(name);
+    if(value) vfo[i].ctun_frequency=atoll(value);
+    sprintf(name,"vfo.%d.rit",i);
+    value=getProperty(name);
+    if(value) vfo[i].rit=atoll(value);
+    sprintf(name,"vfo.%d.lo",i);
+    value=getProperty(name);
+    if(value) vfo[i].lo=atoll(value);
+    sprintf(name,"vfo.%d.offset",i);
+    value=getProperty(name);
+    if(value) vfo[i].offset=atoll(value);
+    sprintf(name,"vfo.%d.mode",i);
+    value=getProperty(name);
+    if(value) vfo[i].mode=atoi(value);
+    sprintf(name,"vfo.%d.filter",i);
+    value=getProperty(name);
+    if(value) vfo[i].filter=atoi(value);
+
+  }
+}
+
+void vfo_band_changed(int b) {
+  BANDSTACK *bandstack;
+
+  int id=active_receiver->id;
+
+  if(id==0) {
+    vfo_save_bandstack();
+  }
+  if(b==vfo[id].band) {
+    // same band selected - step to the next band stack
+    bandstack=bandstack_get_bandstack(b);
+    vfo[id].bandstack++;
+    if(vfo[id].bandstack>=bandstack->entries) {
+      vfo[id].bandstack=0;
+    }
+  } else {
+    // new band - get band stack entry
+    bandstack=bandstack_get_bandstack(b);
+    vfo[id].bandstack=bandstack->current_entry;
+  }
+
+  BAND *band=band_get_band(b);
+  BANDSTACK_ENTRY *entry=&bandstack->entry[vfo[id].bandstack];
+  vfo[id].band=b;
+  vfo[id].frequency=entry->frequency;
+  vfo[id].mode=entry->mode;
+  vfo[id].filter=entry->filter;
+  vfo[id].lo=band->frequencyLO;
+
+  switch(id) {
+    case 0:
+      bandstack->current_entry=vfo[id].bandstack;
+      receiver_vfo_changed(receiver[id]);
+      BAND *band=band_get_band(vfo[id].band);
+      set_alex_rx_antenna(band->alexRxAntenna);
+      set_alex_tx_antenna(band->alexTxAntenna);
+      set_alex_attenuation(band->alexAttenuation);
+      receiver_vfo_changed(receiver[0]);
+      break;
+   case 1:
+      if(receivers==2) {
+        receiver_vfo_changed(receiver[1]);
+      }
+      break;
+  }
+
+  if(split) {
+    tx_set_mode(transmitter,vfo[VFO_B].mode);
+  } else {
+    tx_set_mode(transmitter,vfo[VFO_A].mode);
+  }
+  calcDriveLevel();
+  calcTuneDriveLevel();
+  vfo_update(NULL);
+}
+
+void vfo_bandstack_changed(int b) {
+  int id=active_receiver->id;
+  if(id==0) {
+    vfo_save_bandstack();
+  }
+  vfo[id].bandstack=b;
+
+  BANDSTACK *bandstack=bandstack_get_bandstack(vfo[id].band);
+  BANDSTACK_ENTRY *entry=&bandstack->entry[vfo[id].bandstack];
+  vfo[id].frequency=entry->frequency;
+  vfo[id].mode=entry->mode;
+  vfo[id].filter=entry->filter;
+
+  switch(id) {
+    case 0:
+      bandstack->current_entry=vfo[id].bandstack;
+      receiver_vfo_changed(receiver[id]);
+      BAND *band=band_get_band(vfo[id].band);
+      set_alex_rx_antenna(band->alexRxAntenna);
+      set_alex_tx_antenna(band->alexTxAntenna);
+      set_alex_attenuation(band->alexAttenuation);
+      receiver_vfo_changed(receiver[0]);
+      break;
+   case 1:
+      if(receivers==2) {
+        receiver_vfo_changed(receiver[1]);
+      }
+      break;
+  }
+
+  if(split) {
+    tx_set_mode(transmitter,vfo[VFO_B].mode);
+  } else {
+    tx_set_mode(transmitter,vfo[VFO_A].mode);
+  }
+  calcDriveLevel();
+  calcTuneDriveLevel();
+  vfo_update(NULL);
+
+}
+
+void vfo_mode_changed(int m) {
+  int id=active_receiver->id;
+  vfo[id].mode=m;
+  switch(id) {
+    case 0:
+      receiver_mode_changed(receiver[0]);
+      receiver_filter_changed(receiver[0]);
+      break;
+    case 1:
+      if(receivers==2) {
+        receiver_mode_changed(receiver[1]);
+        receiver_filter_changed(receiver[1]);
+      }
+      break;
+  }
+  if(split) {
+    tx_set_mode(transmitter,vfo[VFO_B].mode);
+  } else {
+    tx_set_mode(transmitter,vfo[VFO_A].mode);
+  }
+
+  vfo_update(NULL);
+}
+
+void vfo_filter_changed(int f) {
+  int id=active_receiver->id;
+  vfo[id].filter=f;
+  switch(id) {
+    case 0:
+      receiver_filter_changed(receiver[0]);
+      break;
+    case 1:
+      if(receivers==2) {
+        receiver_filter_changed(receiver[1]);
+      }
+      break;
+  }
+
+  vfo_update(NULL);
+}
+
+void vfo_a_to_b() {
+  vfo[VFO_B].band=vfo[VFO_A].band;
+  vfo[VFO_B].bandstack=vfo[VFO_A].bandstack;
+  vfo[VFO_B].frequency=vfo[VFO_A].frequency;
+  vfo[VFO_B].mode=vfo[VFO_A].mode;
+  vfo[VFO_B].filter=vfo[VFO_A].filter;
+  vfo[VFO_B].filter=vfo[VFO_A].filter;
+  vfo[VFO_B].lo=vfo[VFO_A].lo;
+  vfo[VFO_B].offset=vfo[VFO_A].offset;
+  vfo[VFO_B].rit=vfo[VFO_A].rit;
+
+  if(receivers==2) {
+    receiver_vfo_changed(receiver[1]);
+  }
+  if(split) {
+    tx_set_mode(transmitter,vfo[VFO_B].mode);
+  }
+  vfo_update(NULL);
+}
+
+void vfo_b_to_a() {
+  vfo[VFO_A].band=vfo[VFO_B].band;
+  vfo[VFO_A].bandstack=vfo[VFO_B].bandstack;
+  vfo[VFO_A].frequency=vfo[VFO_B].frequency;
+  vfo[VFO_A].mode=vfo[VFO_B].mode;
+  vfo[VFO_A].filter=vfo[VFO_B].filter;
+  vfo[VFO_A].lo=vfo[VFO_B].lo;
+  vfo[VFO_A].offset=vfo[VFO_B].offset;
+  vfo[VFO_A].rit=vfo[VFO_B].rit;
+  receiver_vfo_changed(receiver[0]);
+  if(!split) {
+    tx_set_mode(transmitter,vfo[VFO_B].mode);
+  }
+  vfo_update(NULL);
+}
+
+void vfo_a_swap_b() {
+  int temp_band;
+  int temp_bandstack;
+  long long temp_frequency;
+  int temp_mode;
+  int temp_filter;
+  int temp_lo;
+  int temp_offset;
+  int temp_rit;
+
+  temp_band=vfo[VFO_A].band;
+  temp_bandstack=vfo[VFO_A].bandstack;
+  temp_frequency=vfo[VFO_A].frequency;
+  temp_mode=vfo[VFO_A].mode;
+  temp_filter=vfo[VFO_A].filter;
+  temp_lo=vfo[VFO_A].lo;
+  temp_offset=vfo[VFO_A].offset;
+  temp_rit=vfo[VFO_A].rit;
+
+  vfo[VFO_A].band=vfo[VFO_B].band;
+  vfo[VFO_A].bandstack=vfo[VFO_B].bandstack;
+  vfo[VFO_A].frequency=vfo[VFO_B].frequency;
+  vfo[VFO_A].mode=vfo[VFO_B].mode;
+  vfo[VFO_A].filter=vfo[VFO_B].filter;
+  vfo[VFO_A].lo=vfo[VFO_B].lo;
+  vfo[VFO_A].offset=vfo[VFO_B].offset;
+  vfo[VFO_A].rit=vfo[VFO_B].rit;
+
+  vfo[VFO_B].band=temp_band;
+  vfo[VFO_B].bandstack=temp_bandstack;
+  vfo[VFO_B].frequency=temp_frequency;
+  vfo[VFO_B].mode=temp_mode;
+  vfo[VFO_B].filter=temp_filter;
+  vfo[VFO_B].lo=temp_lo;
+  vfo[VFO_B].offset=temp_offset;
+  vfo[VFO_B].rit=temp_rit;
+
+  receiver_vfo_changed(receiver[0]);
+  if(receivers==2) {
+    receiver_vfo_changed(receiver[1]);
+  }
+  if(split) {
+    tx_set_mode(transmitter,vfo[VFO_B].mode);
+  } else {
+    tx_set_mode(transmitter,vfo[VFO_A].mode);
+  }
+  vfo_update(NULL);
+}
+
 void vfo_step(int steps) {
+  int id=active_receiver->id;
   if(!locked) {
+    if(vfo[id].ctun) {
+      vfo[id].ctun_frequency=vfo[id].ctun_frequency+(steps*step);
+    } else {
+      vfo[id].frequency=vfo[id].frequency+(steps*step);
+    }
+    receiver_frequency_changed(active_receiver);
+#ifdef INCLUDED
     BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
-    //entry->frequencyA=entry->frequencyA+(steps*step);
-    //setFrequency(entry->frequencyA);
-    setFrequency(entry->frequencyA+(steps*step));
+    setFrequency(active_receiver->frequency+(steps*step));
+#endif
     vfo_update(NULL);
   }
 }
 
-void vfo_move(int hz) {
+void vfo_move(long long hz) {
+  int id=active_receiver->id;
   if(!locked) {
-    BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
-    //entry->frequencyA=(entry->frequencyA+hz)/step*step;
-    //setFrequency(entry->frequencyA);
-    
+    switch(protocol) {
 #ifdef LIMESDR
-    if(protocol==LIMESDR_PROTOCOL)
-      setFrequency((entry->frequencyA+ddsOffset-hz)/step*step);
-    else 
+      case LIMESDR_PROTOCOL:
+        break;
 #endif
-      if(ctun) {
-        setFrequency((entry->frequencyA+ddsOffset-hz)/step*step);
-      } else {
-        setFrequency((entry->frequencyA+ddsOffset+hz)/step*step);
-      }
+      default:
+        vfo[id].frequency=((vfo[id].frequency+hz)/step)*step;
+        break;
+    }
+    receiver_frequency_changed(active_receiver);
     vfo_update(NULL);
   }
 }
-void vfo_move_to(int hz) {
+void vfo_move_to(long long hz) {
+  int id=active_receiver->id;
   if(!locked) {
+    switch(protocol) {
+#ifdef LIMESDR
+      case LIMESDR_PROTOCOL:
+        break;
+#endif
+      default:
+        vfo[id].frequency=(vfo[id].frequency+hz)/step*step;
+        if(vfo[id].mode==modeCWL) {
+          vfo[id].frequency+=cw_keyer_sidetone_frequency;
+        } else if(vfo[id].mode==modeCWU) {
+          vfo[id].frequency-=cw_keyer_sidetone_frequency;
+        }
+        break;
+    }
+    receiver_vfo_changed(active_receiver);
+
+#ifdef INCLUDED
+
     BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
 
 #ifdef LIMESDR
     if(protocol==LIMESDR_PROTOCOL) {
-      setFrequency((entry->frequencyA+ddsOffset-hz)/step*step);
+      setFrequency((entry->frequency+active_receiver->dds_offset-hz)/step*step);
     } else {
 #endif
-      if(ctun) {
-        setFrequency((entry->frequencyA+hz)/step*step);
+      if(vfo[id].ctun) {
+        setFrequency((active_receiver->frequency+hz)/step*step);
       } else {
-        long f=(entry->frequencyA+ddsOffset+hz)/step*step;
-        if(mode==modeCWL) {
+        long long f=(active_receiver->frequency+active_receiver->dds_offset+hz)/step*step;
+        if(vfo[active_receiver->id].mode==modeCWL) {
           f+=cw_keyer_sidetone_frequency;
-        } else if(mode==modeCWU) {
+        } else if(vfo[active_receiver->id].mode==modeCWU) {
           f-=cw_keyer_sidetone_frequency;
         }
         setFrequency(f);
       }
 #ifdef LIMESDR
     }
+#endif
 #endif
     vfo_update(NULL);
   }
@@ -125,27 +469,10 @@ vfo_scroll_event_cb (GtkWidget      *widget,
 {
   int i;
   if(event->direction==GDK_SCROLL_UP) {
-    i=1;
-  } else {
-    i=-1;
-  }
-  if(event->x>(my_width/2)) {
-    if(event->x>((my_width/4)*3)) {
-      // rit
-      rit+=i;
-      if(rit>10000) {
-        rit=1000;
-      }
-      if(rit<-1000) {
-        rit=-1000;
-      }
-    } else {
-      // step
-    }
+    vfo_move(step);
   } else {
-    // frequency
+    vfo_move(-step);
   }
-  vfo_update(NULL);
 }
 
 
@@ -153,9 +480,6 @@ static gboolean vfo_configure_event_cb (GtkWidget         *widget,
             GdkEventConfigure *event,
             gpointer           data)
 {
-fprintf(stderr,"vfo_configure_event_cb: width=%d height=%d\n",
-                                       gtk_widget_get_allocated_width (widget),
-                                       gtk_widget_get_allocated_height (widget));
   if (vfo_surface)
     cairo_surface_destroy (vfo_surface);
 
@@ -170,10 +494,7 @@ fprintf(stderr,"vfo_configure_event_cb: width=%d height=%d\n",
   cairo_set_source_rgb (cr, 0, 0, 0);
   cairo_paint (cr);
   cairo_destroy(cr);
-
   g_idle_add(vfo_update,NULL);
-
-  /* We've handled the configure event, no need for further processing. */
   return TRUE;
 }
 
@@ -183,15 +504,16 @@ static gboolean vfo_draw_cb (GtkWidget *widget,
 {
   cairo_set_source_surface (cr, vfo_surface, 0, 0);
   cairo_paint (cr);
-
-  return FALSE;
+  return TRUE;
 }
 
 int vfo_update(void *data) {
-    BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
-    FILTER* band_filters=filters[entry->mode];
-    FILTER* band_filter=&band_filters[entry->filter];
+    
+    int id=active_receiver->id;
+    FILTER* band_filters=filters[vfo[id].mode];
+    FILTER* band_filter=&band_filters[vfo[id].filter];
     if(vfo_surface) {
+        char temp_text[32];
         cairo_t *cr;
         cr = cairo_create (vfo_surface);
         cairo_set_source_rgb (cr, 0, 0, 0);
@@ -204,18 +526,40 @@ int vfo_update(void *data) {
         char version[16];
         char text[128];
         if(radio->protocol==ORIGINAL_PROTOCOL) {
+          switch(radio->device) {
+#ifdef USBOZY
+            case DEVICE_OZY:
+              strcpy(version,"");
+              break;
+#endif
+            default:
+              sprintf(version,"%d.%d",
+                  radio->software_version/10,
+                  radio->software_version%10);
+              break;
+          }
+        } else {
             sprintf(version,"%d.%d",
                 radio->software_version/10,
                 radio->software_version%10);
-        } else {
-            sprintf(version,"%d.%d.%d",
-                radio->software_version/100,
-                (radio->software_version%100)/10,
-                radio->software_version%10);
         }
 
         switch(radio->protocol) {
             case ORIGINAL_PROTOCOL:
+              switch(radio->device) {
+#ifdef USBOZY
+                case DEVICE_OZY:
+                  sprintf(text,"%s", radio->name);
+                  break;
+#endif
+                default:
+                  sprintf(text,"%s %s %s",
+                    radio->name,
+                    version,
+                    inet_ntoa(radio->info.network.address.sin_addr));
+                  break;
+              }
+              break;
             case NEW_PROTOCOL:
               sprintf(text,"%s %s %s",
                     radio->name,
@@ -224,126 +568,185 @@ int vfo_update(void *data) {
               break;
 #ifdef LIMESDR
             case LIMESDR_PROTOCOL:
-              sprintf(text,"%s\n",
-                    radio->name);
+              sprintf(text,"%s", radio->name);
               break;
 #endif
         }
-        cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
-        cairo_set_font_size(cr, 10);
+        cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
+        cairo_set_font_size(cr, 12);
         cairo_move_to(cr, 5, 15);  
         cairo_show_text(cr, text);
 
-        long long f=entry->frequencyA+ddsOffset;
-        char sf[32];
-        sprintf(sf,"%0lld.%06lld MHz",f/(long long)1000000,f%(long long)1000000);
-        cairo_set_font_size(cr, 28);
-        if(isTransmitting()) {
+        //long long af=active_receiver->frequency+active_receiver->dds_offset;
+        long long af=vfo[0].frequency+vfo[0].offset;
+        sprintf(temp_text,"VFO A: %0lld.%06lld",af/(long long)1000000,af%(long long)1000000);
+        if(isTransmitting() && !split) {
             cairo_set_source_rgb(cr, 1, 0, 0);
         } else {
-            cairo_set_source_rgb(cr, 0, 1, 0);
+            if(active_receiver->id==0) {
+              cairo_set_source_rgb(cr, 0, 1, 0);
+            } else {
+              cairo_set_source_rgb(cr, 0, 0.65, 0);
+            }
         }
         cairo_move_to(cr, 5, 38);  
-        cairo_show_text(cr, sf);
-
-        cairo_set_font_size(cr, 12);
+        cairo_set_font_size(cr, 22); 
+        cairo_show_text(cr, temp_text);
 
-        if(rit==0) {
-            cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
+        //long long bf=frequencyB;
+        long long bf=vfo[1].frequency+vfo[1].offset;
+        sprintf(temp_text,"VFO B: %0lld.%06lld",bf/(long long)1000000,bf%(long long)1000000);
+        if(isTransmitting() && split) {
+            cairo_set_source_rgb(cr, 1, 0, 0);
         } else {
-            cairo_set_source_rgb(cr, 0, 1, 0);
+            if(active_receiver->id==1) {
+              cairo_set_source_rgb(cr, 0, 1, 0);
+            } else {
+              cairo_set_source_rgb(cr, 0, 0.65, 0);
+            }
         }
-        sprintf(sf,"RIT: %d Hz",rit);
-        cairo_move_to(cr, (my_width/4)*3, 38);  
-        cairo_show_text(cr, sf);
+        cairo_move_to(cr, 260, 38);  
+        cairo_show_text(cr, temp_text);
 
-        cairo_set_source_rgb(cr, 0, 1, 0);
+        cairo_set_font_size(cr, 12);
 
-        int s=0;
-        while(steps[s]!=step && steps[s]!=0) {
-          s++;
+        if(vfo[id].rit==0) {
+            cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
+        } else {
+            cairo_set_source_rgb(cr, 1, 1, 0);
         }
-        sprintf(sf,"Step %s",step_labels[s]);
-        cairo_move_to(cr, my_width/2, 15);  
-        cairo_show_text(cr, sf);
-
-        cairo_move_to(cr, (my_width/4)*3, 15);  
-        cairo_show_text(cr, getFrequencyInfo(f));
+        sprintf(temp_text,"RIT: %d Hz",vfo[id].rit);
+        cairo_move_to(cr, 5, 50);  
+        cairo_set_font_size(cr, 12);
+        cairo_show_text(cr, temp_text);
 
+        cairo_move_to(cr, 210, 15);  
         if(locked) {
-            cairo_set_source_rgb(cr, 1, 0, 0);
-            cairo_move_to(cr, 10, 50);  
-            cairo_show_text(cr, "Locked");
-        }
-
-        if(function) {
-            cairo_set_source_rgb(cr, 1, 0.5, 0);
-            cairo_move_to(cr, 70, 50);  
-            cairo_show_text(cr, "Function");
+          cairo_set_source_rgb(cr, 1, 0, 0);
+        } else {
+          cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
         }
-
+        cairo_show_text(cr, "Locked");
+        
         cairo_set_source_rgb(cr, 1, 1, 0);
-        cairo_move_to(cr, 130, 50);  
-        cairo_show_text(cr, mode_string[entry->mode]);
-
-        cairo_move_to(cr, 190, 50);  
-        if(mode==modeFMN) {
+        cairo_move_to(cr, 100, 50);  
+        if(vfo[id].mode==modeFMN) {
           if(deviation==2500) {
-            cairo_show_text(cr, "8k");
+            sprintf(temp_text,"%s 8k",mode_string[vfo[id].mode]); 
           } else {
-            cairo_show_text(cr, "16k");
+            sprintf(temp_text,"%s 16k",mode_string[vfo[id].mode]); 
           }
         } else {
-          cairo_show_text(cr, band_filter->title);
+          sprintf(temp_text,"%s %s",mode_string[vfo[id].mode],band_filter->title); 
         }
+        cairo_show_text(cr, temp_text);
 
-        cairo_move_to(cr, 250, 50);  
-        if(nr) {
-          cairo_show_text(cr, "NR");
-        }
-        if(nr2) {
-          cairo_show_text(cr, "NR2");
-        }
-        if(nb) {
-          cairo_show_text(cr, "NB");
+        cairo_move_to(cr, 170, 50);  
+        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);
         }
-        if(nb2) {
-          cairo_show_text(cr, "NB2");
+        cairo_show_text(cr, "NR");
+
+        cairo_move_to(cr, 200, 50);  
+        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);
         }
-        if(anf) {
-          cairo_show_text(cr, "ANF");
+        cairo_show_text(cr, "NR2");
+
+        cairo_move_to(cr, 230, 50);  
+        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);
         }
-        if(snb) {
-          cairo_show_text(cr, "SNB");
+        cairo_show_text(cr, "ANF");
+
+        cairo_move_to(cr, 260, 50);  
+        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);
         }
+        cairo_show_text(cr, "SNB");
 
-        cairo_move_to(cr, 310, 50);  
-        switch(agc) {
+        cairo_move_to(cr, 290, 50);  
+        switch(active_receiver->agc) {
           case AGC_OFF:
+            cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
             cairo_show_text(cr, "AGC OFF");
             break;
           case AGC_LONG:
+            cairo_set_source_rgb(cr, 1, 1, 0);
             cairo_show_text(cr, "AGC LONG");
             break;
           case AGC_SLOW:
+            cairo_set_source_rgb(cr, 1, 1, 0);
             cairo_show_text(cr, "AGC SLOW");
             break;
           case AGC_MEDIUM:
+            cairo_set_source_rgb(cr, 1, 1, 0);
             cairo_show_text(cr, "AGC MEDIUM");
             break;
           case AGC_FAST:
+            cairo_set_source_rgb(cr, 1, 1, 0);
             cairo_show_text(cr, "AGC FAST");
             break;
         }
 
+        int s=0;
+        while(steps[s]!=step && steps[s]!=0) {
+          s++;
+        }
+        sprintf(temp_text,"Step %s",step_labels[s]);
+        cairo_move_to(cr, 375, 50);
+        cairo_set_source_rgb(cr, 1, 1, 0);
+        cairo_show_text(cr, temp_text);
+
+        char *info=getFrequencyInfo(af);
+/*
+        cairo_move_to(cr, (my_width/4)*3, 50);
+        cairo_show_text(cr, getFrequencyInfo(af));
+*/
          
-        cairo_move_to(cr, 400, 50);  
-        if(ctun) {
-          cairo_show_text(cr, "CTUN");
+        cairo_move_to(cr, 460, 50);  
+        if(vfo[id].ctun) {
+          cairo_set_source_rgb(cr, 1, 1, 0);
+        } else {
+          cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
+        }
+        cairo_show_text(cr, "CTUN");
+
+        cairo_move_to(cr, 500, 50);  
+        if(cat_control>0) {
+          cairo_set_source_rgb(cr, 1, 1, 0);
+        } else {
+          cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
+        }
+        cairo_show_text(cr, "CAT");
+
+        cairo_move_to(cr, 270, 15);
+        if(split) {
+          cairo_set_source_rgb(cr, 1, 0, 0);
+        } else {
+          cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
+        }
+        cairo_show_text(cr, "Split");
+       
+        cairo_move_to(cr, 310, 15);
+        if(vfo[id].mode==modeCWL || vfo[id].mode==modeCWU) {
+          cairo_set_source_rgb(cr, 1, 1, 0);
+        } else {
+          cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
         }
+        sprintf(temp_text,"CW %d wpm, sidetone %d Hz",cw_keyer_speed,cw_keyer_sidetone_frequency);
+        cairo_show_text(cr, temp_text);
 
         cairo_destroy (cr);
-        gtk_widget_queue_draw (vfo);
+        gtk_widget_queue_draw (vfo_panel);
     } else {
 fprintf(stderr,"vfo_update: no surface!\n");
     }
@@ -365,92 +768,44 @@ vfo_press_event_cb (GtkWidget *widget,
                GdkEventButton *event,
                gpointer        data)
 {
-
+/*
   if((int)event->x < (my_width/4)) {
-    lock_cb(NULL,NULL);
+    //lock_cb(NULL,NULL);
   } else if((int)event->x < (my_width/2) && (int)event->x > (my_width/4)) {
     start_freqent();
   } else {
     start_step();
-/*
-    GtkWidget *dialog=gtk_dialog_new_with_buttons("Step",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
-
-    GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
-    GtkWidget *grid=gtk_grid_new();
-
-    gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
-    gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
-
-    GtkWidget *step_rb=NULL;
-    int i=0;
-    while(steps[i]!=0) {
-      if(i==0) {
-          step_rb=gtk_radio_button_new_with_label(NULL,step_labels[i]);
-      } else {
-          step_rb=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(step_rb),step_labels[i]);
-      }
-      gtk_widget_override_font(step_rb, pango_font_description_from_string("FreeMono 18"));
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (step_rb), steps[i]==step);
-      gtk_widget_show(step_rb);
-      gtk_grid_attach(GTK_GRID(grid),step_rb,i%5,i/5,1,1);
-      g_signal_connect(step_rb,"pressed",G_CALLBACK(vfo_step_select_cb),(gpointer *)i);
-      i++;
-    }
-  
-    gtk_container_add(GTK_CONTAINER(content),grid);
-  
-    GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
-    gtk_widget_override_font(close_button, pango_font_description_from_string("FreeMono 18"));
-    gtk_widget_show_all(dialog);
-
-    g_signal_connect_swapped (dialog,
-                             "response",
-                             G_CALLBACK (gtk_widget_destroy),
-                             dialog);
-  
-    int result=gtk_dialog_run(GTK_DIALOG(dialog));
-*/
   }
+*/
+  start_vfo();
   return TRUE;
 }
 
 GtkWidget* vfo_init(int width,int height,GtkWidget *parent) {
+  int i;
 
 fprintf(stderr,"vfo_init: width=%d height=%d\n", width, height);
+
   parent_window=parent;
   my_width=width;
   my_height=height;
 
-  vfo = gtk_drawing_area_new ();
-  gtk_widget_set_size_request (vfo, width, height);
+  vfo_panel = gtk_drawing_area_new ();
+  gtk_widget_set_size_request (vfo_panel, width, height);
 
-  /* Signals used to handle the backing surface */
-  g_signal_connect (vfo, "draw",
-            G_CALLBACK (vfo_draw_cb), NULL);
-  g_signal_connect (vfo,"configure-event",
+  g_signal_connect (vfo_panel,"configure-event",
             G_CALLBACK (vfo_configure_event_cb), NULL);
+  g_signal_connect (vfo_panel, "draw",
+            G_CALLBACK (vfo_draw_cb), NULL);
 
   /* Event signals */
-  g_signal_connect (vfo, "button-press-event",
+  g_signal_connect (vfo_panel, "button-press-event",
             G_CALLBACK (vfo_press_event_cb), NULL);
-  g_signal_connect(vfo,"scroll_event",
+  g_signal_connect(vfo_panel,"scroll_event",
             G_CALLBACK(vfo_scroll_event_cb),NULL);
-  gtk_widget_set_events (vfo, gtk_widget_get_events (vfo)
+  gtk_widget_set_events (vfo_panel, gtk_widget_get_events (vfo_panel)
                      | GDK_BUTTON_PRESS_MASK
                      | GDK_SCROLL_MASK);
 
-fprintf(stderr,"vfo_init: set Frequency,Mode,Filter\n");
-  BAND *band=band_get_current_band();
-  BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
-  setFrequency(entry->frequencyA);
-  setMode(entry->mode);
-  FILTER* band_filters=filters[entry->mode];
-  FILTER* band_filter=&band_filters[entry->filter];
-  setFilter(band_filter->low,band_filter->high);
-
-  set_alex_rx_antenna(band->alexRxAntenna);
-  set_alex_tx_antenna(band->alexTxAntenna);
-  set_alex_attenuation(band->alexAttenuation);
-
-  return vfo;
+  return vfo_panel;
 }
diff --git a/vfo.h b/vfo.h
index edfb49b1d86e64686b06fed583711d77abeeb3c3..dc13f0f53569ff2302e7434fde80db7f36107ed6 100644 (file)
--- a/vfo.h
+++ b/vfo.h
 #ifndef _VFO_H
 #define _VFO_H
 
+
+enum {
+  VFO_A=0,
+  VFO_B,
+  MAX_VFOS
+};
+
+struct _vfo {
+  int band;
+  int bandstack;
+  long long frequency;
+  int mode;
+  int filter;
+
+  int ctun;
+  long long ctun_frequency;
+  long long rit;
+
+  long long lo;
+  long long offset;
+
+} vfo[MAX_VFOS];
+
+
 extern int steps[];
 extern char *step_labels[];
 
 extern GtkWidget* vfo_init(int width,int height,GtkWidget *parent);
 extern void vfo_step(int steps);
-extern void vfo_move(int hz);
+extern void vfo_move(long long hz);
+extern void vfo_move_to(long long hz);
 extern int vfo_update(void*);
+extern void set_frequency();
+
+extern void vfo_save_state();
+extern void vfo_restore_state();
 
+extern void vfo_band_changed(int b);
+extern void vfo_bandstack_changed(int b);
+extern void vfo_mode_changed(int m);
+extern void vfo_filter_changed(int f);
+extern void vfo_a_to_b();
+extern void vfo_b_to_a();
+extern void vfo_a_swap_b();
 #endif
diff --git a/vfo_menu.c b/vfo_menu.c
new file mode 100644 (file)
index 0000000..a9dfc35
--- /dev/null
@@ -0,0 +1,256 @@
+/* Copyright (C)
+* 2016 - John Melton, G0ORX/N6LYT
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "new_menu.h"
+#include "band.h"
+#include "filter.h"
+#include "mode.h"
+#include "radio.h"
+#include "receiver.h"
+#include "vfo.h"
+
+static GtkWidget *parent_window=NULL;
+static GtkWidget *dialog=NULL;
+static GtkWidget *label;
+
+#define BUF_SIZE 88
+
+static char *btn_labels[] = {"1","2","3",
+               "4","5","6",
+               "7","8","9",
+               ".","0","BS",
+               "HZ","KZ","MZ"
+               ,"CL"
+              };
+
+static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  if(dialog!=NULL) {
+    gtk_widget_destroy(dialog);
+    dialog=NULL;
+    sub_menu=NULL;
+  }
+  return TRUE;
+}
+
+static gboolean freqent_select_cb (GtkWidget *widget, gpointer data) {
+  char *str = (char *) data;
+  const char *labelText;
+  char output[BUF_SIZE], buffer[BUF_SIZE];
+  int  len;
+  double  mult;
+  long long f;
+  static int set = 0;
+
+  if (set) {
+    set = 0;
+    strcpy (buffer, "0");
+    sprintf(output, "<big>%s</big>", buffer);
+    gtk_label_set_markup (GTK_LABEL (label), output);
+    len = 1;
+  } else {
+    labelText = gtk_label_get_text (GTK_LABEL (label));
+    strcpy (buffer, labelText);
+    len = strlen (buffer);
+  }
+
+  if (isdigit (str[0]) || str[0] == '.') {
+
+    buffer[len] = (gchar) str[0];
+    buffer[len+1] = (gchar) 0;
+
+    len = (buffer[0] == '0') ? 1 : 0;
+
+    sprintf(output, "<big>%s</big>", buffer+len);
+    gtk_label_set_markup (GTK_LABEL (label), output);
+  } else {
+
+    if (strcmp (str, "BS") == 0) {
+      /* --- Remove the last character on it. --- */
+      if (len > 0) buffer[len-1] = (gchar) 0;
+
+      /* --- Remove digit from field. --- */
+      sprintf(output, "<big>%s</big>", buffer);
+      gtk_label_set_markup (GTK_LABEL (label), output);
+
+    /* --- clear? --- */
+    } else if (strcmp (str, "CL") == 0) {
+      strcpy (buffer, "0");
+      sprintf(output, "<big>%s</big>", buffer);
+      gtk_label_set_markup (GTK_LABEL (label), output);
+    } else if (str[1] == 'Z') {
+      switch(str[0]) {
+      case 'M':
+        mult = 10000000.0;
+        break;
+      case 'K':
+        mult = 10000.0;
+        break;
+      default :
+        mult = 10.0;
+      }
+      f = ((long long)(atof(buffer)*mult)+5)/10;
+      sprintf(output, "<big>%lld</big>", f);
+      gtk_label_set_markup (GTK_LABEL (label), output);
+      int b=get_band_from_frequency(f);
+      if(b<0) {
+        fprintf(stderr,"get_band_from_frequency: failed for f=%lld\n",f);
+        b=bandGen;
+      }
+      if(b!=band_get_current()) {
+        BAND *band=band_set_current(b);
+        BANDSTACK_ENTRY *entry=bandstack_entry_get_current();
+        //setMode(entry->mode);
+        set_mode(active_receiver,entry->mode);
+        FILTER* band_filters=filters[entry->mode];
+        FILTER* band_filter=&band_filters[entry->filter];
+        //setFilter(band_filter->low,band_filter->high);
+        set_filter(active_receiver,band_filter->low,band_filter->high);
+        if(active_receiver->id==0) {
+          set_alex_rx_antenna(band->alexRxAntenna);
+          set_alex_tx_antenna(band->alexTxAntenna);
+          set_alex_attenuation(band->alexAttenuation);
+        }
+      }
+      setFrequency(f);
+      vfo_update(NULL);
+    
+      set = 1;
+    }
+  }
+  vfo_update(NULL);
+}
+
+static void rit_cb(GtkComboBox *widget,gpointer data) {
+  switch(gtk_combo_box_get_active(widget)) {
+    case 0:
+      rit_increment=1;
+      break;
+    case 1:
+      rit_increment=10;
+      break;
+    case 2:
+      rit_increment=100;
+      break;
+  }
+  vfo_update(NULL);
+}
+
+static void vfo_cb(GtkComboBox *widget,gpointer data) {
+  step=steps[gtk_combo_box_get_active(widget)];
+  vfo_update(NULL);
+}
+
+static GtkWidget *last_mode;
+
+void vfo_menu(GtkWidget *parent) {
+  int i;
+
+  parent_window=parent;
+
+  dialog=gtk_dialog_new();
+  gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
+  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+
+  GdkRGBA color;
+  color.red = 1.0;
+  color.green = 1.0;
+  color.blue = 1.0;
+  color.alpha = 1.0;
+  gtk_widget_override_background_color(dialog,GTK_STATE_FLAG_NORMAL,&color);
+
+  GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+
+  GtkWidget *grid=gtk_grid_new();
+
+  gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+  gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
+  gtk_grid_set_column_spacing (GTK_GRID(grid),4);
+  gtk_grid_set_row_spacing (GTK_GRID(grid),4);
+
+  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);
+
+  char rx_id[32];
+  sprintf(rx_id,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B");
+  GtkWidget *rx_label=gtk_label_new(rx_id);
+  gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1);
+
+  label = gtk_label_new (NULL);
+  gtk_label_set_markup (GTK_LABEL (label), "<big>0</big>");
+  gtk_misc_set_alignment (GTK_MISC (label), 1, .5);
+  gtk_grid_attach(GTK_GRID(grid),label,0,1,3,1);
+
+  GtkWidget *step_rb=NULL;
+  for (i=0; i<16; i++) {
+    GtkWidget *b=gtk_button_new_with_label(btn_labels[i]);
+    set_button_text_color(b,"black");
+    gtk_widget_show(b);
+    gtk_grid_attach(GTK_GRID(grid),b,i%3,2+(i/3),1,1);
+    g_signal_connect(b,"pressed",G_CALLBACK(freqent_select_cb),(gpointer *)btn_labels[i]);
+  }
+
+  GtkWidget *rit_label=gtk_label_new("RIT step: ");
+  gtk_grid_attach(GTK_GRID(grid),rit_label,3,1,1,1);
+
+  GtkWidget *rit_b=gtk_combo_box_text_new();
+  gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(rit_b),NULL,"1 Hz");
+  gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(rit_b),NULL,"10 Hz");
+  gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(rit_b),NULL,"100 Hz");
+  switch(rit_increment) {
+    case 1:
+      gtk_combo_box_set_active(GTK_COMBO_BOX(rit_b), 0);
+      break;
+    case 10:
+      gtk_combo_box_set_active(GTK_COMBO_BOX(rit_b), 1);
+      break;
+    case 100:
+      gtk_combo_box_set_active(GTK_COMBO_BOX(rit_b), 2);
+      break;
+  }
+  g_signal_connect(rit_b,"changed",G_CALLBACK(rit_cb),NULL);
+  gtk_grid_attach(GTK_GRID(grid),rit_b,3,2,1,1);
+
+  GtkWidget *vfo_label=gtk_label_new("VFO step: ");
+  gtk_grid_attach(GTK_GRID(grid),vfo_label,3,3,1,1);
+
+  GtkWidget *vfo_b=gtk_combo_box_text_new();
+  i=0;
+  while(steps[i]!=0) {
+    gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(vfo_b),NULL,step_labels[i]);
+    if(steps[i]==step) {
+      gtk_combo_box_set_active (GTK_COMBO_BOX(vfo_b), i);
+    }
+    i++;
+  }
+  g_signal_connect(vfo_b,"changed",G_CALLBACK(vfo_cb),NULL);
+  gtk_grid_attach(GTK_GRID(grid),vfo_b,3,4,1,1);
+
+  gtk_container_add(GTK_CONTAINER(content),grid);
+
+  sub_menu=dialog;
+
+  gtk_widget_show_all(dialog);
+
+}
diff --git a/vfo_menu.h b/vfo_menu.h
new file mode 100644 (file)
index 0000000..798da2d
--- /dev/null
@@ -0,0 +1,20 @@
+/* Copyright (C)
+* 2016 - John Melton, G0ORX/N6LYT
+*
+* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+extern void vfo_menu(GtkWidget *parent);
diff --git a/vox.c b/vox.c
index 734f2105b2fc3747a7b1cd3a5bd3163b9fc1a49e..287b1cde01304bdd3284764e48d90d5a9b90bf4e 100644 (file)
--- a/vox.c
+++ b/vox.c
@@ -20,6 +20,7 @@
 #include <gtk/gtk.h>
 
 #include "radio.h"
+#include "transmitter.h"
 #include "vox.h"
 #include "vfo.h"
 
@@ -35,17 +36,18 @@ static int vox_timeout_cb(gpointer data) {
 
 
 double vox_get_peak() {
-  return peak*10.0;
+  double result=peak;
+  return result;
 }
 
-void update_vox(double *in,int length) {
+void update_vox(TRANSMITTER *tx) {
   // assumes in is interleaved left and right channel with length samples
   int previous_vox=vox;
   int i;
   double sample;
   peak=0.0;
-  for(i=0;i<length;i++) {
-    sample=in[(i*2)+0];
+  for(i=0;i<tx->buffer_size;i++) {
+    sample=tx->mic_input_buffer[i*2];
     if(sample<0.0) {
       sample=-sample;
     }
@@ -53,22 +55,25 @@ void update_vox(double *in,int length) {
       peak=sample;
     }
   }
-  double threshold=vox_threshold;
-  if(mic_boost && !local_microphone) {
-    threshold=vox_threshold*vox_gain;
-  }
 
-fprintf(stderr,"update_vox: peak=%f threshold=%f\n",peak,threshold);
-  if(peak>threshold) {
-    if(previous_vox) {
-      g_source_remove(vox_timeout);
-    } else {
-      setVox(1);
+//fprintf(stderr,"update_vox: id=%d peak=%f\n",tx->id,peak);
+
+  if(vox_enabled) {
+    double threshold=vox_threshold;
+
+//fprintf(stderr,"update_vox: peak=%f threshold=%f\n",peak,threshold);
+
+    if(peak>threshold) {
+      if(previous_vox) {
+        g_source_remove(vox_timeout);
+      } else {
+        setVox(1);
+      }
+      vox_timeout=g_timeout_add((int)vox_hang,vox_timeout_cb,NULL);
+    }
+    if(vox!=previous_vox) {
+      g_idle_add(vfo_update,NULL);
     }
-    vox_timeout=g_timeout_add((int)vox_hang,vox_timeout_cb,NULL);
-  }
-  if(vox!=previous_vox) {
-    g_idle_add(vfo_update,NULL);
   }
 }
 
diff --git a/vox.h b/vox.h
index b5d5d40ecbb656b68b2f3392c29e50e328ed00df..34bd48e24c85a00ed01a955f5a4297b1c66879f1 100644 (file)
--- a/vox.h
+++ b/vox.h
@@ -17,6 +17,6 @@
 *
 */
 
-extern void update_vox(double *in,int length);
+extern void update_vox(TRANSMITTER *tx);
 extern void vox_cancel();
 extern double vox_get_peak();
index 65bee6adf23105ad8c25bac6bb7bca93e2c69a70..1d2d51676bb3301822e1ca080989e77b7b707c78 100644 (file)
 #include <pthread.h>
 
 #include "new_menu.h"
+#include "radio.h"
+#include "transmitter.h"
 #include "vox_menu.h"
 #include "vox.h"
-#include "radio.h"
 
 static GtkWidget *parent_window=NULL;
 
@@ -34,11 +35,12 @@ static GtkWidget *dialog=NULL;
 
 static GtkWidget *level;
 
-static pthread_t level_thread_id;
+GThread *level_thread_id;
 static int run_level=0;
 static double peak=0.0;
 
 static int level_update(void *data) {
+//fprintf(stderr,"vox peak=%f\n",peak);
   gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(level),peak);
   return 0;
 }
@@ -63,28 +65,20 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat
 static void start_level_thread() {
   int rc;
   run_level=1;
-  rc=pthread_create(&level_thread_id,NULL,level_thread,NULL);
-  if(rc != 0) {
-    fprintf(stderr,"vox_menu: pthread_create failed on level_thread: rc=%d\n", rc);
-    run_level=0;
+  level_thread_id = g_thread_new( "VOX level", level_thread, NULL);
+  if(!level_thread_id ) {
+    fprintf(stderr,"g_thread_new failed on level_thread\n");
   }
+  fprintf(stderr, "level_thread: id=%p\n",level_thread_id);
 }
 
 static void destroy_cb(GtkWidget *widget, gpointer data) {
   run_level=0;
-}
-
-static void vox_cb(GtkWidget *widget, gpointer data) {
-  vox_enabled=vox_enabled==1?0:1;
-  if(vox_enabled) {
-    start_level_thread();
-  } else {
-    run_level=0;
-  }
+  vox_setting=0;
 }
 
 static void vox_value_changed_cb(GtkWidget *widget, gpointer data) {
-  vox_threshold=gtk_range_get_value(GTK_RANGE(widget))/10000.0;
+  vox_threshold=gtk_range_get_value(GTK_RANGE(widget))/1000.0;
 }
 
 static void vox_gain_value_changed_cb(GtkWidget *widget, gpointer data) {
@@ -124,28 +118,16 @@ void vox_menu(GtkWidget *parent) {
   g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
   gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
 
-  GtkWidget *vox_b=gtk_check_button_new_with_label("VOX Enable");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (vox_b), vox_enabled);
-  gtk_widget_show(vox_b);
-  gtk_grid_attach(GTK_GRID(grid),vox_b,0,1,1,1);
-  g_signal_connect(vox_b,"toggled",G_CALLBACK(vox_cb),NULL);
+  GtkWidget *level_label=gtk_label_new("Mic Level:");
+  gtk_misc_set_alignment (GTK_MISC(level_label), 0, 0);
+  gtk_widget_show(level_label);
+  gtk_grid_attach(GTK_GRID(grid),level_label,0,1,1,1);
 
   level=gtk_progress_bar_new();
+  gtk_widget_set_size_request (level, 300, 25);
   gtk_widget_show(level);
   gtk_grid_attach(GTK_GRID(grid),level,1,1,1,1);
 
-/*
-  // try to set progress bar to red
-  GtkStyleContext *style_context;
-  GtkCssProvider *provider = gtk_css_provider_new ();
-  gchar tmp[64];
-  style_context = gtk_widget_get_style_context(level);
-  gtk_style_context_add_provider(style_context, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
-  g_snprintf(tmp, sizeof tmp, "progressbar.trough.progress { background-color: %s; }", "red");
-  gtk_css_provider_load_from_data(GTK_CSS_PROVIDER(provider), tmp, -1, NULL);
-  g_object_unref (provider);
-*/
-
   GtkWidget *threshold_label=gtk_label_new("VOX Threshold:");
   gtk_misc_set_alignment (GTK_MISC(threshold_label), 0, 0);
   gtk_widget_show(threshold_label);
@@ -153,23 +135,11 @@ void vox_menu(GtkWidget *parent) {
 
   GtkWidget *vox_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0,1000.0,1.0);
   gtk_widget_set_size_request (vox_scale, 300, 25);
-  gtk_range_set_value(GTK_RANGE(vox_scale),vox_threshold*10000.0);
+  gtk_range_set_value(GTK_RANGE(vox_scale),vox_threshold*1000.0);
   gtk_widget_show(vox_scale);
   gtk_grid_attach(GTK_GRID(grid),vox_scale,1,2,1,1);
   g_signal_connect(G_OBJECT(vox_scale),"value_changed",G_CALLBACK(vox_value_changed_cb),NULL);
   
-/*
-  GtkWidget *gain_label=gtk_label_new("VOX Gain:");
-  gtk_misc_set_alignment (GTK_MISC(gain_label), 0, 0);
-  gtk_widget_show(gain_label);
-  gtk_grid_attach(GTK_GRID(grid),gain_label,0,3,1,1);
-
-  GtkWidget *gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,1.0,10.0,1.0);
-  gtk_range_set_value(GTK_RANGE(gain_scale),vox_gain*10000.0);
-  gtk_widget_show(gain_scale);
-  gtk_grid_attach(GTK_GRID(grid),gain_scale,1,3,1,1);
-  g_signal_connect(G_OBJECT(gain_scale),"value_changed",G_CALLBACK(vox_gain_value_changed_cb),NULL);
-*/  
   GtkWidget *hang_label=gtk_label_new("VOX Hang (ms):");
   gtk_misc_set_alignment (GTK_MISC(hang_label), 0, 0);
   gtk_widget_show(hang_label);
@@ -186,9 +156,10 @@ void vox_menu(GtkWidget *parent) {
 
   gtk_widget_show_all(dialog);
 
-  if(vox_enabled) {
-    start_level_thread();
+  if(!vox_enabled) {
+    vox_setting=1;
   }
+  start_level_thread();
 
 }
 
index af6606e0c594654a61656b0e3192d575a2f9f298..8dfc38d24308225b42079f5a27716a48906600e7 100644 (file)
@@ -18,3 +18,5 @@
 */
 
 void vox_menu(GtkWidget *parent);
+gboolean vox_cb (GtkWidget *widget, GdkEventButton *event, gpointer data);
+
index b127dc6ac3c3ba4882871304d891d873286fb630..3af56d428caed617c45df31f9a740cdd0d4ecc1c 100644 (file)
@@ -28,8 +28,6 @@
 #include "vfo.h"
 #include "waterfall.h"
 
-static GtkWidget *waterfall;
-static GdkPixbuf *pixbuf = NULL;
 
 static int colorLowR=0; // black
 static int colorLowG=0;
@@ -51,11 +49,13 @@ static gboolean pressed=FALSE;
 
 static gfloat hz_per_pixel;
 
+/*
 #define BANDS 7
 
 static long long frequency[BANDS];
 static gint mode[BANDS];
 static gint band=4;
+*/
 
 static int display_width;
 static int display_height;
@@ -66,11 +66,12 @@ waterfall_configure_event_cb (GtkWidget         *widget,
             GdkEventConfigure *event,
             gpointer           data)
 {
+  RECEIVER *rx=(RECEIVER *)data;
   display_width=gtk_widget_get_allocated_width (widget);
   display_height=gtk_widget_get_allocated_height (widget);
-  pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, display_width, display_height);
+  rx->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, display_width, display_height);
 
-  char *pixels = gdk_pixbuf_get_pixels (pixbuf);
+  char *pixels = gdk_pixbuf_get_pixels (rx->pixbuf);
 
   memset(pixels, 0, display_width*display_height*3);
 
@@ -86,7 +87,8 @@ waterfall_draw_cb (GtkWidget *widget,
  cairo_t   *cr,
  gpointer   data)
 {
-  gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
+  RECEIVER *rx=(RECEIVER *)data;
+  gdk_cairo_set_source_pixbuf (cr, rx->pixbuf, 0, 0);
   cairo_paint (cr);
   return TRUE;
 }
@@ -96,13 +98,7 @@ waterfall_button_press_event_cb (GtkWidget      *widget,
                GdkEventButton *event,
                gpointer        data)
 {
-  int x=(int)event->x;
-  if (event->button == 1) {
-    last_x=(int)event->x;
-    has_moved=FALSE;
-    pressed=TRUE;
-  }
-  return TRUE;
+  return receiver_button_press_event(widget,event,data);
 }
 
 static gboolean
@@ -110,42 +106,14 @@ waterfall_button_release_event_cb (GtkWidget      *widget,
                GdkEventButton *event,
                gpointer        data)
 {
-  if(pressed) {
-    int x=(int)event->x;
-    if (event->button == 1) {
-      if(has_moved) {
-        // drag
-        vfo_move((int)((float)(x-last_x)*hz_per_pixel));
-      } else {
-        // move to this frequency
-        vfo_move_to((int)((float)(x-(display_width/2))*hz_per_pixel));
-      }
-      last_x=x;
-      pressed=FALSE;
-    }
-  }
-  return TRUE;
+  return receiver_button_release_event(widget,event,data);
 }
 
 static gboolean waterfall_motion_notify_event_cb (GtkWidget      *widget,
                 GdkEventMotion *event,
                 gpointer        data)
 {
-  int x, y;
-  GdkModifierType state;
-  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((int)((float)moved*hz_per_pixel));
-    last_x=x;
-    has_moved=TRUE;
-  }
-
-  return TRUE;
+  return receiver_motion_notify_event(widget,event,data);
 }
 
 static gboolean
@@ -153,26 +121,21 @@ waterfall_scroll_event_cb (GtkWidget      *widget,
                GdkEventScroll *event,
                gpointer        data)
 {
-  if(event->direction==GDK_SCROLL_UP) {
-    vfo_move(step);
-  } else {
-    vfo_move(-step);
-  }
+  return receiver_scroll_event(widget,event,data);
 }
 
-void waterfall_update(float *data) {
+void waterfall_update(RECEIVER *rx) {
 
   int i;
 
-  hz_per_pixel=(double)getSampleRate()/(double)display_width;
-
-  if(pixbuf) {
-    char *pixels = gdk_pixbuf_get_pixels (pixbuf);
+  float *samples;
+  if(rx->pixbuf) {
+    char *pixels = gdk_pixbuf_get_pixels (rx->pixbuf);
 
-    int width=gdk_pixbuf_get_width(pixbuf);
-    int height=gdk_pixbuf_get_height(pixbuf);
-    int rowstride=gdk_pixbuf_get_rowstride(pixbuf);
-    int channels=gdk_pixbuf_get_n_channels(pixbuf);
+    int width=gdk_pixbuf_get_width(rx->pixbuf);
+    int height=gdk_pixbuf_get_height(rx->pixbuf);
+    int rowstride=gdk_pixbuf_get_rowstride(rx->pixbuf);
+    int channels=gdk_pixbuf_get_n_channels(rx->pixbuf);
 
     memmove(&pixels[rowstride],pixels,(height-1)*rowstride);
 
@@ -180,20 +143,21 @@ void waterfall_update(float *data) {
     int average=0;
     char *p;
     p=pixels;
+    samples=rx->pixel_samples;
     for(i=0;i<width;i++) {
-            sample=data[i]+get_attenuation();
+            sample=samples[i]+get_attenuation();
             average+=(int)sample;
-            if(sample<(float)waterfall_low) {
+            if(sample<(float)rx->waterfall_low) {
                 *p++=colorLowR;
                 *p++=colorLowG;
                 *p++=colorLowB;
-            } else if(sample>(float)waterfall_high) {
+            } else if(sample>(float)rx->waterfall_high) {
                 *p++=colorHighR;
                 *p++=colorHighG;
                 *p++=colorHighB;
             } else {
-                float range=(float)waterfall_high-(float)waterfall_low;
-                float offset=sample-(float)waterfall_low;
+                float range=(float)rx->waterfall_high-(float)rx->waterfall_low;
+                float offset=sample-(float)rx->waterfall_low;
                 float percent=offset/range;
                 if(percent<(2.0f/9.0f)) {
                     float local_percent = percent / (2.0f/9.0f);
@@ -236,47 +200,52 @@ void waterfall_update(float *data) {
     }
 
     
-    if(waterfall_automatic) {
-      waterfall_low=average/display_width;
-      waterfall_high=waterfall_low+50;
+    if(rx->waterfall_automatic) {
+      rx->waterfall_low=average/display_width;
+      rx->waterfall_high=rx->waterfall_low+50;
     }
 
-    gtk_widget_queue_draw (waterfall);
+    gtk_widget_queue_draw (rx->waterfall);
   }
 }
 
-GtkWidget* waterfall_init(int width,int height) {
+void waterfall_init(RECEIVER *rx,int width,int height) {
   display_width=width;
   display_height=height;
 
-  hz_per_pixel=(double)getSampleRate()/(double)display_width;
+  rx->pixbuf=NULL;
+  rx->waterfall_low=waterfall_low;
+  rx->waterfall_high=waterfall_high;
+  rx->waterfall_automatic=waterfall_automatic;
+
+  hz_per_pixel=(double)rx->sample_rate/(double)display_width;
 
   //waterfall_frame = gtk_frame_new (NULL);
-  waterfall = gtk_drawing_area_new ();
-  gtk_widget_set_size_request (waterfall, width, height);
+  rx->waterfall = gtk_drawing_area_new ();
+  gtk_widget_set_size_request (rx->waterfall, width, height);
 
   /* Signals used to handle the backing surface */
-  g_signal_connect (waterfall, "draw",
-            G_CALLBACK (waterfall_draw_cb), NULL);
-  g_signal_connect (waterfall,"configure-event",
-            G_CALLBACK (waterfall_configure_event_cb), NULL);
+  g_signal_connect (rx->waterfall, "draw",
+            G_CALLBACK (waterfall_draw_cb), rx);
+  g_signal_connect (rx->waterfall,"configure-event",
+            G_CALLBACK (waterfall_configure_event_cb), rx);
 
 
   /* Event signals */
-  g_signal_connect (waterfall, "motion-notify-event",
-            G_CALLBACK (waterfall_motion_notify_event_cb), NULL);
-  g_signal_connect (waterfall, "button-press-event",
-            G_CALLBACK (waterfall_button_press_event_cb), NULL);
-  g_signal_connect (waterfall, "button-release-event",
-            G_CALLBACK (waterfall_button_release_event_cb), NULL);
-  g_signal_connect(waterfall,"scroll_event",
-            G_CALLBACK(waterfall_scroll_event_cb),NULL);
+  g_signal_connect (rx->waterfall, "motion-notify-event",
+            G_CALLBACK (waterfall_motion_notify_event_cb), rx);
+  g_signal_connect (rx->waterfall, "button-press-event",
+            G_CALLBACK (waterfall_button_press_event_cb), rx);
+  g_signal_connect (rx->waterfall, "button-release-event",
+            G_CALLBACK (waterfall_button_release_event_cb), rx);
+  g_signal_connect(rx->waterfall,"scroll_event",
+            G_CALLBACK(waterfall_scroll_event_cb),rx);
 
   /* Ask to receive events the drawing area doesn't normally
    * subscribe to. In particular, we need to ask for the
    * button press and motion notify events that want to handle.
    */
-  gtk_widget_set_events (waterfall, gtk_widget_get_events (waterfall)
+  gtk_widget_set_events (rx->waterfall, gtk_widget_get_events (rx->waterfall)
                      | GDK_BUTTON_PRESS_MASK
                      | GDK_BUTTON_RELEASE_MASK
                      | GDK_BUTTON1_MOTION_MASK
@@ -284,5 +253,4 @@ GtkWidget* waterfall_init(int width,int height) {
                      | GDK_POINTER_MOTION_MASK
                      | GDK_POINTER_MOTION_HINT_MASK);
 
-  return waterfall;
 }
index 6278c38d3517ec3b038a90d6fcc273f63d0fc729..3d41f52bd9585c0eba9e19bfd4af5e1d50f3532e 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef _WATERFALL_H
 #define _WATERFALL_H
 
-void waterfall_update(float *data);
-GtkWidget* waterfall_init(int width,int height);
+extern void waterfall_update(RECEIVER *rx);
+extern void waterfall_init(RECEIVER *rx,int width,int height);
 
 #endif
index 6fafe3c921dc9eae52dbbc75c14c05407a9b43cc..cdeec089dbba3c32e26d269daff762c65f071be4 100644 (file)
@@ -64,9 +64,9 @@
 static int receiver;
 static int running=0;
 
-static int buffer_size=BUFFER_SIZE;
-static int tx_buffer_size=BUFFER_SIZE;
-static int fft_size=4096;
+//static int buffer_size=BUFFER_SIZE;
+//static int tx_buffer_size=BUFFER_SIZE;
+static int tx_buffer_size;
 static int dspRate=48000;
 static int outputRate=48000;
 static int dvOutputRate=8000;
@@ -84,20 +84,20 @@ static void calc_tx_buffer_size() {
   if(protocol==ORIGINAL_PROTOCOL) {
     switch(sample_rate) {
       case 48000:
-        tx_buffer_size=BUFFER_SIZE;
+        tx_buffer_size=buffer_size;
         break;
       case 96000:
-        tx_buffer_size=BUFFER_SIZE/2;
+        tx_buffer_size=buffer_size/2;
         break;
       case 192000:
-        tx_buffer_size=BUFFER_SIZE/4;
+        tx_buffer_size=buffer_size/4;
         break;
       case 384000:
-        tx_buffer_size=BUFFER_SIZE/8;
+        tx_buffer_size=buffer_size/8;
         break;
     }
   } else {
-    tx_buffer_size=BUFFER_SIZE; // input always 192K
+    tx_buffer_size=buffer_size; // input always 192K
   }
 }
 
@@ -253,7 +253,7 @@ static void setupRX(int rx) {
     }
 
     // setup for diversity
-    create_divEXT(0,0,2,BUFFER_SIZE);
+    create_divEXT(0,0,2,buffer_size);
     SetEXTDIVRotate(0, 2, &i_rotate, &q_rotate);
     SetEXTDIVRun(0,diversity_enabled);
 }
@@ -458,7 +458,10 @@ static void initAnalyzer(int channel,int buffer_size) {
 
     int max_w = fft_size + (int) MIN(KEEP_TIME * (double) SPECTRUM_UPDATES_PER_SECOND, KEEP_TIME * (double) fft_size * (double) SPECTRUM_UPDATES_PER_SECOND);
 
-    fprintf(stderr,"SetAnalyzer channel=%d buffer_size=%d\n",channel,buffer_size);
+    overlap = (int)max(0.0, ceil(fft_size - (double)sample_rate / (double)SPECTRUM_UPDATES_PER_SECOND));
+
+    fprintf(stderr,"SetAnalyzer channel=%d buffer_size=%d overlap=%d\n",channel,buffer_size,overlap);
+
 #ifdef PSK
     if(channel==CHANNEL_PSK) {
       data_type=0;
diff --git a/wdsp_init.h b/wdsp_init.h
deleted file mode 100644 (file)
index a61b170..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Copyright (C)
-* 2015 - John Melton, G0ORX/N6LYT
-*
-* 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 2
-* 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, write to the Free Software
-* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-*
-*/
-
-#ifndef _WDSP_INIT_H
-#define _WDSP_INIT_H
-
-extern void wdsp_set_input_rate(double rate);
-extern void wdsp_set_offset(long long offset);
-extern void setMode(int m);
-extern int getMode();
-extern void setFilter(int low,int high);
-extern int getFilterLow();
-extern int getFilterHigh();
-extern void wdsp_init(int rx,int pixels,int protocol);
-extern void wdsp_new_sample_rate(int rate);
-extern void wdsp_set_agc(int rx, int agc);
-extern void wdsp_set_deviation(double deviation);
-extern void wdsp_set_pre_emphasize(int state);
-#endif
index 6a2512519d9a800f3f292d893b12508750aed65a..2736864707cfd97fda4f8d62d0718e8e85e44f1d 100644 (file)
@@ -20,6 +20,7 @@
 #include <gtk/gtk.h>
 #include <semaphore.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "new_menu.h"
@@ -59,10 +60,10 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat
         lof=gtk_entry_get_text(GTK_ENTRY(lo_frequency[i]));
         xvtr->frequencyLO=atoll(lof);
         xvtr->disablePA=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(disable_pa[i]));
-        entry->frequencyA=xvtr->frequencyMin;
-        entry->frequencyB=xvtr->frequencyMin;
+        entry->frequency=xvtr->frequencyMin;
         entry->mode=modeUSB;
         entry->filter=filterF6;
+fprintf(stderr,"min=%s:%lld max=%s:%lld lo=%s:%lld\n",minf,xvtr->frequencyMin,maxf,xvtr->frequencyMax,lof,xvtr->frequencyLO);
       } else {
         xvtr->frequencyMin=0;
         xvtr->frequencyMax=0;