]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
Added SoapySDR support for Receive
authorJohn Melton G0ORX <john.d.melton@googlemail.com>
Sat, 5 Oct 2019 12:25:26 +0000 (13:25 +0100)
committerJohn Melton G0ORX <john.d.melton@googlemail.com>
Sat, 5 Oct 2019 12:25:26 +0000 (13:25 +0100)
71 files changed:
Makefile
about_menu.c
adc.h [new file with mode: 0644]
agc.h
ant_menu.c
audio.c
band.c
band.h
band_menu.c
configure.c
discovered.c
discovered.h
discovery.c
display_menu.c
diversity_menu.c
diversity_menu.h
encoder_menu.c
encoder_menu.h
exit_menu.c
ext.c
ext.h
filter.c
filter.h
frequency.c
general_menu.c
gpio.c
gpio.h
i2c.c
i2c.h
lime_discovery.c [deleted file]
lime_discovery.h [deleted file]
lime_protocol.c [deleted file]
lime_protocol.h [deleted file]
main.c
new_menu.c
new_menu.h
new_protocol_programmer.c
old_protocol.c
property.c
radio.c
radio.h
radio_menu.c
receiver.c
receiver.h
release/pihpsdr-v1.2.3.tar
release/pihpsdr.tar
release/pihpsdr/install.sh
release/pihpsdr/libSoapySDR.so.0.5-1 [deleted file]
release/pihpsdr/libcodec2.so.0.7 [deleted file]
release/pihpsdr/libpsk.so [deleted file]
release/pihpsdr/libwdsp.so
release/pihpsdr/pihpsdr
rigctl.c
rx_menu.c
rx_panadapter.c
sliders.c
sliders.h
soapy_discovery.c [new file with mode: 0644]
soapy_discovery.h [new file with mode: 0644]
soapy_protocol.c [new file with mode: 0644]
soapy_protocol.h [new file with mode: 0644]
switch_menu.c [new file with mode: 0644]
switch_menu.h [new file with mode: 0644]
toolbar.c
toolbar.h
transmitter.h
tx_panadapter.c
version.c
vfo.c
vfo.h
xvtr_menu.c

index a6e660fa3f9338bfc1e6f751d83c9f66fedd9c38..9884a922d8555593f228e7e18acc6b8423807b92 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -3,8 +3,11 @@
 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 CONTROLLER2 (Also include GPIO and I2C)
+#CONTROLLER2_INCLUDE=CONTROLLER2
+
 # uncomment the line below to include GPIO
-#GPIO_INCLUDE=GPIO
+GPIO_INCLUDE=GPIO
 
 # uncomment the line below to include MCP23017 I2C
 #I2C_INCLUDE=I2C
@@ -19,7 +22,7 @@ GIT_VERSION := $(shell git describe --abbrev=0 --tags)
 #FREEDV_INCLUDE=FREEDV
 
 # uncomment the line below to include Pure Signal support
-#PURESIGNAL_INCLUDE=PURESIGNAL
+PURESIGNAL_INCLUDE=PURESIGNAL
 
 # uncomment the line to below include support for sx1509 i2c expander
 #SX1509_INCLUDE=sx1509
@@ -52,6 +55,10 @@ LINK=gcc
 # uncomment the line below for various debug facilities
 #DEBUG_OPTION=-D DEBUG
 
+ifeq ($(CONTROLLER2_INCLUDE),CONTROLLER2)
+CONTROLLER2_OPTIONS=-D CONTROLLER2
+endif
+
 ifeq ($(MIDI_INCLUDE),MIDI)
 MIDI_OPTIONS=-D MIDI
 MIDI_SOURCES= alsa_midi.c midi2.c midi3.c
@@ -94,8 +101,6 @@ USBOZY_OBJS= \
 ozyio.o
 endif
 
-# uncomment the line below for LimeSDR (uncomment line below)
-#LIMESDR_INCLUDE=LIMESDR
 
 # uncomment the line below when Radioberry radio cape is plugged in (for now use emulator and old protocol)
 #RADIOBERRY_INCLUDE=RADIOBERRY
@@ -103,18 +108,21 @@ ifeq ($(RADIOBERRY_INCLUDE),RADIOBERRY)
 RADIOBERRY_OPTIONS=-D RADIOBERRY
 endif
 
-ifeq ($(LIMESDR_INCLUDE),LIMESDR)
-LIMESDR_OPTIONS=-D LIMESDR
+# uncomment the line below for SoapySDR
+SOAPYSDR_INCLUDE=SOAPYSDR
+
+ifeq ($(SOAPYSDR_INCLUDE),SOAPYSDR)
+SOAPYSDR_OPTIONS=-D SOAPYSDR
 SOAPYSDRLIBS=-lSoapySDR
-LIMESDR_SOURCES= \
-lime_discovery.c \
-lime_protocol.c
-LIMESDR_HEADERS= \
-lime_discovery.h \
-lime_protocol.h
-LIMESDR_OBJS= \
-lime_discovery.o \
-lime_protocol.o
+SOAPYSDR_SOURCES= \
+soapy_discovery.c \
+soapy_protocol.c
+SOAPYSDR_HEADERS= \
+soapy_discovery.h \
+soapy_protocol.h
+SOAPYSDR_OBJS= \
+soapy_discovery.o \
+soapy_protocol.o
 endif
 
 
@@ -159,13 +167,16 @@ ifeq ($(GPIO_INCLUDE),GPIO)
   GPIO_LIBS=-lwiringPi
   GPIO_SOURCES= \
   gpio.c \
-  encoder_menu.c
+  encoder_menu.c \
+  switch_menu.c
   GPIO_HEADERS= \
   gpio.h \
-  encoder_menu.h
+  encoder_menu.h \
+  switch_menu.h
   GPIO_OBJS= \
   gpio.o \
-  encoder_menu.o
+  encoder_menu.o \
+  switch_menu.o
 endif
 
 ifeq ($(I2C_INCLUDE),I2C)
@@ -210,8 +221,9 @@ AUDIO_LIBS=-lasound
 #AUDIO_LIBS=-lsoundio
 
 OPTIONS=-g -Wno-deprecated-declarations $(MIDI_OPTIONS) $(PURESIGNAL_OPTIONS) $(REMOTE_OPTIONS) $(USBOZY_OPTIONS) \
-       $(I2C_OPTIONS) $(GPIO_OPTIONS) $(LIMESDR_OPTIONS) $(FREEDV_OPTIONS) $(LOCALCW_OPTIONS) $(RADIOBERRY_OPTIONS) \
+       $(I2C_OPTIONS) $(GPIO_OPTIONS) $(SOAPYSDR_OPTIONS) $(FREEDV_OPTIONS) $(LOCALCW_OPTIONS) $(RADIOBERRY_OPTIONS) \
        $(PI_SDR_OPTIONS) $(PSK_OPTIONS) $(STEMLAB_OPTIONS) \
+        $(CONTROLLER2_OPTIONS) \
        -D GIT_DATE='"$(GIT_DATE)"' -D GIT_VERSION='"$(GIT_VERSION)"' $(DEBUG_OPTION) -O3
 
 LIBS=-lrt -lm -lwdsp -lpthread $(AUDIO_LIBS) $(USBOZY_LIBS) $(PSKLIBS) $(GTKLIBS) $(GPIO_LIBS) $(SOAPYSDRLIBS) $(FREEDVLIBS) $(STEMLAB_LIBS) $(MIDI_LIBS)
@@ -431,17 +443,17 @@ ext.o \
 error_handler.o \
 cwramp.o
 
-$(PROGRAM):  $(OBJS) $(REMOTE_OBJS) $(USBOZY_OBJS) $(LIMESDR_OBJS) $(FREEDV_OBJS) \
+$(PROGRAM):  $(OBJS) $(REMOTE_OBJS) $(USBOZY_OBJS) $(SOAPYSDR_OBJS) $(FREEDV_OBJS) \
                $(LOCALCW_OBJS) $(I2C_OBJS) $(GPIO_OBJS) $(PSK_OBJS) $(PURESIGNAL_OBJS) \
                $(MIDI_OBJS) $(STEMLAB_OBJS)
        $(LINK) -o $(PROGRAM) $(OBJS) $(REMOTE_OBJS) $(USBOZY_OBJS) $(I2C_OBJS) $(GPIO_OBJS) \
-               $(LIMESDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(PSK_OBJS) $(PURESIGNAL_OBJS) \
+               $(SOAPYSDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(PSK_OBJS) $(PURESIGNAL_OBJS) \
                $(MIDI_OBJS) $(STEMLAB_OBJS) $(LIBS)
 
-all:   prebuild  $(PROGRAM) $(HEADERS) $(REMOTE_HEADERS) $(USBOZY_HEADERS) $(LIMESDR_HEADERS) \
+all:   prebuild  $(PROGRAM) $(HEADERS) $(REMOTE_HEADERS) $(USBOZY_HEADERS) $(SOAPYSDR_HEADERS) \
        $(FREEDV_HEADERS) $(LOCALCW_HEADERS) $(I2C_HEADERS) $(GPIO_HEADERS) $(PSK_HEADERS) \
        $(PURESIGNAL_HEADERS) $(MIDI_HEADERS) $(STEMLAB_HEADERS) $(SOURCES) $(REMOTE_SOURCES) \
-       $(USBOZY_SOURCES) $(LIMESDR_SOURCES) $(FREEDV_SOURCES) $(I2C_SOURCES) $(GPIO_SOURCES) \
+       $(USBOZY_SOURCES) $(SOAPYSDR_SOURCES) $(FREEDV_SOURCES) $(I2C_SOURCES) $(GPIO_SOURCES) \
        $(PSK_SOURCES) $(PURESIGNAL_SOURCES) $(MIDI_SOURCES)$(STEMLAB_SOURCES)
 
 prebuild:
index 4cd0a1289a6999546c927814cb7cf06185298b9e..b64c3b8fc4f6ec218ca77c3b8f4488cbccd2c9c5 100644 (file)
@@ -109,6 +109,8 @@ void about_menu(GtkWidget *parent) {
   lines++;
   sprintf(text,"%s\n    Ken Hopper, N9VV, Testing and Documentation",text);
   lines++;
+  sprintf(text,"%s\n    Christoph v. Wüllen, DL1YCF, Pure Signal, Diversity, MIDI",text);
+  lines++;
   lines++;
 
   sprintf(text,"%s\n\nBuild date: %s", text, build_date);
@@ -117,7 +119,7 @@ void about_menu(GtkWidget *parent) {
   sprintf(text,"%s\nBuild version: %s", text, version);
   lines++;
 
-  sprintf(text,"%s\n\nWDSP v%d.%02d", text, GetWDSPVersion()/100, GetWDSPVersion()%100);
+  sprintf(text,"%s\nWDSP version: %d.%02d", text, GetWDSPVersion()/100, GetWDSPVersion()%100);
   lines++;
 
   sprintf(text,"%s\n\nDevice: %s Protocol %s v%d.%d",text,radio->name,radio->protocol==ORIGINAL_PROTOCOL?"1":"2",radio->software_version/10,radio->software_version%10);
diff --git a/adc.h b/adc.h
new file mode 100644 (file)
index 0000000..3585f0c
--- /dev/null
+++ b/adc.h
@@ -0,0 +1,72 @@
+/* Copyright (C)
+* 2018 - 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 ADC_H
+#define ADC_H
+
+enum {
+  AUTOMATIC=0,
+  MANUAL
+};
+
+enum {
+  BYPASS=0,
+  HPF_1_5,
+  HPF_6_5,
+  HPF_9_5,
+  HPF_13,
+  HPF_20
+};
+
+enum {
+  LPF_160=0,
+  LPF_80,
+  LPF_60_40,
+  LPF_30_20,
+  LPF_17_15,
+  LPF_12_10,
+  LPF_6
+};
+
+enum {
+  ANTENNA_1=0,
+  ANTENNA_2,
+  ANTENNA_3,
+  ANTENNA_XVTR,
+  ANTENNA_EXT1,
+  ANTENNA_EXT2
+};
+
+typedef struct _adc {
+  gint filters;
+  gint hpf;
+  gint lpf;
+  gint antenna;
+  gboolean dither;
+  gboolean random;
+  gboolean preamp;
+  gint attenuation;
+  gboolean enable_step_attenuation;
+#ifdef SOAPYSDR
+  gint *rx_gain;
+  gboolean agc;
+#endif
+} ADC;
+
+#endif
diff --git a/agc.h b/agc.h
index 2fcb04f9e857a32d4bfa1c30c96ed69cfc016936..7b8ed04674837b6d426daf5f9d0bfd70de611e60 100644 (file)
--- a/agc.h
+++ b/agc.h
@@ -25,5 +25,6 @@
 #define AGC_SLOW 2
 #define AGC_MEDIUM 3
 #define AGC_FAST 4
+#define AGC_LAST AGC_FAST
 
 #endif
index 3ea8d9b4dd41b10e20cd2df45be8dd2818a6a81a..291e71e52c9202efceba08c74f52f62b94bbf58c 100644 (file)
 #include "ant_menu.h"
 #include "band.h"
 #include "radio.h"
+#include "new_protocol.h"
+#ifdef SOAPYSDR
+#include "soapy_protocol.h"
+#endif
+
 
 static GtkWidget *parent_window=NULL;
 static GtkWidget *menu_b=NULL;
 static GtkWidget *dialog=NULL;
 static GtkWidget *grid=NULL;
+static GtkWidget *adc0_antenna_combo_box;
 
 static void cleanup() {
   if(dialog!=NULL) {
@@ -62,6 +68,18 @@ static void rx_ant_cb(GtkWidget *widget, gpointer data) {
   }
 }
 
+static void adc0_antenna_cb(GtkComboBox *widget,gpointer data) {
+  ADC *adc=(ADC *)data;
+  adc->antenna=gtk_combo_box_get_active(widget);
+  if(radio->protocol==NEW_PROTOCOL) {
+    schedule_high_priority();
+#ifdef SOAPYSDR
+  } else if(radio->device==SOAPYSDR_USB_DEVICE) {
+    soapy_protocol_set_rx_antenna(receiver[0],adc[0].antenna);
+#endif
+  }
+}
+
 static void rx_lime_ant_cb(GtkWidget *widget, gpointer data) {
   int ant=((uintptr_t)data)&0xF;
   BAND *band=band_get_current_band();
@@ -277,14 +295,21 @@ void ant_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 *hf_rb=gtk_radio_button_new_with_label(NULL,"HF");
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hf_rb),TRUE);
-  g_signal_connect(hf_rb,"toggled",G_CALLBACK(hf_rb_cb),NULL);
-  gtk_grid_attach(GTK_GRID(grid),hf_rb,1,0,1,1);
+#ifdef SOAPYSDR
+  if(radio->device!=SOAPYSDR_USB_DEVICE) {
+#endif
+    GtkWidget *hf_rb=gtk_radio_button_new_with_label(NULL,"HF");
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hf_rb),TRUE);
+    g_signal_connect(hf_rb,"toggled",G_CALLBACK(hf_rb_cb),NULL);
+    gtk_grid_attach(GTK_GRID(grid),hf_rb,1,0,1,1);
+
+    GtkWidget *xvtr_rb=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(hf_rb),"XVTR");
+    g_signal_connect(xvtr_rb,"toggled",G_CALLBACK(xvtr_rb_cb),NULL);
+    gtk_grid_attach(GTK_GRID(grid),xvtr_rb,2,0,1,1);
 
-  GtkWidget *xvtr_rb=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(hf_rb),"XVTR");
-  g_signal_connect(xvtr_rb,"toggled",G_CALLBACK(xvtr_rb_cb),NULL);
-  gtk_grid_attach(GTK_GRID(grid),xvtr_rb,2,0,1,1);
+#ifdef SOAPYSDR
+  }
+#endif
 
   if ((protocol == NEW_PROTOCOL      && (device == NEW_DEVICE_HERMES || device == NEW_DEVICE_ANGELIA || device == NEW_DEVICE_ORION)) ||
       (protocol == ORIGINAL_PROTOCOL && (device == DEVICE_HERMES     || device == DEVICE_ANGELIA     || device == DEVICE_ORION))) {
@@ -360,37 +385,27 @@ void ant_menu(GtkWidget *parent) {
     show_hf();
   }
 
-#ifdef LIMESDR
-  if(protocol==LIMESDR_PROTOCOL) {
-    BAND *band=band_get_current_band();
-
-    GtkWidget *rx1_none=gtk_radio_button_new_with_label(NULL,"RX 1: NONE");
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx1_none), band->alexRxAntenna==0);
-    gtk_widget_show(rx1_none);
-    gtk_grid_attach(GTK_GRID(grid),rx1_none,0,1,1,1);
-    g_signal_connect(rx1_none,"pressed",G_CALLBACK(rx_lime_ant_cb),(gpointer)(long)0);
-
-    GtkWidget *rx1_lnah=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(rx1_none),"RX1: LNAH");
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx1_lnah), band->alexRxAntenna==1);
-    gtk_widget_show(rx1_lnah);
-    gtk_grid_attach(GTK_GRID(grid),rx1_lnah,0,2,1,1);
-    g_signal_connect(rx1_lnah,"pressed",G_CALLBACK(rx_lime_ant_cb),(gpointer)(long)+1);
-
-    GtkWidget *rx1_lnal=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(rx1_lnah),"RX1: LNAL");
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx1_lnal), band->alexRxAntenna==2);
-    gtk_widget_show(rx1_lnal);
-    gtk_grid_attach(GTK_GRID(grid),rx1_lnal,0,3,1,1);
-    g_signal_connect(rx1_lnal,"pressed",G_CALLBACK(rx_lime_ant_cb),(gpointer)(long)2);
-
-    GtkWidget *rx1_lnaw=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(rx1_lnal),"RX1: LNAW");
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx1_lnaw), band->alexRxAntenna==3);
-    gtk_widget_show(rx1_lnaw);
-    gtk_grid_attach(GTK_GRID(grid),rx1_lnaw,0,4,1,1);
-    g_signal_connect(rx1_lnaw,"pressed",G_CALLBACK(rx_lime_ant_cb),(gpointer)(long)3);
+#ifdef SOAPYSDR
+  if(radio->device==SOAPYSDR_USB_DEVICE) {
+    int i;
+
+g_print("rx_antennas=%d\n",radio->info.soapy.rx_antennas);
+    if(radio->info.soapy.rx_antennas>0) {
+      GtkWidget *antenna_label=gtk_label_new("RX Antenna:");
+      gtk_grid_attach(GTK_GRID(grid),antenna_label,0,1,1,1);
+      adc0_antenna_combo_box=gtk_combo_box_text_new();
+
+      for(i=0;i<radio->info.soapy.rx_antennas;i++) {
+        gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(adc0_antenna_combo_box),NULL,radio->info.soapy.rx_antenna[i]);
+      }
+
+      gtk_combo_box_set_active(GTK_COMBO_BOX(adc0_antenna_combo_box),adc[0].antenna);
+      g_signal_connect(adc0_antenna_combo_box,"changed",G_CALLBACK(adc0_antenna_cb),&adc[0]);
+      gtk_grid_attach(GTK_GRID(grid),adc0_antenna_combo_box,1,1,1,1);
+    }
   }
 #endif
 
-
   gtk_container_add(GTK_CONTAINER(content),grid);
 
   sub_menu=dialog;
diff --git a/audio.c b/audio.c
index 4c98c8d28a70ba67cd143d5f714972a2ebd8a86f..2d8e541eb59279919c7b25f34feb9ad8c7e8410c 100644 (file)
--- a/audio.c
+++ b/audio.c
 
 #include <alsa/asoundlib.h>
 
-#include "new_protocol.h"
-#include "old_protocol.h"
 #include "radio.h"
 #include "receiver.h"
+#include "transmitter.h"
 #include "audio.h"
 #include "mode.h"
+#include "new_protocol.h"
+#include "old_protocol.h"
+#ifdef SOAPYSDR
+#include "soapy_protocol.h"
+#endif
 
 int audio = 0;
-int audio_buffer_size = 256; // samples (both left and right)
+long 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;
@@ -313,7 +317,7 @@ void audio_close_input() {
 //
 int cw_audio_write(double sample){
   snd_pcm_sframes_t delay;
-  int error;
+  long rc;
   long trim;
   short shortsample;
        
@@ -330,24 +334,23 @@ int cw_audio_write(double sample){
 
       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;
+*/
+      if ((rc = snd_pcm_writei (rx->playback_handle, rx->playback_buffer, audio_buffer_size-trim)) != audio_buffer_size-trim) {
+        if(rc<0) {
+          if(rc==-EPIPE) {
+            if ((rc = snd_pcm_prepare (rx->playback_handle)) < 0) {
+              fprintf (stderr, "audio_write: cannot prepare audio interface for use %d (%s)\n", rc, snd_strerror (rc));
+              return -1;
+            } else {
+              // ignore short write
+            }
           }
         }
       }
@@ -363,7 +366,7 @@ int cw_audio_write(double sample){
 //
 int audio_write(RECEIVER *rx,short left_sample,short right_sample) {
   snd_pcm_sframes_t delay;
-  int error;
+  long rc;
   long trim;
   int mode=transmitter->mode;
   //
@@ -374,7 +377,12 @@ int audio_write(RECEIVER *rx,short left_sample,short right_sample) {
   // If *not* doing CW, the stream continues because we might wish
   // to listen to this rx while transmitting.
   //
-  if (rx == active_receiver && isTransmitting() && (mode==modeCWU || mode==modeCWL)) return 0;
+
+  if (rx == active_receiver && isTransmitting() && (mode==modeCWU || mode==modeCWL)) {
+    fprintf(stderr,"returning from audio_write\n");
+    rx->playback_offset=0;
+    return 0;
+  }
 
   if(rx->playback_handle!=NULL && rx->playback_buffer!=NULL) {
     rx->playback_buffer[rx->playback_offset++]=right_sample;
@@ -386,24 +394,28 @@ int audio_write(RECEIVER *rx,short left_sample,short right_sample) {
 
       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);
+fprintf(stderr,"audio delay=%ld trim=%ld audio_buffer_size=%d\n",delay,trim,audio_buffer_size);
+          if(trim>=audio_buffer_size) {
+            rx->playback_offset=0;
+            return 0;
+          }
         }
       }
-
-      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;
+*/
+      if ((rc = snd_pcm_writei (rx->playback_handle, rx->playback_buffer, audio_buffer_size-trim)) != audio_buffer_size-trim) {
+        if(rc<0) {
+          if(rc==-EPIPE) {
+            if ((rc = snd_pcm_prepare (rx->playback_handle)) < 0) {
+              fprintf (stderr, "audio_write: cannot prepare audio interface for use %d (%s)\n", rc, snd_strerror (rc));
+              rx->playback_offset=0;
+              return -1;
+            }
+          } else {
+            // ignore short write
           }
         }
       }
@@ -441,6 +453,11 @@ fprintf(stderr,"mic_read_thread: mic_buffer_size=%d\n",mic_buffer_size);
         case NEW_PROTOCOL:
           new_protocol_process_local_mic(mic_buffer,1);
           break;
+#ifdef SOAPYSDR
+        case SOAPYSDR_PROTOCOL:
+          soapy_protocol_process_local_mic(mic_buffer);
+          break;
+#endif
         default:
           break;
       }
diff --git a/band.c b/band.c
index 85d88b11c1792c02a1a64785fc2f331f7505b443..bc54e6821469555e4249d036661045284f3d6030 100644 (file)
--- a/band.c
+++ b/band.c
@@ -122,7 +122,7 @@ BANDSTACK_ENTRY bandstack_entries6[] =
      {50125000LL,modeUSB,filterF5,200,2800,200,2800},
      {50200000LL,modeUSB,filterF5,200,2800,200,2800}};
 
-#ifdef LIMESDR
+#ifdef SOAPYSDR
 BANDSTACK_ENTRY bandstack_entries70[] =
     {{70010000LL,modeCWU,filterF6,200,2800,200,2800},
      {70200000LL,modeUSB,filterF5,200,2800,200,2800},
@@ -198,7 +198,7 @@ BANDSTACK bandstack15={3,1,bandstack_entries15};
 BANDSTACK bandstack12={3,1,bandstack_entries12};
 BANDSTACK bandstack10={3,1,bandstack_entries10};
 BANDSTACK bandstack6={3,1,bandstack_entries6};
-#ifdef LIMESDR
+#ifdef SOAPYSDR
 BANDSTACK bandstack70={3,1,bandstack_entries70};
 BANDSTACK bandstack144={6,1,bandstack_entries144};
 BANDSTACK bandstack220={3,1,bandstack_entries220};
@@ -276,7 +276,7 @@ BAND bands[BANDS+XVTRS] =
      {"12",&bandstack12,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,24890000LL,24990000LL,0LL,0LL,0},
      {"10",&bandstack10,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,28000000LL,29700000LL,0LL,0LL,0},
      {"6",&bandstack6,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,50000000LL,54000000LL,0LL,0LL,0},
-#ifdef LIMESDR
+#ifdef SOAPYSDR
      {"70",&bandstack70,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0LL,0},
      {"144",&bandstack144,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,144000000LL,148000000LL,0LL,0LL,0},
      {"220",&bandstack144,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,222000000LL,224980000LL,0LL,0LL,0},
diff --git a/band.h b/band.h
index 937b7c14f620f9f0df1443d5186c6fbb61ec9ab1..8e1762e0b2d3d96a2cdb8948f12a6fd730c086b1 100644 (file)
--- a/band.h
+++ b/band.h
@@ -34,7 +34,7 @@
 #define band12 8
 #define band10 9
 #define band6 10
-#ifdef LIMESDR
+#ifdef SOAPYSDR
 #define band70 11
 #define band220 13
 #define band430 14
@@ -76,6 +76,8 @@ struct _BAND {
     long long frequencyMax;
     long long frequencyLO;
     long long errorLO;
+    long long txFrequencyLO;
+    long long txErrorLO;
     int disablePA;
 };
 
index f1433d126b7d767d14c68e3f68629a072d0dc161..c89cefd3aa544e1d496ea28c18a9bccccd64a62d 100644 (file)
@@ -103,8 +103,8 @@ void band_menu(GtkWidget *parent) {
   gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
 
   for(i=0;i<BANDS+XVTRS;i++) {
-#ifdef LIMESDR
-    if(protocol!=LIMESDR_PROTOCOL) {
+#ifdef SOAPYSDR
+    if(protocol!=SOAPYSDR_PROTOCOL) {
       if(i>=band70 && i<=band3400) {
         continue;
       }
index f8fbd93636eca092689cd40704d47ba5803d3343..9ac48f1cd1544960eefc0255ac592cc5f51ba2bb 100644 (file)
@@ -44,12 +44,6 @@ 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;
@@ -62,6 +56,20 @@ static   GtkWidget *E3_a;
 static   GtkWidget *E3_b_label;
 static   GtkWidget *E3_b;
 static   GtkWidget *b_enable_E3_pullup;
+static GtkWidget *b_enable_E4_encoder;
+static   GtkWidget *E4_a_label;
+static   GtkWidget *E4_a;
+static   GtkWidget *E4_b_label;
+static   GtkWidget *E4_b;
+static   GtkWidget *b_enable_E4_pullup;
+#ifdef CONTROLLER2
+static GtkWidget *b_enable_E5_encoder;
+static   GtkWidget *E5_a_label;
+static   GtkWidget *E5_a;
+static   GtkWidget *E5_b_label;
+static   GtkWidget *E5_b;
+static   GtkWidget *b_enable_E5_pullup;
+#endif
 static GtkWidget *b_enable_mox;
 static   GtkWidget *mox_label;
 static   GtkWidget *mox;
@@ -113,11 +121,6 @@ static gboolean save_cb (GtkWidget *widget, GdkEventButton *event, gpointer data
     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));
@@ -128,6 +131,13 @@ static gboolean save_cb (GtkWidget *widget, GdkEventButton *event, gpointer data
     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_E4_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E4_encoder))?1:0;
+    E4_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E4_a));
+    E4_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E4_b));
+    ENABLE_E4_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E4_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));
 
@@ -151,6 +161,7 @@ static gboolean save_cb (GtkWidget *widget, GdkEventButton *event, gpointer data
 
     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
     ENABLE_CW_BUTTONS=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_cwlr))?1:0;
     CW_ACTIVE_LOW=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_cw_active_low))?1:0;
@@ -213,37 +224,6 @@ void configure_gpio(GtkWidget *parent) {
   gtk_grid_attach(GTK_GRID(grid),b_enable_vfo_pullup,5,y,1,1);
 
 
-  y++;
-
-  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);
-
-  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);
-
-  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);
-
-  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);
-
-  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);
-
-  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++;
 
   b_enable_E2_encoder=gtk_check_button_new_with_label("Enable E2");
@@ -306,8 +286,70 @@ void configure_gpio(GtkWidget *parent) {
   gtk_grid_attach(GTK_GRID(grid),b_enable_E3_pullup,5,y,1,1);
 
 
+
   y++;
+  b_enable_E4_encoder=gtk_check_button_new_with_label("Enable E4");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_E4_encoder), ENABLE_E4_ENCODER);
+  gtk_widget_show(b_enable_E4_encoder);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_E4_encoder,0,y,1,1);
+
+  E4_a_label=gtk_label_new("GPIO A:");
+  gtk_widget_show(E4_a_label);
+  gtk_grid_attach(GTK_GRID(grid),E4_a_label,1,y,1,1);
+
+  E4_a=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(E4_a),E4_ENCODER_A);
+  gtk_widget_show(E4_a);
+  gtk_grid_attach(GTK_GRID(grid),E4_a,2,y,1,1);
+
+  E4_b_label=gtk_label_new("GPIO B:");
+  gtk_widget_show(E4_b_label);
+  gtk_grid_attach(GTK_GRID(grid),E4_b_label,3,y,1,1);
+
+  E4_b=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(E4_b),E4_ENCODER_B);
+  gtk_widget_show(E4_b);
+  gtk_grid_attach(GTK_GRID(grid),E4_b,4,y,1,1);
+
+  b_enable_E4_pullup=gtk_check_button_new_with_label("Enable Pull-up");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_E4_pullup), ENABLE_E4_PULLUP);
+  gtk_widget_show(b_enable_E4_pullup);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_E4_pullup,5,y,1,1);
+
+#ifdef CONTROLLER2
+  y++;
+  b_enable_E5_encoder=gtk_check_button_new_with_label("Enable E5");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_E5_encoder), ENABLE_E5_ENCODER);
+  gtk_widget_show(b_enable_E5_encoder);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_E5_encoder,0,y,1,1);
+
+  E5_a_label=gtk_label_new("GPIO A:");
+  gtk_widget_show(E5_a_label);
+  gtk_grid_attach(GTK_GRID(grid),E5_a_label,1,y,1,1);
+
+  E5_a=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(E5_a),E5_ENCODER_A);
+  gtk_widget_show(E5_a);
+  gtk_grid_attach(GTK_GRID(grid),E5_a,2,y,1,1);
+
+  E5_b_label=gtk_label_new("GPIO B:");
+  gtk_widget_show(E5_b_label);
+  gtk_grid_attach(GTK_GRID(grid),E5_b_label,3,y,1,1);
+
+  E5_b=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(E5_b),E5_ENCODER_B);
+  gtk_widget_show(E5_b);
+  gtk_grid_attach(GTK_GRID(grid),E5_b,4,y,1,1);
+
+  b_enable_E5_pullup=gtk_check_button_new_with_label("Enable Pull-up");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_E5_pullup), ENABLE_E5_PULLUP);
+  gtk_widget_show(b_enable_E5_pullup);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_E5_pullup,5,y,1,1);
+
+#endif
 
+#ifndef CONTROLLER2
+  y++;
   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);
@@ -337,6 +379,7 @@ void configure_gpio(GtkWidget *parent) {
   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);
+#endif
 
 #ifdef LOCALCW
   // With LOCALCW, the menu got too long (does not fit on the screen)
@@ -360,6 +403,7 @@ void configure_gpio(GtkWidget *parent) {
 
   y++;
 
+#ifndef CONTROLLER2
   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);
@@ -373,6 +417,7 @@ void configure_gpio(GtkWidget *parent) {
   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);
+#endif
 
 #ifdef LOCALCW
   cwr_label=gtk_label_new("CWR GPIO:");
@@ -392,6 +437,7 @@ void configure_gpio(GtkWidget *parent) {
 
   y++;
 
+#ifndef CONTROLLER2
   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);
@@ -405,6 +451,7 @@ void configure_gpio(GtkWidget *parent) {
   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);
+#endif
 
 #ifdef LOCALCW
   cws_label=gtk_label_new("  SideTone GPIO:");
@@ -423,6 +470,7 @@ void configure_gpio(GtkWidget *parent) {
 #endif
   y++;
 
+#ifndef CONTROLLER2
   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);
@@ -484,6 +532,7 @@ void configure_gpio(GtkWidget *parent) {
   gtk_spin_button_set_value (GTK_SPIN_BUTTON(function),FUNCTION_BUTTON);
   gtk_widget_show(function);
   gtk_grid_attach(GTK_GRID(grid),function,2,y,1,1);
+#endif
 
   y++;
 
index 513f2551990b6b99eec5d5a81b975bef9e0977b9..15e8248a0c26c45aaa675b292be183f98ea66558 100644 (file)
@@ -17,6 +17,7 @@
 *
 */
 
+#include <gtk/gtk.h>
 #include "discovered.h"
 
 int selected_device=0;
index 7c14ec0ad0c884a56461ca04920e5bd5888c22be..3309f88fff825d54e4f789a3175d471c600325b2 100644 (file)
@@ -21,7 +21,7 @@
 #define _DISCOVERED_H
 
 #include <netinet/in.h>
-#ifdef LIMESDR
+#ifdef SOAPYSDR
 #include <SoapySDR/Device.h>
 #endif
 
@@ -51,8 +51,8 @@
 #define NEW_DEVICE_ORION2 5
 #define NEW_DEVICE_HERMES_LITE 6
 
-#ifdef LIMESDR
-#define LIMESDR_USB_DEVICE 0
+#ifdef SOAPYSDR
+#define SOAPYSDR_USB_DEVICE 0
 #endif
 
 #define STATE_AVAILABLE 2
@@ -60,8 +60,8 @@
 
 #define ORIGINAL_PROTOCOL 0
 #define NEW_PROTOCOL 1
-#ifdef LIMESDR
-#define LIMESDR_PROTOCOL 2
+#ifdef SOAPYSDR
+#define SOAPYSDR_PROTOCOL 2
 #endif
 
 #ifdef REMOTE
@@ -90,6 +90,11 @@ struct _DISCOVERED {
     char name[64];
     int software_version;
     int status;
+    int supported_receivers;
+    int supported_transmitters;
+    int adcs;
+    double frequency_min;
+    double frequency_max;
     union {
       struct network {
         unsigned char mac_address[6];
@@ -100,9 +105,24 @@ struct _DISCOVERED {
         struct sockaddr_in interface_netmask;
         char interface_name[64];
       } network;
-#ifdef LIMESDR
+#ifdef SOAPYSDR
       struct soapy {
-        SoapySDRKwargs *args;
+        int rtlsdr_count;
+        int sample_rate;
+        size_t rx_channels;
+        size_t rx_gains;
+        char **rx_gain;
+        SoapySDRRange *rx_range;
+        gboolean rx_has_automatic_gain;
+        gboolean rx_has_automatic_dc_offset_correction;
+        size_t rx_antennas;
+        char **rx_antenna;
+        size_t tx_channels;
+        size_t tx_gains;
+        char **tx_gain;
+        SoapySDRRange *tx_range;
+        size_t tx_antennas;
+        char **tx_antenna;
       } soapy;
 #endif
     } info;
index 5de6a0aa26f4d251e5ec9a7ab19eb956490ca196..5252bdd063b4aaaa9fd24bd64751d68f746405d6 100644 (file)
@@ -31,6 +31,9 @@
 #include "discovered.h"
 #include "old_discovery.h"
 #include "new_discovery.h"
+#ifdef SOAPYSDR
+#include "soapy_discovery.h"
+#endif
 #include "main.h"
 #include "radio.h"
 #ifdef USBOZY
@@ -180,9 +183,9 @@ void discovery() {
   status_text("Protocol 2 ... Discovering Devices");
   new_discovery();
 
-#ifdef LIMESDR
-  status_text("LimeSDR ... Discovering Devices");
-  lime_discovery();
+#ifdef SOAPYSDR
+  status_text("SoapySDR ... Discovering Devices");
+  soapy_discovery();
 #endif
 
   status_text("Discovery");
@@ -293,10 +296,10 @@ fprintf(stderr,"%p Protocol=%d name=%s\n",d,d->protocol,d->name);
           }
 #endif
           break;
-#ifdef LIMESDR
-        case LIMESDR_PROTOCOL:
-          sprintf(text,"%s",
-                        d->name);
+#ifdef SOAPYSDR
+        case SOAPYSDR_PROTOCOL:
+          sprintf(text,"%s SOAPY_SDR v%d.%d.%d USB",
+                        d->name,d->software_version/100,(d->software_version%100)/10,d->software_version%10);
           break;
 #endif
 #ifdef STEMLAB_DISCOVERY
@@ -334,11 +337,17 @@ fprintf(stderr,"%p Protocol=%d name=%s\n",d,d->protocol,d->name);
         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 SOAPYSDR
+      if(d->device!=SOAPYSDR_USB_DEVICE) {
+#endif
+        // 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 SOAPYSDR
       }
+#endif
 
 #ifdef STEMLAB_DISCOVERY
       if (d->protocol == STEMLAB_PROTOCOL) {
index d9a5276d7e76995813393e46b31d438ce9dad3bb..6efbe0a33002ef24c878f9f5d9cddfff30a9e4b4 100644 (file)
@@ -86,6 +86,10 @@ static void panadapter_low_value_changed_cb(GtkWidget *widget, gpointer data) {
   active_receiver->panadapter_low=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
 }
 
+static void panadapter_step_value_changed_cb(GtkWidget *widget, gpointer data) {
+  active_receiver->panadapter_step=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
+}
+
 static void waterfall_high_value_changed_cb(GtkWidget *widget, gpointer data) {
   active_receiver->waterfall_high=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
 }
@@ -113,12 +117,12 @@ static void display_sliders_cb(GtkWidget *widget, gpointer data) {
   reconfigure_radio();
 }
 
-/*
+
 static void display_toolbar_cb(GtkWidget *widget, gpointer data) {
   display_toolbar=display_toolbar==1?0:1;
   reconfigure_radio();
 }
-*/
+
 void display_menu(GtkWidget *parent) {
   int i;
 
@@ -145,193 +149,269 @@ void display_menu(GtkWidget *parent) {
   //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
   //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
 
+  int col=0;
+  int row=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,0,0,1,1);
+  gtk_grid_attach(GTK_GRID(grid),close_b,col,row,1,1);
+
+  row++;
+  col=0;
 
   GtkWidget *filled_b=gtk_check_button_new_with_label("Fill Panadapter");
   //gtk_widget_override_font(filled_b, pango_font_description_from_string("Arial 18"));
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (filled_b), display_filled);
   gtk_widget_show(filled_b);
-  gtk_grid_attach(GTK_GRID(grid),filled_b,0,1,1,1);
+  gtk_grid_attach(GTK_GRID(grid),filled_b,col,row,1,1);
   g_signal_connect(filled_b,"toggled",G_CALLBACK(filled_cb),NULL);
 
+  row++;
+  col=0;
+
   GtkWidget *frames_per_second_label=gtk_label_new("Frames Per Second: ");
   //gtk_widget_override_font(frames_per_second_label, pango_font_description_from_string("Arial 18"));
   gtk_widget_show(frames_per_second_label);
-  gtk_grid_attach(GTK_GRID(grid),frames_per_second_label,0,2,1,1);
+  gtk_grid_attach(GTK_GRID(grid),frames_per_second_label,col,row,1,1);
+
+  col++;
 
   GtkWidget *frames_per_second_r=gtk_spin_button_new_with_range(1.0,100.0,1.0);
   //gtk_widget_override_font(frames_per_second_r, pango_font_description_from_string("Arial 18"));
   gtk_spin_button_set_value(GTK_SPIN_BUTTON(frames_per_second_r),(double)updates_per_second);
   gtk_widget_show(frames_per_second_r);
-  gtk_grid_attach(GTK_GRID(grid),frames_per_second_r,1,2,1,1);
+  gtk_grid_attach(GTK_GRID(grid),frames_per_second_r,col,row,1,1);
   g_signal_connect(frames_per_second_r,"value_changed",G_CALLBACK(frames_per_second_value_changed_cb),NULL);
 
+  row++;
+  col=0;
 
   GtkWidget *panadapter_high_label=gtk_label_new("Panadapter High: ");
   //gtk_widget_override_font(panadapter_high_label, pango_font_description_from_string("Arial 18"));
   gtk_widget_show(panadapter_high_label);
-  gtk_grid_attach(GTK_GRID(grid),panadapter_high_label,0,3,1,1);
+  gtk_grid_attach(GTK_GRID(grid),panadapter_high_label,col,row,1,1);
+
+  col++;
 
   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)active_receiver->panadapter_high);
   gtk_widget_show(panadapter_high_r);
-  gtk_grid_attach(GTK_GRID(grid),panadapter_high_r,1,3,1,1);
+  gtk_grid_attach(GTK_GRID(grid),panadapter_high_r,col,row,1,1);
   g_signal_connect(panadapter_high_r,"value_changed",G_CALLBACK(panadapter_high_value_changed_cb),NULL);
 
+  row++;
+  col=0;
+
   GtkWidget *panadapter_low_label=gtk_label_new("Panadapter Low: ");
   //gtk_widget_override_font(panadapter_low_label, pango_font_description_from_string("Arial 18"));
   gtk_widget_show(panadapter_low_label);
-  gtk_grid_attach(GTK_GRID(grid),panadapter_low_label,0,4,1,1);
+  gtk_grid_attach(GTK_GRID(grid),panadapter_low_label,col,row,1,1);
+
+  col++;
 
   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)active_receiver->panadapter_low);
   gtk_widget_show(panadapter_low_r);
-  gtk_grid_attach(GTK_GRID(grid),panadapter_low_r,1,4,1,1);
+  gtk_grid_attach(GTK_GRID(grid),panadapter_low_r,col,row,1,1);
   g_signal_connect(panadapter_low_r,"value_changed",G_CALLBACK(panadapter_low_value_changed_cb),NULL);
 
+  row++;
+  col=0;
+
+  GtkWidget *panadapter_step_label=gtk_label_new("Panadapter Step: ");
+  //gtk_widget_override_font(panadapter_step_label, pango_font_description_from_string("Arial 18"));
+  gtk_widget_show(panadapter_step_label);
+  gtk_grid_attach(GTK_GRID(grid),panadapter_step_label,col,row,1,1);
+
+  col++;
+
+  GtkWidget *panadapter_step_r=gtk_spin_button_new_with_range(1.0,20.0,1.0);
+  //gtk_widget_override_font(panadapter_step_r, pango_font_description_from_string("Arial 18"));
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON(panadapter_step_r),(double)active_receiver->panadapter_step);
+  gtk_widget_show(panadapter_step_r);
+  gtk_grid_attach(GTK_GRID(grid),panadapter_step_r,col,row,1,1);
+  g_signal_connect(panadapter_step_r,"value_changed",G_CALLBACK(panadapter_step_value_changed_cb),NULL);
+
+  row++;
+  col=0;
+
   GtkWidget *waterfall_automatic_label=gtk_label_new("Waterfall Automatic: ");
   //gtk_widget_override_font(waterfall_automatic_label, pango_font_description_from_string("Arial 18"));
   gtk_widget_show(waterfall_automatic_label);
-  gtk_grid_attach(GTK_GRID(grid),waterfall_automatic_label,0,5,1,1);
+  gtk_grid_attach(GTK_GRID(grid),waterfall_automatic_label,col,row,1,1);
+
+  col++;
 
   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), active_receiver->waterfall_automatic);
   gtk_widget_show(waterfall_automatic_b);
-  gtk_grid_attach(GTK_GRID(grid),waterfall_automatic_b,1,5,1,1);
+  gtk_grid_attach(GTK_GRID(grid),waterfall_automatic_b,col,row,1,1);
   g_signal_connect(waterfall_automatic_b,"toggled",G_CALLBACK(waterfall_automatic_cb),NULL);
 
+  row++;
+  col=0;
+
   GtkWidget *waterfall_high_label=gtk_label_new("Waterfall High: ");
   //gtk_widget_override_font(waterfall_high_label, pango_font_description_from_string("Arial 18"));
   gtk_widget_show(waterfall_high_label);
-  gtk_grid_attach(GTK_GRID(grid),waterfall_high_label,0,6,1,1);
+  gtk_grid_attach(GTK_GRID(grid),waterfall_high_label,col,row,1,1);
+
+  col++;
 
   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)active_receiver->waterfall_high);
   gtk_widget_show(waterfall_high_r);
-  gtk_grid_attach(GTK_GRID(grid),waterfall_high_r,1,6,1,1);
+  gtk_grid_attach(GTK_GRID(grid),waterfall_high_r,col,row,1,1);
   g_signal_connect(waterfall_high_r,"value_changed",G_CALLBACK(waterfall_high_value_changed_cb),NULL);
 
+  row++;
+  col=0;
+
   GtkWidget *waterfall_low_label=gtk_label_new("Waterfall Low: ");
   //gtk_widget_override_font(waterfall_low_label, pango_font_description_from_string("Arial 18"));
   gtk_widget_show(waterfall_low_label);
-  gtk_grid_attach(GTK_GRID(grid),waterfall_low_label,0,7,1,1);
+  gtk_grid_attach(GTK_GRID(grid),waterfall_low_label,col,row,1,1);
+
+  col++;
 
   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)active_receiver->waterfall_low);
   gtk_widget_show(waterfall_low_r);
-  gtk_grid_attach(GTK_GRID(grid),waterfall_low_r,1,7,1,1);
+  gtk_grid_attach(GTK_GRID(grid),waterfall_low_r,col,row,1,1);
   g_signal_connect(waterfall_low_r,"value_changed",G_CALLBACK(waterfall_low_value_changed_cb),NULL);
 
+  col=2;
+  row=1;
+
   GtkWidget *detector_mode_label=gtk_label_new("Detector: ");
   //gtk_widget_override_font(detector_mode_label, pango_font_description_from_string("Arial 18"));
   gtk_widget_show(detector_mode_label);
-  gtk_grid_attach(GTK_GRID(grid),detector_mode_label,2,1,1,1);
+  gtk_grid_attach(GTK_GRID(grid),detector_mode_label,col,row,1,1);
+
+  row++;
 
   GtkWidget *detector_mode_peak=gtk_radio_button_new_with_label(NULL,"Peak");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (detector_mode_peak), display_detector_mode==DETECTOR_MODE_PEAK);
   gtk_widget_show(detector_mode_peak);
-  gtk_grid_attach(GTK_GRID(grid),detector_mode_peak,2,2,1,1);
+  gtk_grid_attach(GTK_GRID(grid),detector_mode_peak,col,row,1,1);
   g_signal_connect(detector_mode_peak,"pressed",G_CALLBACK(detector_mode_cb),(gpointer *)DETECTOR_MODE_PEAK);
 
+  row++;
+
   GtkWidget *detector_mode_rosenfell=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(detector_mode_peak),"Rosenfell");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (detector_mode_rosenfell), display_detector_mode==DETECTOR_MODE_ROSENFELL);
   gtk_widget_show(detector_mode_rosenfell);
-  gtk_grid_attach(GTK_GRID(grid),detector_mode_rosenfell,2,3,1,1);
+  gtk_grid_attach(GTK_GRID(grid),detector_mode_rosenfell,col,row,1,1);
   g_signal_connect(detector_mode_rosenfell,"pressed",G_CALLBACK(detector_mode_cb),(gpointer *)DETECTOR_MODE_ROSENFELL);
 
+  row++;
+
   GtkWidget *detector_mode_average=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(detector_mode_rosenfell),"Average");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (detector_mode_average), display_detector_mode==DETECTOR_MODE_AVERAGE);
   gtk_widget_show(detector_mode_average);
-  gtk_grid_attach(GTK_GRID(grid),detector_mode_average,2,4,1,1);
+  gtk_grid_attach(GTK_GRID(grid),detector_mode_average,col,row,1,1);
   g_signal_connect(detector_mode_average,"pressed",G_CALLBACK(detector_mode_cb),(gpointer *)DETECTOR_MODE_AVERAGE);
 
-   GtkWidget *detector_mode_sample=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(detector_mode_average),"Sample");
+  row++;
+
+  GtkWidget *detector_mode_sample=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(detector_mode_average),"Sample");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (detector_mode_sample), display_detector_mode==DETECTOR_MODE_SAMPLE);
   gtk_widget_show(detector_mode_sample);
-  gtk_grid_attach(GTK_GRID(grid),detector_mode_sample,2,5,1,1);
+  gtk_grid_attach(GTK_GRID(grid),detector_mode_sample,col,row,1,1);
   g_signal_connect(detector_mode_sample,"pressed",G_CALLBACK(detector_mode_cb),(gpointer *)DETECTOR_MODE_SAMPLE);
 
 
+  col=3;
+  row=1;
 
   GtkWidget *average_mode_label=gtk_label_new("Averaging: ");
   //gtk_widget_override_font(average_mode_label, pango_font_description_from_string("Arial 18"));
   gtk_widget_show(average_mode_label);
-  gtk_grid_attach(GTK_GRID(grid),average_mode_label,3,1,1,1);
+  gtk_grid_attach(GTK_GRID(grid),average_mode_label,col,row,1,1);
+
+  row++;
 
   GtkWidget *average_mode_none=gtk_radio_button_new_with_label(NULL,"None");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (average_mode_none), display_detector_mode==AVERAGE_MODE_NONE);
   gtk_widget_show(average_mode_none);
-  gtk_grid_attach(GTK_GRID(grid),average_mode_none,3,2,1,1);
+  gtk_grid_attach(GTK_GRID(grid),average_mode_none,col,row,1,1);
   g_signal_connect(average_mode_none,"pressed",G_CALLBACK(average_mode_cb),(gpointer *)AVERAGE_MODE_NONE);
 
+  row++;
+
   GtkWidget *average_mode_recursive=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(average_mode_none),"Recursive");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (average_mode_recursive), display_average_mode==AVERAGE_MODE_RECURSIVE);
   gtk_widget_show(average_mode_recursive);
-  gtk_grid_attach(GTK_GRID(grid),average_mode_recursive,3,3,1,1);
+  gtk_grid_attach(GTK_GRID(grid),average_mode_recursive,col,row,1,1);
   g_signal_connect(average_mode_recursive,"pressed",G_CALLBACK(average_mode_cb),(gpointer *)AVERAGE_MODE_RECURSIVE);
 
+  row++;
+
   GtkWidget *average_mode_time_window=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(average_mode_recursive),"Time Window");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (average_mode_time_window), display_average_mode==AVERAGE_MODE_TIME_WINDOW);
   gtk_widget_show(average_mode_time_window);
-  gtk_grid_attach(GTK_GRID(grid),average_mode_time_window,3,4,1,1);
+  gtk_grid_attach(GTK_GRID(grid),average_mode_time_window,col,row,1,1);
   g_signal_connect(average_mode_time_window,"pressed",G_CALLBACK(average_mode_cb),(gpointer *)AVERAGE_MODE_TIME_WINDOW);
 
+  row++;
+
   GtkWidget *average_mode_log_recursive=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(average_mode_time_window),"Log Recursive");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (average_mode_log_recursive), display_average_mode==AVERAGE_MODE_LOG_RECURSIVE);
   gtk_widget_show(average_mode_log_recursive);
-  gtk_grid_attach(GTK_GRID(grid),average_mode_log_recursive,3,5,1,1);
+  gtk_grid_attach(GTK_GRID(grid),average_mode_log_recursive,col,row,1,1);
   g_signal_connect(average_mode_log_recursive,"pressed",G_CALLBACK(average_mode_cb),(gpointer *)AVERAGE_MODE_LOG_RECURSIVE);
 
+  row++;
 
   GtkWidget *time_label=gtk_label_new("Time (ms): ");
   //gtk_widget_override_font(average_mode_label, pango_font_description_from_string("Arial 18"));
   gtk_widget_show(time_label);
-  gtk_grid_attach(GTK_GRID(grid),time_label,3,6,1,1);
+  gtk_grid_attach(GTK_GRID(grid),time_label,col,row,1,1);
+
+  col++;
 
   GtkWidget *time_r=gtk_spin_button_new_with_range(1.0,9999.0,1.0);
   gtk_spin_button_set_value(GTK_SPIN_BUTTON(time_r),(double)display_average_time);
   gtk_widget_show(time_r);
-  gtk_grid_attach(GTK_GRID(grid),time_r,4,6,1,1);
+  gtk_grid_attach(GTK_GRID(grid),time_r,col,row,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);
-*/
+  row++;
+  row++;
+  row++;
+  col=1;
 
+  
   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), active_receiver->display_waterfall);
   gtk_widget_show(b_display_waterfall);
-  gtk_grid_attach(GTK_GRID(grid),b_display_waterfall,1,8,1,1);
+  gtk_grid_attach(GTK_GRID(grid),b_display_waterfall,col,row,1,1);
   g_signal_connect(b_display_waterfall,"toggled",G_CALLBACK(display_waterfall_cb),(gpointer *)NULL);
 
+  col++;
+
   GtkWidget *b_display_sliders=gtk_check_button_new_with_label("Display Sliders");
   //gtk_widget_override_font(b_display_sliders, pango_font_description_from_string("Arial 18"));
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_display_sliders), display_sliders);
   gtk_widget_show(b_display_sliders);
-  gtk_grid_attach(GTK_GRID(grid),b_display_sliders,2,8,1,1);
+  gtk_grid_attach(GTK_GRID(grid),b_display_sliders,col,row,1,1);
   g_signal_connect(b_display_sliders,"toggled",G_CALLBACK(display_sliders_cb),(gpointer *)NULL);
 
-/*
+  col++;
+
   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);
+  gtk_grid_attach(GTK_GRID(grid),b_display_toolbar,col,row,1,1);
   g_signal_connect(b_display_toolbar,"toggled",G_CALLBACK(display_toolbar_cb),(gpointer *)NULL);
-*/
+
   gtk_container_add(GTK_CONTAINER(content),grid);
 
   sub_menu=dialog;
index 4e084f161b43d90377503934b508695bd492e387..f3df140c0f03ebe959801f1a167d47f90bf6db13 100644 (file)
 #include "diversity_menu.h"
 #include "radio.h"
 #include "new_protocol.h"
+#include "sliders.h"
 
 #include <math.h> 
 
 static GtkWidget *parent_window=NULL;
 
 static GtkWidget *dialog=NULL;
+static GtkWidget *gain_scale=NULL;
+static GtkWidget *phase_scale=NULL;
 
 static GtkWidget *level;
 
@@ -42,6 +45,8 @@ static void cleanup() {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     sub_menu=NULL;
+    gain_scale=NULL;
+    phase_scale=NULL;
   }
 }
 
@@ -68,24 +73,56 @@ static void diversity_cb(GtkWidget *widget, gpointer data) {
 // The DIVERSITY rotation parameters must be re-calculated
 // each time the gain or the phase changes.
 //
-static void gain_value_changed_cb(GtkWidget *widget, gpointer data) {
+static void set_gain(double gain) {
   double amplitude,arg;
-  div_gain=gtk_range_get_value(GTK_RANGE(widget));
+  div_gain=gain;
   amplitude=pow(10.0, 0.05*div_gain);
   arg=div_phase*0.017453292519943295769236907684886;
   div_cos=amplitude*cos(arg);
   div_sin=amplitude*sin(arg);
 }
 
-static void phase_value_changed_cb(GtkWidget *widget, gpointer data) {
+static void gain_value_changed_cb(GtkWidget *widget, gpointer data) {
+  set_gain(gtk_range_get_value(GTK_RANGE(widget)));
+}
+
+void update_diversity_gain(double increment) {
+  double g=div_gain+(increment/10);
+  if(g<-12.0) g=-12.0;
+  if(g>12.0) g=12.0;
+  if(gain_scale!=NULL) {
+    gtk_range_set_value(GTK_RANGE(gain_scale),div_gain);
+  } else {
+    show_diversity_gain();
+  }
+  set_gain(g);
+}
+
+static void set_phase(double phase) {
   double amplitude,arg;
-  div_phase=gtk_range_get_value(GTK_RANGE(widget));
+  div_phase=phase;
   amplitude=pow(10.0, 0.05*div_gain);
   arg=div_phase*0.017453292519943295769236907684886;
   div_cos=amplitude*cos(arg);
   div_sin=amplitude*sin(arg);
 }
 
+static void phase_value_changed_cb(GtkWidget *widget, gpointer data) {
+  set_phase(gtk_range_get_value(GTK_RANGE(widget)));
+}
+
+void update_diversity_phase(double increment) {
+  double p=div_phase+increment;
+  if(p<0.0) p=360.0;
+  if(p>360.0) p=0.0;
+  if(phase_scale!=NULL) {
+    gtk_range_set_value(GTK_RANGE(phase_scale),div_phase);
+  } else {
+    show_diversity_phase();
+  }
+  set_phase(p);
+}
+
 void diversity_menu(GtkWidget *parent) {
   int i;
 
@@ -119,32 +156,32 @@ void diversity_menu(GtkWidget *parent) {
   GtkWidget *diversity_b=gtk_check_button_new_with_label("Diversity Enable");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (diversity_b), diversity_enabled);
   gtk_widget_show(diversity_b);
-  gtk_grid_attach(GTK_GRID(grid),diversity_b,0,1,1,1);
+  gtk_grid_attach(GTK_GRID(grid),diversity_b,1,0,1,1);
   g_signal_connect(diversity_b,"toggled",G_CALLBACK(diversity_cb),NULL);
 
 
   GtkWidget *gain_label=gtk_label_new("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,2,1,1);
+  gtk_grid_attach(GTK_GRID(grid),gain_label,0,1,1,1);
 
-  GtkWidget *gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,-12.0,+12.0,0.1);
+  gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,-12.0,+12.0,0.1);
   gtk_widget_set_size_request (gain_scale, 300, 25);
   gtk_range_set_value(GTK_RANGE(gain_scale),div_gain);
   gtk_widget_show(gain_scale);
-  gtk_grid_attach(GTK_GRID(grid),gain_scale,1,2,1,1);
+  gtk_grid_attach(GTK_GRID(grid),gain_scale,1,1,1,1);
   g_signal_connect(G_OBJECT(gain_scale),"value_changed",G_CALLBACK(gain_value_changed_cb),NULL);
 
   GtkWidget *phase_label=gtk_label_new("Phase:");
   gtk_misc_set_alignment (GTK_MISC(phase_label), 0, 0);
   gtk_widget_show(phase_label);
-  gtk_grid_attach(GTK_GRID(grid),phase_label,0,3,1,1);
+  gtk_grid_attach(GTK_GRID(grid),phase_label,0,2,1,1);
 
-  GtkWidget *phase_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0,360.0,1.0);
+  phase_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0,360.0,1.0);
   gtk_widget_set_size_request (phase_scale, 300, 25);
   gtk_range_set_value(GTK_RANGE(phase_scale),div_phase);
   gtk_widget_show(phase_scale);
-  gtk_grid_attach(GTK_GRID(grid),phase_scale,1,3,1,1);
+  gtk_grid_attach(GTK_GRID(grid),phase_scale,1,2,1,1);
   g_signal_connect(G_OBJECT(phase_scale),"value_changed",G_CALLBACK(phase_value_changed_cb),NULL);
 
   
index 2530daeed83edaf8c4b3a0c60f6e60b4b2eae260..b71588f9f0609304b9a4e1f186c727873323269a 100644 (file)
@@ -18,3 +18,5 @@
 */
 
 extern void diversity_menu(GtkWidget *parent);
+extern void update_diversity_gain(double increment);
+extern void update_diversity_phase(double increment);
index e3d5af093023b9fff84043fbc18ff352a31577b1..83d89baae483412315889e9dfa6601e02ed2fdbd 100644 (file)
 #include "vfo.h"
 #include "button_text.h"
 #include "gpio.h"
+#ifdef CONTROLLER2
+#include "i2c.h"
+#endif
 
 static GtkWidget *parent_window=NULL;
 
 static GtkWidget *dialog=NULL;
 
-static GtkWidget *b_af_gain;
-static GtkWidget *b_agc_gain;
+static GtkWidget *b_af_gain_rx1;
+static GtkWidget *b_af_gain_rx2;
+static GtkWidget *b_agc_gain_rx1;
+static GtkWidget *b_agc_gain_rx2;
 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_rit_rx1;
+static GtkWidget *b_rit_rx2;
+static GtkWidget *b_xit;
 static GtkWidget *b_cw_speed;
 static GtkWidget *b_cw_frequency;
 static GtkWidget *b_panadapter_high;
@@ -51,12 +58,62 @@ static GtkWidget *b_panadapter_low;
 static GtkWidget *b_squelch;
 static GtkWidget *b_compression;
 
+#ifdef CONTROLLER2
+static GtkWidget *b_top_af_gain_rx1;
+static GtkWidget *b_top_af_gain_rx2;
+static GtkWidget *b_top_agc_gain_rx1;
+static GtkWidget *b_top_agc_gain_rx2;
+static GtkWidget *b_top_attenuation;
+static GtkWidget *b_top_mic_gain;
+static GtkWidget *b_top_drive;
+static GtkWidget *b_top_tune_drive;
+static GtkWidget *b_top_rit_rx1;
+static GtkWidget *b_top_rit_rx2;
+static GtkWidget *b_top_xit;
+static GtkWidget *b_top_cw_speed;
+static GtkWidget *b_top_cw_frequency;
+static GtkWidget *b_top_panadapter_high;
+static GtkWidget *b_top_panadapter_low;
+static GtkWidget *b_top_squelch;
+static GtkWidget *b_top_compression;
+#endif
+
+enum {
+  ENC2,
+#ifdef CONTROLLER2
+  ENC2_TOP,
+#endif
+  ENC2_SW,
+  ENC3,
+#ifdef CONTROLLER2
+  ENC3_TOP,
+#endif
+  ENC3_SW,
+  ENC4,
+#ifdef CONTROLLER2
+  ENC4_TOP,
+#endif
+  ENC4_SW,
+#ifdef CONTROLLER2
+  ENC5,
+  ENC5_TOP,
+  ENC5_SW,
+#endif
+};
+
+typedef struct _choice {
+  int id;
+  int action;
+  GtkWidget *button;
+} CHOICE;
+
 static int encoder;
 
 static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
+    active_menu=NO_MENU;
     sub_menu=NULL;
   }
 }
@@ -71,60 +128,132 @@ static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_d
   return FALSE;
 }
 
-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-1;
-        }
-      } if(pos<0) {
-        e1_encoder_action++;
-        if(e1_encoder_action>=ENCODER_LAST) {
-          e1_encoder_action=0;
-        }
-      }
-      action=e1_encoder_action;
+static void enc_select_cb(GtkWidget *widget,gpointer data) {
+  CHOICE *choice=(CHOICE *)data;
+  switch(choice->id) {
+    case ENC2:
+      e2_encoder_action=choice->action;
       break;
-    case 2:
-      if(pos>0) {
-        e2_encoder_action--;
-        if(e2_encoder_action<0) {
-          e2_encoder_action=ENCODER_LAST-1;
-        }
-      } if(pos<0) {
-        e2_encoder_action++;
-        if(e2_encoder_action>=ENCODER_LAST) {
-          e2_encoder_action=0;
-        }
-      }
-      action=e2_encoder_action;
+#ifdef CONTROLLER2
+    case ENC2_TOP:
+      e2_top_encoder_action=choice->action;
       break;
-    case 3:
-      if(pos>0) {
-        e3_encoder_action--;
-        if(e3_encoder_action<0) {
-          e3_encoder_action=ENCODER_LAST-1;
-        }
-      } if(pos<0) {
-        e3_encoder_action++;
-        if(e3_encoder_action>=ENCODER_LAST) {
-          e3_encoder_action=0;
-        }
-      }
-      action=e3_encoder_action;
+#endif
+    case ENC3:
+      e3_encoder_action=choice->action;
+      break;
+#ifdef CONTROLLER2
+    case ENC3_TOP:
+      e3_top_encoder_action=choice->action;
+      break;
+#endif
+    case ENC4:
+      e4_encoder_action=choice->action;
+      break;
+#ifdef CONTROLLER2
+    case ENC4_TOP:
+      e4_top_encoder_action=choice->action;
+      break;
+#endif
+#ifdef CONTROLLER2
+    case ENC5:
+      e5_encoder_action=choice->action;
+      break;
+    case ENC5_TOP:
+      e5_top_encoder_action=choice->action;
+      break;
+#endif
+  }
+  gtk_button_set_label(GTK_BUTTON(choice->button),encoder_string[choice->action]);
+}
+
+static gboolean enc_cb(GtkWidget *widget, GdkEvent *event, gpointer data) {
+  int enc=GPOINTER_TO_INT(data);
+  int i;
+
+  GtkWidget *menu=gtk_menu_new();
+  for(i=0;i<ENCODER_ACTIONS;i++) {
+    GtkWidget *menu_item=gtk_menu_item_new_with_label(encoder_string[i]);
+    CHOICE *choice=g_new0(CHOICE,1);
+    choice->id=enc;
+    choice->action=i;
+    choice->button=widget;
+    g_signal_connect(menu_item,"activate",G_CALLBACK(enc_select_cb),choice);
+    gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
+  }
+  gtk_widget_show_all(menu);
+#if GTK_CHECK_VERSION(3,22,0)
+  gtk_menu_popup_at_pointer(GTK_MENU(menu),(GdkEvent *)event);
+// the following line of code is to work around the problem of the popup menu not having scroll bars.
+  gtk_menu_reposition(GTK_MENU(menu));
+#else
+  gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,0,gtk_get_current_event_time());
+#endif
+  
+  return TRUE;
+}
+
+static void sw_select_cb(GtkWidget *widget,gpointer data) {
+  CHOICE *choice=(CHOICE *)data;
+  switch(choice->id) {
+    case ENC2_SW:
+      e2_sw_action=choice->action;
+      break;
+    case ENC3_SW:
+      e3_sw_action=choice->action;
+      break;
+    case ENC4_SW:
+      e4_sw_action=choice->action;
+      break;
+#ifdef CONTROLLER2
+    case ENC5_SW:
+      e5_sw_action=choice->action;
       break;
+#endif
   }
+  gtk_button_set_label(GTK_BUTTON(choice->button),sw_string[choice->action]);
+}
+
+static gboolean sw_cb(GtkWidget *widget, GdkEvent *event, gpointer data) {
+  int sw=GPOINTER_TO_INT(data);
+  int i;
 
+  GtkWidget *menu=gtk_menu_new();
+  for(i=0;i<SWITCH_ACTIONS;i++) {
+    GtkWidget *menu_item=gtk_menu_item_new_with_label(sw_string[i]);
+    CHOICE *choice=g_new0(CHOICE,1);
+    choice->id=sw;
+    choice->action=i;
+    choice->button=widget;
+    g_signal_connect(menu_item,"activate",G_CALLBACK(sw_select_cb),choice);
+    gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
+  }
+  gtk_widget_show_all(menu);
+#if GTK_CHECK_VERSION(3,22,0)
+  gtk_menu_popup_at_pointer(GTK_MENU(menu),(GdkEvent *)event);
+// the following line of code is to work around the problem of the popup menu not having scroll bars.
+  gtk_menu_reposition(GTK_MENU(menu));
+#else
+  gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,0,gtk_get_current_event_time());
+#endif
+
+  return TRUE;
+}
+
+GtkWidget* getRadioButton(int action) {
+  GtkWidget* button;
   switch(action) {
-    case ENCODER_AF_GAIN:
-      button=b_af_gain;
+    case ENCODER_AF_GAIN_RX1:
+      button=b_af_gain_rx1;
+      break;
+    case ENCODER_AF_GAIN_RX2:
+      button=b_af_gain_rx2;
+      break;
+    case ENCODER_AGC_GAIN_RX1:
+      button=b_agc_gain_rx1;
       break;
-    case ENCODER_AGC_GAIN:
-      button=b_agc_gain;
+    case ENCODER_AGC_GAIN_RX2:
+      button=b_agc_gain_rx2;
       break;
     case ENCODER_ATTENUATION:
       button=b_attenuation;
@@ -140,8 +269,11 @@ void encoder_select(int pos) {
       button=b_tune_drive;
       break;
 */
-    case ENCODER_RIT:
-      button=b_rit;
+    case ENCODER_RIT_RX1:
+      button=b_rit_rx1;
+      break;
+    case ENCODER_RIT_RX2:
+      button=b_rit_rx2;
       break;
     case ENCODER_CW_SPEED:
       button=b_cw_speed;
@@ -162,25 +294,493 @@ void encoder_select(int pos) {
       button=b_compression;
       break;
   }
+  return button;
+}
+
+#ifdef CONTROLLER2
+GtkWidget* getTopRadioButton(int action) {
+  GtkWidget* button;
+  switch(action) {
+    case ENCODER_AF_GAIN_RX1:
+      button=b_top_af_gain_rx1;
+      break;
+    case ENCODER_AF_GAIN_RX2:
+      button=b_top_af_gain_rx2;
+      break;
+    case ENCODER_AGC_GAIN_RX1:
+      button=b_top_agc_gain_rx1;
+      break;
+    case ENCODER_AGC_GAIN_RX2:
+      button=b_top_agc_gain_rx2;
+      break;
+    case ENCODER_ATTENUATION:
+      button=b_top_attenuation;
+      break;
+    case ENCODER_MIC_GAIN:
+      button=b_top_mic_gain;
+      break;
+    case ENCODER_DRIVE:
+      button=b_top_drive;
+      break;
+/*
+    case ENCODER_TUNE_DRIVE:
+      button=b_top_tune_drive;
+      break;
+*/
+    case ENCODER_RIT_RX1:
+      button=b_top_rit_rx1;
+      break;
+    case ENCODER_RIT_RX2:
+      button=b_top_rit_rx2;
+      break;
+    case ENCODER_CW_SPEED:
+      button=b_top_cw_speed;
+      break;
+    case ENCODER_CW_FREQUENCY:
+      button=b_top_cw_frequency;
+      break;
+    case ENCODER_PANADAPTER_HIGH:
+      button=b_top_panadapter_high;
+      break;
+    case ENCODER_PANADAPTER_LOW:
+      button=b_top_panadapter_low;
+      break;
+    case ENCODER_SQUELCH:
+      button=b_top_squelch;
+      break;
+    case ENCODER_COMP:
+      button=b_top_compression;
+      break;
+  }
+  return button;
+}
+#endif
+
+
+static gboolean select_cb (GtkWidget *widget, gpointer data) {
+  GtkWidget *button;
+  int action;
+
+  switch(encoder) {
+    case 2:
+      action=e2_encoder_action;
+      break;
+    case 3:
+      action=e3_encoder_action;
+      break;
+    case 4:
+      action=e4_encoder_action;
+      break;
+    case 5:
+      action=e5_encoder_action;
+      break;
+  }
+  button=getRadioButton(action);
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
+}
 
+#ifdef CONTROLLER2
+static gboolean top_select_cb (GtkWidget *widget, gpointer data) {
+  GtkWidget *button;
+  int action;
+
+  switch(encoder) {
+    case 2:
+      action=e2_top_encoder_action;
+      break;
+    case 3:
+      action=e3_top_encoder_action;
+      break;
+    case 4:
+      action=e4_top_encoder_action;
+      break;
+    case 5:
+      action=e5_top_encoder_action;
+      break;
+  }
+  button=getTopRadioButton(action);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
 }
+#endif
 
-static gboolean action_select_cb (GtkWidget *widget, gpointer data) {
-  int action=(int)data;
+void encoder_select(int pos) {
+  int action;
+  GtkWidget *button;
   switch(encoder) {
-    case 1:
-      e1_encoder_action=action;
+    case 2:
+        if(pos>0) {
+          e2_encoder_action--;
+          if(e2_encoder_action<0) {
+            e2_encoder_action=ENCODER_ACTIONS-1;
+          }
+        } if(pos<0) {
+          e2_encoder_action++;
+          if(e2_encoder_action>=ENCODER_ACTIONS) {
+            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_ACTIONS-1;
+          }
+        } if(pos<0) {
+          e3_encoder_action++;
+          if(e3_encoder_action>=ENCODER_ACTIONS) {
+            e3_encoder_action=0;
+          }
+        }
+        action=e3_encoder_action;
+      break;
+    case 4:
+        if(pos>0) {
+          e4_encoder_action--;
+          if(e4_encoder_action<0) {
+            e4_encoder_action=ENCODER_ACTIONS-1;
+          }
+        } if(pos<0) {
+          e4_encoder_action++;
+          if(e4_encoder_action>=ENCODER_ACTIONS) {
+            e4_encoder_action=0;
+          }
+        }
+        action=e4_encoder_action;
+      break;
+  }
+
+  button=getRadioButton(action);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
+
+}
+
+#ifdef CONTROLLER2
+void top_encoder_select(int pos) {
+  int action;
+  GtkWidget *button;
+  switch(encoder) {
     case 2:
-      e2_encoder_action=action;
+        if(pos>0) {
+          e2_top_encoder_action--;
+          if(e2_top_encoder_action<0) {
+            e2_top_encoder_action=ENCODER_ACTIONS-1;
+          }
+        } if(pos<0) {
+          e2_top_encoder_action++;
+          if(e2_top_encoder_action>=ENCODER_ACTIONS) {
+            e2_top_encoder_action=0;
+          }
+        }
+        action=e2_top_encoder_action;
       break;
     case 3:
-      e3_encoder_action=action;
+        if(pos>0) {
+          e3_top_encoder_action--;
+          if(e3_top_encoder_action<0) {
+            e3_top_encoder_action=ENCODER_ACTIONS-1;
+          }
+        } if(pos<0) {
+          e3_top_encoder_action++;
+          if(e3_top_encoder_action>=ENCODER_ACTIONS) {
+            e3_top_encoder_action=0;
+          }
+        }
+        action=e3_top_encoder_action;
+      break;
+    case 4:
+        if(pos>0) {
+          e4_top_encoder_action--;
+          if(e4_top_encoder_action<0) {
+            e4_top_encoder_action=ENCODER_ACTIONS-1;
+          }
+        } if(pos<0) {
+          e4_top_encoder_action++;
+          if(e4_top_encoder_action>=ENCODER_ACTIONS) {
+            e4_top_encoder_action=0;
+          }
+        }
+        action=e4_top_encoder_action;
+      break;
+    case 5:
+        if(pos>0) {
+          e5_top_encoder_action--;
+          if(e5_top_encoder_action<0) {
+            e5_top_encoder_action=ENCODER_ACTIONS-1;
+          }
+        } if(pos<0) {
+          e5_top_encoder_action++;
+          if(e5_top_encoder_action>=ENCODER_ACTIONS) {
+            e5_top_encoder_action=0;
+          }
+        }
+        action=e5_top_encoder_action;
       break;
   }
+
+  button=getTopRadioButton(action);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
+
+}
+#endif
+
+  static gboolean action_select_cb (GtkWidget *widget, gpointer data) {
+    int action=(int)data;
+    switch(encoder) {
+      case 2:
+        e2_encoder_action=action;
+        break;
+      case 3:
+        e3_encoder_action=action;
+        break;
+      case 4:
+        e4_encoder_action=action;
+        break;
+      case 5:
+        e5_encoder_action=action;
+        break;
+    }
+  }
+
+#ifdef CONTROLLER2
+  static gboolean top_action_select_cb (GtkWidget *widget, gpointer data) {
+    int action=(int)data;
+    switch(encoder) {
+      case 2:
+        e2_top_encoder_action=action;
+        break;
+      case 3:
+        e3_top_encoder_action=action;
+        break;
+      case 4:
+        e4_top_encoder_action=action;
+        break;
+      case 5:
+        e5_top_encoder_action=action;
+        break;
+    }
+  }
+#endif
+
+  static gboolean enc2_cb(GtkWidget *widget, gpointer data) {
+    int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget));
+    e2_encoder_action=i;
+    return TRUE;
+  }
+
+  static gboolean enc2_sw_cb(GtkWidget *widget, gpointer data) {
+    int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget));
+    e2_sw_action=i;
+    return TRUE;
+  }
+
+  static gboolean enc3_cb(GtkWidget *widget, gpointer data) {
+    int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget));
+    e3_encoder_action=i;
+    return TRUE;
+  }
+
+  static gboolean enc3_sw_cb(GtkWidget *widget, gpointer data) {
+    int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget));
+    e3_sw_action=i;
+    return TRUE;
+  }
+
+  static gboolean enc4_cb(GtkWidget *widget, gpointer data) {
+    int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget));
+    e4_encoder_action=i;
+    return TRUE;
+  }
+
+  static gboolean enc4_sw_cb(GtkWidget *widget, gpointer data) {
+    int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget));
+    e4_sw_action=i;
+    return TRUE;
+  }
+
+#ifdef CONTROLLER2
+  static gboolean enc2_top_cb(GtkWidget *widget, gpointer data) {
+    int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget));
+    e2_top_encoder_action=i;
+    return TRUE;
+  }
+
+  static gboolean enc3_top_cb(GtkWidget *widget, gpointer data) {
+    int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget));
+    e3_top_encoder_action=i;
+    return TRUE;
+  }
+
+  static gboolean enc4_top_cb(GtkWidget *widget, gpointer data) {
+    int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget));
+    e4_top_encoder_action=i;
+    return TRUE;
+  }
+
+  static gboolean enc5_cb(GtkWidget *widget, gpointer data) {
+    int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget));
+    e5_encoder_action=i;
+    return TRUE;
+  }
+  static gboolean enc5_sw_cb(GtkWidget *widget, gpointer data) {
+    int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget));
+    e5_sw_action=i;
+    return TRUE;
+  }
+
+
+  static gboolean enc5_top_cb(GtkWidget *widget, gpointer data) {
+    int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget));
+    e5_top_encoder_action=i;
+    return TRUE;
+  }
+#endif
+
+void encoder_menu(GtkWidget *parent) {
+  int row=0;
+  int col=0;
+  int i;
+
+  dialog=gtk_dialog_new();
+  gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  char title[32];
+  sprintf(title,"piHPSDR - Encoder Actions:");
+  gtk_window_set_title(GTK_WINDOW(dialog),title);
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), 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);
+  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,col,row,1,1);
+
+  row++;
+  col=1;
+#ifdef CONTROLLER2
+  GtkWidget *label_bottom=gtk_label_new("Bottom");
+  gtk_grid_attach(GTK_GRID(grid),label_bottom,col,row,1,1);
+  col++;
+  GtkWidget *label_top=gtk_label_new("Top");
+  gtk_grid_attach(GTK_GRID(grid),label_top,col,row,1,1);
+  col++;
+#else
+  GtkWidget *label_encoder=gtk_label_new("Encoder");
+  gtk_grid_attach(GTK_GRID(grid),label_encoder,col,row,1,1);
+  col++;
+#endif
+  GtkWidget *label_switch=gtk_label_new("Switch");
+  gtk_grid_attach(GTK_GRID(grid),label_switch,col,row,1,1);
+  col++;
+
+  row++;
+  col=0;
+
+  GtkWidget *enc2_title=gtk_label_new("ENC2: ");
+  gtk_grid_attach(GTK_GRID(grid),enc2_title,col,row,1,1);
+  col++;
+
+  GtkWidget *enc2=gtk_button_new_with_label(encoder_string[e2_encoder_action]);
+  gtk_grid_attach(GTK_GRID(grid),enc2,col,row,1,1);
+  g_signal_connect(enc2,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC2));
+  col++;
+  
+#ifdef CONTROLLER2
+  GtkWidget *enc2_top=gtk_button_new_with_label(encoder_string[e2_top_encoder_action]);
+  gtk_grid_attach(GTK_GRID(grid),enc2_top,col,row,1,1);
+  g_signal_connect(enc2_top,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC2_TOP));
+  col++;
+#endif
+
+  GtkWidget *enc2_sw=gtk_button_new_with_label(sw_string[e2_sw_action]);
+  gtk_grid_attach(GTK_GRID(grid),enc2_sw,col,row,1,1);
+  g_signal_connect(enc2_sw,"button_press_event",G_CALLBACK(sw_cb),GINT_TO_POINTER(ENC2_SW));
+
+  row++;
+  col=0;
+
+  GtkWidget *enc3_title=gtk_label_new("ENC3: ");
+  gtk_grid_attach(GTK_GRID(grid),enc3_title,col,row,1,1);
+  col++;
+
+  GtkWidget *enc3=gtk_button_new_with_label(encoder_string[e3_encoder_action]);
+  gtk_grid_attach(GTK_GRID(grid),enc3,col,row,1,1);
+  g_signal_connect(enc3,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC3));
+  col++;
+  
+#ifdef CONTROLLER2
+  GtkWidget *enc3_top=gtk_button_new_with_label(encoder_string[e3_top_encoder_action]);
+  gtk_grid_attach(GTK_GRID(grid),enc3_top,col,row,1,1);
+  g_signal_connect(enc3_top,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC3_TOP));
+  col++;
+#endif
+
+  GtkWidget *enc3_sw=gtk_button_new_with_label(sw_string[e3_sw_action]);
+  gtk_grid_attach(GTK_GRID(grid),enc3_sw,col,row,1,1);
+  g_signal_connect(enc3_sw,"button_press_event",G_CALLBACK(sw_cb),GINT_TO_POINTER(ENC3_SW));
+
+  row++;
+  col=0;
+
+  GtkWidget *enc4_title=gtk_label_new("ENC4: ");
+  gtk_grid_attach(GTK_GRID(grid),enc4_title,col,row,1,1);
+  col++;
+
+  GtkWidget *enc4=gtk_button_new_with_label(encoder_string[e4_encoder_action]);
+  gtk_grid_attach(GTK_GRID(grid),enc4,col,row,1,1);
+  g_signal_connect(enc4,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC4));
+  col++;
+  
+#ifdef CONTROLLER2
+  GtkWidget *enc4_top=gtk_button_new_with_label(encoder_string[e4_top_encoder_action]);
+  gtk_grid_attach(GTK_GRID(grid),enc4_top,col,row,1,1);
+  g_signal_connect(enc4_top,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC4_TOP));
+  col++;
+#endif
+
+  GtkWidget *enc4_sw=gtk_button_new_with_label(sw_string[e4_sw_action]);
+  gtk_grid_attach(GTK_GRID(grid),enc4_sw,col,row,1,1);
+  g_signal_connect(enc4_sw,"button_press_event",G_CALLBACK(sw_cb),GINT_TO_POINTER(ENC4_SW));
+
+  row++;
+  col=0;
+
+#ifdef CONTROLLER2
+  GtkWidget *enc5_title=gtk_label_new("ENC5: ");
+  gtk_grid_attach(GTK_GRID(grid),enc5_title,col,row,1,1);
+  col++;
+
+  GtkWidget *enc5=gtk_button_new_with_label(encoder_string[e5_encoder_action]);
+  gtk_grid_attach(GTK_GRID(grid),enc5,col,row,1,1);
+  g_signal_connect(enc5,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC5));
+  col++;
+  
+  GtkWidget *enc5_top=gtk_button_new_with_label(encoder_string[e5_top_encoder_action]);
+  gtk_grid_attach(GTK_GRID(grid),enc5_top,col,row,1,1);
+  g_signal_connect(enc5_top,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC5_TOP));
+  col++;
+
+  GtkWidget *enc5_sw=gtk_button_new_with_label(sw_string[e5_sw_action]);
+  gtk_grid_attach(GTK_GRID(grid),enc5_sw,col,row,1,1);
+  g_signal_connect(enc5_sw,"button_press_event",G_CALLBACK(sw_cb),GINT_TO_POINTER(ENC5_SW));
+#endif
+
+  gtk_container_add(GTK_CONTAINER(content),grid);
+
+  sub_menu=dialog;
+
+  gtk_widget_show_all(dialog);
 }
 
+/*
 void encoder_menu(GtkWidget *parent,int e) {
   GtkWidget *b;
   int i;
@@ -189,17 +789,42 @@ void encoder_menu(GtkWidget *parent,int e) {
   encoder=e;
 
   int encoder_action;
+#ifdef CONTROLLER2
+  int top_encoder_action;
+#endif
   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;
+    case 4:
+      encoder_action=e4_encoder_action;
+      break;
+#ifdef CONTROLLER2
+    case 5:
+      encoder_action=e5_encoder_action;
+      break;
+#endif
   }
+#ifdef CONTROLLER2
+  switch(encoder) {
+    case 2:
+      top_encoder_action=e2_top_encoder_action;
+      break;
+    case 3:
+      top_encoder_action=e3_top_encoder_action;
+      break;
+    case 4:
+      top_encoder_action=e4_top_encoder_action;
+      break;
+    case 5:
+      top_encoder_action=e5_top_encoder_action;
+      break;
+  }
+#endif
+
   parent_window=parent;
 
   dialog=gtk_dialog_new();
@@ -236,25 +861,49 @@ void encoder_menu(GtkWidget *parent,int e) {
   row++;
   col=0;
 
-  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,col,row,2,1);
-  g_signal_connect(b_af_gain,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_AF_GAIN);
+#ifdef CONTROLLER2
+  GtkWidget *bottom_title=gtk_label_new("Bottom");
+  gtk_grid_attach(GTK_GRID(grid),bottom_title,col,row,4,1);
+
+  row++;
+  col=0;
+#endif
+
+  b_af_gain_rx1=gtk_radio_button_new_with_label(NULL,"AF Gain RX1");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_af_gain_rx1), encoder_action==ENCODER_AF_GAIN_RX1);
+  gtk_widget_show(b_af_gain_rx1);
+  gtk_grid_attach(GTK_GRID(grid),b_af_gain_rx1,col,row,2,1);
+  g_signal_connect(b_af_gain_rx1,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_AF_GAIN_RX1);
 
   row++;
 
-  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,col,row,2,1);
-  g_signal_connect(b_agc_gain,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_AGC_GAIN);
+  b_af_gain_rx2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_af_gain_rx1),"AF Gain RX2");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_af_gain_rx2), encoder_action==ENCODER_AF_GAIN_RX2);
+  gtk_widget_show(b_af_gain_rx2);
+  gtk_grid_attach(GTK_GRID(grid),b_af_gain_rx2,col,row,2,1);
+  g_signal_connect(b_af_gain_rx2,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_AF_GAIN_RX2);
+
+  row++;
+
+  b_agc_gain_rx1=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_af_gain_rx2),"AGC Gain RX1");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_agc_gain_rx1), encoder_action==ENCODER_AGC_GAIN_RX1);
+  gtk_widget_show(b_agc_gain_rx1);
+  gtk_grid_attach(GTK_GRID(grid),b_agc_gain_rx1,col,row,2,1);
+  g_signal_connect(b_agc_gain_rx1,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_AGC_GAIN_RX1);
+
+  row++;
+
+  b_agc_gain_rx2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_agc_gain_rx1),"AGC Gain RX2");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_agc_gain_rx2), encoder_action==ENCODER_AGC_GAIN_RX2);
+  gtk_widget_show(b_agc_gain_rx2);
+  gtk_grid_attach(GTK_GRID(grid),b_agc_gain_rx2,col,row,2,1);
+  g_signal_connect(b_agc_gain_rx2,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_AGC_GAIN_RX2);
 
   row++;
 #ifdef RADIOBERRY
-       b_attenuation=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_agc_gain),"RX GAIN");
+       b_attenuation=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_agc_gain_rx2),"RX GAIN");
 #else
-       b_attenuation=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_agc_gain),"Attenuation");
+       b_attenuation=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_agc_gain_rx2),"Attenuation");
 #endif
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_attenuation), encoder_action==ENCODER_ATTENUATION);
   gtk_widget_show(b_attenuation);
@@ -277,18 +926,32 @@ void encoder_menu(GtkWidget *parent,int e) {
   gtk_grid_attach(GTK_GRID(grid),b_drive,col,row,2,1);
   g_signal_connect(b_drive,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_DRIVE);
 
+  b_xit=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_drive),"XIT");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_xit), encoder_action==ENCODER_XIT);
+  gtk_widget_show(b_xit);
+  gtk_grid_attach(GTK_GRID(grid),b_xit,col,row,2,1);
+  g_signal_connect(b_xit,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_XIT);
+
+  col++;
+  row=1;
+
+  b_rit_rx1=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_drive),"RIT RX1");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_rit_rx1), encoder_action==ENCODER_RIT_RX1);
+  gtk_widget_show(b_rit_rx1);
+  gtk_grid_attach(GTK_GRID(grid),b_rit_rx1,col,row,2,1);
+  g_signal_connect(b_rit_rx1,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_RIT_RX1);
+
   row++;
 
-  b_rit=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_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,col,row,2,1);
-  g_signal_connect(b_rit,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_RIT);
+  b_rit_rx2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_rit_rx1),"RIT RX2");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_rit_rx2), encoder_action==ENCODER_RIT_RX2);
+  gtk_widget_show(b_rit_rx2);
+  gtk_grid_attach(GTK_GRID(grid),b_rit_rx2,col,row,2,1);
+  g_signal_connect(b_rit_rx2,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_RIT_RX2);
 
-  col=2;
-  row=1;
+  row++;
 
-  b_cw_speed=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_rit),"CW Speed");
+  b_cw_speed=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_rit_rx2),"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,col,row,2,1);
@@ -341,3 +1004,4 @@ void encoder_menu(GtkWidget *parent,int e) {
   gtk_widget_show_all(dialog);
 
 }
+*/
index 8b4559599541a586417102ee81ff724f46f1a67f..3f422729dc4e4b8f9049ce1a796d07591c506590 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef _ENCODER_MENU_H
 #define _ENCODER_MENU_H
 
-extern void encoder_menu(GtkWidget *parent,int e);
+extern void encoder_menu(GtkWidget *parent);
 
 extern void encoder_select(int pos);
 #endif
index 3f09a72b1c559a769cd09e3b51d10511ba2e8da4..a671a10ca8ae13a4bb5182ca54d868ce43469156 100644 (file)
@@ -27,6 +27,9 @@
 #include "radio.h"
 #include "new_protocol.h"
 #include "old_protocol.h"
+#ifdef SOAPYSDR
+#include "soapy_protocol.h"
+#endif
 #ifdef GPIO
 #include "gpio.h"
 #endif
@@ -66,9 +69,9 @@ static gboolean exit_cb (GtkWidget *widget, GdkEventButton *event, gpointer data
     case NEW_PROTOCOL:
       new_protocol_stop();
       break;
-#ifdef LIMESDR
-    case LIMESDR_PROTOCOL:
-      lime_protocol_stop();
+#ifdef SOAPYSDR
+    case SOAPYSDR_PROTOCOL:
+      soapy_protocol_stop();
       break;
 #endif
   }
@@ -87,9 +90,9 @@ static gboolean reboot_cb (GtkWidget *widget, GdkEventButton *event, gpointer da
     case NEW_PROTOCOL:
       new_protocol_stop();
       break;
-#ifdef LIMESDR
-    case LIMESDR_PROTOCOL:
-      lime_protocol_stop();
+#ifdef SOAPYSDR
+    case SOAPYSDR_PROTOCOL:
+      soapy_protocol_stop();
       break;
 #endif
   }
@@ -109,9 +112,9 @@ static gboolean shutdown_cb (GtkWidget *widget, GdkEventButton *event, gpointer
     case NEW_PROTOCOL:
       new_protocol_stop();
       break;
-#ifdef LIMESDR
-    case LIMESDR_PROTOCOL:
-      lime_protocol_stop();
+#ifdef SOAPYSDR
+    case SOAPYSDR_PROTOCOL:
+      soapy_protocol_stop();
       break;
 #endif
   }
diff --git a/ext.c b/ext.c
index 1379c5c0efd33d6ac909b1803316652bdfb38fe0..e8e02babab155d51431eb869cedbc5cbeab2d15f 100644 (file)
--- a/ext.c
+++ b/ext.c
 #include "sliders.h"
 #include "toolbar.h"
 #include "band_menu.h"
+#include "diversity_menu.h"
 #include "vfo.h"
 #include "radio.h"
 #include "new_menu.h"
+#include "new_protocol.h"
 #ifdef PURESIGNAL
 #include "ps_menu.h"
 #endif
+#include "agc.h"
+#include "filter.h"
 #include "band.h"
+#include "bandstack.h"
+#include "wdsp.h"
 
 // The following calls functions can be called usig g_idle_add
 
@@ -96,6 +102,11 @@ int ext_band_update(void *data) {
   return 0;
 }
 
+int ext_bandstack_update(void *data) {
+  start_bandstack();
+  return 0;
+}
+
 int ext_mode_update(void *data) {
   start_mode();
   return 0;
@@ -106,28 +117,38 @@ int ext_filter_update(void *data) {
   return 0;
 }
 
+int ext_frequency_update(void *data) {
+  start_vfo();
+  return 0;
+}
+
+int ext_memory_update(void *data) {
+  start_store();
+  return 0;
+}
+
 int ext_noise_update(void *data) {
   start_noise();
   return 0;
 }
 
 int ext_mox_update(void *data) {
-  mox_update((int)(uintptr_t)data);
+  mox_update(GPOINTER_TO_INT(data));
   return 0;
 }
 
 int ext_tune_update(void *data) {
-  tune_update((int)(uintptr_t)data);
+  tune_update(GPOINTER_TO_INT(data));
   return 0;
 }
 
 int ext_vox_changed(void *data) {
-  vox_changed((int)(uintptr_t)data);
+  vox_changed(GPOINTER_TO_INT(data));
   return 0;
 }
 
 int ext_update_agc_gain(void *data) {
-  update_agc_gain(*(double *)data);
+  update_agc_gain(GPOINTER_TO_INT(data));
   free(data);
   return 0;
 }
@@ -143,12 +164,12 @@ int ext_calc_drive_level(void *data) {
 }
 
 int ext_vfo_band_changed(void *data) {
-  vfo_band_changed((int)(uintptr_t)data);
+  vfo_band_changed(GPOINTER_TO_INT(data));
   return 0;
 }
 
 int ext_radio_change_sample_rate(void *data) {
-  radio_change_sample_rate((int)(uintptr_t)data);
+  radio_change_sample_rate(GPOINTER_TO_INT(data));
   return 0;
 }
 
@@ -185,7 +206,7 @@ int ext_set_mic_gain(void * data) {
 
 int ext_set_agc_gain(void *data) {
   double d=*(double *)data;
-  set_agc_gain(d);
+  set_agc_gain(active_receiver->id,d);
   free(data);
   return 0;
 }
@@ -223,7 +244,7 @@ int ext_update_att_preamp(void *data) {
 }
 
 int ext_set_alex_attenuation(void *data) {
-  int val=(int)(uintptr_t)data;
+  int val=GPOINTER_TO_INT(data);
   set_alex_attenuation(val);
   return 0;
 }
@@ -234,3 +255,239 @@ int ext_set_attenuation_value(void *data) {
   free(data);
   return 0;
 }
+
+
+#ifdef PURESIGNAL
+int ext_ps_update(void *data) {
+  if(transmitter->puresignal==0) {
+    tx_set_ps(transmitter,1);
+  } else {
+    tx_set_ps(transmitter,0);
+  }
+  return 0;
+}
+#endif
+
+int ext_two_tone(void *data) {
+  int state=transmitter->twotone?0:1;
+  tx_set_twotone(transmitter,state);
+  return 0;
+}
+
+int ext_nr_update(void *data) {
+  if(active_receiver->nr==0 && active_receiver->nr2==0) {
+    active_receiver->nr=1;
+    active_receiver->nr2=0;
+    mode_settings[vfo[active_receiver->id].mode].nr=1;
+    mode_settings[vfo[active_receiver->id].mode].nr2=0;
+  } else if(active_receiver->nr==1 && active_receiver->nr2==0) {
+    active_receiver->nr=0;
+    active_receiver->nr2=1;
+    mode_settings[vfo[active_receiver->id].mode].nr=0;
+    mode_settings[vfo[active_receiver->id].mode].nr2=1;
+  } else if(active_receiver->nr==0 && active_receiver->nr2==1) {
+    active_receiver->nr=0;
+    active_receiver->nr2=0;
+    mode_settings[vfo[active_receiver->id].mode].nr=0;
+    mode_settings[vfo[active_receiver->id].mode].nr2=0;
+  }
+  SetRXAANRRun(active_receiver->id, active_receiver->nr);
+  SetRXAEMNRRun(active_receiver->id, active_receiver->nr2);
+  vfo_update();
+  return 0;
+}
+
+int ext_nb_update(void *data) {
+  if(active_receiver->nb==0 && active_receiver->nb2==0) {
+    active_receiver->nb=1;
+    active_receiver->nb2=0;
+    mode_settings[vfo[active_receiver->id].mode].nb=1;
+    mode_settings[vfo[active_receiver->id].mode].nb2=0;
+  } else if(active_receiver->nb==1 && active_receiver->nb2==0) {
+    active_receiver->nb=0;
+    active_receiver->nb2=1;
+    mode_settings[vfo[active_receiver->id].mode].nb=0;
+    mode_settings[vfo[active_receiver->id].mode].nb2=1;
+  } else if(active_receiver->nb==0 && active_receiver->nb2==1) {
+    active_receiver->nb=0;
+    active_receiver->nb2=0;
+    mode_settings[vfo[active_receiver->id].mode].nb=0;
+    mode_settings[vfo[active_receiver->id].mode].nb2=0;
+  }
+  SetEXTANBRun(active_receiver->id, active_receiver->nb);
+  SetEXTNOBRun(active_receiver->id, active_receiver->nb2);
+  vfo_update();
+  return 0;
+}
+
+int ext_snb_update(void *data) {
+  if(active_receiver->snb==0) {
+    active_receiver->snb=1;
+    mode_settings[vfo[active_receiver->id].mode].snb=1;
+  } else {
+    active_receiver->snb=0;
+    mode_settings[vfo[active_receiver->id].mode].snb=0;
+  }
+  SetRXASNBARun(active_receiver->id, active_receiver->snb);
+  vfo_update();
+  return 0;
+}
+
+int ext_band_plus(void *data) {
+  int id=active_receiver->id;
+  int b=vfo[id].band;
+  b++;
+  if(b>=BANDS) b=0;
+  vfo_band_changed(b);
+  return 0;
+}
+
+
+int ext_band_minus(void *data) {
+  int id=active_receiver->id;
+  int b=vfo[id].band;
+  b--;
+  if(b<0) b=BANDS-1;
+  vfo_band_changed(b);
+  return 0;
+}
+
+int ext_bandstack_plus(void *data) {
+  BAND *band=band_get_band(vfo[active_receiver->id].band);
+  BANDSTACK *bandstack=band->bandstack;
+  int b=vfo[active_receiver->id].bandstack+1;
+  if(b>=bandstack->entries) b=0;
+  vfo_bandstack_changed(b);
+  return 0;
+}
+
+int ext_bandstack_minus(void *data) {
+  BAND *band=band_get_band(vfo[active_receiver->id].band);
+  BANDSTACK *bandstack=band->bandstack;
+  int b=vfo[active_receiver->id].bandstack-1;
+  if(b<0) b=bandstack->entries-1;;
+  vfo_bandstack_changed(b);
+  return 0;
+}
+
+int ext_lock_update(void *data) {
+  locked=locked==1?0:1;
+  vfo_update();
+  return 0;
+}
+
+int ext_rit_update(void *data) {
+  vfo[active_receiver->id].rit_enabled=vfo[active_receiver->id].rit_enabled==1?0:1;
+  if(protocol==NEW_PROTOCOL) {
+    schedule_high_priority();
+  }
+  vfo_update();
+  return 0;
+}
+
+int ext_rit_clear(void *data) {
+  vfo[active_receiver->id].rit=0;
+  vfo_update();
+  return 0;
+}
+
+int ext_xit_update(void *data) {
+  return 0;
+}
+
+int ext_xit_clear(void *data) {
+  return 0;
+}
+
+int ext_filter_plus(void *data) {
+  int f=vfo[active_receiver->id].filter-1;
+  if(f<0) f=FILTERS-1;
+  vfo_filter_changed(f);
+  return 0;
+}
+
+int ext_filter_minus(void *data) {
+  int f=vfo[active_receiver->id].filter+1;
+  if(f>=FILTERS) f=0;
+  vfo_filter_changed(f);
+  return 0;
+}
+
+int ext_mode_plus(void *data) {
+  int mode=vfo[active_receiver->id].mode;
+  mode++;
+  if(mode>=MODES) mode=0;
+  vfo_mode_changed(mode);
+  return 0;
+}
+
+int ext_mode_minus(void *data) {
+  int mode=vfo[active_receiver->id].mode;
+  mode--;
+  if(mode<0) mode=MODES-1;
+  vfo_mode_changed(mode);
+  return 0;
+}
+
+int ext_ctun_update(void *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();
+  return 0;
+}
+
+int ext_agc_update(void *data) {
+  active_receiver->agc++;
+  if(active_receiver->agc>+AGC_LAST) {
+    active_receiver->agc=0;
+  }
+  set_agc(active_receiver, active_receiver->agc);
+  vfo_update();
+  return 0;
+}
+
+int ext_split_update(void *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();
+  return 0;
+}
+
+int ext_start_rx(void *data) {
+  start_rx();
+  return 0;
+}
+
+int ext_diversity_update(void *data) {
+  int menu=GPOINTER_TO_INT(data);
+  if(menu) {
+    start_diversity();
+  } else {
+    diversity_enabled=diversity_enabled==1?0:1;
+    if (protocol == NEW_PROTOCOL) {
+      schedule_high_priority();
+      schedule_receive_specific();
+    }
+    vfo_update();
+  }
+  return 0;
+}
+
+int ext_function_update(void *data) {
+  function++;
+  if(function>MAX_FUNCTION) {
+    function=0;
+  }
+  update_toolbar_labels();
+  vfo_update();
+}
+
diff --git a/ext.h b/ext.h
index 97ab82985029660c6c35e7e23d1c961d6b9e96bd..ac995554b6d83fd2f24b1b82cf5dae61c7419fe5 100644 (file)
--- a/ext.h
+++ b/ext.h
@@ -28,6 +28,7 @@ extern int ext_vfo_update(void *data);
 extern int ext_set_frequency(void *data);
 extern int ext_vfo_filter_changed(void *data);
 extern int ext_band_update(void *data);
+extern int ext_bandstack_update(void *data);
 extern int ext_mox_update(void *data);
 extern int ext_tune_update(void *data);
 extern int ext_linein_changed(void *data);
@@ -39,6 +40,32 @@ extern int ext_calc_drive_level(void *data);
 extern int ext_vfo_band_changed(void *data);
 extern int ext_radio_change_sample_rate(void *data);
 
+extern int ext_ps_update(void *data);
+extern int ext_two_tone(void *data);
+extern int ext_nr_update(void *data);
+extern int ext_nb_update(void *data);
+extern int ext_snb_update(void *data);
+extern int ext_band_plus(void *data);
+extern int ext_band_minus(void *data);
+extern int ext_bandstack_plus(void *data);
+extern int ext_bandstack_minus(void *data);
+extern int ext_a_to_b(void *data);
+extern int ext_lock_update(void *data);
+extern int ext_rit_update(void *data);
+extern int ext_rit_clear(void *data);
+extern int ext_xit_update(void *data);
+extern int ext_xit_clear(void *data);
+extern int ext_filter_plus(void *data);
+extern int ext_filter_minus(void *data);
+extern int ext_mode_plus(void *data);
+extern int ext_mode_minus(void *data);
+extern int ext_b_to_a(void *data);
+extern int ext_a_swap_b(void *data);
+extern int ext_ctun_update(void *data);
+extern int ext_agc_update(void *data);
+extern int ext_split_update(void *data);
+
+
 extern int ext_cw_setup();
 extern int ext_cw_key(void *data);
 
@@ -50,6 +77,10 @@ extern int ext_mode_update(void *data);
 extern int ext_filter_update(void *data);
 extern int ext_noise_update(void *data);
 
+extern int ext_frequency_update(void *data);
+extern int ext_memory_update(void *data);
+extern int ext_function_update(void *data);
+
 #ifdef PURESIGNAL
 extern int ext_tx_set_ps(void *data);
 #endif
@@ -67,3 +98,6 @@ int ext_update_att_preamp(void *data);
 int ext_set_alex_attenuation(void *data);
 int ext_set_attenuation_value(void *data);
 int ext_set_compression(void *data);
+
+int ext_start_rx(void *data);
+int ext_diversity_update(void *data);
index 86c1ad8310f1ef81e7bdc0875a739f9db0e57e55..28043afb43cfa6a7a4eb2223aa883c136b6a4985 100644 (file)
--- a/filter.c
+++ b/filter.c
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "sliders.h"
 #include "filter.h"
+#include "receiver.h"
+#include "vfo.h"
+#include "radio.h"
 #include "property.h"
 
 FILTER filterLSB[FILTERS]={
@@ -431,3 +435,26 @@ void filterRestoreState() {
 
 }
 
+void filter_width_changed(int rx,int increment) {
+  int id=receiver[rx]->id;
+  FILTER *mode_filters=filters[vfo[id].mode];
+  FILTER *filter=&mode_filters[vfo[id].filter];
+
+fprintf(stderr,"filter_width_changed: rx=%d mode=%d filter=%d increment=%d\n",rx,vfo[id].mode,vfo[id].filter,increment);
+
+  if(vfo[id].filter==filterVar1 || vfo[id].filter==filterVar2) {
+    filter->high=filter->high+increment;
+fprintf(stderr,"filter->low=%d filter->high=%d\n",filter->low,filter->high);
+    if(vfo[id].mode==modeCWL || vfo[id].mode==modeCWU) {
+      filter->low=filter->high;
+    }
+    vfo_filter_changed(vfo[id].filter);
+    int width=filter->high-filter->low;
+    if(vfo[id].mode==modeCWL || vfo[id].mode==modeCWU) {
+      width=filter->high;
+    } else {
+      if(width<0) width=filter->low-filter->high;
+    }
+    set_filter_width(id,width);
+  }
+}
index ea950032babf1f0f8ee0a1d9a91fd85ada4c0123..1e1b4634f011cf04cea19d3409b045079d3ef7cf 100644 (file)
--- a/filter.h
+++ b/filter.h
@@ -59,4 +59,5 @@ FILTER *filters[MODES];
 
 void filterSaveState();
 void filterRestoreState();
+void filter_width_changed(int rx,int increment);
 #endif
index d69fe76d58e09194ebfcbde842df12694e6315eb..53d6dff2d42a29b40de0df4f3d5ebccb1a9c924b 100644 (file)
@@ -326,39 +326,7 @@ struct frequency_info frequencyInfo[]=
         { 1296800000LL,  1296999999LL, "23CM Experimental Beacons",          NOBAND,  TRUE },
         { 1297000000LL,  1300000000LL, "23CM Digital Modes",                 NOBAND,  TRUE },
 
-        { 2300000000LL,  2302999999LL, "2.3GHz High Data Rate",              NOBAND,  TRUE },
-        { 2303000000LL,  2303499999LL, "2.3GHz Packet",                      NOBAND,  TRUE },
-        { 2303500000LL,  2303800000LL, "2.3GHz TTY Packet",                  NOBAND,  TRUE },
-        { 2303800001LL,  2303899999LL, "2.3GHz General",                     NOBAND,  TRUE },
-        { 2303900000LL,  2303900000LL, "2.3GHz Packet/TTY/CW/EME",           NOBAND,  TRUE },
-        { 2303900001LL,  2304099999LL, "2.3GHz CW/EME",                      NOBAND,  TRUE },
-        { 2304100000LL,  2304100000LL, "2.3GHz Calling Frequency",           NOBAND,  TRUE },
-        { 2304100001LL,  2304199999LL, "2.3GHz CW/EME/SSB",                  NOBAND,  TRUE },
-        { 2304200000LL,  2304299999LL, "2.3GHz SSB/SSTV/FAX/Packet AM/Amtor",NOBAND,  TRUE },
-        { 2304300000LL,  2304319999LL, "2.3GHz Propagation Beacon Network",  NOBAND,  TRUE },
-        { 2304320000LL,  2304399999LL, "2.3GHz General Propagation Beacons", NOBAND,  TRUE },
-        { 2304400000LL,  2304499999LL, "2.3GHz SSB/SSTV/ACSSB/FAX/Packet AM",NOBAND,  TRUE },
-        { 2304500000LL,  2304699999LL, "2.3GHz X-Band Translator Input",     NOBAND,  TRUE },
-        { 2304700000LL,  2304899999LL, "2.3GHz X-Band Translator Output",    NOBAND,  TRUE },
-        { 2304900000LL,  2304999999LL, "2.3GHz Experimental Beacons",        NOBAND,  TRUE },
-        { 2305000000LL,  2305199999LL, "2.3GHz FM Simplex",                  NOBAND,  TRUE },
-        { 2305200000LL,  2305200000LL, "2.3GHz FM Simplex Calling",          NOBAND,  TRUE },
-        { 2305200001LL,  2305999999LL, "2.3GHz FM Simplex",                  NOBAND,  TRUE },
-        { 2306000000LL,  2308999999LL, "2.3GHz FM Repeaters",                NOBAND,  TRUE },
-        { 2309000000LL,  2310000000LL, "2.3GHz Control/Aux Links",           NOBAND,  TRUE },
-        { 2390000000LL,  2395999999LL, "2.3GHz Fast-Scan TV",                NOBAND,  TRUE },
-        { 2396000000LL,  2398999999LL, "2.3GHz High Rate Data",              NOBAND,  TRUE },
-        { 2399000000LL,  2399499999LL, "2.3GHz Packet",                      NOBAND,  TRUE },
-        { 2399500000LL,  2399999999LL, "2.3GHz Control/Aux Links",           NOBAND,  TRUE },
-        { 2400000000LL,  2402999999LL, "2.4GHz Satellite",                   NOBAND,  TRUE },
-        { 2403000000LL,  2407999999LL, "2.4GHz Satellite High-Rate Data",    NOBAND,  TRUE },
-        { 2408000000LL,  2409999999LL, "2.4GHz Satellite",                   NOBAND,  TRUE },
-        { 2410000000LL,  2412999999LL, "2.4GHz FM Repeaters",                NOBAND,  TRUE },
-        { 2413000000LL,  2417999999LL, "2.4GHz High-Rate Data",              NOBAND,  TRUE },
-        { 2418000000LL,  2429999999LL, "2.4GHz Fast-Scan TV",                NOBAND,  TRUE },
-        { 2430000000LL,  2432999999LL, "2.4GHz Satellite",                   NOBAND,  TRUE },
-        { 2433000000LL,  2437999999LL, "2.4GHz Sat High-Rate Data",          NOBAND,  TRUE },
-        { 2438000000LL,  2450000000LL, "2.4GHz Wideband FM/FSTV/FMTV",       NOBAND,  TRUE },
+        { 2300000000LL,  2449999999LL, "13cm",              NOBAND,  TRUE },
 
         { 3456000000LL,  3456099999LL, "3.4GHz General",                     NOBAND,  TRUE },
         { 3456100000LL,  3456100000LL, "3.4GHz Calling Frequency",           NOBAND,  TRUE },
@@ -370,9 +338,7 @@ struct frequency_info frequencyInfo[]=
         { 5760100001LL,  5760299999LL, "5.7GHz General",                     NOBAND,  TRUE },
         { 5760300000LL,  5760400000LL, "5.7GHz Propagation Beacons",         NOBAND,  TRUE },
 
-        {10368000000LL, 10368099999LL, "10GHz General",                      NOBAND,  TRUE },
-        {10368100000LL, 10368100000LL, "10GHz Calling Frequency",            NOBAND,  TRUE },
-        {10368100001LL, 10368400000LL, "10GHz General",                      NOBAND,  TRUE },
+        {10000000000LL, 10499999999LL, "10GHz",                              NOBAND,  TRUE },
 
         {24192000000LL, 24192099999LL, "24GHz General",                      NOBAND,  TRUE },
         {24192100000LL, 24192100000LL, "24GHz Calling Frequency",            NOBAND,  TRUE },
index 91685446f3106f7a0e7295e96ba2bd67b430a9f8..01e173f5064bdc89b8766714af9bb0274148ec19 100644 (file)
@@ -269,8 +269,8 @@ void general_menu(GtkWidget *parent) {
 
   }
 
-#ifdef LIMESDR
-  if(protocol==LIMESDR_PROTOCOL) {
+#ifdef SOAPYSDR
+  if(protocol==SOAPYSDR_PROTOCOL) {
     GtkWidget *sample_rate_1M=gtk_radio_button_new_with_label(NULL,"1000000");
     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_1M), sample_rate==1000000);
     gtk_grid_attach(GTK_GRID(grid),sample_rate_1M,0,2,1,1);
diff --git a/gpio.c b/gpio.c
index dccc90fa052850312f1a143bc15c2eab3aa77f1d..a69196bc2aac16e036968f288b52f90cf5249ed7 100644 (file)
--- a/gpio.c
+++ b/gpio.c
@@ -50,6 +50,7 @@
 #endif
 #include "new_menu.h"
 #include "encoder_menu.h"
+#include "diversity_menu.h"
 #include "gpio.h"
 #ifdef CONTROLLER2
 #include "i2c.h"
@@ -76,31 +77,39 @@ int VFO_ENCODER_B=0;
 #ifdef VFO_HAS_FUNCTION
 int VFO_FUNCTION=12;
 #endif
-int ENABLE_E1_ENCODER=1;
-int ENABLE_E1_PULLUP=0;
-int E1_ENCODER_A=28;
-int E1_ENCODER_B=25;
-int E1_FUNCTION=3;
 int ENABLE_E2_ENCODER=1;
-int ENABLE_E2_PULLUP=0;
-int E2_ENCODER_A=7;
-int E2_ENCODER_B=29;
-int E2_FUNCTION=2;
+int ENABLE_E2_PULLUP=1;
+int E2_ENCODER_A=21;
+int E2_ENCODER_B=22;
+int E2_TOP_ENCODER_A=25;
+int E2_TOP_ENCODER_B=28;
+int E2_FUNCTION=3;
 int ENABLE_E3_ENCODER=1;
-int ENABLE_E3_PULLUP=0;
-int E3_ENCODER_A=27;
-int E3_ENCODER_B=24;
-int E3_FUNCTION=4;
+int ENABLE_E3_PULLUP=1;
+int E3_ENCODER_A=13;
+int E3_ENCODER_B=11;
+int E3_TOP_ENCODER_A=29;
+int E3_TOP_ENCODER_B=7;
+int E3_FUNCTION=2;
 int ENABLE_E4_ENCODER=1;
-int ENABLE_E4_PULLUP=0;
-int E4_ENCODER_A=6;
-int E4_ENCODER_B=10;
-int E4_FUNCTION=5;
+int ENABLE_E4_PULLUP=1;
+int E4_ENCODER_A=14;
+int E4_ENCODER_B=12;
+int E4_TOP_ENCODER_A=24;
+int E4_TOP_ENCODER_B=27;
+int E4_FUNCTION=4;
+int ENABLE_E5_ENCODER=1;
+int ENABLE_E5_PULLUP=1;
+int E5_ENCODER_A=23;
+int E5_ENCODER_B=26;
+int E5_TOP_ENCODER_A=10;
+int E5_TOP_ENCODER_B=6;
+int E5_FUNCTION=5;
 
-int ENABLE_E1_BUTTON=1;
 int ENABLE_E2_BUTTON=1;
 int ENABLE_E3_BUTTON=1;
 int ENABLE_E4_BUTTON=1;
+int ENABLE_E5_BUTTON=1;
 
 int I2C_INTERRUPT=16;
 
@@ -110,21 +119,21 @@ int ENABLE_VFO_ENCODER=1;
 int ENABLE_VFO_PULLUP=1;
 int VFO_ENCODER_A=1;
 int VFO_ENCODER_B=0;
-int ENABLE_E1_ENCODER=1;
-int ENABLE_E1_PULLUP=0;
-int E1_ENCODER_A=28;
-int E1_ENCODER_B=25;
-int E1_FUNCTION=6;
 int ENABLE_E2_ENCODER=1;
 int ENABLE_E2_PULLUP=0;
-int E2_ENCODER_A=27;
-int E2_ENCODER_B=24;
-int E2_FUNCTION=10;
+int E2_ENCODER_A=28;
+int E2_ENCODER_B=25;
+int E2_FUNCTION=6;
 int ENABLE_E3_ENCODER=1;
 int ENABLE_E3_PULLUP=0;
-int E3_ENCODER_A=7;
-int E3_ENCODER_B=29;
-int E3_FUNCTION=11;
+int E3_ENCODER_A=27;
+int E3_ENCODER_B=24;
+int E3_FUNCTION=10;
+int ENABLE_E4_ENCODER=1;
+int ENABLE_E4_PULLUP=0;
+int E4_ENCODER_A=7;
+int E4_ENCODER_B=29;
+int E4_FUNCTION=11;
 int ENABLE_S1_BUTTON=1;
 int S1_BUTTON=23;
 int ENABLE_S2_BUTTON=1;
@@ -141,9 +150,9 @@ int ENABLE_MOX_BUTTON=1;
 int MOX_BUTTON=2;
 int ENABLE_FUNCTION_BUTTON=1;
 int FUNCTION_BUTTON=3;
-int ENABLE_E1_BUTTON=1;
 int ENABLE_E2_BUTTON=1;
 int ENABLE_E3_BUTTON=1;
+int ENABLE_E4_BUTTON=1;
 #endif
 
 #ifdef LOCALCW
@@ -155,24 +164,43 @@ int ENABLE_CW_BUTTONS=1;
 int CW_ACTIVE_LOW=1;
 #endif
 
-static volatile int vfoEncoderPos;
-static volatile int vfo_A;
-static volatile int vfo_B;
-static volatile int vfoFunction;
-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;
+int vfoEncoderPos;
+int vfoFunction;
+
 #ifdef CONTROLLER2
-static volatile int e4EncoderPos;
-static volatile int e4Function;
-int e4_encoder_action=ENCODER_MIC_GAIN;
+int e2EncoderPos;
+int e2_sw_action=MENU_BAND;
+int e2_encoder_action=ENCODER_AF_GAIN_RX2;
+int e3EncoderPos;
+int e3_sw_action=MENU_MODE;
+int e3_encoder_action=ENCODER_AGC_GAIN_RX2;
+int e4EncoderPos;
+int e4_sw_action=MENU_FILTER;
+int e4_encoder_action=ENCODER_IF_WIDTH_RX2;
+int e2_top_encoder_action=ENCODER_AF_GAIN_RX1;
+int e3_top_encoder_action=ENCODER_AGC_GAIN_RX1;
+int e4_top_encoder_action=ENCODER_IF_WIDTH_RX1;
+int e2TopEncoderPos;
+int e3TopEncoderPos;
+int e4TopEncoderPos;
+
+int e5_encoder_action=ENCODER_DRIVE;
+int e5_top_encoder_action=ENCODER_TUNE_DRIVE;
+int e5EncoderPos;
+int e5TopEncoderPos;
+int e5_sw_action=MENU_FREQUENCY;
+#else
+int e2EncoderPos;
+int e2_sw_action=RIT;
+int e2_encoder_action=ENCODER_AF_GAIN_RX1;
+int e3EncoderPos;
+int e3_sw_action=AGC;
+int e3_encoder_action=ENCODER_AGC_GAIN_RX1;
+int e4EncoderPos;
+int e4_sw_action=BAND_PLUS;
+int e4_encoder_action=ENCODER_DRIVE;
 #endif
+
 static volatile int function_state;
 static volatile int band_state;
 static volatile int bandstack_state;
@@ -187,16 +215,6 @@ static gpointer rotary_encoder_thread(gpointer data);
 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;
-#ifdef CONTROLLER2
-static int e4_function=0;
-static int previous_e4_function=0;
-#endif
 static int band_button=0;
 static int previous_band_button=0;
 static int bandstack_button=0;
@@ -214,25 +232,76 @@ static int previous_mox_button=0;
 
 static int running=0;
 
-char *encoder_string[] = {
-"AF GAIN",
-"AGC GAIN",
-#ifdef RADIOBERRY
-       "RX-GAIN",
-#else
-       "ATTENUATION",
+char *encoder_string[ENCODER_ACTIONS] = {
+  "AF GAIN RX1",
+  "RF GAIN RX1",
+  "AF GAIN RX2",
+  "RF GAIN RX2",
+  "AGC GAIN RX1",
+  "AGC GAIN RX2",
+  "IF WIDTH RX1",
+  "IF WIDTH RX2",
+  "ATTENUATION",
+  "MIC GAIN",
+  "DRIVE",
+  "TUNE DRIVE",
+  "RIT RX1",
+  "RIT RX2",
+  "XIT",
+  "CW SPEED",
+  "CW FREQUENCY",
+  "PANADAPTER HIGH",
+  "PANADAPTER LOW",
+  "SQUELCH",
+  "COMP",
+  "DIVERSITY GAIN",
+  "DIVERSITY PHASE"};
+
+char *sw_string[SWITCH_ACTIONS] = {
+  "NO ACTION",
+  "TUNE",
+  "MOX",
+  "PS",
+  "TWO TONE",
+  "NR",
+  "NB",
+  "SNB",
+  "RIT",
+  "RIT Clear",
+  "XIT",
+  "XIT Clear",
+  "BAND PLUS",
+  "BAND MINUS",
+  "BANDSTACK PLUS",
+  "BANDSTACK MINUS",
+  "MODE PLUS",
+  "MODE MINUS",
+  "FILTER PLUS",
+  "FILTER MINUS",
+  "A TO B",
+  "B TO A",
+  "A SWAP B",
+  "LOCK",
+  "CTUN",
+  "AGC",
+  "SPLIT",
+  "DIVERSITY",
+  "BAND MENU",
+  "BANDSTACK MENU",
+  "MODE MENU",
+  "FILTER MENU",
+  "FREQUENCY MENU",
+  "MEMORY MENU",
+  "DIVERSITY MENU",
+#ifndef CONTROLLER2
+  "FUNCTION",
 #endif
-"MIC GAIN",
-"DRIVE",
-"RIT",
-"CW SPEED",
-"CW FREQUENCY",
-"PANADAPTER HIGH",
-"PANADAPTER LOW",
-"SQUELCH",
-"COMP"
 };
 
+#ifdef CONTROLLER2
+int sw_action[SWITCHES] = {TUNE,MOX,PS,TWO_TONE,NR,A_TO_B,B_TO_A,MODE_MINUS,BAND_MINUS,MODE_PLUS,BAND_PLUS,XIT,NB,SNB,LOCK,CTUN};
+#endif
+
 static int mox_pressed(void *data) {
   if(running) sim_mox_cb(NULL,NULL);
   return 0;
@@ -324,26 +393,126 @@ static int vfo_function_released(void *data) {
 }
 
 static int e_function_pressed(void *data) {
-  int encoder=(int)data;
-  start_encoder(encoder);
+  int action=(int)data;
+fprintf(stderr,"e_function_pressed: %d\n",action);
+  switch(action) {
+    case TUNE:
+      g_idle_add(ext_tune_update,NULL);
+      break;
+    case MOX:
+      g_idle_add(ext_mox_update,NULL);
+      break;
+    case PS:
+      g_idle_add(ext_ps_update,NULL);
+      break;
+    case TWO_TONE:
+      g_idle_add(ext_two_tone,NULL);
+      break;
+    case NR:
+      g_idle_add(ext_nr_update,NULL);
+      break;
+    case NB:
+      g_idle_add(ext_nb_update,NULL);
+      break;
+    case SNB:
+      g_idle_add(ext_snb_update,NULL);
+      break;
+    case RIT:
+      g_idle_add(ext_rit_update,NULL);
+      break;
+    case RIT_CLEAR:
+      g_idle_add(ext_rit_clear,NULL);
+      break;
+    case XIT:
+      g_idle_add(ext_xit_update,NULL);
+      break;
+    case XIT_CLEAR:
+      g_idle_add(ext_xit_clear,NULL);
+      break;
+    case BAND_PLUS:
+      g_idle_add(ext_band_plus,NULL);
+      break;
+    case BAND_MINUS:
+      g_idle_add(ext_band_minus,NULL);
+      break;
+    case BANDSTACK_PLUS:
+      g_idle_add(ext_bandstack_plus,NULL);
+      break;
+    case BANDSTACK_MINUS:
+      g_idle_add(ext_bandstack_minus,NULL);
+      break;
+    case MODE_PLUS:
+      g_idle_add(ext_mode_plus,NULL);
+      break;
+    case MODE_MINUS:
+      g_idle_add(ext_mode_minus,NULL);
+      break;
+    case FILTER_PLUS:
+      g_idle_add(ext_filter_plus,NULL);
+      break;
+    case FILTER_MINUS:
+      g_idle_add(ext_filter_minus,NULL);
+      break;
+    case A_TO_B:
+      g_idle_add(ext_vfo_a_to_b,NULL);
+      break;
+    case B_TO_A:
+      g_idle_add(ext_vfo_b_to_a,NULL);
+      break;
+    case A_SWAP_B:
+      g_idle_add(ext_vfo_a_swap_b,NULL);
+      break;
+    case LOCK:
+      g_idle_add(ext_lock_update,NULL);
+      break;
+    case CTUN:
+      g_idle_add(ext_ctun_update,NULL);
+      break;
+    case AGC:
+      g_idle_add(ext_agc_update,NULL);
+      break;
+    case SPLIT:
+      g_idle_add(ext_split_update,NULL);
+      break;
+    case DIVERSITY:
+      g_idle_add(ext_diversity_update,GINT_TO_POINTER(0));
+      break;
+    case MENU_BAND:
+      g_idle_add(ext_band_update,NULL);
+      break;
+    case MENU_BANDSTACK:
+      g_idle_add(ext_bandstack_update,NULL);
+      break;
+    case MENU_MODE:
+      g_idle_add(ext_mode_update,NULL);
+      break;
+    case MENU_FILTER:
+      g_idle_add(ext_filter_update,NULL);
+      break;
+    case MENU_FREQUENCY:
+      g_idle_add(ext_frequency_update,NULL);
+      break;
+    case MENU_MEMORY:
+      g_idle_add(ext_memory_update,NULL);
+      break;
+    case MENU_DIVERSITY:
+      g_idle_add(ext_diversity_update,GINT_TO_POINTER(1));
+      break;
+#ifndef CONTROLLER2
+    case FUNCTION:
+      g_idle_add(ext_function_update,NULL);
+      break;
+#endif
+  }
   return 0;
 }
 
-static unsigned long e1debounce=0;
-
-static void e1FunctionAlert() {
-    int level=digitalRead(E1_FUNCTION);
-    if(level==0) {
-      if(running) g_idle_add(e_function_pressed,(gpointer)1);
-    }
-}
-
 static unsigned long e2debounce=0;
 
 static void e2FunctionAlert() {
     int level=digitalRead(E2_FUNCTION);
     if(level==0) {
-      if(running) g_idle_add(e_function_pressed,(gpointer)2);
+      if(running) g_idle_add(e_function_pressed,(gpointer)e2_sw_action);
     }
 }
 
@@ -352,17 +521,26 @@ static unsigned long e3debounce=0;
 static void e3FunctionAlert() {
     int level=digitalRead(E3_FUNCTION);
     if(level==0) {
-      if(running) g_idle_add(e_function_pressed,(gpointer)3);
+      if(running) g_idle_add(e_function_pressed,(gpointer)e3_sw_action);
     }
 }
 
-#ifdef CONTROLLER2
 static unsigned long e4debounce=0;
 
 static void e4FunctionAlert() {
     int level=digitalRead(E4_FUNCTION);
     if(level==0) {
-      if(running) g_idle_add(e_function_pressed,(gpointer)4);
+      if(running) g_idle_add(e_function_pressed,(gpointer)e4_sw_action);
+    }
+}
+
+#ifdef CONTROLLER2
+static unsigned long e5debounce=0;
+
+static void e5FunctionAlert() {
+    int level=digitalRead(E5_FUNCTION);
+    if(level==0) {
+      if(running) g_idle_add(e_function_pressed,(gpointer)e5_sw_action);
     }
 }
 #endif
@@ -600,8 +778,22 @@ static void vfoFunctionAlert() {
 #endif
 
 static void vfoEncoderInt(int A_or_B) {
-    int switch_A=digitalRead(VFO_ENCODER_A);
-    int switch_B=digitalRead(VFO_ENCODER_B);
+    static int vfoA=1, vfoB=1;
+    int levelA=digitalRead(VFO_ENCODER_A);
+    int levelB=digitalRead(VFO_ENCODER_B);
+
+  if(levelA!=vfoA) {
+    if(levelA==levelB) ++vfoEncoderPos;
+    if(levelA!=levelB) --vfoEncoderPos;
+    vfoA=levelA;
+  }
+/*
+  if(levelA!=e2CurrentA) {
+    if(levelA==levelB) ++e2EncoderPos;
+    if(levelA!=levelB) --e2EncoderPos;
+    e2CurrentA=levelA;
+  }
+
     if(vfo_A==switch_A && vfo_B==switch_B) {
       return; // same as last
     }
@@ -614,6 +806,7 @@ static void vfoEncoderInt(int A_or_B) {
         vfoEncoderPos++;
       }
     }
+*/
 }
 
 static void vfoEncoderA() {
@@ -624,65 +817,49 @@ static void vfoEncoderB() {
     vfoEncoderInt(VFO_ENCODER_B);
 }
 
-static void e1EncoderInterrupt(int gpio) {
-  static int e1CurrentA=1, e1CurrentB=1;
-
-  int levelA=digitalRead(E1_ENCODER_A);
-  int levelB=digitalRead(E1_ENCODER_B);
-
-  if(e1CurrentA==levelA && e1CurrentB==levelB) {
-    return;
-  }
+static void e2EncoderInterrupt(int gpio) {
+  static int e2CurrentA=1, e2CurrentB=1;
 
-  e1CurrentA=levelA;
-  e1CurrentB=levelB;
+  int levelA=digitalRead(E2_ENCODER_A);
+  int levelB=digitalRead(E2_ENCODER_B);
 
-  if(levelA && levelB) {
-    if(gpio==E1_ENCODER_B) {
-      --e1EncoderPos;
-    } else {
-      ++e1EncoderPos;
-    }
+  if(levelA!=e2CurrentA) {
+    if(levelA==levelB) ++e2EncoderPos;
+    if(levelA!=levelB) --e2EncoderPos;
+    e2CurrentA=levelA;
   }
 }
 
-static void e1EncoderA() {
-  e1EncoderInterrupt(E1_ENCODER_A);
+static void e2EncoderA() {
+  e2EncoderInterrupt(E2_ENCODER_A);
 }
 
-static void e1EncoderB() {
-  e1EncoderInterrupt(E1_ENCODER_B);
+static void e2EncoderB() {
+  e2EncoderInterrupt(E2_ENCODER_B);
 }
 
-static void e2EncoderInterrupt(int gpio) {
-  static int e2CurrentA=1, e2CurrentB=1;
-
-  int levelA=digitalRead(E2_ENCODER_A);
-  int levelB=digitalRead(E2_ENCODER_B);
-
-  if(e2CurrentA==levelA && e2CurrentB==levelB) {
-    return;
-  }
+#ifdef CONTROLLER2
+static void e2TopEncoderInterrupt(int gpio) {
+  static int e2TopCurrentA=1, e2TopCurrentB=1;
 
-  e2CurrentA=levelA;
-  e2CurrentB=levelB;
+  int levelA=digitalRead(E2_TOP_ENCODER_A);
+  int levelB=digitalRead(E2_TOP_ENCODER_B);
 
-  if(levelA && levelB) {
-    if(gpio==E2_ENCODER_B) {
-      --e2EncoderPos;
-    } else {
-      ++e2EncoderPos;
-    }
+  if(levelA!=e2TopCurrentA) {
+    if(levelA==levelB) ++e2TopEncoderPos;
+    if(levelA!=levelB) --e2TopEncoderPos;
+    e2TopCurrentA=levelA;
   }
 }
 
-static void e2EncoderA() {
-  e2EncoderInterrupt(E2_ENCODER_A);
+static void e2TopEncoderA() {
+  e2TopEncoderInterrupt(E2_TOP_ENCODER_A);
 }
 
-static void e2EncoderB() {
-  e2EncoderInterrupt(E2_ENCODER_B);
+static void e2TopEncoderB() {
+  e2TopEncoderInterrupt(E2_TOP_ENCODER_B);
 }
+#endif
 
 static void e3EncoderInterrupt(int gpio) {
   static int e3CurrentA=1, e3CurrentB=1;
@@ -690,19 +867,10 @@ static void e3EncoderInterrupt(int gpio) {
   int levelA=digitalRead(E3_ENCODER_A);
   int levelB=digitalRead(E3_ENCODER_B);
 
-  if(e3CurrentA==levelA && e3CurrentB==levelB) {
-    return;
-  }
-
-  e3CurrentA=levelA;
-  e3CurrentB=levelB;
-
-  if(levelA && levelB) {
-    if(gpio==E3_ENCODER_B) {
-      --e3EncoderPos;
-    } else {
-      ++e3EncoderPos;
-    }
+  if(levelA!=e3CurrentA) {
+    if(levelA==levelB) ++e3EncoderPos;
+    if(levelA!=levelB) --e3EncoderPos;
+    e3CurrentA=levelA;
   }
 }
 
@@ -715,25 +883,39 @@ static void e3EncoderB() {
 }
 
 #ifdef CONTROLLER2
+static void e3TopEncoderInterrupt(int gpio) {
+  static int e3TopCurrentA=1, e3TopCurrentB=1;
+
+  int levelA=digitalRead(E3_TOP_ENCODER_A);
+  int levelB=digitalRead(E3_TOP_ENCODER_B);
+
+
+  if(levelA!=e3TopCurrentA) {
+    if(levelA==levelB) ++e3TopEncoderPos;
+    if(levelA!=levelB) --e3TopEncoderPos;
+    e3TopCurrentA=levelA;
+  }
+}
+
+static void e3TopEncoderA() {
+  e3TopEncoderInterrupt(E3_TOP_ENCODER_A);
+}
+
+static void e3TopEncoderB() {
+  e3TopEncoderInterrupt(E3_TOP_ENCODER_B);
+}
+#endif
+
 static void e4EncoderInterrupt(int gpio) {
   static int e4CurrentA=1, e4CurrentB=1;
 
   int levelA=digitalRead(E4_ENCODER_A);
   int levelB=digitalRead(E4_ENCODER_B);
 
-  if(e4CurrentA==levelA && e4CurrentB==levelB) {
-    return;
-  }
-
-  e4CurrentA=levelA;
-  e4CurrentB=levelB;
-
-  if(levelA && levelB) {
-    if(gpio==E4_ENCODER_B) {
-      --e4EncoderPos;
-    } else {
-      ++e4EncoderPos;
-    }
+  if(levelA!=e4CurrentA) {
+    if(levelA==levelB) ++e4EncoderPos;
+    if(levelA!=levelB) --e4EncoderPos;
+    e4CurrentA=levelA;
   }
 }
 
@@ -744,6 +926,75 @@ static void e4EncoderA() {
 static void e4EncoderB() {
   e4EncoderInterrupt(E4_ENCODER_B);
 }
+
+#ifdef CONTROLLER2
+static void e4TopEncoderInterrupt(int gpio) {
+  static int e4TopCurrentA=1, e4TopCurrentB=1;
+
+  int levelA=digitalRead(E4_TOP_ENCODER_A);
+  int levelB=digitalRead(E4_TOP_ENCODER_B);
+
+  if(levelA!=e4TopCurrentA) {
+    if(levelA==levelB) ++e4TopEncoderPos;
+    if(levelA!=levelB) --e4TopEncoderPos;
+    e4TopCurrentA=levelA;
+  }
+}
+
+static void e4TopEncoderA() {
+  e4TopEncoderInterrupt(E4_TOP_ENCODER_A);
+}
+
+static void e4TopEncoderB() {
+  e4TopEncoderInterrupt(E4_TOP_ENCODER_B);
+}
+#endif
+
+
+#ifdef CONTROLLER2
+static void e5EncoderInterrupt(int gpio) {
+  static int e5CurrentA=1, e5CurrentB=1;
+
+  int levelA=digitalRead(E5_ENCODER_A);
+  int levelB=digitalRead(E5_ENCODER_B);
+
+
+  if(levelA!=e5CurrentA) {
+    if(levelA==levelB) ++e5EncoderPos;
+    if(levelA!=levelB) --e5EncoderPos;
+    e5CurrentA=levelA;
+  }
+}
+
+static void e5EncoderA() {
+  e5EncoderInterrupt(E5_ENCODER_A);
+}
+
+static void e5EncoderB() {
+  e5EncoderInterrupt(E5_ENCODER_B);
+}
+
+static void e5TopEncoderInterrupt(int gpio) {
+  static int e5TopCurrentA=1, e5TopCurrentB=1;
+
+  int levelA=digitalRead(E5_TOP_ENCODER_A);
+  int levelB=digitalRead(E5_TOP_ENCODER_B);
+
+  if(levelA!=e5TopCurrentA) {
+    if(levelA==levelB) ++e5TopEncoderPos;
+    if(levelA!=levelB) --e5TopEncoderPos;
+    e5TopCurrentA=levelA;
+  }
+}
+
+static void e5TopEncoderA() {
+  e5TopEncoderInterrupt(E5_TOP_ENCODER_A);
+}
+
+static void e5TopEncoderB() {
+  e5TopEncoderInterrupt(E5_TOP_ENCODER_B);
+}
+
 #endif
 
 #ifdef CONTROLLER2
@@ -755,8 +1006,50 @@ static void pI2CInterrupt() {
 }
 #endif
 
+void gpio_restore_actions() {
+  char* value;
+  char name[80];
+  int i;
+
+  value=getProperty("e2_encoder_action");
+  if(value) e2_encoder_action=atoi(value);
+  value=getProperty("e2_sw_action");
+  if(value) e2_sw_action=atoi(value);
+  value=getProperty("e3_encoder_action");
+  if(value) e3_encoder_action=atoi(value);
+  value=getProperty("e3_sw_action");
+  if(value) e3_sw_action=atoi(value);
+  value=getProperty("e4_encoder_action");
+  if(value) e4_encoder_action=atoi(value);
+  value=getProperty("e4_sw_action");
+  if(value) e4_sw_action=atoi(value);
+#ifdef CONTROLLER2
+  value=getProperty("e2_top_encoder_action");
+  if(value) e2_top_encoder_action=atoi(value);
+  value=getProperty("e3_top_encoder_action");
+  if(value) e3_top_encoder_action=atoi(value);
+  value=getProperty("e4_top_encoder_action");
+  if(value) e4_top_encoder_action=atoi(value);
+  value=getProperty("e5_encoder_action");
+  if(value) e5_encoder_action=atoi(value);
+  value=getProperty("e5_top_encoder_action");
+  if(value) e5_top_encoder_action=atoi(value);
+  value=getProperty("e5_sw_action");
+  if(value) e5_sw_action=atoi(value);
+  for(i=0;i<SWITCHES;i++) {
+    sprintf(name,"sw_action[%d]",i);
+    value=getProperty(name);           
+    if(value) sw_action[i]=atoi(value);                
+  }
+#endif
+
+}
+
 void gpio_restore_state() {
   char* value;
+  char name[80];
+  int i;
+
   loadProperties("gpio.props");
   value=getProperty("ENABLE_VFO_ENCODER");
   if(value) ENABLE_VFO_ENCODER=atoi(value);
@@ -766,14 +1059,6 @@ void gpio_restore_state() {
   if(value) VFO_ENCODER_A=atoi(value);
   value=getProperty("VFO_ENCODER_B");
   if(value) VFO_ENCODER_B=atoi(value);
-  value=getProperty("ENABLE_E1_ENCODER");
-  if(value) ENABLE_E1_ENCODER=atoi(value);
-  value=getProperty("ENABLE_E1_PULLUP");
-  if(value) ENABLE_E1_PULLUP=atoi(value);
-  value=getProperty("E1_ENCODER_A");
-  if(value) E1_ENCODER_A=atoi(value);
-  value=getProperty("E1_ENCODER_B");
-  if(value) E1_ENCODER_B=atoi(value);
   value=getProperty("ENABLE_E2_ENCODER");
   if(value) ENABLE_E2_ENCODER=atoi(value);
   value=getProperty("ENABLE_E2_PULLUP");
@@ -790,7 +1075,6 @@ void gpio_restore_state() {
   if(value) E3_ENCODER_A=atoi(value);
   value=getProperty("E3_ENCODER_B");
   if(value) E3_ENCODER_B=atoi(value);
-#ifdef CONTROLLER2
   value=getProperty("ENABLE_E4_ENCODER");
   if(value) ENABLE_E4_ENCODER=atoi(value);
   value=getProperty("ENABLE_E4_PULLUP");
@@ -799,6 +1083,15 @@ void gpio_restore_state() {
   if(value) E4_ENCODER_A=atoi(value);
   value=getProperty("E4_ENCODER_B");
   if(value) E4_ENCODER_B=atoi(value);
+#ifdef CONTROLLER2
+  value=getProperty("ENABLE_E5_ENCODER");
+  if(value) ENABLE_E5_ENCODER=atoi(value);
+  value=getProperty("ENABLE_E5_PULLUP");
+  if(value) ENABLE_E5_PULLUP=atoi(value);
+  value=getProperty("E5_ENCODER_A");
+  if(value) E5_ENCODER_A=atoi(value);
+  value=getProperty("E5_ENCODER_B");
+  if(value) E5_ENCODER_B=atoi(value);
 #endif
 #ifndef CONTROLLER2
   value=getProperty("ENABLE_S1_BUTTON");
@@ -835,15 +1128,15 @@ void gpio_restore_state() {
   if(value) MOX_BUTTON=atoi(value);
 #endif
 
-  value=getProperty("ENABLE_E1_BUTTON");
-  if(value) ENABLE_E1_BUTTON=atoi(value);
   value=getProperty("ENABLE_E2_BUTTON");
   if(value) ENABLE_E2_BUTTON=atoi(value);
   value=getProperty("ENABLE_E3_BUTTON");
   if(value) ENABLE_E3_BUTTON=atoi(value);
-#ifdef CONTROLLER2
   value=getProperty("ENABLE_E4_BUTTON");
   if(value) ENABLE_E4_BUTTON=atoi(value);
+#ifdef CONTROLLER2
+  value=getProperty("ENABLE_E5_BUTTON");
+  if(value) ENABLE_E5_BUTTON=atoi(value);
 #endif
 #ifdef LOCALCW         
  value=getProperty("ENABLE_CW_BUTTONS");               
@@ -860,11 +1153,50 @@ void gpio_restore_state() {
  if(value) ENABLE_GPIO_SIDETONE=atoi(value);           
 #endif
 
+}
+
+void gpio_save_actions() {
+  int i;
+  char name[80];
+  char value[80];
+  sprintf(value,"%d",e2_sw_action);
+  setProperty("e2_sw_action",value);
+  sprintf(value,"%d",e2_encoder_action);
+  setProperty("e2_encoder_action",value);
+  sprintf(value,"%d",e3_sw_action);
+  setProperty("e3_sw_action",value);
+  sprintf(value,"%d",e3_encoder_action);
+  setProperty("e3_encoder_action",value);
+  sprintf(value,"%d",e4_sw_action);
+  setProperty("e4_sw_action",value);
+  sprintf(value,"%d",e4_encoder_action);
+  setProperty("e4_encoder_action",value);
+#ifdef CONTROLLER2
+  sprintf(value,"%d",e2_top_encoder_action);
+  setProperty("e2_top_encoder_action",value);
+  sprintf(value,"%d",e3_top_encoder_action);
+  setProperty("e3_top_encoder_action",value);
+  sprintf(value,"%d",e4_top_encoder_action);
+  setProperty("e4_top_encoder_action",value);
+  sprintf(value,"%d",e5_sw_action);
+  setProperty("e5_sw_action",value);
+  sprintf(value,"%d",e5_encoder_action);
+  setProperty("e5_encoder_action",value);
+  sprintf(value,"%d",e5_top_encoder_action);
+  setProperty("e5_top_encoder_action",value);
+  for(i=0;i<SWITCHES;i++) {
+    sprintf(name,"sw_action[%d]",i);
+    sprintf(value,"%d",sw_action[i]);
+    setProperty(name,value);           
+  }
+#endif
 
 }
 
 void gpio_save_state() {
-   char value[80];
+  int i;
+  char name[80];
+  char value[80];
 
   sprintf(value,"%d",ENABLE_VFO_ENCODER);
   setProperty("ENABLE_VFO_ENCODER",value);
@@ -874,14 +1206,6 @@ void gpio_save_state() {
   setProperty("VFO_ENCODER_A",value);
   sprintf(value,"%d",VFO_ENCODER_B);
   setProperty("VFO_ENCODER_B",value);
-  sprintf(value,"%d",ENABLE_E1_ENCODER);
-  setProperty("ENABLE_E1_ENCODER",value);
-  sprintf(value,"%d",ENABLE_E1_PULLUP);
-  setProperty("ENABLE_E1_PULLUP",value);
-  sprintf(value,"%d",E1_ENCODER_A);
-  setProperty("E1_ENCODER_A",value);
-  sprintf(value,"%d",E1_ENCODER_B);
-  setProperty("E1_ENCODER_B",value);
   sprintf(value,"%d",ENABLE_E2_ENCODER);
   setProperty("ENABLE_E2_ENCODER",value);
   sprintf(value,"%d",ENABLE_E2_PULLUP);
@@ -898,7 +1222,6 @@ void gpio_save_state() {
   setProperty("E3_ENCODER_A",value);
   sprintf(value,"%d",E3_ENCODER_B);
   setProperty("E3_ENCODER_B",value);
-#ifdef CONTROLLER2
   sprintf(value,"%d",ENABLE_E4_ENCODER);
   setProperty("ENABLE_E4_ENCODER",value);
   sprintf(value,"%d",ENABLE_E4_PULLUP);
@@ -907,6 +1230,15 @@ void gpio_save_state() {
   setProperty("E4_ENCODER_A",value);
   sprintf(value,"%d",E4_ENCODER_B);
   setProperty("E4_ENCODER_B",value);
+#ifdef CONTROLLER2
+  sprintf(value,"%d",ENABLE_E5_ENCODER);
+  setProperty("ENABLE_E5_ENCODER",value);
+  sprintf(value,"%d",ENABLE_E5_PULLUP);
+  setProperty("ENABLE_E5_PULLUP",value);
+  sprintf(value,"%d",E5_ENCODER_A);
+  setProperty("E5_ENCODER_A",value);
+  sprintf(value,"%d",E5_ENCODER_B);
+  setProperty("E5_ENCODER_B",value);
 #endif
 #ifndef CONTROLLER2
   sprintf(value,"%d",ENABLE_S1_BUTTON);
@@ -943,49 +1275,58 @@ void gpio_save_state() {
   setProperty("MOX_BUTTON",value);
 #endif
 
-  sprintf(value,"%d",ENABLE_E1_BUTTON);
-  setProperty("ENABLE_E1_BUTTON",value);
   sprintf(value,"%d",ENABLE_E2_BUTTON);
   setProperty("ENABLE_E2_BUTTON",value);
   sprintf(value,"%d",ENABLE_E3_BUTTON);
   setProperty("ENABLE_E3_BUTTON",value);
-#ifdef CONTROLLER2
   sprintf(value,"%d",ENABLE_E4_BUTTON);
   setProperty("ENABLE_E4_BUTTON",value);
+#ifdef CONTROLLER2
+  sprintf(value,"%d",ENABLE_E5_BUTTON);
+  setProperty("ENABLE_E5_BUTTON",value);
 #endif
 #ifdef LOCALCW         
- sprintf(value,"%d",ENABLE_CW_BUTTONS);                
- setProperty("ENABLE_CW_BUTTONS",value);               
- sprintf(value,"%d",CW_ACTIVE_LOW);            
- setProperty("CW_ACTIVE_LOW",value);           
- sprintf(value,"%d",CWL_BUTTON);               
- setProperty("CWL_BUTTON",value);              
- sprintf(value,"%d",CWR_BUTTON);               
- setProperty("CWR_BUTTON",value);              
- sprintf(value,"%d",SIDETONE_GPIO);            
- setProperty("SIDETONE_GPIO",value);           
- sprintf(value,"%d",ENABLE_GPIO_SIDETONE);             
- setProperty("ENABLE_GPIO_SIDETONE",value);            
+  sprintf(value,"%d",ENABLE_CW_BUTTONS);               
+  setProperty("ENABLE_CW_BUTTONS",value);              
+  sprintf(value,"%d",CW_ACTIVE_LOW);           
+  setProperty("CW_ACTIVE_LOW",value);          
+  sprintf(value,"%d",CWL_BUTTON);              
+  setProperty("CWL_BUTTON",value);             
+  sprintf(value,"%d",CWR_BUTTON);              
+  setProperty("CWR_BUTTON",value);             
+  sprintf(value,"%d",SIDETONE_GPIO);           
+  setProperty("SIDETONE_GPIO",value);          
+  sprintf(value,"%d",ENABLE_GPIO_SIDETONE);            
+  setProperty("ENABLE_GPIO_SIDETONE",value);           
 #endif
 
   saveProperties("gpio.props");
+
 }
 
 static void setup_pin(int pin, int up_down, void(*pAlert)(void)) {
-fprintf(stderr,"setup_pin: pin=%d mode=%d updown=%d\n",pin,INPUT,up_down);
+  int rc;
   pinMode(pin,INPUT);
   pullUpDnControl(pin,up_down);
   usleep(10000);
-  wiringPiISR(pin,INT_EDGE_BOTH,pAlert);
+  rc=wiringPiISR(pin,INT_EDGE_FALLING,pAlert);
+  if(rc<0) {
+    fprintf(stderr,"wirngPiISR returned %d\n",rc);
+  }
 }
 
 
 static void setup_encoder_pin(int pin, int up_down, void(*pAlert)(void)) {
-fprintf(stderr,"setup_encoder_pin: pin=%d updown=%d\n",pin,up_down);
-    pinMode(pin,INPUT);
-    pullUpDnControl(pin,up_down);
-    usleep(10000);
-    wiringPiISR(pin,INT_EDGE_RISING,pAlert);
+  int rc;
+  pinMode(pin,INPUT);
+  pullUpDnControl(pin,up_down);
+  usleep(10000);
+  if(pAlert!=NULL) {
+    rc=wiringPiISR(pin,INT_EDGE_BOTH,pAlert);
+    if(rc<0) {
+      fprintf(stderr,"wirngPiISR returned %d\n",rc);
+    }
+  }
 }
 
 #ifdef LOCALCW
@@ -995,11 +1336,14 @@ fprintf(stderr,"setup_encoder_pin: pin=%d updown=%d\n",pin,up_down);
 //
 
 static void setup_cw_pin(int pin, void(*pAlert)(void)) {
-   fprintf(stderr,"setup_cw_pin: pin=%d \n",pin);
-   pinMode(pin,INPUT);
-   pullUpDnControl(pin,PUD_UP);
-   usleep(10000);
-   wiringPiISR(pin,INT_EDGE_BOTH,pAlert);
+  int rc;
+  pinMode(pin,INPUT);
+  pullUpDnControl(pin,PUD_UP);
+  usleep(10000);
+  rc=wiringPiISR(pin,INT_EDGE_BOTH,pAlert);
+  if(rc<0) {
+    fprintf(stderr,"wirngPiISR returned %d\n",rc);
+  }
 }
 
 static void cwAlert_left() {
@@ -1060,56 +1404,79 @@ int gpio_init() {
     setup_pin(VFO_FUNCTION, PUD_UP, &vfoFunctionAlert);
     vfoFunction=0;
 #endif
-    vfo_A=1;
-    vfo_B=1;
     setup_encoder_pin(VFO_ENCODER_A,ENABLE_VFO_PULLUP?PUD_UP:PUD_DOWN,&vfoEncoderA);
-    setup_encoder_pin(VFO_ENCODER_B,ENABLE_VFO_PULLUP?PUD_UP:PUD_DOWN,&vfoEncoderB);
+    setup_encoder_pin(VFO_ENCODER_B,ENABLE_VFO_PULLUP?PUD_UP:PUD_DOWN,NULL);
+    //setup_encoder_pin(VFO_ENCODER_B,ENABLE_VFO_PULLUP?PUD_UP:PUD_DOWN,&vfoEncoderB);
 #else
-    vfo_A=1;
-    vfo_B=1;
     setup_encoder_pin(VFO_ENCODER_A,ENABLE_VFO_PULLUP?PUD_UP:PUD_DOWN,&vfoEncoderA);
-    setup_encoder_pin(VFO_ENCODER_B,ENABLE_VFO_PULLUP?PUD_UP:PUD_DOWN,&vfoEncoderB);
-    //setup_pin(VFO_ENCODER_A,ENABLE_VFO_PULLUP?PUD_UP:PUD_OFF,&vfoEncoderA);
-    //setup_pin(VFO_ENCODER_B,ENABLE_VFO_PULLUP?PUD_UP:PUD_OFF,&vfoEncoderB);
+    setup_encoder_pin(VFO_ENCODER_B,ENABLE_VFO_PULLUP?PUD_UP:PUD_DOWN,NULL);
+    //setup_encoder_pin(VFO_ENCODER_B,ENABLE_VFO_PULLUP?PUD_UP:PUD_DOWN,&vfoEncoderB);
 #endif
     vfoEncoderPos=0;
   }
 
-  if(ENABLE_E1_ENCODER) {
-       setup_pin(E1_FUNCTION, PUD_UP, &e1FunctionAlert);
-       e1Function=0;  
-         
-    setup_encoder_pin(E1_ENCODER_A,ENABLE_E1_PULLUP?PUD_UP:PUD_OFF,&e1EncoderA);
-    setup_encoder_pin(E1_ENCODER_B,ENABLE_E1_PULLUP?PUD_UP:PUD_OFF,&e1EncoderB);
-    e1EncoderPos=0;
-  }
-
   if(ENABLE_E2_ENCODER) {
-       setup_pin(E2_FUNCTION, PUD_UP, &e2FunctionAlert);
-       e2Function=0;
-       
+    setup_pin(E2_FUNCTION, PUD_UP, &e2FunctionAlert);
+         
     setup_encoder_pin(E2_ENCODER_A,ENABLE_E2_PULLUP?PUD_UP:PUD_OFF,&e2EncoderA);
-    setup_encoder_pin(E2_ENCODER_B,ENABLE_E2_PULLUP?PUD_UP:PUD_OFF,&e2EncoderB);
+    setup_encoder_pin(E2_ENCODER_B,ENABLE_E2_PULLUP?PUD_UP:PUD_OFF,NULL);
+    //setup_encoder_pin(E2_ENCODER_B,ENABLE_E2_PULLUP?PUD_UP:PUD_OFF,&e2EncoderB);
     e2EncoderPos=0;
+
+
+#ifdef CONTROLLER2
+    setup_encoder_pin(E2_TOP_ENCODER_A,ENABLE_E2_PULLUP?PUD_UP:PUD_OFF,&e2TopEncoderA);
+    setup_encoder_pin(E2_TOP_ENCODER_B,ENABLE_E2_PULLUP?PUD_UP:PUD_OFF,NULL);
+    //setup_encoder_pin(E2_TOP_ENCODER_B,ENABLE_E2_PULLUP?PUD_UP:PUD_OFF,&e2TopEncoderB);
+    e2TopEncoderPos=0;
+#endif
   }
 
   if(ENABLE_E3_ENCODER) {
-       setup_pin(E3_FUNCTION, PUD_UP, &e3FunctionAlert);
-       e3Function=0;  
-         
+    setup_pin(E3_FUNCTION, PUD_UP, &e3FunctionAlert);
+       
     setup_encoder_pin(E3_ENCODER_A,ENABLE_E3_PULLUP?PUD_UP:PUD_OFF,&e3EncoderA);
-    setup_encoder_pin(E3_ENCODER_B,ENABLE_E3_PULLUP?PUD_UP:PUD_OFF,&e3EncoderB);
+    setup_encoder_pin(E3_ENCODER_B,ENABLE_E3_PULLUP?PUD_UP:PUD_OFF,NULL);
+    //setup_encoder_pin(E3_ENCODER_B,ENABLE_E3_PULLUP?PUD_UP:PUD_OFF,&e3EncoderB);
     e3EncoderPos=0;
-  }
 
 #ifdef CONTROLLER2
-  setup_pin(E4_FUNCTION, PUD_UP, &e4FunctionAlert);
-  e4Function=0;
+    setup_encoder_pin(E3_TOP_ENCODER_A,ENABLE_E3_PULLUP?PUD_UP:PUD_OFF,&e3TopEncoderA);
+    setup_encoder_pin(E3_TOP_ENCODER_B,ENABLE_E3_PULLUP?PUD_UP:PUD_OFF,NULL);
+    //setup_encoder_pin(E3_TOP_ENCODER_B,ENABLE_E3_PULLUP?PUD_UP:PUD_OFF,&e3TopEncoderB);
+    e3TopEncoderPos=0;
+#endif
+  }
 
   if(ENABLE_E4_ENCODER) {
+    setup_pin(E4_FUNCTION, PUD_UP, &e4FunctionAlert);
+         
     setup_encoder_pin(E4_ENCODER_A,ENABLE_E4_PULLUP?PUD_UP:PUD_OFF,&e4EncoderA);
-    setup_encoder_pin(E4_ENCODER_B,ENABLE_E4_PULLUP?PUD_UP:PUD_OFF,&e4EncoderB);
+    setup_encoder_pin(E4_ENCODER_B,ENABLE_E4_PULLUP?PUD_UP:PUD_OFF,NULL);
+    //setup_encoder_pin(E4_ENCODER_B,ENABLE_E4_PULLUP?PUD_UP:PUD_OFF,&e4EncoderB);
     e4EncoderPos=0;
+         
+#ifdef CONTROLLER2
+    setup_encoder_pin(E4_TOP_ENCODER_A,ENABLE_E4_PULLUP?PUD_UP:PUD_OFF,&e4TopEncoderA);
+    setup_encoder_pin(E4_TOP_ENCODER_B,ENABLE_E4_PULLUP?PUD_UP:PUD_OFF,NULL);
+    //setup_encoder_pin(E4_TOP_ENCODER_B,ENABLE_E4_PULLUP?PUD_UP:PUD_OFF,&e4TopEncoderB);
+    e4TopEncoderPos=0;
+#endif
+  }
+
+#ifdef CONTROLLER2
+  if(ENABLE_E5_ENCODER) {
+    setup_pin(E5_FUNCTION, PUD_UP, &e5FunctionAlert);
+
+    setup_encoder_pin(E5_ENCODER_A,ENABLE_E5_PULLUP?PUD_UP:PUD_OFF,&e5EncoderA);
+    setup_encoder_pin(E5_ENCODER_B,ENABLE_E5_PULLUP?PUD_UP:PUD_OFF,NULL);
+    //setup_encoder_pin(E5_ENCODER_B,ENABLE_E5_PULLUP?PUD_UP:PUD_OFF,&e5EncoderB);
+    e5EncoderPos=0;
+
+    setup_encoder_pin(E5_TOP_ENCODER_A,ENABLE_E5_PULLUP?PUD_UP:PUD_OFF,&e5TopEncoderA);
+    setup_encoder_pin(E5_TOP_ENCODER_B,ENABLE_E5_PULLUP?PUD_UP:PUD_OFF,NULL);
+    //setup_encoder_pin(E5_TOP_ENCODER_B,ENABLE_E5_PULLUP?PUD_UP:PUD_OFF,&e5TopEncoderB);
+    e5TopEncoderPos=0;
   }
 #endif
 
@@ -1209,12 +1576,6 @@ int vfo_encoder_get_pos() {
   return pos;
 }
 
-int e1_encoder_get_pos() {
-    int pos=e1EncoderPos;
-    e1EncoderPos=0;
-    return pos;
-}
-
 int e2_encoder_get_pos() {
     int pos=e2EncoderPos;
     e2EncoderPos=0;
@@ -1227,16 +1588,46 @@ int e3_encoder_get_pos() {
     return pos;
 }
 
-int e3_function_get_state() {
-    return e3Function;
-}
-
-#ifdef CONTROLLER2
 int e4_encoder_get_pos() {
     int pos=e4EncoderPos;
     e4EncoderPos=0;
     return pos;
 }
+
+int e4_function_get_state() {
+    return e4_sw_action;
+}
+
+#ifdef CONTROLLER2
+int e2_top_encoder_get_pos() {
+    int pos=e2TopEncoderPos;
+    e2TopEncoderPos=0;
+    return pos;
+}
+
+int e3_top_encoder_get_pos() {
+    int pos=e3TopEncoderPos;
+    e3TopEncoderPos=0;
+    return pos;
+}
+
+int e4_top_encoder_get_pos() {
+    int pos=e4TopEncoderPos;
+    e4TopEncoderPos=0;
+    return pos;
+}
+
+int e5_encoder_get_pos() {
+    int pos=e5EncoderPos;
+    e5EncoderPos=0;
+    return pos;
+}
+
+int e5_top_encoder_get_pos() {
+    int pos=e5TopEncoderPos;
+    e5TopEncoderPos=0;
+    return pos;
+}
 #endif
 
 int function_get_state() {
@@ -1295,25 +1686,51 @@ static void encoder_changed(int action,int pos) {
   int new_val;
 
   switch(action) {
-    case ENCODER_AF_GAIN:
-      value=active_receiver->volume;
+    case ENCODER_AF_GAIN_RX1:
+      value=receiver[0]->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);
+      set_af_gain(0,value);
+      break;
+    case ENCODER_AF_GAIN_RX2:
+      value=receiver[1]->volume;
+      value+=(double)pos/100.0;
+      if(value<0.0) {
+        value=0.0;
+      } else if(value>1.0) {
+        value=1.0;
+      }
+      set_af_gain(1,value);
+      break;
+    case ENCODER_AGC_GAIN_RX1:
+      value=receiver[0]->agc_gain;
+      value+=(double)pos;
+      if(value<-20.0) {
+        value=-20.0;
+      } else if(value>120.0) {
+        value=120.0;
+      }
+      set_agc_gain(0,value);
       break;
-    case ENCODER_AGC_GAIN:
-      value=active_receiver->agc_gain;
+    case ENCODER_AGC_GAIN_RX2:
+      value=receiver[1]->agc_gain;
       value+=(double)pos;
       if(value<-20.0) {
         value=-20.0;
       } else if(value>120.0) {
         value=120.0;
       }
-      set_agc_gain(value);
+      set_agc_gain(1,value);
+      break;
+    case ENCODER_IF_WIDTH_RX1:
+      filter_width_changed(0,pos);
+      break;
+    case ENCODER_IF_WIDTH_RX2:
+      filter_width_changed(1,pos);
       break;
     case ENCODER_ATTENUATION:
       value=(double)adc_attenuation[active_receiver->adc];
@@ -1333,7 +1750,6 @@ static void encoder_changed(int action,int pos) {
       break;
     case ENCODER_MIC_GAIN:
       value=mic_gain;
-      //gain+=(double)pos/100.0;
       value+=(double)pos;
       if(value<-10.0) {
         value=-10.0;
@@ -1352,15 +1768,29 @@ static void encoder_changed(int action,int pos) {
       }
       set_drive(value);
       break;
-    case ENCODER_RIT:
-      value=(double)vfo[active_receiver->id].rit;
+    case ENCODER_RIT_RX1:
+      value=(double)vfo[receiver[0]->id].rit;
       value+=(double)(pos*rit_increment);
       if(value<-1000.0) {
         value=-1000.0;
       } else if(value>1000.0) {
         value=1000.0;
       }
-      vfo[active_receiver->id].rit=(int)value;
+      vfo[receiver[0]->id].rit=(int)value;
+      if(protocol==NEW_PROTOCOL) {
+        schedule_high_priority();
+      }
+      g_idle_add(ext_vfo_update,NULL);
+      break;
+    case ENCODER_RIT_RX2:
+      value=(double)vfo[receiver[1]->id].rit;
+      value+=(double)(pos*rit_increment);
+      if(value<-1000.0) {
+        value=-1000.0;
+      } else if(value>1000.0) {
+        value=1000.0;
+      }
+      vfo[receiver[1]->id].rit=(int)value;
       if(protocol==NEW_PROTOCOL) {
         schedule_high_priority();
       }
@@ -1420,49 +1850,99 @@ static void encoder_changed(int action,int pos) {
       transmitter->compressor_level=(int)value;
       set_compression(transmitter);
       break;
+    case ENCODER_DIVERSITY_GAIN:
+      update_diversity_gain((double)pos);
+      break;
+    case ENCODER_DIVERSITY_PHASE:
+      update_diversity_phase((double)pos);
+      break;
   }
 }
 
-static int e1_encoder_changed(void *data) {
+static int e2_encoder_changed(void *data) {
   int pos=(int)data;
-  if(active_menu==E1_MENU) {
+  if(active_menu==E2_MENU) {
     encoder_select(pos);
   } else {
-    encoder_changed(e1_encoder_action,pos);
+    encoder_changed(e2_encoder_action,pos);
   }
   //free(data);
   return 0;
 }
 
-static int e2_encoder_changed(void *data) {
+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 e4_encoder_changed(void *data) {
+  int pos=(int)data;
+  if(active_menu==E4_MENU) {
+    encoder_select(pos);
+  } else {
+    encoder_changed(e4_encoder_action,pos);
+  }
+  //free(data);
+  return 0;
+}
+
+#ifdef CONTROLLER2
+static int e2_top_encoder_changed(void *data) {
   int pos=(int)data;
   if(active_menu==E2_MENU) {
     encoder_select(pos);
   } else {
-    encoder_changed(e2_encoder_action,pos);
+    encoder_changed(e2_top_encoder_action,pos);
   }
   //free(data);
   return 0;
 }
 
-static int e3_encoder_changed(void *data) {
+static int e3_top_encoder_changed(void *data) {
   int pos=(int)data;
   if(active_menu==E3_MENU) {
     encoder_select(pos);
   } else {
-    encoder_changed(e3_encoder_action,pos);
+    encoder_changed(e3_top_encoder_action,pos);
   }
   //free(data);
   return 0;
 }
 
-#ifdef CONTROLLER2
-static int e4_encoder_changed(void *data) {
+static int e4_top_encoder_changed(void *data) {
   int pos=(int)data;
   if(active_menu==E4_MENU) {
     encoder_select(pos);
   } else {
-    encoder_changed(e4_encoder_action,pos);
+    encoder_changed(e4_top_encoder_action,pos);
+  }
+  //free(data);
+  return 0;
+}
+
+static int e5_encoder_changed(void *data) {
+  int pos=(int)data;
+  if(active_menu==E5_MENU) {
+    encoder_select(pos);
+  } else {
+    encoder_changed(e5_encoder_action,pos);
+  }
+  //free(data);
+  return 0;
+}
+
+static int e5_top_encoder_changed(void *data) {
+  int pos=(int)data;
+  if(active_menu==E5_MENU) {
+    encoder_select(pos);
+  } else {
+    encoder_changed(e5_top_encoder_action,pos);
   }
   //free(data);
   return 0;
@@ -1482,11 +1962,6 @@ static gpointer rotary_encoder_thread(gpointer data) {
             g_idle_add(vfo_encoder_changed,(gpointer)pos);
         }
 
-        pos=e1_encoder_get_pos();
-        if(pos!=0) {
-            g_idle_add(e1_encoder_changed,(gpointer)pos);
-        }
-
         pos=e2_encoder_get_pos();
         if(pos!=0) {
             g_idle_add(e2_encoder_changed,(gpointer)pos);
@@ -1497,11 +1972,36 @@ static gpointer rotary_encoder_thread(gpointer data) {
             g_idle_add(e3_encoder_changed,(gpointer)pos);
         }
 
-#ifdef CONTROLLER2
         pos=e4_encoder_get_pos();
         if(pos!=0) {
             g_idle_add(e4_encoder_changed,(gpointer)pos);
         }
+
+#ifdef CONTROLLER2
+        pos=e2_top_encoder_get_pos();
+        if(pos!=0) {
+            g_idle_add(e2_top_encoder_changed,(gpointer)pos);
+        }
+
+        pos=e3_top_encoder_get_pos();
+        if(pos!=0) {
+            g_idle_add(e3_top_encoder_changed,(gpointer)pos);
+        }
+
+        pos=e4_top_encoder_get_pos();
+        if(pos!=0) {
+            g_idle_add(e4_top_encoder_changed,(gpointer)pos);
+        }
+
+        pos=e5_encoder_get_pos();
+        if(pos!=0) {
+            g_idle_add(e5_encoder_changed,(gpointer)pos);
+        }
+
+        pos=e5_top_encoder_get_pos();
+        if(pos!=0) {
+            g_idle_add(e5_top_encoder_changed,(gpointer)pos);
+        }
 #endif
 
 #ifdef sx1509
diff --git a/gpio.h b/gpio.h
index e2253f3eaf75bf0ae89eedd2ff060188ec8c88f0..67575451179ae701f706a6e7d72faec46f66b5e4 100644 (file)
--- a/gpio.h
+++ b/gpio.h
 #define _GPIO_H
 
 enum {
-  ENCODER_AF_GAIN=0,
-  ENCODER_AGC_GAIN,
+  ENCODER_AF_GAIN_RX1=0,
+  ENCODER_RF_GAIN_RX1,
+  ENCODER_AF_GAIN_RX2,
+  ENCODER_RF_GAIN_RX2,
+  ENCODER_AGC_GAIN_RX1,
+  ENCODER_AGC_GAIN_RX2,
+  ENCODER_IF_WIDTH_RX1,
+  ENCODER_IF_WIDTH_RX2,
   ENCODER_ATTENUATION,
   ENCODER_MIC_GAIN,
   ENCODER_DRIVE,
-//  ENCODER_TUNE_DRIVE,
-  ENCODER_RIT,
+  ENCODER_TUNE_DRIVE,
+  ENCODER_RIT_RX1,
+  ENCODER_RIT_RX2,
+  ENCODER_XIT,
   ENCODER_CW_SPEED,
   ENCODER_CW_FREQUENCY,
   ENCODER_PANADAPTER_HIGH,
   ENCODER_PANADAPTER_LOW,
   ENCODER_SQUELCH,
   ENCODER_COMP,
-  ENCODER_LAST
+  ENCODER_DIVERSITY_GAIN,
+  ENCODER_DIVERSITY_PHASE,
+  ENCODER_ACTIONS
 };
 
+extern char *encoder_string[ENCODER_ACTIONS];
+
+enum {
+  NO_ACTION=0,
+  TUNE,
+  MOX,
+  PS,
+  TWO_TONE,
+  NR,
+  NB,
+  SNB,
+  RIT,
+  RIT_CLEAR,
+  XIT,
+  XIT_CLEAR,
+  BAND_PLUS,
+  BAND_MINUS,
+  BANDSTACK_PLUS,
+  BANDSTACK_MINUS,
+  MODE_PLUS,
+  MODE_MINUS,
+  FILTER_PLUS,
+  FILTER_MINUS,
+  A_TO_B,
+  B_TO_A,
+  A_SWAP_B,
+  LOCK,
+  CTUN,
+  AGC,
+  SPLIT,
+  DIVERSITY,
+  MENU_BAND,
+  MENU_BANDSTACK,
+  MENU_MODE,
+  MENU_FILTER,
+  MENU_FREQUENCY,
+  MENU_MEMORY,
+  MENU_DIVERSITY,
+  FUNCTION,
+  SWITCH_ACTIONS
+};
+
+extern char *sw_string[SWITCH_ACTIONS];
+
+
+#ifndef CONTROLLER2
+#define SWITCHES 8
+enum {
+  SW1=0,
+  SW2,
+  SW3,
+  SW4,
+  SW5,
+  SW6,
+  SW7,
+  SW8
+};
+#else
+#define SWITCHES 16
+enum {
+  SW2=0,
+  SW3,
+  SW4,
+  SW5,
+  SW6,
+  SW7,
+  SW8,
+  SW9,
+  SW10,
+  SW11,
+  SW12,
+  SW13,
+  SW14,
+  SW15,
+  SW16,
+  SW17
+};
+
+#endif
+
+extern int sw_action[SWITCHES];
 
 extern int settle_time;
 
-extern char *encoder_string[ENCODER_LAST];
 
-extern int e1_encoder_action;
 extern int e2_encoder_action;
 extern int e3_encoder_action;
+extern int e4_encoder_action;
+extern int e5_encoder_action;
+
+extern int e2_top_encoder_action;
+extern int e3_top_encoder_action;
+extern int e4_top_encoder_action;
+extern int e5_top_encoder_action;
+
+extern int e2_sw_action;
+extern int e3_sw_action;
+extern int e4_sw_action;
+extern int e5_sw_action;
 
 extern int ENABLE_VFO_ENCODER;
 extern int ENABLE_VFO_PULLUP;
@@ -52,10 +153,6 @@ extern int VFO_ENCODER_A;
 extern int VFO_ENCODER_B;
 extern int VFO_ENCODER_A_PIN;
 extern int VFO_ENCODER_B_PIN;
-extern int ENABLE_E1_ENCODER;
-extern int ENABLE_E1_PULLUP;
-extern int E1_ENCODER_A;
-extern int E1_ENCODER_B;
 extern int ENABLE_E2_ENCODER;
 extern int ENABLE_E2_PULLUP;
 extern int E2_ENCODER_A;
@@ -64,6 +161,16 @@ extern int ENABLE_E3_ENCODER;
 extern int ENABLE_E3_PULLUP;
 extern int E3_ENCODER_A;
 extern int E3_ENCODER_B;
+extern int ENABLE_E4_ENCODER;
+extern int ENABLE_E4_PULLUP;
+extern int E4_ENCODER_A;
+extern int E4_ENCODER_B;
+#ifdef CONTROLLER2
+extern int ENABLE_E5_ENCODER;
+extern int ENABLE_E5_PULLUP;
+extern int E5_ENCODER_A;
+extern int E5_ENCODER_B;
+#endif
 extern int ENABLE_S1_BUTTON;
 extern int S1_BUTTON;
 extern int ENABLE_S2_BUTTON;
@@ -93,8 +200,10 @@ int  gpio_right_cw_key();
 int  gpio_cw_sidetone_enabled();
 #endif
 
+void gpio_restore_actions();
 void gpio_restore_state();
 void gpio_save_state();
+void gpio_save_actions();
 int gpio_init();
 void gpio_close();
 int vfo_encoder_get_pos();
diff --git a/i2c.c b/i2c.c
index fac927a73af3753af40016cf39d97b7524c46b5c..e6d6a24fddb00741bc3b16ce656727109f29b725 100644 (file)
--- a/i2c.c
+++ b/i2c.c
@@ -9,6 +9,7 @@
 
 #include <gtk/gtk.h>
 #include "i2c.h"
+#include "gpio.h"
 #include "band.h"
 #include "band_menu.h"
 #include "bandstack.h"
 #define ADDRESS_1 0X20
 #define ADDRESS_2 0X23
 
+#define SW_2  0X8000
+#define SW_3  0X4000
+#define SW_4  0X2000
+#define SW_5  0X1000
+#define SW_6  0X0008
+#define SW_7  0X0004
+#define SW_8  0X0002
+#define SW_9  0X0001
+#define SW_10 0X0010
+#define SW_11 0X0020
+#define SW_12 0X0040
+#define SW_13 0X0080
+#define SW_14 0X0800
+#define SW_15 0X0400
+#define SW_16 0X0200
+#define SW_17 0X0100
+
 static int write_byte_data(unsigned char addr,unsigned char reg, unsigned char data) {
   int fd;
   int rc;
@@ -109,56 +127,144 @@ void i2c_interrupt() {
     flags=read_word_data(ADDRESS_1,0x0E);
     if(flags) {
       ints=read_word_data(ADDRESS_1,0x10);
-      fprintf(stderr,"i2c_interrupt: flags=%04X,ints=%04X\n",flags,ints);
       if(ints) {
+        int i=-1;
         switch(ints) {
-          case 0x0001:
-            g_idle_add(ext_mox_update,NULL);
+          case SW_2:
+            i=SW2;
+            break;
+          case SW_3:
+            i=SW3;
+            break;
+          case SW_4:
+            i=SW4;
+            break;
+          case SW_5:
+            i=SW5;
+            break;
+          case SW_6:
+            i=SW6;
+            break;
+          case SW_7:
+            i=SW7;
+            break;
+          case SW_8:
+            i=SW8;
+            break;
+          case SW_9:
+            i=SW9;
+            break;
+          case SW_10:
+            i=SW10;
+            break;
+          case SW_11:
+            i=SW11;
+            break;
+          case SW_12:
+            i=SW12;
+            break;
+          case SW_13:
+            i=SW13;
+            break;
+          case SW_14:
+            i=SW14;
+            break;
+          case SW_15:
+            i=SW15;
+            break;
+          case SW_16:
+            i=SW16;
+            break;
+          case SW_17:
+            i=SW17;
+            break;
+        }
+        switch(sw_action[i]) {
+          case TUNE:
+            {
+            int tune=getTune();
+            if(tune==0) tune=1; else tune=0;
+            g_idle_add(ext_tune_update,GINT_TO_POINTER(tune));
+            }
+            break;
+          case MOX:
+            {
+            int mox=getMox();
+            if(mox==0) mox=1; else mox=0;
+            g_idle_add(ext_mox_update,GINT_TO_POINTER(mox));
+            }
+            break;
+          case PS:
+            g_idle_add(ext_ps_update,NULL);
+            break;
+          case TWO_TONE:
+            g_idle_add(ext_two_tone,NULL);
+            break;
+          case NR:
+            g_idle_add(ext_nr_update,NULL);
+            break;
+          case NB:
+            g_idle_add(ext_nb_update,NULL);
+            break;
+          case SNB:
+            g_idle_add(ext_snb_update,NULL);
+            break;
+          case RIT:
+            g_idle_add(ext_rit_update,NULL);
+            break;
+          case RIT_CLEAR:
+            g_idle_add(ext_rit_clear,NULL);
+            break;
+          case XIT:
+            g_idle_add(ext_xit_update,NULL);
+            break;
+          case XIT_CLEAR:
+            g_idle_add(ext_xit_clear,NULL);
             break;
-          case 0x0002:
-            g_idle_add(ext_tune_update,NULL);
+          case BAND_PLUS:
+            g_idle_add(ext_band_plus,NULL);
             break;
-          case 0x0004:
-            g_idle_add(ext_band_update,NULL);
+          case BAND_MINUS:
+            g_idle_add(ext_band_minus,NULL);
             break;
-          case 0x0008:
-            g_idle_add(ext_band_update,(void *)band40);
+          case BANDSTACK_PLUS:
+            g_idle_add(ext_bandstack_plus,NULL);
             break;
-          case 0x0010:
-            g_idle_add(ext_band_update,(void *)band30);
+          case BANDSTACK_MINUS:
+            g_idle_add(ext_bandstack_minus,NULL);
             break;
-          case 0x0020:
-            g_idle_add(ext_band_update,(void *)band20);
+          case MODE_PLUS:
+            g_idle_add(ext_mode_plus,NULL);
             break;
-          case 0x0040:
-            g_idle_add(ext_band_update,(void *)band17);
+          case MODE_MINUS:
+            g_idle_add(ext_mode_minus,NULL);
             break;
-          case 0x0080:
-            g_idle_add(ext_band_update,(void *)band15);
+          case FILTER_PLUS:
+            g_idle_add(ext_filter_plus,NULL);
             break;
-          case 0x0100:
-            g_idle_add(ext_band_update,(void *)band12);
+          case FILTER_MINUS:
+            g_idle_add(ext_filter_minus,NULL);
             break;
-          case 0x0200:
-            g_idle_add(ext_band_update,(void *)band10);
+          case A_TO_B:
+            g_idle_add(ext_vfo_a_to_b,NULL);
             break;
-          case 0x0400:
-            g_idle_add(ext_band_update,(void *)band6);
+          case B_TO_A:
+            g_idle_add(ext_vfo_b_to_a,NULL);
             break;
-          case 0x0800:
-            g_idle_add(ext_band_update,(void *)bandGen);
+          case A_SWAP_B:
+            g_idle_add(ext_vfo_a_swap_b,NULL);
             break;
-          case 0x1000:
-            g_idle_add(ext_band_update,(void *)band12);
+          case LOCK:
+            g_idle_add(ext_lock_update,NULL);
             break;
-          case 0x2000:
-            g_idle_add(ext_band_update,(void *)band10);
+          case CTUN:
+            g_idle_add(ext_ctun_update,NULL);
             break;
-          case 0x4000:
-            g_idle_add(ext_band_update,(void *)band6);
+          case AGC:
+            g_idle_add(ext_agc_update,NULL);
             break;
-          case 0x8000:
-            g_idle_add(ext_band_update,(void *)bandGen);
+          case SPLIT:
+            g_idle_add(ext_split_update,NULL);
             break;
         }
       }
diff --git a/i2c.h b/i2c.h
index e06808d7e2fe88732d72d4a51d47e57ebeb1f2cb..3271c26c9da80e770be17bf01c848ec0728e46d7 100644 (file)
--- a/i2c.h
+++ b/i2c.h
@@ -1,3 +1,2 @@
-
-void i2c_init();
-void i2c_interrupt();
+extern void i2c_init();
+extern void i2c_interrupt();
diff --git a/lime_discovery.c b/lime_discovery.c
deleted file mode 100644 (file)
index 86979bb..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <SoapySDR/Device.h>
-#include "discovered.h"
-#include "lime_discovery.h"
-
-void lime_discovery() {
-  SoapySDRKwargs args;
-  size_t length;
-  int i;
-  args.size=0;
-  SoapySDRKwargs *devs=SoapySDRDevice_enumerate(&args, &length);
-
-fprintf(stderr,"lime_discovery: length=%ld devs->size=%ld\n",length,devs->size);
-
-  for(i=0;i<devs->size;i++) {
-fprintf(stderr,"lime_discovery:device key=%s val=%s\n",devs->keys[i], devs->vals[i]);
-    if(strcmp(devs->keys[i],"name")==0) {
-      discovered[devices].protocol=LIMESDR_PROTOCOL;
-      discovered[devices].device=LIMESDR_USB_DEVICE;
-      strcpy(discovered[devices].name,devs->vals[i]);
-      discovered[devices].status=STATE_AVAILABLE;
-      discovered[devices].info.soapy.args=devs;
-      devices++;
-    }
-  }
-
-/*
-  SoapySDRDevice *device=SoapySDRDevice_make(devs);
-  if(device==NULL) {
-    fprintf(stderr,"SoapySDRDevice_make failed: %s\n",SoapySDRDevice_lastError());
-    return;
-  }
-
-  SoapySDRKwargs info=SoapySDRDevice_getHardwareInfo(device);
-  int version=0;
-  for(i=0;i<info.size;i++) {
-fprintf(stderr,"lime_discovery: info key=%s val=%s\n",info.keys[i], info.vals[i]);
-    if(strcmp(info.keys[i],"firmwareVersion")==0) {
-      version+=atoi(info.vals[i])*100;
-    }
-    if(strcmp(info.keys[i],"hardwareVersion")==0) {
-      version+=atoi(info.vals[i])*10;
-    }
-    if(strcmp(info.keys[i],"protocolVersion")==0) {
-      version+=atoi(info.vals[i]);
-    }
-  }
-  
-  discovered[devices].software_version=version;
-*/
-
-/*
-  fprintf(stderr,"SampleRates\n");
-  int rates;
-  double *rate;
-  rate=SoapySDRDevice_listSampleRates(device,SOAPY_SDR_RX,0,&rates);
-  for(i=0;i<rates;i++) {
-    fprintf(stderr,"rate=%f\n",rate[i]);
-  }
-
-  fprintf(stderr,"Bandwidths\n");
-  int bandwidths;
-  double *bandwidth;
-  bandwidth=SoapySDRDevice_listSampleRates(device,SOAPY_SDR_RX,0,&bandwidths);
-  for(i=0;i<bandwidths;i++) {
-    fprintf(stderr,"bandwidth=%f\n",bandwidth[i]);
-  }
-
-  fprintf(stderr,"Antennas\n");
-  int antennas;
-  char **antenna;
-  antenna=SoapySDRDevice_listAntennas(device,SOAPY_SDR_RX,0,&antennas);
-  for(i=0;i<antennas;i++) {
-    fprintf(stderr,"antenna=%s\n",antenna[i]);
-  }
-
-  char *ant=SoapySDRDevice_getAntenna(device,SOAPY_SDR_RX,0);
-  fprintf(stderr,"selected antenna=%s\n",ant);
-
-  SoapySDRDevice_unmake(device);
-
-*/
-  fprintf(stderr,"lime_discovery found %d devices\n",length);
-}
diff --git a/lime_discovery.h b/lime_discovery.h
deleted file mode 100644 (file)
index 6c73d73..0000000
+++ /dev/null
@@ -1,25 +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 _LIME_DISCOVERY_H
-#define _LIME_DISCOVERY_H
-
-void lime_discovery();
-
-#endif
diff --git a/lime_protocol.c b/lime_protocol.c
deleted file mode 100644 (file)
index c7e1d92..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <wdsp.h>
-
-//#define TIMING
-#ifdef TIMING
-#include <sys/time.h>
-#endif
-
-#include "audio.h"
-#include "channel.h"
-#include "discovered.h"
-#include "lime_protocol.h"
-#include "radio.h"
-#include "receiver.h"
-#include "SoapySDR/Constants.h"
-#include "SoapySDR/Device.h"
-
-static double bandwidth=3000000.0;
-
-static size_t lime_receiver;
-static SoapySDRDevice *lime_device;
-static SoapySDRStream *stream;
-static int lime_sample_rate;
-static int display_width;
-static int lime_buffer_size=BUFFER_SIZE;
-static int outputsamples;
-static int lime_fft_size=4096;
-static int dspRate=48000;
-static int outputRate=48000;
-static float *buffer;
-static int max_samples;
-
-static long long saved_frequency=0LL;
-static int saved_antenna=-1;
-
-//static double iqinputbuffer[BUFFER_SIZE*2];
-static double audiooutputbuffer[BUFFER_SIZE*2];
-static int samples=0;
-
-static GThread *receive_thread_id;
-static gpointer receive_thread(gpointer data);
-
-static int actual_rate;
-#ifdef RESAMPLE
-static void *resampler;
-static double resamples[1024*2];
-static double resampled[1024*2];
-#endif
-
-#ifdef TIMING
-static int rate_samples;
-#endif
-
-static int running;
-
-void lime_protocol_change_sample_rate(int rate) {
-}
-
-void lime_protocol_init(int rx,int pixels,int sample_rate) {
-  SoapySDRKwargs args;
-  int rc;
-
-fprintf(stderr,"lime_protocol_init: lime_receiver=%d pixels=%d sample_rate=%d\n",rx,pixels,sample_rate);
-
-  lime_receiver=(size_t)rx;
-  display_width=pixels;
-  lime_sample_rate=sample_rate;
-
-  outputsamples=BUFFER_SIZE/(sample_rate/48000);
-/*
-  switch(sample_rate) {
-    case 48000:
-      outputsamples=BUFFER_SIZE;
-      break;
-    case 96000:
-      outputsamples=BUFFER_SIZE/2;
-      break;
-    case 192000:
-      outputsamples=BUFFER_SIZE/4;
-      break;
-    case 384000:
-      outputsamples=BUFFER_SIZE/8;
-      break;
-    case 768000:
-      outputsamples=BUFFER_SIZE/16;
-      break;
-    case 1536000:
-      outputsamples=BUFFER_SIZE/32;
-      break;
-  }
-*/
-
-
-
-
-  args.size=0;
-
-  // initialize the radio
-fprintf(stderr,"lime_protocol: receive_thread: SoapySDRDevice_make\n");
-  lime_device=SoapySDRDevice_make(radio->info.soapy.args);
-  if(lime_device==NULL) {
-    fprintf(stderr,"lime_protocol: SoapySDRDevice_make failed: %s\n",SoapySDRDevice_lastError());
-    _exit(-1);
-  }
-
-fprintf(stderr,"lime_protocol: set antenna to NONE\n");
-  lime_protocol_set_antenna(0);
-
-fprintf(stderr,"lime_protocol: setting samplerate=%f\n",(double)sample_rate);
-  rc=SoapySDRDevice_setSampleRate(lime_device,SOAPY_SDR_RX,lime_receiver,(double)sample_rate);
-  if(rc!=0) {
-    fprintf(stderr,"lime_protocol: SoapySDRDevice_setSampleRate(%f) failed: %s\n",(double)sample_rate,SoapySDRDevice_lastError());
-  }
-
-  actual_rate=(int)SoapySDRDevice_getSampleRate(lime_device, SOAPY_SDR_RX, lime_receiver);
-fprintf(stderr,"lime_protocol: actual samplerate= %d\n",actual_rate);
-#ifdef RESAMPLE
-if(sample_rate==768000 && actual_rate==767999) {
-  actual_rate=768000;
-  fprintf(stderr,"lime_protocol: forced actual_rate\n");
-}
-#endif
-
-fprintf(stderr,"lime_protocol: setting bandwidth =%f\n",bandwidth);
-  rc=SoapySDRDevice_setBandwidth(lime_device,SOAPY_SDR_RX,lime_receiver,bandwidth);
-  if(rc!=0) {
-    fprintf(stderr,"lime_protocol: SoapySDRDevice_setBandwidth(%f) failed: %s\n",bandwidth,SoapySDRDevice_lastError());
-  }
-
-if(saved_frequency!=0LL) {
-fprintf(stderr,"lime_protocol: setting save_frequency: %lld\n",saved_frequency);
-    lime_protocol_set_frequency(saved_frequency);
-}
-
-/*
-fprintf(stderr,"lime_protocol: set baseband frequency\n");
-  rc=SoapySDRDevice_setFrequencyComponent(lime_device,SOAPY_SDR_RX,lime_receiver,"BB",0.0,&args);
-  if(rc!=0) {
-    fprintf(stderr,"lime_protocol: SoapySDRDevice_setFrequencyComponent(BB) failed: %s\n",SoapySDRDevice_lastError());
-  }
-*/
-  
-fprintf(stderr,"setting antennal to LNAL\n");
-  lime_protocol_set_antenna(2);
-
-fprintf(stderr,"setting Gain LNA=30.0\n");
-  rc=SoapySDRDevice_setGainElement(lime_device,SOAPY_SDR_RX,lime_receiver,"LNA",30.0);
-  if(rc!=0) {
-    fprintf(stderr,"lime_protocol: SoapySDRDevice_setGain LNA failed: %s\n",SoapySDRDevice_lastError());
-  }
-fprintf(stderr,"setting Gain PGA=19.0\n");
-  rc=SoapySDRDevice_setGainElement(lime_device,SOAPY_SDR_RX,lime_receiver,"PGA",19.0);
-  if(rc!=0) {
-    fprintf(stderr,"lime_protocol: SoapySDRDevice_setGain PGA failed: %s\n",SoapySDRDevice_lastError());
-  }
-fprintf(stderr,"setting Gain TIA=12.0\n");
-  rc=SoapySDRDevice_setGainElement(lime_device,SOAPY_SDR_RX,lime_receiver,"TIA",12.0);
-  if(rc!=0) {
-    fprintf(stderr,"lime_protocol: SoapySDRDevice_setGain TIA failed: %s\n",SoapySDRDevice_lastError());
-  }
-
-fprintf(stderr,"lime_protocol: receive_thread: SoapySDRDevice_setupStream\n");
-  size_t channels=(size_t)lime_receiver;
-  rc=SoapySDRDevice_setupStream(lime_device,&stream,SOAPY_SDR_RX,"CF32",&channels,1,&args);
-  if(rc!=0) {
-    fprintf(stderr,"lime_protocol: SoapySDRDevice_setupStream failed: %s\n",SoapySDRDevice_lastError());
-    _exit(-1);
-  }
-
-  max_samples=SoapySDRDevice_getStreamMTU(lime_device,stream);
-fprintf(stderr,"max_samples=%d\n",max_samples);
-
-  buffer=(float *)malloc(max_samples*sizeof(float)*2);
-
-#ifdef RESAMPLE
-  if(actual_rate!=sample_rate) {
-fprintf(stderr,"lime_protocol: creating resampler from %d to %d\n",actual_rate,sample_rate);
-    resampler=create_resample (1, max_samples, resamples, resampled, actual_rate, sample_rate, 0.0, 0, 1.0);
-  }
-#endif
-
-  rc=SoapySDRDevice_activateStream(lime_device, stream, 0, 0LL, 0);
-  if(rc!=0) {
-    fprintf(stderr,"lime_protocol: SoapySDRDevice_activateStream failed: %s\n",SoapySDRDevice_lastError());
-    _exit(-1);
-  }
-
-
-  if(saved_antenna!=-1) {
-fprintf(stderr,"lime_protocol: setting save_antenna: %d\n",saved_antenna);
-    lime_protocol_set_antenna(saved_antenna);
-  }
-
-  if(saved_frequency!=0LL) {
-fprintf(stderr,"lime_protocol: setting save_frequency: %lld\n",saved_frequency);
-      lime_protocol_set_frequency(saved_frequency);
-  }
-
-fprintf(stderr,"lime_protocol_init: audio_open_output\n");
-  if(audio_open_output(receiver[0])!=0) {
-    receiver[0]->local_audio=false;
-    fprintf(stderr,"audio_open_output failed\n");
-  }
-
-fprintf(stderr,"lime_protocol_init: create receive_thread\n");
-  receive_thread_id = g_thread_new( "lime protocol", receive_thread, NULL);
-  if( ! receive_thread_id )
-  {
-    fprintf(stderr,"g_thread_new failed for receive_thread\n");
-    exit( -1 );
-  }
-  fprintf(stderr, "receive_thread: id=%p\n",receive_thread_id);
-}
-
-static void *receive_thread(void *arg) {
-  float isample;
-  float qsample;
-  int outsamples;
-  int elements;
-  int flags=0;
-  long long timeNs=0;
-  long timeoutUs=10000L;
-  int i;
-#ifdef TIMING
-  struct timeval tv;
-  long start_time, end_time;
-  rate_samples=0;
-  gettimeofday(&tv, NULL); start_time=tv.tv_usec + 1000000 * tv.tv_sec;
-#endif
-  running=1;
-fprintf(stderr,"lime_protocol: receive_thread\n");
-  while(running) {
-    elements=SoapySDRDevice_readStream(lime_device,stream,(void *)&buffer,max_samples,&flags,&timeNs,timeoutUs);
-//fprintf(stderr,"read %d elements\n",elements);
-#ifdef RESAMPLE
-    if(actual_rate!=lime_sample_rate) {
-      for(i=0;i<elements;i++) {
-        resamples[i*2]=(double)buffer[i*2];
-        resamples[(i*2)+1]=(double)buffer[(i*2)+1];
-      }
-
-      outsamples=xresample(resampler);
-
-      for(i=0;i<outsamples;i++) {
-        add_iq_samples(receiver[0],(double)resampled[i*2],(double)resampled[(i*2)+1]);
-      }
-    } else {
-#endif
-      for(i=0;i<elements;i++) {
-        add_iq_samples(receiver[0],(double)buffer[i*2],(double)buffer[(i*2)+1]);
-      }
-#ifdef RESAMPLE
-    }
-#endif
-  }
-
-fprintf(stderr,"lime_protocol: receive_thread: SoapySDRDevice_closeStream\n");
-  SoapySDRDevice_closeStream(lime_device,stream);
-fprintf(stderr,"lime_protocol: receive_thread: SoapySDRDevice_unmake\n");
-  SoapySDRDevice_unmake(lime_device);
-
-}
-
-
-void lime_protocol_stop() {
-  running=0;
-}
-
-void lime_protocol_set_frequency(long long f) {
-  int rc;
-  char *ant;
-
-  if(lime_device!=NULL) {
-    SoapySDRKwargs args;
-    args.size=0;
-fprintf(stderr,"lime_protocol: setFrequency: %lld\n",f);
-    rc=SoapySDRDevice_setFrequency(lime_device,SOAPY_SDR_RX,lime_receiver,(double)f,&args);
-    if(rc!=0) {
-      fprintf(stderr,"lime_protocol: SoapySDRDevice_setFrequency() failed: %s\n",SoapySDRDevice_lastError());
-    }
-  } else {
-fprintf(stderr,"lime_protocol: setFrequency: %lld device is NULL\n",f);
-    saved_frequency=f;
-  }
-}
-
-void lime_protocol_set_antenna(int ant) {
-  int rc;
- // char *antstr;
-  if(lime_device!=NULL) {
-/*
-    antstr=SoapySDRDevice_getAntenna(lime_device,SOAPY_SDR_RX,lime_receiver);
-    fprintf(stderr,"lime_protocol: set_antenna: current antenna=%s\n",antstr);
-*/
-    switch(ant) {
-      case 0:
-fprintf(stderr,"lime_protocol: setAntenna: NONE\n");
-        rc=SoapySDRDevice_setAntenna(lime_device,SOAPY_SDR_RX,lime_receiver,"NONE");
-        if(rc!=0) {
-          fprintf(stderr,"lime_protocol: SoapySDRDevice_setAntenna NONE failed: %s\n",SoapySDRDevice_lastError());
-        }
-        break;
-      case 1:
-fprintf(stderr,"lime_protocol: setAntenna: LNAH\n");
-        rc=SoapySDRDevice_setAntenna(lime_device,SOAPY_SDR_RX,lime_receiver,"LNAH");
-        if(rc!=0) {
-          fprintf(stderr,"lime_protocol: SoapySDRDevice_setAntenna LNAH failed: %s\n",SoapySDRDevice_lastError());
-        }
-        break;
-      case 2:
-fprintf(stderr,"lime_protocol: setAntenna: LNAL\n");
-        rc=SoapySDRDevice_setAntenna(lime_device,SOAPY_SDR_RX,lime_receiver,"LNAL");
-        if(rc!=0) {
-          fprintf(stderr,"lime_protocol: SoapySDRDevice_setAntenna LNAL failed: %s\n",SoapySDRDevice_lastError());
-        }
-        break;
-      case 3:
-fprintf(stderr,"lime_protocol: setAntenna: LNAW\n");
-        rc=SoapySDRDevice_setAntenna(lime_device,SOAPY_SDR_RX,lime_receiver,"LNAW");
-        if(rc!=0) {
-          fprintf(stderr,"lime_protocol: SoapySDRDevice_setAntenna LNAW failed: %s\n",SoapySDRDevice_lastError());
-        }
-        break;
-    }
-/*
-    antstr=SoapySDRDevice_getAntenna(lime_device,SOAPY_SDR_RX,lime_receiver);
-    fprintf(stderr,"lime_protocol: set_antenna: antenna=%s\n",antstr);
-*/
-  } else {
-    fprintf(stderr,"lime_protocol: setAntenna: device is NULL\n");
-    saved_antenna=ant;
-  }
-}
-
-void lime_protocol_set_attenuation(int attenuation) {
-  int rc;
-  fprintf(stderr,"setting Gain LNA=%f\n",30.0-(double)attenuation);
-  rc=SoapySDRDevice_setGainElement(lime_device,SOAPY_SDR_RX,lime_receiver,"LNA",30.0-(double)attenuation);
-  if(rc!=0) {
-    fprintf(stderr,"lime_protocol: SoapySDRDevice_setGain LNA failed: %s\n",SoapySDRDevice_lastError());
-  }
-}
diff --git a/lime_protocol.h b/lime_protocol.h
deleted file mode 100644 (file)
index 91d7d25..0000000
+++ /dev/null
@@ -1,32 +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 _LIME_PROTOCOL_H
-#define _LIME_PROTOCOL_H
-
-#define BUFFER_SIZE 1024
-
-void lime_protocol_init(int rx,int pixels,int sample_rate);
-void lime_protocol_stop();
-void lime_protocol_set_frequency(long long f);
-void lime_protocol_set_antenna(int ant);
-void lime_protocol_set_attenuation(int attenuation);
-void lime_protocol_change_sample_rate(int rate);
-
-#endif
diff --git a/main.c b/main.c
index 55c9708ec57b85eba27ddf3669dcd8059176167c..bed1b68e80d3acf4ef99af611245ce1da9830322 100644 (file)
--- a/main.c
+++ b/main.c
@@ -54,6 +54,9 @@
 #include "discovery.h"
 #include "new_protocol.h"
 #include "old_protocol.h"
+#ifdef SOAPYSDR
+#include "soapy_protocol.h"
+#endif
 #include "frequency.h"   // for canTransmit
 #include "ext.h"
 
@@ -136,9 +139,9 @@ gboolean main_delete (GtkWidget *widget) {
       case NEW_PROTOCOL:
         new_protocol_stop();
         break;
-#ifdef LIMESDR
-      case LIMESDR_PROTOCOL:
-        lime_protocol_stop();
+#ifdef SOAPYSDR
+      case SOAPYSDR_PROTOCOL:
+        soapy_protocol_stop();
         break;
 #endif
     }
@@ -223,6 +226,7 @@ fprintf(stderr,"display_width=%d display_height=%d\n", display_width, display_he
 
   //fprintf(stderr,"create top level window\n");
   top_window = gtk_application_window_new (app);
+fprintf(stderr,"top_window=%p\n",top_window);
   if(full_screen) {
     fprintf(stderr,"full screen\n");
     gtk_window_fullscreen(GTK_WINDOW(top_window));
index 959c320a432ab94eab9f19284961aa68caad671d..2d31ca83a752802efa4416f0b2fadbe9b37bf1a5 100644 (file)
@@ -56,6 +56,9 @@
 #include "tx_menu.h"
 #include "ps_menu.h"
 #include "encoder_menu.h"
+#ifdef CONTROLLER2
+#include "switch_menu.h"
+#endif
 #include "vfo_menu.h"
 #include "fft_menu.h"
 #include "main.h"
@@ -154,6 +157,24 @@ static gboolean rigctl_cb (GtkWidget *widget, GdkEventButton *event, gpointer da
   return TRUE;
 }
 
+#ifdef GPIO
+static gboolean encoder_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  cleanup();
+  fprintf(stderr, "new_menu: calling encoder_menu\n");
+  encoder_menu(top_window);
+  return TRUE;
+}
+
+#ifdef CONTROLLER2
+static gboolean switch_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  cleanup();
+  fprintf(stderr, "new_menu: calling switch_menu\n");
+  switch_menu(top_window);
+  return TRUE;
+}
+#endif
+#endif
+
 static gboolean cw_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   cleanup();
   cw_menu(top_window);
@@ -186,6 +207,11 @@ static gboolean equalizer_cb (GtkWidget *widget, GdkEventButton *event, gpointer
   return TRUE;
 }
 
+void start_rx() {
+  cleanup();
+  rx_menu(top_window);
+}
+
 void start_step() {
   cleanup();
   step_menu(top_window);
@@ -363,16 +389,12 @@ static gboolean ps_cb (GtkWidget *widget, GdkEventButton *event, gpointer data)
 #endif
 
 #ifdef GPIO
+/*
 void start_encoder(int encoder) {
   int old_menu=active_menu;
   cleanup();
+fprintf(stderr,"start_encoder: %d old_menu=%d active_menu=%d\n",encoder,old_menu,active_menu);
   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);
@@ -385,6 +407,18 @@ void start_encoder(int encoder) {
         active_menu=E3_MENU;
       }
       break;
+    case 4:
+      if(old_menu!=E4_MENU) {
+        encoder_menu(top_window,encoder);
+        active_menu=E4_MENU;
+      }
+      break;
+    case 5:
+      if(old_menu!=E5_MENU) {
+        encoder_menu(top_window,encoder);
+        active_menu=E5_MENU;
+      }
+      break;
   }
 }
 
@@ -393,6 +427,7 @@ static gboolean encoder_cb (GtkWidget *widget, GdkEventButton *event, gpointer d
   start_encoder(encoder);
   return TRUE;
 }
+*/
 #endif
 
 void start_test() {
@@ -541,10 +576,19 @@ void new_menu()
     gtk_grid_attach(GTK_GRID(grid),rigctl_b,(i%5),i/5,1,1);
     i++;
 
-    GtkWidget *about_b=gtk_button_new_with_label("About");
-    g_signal_connect (about_b, "button-press-event", G_CALLBACK(about_b_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),about_b,(i%5),i/5,1,1);
+#ifdef GPIO
+    GtkWidget *encoders_b=gtk_button_new_with_label("Encoders");
+    g_signal_connect (encoders_b, "button-press-event", G_CALLBACK(encoder_cb), NULL);
+    gtk_grid_attach(GTK_GRID(grid),encoders_b,(i%5),i/5,1,1);
+    i++;
+
+#ifdef CONTROLLER2
+    GtkWidget *switches_b=gtk_button_new_with_label("Switches");
+    g_signal_connect (switches_b, "button-press-event", G_CALLBACK(switch_cb), NULL);
+    gtk_grid_attach(GTK_GRID(grid),switches_b,(i%5),i/5,1,1);
     i++;
+#endif
+#endif
 
 //
 //  We need at least two receivers and two ADCs to do DIVERSITY
@@ -556,6 +600,11 @@ void new_menu()
       i++;
     }
 
+    GtkWidget *about_b=gtk_button_new_with_label("About");
+    g_signal_connect (about_b, "button-press-event", G_CALLBACK(about_b_cb), NULL);
+    gtk_grid_attach(GTK_GRID(grid),about_b,(i%5),i/5,1,1);
+    i++;
+
     gtk_container_add(GTK_CONTAINER(content),grid);
 
     gtk_widget_show_all(dialog);
index a32faedfc65446b0c839852289c379d05bd2e8bf..f251aae85c022b5690fce8d1dc8a38e7409b9ac7 100644 (file)
@@ -16,6 +16,8 @@ extern void start_encoder();
 extern void start_vfo();
 extern void start_agc();
 extern void start_store();
+extern void start_rx();
+extern void start_diversity();
 
 extern void encoder_step(int encoder,int step);
 
@@ -23,9 +25,10 @@ extern int menu_active_receiver_changed(void *data);
 
 enum {
   NO_MENU = 0,
-  E1_MENU,
   E2_MENU,
   E3_MENU,
+  E4_MENU,
+  E5_MENU,
   BAND_MENU,
   BANDSTACK_MENU,
   MODE_MENU,
index 38d20105790a5777ff609ed56e0f959758c76822..dd1b60c2d600e1bca22d43fc0390bc66d94e2519 100644 (file)
@@ -37,6 +37,7 @@
 #include <math.h>
 #include <errno.h>
 
+#include <gtk/gtk.h>
 
 #include "discovered.h"
 #include "new_protocol.h"
index c38f135bdf57f1d8513ae4d146def096d789384b..5a8981a71b967a104ca64742565bb24f36a978b3 100644 (file)
@@ -643,7 +643,11 @@ static int second_receiver_channel() {
   // return the channel number of the second receiver
   //
 #ifdef PURESIGNAL
-  return 2;
+  if(device==DEVICE_HERMES_LITE) {
+    return 1;
+  } else {
+    return 2;
+  }
 #else
   return 1;
 #endif
@@ -671,9 +675,15 @@ static long long channel_freq(int chan) {
   switch (chan) {
 #ifdef PURESIGNAL
     case 0:
-    case 1:
       vfonum=receiver[0]->id;
       break;
+    case 1:
+      if(device==DEVICE_HERMES_LITE) {
+        vfonum=receiver[1]->id;
+      } else {
+        vfonum=receiver[0]->id;
+      }
+      break;
     case 2:
     case 3:
     case 4:
index 08f74af65b678b26c1a3793d085fd5e7cb535736..beba9a5244538d9ddda5b1de377ca35435e2ef80 100644 (file)
@@ -83,7 +83,7 @@ void saveProperties(char* filename) {
     char line[512];
     char version[32];
 
-    //fprintf(stderr,"saveProperties: %s\n",filename);
+    fprintf(stderr,"saveProperties: %s\n",filename);
 
     if(!f) {
         fprintf(stderr,"can't open %s\n",filename);
diff --git a/radio.c b/radio.c
index 6d82af4ea17d44c999dd2ae521d6dbc063083924..47c6fde67572bfa9f6d719c87db0fd8eea480497 100644 (file)
--- a/radio.c
+++ b/radio.c
@@ -29,6 +29,7 @@
 
 #include <wdsp.h>
 
+#include "adc.h"
 #include "audio.h"
 #include "discovered.h"
 //#include "discovery.h"
@@ -46,8 +47,8 @@
 #include "new_protocol.h"
 #include "old_protocol.h"
 #include "store.h"
-#ifdef LIMESDR
-#include "lime_protocol.h"
+#ifdef SOAPYSDR
+#include "soapy_protocol.h"
 #endif
 #ifdef FREEDV
 #include "freedv.h"
@@ -122,6 +123,9 @@ int region=REGION_OTHER;
 
 int echo=0;
 
+int radio_sample_rate;
+gboolean iqswap;
+
 static gint save_timer_id;
 
 DISCOVERED *radio=NULL;
@@ -175,6 +179,7 @@ int waterfall_high=-100;
 int waterfall_low=-150;
 
 int display_sliders=1;
+int display_toolbar=1;
 
 //double volume=0.2;
 double mic_gain=0.0;
@@ -391,6 +396,7 @@ void start_radio() {
 #endif
 
   char text[256];
+
   //for(i=0;i<devices;i++) {
     switch(radio->protocol) {
       case ORIGINAL_PROTOCOL:
@@ -410,24 +416,92 @@ void start_radio() {
   //}
 
 
+  char p[32];
+  char version[32];
+  char mac[32];
+  char ip[32];
+  char iface[32];
+
+  switch(radio->protocol) {
+    case ORIGINAL_PROTOCOL:
+      strcpy(p,"Protocol 1");
+      sprintf(version,"v%d.%d)",
+                   radio->software_version/10,
+                   radio->software_version%10);
+      sprintf(mac,"%02X:%02X:%02X:%02X:%02X:%02X",
+                  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]);
+      sprintf(ip,"%s", inet_ntoa(radio->info.network.address.sin_addr));
+      sprintf(iface,"%s", radio->info.network.interface_name);
+      break;
+    case NEW_PROTOCOL:
+      strcpy(p,"Protocol 2");
+      sprintf(version,"v%d.%d)",
+                   radio->software_version/10,
+                   radio->software_version%10);
+      sprintf(mac,"%02X:%02X:%02X:%02X:%02X:%02X",
+                  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]);
+      sprintf(ip,"%s", inet_ntoa(radio->info.network.address.sin_addr));
+      sprintf(iface,"%s", radio->info.network.interface_name);
+      break;
+#ifdef SOAPYSDR
+    case SOAPYSDR_PROTOCOL:
+      strcpy(p,"SoapySDR");
+      sprintf(version,"v%d.%d.%d)",
+                   radio->software_version/100,
+                   (radio->software_version%100)/10,
+                   radio->software_version%10);
+      strcpy(mac,"");
+      strcpy(ip,"");
+      strcpy(iface,"");
+      break;
+#endif
+  }
+
+  switch(protocol) {
+    case ORIGINAL_PROTOCOL:
+    case NEW_PROTOCOL:
+#ifdef USBOZY
+      if(radio->device==DEVICE_OZY) {
+        sprintf(text,"%s (%s) on USB /dev/ozy\n", radio->name, p);
+      } else {
+#endif
+        sprintf(text,"Starting %s (%s %s)",
+                      radio->name,
+                      p,
+                      version);
+#ifdef USBOZY
+      }
+#endif
+      break;
+#ifdef SOAPYSDR
+    case SOAPYSDR_PROTOCOL:
+      sprintf(text,"Starting %s (%s %s)",
+                    radio->name,
+                    "SoapySDR",
+                    version);
+      break;
+#endif
+    }
 
   status_text(text);
 
-  sprintf(text,"piHPSDR: %s (%s v%d.%d) %s (%02X:%02X:%02X:%02X:%02X:%02X) on %s",
+  sprintf(text,"piHPSDR: %s (%s %s) %s (%s) on %s",
                           radio->name,
-                          radio->protocol==ORIGINAL_PROTOCOL?"Protocol 1":"Protocol 2",
-                          radio->software_version/10,
-                          radio->software_version%10,
-                          inet_ntoa(radio->info.network.address.sin_addr),
-                          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],
-                          radio->info.network.interface_name);
-
-//fprintf(stderr,"title: length=%d\n", (int)strlen(text));
+                          p,
+                          version,
+                          ip,
+                          mac,
+                          iface);
 
   gtk_window_set_title (GTK_WINDOW (top_window), text);
 
@@ -454,9 +528,9 @@ void start_radio() {
           break;
       }
       break;
-#ifdef LIMESDR
-    case LIMESDR_PROTOCOL:
-      sprintf(property_path,"limesdr.props");
+#ifdef SOAPYSDR
+    case SOAPYSDR_PROTOCOL:
+      sprintf(property_path,"%s.props",radio->name);
       break;
 #endif
   }
@@ -518,16 +592,104 @@ void start_radio() {
           break;
       }
       break;
+#ifdef SOAPYSDR
+    case SOAPYSDR_PROTOCOL:
+      if(strcmp(radio->name,"lime")==0) {
+        n_adc=2;
+      } else {
+        n_adc=1;
+      }
+      break;
+#endif
     default:
       break;
   }
 
+  iqswap=0;
+
+#ifdef SOAPYSDR
+  if(radio->device==SOAPYSDR_USB_DEVICE) {
+    iqswap=1;
+  }
+  receivers=1;
+#endif
+
   adc_attenuation[0]=0;
   adc_attenuation[1]=0;
   rx_gain_slider[0] = 0;
   rx_gain_slider[1] = 0;
 
+  adc[0].antenna=ANTENNA_1;
+  adc[0].filters=AUTOMATIC;
+  adc[0].hpf=HPF_13;
+  adc[0].lpf=LPF_30_20;
+  adc[0].dither=FALSE;
+  adc[0].random=FALSE;
+  adc[0].preamp=FALSE;
+  adc[0].attenuation=0;
+#ifdef SOAPYSDR
+  adc[0].antenna=1; // LNAH
+  if(radio->device==SOAPYSDR_USB_DEVICE) {
+    adc[0].rx_gain=malloc(radio->info.soapy.rx_gains*sizeof(gint));
+    for (size_t i = 0; i < radio->info.soapy.rx_gains; i++) {
+      adc[0].rx_gain[i]=0;
+    }
+    adc[0].agc=FALSE;
+/*
+    if(r->can_transmit) {
+      r->dac[0].antenna=1;
+      r->dac[0].tx_gain=malloc(r->discovered->info.soapy.tx_gains*sizeof(gint));
+      for (size_t i = 0; i < r->discovered->info.soapy.tx_gains; i++) {
+        r->dac[0].tx_gain[i]=0;
+      }
+    }
+*/
+  }
+#endif
+
+  adc[1].antenna=ANTENNA_1;
+  adc[1].filters=AUTOMATIC;
+  adc[1].hpf=HPF_9_5;
+  adc[1].lpf=LPF_60_40;
+  adc[1].dither=FALSE;
+  adc[1].random=FALSE;
+  adc[1].preamp=FALSE;
+  adc[1].attenuation=0;
+#ifdef SOAPYSDR
+  adc[1].antenna=3; // LNAW
+  if(radio->device==SOAPYSDR_USB_DEVICE) {
+    adc[1].rx_gain=malloc(radio->info.soapy.rx_gains*sizeof(gint));
+    for (size_t i = 0; i < radio->info.soapy.rx_gains; i++) {
+      adc[1].rx_gain[i]=0;
+    }
+    adc[1].agc=FALSE;
+
+/*
+    if(r->can_transmit) {
+      r->dac[1].tx_gain=malloc(r->discovered->info.soapy.tx_gains*sizeof(gint));
+      for (size_t i = 0; i < r->discovered->info.soapy.tx_gains; i++) {
+        r->dac[1].tx_gain[i]=0;
+      }
+    }
+*/
+  }
+
+  radio_sample_rate=radio->info.soapy.sample_rate;
+#endif
+
 //fprintf(stderr,"meter_calibration=%f display_calibration=%f\n", meter_calibration, display_calibration);
+
+#ifdef CONTROLLER2
+  display_sliders=0;
+  display_toolbar=1;
+#else
+  display_sliders=1;
+  display_toolbar=1;
+#endif
+
+#ifdef GPIO
+  gpio_restore_state();
+#endif
   radioRestoreState();
 
 
@@ -537,8 +699,19 @@ void start_radio() {
 // Change setting to reasonable value then.
 // 
 //
-  if (protocol == ORIGINAL_PROTOCOL && buffer_size > 2048) buffer_size=2048;
-  if (protocol == NEW_PROTOCOL      && buffer_size >  512) buffer_size= 512;
+  switch (protocol) {
+    case ORIGINAL_PROTOCOL:
+      if (buffer_size > 2048) buffer_size=2048;
+      break;
+    case NEW_PROTOCOL:
+      if (buffer_size > 512) buffer_size=512;
+      break;
+#ifdef SOAPYSDR
+    case SOAPYSDR_PROTOCOL:
+      if (buffer_size > 2048) buffer_size=2048;
+      break;
+#endif
+  }
 
   radio_change_region(region);
 
@@ -572,10 +745,13 @@ void start_radio() {
   y+=MENU_HEIGHT;
 
 
-  int rx_height=display_height-VFO_HEIGHT-TOOLBAR_HEIGHT;
+  int rx_height=display_height-VFO_HEIGHT;
   if(display_sliders) {
     rx_height-=SLIDERS_HEIGHT;
   }
+  if(display_toolbar) {
+    rx_height-=TOOLBAR_HEIGHT;
+  }
   int tx_height=rx_height;
   rx_height=rx_height/RECEIVERS;
 
@@ -639,9 +815,9 @@ void start_radio() {
     case NEW_PROTOCOL:
       new_protocol_init(display_width);
       break;
-#ifdef LIMESDR
-    case LIMESDR_PROTOCOL:
-      lime_protocol_init(0,display_width,receiver[0]->sample_rate);
+#ifdef SOAPYSDR
+    case SOAPYSDR_PROTOCOL:
+      soapy_protocol_init(0,false);
       break;
 #endif
   }
@@ -660,9 +836,11 @@ void start_radio() {
   }
 
 
-  toolbar = toolbar_init(display_width,TOOLBAR_HEIGHT,top_window);
-  gtk_fixed_put(GTK_FIXED(fixed),toolbar,0,y);
-  y+=TOOLBAR_HEIGHT;
+  if(display_toolbar) {
+    toolbar = toolbar_init(display_width,TOOLBAR_HEIGHT,top_window);
+    gtk_fixed_put(GTK_FIXED(fixed),toolbar,0,y);
+    y+=TOOLBAR_HEIGHT;
+  }
 
 //
 // Now, if there should only one receiver be displayed
@@ -686,7 +864,7 @@ void start_radio() {
   
 
   // save every 30 seconds
-  save_timer_id=gdk_threads_add_timeout(30000, save_cb, NULL);
+  //save_timer_id=gdk_threads_add_timeout(30000, save_cb, NULL);
 
 #ifdef PSK
   if(vfo[active_receiver->id].mode==modePSK) {
@@ -710,6 +888,33 @@ void start_radio() {
     schedule_high_priority();
   }
 
+#ifdef SOAPYSDR
+  if(protocol==SOAPYSDR_PROTOCOL) {
+    RECEIVER *rx=receiver[0];
+    soapy_protocol_create_receiver(rx);
+
+
+    soapy_protocol_set_rx_antenna(rx,adc[0].antenna);
+    for(int i=0;i<radio->info.soapy.rx_gains;i++) {
+      soapy_protocol_set_gain(rx,radio->info.soapy.rx_gain[i],adc[0].rx_gain[i]);
+    }
+    soapy_protocol_set_rx_frequency(rx,VFO_A);
+    soapy_protocol_set_automatic_gain(rx,adc[0].agc);
+    for(int i=0;i<radio->info.soapy.rx_gains;i++) {
+      soapy_protocol_set_gain(rx,radio->info.soapy.rx_gain[i],adc[0].rx_gain[i]);
+    }
+    soapy_protocol_start_receiver(rx);
+/*
+    if(r->can_transmit) {
+      if(r->transmitter!=NULL && r->transmitter->rx==rx) {
+        soapy_protocol_set_tx_antenna(r->transmitter,1);
+        soapy_protocol_set_tx_frequency(r->transmitter);
+      }
+    }
+*/
+  }
+#endif
+
   g_idle_add(ext_vfo_update,(gpointer)NULL);
 
   gdk_window_set_cursor(gtk_widget_get_window(top_window),gdk_cursor_new(GDK_ARROW));
@@ -766,9 +971,9 @@ void radio_change_sample_rate(int rate) {
         tx_set_ps_sample_rate(transmitter,rate);
       }
       break;
-#ifdef LIMESDR
-    case LIMESDR_PROTOCOL:
-      lime_protocol_change_sample_rate(rate);
+#ifdef SOAPYSDR
+    case SOAPYSDR_PROTOCOL:
+      soapy_protocol_change_sample_rate(receiver[0],rate);
       break;
 #endif
   }
@@ -857,9 +1062,20 @@ void setMox(int state) {
     mox=state;
   }
   vox=0;
-  if(protocol==NEW_PROTOCOL) {
+  switch(protocol) {
+    case NEW_PROTOCOL:
       schedule_high_priority();
       schedule_receive_specific();
+      break;
+#ifdef SOAPYSDR
+    case SOAPYSDR_PROTOCOL:
+      if(transmitter!=NULL) {
+        soapy_protocol_set_tx_frequency(transmitter);
+      }
+      break;
+#endif
+    default:
+     break;
   }
 }
 
@@ -878,6 +1094,42 @@ void vox_changed(int state) {
   }
 }
 
+void frequency_changed(RECEIVER *rx) {
+//fprintf(stderr,"frequency_changed: channel=%d frequency=%ld lo=%ld error=%ld ctun=%d offset=%ld\n",rx->channel,rx->frequency_a,rx->lo_a,rx->error_a,rx->ctun,rx->offset);
+  if(vfo[0].ctun) {
+    SetRXAShiftFreq(rx->id, (double)vfo[0].offset);
+    RXANBPSetShiftFrequency(rx->id, (double)vfo[0].offset);
+#ifdef SOAPYSDR
+    if(radio->protocol==SOAPYSDR_PROTOCOL) {
+/*
+      if(radio->can_transmit) {
+        if(radio->transmitter!=NULL && radio->transmitter->rx==rx) {
+          //soapy_protocol_set_tx_frequency(radio->transmitter);
+        }
+      }
+*/
+    }
+#endif
+  } else {
+    double f=(double)(vfo[0].frequency-vfo[0].lo);
+    if(radio->protocol==NEW_PROTOCOL) {
+      schedule_high_priority();
+#ifdef SOAPYSDR
+    } else if(radio->protocol==SOAPYSDR_PROTOCOL) {
+      soapy_protocol_set_rx_frequency(rx,VFO_A);
+/*
+      if(radio->can_transmit) {
+        if(radio->transmitter!=NULL && radio->transmitter->rx==rx) {
+          soapy_protocol_set_tx_frequency(radio->transmitter);
+        }
+      }
+*/
+#endif
+    }
+    vfo[0].band=get_band_from_frequency(vfo[0].frequency);
+  }
+}
+
 
 void setTune(int state) {
   int i;
@@ -1002,6 +1254,9 @@ void setFrequency(long long f) {
   switch(protocol) {
     case NEW_PROTOCOL:
     case ORIGINAL_PROTOCOL:
+#ifdef SOAPYSDR
+    case SOAPYSDR_PROTOCOL:
+#endif
       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);
@@ -1015,20 +1270,6 @@ void setFrequency(long long f) {
         vfo[v].frequency=f;
       }
       break;
-#ifdef LIMESDR
-    case LIMESDR_PROTOCOL:
-      {
-fprintf(stderr,"setFrequency: %lld\n",f);
-      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;
-      vfo[v].offset=f-vfo[v].frequency;
-      set_offset(active_receiver,vfo[v].offset);
-      return;
-      }
-      break;
-#endif
   }
 
   switch(protocol) {
@@ -1037,11 +1278,12 @@ fprintf(stderr,"setFrequency: %lld\n",f);
       break;
     case ORIGINAL_PROTOCOL:
       break;
-#ifdef LIMESDR
-    case LIMESDR_PROTOCOL:
-      lime_protocol_set_frequency(f);
-      vfo[v].offset=0;
-      set_offset(active_receiver,vfo[v].offset);
+#ifdef SOAPYSDR
+    case SOAPYSDR_PROTOCOL:
+      if(!vfo[v].ctun) {
+        soapy_protocol_set_rx_frequency(active_receiver,v);
+        vfo[v].offset=0;
+      }
       break;
 #endif
   }
@@ -1112,9 +1354,9 @@ void set_attenuation(int value) {
       case NEW_PROTOCOL:
         schedule_high_priority();
         break;
-#ifdef LIMESDR
-      case LIMESDR_PROTOCOL:
-        lime_protocol_set_attenuation(value);
+#ifdef SOAPYSDR
+      case SOAPYSDR_PROTOCOL:
+        //soapy_protocol_set_attenuation(value);
         break;
 #endif
     }
@@ -1127,9 +1369,9 @@ void set_alex_rx_antenna(int v) {
           schedule_high_priority();
       }
     }
-#ifdef LIMESDR
-    if(protocol==LIMESDR_PROTOCOL) {
-        lime_protocol_set_antenna(v);;
+#ifdef SOAPYSDR
+    if(protocol==SOAPYSDR_PROTOCOL) {
+        soapy_protocol_set_rx_antenna(active_receiver,v);
     }
 #endif
 }
@@ -1160,14 +1402,17 @@ void set_alex_attenuation(int v) {
 }
 
 void radioRestoreState() {
+    char name[80];
     char *value;
 
 fprintf(stderr,"radioRestoreState: %s\n",property_path);
+fprintf(stderr,"sem_wait\n");
 #ifdef __APPLE__
     sem_wait(property_sem);
 #else
     sem_wait(&property_sem);
 #endif
+fprintf(stderr,"sem_wait: returner\n");
     loadProperties(property_path);
 
     value=getProperty("new_pa_board");
@@ -1206,10 +1451,8 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path);
     if(value) panadapter_low=atoi(value);
     value=getProperty("display_sliders");
     if(value) display_sliders=atoi(value);
-/*
     value=getProperty("display_toolbar");
     if(value) display_toolbar=atoi(value);
-*/
     value=getProperty("waterfall_high");
     if(value) waterfall_high=atoi(value);
     value=getProperty("waterfall_low");
@@ -1335,23 +1578,20 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path);
     value=getProperty("tone_level");
     if(value) tone_level=atof(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);
 
+    value=getProperty("iqswap");
+    if(value) iqswap=atoi(value);
+
     filterRestoreState();
     bandRestoreState();
     memRestoreState();
     vfo_restore_state();
     modesettings_restore_state();
+#ifdef GPIO
+    gpio_restore_actions();
+#endif
 #ifdef FREEDV
     freedv_restore_state();
 #endif
@@ -1368,8 +1608,34 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path);
     value=getProperty("rx1_gain_slider");
     if(value) rx_gain_slider[0]=atoi(value);
     value=getProperty("rx2_gain_slider");
-       if(value) rx_gain_slider[1]=atoi(value);
+    if(value) rx_gain_slider[1]=atoi(value);
+
+#ifdef SOAPYSDR
+  if(radio->device==SOAPYSDR_USB_DEVICE) {
+    for(int i=0;i<radio->info.soapy.rx_gains;i++) {
+      sprintf(name,"radio.adc[0].rx_gain.%s",radio->info.soapy.rx_gain[i]) ;
+      value=getProperty(name);
+      if(value!=NULL) adc[0].rx_gain[i]=atoi(value);
+    }
+    value=getProperty("radio.adc[0].agc");
+    if(value!=NULL) adc[0].agc=atoi(value);
+    value=getProperty("radio.adc[0].antenna");
+    if(value!=NULL) adc[0].antenna=atoi(value);
+
+/*
+    if(radio->can_transmit) {
+      for(int i=0;i<radio->info.soapy.tx_gains;i++) {
+        sprintf(name,"radio.dac[0].tx_gain.%s",radio->info.soapy.tx_gain[i]);
+        value=getProperty(name);
+        if(value!=NULL) dac[0].tx_gain[i]=atoi(value);
+      }
+    }
+*/
+  }
+#endif
+
        
+fprintf(stderr,"sem_post\n");
 #ifdef __APPLE__
     sem_post(property_sem);
 #else
@@ -1379,13 +1645,17 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path);
 
 void radioSaveState() {
     int i;
+    char name[80];
     char value[80];
 
+fprintf(stderr,"radioSaveState: %s\n",property_path);
+fprintf(stderr,"sem_wait\n");
 #ifdef __APPLE__
     sem_wait(property_sem);
 #else
     sem_wait(&property_sem);
 #endif
+fprintf(stderr,"sem_wait: returned\n");
     sprintf(value,"%d",new_pa_board);
     setProperty("new_pa_board",value);
     sprintf(value,"%d",region);
@@ -1416,6 +1686,8 @@ void radioSaveState() {
     setProperty("panadapter_low",value);
     sprintf(value,"%d",display_sliders);
     setProperty("display_sliders",value);
+    sprintf(value,"%d",display_toolbar);
+    setProperty("display_toolbar",value);
     sprintf(value,"%d",waterfall_high);
     setProperty("waterfall_high",value);
     sprintf(value,"%d",waterfall_low);
@@ -1531,24 +1803,69 @@ void radioSaveState() {
     sprintf(value,"%f",tone_level);
     setProperty("tone_level",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
-
     sprintf(value,"%d",adc_attenuation[0]);
     setProperty("adc_0_attenuation",value);
     sprintf(value,"%d",adc_attenuation[1]);
     setProperty("adc_1_attenuation",value);
        
-       sprintf(value,"%d",rx_gain_slider[0]);
+    sprintf(value,"%d",rx_gain_slider[0]);
     setProperty("rx1_gain_slider",value);
     sprintf(value,"%d",rx_gain_slider[1]);
     setProperty("rx2_gain_slider",value);
+
+#ifdef SOAPYSDR
+    if(radio->device==SOAPYSDR_USB_DEVICE) {
+      for(int i=0;i<radio->info.soapy.rx_gains;i++) {
+        sprintf(name,"radio.adc[0].rx_gain.%s",radio->info.soapy.rx_gain[i]);
+        sprintf(value,"%d", adc[0].rx_gain[i]);
+        setProperty(name,value);
+      }
+      sprintf(name,"radio.adc[0].agc");
+      sprintf(value,"%d", soapy_protocol_get_automatic_gain(receiver[0]));
+      setProperty(name,value);
+      sprintf(name,"radio.adc[0].antenna");
+      sprintf(value,"%d", adc[0].antenna);
+      setProperty(name,value);
+
+/*
+      if(radio->can_transmit) {
+        for(int i=0;i<radio->discovered->info.soapy.tx_gains;i++) {
+          sprintf(name,"radio.dac[0].tx_gain.%s",radio->discovered->info.soapy.tx_gain[i]);
+          sprintf(value,"%d", radio->dac[0].tx_gain[i]);
+          setProperty(name,value);
+        }
+      }
+*/
+      for(int i=0;i<radio->info.soapy.rx_gains;i++) {
+        sprintf(name,"radio.adc[1].rx_gain.%s",radio->info.soapy.rx_gain[i]);
+        sprintf(value,"%d", adc[1].rx_gain[i]);
+        setProperty(name,value);
+      }
+      sprintf(name,"radio.adc[1].agc");
+      sprintf(value,"%d", soapy_protocol_get_automatic_gain(receiver[1]));
+      setProperty(name,value);
+      sprintf(name,"radio.adc[1].antenna");
+      sprintf(value,"%d", adc[1].antenna);
+      setProperty(name,value);
+
+/*
+      if(radio->can_transmit) {
+        for(int i=0;i<radio->discovered->info.soapy.tx_gains;i++) {
+          sprintf(name,"radio.dac[1].tx_gain.%s",radio->discovered->info.soapy.tx_gain[i]);
+          sprintf(value,"%d", radio->dac[1].tx_gain[i]);
+          setProperty(name,value);
+        }
+      }
+*/
+    }
+#endif
+
+
+    sprintf(value,"%d",receivers);
+    setProperty("receivers",value);
+       
+    sprintf(value,"%d",iqswap);
+    setProperty("iqswap",value);
        
     vfo_save_state();
     modesettings_save_state();
@@ -1571,12 +1888,17 @@ void radioSaveState() {
     bandSaveState();
     memSaveState();
 
+#ifdef GPIO
+    gpio_save_actions();
+#endif
+
     sprintf(value,"%d",rigctl_enable);
     setProperty("rigctl_enable",value);
     sprintf(value,"%d",rigctl_port_base);
     setProperty("rigctl_port_base",value);
 
     saveProperties(property_path);
+fprintf(stderr,"sem_post\n");
 #ifdef __APPLE__
     sem_post(property_sem);
 #else
diff --git a/radio.h b/radio.h
index f1898aeea3696c799169865da9030ace578aac4b..f10902e7033d0fca40c34db4628c071a01871954 100644 (file)
--- a/radio.h
+++ b/radio.h
@@ -20,6 +20,7 @@
 #ifndef _RADIO_H
 #define _RADIO_H
 
+#include "adc.h"
 #include "discovered.h"
 #include "receiver.h"
 #include "transmitter.h"
@@ -88,6 +89,9 @@ extern TRANSMITTER *transmitter;
 
 extern int echo;
 
+extern int radio_sample_rate;
+extern gboolean iqswap;
+
 #define MAX_BUFFER_SIZE 2048
 
 extern int buffer_size;
@@ -146,7 +150,7 @@ extern int mic_ptt_tip_bias_ring;
 
 int receivers;
 
-int adc[2];
+ADC adc[2];
 int adc_attenuation[2];
 int rx_gain_slider[2];
 
@@ -265,6 +269,7 @@ extern int getMox();
 extern void setTune(int state);
 extern int getTune();
 extern void vox_changed(int state);
+extern void frequency_changed(RECEIVER *rx);
 extern double getDrive();
 extern void setDrive(double d);
 extern void calcDriveLevel();
index 9d40fdb12fde0af5c401644286560d0509f109a7..4f6b87f5ab4ffe46ef0788a05346b5878c304ce4 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "new_menu.h"
 #include "radio_menu.h"
+#include "adc.h"
 #include "band.h"
 #include "filter.h"
 #include "radio.h"
@@ -33,6 +34,9 @@
 #include "sliders.h"
 #include "new_protocol.h"
 #include "old_protocol.h"
+#ifdef SOAPYSDR
+#include "soapy_protocol.h"
+#endif
 #include "gpio.h"
 
 static GtkWidget *parent_window=NULL;
@@ -59,6 +63,46 @@ static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_d
   return FALSE;
 }
 
+#ifdef SOAPYSDR
+static void gain_value_changed_cb(GtkWidget *widget, gpointer data) {
+  ADC *adc=(ADC *)data;
+  int gain;
+  if(radio->device==SOAPYSDR_USB_DEVICE) {
+    gain=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
+    soapy_protocol_set_gain(receiver[0],(char *)gtk_widget_get_name(widget),gain);
+    for(int i=0;i<radio->info.soapy.rx_gains;i++) {
+      if(strcmp(radio->info.soapy.rx_gain[i],(char *)gtk_widget_get_name(widget))==0) {
+        adc[0].rx_gain[i]=gain;
+        break;
+      }
+    }
+  }
+}
+
+static void agc_changed_cb(GtkWidget *widget, gpointer data) {
+  ADC *adc=(ADC *)data;
+  gboolean agc=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+  soapy_protocol_set_automatic_gain(receiver[0],agc);
+}
+
+/*
+static void dac0_gain_value_changed_cb(GtkWidget *widget, gpointer data) {
+  DAC *dac=(DAC *)data;
+  int gain;
+  if(radio->device==SOAPYSDR_USB_DEVICE) {
+    gain=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
+    soapy_protocol_set_tx_gain(radio->transmitter,(char *)gtk_widget_get_name(widget),gain);
+    for(int i=0;i<radio->discovered->info.soapy.tx_gains;i++) {
+      if(strcmp(radio->discovered->info.soapy.tx_gain[i],(char *)gtk_widget_get_name(widget))==0) {
+        radio->dac[0].tx_gain[i]=gain;
+        break;
+      }
+    }
+  }
+}
+*/
+#endif
+
 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));
 }
@@ -94,6 +138,11 @@ static void bias_cb(GtkWidget *widget, gpointer data) {
   mic_bias_enabled=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
 }
 
+static void iqswap_cb(GtkWidget *widget, gpointer data) {
+  iqswap=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+}
+
+
 static void load_filters(void) {
   if(protocol==NEW_PROTOCOL) {
     filter_board_changed();
@@ -280,25 +329,25 @@ void radio_menu(GtkWidget *parent) {
       }
       break;
   
-#ifdef LIMESDR
-    case LIMESDR_PROTOCOL:
+#ifdef SOAPYSDR
+    case SOAPYSDR_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);
+      char rate[16];
+      sprintf(rate,"%d",radio->info.soapy.sample_rate);
+
+      GtkWidget *sample_rate=gtk_radio_button_new_with_label(NULL,rate);
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate), radio->info.soapy.sample_rate);
+      gtk_grid_attach(GTK_GRID(grid),sample_rate,x,2,1,1);
+      g_signal_connect(sample_rate,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)radio->info.soapy.sample_rate);
+
       x++;
       }
       break;
 #endif
+
   }
 
 
@@ -387,6 +436,11 @@ void radio_menu(GtkWidget *parent) {
   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);
 
+  GtkWidget *iqswap_b=gtk_check_button_new_with_label("Swap IQ");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (iqswap_b), iqswap);
+  gtk_grid_attach(GTK_GRID(grid),iqswap_b,x,4,1,1);
+  g_signal_connect(iqswap_b,"toggled",G_CALLBACK(iqswap_cb),NULL);
+
   x++;
 
 #ifdef USBOZY
@@ -429,6 +483,43 @@ void radio_menu(GtkWidget *parent) {
     g_signal_connect(pene_tx_b,"toggled",G_CALLBACK(penelopetx_cb),NULL);
   }
 
+#ifdef SOAPYSDR
+  if(radio->device==SOAPYSDR_USB_DEVICE) {
+    int i;
+    if(radio->info.soapy.rx_gains>0) {
+        x++;
+        GtkWidget *gain=gtk_label_new("Gains:");
+        gtk_grid_attach(GTK_GRID(grid),gain,0,x,1,1);
+        x++;
+      }
+
+      if(radio->info.soapy.rx_has_automatic_gain) {
+        GtkWidget *agc=gtk_check_button_new_with_label("Hardware AGC: ");
+        gtk_grid_attach(GTK_GRID(grid),agc,1,x,1,1);
+        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(agc),adc[0].agc);
+        g_signal_connect(agc,"toggled",G_CALLBACK(agc_changed_cb),&adc[0]);
+        x++;
+      }
+
+      for(i=0;i<radio->info.soapy.rx_gains;i++) {
+        GtkWidget *gain_label=gtk_label_new(radio->info.soapy.rx_gain[i]);
+        gtk_grid_attach(GTK_GRID(grid),gain_label,0,x,1,1);
+        SoapySDRRange range=radio->info.soapy.rx_range[i];
+        if(range.step==0.0) {
+          range.step=1.0;
+        }
+        GtkWidget *gain_b=gtk_spin_button_new_with_range(range.minimum,range.maximum,range.step);
+        gtk_widget_set_name (gain_b, radio->info.soapy.rx_gain[i]);
+        gtk_spin_button_set_value(GTK_SPIN_BUTTON(gain_b),(double)adc[0].rx_gain[i]);
+        gtk_grid_attach(GTK_GRID(grid),gain_b,1,x,1,1);
+        g_signal_connect(gain_b,"value_changed",G_CALLBACK(gain_value_changed_cb),&adc[0]);
+        x++;
+      }
+
+  }
+#endif
+
+
   gtk_container_add(GTK_CONTAINER(content),grid);
 
   sub_menu=dialog;
index 41a8664fc07a96d326bc2f55ceb4527b462bd20c..694bff9a807427198f98c84219a3bde88f240022 100644 (file)
 #include "main.h"
 #include "meter.h"
 #include "mode.h"
-#include "new_protocol.h"
-#include "old_protocol.h"
-#ifdef LIME_PROTOOCL
-#include "lime_protocol.h"
-#endif
 #include "property.h"
 #include "radio.h"
 #include "receiver.h"
 #include "rx_panadapter.h"
 #include "sliders.h"
 #include "waterfall.h"
+#include "new_protocol.h"
+#include "old_protocol.h"
+#ifdef SOAPYSDR
+#include "soapy_protocol.h"
+#endif
 #ifdef FREEDV
 #include "freedv.h"
 #endif
@@ -85,6 +85,8 @@ gboolean receiver_button_press_event(GtkWidget *widget, GdkEventButton *event, g
       last_x=(int)event->x;
       has_moved=FALSE;
       pressed=TRUE;
+    } else if(event->button==3) {
+      g_idle_add(ext_start_rx,NULL);
     }
   } else {
     making_active=TRUE;
@@ -100,6 +102,9 @@ gboolean receiver_button_release_event(GtkWidget *widget, GdkEventButton *event,
     g_idle_add(menu_active_receiver_changed,NULL);
     g_idle_add(ext_vfo_update,NULL);
     g_idle_add(sliders_active_receiver_changed,NULL);
+    if(event->button==3) {
+      g_idle_add(ext_start_rx,NULL);
+    }
   } else {
     int display_width=gtk_widget_get_allocated_width (rx->panadapter);
     int display_height=gtk_widget_get_allocated_height (rx->panadapter);
@@ -133,12 +138,13 @@ gboolean receiver_motion_notify_event(GtkWidget *widget, GdkEventMotion *event,
                                 &x,
                                 &y,
                                 &state);
-    if(state & GDK_BUTTON1_MASK) {
+    // G0ORX: removed test as with it unable to drag screen
+    //if(state & GDK_BUTTON1_MASK) {
       int moved=last_x-x;
       vfo_move((long long)((float)moved*rx->hz_per_pixel));
       last_x=x;
       has_moved=TRUE;
-    }
+    //}
   }
 
   return TRUE;
@@ -198,6 +204,9 @@ void receiver_save_state(RECEIVER *rx) {
   sprintf(name,"receiver.%d.panadapter_high",rx->id);
   sprintf(value,"%d",rx->panadapter_high);
   setProperty(name,value);
+  sprintf(name,"receiver.%d.panadapter_step",rx->id);
+  sprintf(value,"%d",rx->panadapter_step);
+  setProperty(name,value);
   sprintf(name,"receiver.%d.display_waterfall",rx->id);
   sprintf(value,"%d",rx->display_waterfall);
   setProperty(name,value);
@@ -367,6 +376,9 @@ fprintf(stderr,"receiver_restore_state: id=%d\n",rx->id);
   sprintf(name,"receiver.%d.panadapter_high",rx->id);
   value=getProperty(name);
   if(value) rx->panadapter_high=atoi(value);
+  sprintf(name,"receiver.%d.panadapter_step",rx->id);
+  value=getProperty(name);
+  if(value) rx->panadapter_step=atoi(value);
   sprintf(name,"receiver.%d.display_waterfall",rx->id);
   value=getProperty(name);
   if(value) rx->display_waterfall=atoi(value);
@@ -444,6 +456,11 @@ fprintf(stderr,"receiver_restore_state: id=%d\n",rx->id);
   if(value) rx->audio_channel=atoi(value);
   sprintf(name,"receiver.%d.local_audio",rx->id);
   value=getProperty(name);
+if(value) {
+  fprintf(stderr,"%s=%s\n",name,value);
+} else {
+  fprintf(stderr,"%s=NULL\n",name);
+}
   if(value) rx->local_audio=atoi(value);
   sprintf(name,"receiver.%d.mute_when_not_active",rx->id);
   value=getProperty(name);
@@ -800,6 +817,7 @@ fprintf(stderr,"create_pure_signal_receiver: id=%d buffer_size=%d\n",id,buffer_s
 
   rx->panadapter_high=-40;
   rx->panadapter_low=-140;
+  rx->panadapter_step=20;
 
   rx->volume=0.0;
 
@@ -894,7 +912,25 @@ fprintf(stderr,"create_receiver: id=%d buffer_size=%d fft_size=%d pixels=%d fps=
       }
   }
 fprintf(stderr,"create_receiver: id=%d default adc=%d\n",rx->id, rx->adc);
-  rx->sample_rate=48000;
+#ifdef SOAPYSDR
+  if(radio->device==SOAPYSDR_USB_DEVICE) {
+/*
+    if(strcmp(radio->name,"lime")==0) {
+      rx->sample_rate=384000;
+    } else if(strcmp(radio->name,"rtlsdr")==0) {
+      rx->sample_rate=384000;
+    } else {
+      rx->sample_rate=384000;
+    }
+*/
+    rx->sample_rate=radio->info.soapy.sample_rate;
+    rx->resample_step=1;
+  } else {
+#endif
+    rx->sample_rate=48000;
+#ifdef SOAPYSDR
+  }
+#endif
   rx->buffer_size=buffer_size;
   rx->fft_size=fft_size;
   rx->pixels=pixels;
@@ -979,6 +1015,9 @@ fprintf(stderr,"create_receiver: id=%d default adc=%d\n",rx->id, rx->adc);
 
   receiver_restore_state(rx);
 
+  rx->resample_step=radio->info.soapy.sample_rate/rx->sample_rate;
+
+fprintf(stderr,"create_receiver (after restore): rx=%p id=%d local_audio=%d\n",rx,rx->id,rx->local_audio);
   int scale=rx->sample_rate/48000;
   rx->output_samples=rx->buffer_size/scale;
   rx->audio_output_buffer=malloc(sizeof(double)*2*rx->output_samples);
@@ -1078,6 +1117,7 @@ fprintf(stderr,"RXASetMP %d\n",rx->low_latency);
 
   create_visual(rx);
 
+fprintf(stderr,"create_receiver: rx=%p id=%d local_audio=%d\n",rx,rx->id,rx->local_audio);
   if(rx->local_audio) {
     audio_open_output(rx);
   }
@@ -1135,6 +1175,14 @@ void receiver_change_sample_rate(RECEIVER *rx,int sample_rate) {
   SetInputSamplerate(rx->id, sample_rate);
   SetEXTANBSamplerate (rx->id, sample_rate);
   SetEXTNOBSamplerate (rx->id, sample_rate);
+
+#ifdef SOAPYSDR
+  if(protocol==SOAPYSDR_PROTOCOL) {
+    rx->resample_step=radio_sample_rate/rx->sample_rate;
+g_print("receiver_change_sample_rate: resample_step=%d\n",rx->resample_step);
+  }
+#endif
+
   SetChannelState(rx->id,1,0);
 
 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);
@@ -1146,8 +1194,17 @@ void receiver_frequency_changed(RECEIVER *rx) {
   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
+  } else {
+    switch(protocol) {
+      case NEW_PROTOCOL:
+        schedule_high_priority(); // send new frequency
+        break;
+#if SOAPYSDR
+      case SOAPYSDR_PROTOCOL:
+        soapy_protocol_set_rx_frequency(rx,id);
+        break;
+#endif
+    }
   }
 }
 
@@ -1232,8 +1289,8 @@ static void process_freedv_rx_buffer(RECEIVER *rx) {
                 case NEW_PROTOCOL:
                   new_protocol_audio_samples(rx,left_audio_sample,right_audio_sample);
                   break;
-#ifdef LIMESDR
-                case LIMESDR_PROTOCOL:
+#ifdef SOAPYSDR
+                case SOAPYSDR_PROTOCOL:
                   break;
 #endif
               }
@@ -1310,8 +1367,8 @@ static void process_rx_buffer(RECEIVER *rx) {
             }
           }
           break;
-#ifdef LIMESDR
-        case LIMESDR_PROTOCOL:
+#ifdef SOAPYSDR
+        case SOAPYSDR_PROTOCOL:
           break;
 #endif
       }
@@ -1352,7 +1409,7 @@ void full_rx_buffer(RECEIVER *rx) {
 
   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);
+    //fprintf(stderr,"full_rx_buffer: id=%d fexchange0: error=%d\n",rx->id,error);
   }
 
   if(rx->displaying) {
index 0327a99f650b9b25763a730c66068b480e71c199..0464c6321c7fa3ea698fdb181e5c3474b3c6d002 100644 (file)
@@ -39,6 +39,7 @@ typedef enum _audio_t audio_t;
 typedef struct _receiver {
   int id;
 
+  int ddc;
   int adc;
 
   double volume;
@@ -99,6 +100,7 @@ typedef struct _receiver {
 
   int panadapter_low;
   int panadapter_high;
+  int panadapter_step;
 
   int waterfall_low;
   int waterfall_high;
@@ -128,6 +130,9 @@ typedef struct _receiver {
 
   int mute_radio;
 
+  gdouble *buffer;
+  int resample_step;
+
 #ifdef FREEDV
   GMutex freedv_mutex;
   int freedv;
index 2628abf17a0fe087f4a5f493cb04e4afec489031..e92fc2a26ab5fb57f4b6c836f2531f167895b7e7 100644 (file)
Binary files a/release/pihpsdr-v1.2.3.tar and b/release/pihpsdr-v1.2.3.tar differ
index 2628abf17a0fe087f4a5f493cb04e4afec489031..ab8bf7558d1ddff3ef08f2d47ddfc2558fc47b1b 100644 (file)
Binary files a/release/pihpsdr.tar and b/release/pihpsdr.tar differ
index e44c8962692d106a6b248084b1718cefca31de46..757fd4ba661a23032054a670e544075742620e1a 100755 (executable)
@@ -33,11 +33,17 @@ fi
 cp pihpsdr.desktop ~/.local/share/applications
 echo "removing old versions of shared libraries"
 sudo rm -rf /usr/local/lib/libwdsp.so
-sudo rm -rf /usr/local/lib/libcodec2.*
 echo "installing pihpsdr"
 sudo cp pihpsdr /usr/local/bin
 echo "installing shared libraries"
 sudo cp libwdsp.so /usr/local/lib
-sudo cp libcodec2.so.0.7 /usr/local/lib
-cd /usr/local/lib; sudo ln -s libcodec2.so.0.7 libcodec2.so
+sudo cp libLimeSuite.so.19.04.1 /usr/local/lib
+sudo cp libSoapySDR.so.0.8.0 /usr/local/lib
+sudo cp -R SoapySDR /usr/local/lib
+cd /usr/local/lib
+sudo ln -s libLimeSuite.so.19.04.1 libLimeSuite.so.19.04-1
+sudo ln -s libLimeSuite.so.19.04-1 libLimeSuite.so
+sudo ln -s libSoapySDR.so.0.8.0 libSoapySDR.so.0.8
+sudo ln -s libSoapySDR.so.0.8 libLimeSuite.so
+sudo apt-get install librtlsdr-dev
 sudo ldconfig
diff --git a/release/pihpsdr/libSoapySDR.so.0.5-1 b/release/pihpsdr/libSoapySDR.so.0.5-1
deleted file mode 100755 (executable)
index 3c0232f..0000000
Binary files a/release/pihpsdr/libSoapySDR.so.0.5-1 and /dev/null differ
diff --git a/release/pihpsdr/libcodec2.so.0.7 b/release/pihpsdr/libcodec2.so.0.7
deleted file mode 100755 (executable)
index 5038f4f..0000000
Binary files a/release/pihpsdr/libcodec2.so.0.7 and /dev/null differ
diff --git a/release/pihpsdr/libpsk.so b/release/pihpsdr/libpsk.so
deleted file mode 100755 (executable)
index 0ace61f..0000000
Binary files a/release/pihpsdr/libpsk.so and /dev/null differ
index 744bf4b494d0527cba64299880894dd9e5e38978..a020b796df1e72ca20ea9b0d290c3c292e4dfb79 100755 (executable)
Binary files a/release/pihpsdr/libwdsp.so and b/release/pihpsdr/libwdsp.so differ
index 51696e9a08cd2d021821c7b97b0bdcf184e98eff..b741cd28536094fcbd64a98fe9cd5073aa46be79 100755 (executable)
Binary files a/release/pihpsdr/pihpsdr and b/release/pihpsdr/pihpsdr differ
index ee19965892ee7f24c30f9d0c803561471c8bd06e..54b61ba186e7578069a99ed8f85c17a79c462625 100644 (file)
--- a/rigctl.c
+++ b/rigctl.c
@@ -1181,7 +1181,7 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                                              fprintf(stderr,"RIGCTL: BD - current band=%d\n",cur_band);
                                              #endif
                                              if(cur_band == 0) {
-                                                #ifdef LIMESDR
+                                                #ifdef SOAPYSDR
                                                     cur_band = band472;
                                                 #else
                                                     cur_band = band6;
index 66d262cf7500c10a259cb59e9a53f75f89a43037..eec192747a07c435398f5c27e29030249227ca64 100644 (file)
--- a/rx_menu.c
+++ b/rx_menu.c
@@ -225,25 +225,30 @@ void rx_menu(GtkWidget *parent) {
       x++;
       break;
 
-#ifdef LIMESDR
-    case LIMESDR_PROTOCOL:
+#ifdef SOAPYSDR
+    case SOAPYSDR_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);
+      char rate[16];
+      sprintf(rate,"%d",radio->info.soapy.sample_rate);
+      GtkWidget *sample_rate=gtk_radio_button_new_with_label(NULL,rate);
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate), radio->info.soapy.sample_rate);
+      gtk_grid_attach(GTK_GRID(grid),sample_rate,x,2,1,1);
+      g_signal_connect(sample_rate,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)radio->info.soapy.sample_rate);
+
+      if(radio->info.soapy.sample_rate>384000) {
+          GtkWidget *sample_rate_384K=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate),"384000");
+          gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_384K), active_receiver->sample_rate==384000);
+          gtk_grid_attach(GTK_GRID(grid),sample_rate_384K,x,3,1,1);
+          g_signal_connect(sample_rate_384K,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)384000);
+      }
       }
       x++;
       break;
 #endif
+
   }
  
   //
index 52a2eb816a2cb53a524e0fce53ff9f2a32742ed9..ad363114d6307fe70b3299bccb8abaaef849a23a 100644 (file)
@@ -223,7 +223,7 @@ void rx_panadapter_update(RECEIVER *rx) {
 
 
   // filter
-  cairo_set_source_rgba (cr, 0.25, 0.25, 0.25, 0.75);
+  cairo_set_source_rgba (cr, 0.75, 0.75, 0.00, 0.75);
   filter_left =-cwshift+(double)display_width/2.0+(((double)rx->filter_low+vfo[rx->id].offset)/rx->hz_per_pixel);
   filter_right=-cwshift+(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);
@@ -260,7 +260,7 @@ void rx_panadapter_update(RECEIVER *rx) {
   char v[32];
 
   for(i=rx->panadapter_high;i>=rx->panadapter_low;i--) {
-    int mod=abs(i)%20;
+    int mod=abs(i)%rx->panadapter_step;
     if(mod==0) {
       double y = (double)(rx->panadapter_high-i)*dbm_per_line;
       cairo_move_to(cr,0.0,y);
@@ -327,7 +327,7 @@ void rx_panadapter_update(RECEIVER *rx) {
     // band edges
     if(band->frequencyMin!=0LL) {
       cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
-      cairo_set_line_width(cr, 2.0);
+      cairo_set_line_width(cr, 1.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);
@@ -458,26 +458,28 @@ void rx_panadapter_update(RECEIVER *rx) {
   }
 #endif
 
-#ifdef GPIO
+#ifdef GPIO 
+#ifndef CONTROLLER2 
   if(active) {
     cairo_set_source_rgb(cr,1.0,1.0,0.0);
     cairo_set_font_size(cr,16);
-    if(ENABLE_E1_ENCODER) {
+    if(ENABLE_E2_ENCODER) {
       cairo_move_to(cr, display_width-150,30);
-      cairo_show_text(cr, encoder_string[e1_encoder_action]);
+      cairo_show_text(cr, encoder_string[e2_encoder_action]);
     }
 
-    if(ENABLE_E2_ENCODER) {
+    if(ENABLE_E3_ENCODER) {
       cairo_move_to(cr, display_width-150,50);
-      cairo_show_text(cr, encoder_string[e2_encoder_action]);
+      cairo_show_text(cr, encoder_string[e3_encoder_action]);
     }
 
-    if(ENABLE_E3_ENCODER) {
+    if(ENABLE_E4_ENCODER) {
       cairo_move_to(cr, display_width-150,70);
-      cairo_show_text(cr, encoder_string[e3_encoder_action]);
+      cairo_show_text(cr, encoder_string[e4_encoder_action]);
     }
   }
 #endif
+#endif
 
 
   cairo_destroy (cr);
index f95fdee8f7aa25f1e2421981f3d1823aa276ca43..b9b0901240d7c4cf22cee74b9e79c6726a128249 100644 (file)
--- a/sliders.c
+++ b/sliders.c
@@ -69,6 +69,9 @@ static GtkWidget *sliders;
 #define ATTENUATION 6
 #define SQUELCH 7
 #define COMP 8
+#define FILTER_WIDTH 9
+#define DIVERSITY_GAIN 10
+#define DIVERSITY_PHASE 11
 
 static gint scale_timer;
 static int scale_status=NONE;
@@ -93,6 +96,9 @@ static GtkWidget *comp_label;
 static GtkWidget *comp_scale;
 static GtkWidget *comp_enable;
 static GtkWidget *dummy_label;
+static GtkWidget *filter_width_scale;
+static GtkWidget *diversity_gain_scale;
+static GtkWidget *diversity_phase_scale;
 
 static GdkRGBA white;
 static GdkRGBA gray;
@@ -275,11 +281,11 @@ static void agcgain_value_changed_cb(GtkWidget *widget, gpointer data) {
   SetRXAAGCTop(active_receiver->id, active_receiver->agc_gain);
 }
 
-void set_agc_gain(double value) {
-  active_receiver->agc_gain=value;
-  SetRXAAGCTop(active_receiver->id, active_receiver->agc_gain);
+void set_agc_gain(int rx,double value) {
+  receiver[rx]->agc_gain=value;
+  SetRXAAGCTop(receiver[rx]->id, receiver[rx]->agc_gain);
   if(display_sliders) {
-    gtk_range_set_value (GTK_RANGE(agc_scale),active_receiver->agc_gain);
+    gtk_range_set_value (GTK_RANGE(agc_scale),receiver[rx]->agc_gain);
   } else {
     if(scale_status!=AGC_GAIN) {
       if(scale_status!=NONE) {
@@ -294,7 +300,7 @@ void set_agc_gain(double value) {
       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),active_receiver->agc_gain);
+      gtk_range_set_value (GTK_RANGE(agc_scale),receiver[rx]->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);
@@ -302,14 +308,14 @@ 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),active_receiver->agc_gain);
+      gtk_range_set_value (GTK_RANGE(agc_scale),receiver[rx]->agc_gain);
       scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
     }
   }
 }
 
 void update_agc_gain(double gain) {
-  set_agc_gain(gain);
+  set_agc_gain(active_receiver->id,gain);
 }
 
 static void afgain_value_changed_cb(GtkWidget *widget, gpointer data) {
@@ -324,14 +330,14 @@ static void afgain_value_changed_cb(GtkWidget *widget, gpointer data) {
 }
 
 void update_af_gain() {
-  set_af_gain(active_receiver->volume);
+  set_af_gain(active_receiver->id,active_receiver->volume);
 }
 
-void set_af_gain(double value) {
-  active_receiver->volume=value;
-  SetRXAPanelGain1 (active_receiver->id, active_receiver->volume);
+void set_af_gain(int rx,double value) {
+  receiver[rx]->volume=value;
+  SetRXAPanelGain1 (receiver[rx]->id, receiver[rx]->volume);
   if(display_sliders) {
-    gtk_range_set_value (GTK_RANGE(af_gain_scale),active_receiver->volume*100.0);
+    gtk_range_set_value (GTK_RANGE(af_gain_scale),receiver[rx]->volume*100.0);
   } else {
     if(scale_status!=AF_GAIN) {
       if(scale_status!=NONE) {
@@ -346,7 +352,7 @@ void set_af_gain(double value) {
       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),active_receiver->volume*100.0);
+      gtk_range_set_value (GTK_RANGE(af_gain_scale),receiver[rx]->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);
@@ -354,12 +360,40 @@ 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),active_receiver->volume*100.0);
+      gtk_range_set_value (GTK_RANGE(af_gain_scale),receiver[rx]->volume*100.0);
       scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
     }
   }
 }
 
+void set_filter_width(int rx,int width) {
+    if(scale_status!=FILTER_WIDTH) {
+      if(scale_status!=NONE) {
+        g_source_remove(scale_timer);
+        gtk_widget_destroy(scale_dialog);
+        scale_status=NONE;
+      }
+    }
+    if(scale_status==NONE) {
+      scale_status=FILTER_WIDTH;
+      scale_dialog=gtk_dialog_new_with_buttons("Filter Width (Hz)",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+      GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
+      filter_width_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 4000.0, 1.00);
+      gtk_widget_set_size_request (filter_width_scale, 400, 30);
+      gtk_range_set_value (GTK_RANGE(filter_width_scale),(double)width);
+      gtk_widget_show(filter_width_scale);
+      gtk_container_add(GTK_CONTAINER(content),filter_width_scale);
+      scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
+      //gtk_widget_show_all(scale_dialog);
+      int result=gtk_dialog_run(GTK_DIALOG(scale_dialog));
+    } else {
+      g_source_remove(scale_timer);
+      gtk_range_set_value (GTK_RANGE(filter_width_scale),(double)width);
+      scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
+    }
+}
+
+
 static void micgain_value_changed_cb(GtkWidget *widget, gpointer data) {
     if(mic_linein) {
       linein_gain=(int)gtk_range_get_value(GTK_RANGE(widget));
@@ -583,6 +617,61 @@ void set_compression(TRANSMITTER* tx) {
   g_idle_add(ext_vfo_update, NULL);
 }
 
+void show_diversity_gain() {
+    if(scale_status!=DIVERSITY_GAIN) {
+      if(scale_status!=NONE) {
+        g_source_remove(scale_timer);
+        gtk_widget_destroy(scale_dialog);
+        scale_status=NONE;
+      }
+    }
+    if(scale_status==NONE) {
+      scale_status=DIVERSITY_GAIN;
+      scale_dialog=gtk_dialog_new_with_buttons("Diversity Gain",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+      GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
+      diversity_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,-12.0, 12.0, 0.1);
+      gtk_widget_set_size_request (diversity_gain_scale, 400, 30);
+      gtk_range_set_value (GTK_RANGE(diversity_gain_scale),div_gain);
+      gtk_widget_show(diversity_gain_scale);
+      gtk_container_add(GTK_CONTAINER(content),diversity_gain_scale);
+      scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
+      //gtk_widget_show_all(scale_dialog);
+      int result=gtk_dialog_run(GTK_DIALOG(scale_dialog));
+    } else {
+      g_source_remove(scale_timer);
+      gtk_range_set_value (GTK_RANGE(diversity_gain_scale),div_gain);
+      scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
+    }
+}
+
+void show_diversity_phase() {
+    if(scale_status!=DIVERSITY_PHASE) {
+      if(scale_status!=NONE) {
+        g_source_remove(scale_timer);
+        gtk_widget_destroy(scale_dialog);
+        scale_status=NONE;
+      }
+    }
+    if(scale_status==NONE) {
+      scale_status=DIVERSITY_PHASE;
+      scale_dialog=gtk_dialog_new_with_buttons("Diversity Phase",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+      GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
+      diversity_phase_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 360.0, 1.0);
+      gtk_widget_set_size_request (diversity_phase_scale, 400, 30);
+      gtk_range_set_value (GTK_RANGE(diversity_phase_scale),div_phase);
+      gtk_widget_show(diversity_phase_scale);
+      gtk_container_add(GTK_CONTAINER(content),diversity_phase_scale);
+      scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
+      //gtk_widget_show_all(scale_dialog);
+      int result=gtk_dialog_run(GTK_DIALOG(scale_dialog));
+    } else {
+      g_source_remove(scale_timer);
+      gtk_range_set_value (GTK_RANGE(diversity_phase_scale),div_phase);
+      scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
+    }
+}
+
+
 GtkWidget *sliders_init(int my_width, int my_height) {
   width=my_width;
   height=my_height;
index a33ac7f5a33ccff6ce3a00d783be19bf2b8789a1..32fef862452fa54f0eb2dc829e57138284f50fae 100644 (file)
--- a/sliders.h
+++ b/sliders.h
@@ -1,8 +1,6 @@
 /* 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.
 *
@@ -32,13 +30,15 @@ extern void update_agc_gain(double gain);
 extern void update_af_gain();
 extern int update_mic_gain(void *);
 extern int update_drive(void *);
+extern int update_tune_drive(void *);
 
-extern void set_agc_gain(double value);
-extern void set_af_gain(double value);
+extern void set_agc_gain(int rx,double value);
+extern void set_af_gain(int rx,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 void set_filter_width(int rx,int width);
 extern GtkWidget *sliders_init(int my_width, int my_height);
 
 extern void sliders_update();
@@ -46,4 +46,7 @@ extern void sliders_update();
 extern void set_squelch();
 extern void set_compression(TRANSMITTER *tx);
 
+extern void show_diversity_gain();
+extern void show_diversity_phase();
+
 #endif
diff --git a/soapy_discovery.c b/soapy_discovery.c
new file mode 100644 (file)
index 0000000..54c64fd
--- /dev/null
@@ -0,0 +1,244 @@
+/* Copyright (C)
+* 2019 - 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 <string.h>
+#include <SoapySDR/Device.h>
+#include <SoapySDR/Formats.h>
+#include "discovered.h"
+#include "soapy_discovery.h"
+
+static int rtlsdr_count=0;
+
+static void get_info(char *driver) {
+  size_t rx_rates_length, tx_rates_length, rx_gains_length, tx_gains_length, ranges_length, rx_antennas_length, tx_antennas_length, rx_bandwidth_length, tx_bandwidth_length;
+  int i;
+  SoapySDRKwargs args={};
+  int version=0;
+  int rtlsdr_val=0;
+
+  fprintf(stderr,"soapy_discovery: get_info: %s\n", driver);
+
+  SoapySDRKwargs_set(&args, "driver", driver);
+  if(strcmp(driver,"rtlsdr")==0) {
+    char count[16];
+    sprintf(count,"%d",rtlsdr_count);
+    SoapySDRKwargs_set(&args, "rtl", count);
+    rtlsdr_val=rtlsdr_count;
+    rtlsdr_count++;
+  }
+  SoapySDRDevice *sdr = SoapySDRDevice_make(&args);
+  SoapySDRKwargs_clear(&args);
+  version=0;
+
+  char *driverkey=SoapySDRDevice_getDriverKey(sdr);
+  fprintf(stderr,"DriverKey=%s\n",driverkey);
+
+  char *hardwarekey=SoapySDRDevice_getHardwareKey(sdr);
+  fprintf(stderr,"HardwareKey=%s\n",hardwarekey);
+
+  SoapySDRKwargs info=SoapySDRDevice_getHardwareInfo(sdr);
+  for(i=0;i<info.size;i++) {
+    fprintf(stderr,"soapy_discovery: hardware info key=%s val=%s\n",info.keys[i], info.vals[i]);
+    if(strcmp(info.keys[i],"firmwareVersion")==0) {
+      version+=atoi(info.vals[i])*100;
+    }
+    if(strcmp(info.keys[i],"hardwareVersion")==0) {
+      version+=atoi(info.vals[i])*10;
+    }
+    if(strcmp(info.keys[i],"protocolVersion")==0) {
+      version+=atoi(info.vals[i]);
+    }
+  }
+
+  size_t rx_channels=SoapySDRDevice_getNumChannels(sdr, SOAPY_SDR_RX);
+  fprintf(stderr,"Rx channels: %ld\n",rx_channels);
+  for(int i=0;i<rx_channels;i++) {
+    fprintf(stderr,"Rx channel full duplex: channel=%d fullduplex=%d\n",i,SoapySDRDevice_getFullDuplex(sdr, SOAPY_SDR_RX, i));
+  }
+
+  size_t tx_channels=SoapySDRDevice_getNumChannels(sdr, SOAPY_SDR_TX);
+  fprintf(stderr,"Tx channels: %ld\n",tx_channels);
+  for(int i=0;i<tx_channels;i++) {
+    fprintf(stderr,"Tx channel full duplex: channel=%d fullduplex=%d\n",i,SoapySDRDevice_getFullDuplex(sdr, SOAPY_SDR_TX, i));
+  }
+
+
+  int sample_rate=0;
+  SoapySDRRange *rx_rates=SoapySDRDevice_getSampleRateRange(sdr, SOAPY_SDR_RX, 0, &rx_rates_length);
+  fprintf(stderr,"Rx sample rates: ");
+  for (size_t i = 0; i < rx_rates_length; i++) {
+    fprintf(stderr,"%f -> %f (%f),", rx_rates[i].minimum, rx_rates[i].maximum, rx_rates[i].minimum/48000.0);
+    if(sample_rate==0) {
+      if(rx_rates[i].minimum==rx_rates[i].maximum) {
+        if(((int)rx_rates[i].minimum%48000)==0) {
+          sample_rate=(int)rx_rates[i].minimum;
+        }
+      } else {
+        if((384000.0>=rx_rates[i].minimum) && (384000<=(int)rx_rates[i].maximum)) {
+          sample_rate=384000;
+        }
+/*
+        if((768000.0>=rx_rates[i].minimum) && (768000<=(int)rx_rates[i].maximum)) {
+          sample_rate=768000;
+        }
+*/
+      }
+    }
+  }
+  fprintf(stderr,"\n");
+  free(rx_rates);
+  fprintf(stderr,"sample_rate selected %d\n",sample_rate);
+
+  SoapySDRRange *tx_rates=SoapySDRDevice_getSampleRateRange(sdr, SOAPY_SDR_TX, 1, &tx_rates_length);
+  fprintf(stderr,"Tx sample rates: ");
+  for (size_t i = 0; i < tx_rates_length; i++) {
+    fprintf(stderr,"%f -> %f (%f),", tx_rates[i].minimum, tx_rates[i].maximum, tx_rates[i].minimum/48000.0);
+  }
+  fprintf(stderr,"\n");
+  free(tx_rates);
+
+  double *bandwidths=SoapySDRDevice_listBandwidths(sdr, SOAPY_SDR_RX, 0, &rx_bandwidth_length);
+  fprintf(stderr,"Rx bandwidths: ");
+  for (size_t i = 0; i < rx_bandwidth_length; i++) {
+    fprintf(stderr,"%f, ", bandwidths[i]);
+  }
+  fprintf(stderr,"\n");
+  free(bandwidths);
+
+  bandwidths=SoapySDRDevice_listBandwidths(sdr, SOAPY_SDR_TX, 0, &tx_bandwidth_length);
+  fprintf(stderr,"Tx bandwidths: ");
+  for (size_t i = 0; i < tx_bandwidth_length; i++) {
+    fprintf(stderr,"%f, ", bandwidths[i]);
+  }
+  fprintf(stderr,"\n");
+  free(bandwidths);
+
+  double bandwidth=SoapySDRDevice_getBandwidth(sdr, SOAPY_SDR_RX, 0);
+  fprintf(stderr,"RX0: bandwidth=%f\n",bandwidth);
+
+  bandwidth=SoapySDRDevice_getBandwidth(sdr, SOAPY_SDR_TX, 0);
+  fprintf(stderr,"TX0: bandwidth=%f\n",bandwidth);
+
+  SoapySDRRange *ranges = SoapySDRDevice_getFrequencyRange(sdr, SOAPY_SDR_RX, 0, &ranges_length);
+  fprintf(stderr,"Rx freq ranges: ");
+  for (size_t i = 0; i < ranges_length; i++) fprintf(stderr,"[%f Hz -> %f Hz step=%f], ", ranges[i].minimum, ranges[i].maximum,ranges[i].step);
+  fprintf(stderr,"\n");
+
+  char** rx_antennas = SoapySDRDevice_listAntennas(sdr, SOAPY_SDR_RX, 0, &rx_antennas_length);
+  fprintf(stderr, "Rx antennas: ");
+  for (size_t i = 0; i < rx_antennas_length; i++) fprintf(stderr, "%s, ", rx_antennas[i]);
+  fprintf(stderr,"\n");
+
+  char** tx_antennas = SoapySDRDevice_listAntennas(sdr, SOAPY_SDR_TX, 0, &tx_antennas_length);
+  fprintf(stderr, "Tx antennas: ");
+  for (size_t i = 0; i < tx_antennas_length; i++) fprintf(stderr, "%s, ", tx_antennas[i]);
+  fprintf(stderr,"\n");
+
+  char **rx_gains = SoapySDRDevice_listGains(sdr, SOAPY_SDR_RX, 0, &rx_gains_length);
+
+  gboolean has_automatic_gain=SoapySDRDevice_hasGainMode(sdr, SOAPY_SDR_RX, 0);
+  fprintf(stderr,"has_automaic_gain=%d\n",has_automatic_gain);
+
+  gboolean has_automatic_dc_offset_correction=SoapySDRDevice_hasDCOffsetMode(sdr, SOAPY_SDR_RX, 0);
+  fprintf(stderr,"has_automaic_dc_offset_correction=%d\n",has_automatic_dc_offset_correction);
+
+  char **tx_gains = SoapySDRDevice_listGains(sdr, SOAPY_SDR_TX, 1, &tx_gains_length);
+
+  size_t formats_length;
+  char **formats = SoapySDRDevice_getStreamFormats(sdr,SOAPY_SDR_RX,0,&formats_length);
+  fprintf(stderr, "Rx formats: ");
+  for (size_t i = 0; i < formats_length; i++) fprintf(stderr, "%s, ", formats[i]);
+  fprintf(stderr,"\n");
+
+  fprintf(stderr,"float=%lu double=%lu\n",sizeof(float),sizeof(double));
+
+  if(devices<MAX_DEVICES) {
+    discovered[devices].device=SOAPYSDR_USB_DEVICE;
+    discovered[devices].protocol=SOAPYSDR_PROTOCOL;
+    strcpy(discovered[devices].name,driver);
+    discovered[devices].supported_receivers=rx_channels;
+    discovered[devices].supported_transmitters=tx_channels;
+    discovered[devices].adcs=rx_channels;
+    discovered[devices].status=STATE_AVAILABLE;
+    discovered[devices].software_version=version;
+    discovered[devices].frequency_min=ranges[0].minimum;
+    discovered[devices].frequency_max=ranges[0].maximum;
+    discovered[devices].info.soapy.sample_rate=sample_rate;
+    if(strcmp(driver,"rtlsdr")==0) {
+      discovered[devices].info.soapy.rtlsdr_count=rtlsdr_val;
+    } else {
+      discovered[devices].info.soapy.rtlsdr_count=0;
+    }
+    discovered[devices].info.soapy.rx_channels=rx_channels;
+    discovered[devices].info.soapy.rx_gains=rx_gains_length;
+    discovered[devices].info.soapy.rx_gain=rx_gains;
+    discovered[devices].info.soapy.rx_range=malloc(rx_gains_length*sizeof(SoapySDRRange));
+fprintf(stderr,"Rx gains: \n");
+    for (size_t i = 0; i < rx_gains_length; i++) {
+      fprintf(stderr,"%s ", rx_gains[i]);
+      SoapySDRRange rx_range=SoapySDRDevice_getGainElementRange(sdr, SOAPY_SDR_RX, 0, rx_gains[i]);
+      fprintf(stderr,"%f -> %f step=%f\n",rx_range.minimum,rx_range.maximum,rx_range.step);
+      discovered[devices].info.soapy.rx_range[i]=rx_range;
+    }
+    discovered[devices].info.soapy.rx_has_automatic_gain=has_automatic_gain;
+    discovered[devices].info.soapy.rx_has_automatic_dc_offset_correction=has_automatic_dc_offset_correction;
+    discovered[devices].info.soapy.rx_antennas=rx_antennas_length;
+    discovered[devices].info.soapy.rx_antenna=rx_antennas;
+
+    discovered[devices].info.soapy.tx_channels=tx_channels;
+    discovered[devices].info.soapy.tx_gains=tx_gains_length;
+    discovered[devices].info.soapy.tx_gain=tx_gains;
+    discovered[devices].info.soapy.tx_range=malloc(tx_gains_length*sizeof(SoapySDRRange));
+fprintf(stderr,"Tx gains: \n");
+    for (size_t i = 0; i < tx_gains_length; i++) {
+      fprintf(stderr,"%s ", tx_gains[i]);
+      SoapySDRRange tx_range=SoapySDRDevice_getGainElementRange(sdr, SOAPY_SDR_TX, 1, tx_gains[i]);
+      fprintf(stderr,"%f -> %f step=%f\n",tx_range.minimum,tx_range.maximum,tx_range.step);
+      discovered[devices].info.soapy.tx_range[i]=tx_range;
+    }
+    discovered[devices].info.soapy.tx_antennas=tx_antennas_length;
+    discovered[devices].info.soapy.tx_antenna=tx_antennas;
+    devices++;
+  }
+
+
+  free(ranges);
+
+}
+
+void soapy_discovery() {
+  size_t length;
+  int i,j;
+  SoapySDRKwargs args={};
+
+fprintf(stderr,"soapy_discovery\n");
+  SoapySDRKwargs *results = SoapySDRDevice_enumerate(NULL, &length);
+fprintf(stderr,"soapy_discovery: length=%d\n",length);
+  for (i = 0; i < length; i++) {
+    for (size_t j = 0; j < results[i].size; j++) {
+      if(strcmp(results[i].keys[j],"driver")==0 && strcmp(results[i].vals[j],"audio")!=0) {
+        get_info(results[i].vals[j]);
+      }
+    }
+  }
+  SoapySDRKwargsList_clear(results, length);
+}
diff --git a/soapy_discovery.h b/soapy_discovery.h
new file mode 100644 (file)
index 0000000..65df402
--- /dev/null
@@ -0,0 +1,25 @@
+/* Copyright (C)
+* 2019 - 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 _SOAPY_DISCOVERY_H
+#define _SOAPY_DISCOVERY_H
+
+void soapy_discovery();
+
+#endif
diff --git a/soapy_protocol.c b/soapy_protocol.c
new file mode 100644 (file)
index 0000000..2255dcb
--- /dev/null
@@ -0,0 +1,482 @@
+/* Copyright (C)
+* 2019 - 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <wdsp.h>
+
+#include "SoapySDR/Constants.h"
+#include "SoapySDR/Device.h"
+#include "SoapySDR/Formats.h"
+#include "SoapySDR/Version.h"
+
+//#define TIMING
+#ifdef TIMING
+#include <sys/time.h>
+#endif
+
+#include "band.h"
+#include "channel.h"
+#include "discovered.h"
+#include "mode.h"
+#include "filter.h"
+#include "receiver.h"
+#include "transmitter.h"
+//#include "wideband.h"
+//#include "adc.h"
+//#include "dac.h"
+#include "radio.h"
+#include "main.h"
+//#include "protocol1.h"
+#include "soapy_protocol.h"
+#include "audio.h"
+#include "signal.h"
+#include "vfo.h"
+#ifdef FREEDV
+#include "freedv.h"
+#endif
+#ifdef PSK
+#include "psk.h"
+#endif
+#include "ext.h"
+#include "error_handler.h"
+
+static double bandwidth=2500000.0;
+
+static SoapySDRDevice *soapy_device;
+static SoapySDRStream *rx_stream;
+static SoapySDRStream *tx_stream;
+static int soapy_rx_sample_rate;
+static int soapy_tx_sample_rate;
+static int max_samples;
+
+static int samples=0;
+
+static GThread *receive_thread_id;
+static gpointer receive_thread(gpointer data);
+
+static int actual_rate;
+
+#ifdef TIMING
+static int rate_samples;
+#endif
+
+static gboolean running;
+
+static int mic_sample_divisor=1;
+
+
+static int max_tx_samples;
+static float *output_buffer;
+static int output_buffer_index;
+
+SoapySDRDevice *get_soapy_device() {
+  return soapy_device;
+}
+
+void soapy_protocol_set_mic_sample_rate(int rate) {
+  mic_sample_divisor=rate/48000;
+}
+
+void soapy_protocol_change_sample_rate(RECEIVER *rx,int rate) {
+}
+
+void soapy_protocol_create_receiver(RECEIVER *rx) {
+  int rc;
+
+  soapy_rx_sample_rate=rx->sample_rate;
+
+fprintf(stderr,"soapy_protocol_create_receiver: setting samplerate=%f adc=%d\n",(double)soapy_rx_sample_rate,rx->adc);
+  rc=SoapySDRDevice_setSampleRate(soapy_device,SOAPY_SDR_RX,rx->adc,(double)soapy_rx_sample_rate);
+  if(rc!=0) {
+    fprintf(stderr,"soapy_protocol_create_receiver: SoapySDRDevice_setSampleRate(%f) failed: %s\n",(double)soapy_rx_sample_rate,SoapySDR_errToStr(rc));
+  }
+
+  size_t channel=rx->adc;
+#if defined(SOAPY_SDR_API_VERSION) && (SOAPY_SDR_API_VERSION < 0x00080000)
+fprintf(stderr,"soapy_protocol_create_receiver: SoapySDRDevice_setupStream(version<0x00080000): channel=%ld\n",channel);
+  rc=SoapySDRDevice_setupStream(soapy_device,&rx_stream,SOAPY_SDR_RX,SOAPY_SDR_CF32,&channel,1,NULL);
+  if(rc!=0) {
+    fprintf(stderr,"soapy_protocol_create_receiver: SoapySDRDevice_setupStream (RX) failed: %s\n",SoapySDR_errToStr(rc));
+    _exit(-1);
+  }
+#else
+fprintf(stderr,"soapy_protocol_create_receiver: SoapySDRDevice_setupStream(version>=0x00080000): channel=%ld\n",channel);
+  rx_stream=SoapySDRDevice_setupStream(soapy_device,SOAPY_SDR_RX,SOAPY_SDR_CF32,&channel,1,NULL);
+  if(rx_stream==NULL) {
+    fprintf(stderr,"soapy_protocol_create_receiver: SoapySDRDevice_setupStream (RX) failed (rx_stream is NULL)\n");
+    _exit(-1);
+  }
+#endif
+
+
+  max_samples=SoapySDRDevice_getStreamMTU(soapy_device,rx_stream);
+  if(max_samples>(2*rx->fft_size)) {
+    max_samples=2*rx->fft_size;
+  }
+  rx->buffer=g_new(double,max_samples*2);
+
+fprintf(stderr,"soapy_protocol_create_receiver: max_samples=%d buffer=%p\n",max_samples,rx->buffer);
+
+}
+
+void soapy_protocol_start_receiver(RECEIVER *rx) {
+  int rc;
+
+fprintf(stderr,"soapy_protocol_start_receiver: activate_stream\n");
+  rc=SoapySDRDevice_activateStream(soapy_device, rx_stream, 0, 0LL, 0);
+  if(rc!=0) {
+    fprintf(stderr,"soapy_protocol_start_receiver: SoapySDRDevice_activateStream failed: %s\n",SoapySDR_errToStr(rc));
+    _exit(-1);
+  }
+
+fprintf(stderr,"soapy_protocol_start_receiver: create receive_thread\n");
+  receive_thread_id = g_thread_new( "rx_thread", receive_thread, rx);
+  if( ! receive_thread_id )
+  {
+    fprintf(stderr,"g_thread_new failed for receive_thread\n");
+    exit( -1 );
+  }
+  fprintf(stderr, "receive_thread: id=%p\n",receive_thread_id);
+}
+
+void soapy_protocol_create_transmitter(TRANSMITTER *tx) {
+  int rc;
+
+  soapy_tx_sample_rate=tx->iq_output_rate;
+
+fprintf(stderr,"soapy_protocol_create_transmitter: setting samplerate=%f\n",(double)soapy_tx_sample_rate);
+  rc=SoapySDRDevice_setSampleRate(soapy_device,SOAPY_SDR_TX,8,(double)soapy_tx_sample_rate);
+  if(rc!=0) {
+    fprintf(stderr,"soapy_protocol_configure_transmitter: SoapySDRDevice_setSampleRate(%f) failed: %s\n",(double)soapy_tx_sample_rate,SoapySDR_errToStr(rc));
+  }
+
+  size_t channel=0;
+fprintf(stderr,"soapy_protocol_create_transmitter: SoapySDRDevice_setupStream: channel=%ld\n",channel);
+#if defined(SOAPY_SDR_API_VERSION) && (SOAPY_SDR_API_VERSION < 0x00080000)
+  rc=SoapySDRDevice_setupStream(soapy_device,&tx_stream,SOAPY_SDR_TX,SOAPY_SDR_CF32,&channel,1,NULL);
+  if(rc!=0) {
+    fprintf(stderr,"soapy_protocol_create_transmitter: SoapySDRDevice_setupStream (RX) failed: %s\n",SoapySDR_errToStr(rc));
+    _exit(-1);
+  }
+#else
+  tx_stream=SoapySDRDevice_setupStream(soapy_device,SOAPY_SDR_TX,SOAPY_SDR_CF32,&channel,1,NULL);
+  if(tx_stream==NULL) {
+    fprintf(stderr,"soapy_protocol_create_transmitter: SoapySDRDevice_setupStream (TX) failed: %s\n",SoapySDR_errToStr(rc));
+    _exit(-1);
+  }
+#endif
+
+  max_tx_samples=SoapySDRDevice_getStreamMTU(soapy_device,tx_stream);
+  if(max_tx_samples>(2*tx->fft_size)) {
+    max_tx_samples=2*tx->fft_size;
+  }
+fprintf(stderr,"soapy_protocol_create_transmitter: max_tx_samples=%d\n",max_tx_samples);
+  output_buffer=(float *)malloc(max_tx_samples*sizeof(float)*2);
+
+}
+
+void soapy_protocol_start_transmitter(TRANSMITTER *tx) {
+  int rc;
+
+fprintf(stderr,"soapy_protocol_start_transmitter: activateStream\n");
+  rc=SoapySDRDevice_activateStream(soapy_device, tx_stream, 0, 0LL, 0);
+  if(rc!=0) {
+    fprintf(stderr,"soapy_protocol_start_transmitter: SoapySDRDevice_activateStream failed: %s\n",SoapySDR_errToStr(rc));
+    _exit(-1);
+  }
+}
+
+void soapy_protocol_stop_transmitter(TRANSMITTER *tx) {
+  int rc;
+
+fprintf(stderr,"soapy_protocol_stop_transmitter: deactivateStream\n");
+  rc=SoapySDRDevice_deactivateStream(soapy_device, tx_stream, 0, 0LL);
+  if(rc!=0) {
+    fprintf(stderr,"soapy_protocol_stop_transmitter: SoapySDRDevice_deactivateStream failed: %s\n",SoapySDR_errToStr(rc));
+    _exit(-1);
+  }
+}
+
+void soapy_protocol_init(int rx,gboolean hf) {
+  SoapySDRKwargs args={};
+  int rc;
+  int i;
+
+fprintf(stderr,"soapy_protocol_init: rx=%d hf=%d\n",rx,hf);
+
+  // initialize the radio
+fprintf(stderr,"soapy_protocol_init: SoapySDRDevice_make\n");
+  SoapySDRKwargs_set(&args, "driver", radio->name);
+  if(strcmp(radio->name,"rtlsdr")==0) {
+    char id[16];
+    sprintf(id,"%d",radio->info.soapy.rtlsdr_count);
+    SoapySDRKwargs_set(&args, "rtl", id);
+
+    if(hf) {
+      SoapySDRKwargs_set(&args, "direct_samp", "2");
+    } else {
+      SoapySDRKwargs_set(&args, "direct_samp", "0");
+    }
+  }
+  soapy_device=SoapySDRDevice_make(&args);
+  if(soapy_device==NULL) {
+    fprintf(stderr,"soapy_protocol: SoapySDRDevice_make failed: %s\n",SoapySDRDevice_lastError());
+    _exit(-1);
+  }
+  SoapySDRKwargs_clear(&args);
+
+}
+
+static void *receive_thread(void *arg) {
+  double isample;
+  double qsample;
+  int elements;
+  int flags=0;
+  long long timeNs=0;
+  long timeoutUs=100000L;
+  int i;
+#ifdef TIMING
+  struct timeval tv;
+  long start_time, end_time;
+  rate_samples=0;
+  gettimeofday(&tv, NULL); start_time=tv.tv_usec + 1000000 * tv.tv_sec;
+#endif
+  RECEIVER *rx=(RECEIVER *)arg;
+  float *buffer=g_new(float,max_samples*2);
+  void *buffs[]={buffer};
+  running=TRUE;
+fprintf(stderr,"soapy_protocol: receive_thread\n");
+  while(running) {
+    elements=SoapySDRDevice_readStream(soapy_device,rx_stream,buffs,max_samples,&flags,&timeNs,timeoutUs);
+    if(elements<0) {
+      fprintf(stderr,"soapy_protocol_receive_thread: SoapySDRDevice_readStream failed: %s max_samples=%d\n",SoapySDR_errToStr(elements),max_samples);
+    }
+    for(i=0;i<elements;i++) {
+      rx->buffer[i*2]=(double)buffer[i*2];
+      rx->buffer[(i*2)+1]=(double)buffer[(i*2)+1];
+    }
+/*
+    if(rx->resampler!=NULL) {
+      int out_elements=xresample(rx->resampler);
+g_print("resampler: elements in=%d out=%d\n",elements,out_elements);
+      for(i=0;i<out_elements;i++) {
+        if(iqswap) {
+          qsample=rx->resampled_buffer[i*2];
+          isample=rx->resampled_buffer[(i*2)+1];
+        } else {
+          isample=rx->resampled_buffer[i*2];
+          qsample=rx->resampled_buffer[(i*2)+1];
+        }
+        add_iq_samples(rx,isample,qsample);
+      }
+*/
+    if(rx->sample_rate!=radio_sample_rate) {
+      for(int i=0;i<elements;i+=rx->resample_step) {
+/*
+        isample=0.0;
+        qsample=0.0;
+        for(int j=0;j<rx->resample_step;j++) {
+          isample+=rx->buffer[(i+j)*2];
+          qsample+=rx->buffer[((i+j)*2)+1];
+        }
+        if(iqswap) {
+          add_iq_samples(rx,qsample/(double)rx->resample_step,isample/(double)rx->resample_step);
+        } else {
+          add_iq_samples(rx,isample/(double)rx->resample_step,qsample/(double)rx->resample_step);
+        }
+*/
+        isample=rx->buffer[i*2];
+        qsample=rx->buffer[(i*2)+1];
+        if(iqswap) {
+          add_iq_samples(rx,qsample,isample);
+        } else {
+          add_iq_samples(rx,isample,qsample);
+        }
+      }
+    } else {
+      for(i=0;i<elements;i++) {
+        isample=rx->buffer[i*2];
+        qsample=rx->buffer[(i*2)+1];
+        if(iqswap) {
+          add_iq_samples(rx,qsample,isample);
+        } else {
+          add_iq_samples(rx,isample,qsample);
+        }
+#ifdef TIMING
+        rate_samples++;
+        if(rate_samples>=rx->sample_rate) {
+          gettimeofday(&tv, NULL); end_time=tv.tv_usec + 1000000 * tv.tv_sec;
+          fprintf(stderr,"%d samples in %ld usec\n",rx->sample_rate,end_time-start_time);
+          rate_samples=0;
+          start_time=end_time;
+        }
+#endif
+      }
+    }
+  }
+
+fprintf(stderr,"soapy_protocol: receive_thread: SoapySDRDevice_deactivateStream\n");
+  SoapySDRDevice_deactivateStream(soapy_device,rx_stream,0,0LL);
+fprintf(stderr,"soapy_protocol: receive_thread: SoapySDRDevice_closeStream\n");
+  SoapySDRDevice_closeStream(soapy_device,rx_stream);
+fprintf(stderr,"soapy_protocol: receive_thread: SoapySDRDevice_unmake\n");
+  SoapySDRDevice_unmake(soapy_device);
+  //_exit(0);
+}
+
+void soapy_protocol_process_local_mic(unsigned char *buffer) {
+  int b;
+  int i;
+  short sample;
+
+// always 48000 samples per second
+  b=0;
+  for(i=0;i<720;i++) {
+    sample=(short)(buffer[i]*32767.0);
+#ifdef FREEDV
+    if(active_receiver->freedv) {
+      add_freedv_mic_sample(transmitter,sample);
+    } else {
+#endif
+      add_mic_sample(transmitter,sample);
+#ifdef FREEDV
+    }
+#endif
+  }
+}
+
+void soapy_protocol_iq_samples(float isample,float qsample) {
+  const void *tx_buffs[]={output_buffer};
+  int flags=0;
+  long long timeNs=0;
+  long timeoutUs=100000L;
+  if(isTransmitting(radio)) {
+    output_buffer[output_buffer_index++]=isample;
+    output_buffer[output_buffer_index++]=qsample;
+    if(output_buffer_index>=max_tx_samples) {
+// write the buffer
+      int elements=SoapySDRDevice_writeStream(soapy_device,tx_stream,tx_buffs,max_tx_samples,&flags,timeNs,timeoutUs);
+      if(elements!=max_tx_samples) {
+        g_print("soapy_protocol_iq_samples: writeStream returned %d for %d elements\n",elements,max_tx_samples);
+      }
+      output_buffer_index=0;
+    }
+  }
+}
+
+
+
+void soapy_protocol_stop() {
+fprintf(stderr,"soapy_protocol_stop\n");
+  running=FALSE;
+}
+
+void soapy_protocol_set_rx_frequency(RECEIVER *rx,int v) {
+  int rc;
+
+  if(soapy_device!=NULL) {
+    double f=(double)(vfo[v].frequency-vfo[v].lo);
+//g_print("soapy_protocol_set_rx_frequency: %f (%f %f)\n",f,(double)vfo[v].frequency,(double)vfo[v].lo);
+    rc=SoapySDRDevice_setFrequency(soapy_device,SOAPY_SDR_RX,rx->adc,f,NULL);
+    if(rc!=0) {
+      fprintf(stderr,"soapy_protocol: SoapySDRDevice_setFrequency(RX) failed: %s\n",SoapySDR_errToStr(rc));
+    }
+  }
+}
+
+void soapy_protocol_set_tx_frequency(TRANSMITTER *tx) {
+  int v=active_receiver->id;
+  int rc;
+  double f;
+
+  if(soapy_device!=NULL) {
+    //f=(double)(vfo[v].frequency+vfo[v].ctun_frequency-vfo[v].lo_tx);
+    if(vfo[v].ctun) {
+      f=(double)(vfo[v].ctun_frequency-vfo[v].lo_tx);
+    } else {
+      f=(double)(vfo[v].frequency-vfo[v].lo_tx);
+    }
+//g_print("soapy_protocol_set_tx_frequency: %f\n",f);
+    rc=SoapySDRDevice_setFrequency(soapy_device,SOAPY_SDR_TX,active_receiver->adc,f,NULL);
+    if(rc!=0) {
+      fprintf(stderr,"soapy_protocol: SoapySDRDevice_setFrequency(TX) failed: %s\n",SoapySDR_errToStr(rc));
+    }
+  }
+}
+
+void soapy_protocol_set_rx_antenna(RECEIVER *rx,int ant) {
+  int rc;
+  if(soapy_device!=NULL) {
+//    fprintf(stderr,"soapy_protocol: set_rx_antenna: %s\n",radio->info.soapy.rx_antenna[ant]);
+    rc=SoapySDRDevice_setAntenna(soapy_device,SOAPY_SDR_RX,rx->adc,radio->info.soapy.rx_antenna[ant]);
+    if(rc!=0) {
+      fprintf(stderr,"soapy_protocol: SoapySDRDevice_setAntenna RX failed: %s\n",SoapySDR_errToStr(rc));
+    }
+  }
+}
+
+void soapy_protocol_set_tx_antenna(TRANSMITTER *tx,int ant) {
+  int rc;
+  if(soapy_device!=NULL) {
+//    fprintf(stderr,"soapy_protocol: set_tx_antenna: %s\n",radio->info.soapy.tx_antenna[ant]);
+    rc=SoapySDRDevice_setAntenna(soapy_device,SOAPY_SDR_TX,active_receiver->adc,radio->info.soapy.tx_antenna[ant]);
+    if(rc!=0) {
+      fprintf(stderr,"soapy_protocol: SoapySDRDevice_setAntenna TX failed: %s\n",SoapySDR_errToStr(rc));
+    }
+  }
+}
+
+void soapy_protocol_set_gain(RECEIVER *rx,char *name,int gain) {
+  int rc;
+//fprintf(stderr,"soapy_protocol_set_gain: adc=%d %s=%d\n",rx->adc,name,gain);
+  rc=SoapySDRDevice_setGainElement(soapy_device,SOAPY_SDR_RX,rx->adc,name,(double)gain);
+  if(rc!=0) {
+    fprintf(stderr,"soapy_protocol: SoapySDRDevice_setGain %s failed: %s\n",name,SoapySDR_errToStr(rc));
+  }
+}
+
+void soapy_protocol_set_tx_gain(TRANSMITTER *tx,char *name,int gain) {
+  int rc;
+  rc=SoapySDRDevice_setGainElement(soapy_device,SOAPY_SDR_TX,tx->dac,name,(double)gain);
+  if(rc!=0) {
+    fprintf(stderr,"soapy_protocol: SoapySDRDevice_setGain %s failed: %s\n",name,SoapySDR_errToStr(rc));
+  }
+}
+
+int soapy_protocol_get_gain(RECEIVER *rx,char *name) {
+  double gain;
+  gain=SoapySDRDevice_getGainElement(soapy_device,SOAPY_SDR_RX,rx->adc,name);
+  return (int)gain;
+}
+
+gboolean soapy_protocol_get_automatic_gain(RECEIVER *rx) {
+  gboolean mode=SoapySDRDevice_getGainMode(soapy_device, SOAPY_SDR_RX, rx->adc);
+  return mode;
+}
+
+void soapy_protocol_set_automatic_gain(RECEIVER *rx,gboolean mode) {
+  int rc;
+  rc=SoapySDRDevice_setGainMode(soapy_device, SOAPY_SDR_RX, rx->adc,mode);
+  if(rc!=0) {
+
+    fprintf(stderr,"soapy_protocol: SoapySDRDevice_getGainMode failed: %s\n", SoapySDR_errToStr(rc));
+  }
+}
diff --git a/soapy_protocol.h b/soapy_protocol.h
new file mode 100644 (file)
index 0000000..3db9d17
--- /dev/null
@@ -0,0 +1,49 @@
+/* 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 _SOAPY_PROTOCOL_H
+#define _SOAPY_PROTOCOL_H
+
+#define BUFFER_SIZE 1024
+
+SoapySDRDevice *get_soapy_device();
+
+void soapy_protocol_create_receiver(RECEIVER *rx);
+void soapy_protocol_start_receiver(RECEIVER *rx);
+
+void soapy_protocol_init(int rx,gboolean hf);
+void soapy_protocol_stop();
+void soapy_protocol_set_rx_frequency(RECEIVER *rx,int v);
+void soapy_protocol_set_rx_antenna(RECEIVER *rx,int ant);
+void soapy_protocol_set_lna_gain(RECEIVER *rx,int gain);
+void soapy_protocol_set_gain(RECEIVER *rx,char *name,int gain);
+int soapy_protocol_get_gain(RECEIVER *rx,char *name);
+void soapy_protocol_change_sample_rate(RECEIVER *rx,int rate);
+gboolean soapy_protocol_get_automatic_gain(RECEIVER *rx);
+void soapy_protocol_set_automatic_gain(RECEIVER *rx,gboolean mode);
+void soapy_protocol_create_transmitter(TRANSMITTER *tx);
+void soapy_protocol_start_transmitter(TRANSMITTER *tx);
+void soapy_protocol_stop_transmitter(TRANSMITTER *tx);
+void soapy_protocol_set_tx_frequency(TRANSMITTER *tx);
+void soapy_protocol_set_tx_antenna(TRANSMITTER *tx,int ant);
+void soapy_protocol_set_tx_gain(TRANSMITTER *tx,char *name,int gain);
+void soapy_protocol_process_local_mic(unsigned char *buffer);
+void soapy_protocol_iq_samples(float isample,float qsample);
+void soapy_protocol_set_mic_sample_rate(int rate);
+#endif
diff --git a/switch_menu.c b/switch_menu.c
new file mode 100644 (file)
index 0000000..fd5a40c
--- /dev/null
@@ -0,0 +1,395 @@
+/* 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.
+*
+*/
+
+#ifdef CONTROLLER2
+#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"
+#ifdef CONTROLLER2
+#include "i2c.h"
+#endif
+
+typedef struct _choice {
+  int sw;
+  int action;
+  GtkWidget *button;
+} CHOICE;
+
+static GtkWidget *parent_window=NULL;
+
+static GtkWidget *dialog=NULL;
+
+
+static void cleanup() {
+  if(dialog!=NULL) {
+    gtk_widget_destroy(dialog);
+    dialog=NULL;
+    active_menu=NO_MENU;
+    sub_menu=NULL;
+  }
+}
+
+static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  cleanup();
+  return TRUE;
+}
+
+static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
+  cleanup();
+  return FALSE;
+}
+
+
+static void sw_select_cb(GtkWidget *widget, gpointer data) {
+  char text[128];
+  CHOICE *choice=(CHOICE *)data;
+  sw_action[choice->sw]=choice->action;
+  GtkWidget *label=gtk_bin_get_child(GTK_BIN(choice->button));
+  sprintf(text,"<span size=\"smaller\">%s</span>",sw_string[choice->action]);
+  gtk_label_set_markup (GTK_LABEL(label), text);
+}
+
+static gboolean sw_cb(GtkWidget *widget, GdkEvent *event, gpointer data) {
+  int sw=GPOINTER_TO_INT(data);
+  int i;
+
+  GtkWidget *menu=gtk_menu_new();
+  for(i=0;i<SWITCH_ACTIONS;i++) {
+    GtkWidget *menu_item=gtk_menu_item_new_with_label(sw_string[i]);
+    CHOICE *choice=g_new0(CHOICE,1);
+    choice->sw=sw;
+    choice->action=i;
+    choice->button=widget;
+    g_signal_connect(menu_item,"activate",G_CALLBACK(sw_select_cb),choice);
+    gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
+fprintf(stderr,"%d=%s\n",i,sw_string[i]);
+  }
+  gtk_widget_show_all(menu);
+#if GTK_CHECK_VERSION(3,22,0)
+  gtk_menu_popup_at_pointer(GTK_MENU(menu),(GdkEvent *)event);
+// the following line of code is to work around the problem of the popup menu not having scroll bars.
+  gtk_menu_reposition(GTK_MENU(menu));
+#else
+  gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,0,gtk_get_current_event_time());
+#endif
+  return TRUE;
+}
+
+void switch_menu(GtkWidget *parent) {
+  int row=0;
+  int col=0;
+  int i;
+  char label[32];
+
+  dialog=gtk_dialog_new();
+  gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  char title[32];
+  sprintf(title,"piHPSDR - Encoder Actions:");
+  gtk_window_set_title(GTK_WINDOW(dialog),title);
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
+
+  GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+
+  GtkWidget *grid=gtk_grid_new();
+
+  gtk_grid_set_column_homogeneous(GTK_GRID(grid),FALSE);
+  gtk_grid_set_row_homogeneous(GTK_GRID(grid),FALSE);
+  gtk_grid_set_column_spacing (GTK_GRID(grid),2);
+  gtk_grid_set_row_spacing (GTK_GRID(grid),2);
+
+  GtkWidget *close_b=gtk_button_new_with_label("Close");
+  GtkWidget *close_label=gtk_bin_get_child(GTK_BIN(close_b));
+  sprintf(label,"<span size=\"smaller\">Close</span>");
+  gtk_label_set_markup (GTK_LABEL(close_label), label);
+  g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
+  gtk_grid_attach(GTK_GRID(grid),close_b,col,row,1,1);
+
+  row++;
+  col=0;
+
+#ifndef CONTROLLER2
+
+  GtkWidget *sw7_title=gtk_label_new("SW7: ");
+  gtk_grid_attach(GTK_GRID(grid),sw7_title,col,row,1,1);
+  col++;
+
+  GtkWidget *sw7_combo_box=gtk_combo_box_text_new();
+  for(i=0;i<SWITCH_ACTIONS;i++) {
+    gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(sw7_combo_box),NULL,sw_string[i]);
+  }
+  gtk_combo_box_set_active(GTK_COMBO_BOX(sw7_combo_box),sw_action[6]);
+  g_signal_connect(sw7_combo_box,"changed",G_CALLBACK(sw_cb),GINT_TO_POINTER(SW7));
+  gtk_grid_attach(GTK_GRID(grid),sw7_combo_box,col,row,1,1);
+  col++;
+
+  GtkWidget *sw1_title=gtk_label_new("SW1: ");
+  gtk_grid_attach(GTK_GRID(grid),sw1_title,col,row,1,1);
+  col++;
+
+  GtkWidget *sw1_combo_box=gtk_combo_box_text_new();
+  for(i=0;i<SWITCH_ACTIONS;i++) {
+    gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(sw1_combo_box),NULL,sw_string[i]);
+  }
+  gtk_combo_box_set_active(GTK_COMBO_BOX(sw1_combo_box),sw_action[0]);
+  g_signal_connect(sw1_combo_box,"changed",G_CALLBACK(sw_cb),GINT_TO_POINTER(SW1));
+  gtk_grid_attach(GTK_GRID(grid),sw1_combo_box,col,row,1,1);
+  row++;
+  col=0;
+
+  GtkWidget *sw2_title=gtk_label_new("SW2: ");
+  gtk_grid_attach(GTK_GRID(grid),sw2_title,col,row,1,1);
+  col++;
+
+  GtkWidget *sw2_combo_box=gtk_combo_box_text_new();
+  for(i=0;i<SWITCH_ACTIONS;i++) {
+    gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(sw2_combo_box),NULL,sw_string[i]);
+  }
+  gtk_combo_box_set_active(GTK_COMBO_BOX(sw2_combo_box),sw_action[1]);
+  g_signal_connect(sw2_combo_box,"changed",G_CALLBACK(sw_cb),GINT_TO_POINTER(SW2));
+  gtk_grid_attach(GTK_GRID(grid),sw2_combo_box,col,row,1,1);
+  col++;
+
+  GtkWidget *sw3_title=gtk_label_new("SW3: ");
+  gtk_grid_attach(GTK_GRID(grid),sw3_title,col,row,1,1);
+  col++;
+
+  GtkWidget *sw3_combo_box=gtk_combo_box_text_new();
+  for(i=0;i<SWITCH_ACTIONS;i++) {
+    gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(sw3_combo_box),NULL,sw_string[i]);
+  }
+  gtk_combo_box_set_active(GTK_COMBO_BOX(sw3_combo_box),sw_action[2]);
+  g_signal_connect(sw3_combo_box,"changed",G_CALLBACK(sw_cb),GINT_TO_POINTER(SW3));
+  gtk_grid_attach(GTK_GRID(grid),sw3_combo_box,col,row,1,1);
+  row++;
+  col=0;
+
+  GtkWidget *sw4_title=gtk_label_new("SW4: ");
+  gtk_grid_attach(GTK_GRID(grid),sw4_title,col,row,1,1);
+  col++;
+
+  GtkWidget *sw4_combo_box=gtk_combo_box_text_new();
+  for(i=0;i<SWITCH_ACTIONS;i++) {
+    gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(sw4_combo_box),NULL,sw_string[i]);
+  }
+  gtk_combo_box_set_active(GTK_COMBO_BOX(sw4_combo_box),sw_action[3]);
+  g_signal_connect(sw4_combo_box,"changed",G_CALLBACK(sw_cb),GINT_TO_POINTER(SW4));
+  gtk_grid_attach(GTK_GRID(grid),sw4_combo_box,col,row,1,1);
+  col++;
+
+  GtkWidget *sw5_title=gtk_label_new("SW5: ");
+  gtk_grid_attach(GTK_GRID(grid),sw5_title,col,row,1,1);
+  col++;
+
+  GtkWidget *sw5_combo_box=gtk_combo_box_text_new();
+  for(i=0;i<SWITCH_ACTIONS;i++) {
+    gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(sw5_combo_box),NULL,sw_string[i]);
+  }
+  gtk_combo_box_set_active(GTK_COMBO_BOX(sw5_combo_box),sw_action[4]);
+  g_signal_connect(sw5_combo_box,"changed",G_CALLBACK(sw_cb),GINT_TO_POINTER(SW5));
+  gtk_grid_attach(GTK_GRID(grid),sw5_combo_box,col,row,1,1);
+  row++;
+  col=0;
+
+  GtkWidget *sw6_title=gtk_label_new("SW6: ");
+  gtk_grid_attach(GTK_GRID(grid),sw6_title,col,row,1,1);
+  col++;
+
+  GtkWidget *sw6_combo_box=gtk_combo_box_text_new();
+  for(i=0;i<SWITCH_ACTIONS;i++) {
+    gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(sw6_combo_box),NULL,sw_string[i]);
+  }
+  gtk_combo_box_set_active(GTK_COMBO_BOX(sw6_combo_box),sw_action[5]);
+  g_signal_connect(sw6_combo_box,"changed",G_CALLBACK(sw_cb),GINT_TO_POINTER(SW6));
+  gtk_grid_attach(GTK_GRID(grid),sw6_combo_box,col,row,1,1);
+  col++;
+
+  GtkWidget *sw8_title=gtk_label_new("SW8: ");
+  gtk_grid_attach(GTK_GRID(grid),sw8_title,col,row,1,1);
+  col++;
+
+  GtkWidget *sw8_combo_box=gtk_combo_box_text_new();
+  for(i=0;i<SWITCH_ACTIONS;i++) {
+    gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(sw8_combo_box),NULL,sw_string[i]);
+  }
+  gtk_combo_box_set_active(GTK_COMBO_BOX(sw8_combo_box),sw_action[7]);
+  g_signal_connect(sw8_combo_box,"changed",G_CALLBACK(sw_cb),GINT_TO_POINTER(SW8));
+  gtk_grid_attach(GTK_GRID(grid),sw8_combo_box,col,row,1,1);
+  col++;
+
+#else
+
+  col=8;
+
+  GtkWidget *sw13=gtk_button_new_with_label(sw_string[sw_action[SW13]]);
+  GtkWidget *sw13_label=gtk_bin_get_child(GTK_BIN(sw13));
+  sprintf(label,"<span size=\"smaller\">%s</span>",sw_string[sw_action[SW13]]);
+  gtk_label_set_markup (GTK_LABEL(sw13_label), label);
+  gtk_grid_attach(GTK_GRID(grid),sw13,col,row,1,1);
+  g_signal_connect (sw13, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW13));
+  row++;
+  col=7;
+
+  GtkWidget *sw12=gtk_button_new_with_label(sw_string[sw_action[SW12]]);
+  GtkWidget *sw12_label=gtk_bin_get_child(GTK_BIN(sw12));
+  sprintf(label,"<span size=\"smaller\">%s</span>",sw_string[sw_action[SW12]]);
+  gtk_label_set_markup (GTK_LABEL(sw12_label), label);
+  gtk_grid_attach(GTK_GRID(grid),sw12,col,row,1,1);
+  g_signal_connect (sw12, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW12));
+  col++;
+
+  GtkWidget *sw11=gtk_button_new_with_label(sw_string[sw_action[SW11]]);
+  GtkWidget *sw11_label=gtk_bin_get_child(GTK_BIN(sw11));
+  sprintf(label,"<span size=\"smaller\">%s</span>",sw_string[sw_action[SW11]]);
+  gtk_label_set_markup (GTK_LABEL(sw11_label), label);
+  gtk_grid_attach(GTK_GRID(grid),sw11,col,row,1,1);
+  g_signal_connect (sw11, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW11));
+  row++;
+  col=7;
+
+  GtkWidget *sw10=gtk_button_new_with_label(sw_string[sw_action[SW10]]);
+  GtkWidget *sw10_label=gtk_bin_get_child(GTK_BIN(sw10));
+  sprintf(label,"<span size=\"smaller\">%s</span>",sw_string[sw_action[SW10]]);
+  gtk_label_set_markup (GTK_LABEL(sw10_label), label);
+  gtk_grid_attach(GTK_GRID(grid),sw10,col,row,1,1);
+  g_signal_connect (sw10, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW10));
+  col++;
+
+  GtkWidget *sw9=gtk_button_new_with_label(sw_string[sw_action[SW9]]);
+  GtkWidget *sw9_label=gtk_bin_get_child(GTK_BIN(sw9));
+  sprintf(label,"<span size=\"smaller\">%s</span>",sw_string[sw_action[SW9]]);
+  gtk_label_set_markup (GTK_LABEL(sw9_label), label);
+  gtk_grid_attach(GTK_GRID(grid),sw9,col,row,1,1);
+  g_signal_connect (sw9, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW9));
+  row++;
+  col=7;
+
+  GtkWidget *sw7=gtk_button_new_with_label(sw_string[sw_action[SW7]]);
+  GtkWidget *sw7_label=gtk_bin_get_child(GTK_BIN(sw7));
+  sprintf(label,"<span size=\"smaller\">%s</span>",sw_string[sw_action[SW7]]);
+  gtk_label_set_markup (GTK_LABEL(sw7_label), label);
+  gtk_grid_attach(GTK_GRID(grid),sw7,col,row,1,1);
+  g_signal_connect (sw7, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW7));
+  col++;
+
+  GtkWidget *sw8=gtk_button_new_with_label(sw_string[sw_action[SW8]]);
+  GtkWidget *sw8_label=gtk_bin_get_child(GTK_BIN(sw8));
+  sprintf(label,"<span size=\"smaller\">%s</span>",sw_string[sw_action[SW8]]);
+  gtk_label_set_markup (GTK_LABEL(sw8_label), label);
+  gtk_grid_attach(GTK_GRID(grid),sw8,col,row,1,1);
+  g_signal_connect (sw8, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW8));
+  row++;
+  col=7;
+
+  GtkWidget *sw16=gtk_button_new_with_label(sw_string[sw_action[SW16]]);
+  GtkWidget *sw16_label=gtk_bin_get_child(GTK_BIN(sw16));
+  sprintf(label,"<span size=\"smaller\">%s</span>",sw_string[sw_action[SW16]]);
+  gtk_label_set_markup (GTK_LABEL(sw16_label), label);
+  gtk_grid_attach(GTK_GRID(grid),sw16,col,row,1,1);
+  g_signal_connect (sw16, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW16));
+  col++;
+
+  GtkWidget *sw17=gtk_button_new_with_label(sw_string[sw_action[SW17]]);
+  GtkWidget *sw17_label=gtk_bin_get_child(GTK_BIN(sw17));
+  sprintf(label,"<span size=\"smaller\">%s</span>",sw_string[sw_action[SW17]]);
+  gtk_label_set_markup (GTK_LABEL(sw17_label), label);
+  gtk_grid_attach(GTK_GRID(grid),sw17,col,row,1,1);
+  g_signal_connect (sw17, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW17));
+  row++;
+  col=0;
+
+  GtkWidget *sw2=gtk_button_new_with_label(sw_string[sw_action[SW2]]);
+  GtkWidget *sw2_label=gtk_bin_get_child(GTK_BIN(sw2));
+  sprintf(label,"<span size=\"smaller\">%s</span>",sw_string[sw_action[SW2]]);
+  gtk_label_set_markup (GTK_LABEL(sw2_label), label);
+  gtk_grid_attach(GTK_GRID(grid),sw2,col,row,1,1);
+  g_signal_connect (sw2, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW2));
+  col++;
+  
+  GtkWidget *sw3=gtk_button_new_with_label(sw_string[sw_action[SW3]]);
+  GtkWidget *sw3_label=gtk_bin_get_child(GTK_BIN(sw3));
+  sprintf(label,"<span size=\"smaller\">%s</span>",sw_string[sw_action[SW3]]);
+  gtk_label_set_markup (GTK_LABEL(sw3_label), label);
+  gtk_grid_attach(GTK_GRID(grid),sw3,col,row,1,1);
+  g_signal_connect (sw3, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW3));
+  col++;
+  
+  GtkWidget *sw4=gtk_button_new_with_label(sw_string[sw_action[SW4]]);
+  GtkWidget *sw4_label=gtk_bin_get_child(GTK_BIN(sw4));
+  sprintf(label,"<span size=\"smaller\">%s</span>",sw_string[sw_action[SW4]]);
+  gtk_label_set_markup (GTK_LABEL(sw4_label), label);
+  gtk_grid_attach(GTK_GRID(grid),sw4,col,row,1,1);
+  g_signal_connect (sw4, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW4));
+  col++;
+  
+  GtkWidget *sw5=gtk_button_new_with_label(sw_string[sw_action[SW5]]);
+  GtkWidget *sw5_label=gtk_bin_get_child(GTK_BIN(sw5));
+  sprintf(label,"<span size=\"smaller\">%s</span>",sw_string[sw_action[SW5]]);
+  gtk_label_set_markup (GTK_LABEL(sw5_label), label);
+  gtk_grid_attach(GTK_GRID(grid),sw5,col,row,1,1);
+  g_signal_connect (sw5, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW5));
+  col++;
+  
+  GtkWidget *sw6=gtk_button_new_with_label(sw_string[sw_action[SW6]]);
+  GtkWidget *sw6_label=gtk_bin_get_child(GTK_BIN(sw6));
+  sprintf(label,"<span size=\"smaller\">%s</span>",sw_string[sw_action[SW6]]);
+  gtk_label_set_markup (GTK_LABEL(sw6_label), label);
+  gtk_grid_attach(GTK_GRID(grid),sw6,col,row,1,1);
+  g_signal_connect (sw6, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW6));
+  col++;
+  
+  GtkWidget *sw14=gtk_button_new_with_label(sw_string[sw_action[SW14]]);
+  GtkWidget *sw14_label=gtk_bin_get_child(GTK_BIN(sw14));
+  sprintf(label,"<span size=\"smaller\">%s</span>",sw_string[sw_action[SW14]]);
+  gtk_label_set_markup (GTK_LABEL(sw14_label), label);
+  gtk_grid_attach(GTK_GRID(grid),sw14,col,row,1,1);
+  g_signal_connect (sw14, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW14));
+  col++;
+  
+  GtkWidget *sw15=gtk_button_new_with_label(sw_string[sw_action[SW15]]);
+  GtkWidget *sw15_label=gtk_bin_get_child(GTK_BIN(sw15));
+  sprintf(label,"<span size=\"smaller\">%s</span>",sw_string[sw_action[SW15]]);
+  gtk_label_set_markup (GTK_LABEL(sw15_label), label);
+  gtk_grid_attach(GTK_GRID(grid),sw15,col,row,1,1);
+  g_signal_connect (sw15, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW15));
+  col++;
+
+
+
+#endif
+
+  gtk_container_add(GTK_CONTAINER(content),grid);
+
+  sub_menu=dialog;
+
+  gtk_widget_show_all(dialog);
+}
+#endif
diff --git a/switch_menu.h b/switch_menu.h
new file mode 100644 (file)
index 0000000..487b77b
--- /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 _SWITCH_MENU_H
+#define _SWITCH_MENU_H
+
+extern void switch_menu(GtkWidget *parent);
+
+extern void switch_select(int pos);
+#endif
index 43371184765b37fd181857817e1df37379dc60ed..395db8e09060e6a3d6abc538bc70f1a6f184444f 100644 (file)
--- a/toolbar.c
+++ b/toolbar.c
@@ -48,7 +48,6 @@
 #include "button_text.h"
 #include "ext.h"       
 
-#define MAX_FUNCTION 3
 int function=0;
 
 static int width;
@@ -351,6 +350,7 @@ void mox_cb(GtkWidget *widget, gpointer data) {
 }
 
 void mox_update(int state) {
+fprintf(stderr,"mox_update: state=%d\n",state);
   if(getTune()==1) {
     setTune(0);
   }
index 38b2487ad376bb603bdc40a85ccd48ca2537fe8f..19b1adfca2e2c9559ff4bc8247958c7e41160b23 100644 (file)
--- a/toolbar.h
+++ b/toolbar.h
@@ -20,6 +20,8 @@
 #ifndef _TOOLBAR_H
 #define _TOOLBAR_H
 
+#define MAX_FUNCTION 3
+
 extern int function;
 
 
index 0defd5ff5cf7edf84405f10c276ee3eb11874aa7..388682423bc7fc634c904bd474008f903bd1d9c5 100644 (file)
@@ -26,6 +26,7 @@
 
 typedef struct _transmitter {
   int id;
+  int dac;
   int fps;
   int displaying;
   int mic_sample_rate;
index e9690f720943dc5f5e664b6de98351b31b191270..209bbc1afa5f269684c5bc5f4e545ac2990c7750 100644 (file)
@@ -349,23 +349,25 @@ void tx_panadapter_update(TRANSMITTER *tx) {
 #endif
 
 #ifdef GPIO
+#ifndef CONTROLLER2
   cairo_set_source_rgb(cr,1.0,1.0,0.0);
   cairo_set_font_size(cr,16);
-  if(ENABLE_E1_ENCODER) {
+  if(ENABLE_E2_ENCODER) {
     cairo_move_to(cr, display_width-150,30);
-    cairo_show_text(cr, encoder_string[e1_encoder_action]);
+    cairo_show_text(cr, encoder_string[e2_encoder_action]);
   }
 
-  if(ENABLE_E2_ENCODER) {
+  if(ENABLE_E3_ENCODER) {
     cairo_move_to(cr, display_width-150,50);
-    cairo_show_text(cr, encoder_string[e2_encoder_action]);
+    cairo_show_text(cr, encoder_string[e3_encoder_action]);
   }
 
-  if(ENABLE_E3_ENCODER) {
+  if(ENABLE_E4_ENCODER) {
     cairo_move_to(cr, display_width-150,70);
-    cairo_show_text(cr, encoder_string[e3_encoder_action]);
+    cairo_show_text(cr, encoder_string[e4_encoder_action]);
   }
 #endif
+#endif
 
 #ifdef PURESIGNAL
   if(tx->puresignal) {
index ea575533ac745e8a3e98a4d25e6fc5d7e15d3a99..2b9e70646c3bfa6484c123ea26dfb0dd089109e7 100644 (file)
--- a/version.c
+++ b/version.c
@@ -20,4 +20,8 @@
 char build_date[]=GIT_DATE;
 char build_version[]=GIT_VERSION;
 
-char version[]=GIT_VERSION;
+#ifdef CONTROLLER2
+char version[]="2.0.0 (Controller2)";
+#else
+char version[]="2.0.0";
+#endif
diff --git a/vfo.c b/vfo.c
index 01075cc950f031531261fd8e7d2ea1c4e4eeea42..0664f8e678c8100f2041d2682856a4068a3a3655 100644 (file)
--- a/vfo.c
+++ b/vfo.c
@@ -173,6 +173,9 @@ void vfo_save_state() {
     sprintf(name,"vfo.%d.lo",i);
     sprintf(value,"%lld",vfo[i].lo);
     setProperty(name,value);
+    sprintf(name,"vfo.%d.lo_tx",i);
+    sprintf(value,"%lld",vfo[i].lo_tx);
+    setProperty(name,value);
     sprintf(name,"vfo.%d.ctun_frequency",i);
     sprintf(value,"%lld",vfo[i].ctun_frequency);
     setProperty(name,value);
@@ -236,7 +239,9 @@ void vfo_restore_state() {
     sprintf(name,"vfo.%d.filter",i);
     value=getProperty(name);
     if(value) vfo[i].filter=atoi(value);
-
+    sprintf(name,"vfo.%d.lo_tx",i);
+    value=getProperty(name);
+    if(value) vfo[i].lo_tx=atoll(value);
   }
 }
 
@@ -279,6 +284,8 @@ void vfo_band_changed(int b) {
   vfo[id].mode=entry->mode;
   vfo[id].filter=entry->filter;
   vfo[id].lo=band->frequencyLO+band->errorLO;
+  vfo[id].lo_tx=band->txFrequencyLO+band->txErrorLO;
+
 
   switch(id) {
     case 0:
@@ -537,11 +544,13 @@ void vfo_move(long long hz) {
   int id=active_receiver->id;
   if(!locked) {
     switch(protocol) {
-#ifdef LIMESDR
-      case LIMESDR_PROTOCOL:
+/*
+#ifdef SOAPYSDR
+      case SOAPYSDR_PROTOCOL:
         vfo[id].ctun_frequency=((vfo[id].ctun_frequency-hz)/step)*step;
         break;
 #endif
+*/
       default:
         if(vfo[id].ctun) {
           vfo[id].ctun_frequency=((vfo[id].ctun_frequency-hz)/step)*step;
@@ -559,11 +568,13 @@ void vfo_move_to(long long hz) {
   int id=active_receiver->id;
   if(!locked) {
     switch(protocol) {
-#ifdef LIMESDR
-      case LIMESDR_PROTOCOL:
+/*
+#ifdef SOAPYSDR
+      case SOAPYSDR_PROTOCOL:
         vfo[id].ctun_frequency=(vfo[id].frequency+hz)/step*step;
         break;
 #endif
+*/
       default:
         if(vfo[id].ctun) {
           vfo[id].ctun_frequency=(vfo[id].frequency+hz)/step*step;
@@ -588,8 +599,8 @@ void vfo_move_to(long long hz) {
 
     BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
 
-#ifdef LIMESDR
-    if(protocol==LIMESDR_PROTOCOL) {
+#ifdef SOAPYSDR
+    if(protocol==SOAPYSDR_PROTOCOL) {
       setFrequency((entry->frequency+active_receiver->dds_offset-hz)/step*step);
     } else {
 #endif
@@ -604,7 +615,7 @@ void vfo_move_to(long long hz) {
         }
         setFrequency(f);
       }
-#ifdef LIMESDR
+#ifdef SOAPYSDR
     }
 #endif
 #endif
@@ -789,7 +800,7 @@ void vfo_update() {
           cairo_show_text(cr, "NR2");
        } else {
           cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
-          cairo_show_text(cr, "NR2");
+          cairo_show_text(cr, "NR");
         }
 
         cairo_move_to(cr, 210, 50);  
@@ -846,6 +857,14 @@ void vfo_update() {
             cairo_show_text(cr, "CMPR OFF");
        }
 
+        cairo_move_to(cr, 500, 50);  
+        if(diversity_enabled) {
+          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, "DIV");
+
         int s=0;
         while(steps[s]!=step && steps[s]!=0) {
           s++;
diff --git a/vfo.h b/vfo.h
index 081da643f356635121468be2a1601cd194749e56..c2218851e23eca3e2617e8ef6f77c1d5d97d638a 100644 (file)
--- a/vfo.h
+++ b/vfo.h
@@ -42,6 +42,7 @@ struct _vfo {
 
   long long lo;
   long long offset;
+  long long lo_tx;
 
 } vfo[MAX_VFOS];
 
index 962d583c2504f4629fa466a91e561370e424ee65..d8258183d00856adc1d3c9a5179c2014e2b47ef8 100644 (file)
@@ -39,6 +39,8 @@ static GtkWidget *min_frequency[BANDS+XVTRS];
 static GtkWidget *max_frequency[BANDS+XVTRS];
 static GtkWidget *lo_frequency[BANDS+XVTRS];
 static GtkWidget *lo_error[BANDS+XVTRS];
+static GtkWidget *tx_lo_frequency[BANDS+XVTRS];
+static GtkWidget *tx_lo_error[BANDS+XVTRS];
 static GtkWidget *disable_pa[BANDS+XVTRS];
 
 static void save_xvtr () {
@@ -50,6 +52,8 @@ static void save_xvtr () {
     const char *maxf;
     const char *lof;
     const char *loerr;
+    const char *txlof;
+    const char *txloerr;
     for(i=BANDS;i<BANDS+XVTRS;i++) {
       BAND *xvtr=band_get_band(i);
       BANDSTACK *bandstack=xvtr->bandstack;
@@ -57,17 +61,21 @@ static void save_xvtr () {
       strcpy(xvtr->title,t);
       if(strlen(t)!=0) {
         minf=gtk_entry_get_text(GTK_ENTRY(min_frequency[i]));
-        xvtr->frequencyMin=atoll(minf)*1000000;
+        xvtr->frequencyMin=(long long)(atof(minf)*1000000.0);
         maxf=gtk_entry_get_text(GTK_ENTRY(max_frequency[i]));
-        xvtr->frequencyMax=atoll(maxf)*1000000;
+        xvtr->frequencyMax=(long long)(atof(maxf)*1000000.0);
         lof=gtk_entry_get_text(GTK_ENTRY(lo_frequency[i]));
-        xvtr->frequencyLO=atoll(lof)*1000000;
+        xvtr->frequencyLO=(long long)(atof(lof)*1000000.0);
         loerr=gtk_entry_get_text(GTK_ENTRY(lo_error[i]));
         xvtr->errorLO=atoll(loerr);
+        txlof=gtk_entry_get_text(GTK_ENTRY(tx_lo_frequency[i]));
+        xvtr->txFrequencyLO=(long long)(atof(txlof)*1000000.0);
+        txloerr=gtk_entry_get_text(GTK_ENTRY(tx_lo_error[i]));
+        xvtr->txErrorLO=atoll(txloerr);
         xvtr->disablePA=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(disable_pa[i]));
         for(b=0;b<bandstack->entries;b++) {
           BANDSTACK_ENTRY *entry=&bandstack->entry[b];
-          entry->frequency=xvtr->frequencyMin;
+          entry->frequency=xvtr->frequencyMin+((xvtr->frequencyMax-xvtr->frequencyMin)/2);
           entry->mode=modeUSB;
           entry->filter=filterF6;
         }
@@ -84,6 +92,96 @@ fprintf(stderr,"min=%s:%lld max=%s:%lld lo=%s:%lld\n",minf,xvtr->frequencyMin,ma
   }
 }
 
+void update_receiver(int band,gboolean error) {
+  int i;
+  RECEIVER *rx=active_receiver;
+  gboolean saved_ctun;
+g_print("update_receiver: band=%d error=%d\n",band,error);
+  if(vfo[0].band==band) {
+    BAND *xvtr=band_get_band(band);
+g_print("update_receiver: found band: %s\n",xvtr->title);
+    vfo[0].lo=xvtr->frequencyLO+xvtr->errorLO;
+    vfo[0].lo_tx=xvtr->txFrequencyLO+xvtr->txErrorLO;
+    saved_ctun=vfo[0].ctun;
+    if(saved_ctun) {
+      vfo[0].ctun=FALSE;
+    }
+    frequency_changed(rx);
+    if(saved_ctun) {
+      vfo[0].ctun=TRUE;
+    }
+
+/*
+    if(radio->transmitter!=NULL) {
+      if(radio->transmitter->rx==rx) {
+        update_tx_panadapter(radio);
+      }
+    }
+*/
+  }
+}
+
+void min_frequency_cb(GtkEditable *editable,gpointer user_data) {
+  int band=GPOINTER_TO_INT(user_data);
+  BAND *xvtr=band_get_band(band);
+  const char* minf=gtk_entry_get_text(GTK_ENTRY(min_frequency[band]));
+  xvtr->frequencyMin=(long long)(atof(minf)*1000000.0);
+  update_receiver(band,FALSE);
+}
+
+void max_frequency_cb(GtkEditable *editable,gpointer user_data) {
+  int band=GPOINTER_TO_INT(user_data);
+  BAND *xvtr=band_get_band(band);
+  const char* maxf=gtk_entry_get_text(GTK_ENTRY(max_frequency[band]));
+  xvtr->frequencyMin=(long long)(atof(maxf)*1000000.0);
+  update_receiver(band,FALSE);
+}
+
+void lo_frequency_cb(GtkEditable *editable,gpointer user_data) {
+  int band=GPOINTER_TO_INT(user_data);
+  BAND *xvtr=band_get_band(band);
+  const char* lof=gtk_entry_get_text(GTK_ENTRY(lo_frequency[band]));
+  xvtr->frequencyLO=(long long)(atof(lof)*1000000.0);
+  update_receiver(band,FALSE);
+}
+
+void lo_error_cb(GtkEditable *editable,gpointer user_data) {
+g_print("lo_error_cb\n");
+  int band=GPOINTER_TO_INT(user_data);
+  BAND *xvtr=band_get_band(band);
+  const char* errorf=gtk_entry_get_text(GTK_ENTRY(lo_error[band]));
+  xvtr->errorLO=atoll(errorf);
+  update_receiver(band,TRUE);
+}
+
+void lo_error_update(RECEIVER *rx,long long offset) {
+g_print("lo_error_update: band=%d\n",vfo[0].band);
+  BAND *xvtr=band_get_band(vfo[0].band);
+  if(dialog!=NULL) {
+    char temp[32];
+    sprintf(temp,"%lld",xvtr->errorLO);
+    gtk_entry_set_text(GTK_ENTRY(lo_error[vfo[0].band]),temp);
+  }
+  xvtr->errorLO=xvtr->errorLO+offset;
+  update_receiver(vfo[0].band,TRUE);
+}
+
+void tx_lo_frequency_cb(GtkEditable *editable,gpointer user_data) {
+  int band=GPOINTER_TO_INT(user_data);
+  BAND *xvtr=band_get_band(band);
+  const char* lof=gtk_entry_get_text(GTK_ENTRY(tx_lo_frequency[band]));
+  xvtr->txFrequencyLO=(long long)(atof(lof)*1000000.0);
+  update_receiver(band,FALSE);
+}
+
+void tx_lo_error_cb(GtkEditable *editable,gpointer user_data) {
+  int band=GPOINTER_TO_INT(user_data);
+  BAND *xvtr=band_get_band(band);
+  const char* errorf=gtk_entry_get_text(GTK_ENTRY(tx_lo_error[band]));
+  xvtr->txErrorLO=atoll(errorf);
+  update_receiver(band,TRUE);
+}
+
 static void cleanup() {
   save_xvtr();
   if(dialog!=NULL) {
@@ -137,16 +235,20 @@ fprintf(stderr,"xvtr_menu\n");
 
   GtkWidget *label=gtk_label_new("Title");
   gtk_grid_attach(GTK_GRID(grid),label,0,1,1,1);
-  label=gtk_label_new("Min Frequency(MHz)");
+  label=gtk_label_new("Min Freq(MHz)");
   gtk_grid_attach(GTK_GRID(grid),label,1,1,1,1);
-  label=gtk_label_new("Max Frequency(MHz)");
+  label=gtk_label_new("Max Freq(MHz)");
   gtk_grid_attach(GTK_GRID(grid),label,2,1,1,1);
-  label=gtk_label_new("LO Frequency(MHz)");
+  label=gtk_label_new("LO Freq(MHz)");
   gtk_grid_attach(GTK_GRID(grid),label,3,1,1,1);
-  label=gtk_label_new("LO Error(Hz)");
+  label=gtk_label_new("LO Err(Hz)");
   gtk_grid_attach(GTK_GRID(grid),label,4,1,1,1);
-  label=gtk_label_new("Disable PA");
+  label=gtk_label_new("TX LO Freq(MHz)");
   gtk_grid_attach(GTK_GRID(grid),label,5,1,1,1);
+  label=gtk_label_new("TX LO Err(Hz)");
+  gtk_grid_attach(GTK_GRID(grid),label,6,1,1,1);
+  label=gtk_label_new("Disable PA");
+  gtk_grid_attach(GTK_GRID(grid),label,7,1,1,1);
 
 
   for(i=BANDS;i<BANDS+XVTRS;i++) {
@@ -159,31 +261,49 @@ fprintf(stderr,"xvtr_menu\n");
 
     min_frequency[i]=gtk_entry_new();
     gtk_entry_set_width_chars(GTK_ENTRY(min_frequency[i]),7);
-    sprintf(f,"%lld",xvtr->frequencyMin/1000000LL);
+    sprintf(f,"%5.3f",(double)xvtr->frequencyMin/1000000.0);
     gtk_entry_set_text(GTK_ENTRY(min_frequency[i]),f);
     gtk_grid_attach(GTK_GRID(grid),min_frequency[i],1,i+2,1,1);
+    g_signal_connect(min_frequency[i],"changed",G_CALLBACK(min_frequency_cb),GINT_TO_POINTER(i));
     
     max_frequency[i]=gtk_entry_new();
     gtk_entry_set_width_chars(GTK_ENTRY(max_frequency[i]),7);
-    sprintf(f,"%lld",xvtr->frequencyMax/1000000LL);
+    sprintf(f,"%5.3f",(double)xvtr->frequencyMax/1000000.0);
     gtk_entry_set_text(GTK_ENTRY(max_frequency[i]),f);
     gtk_grid_attach(GTK_GRID(grid),max_frequency[i],2,i+2,1,1);
+    g_signal_connect(max_frequency[i],"changed",G_CALLBACK(max_frequency_cb),GINT_TO_POINTER(i));
     
     lo_frequency[i]=gtk_entry_new();
     gtk_entry_set_width_chars(GTK_ENTRY(lo_frequency[i]),7);
-    sprintf(f,"%lld",xvtr->frequencyLO/1000000LL);
+    sprintf(f,"%5.3f",(double)xvtr->frequencyLO/1000000.0);
     gtk_entry_set_text(GTK_ENTRY(lo_frequency[i]),f);
     gtk_grid_attach(GTK_GRID(grid),lo_frequency[i],3,i+2,1,1);
+    g_signal_connect(lo_frequency[i],"changed",G_CALLBACK(lo_frequency_cb),GINT_TO_POINTER(i));
 
     lo_error[i]=gtk_entry_new();
     gtk_entry_set_width_chars(GTK_ENTRY(lo_error[i]),9);
     sprintf(f,"%lld",xvtr->errorLO);
     gtk_entry_set_text(GTK_ENTRY(lo_error[i]),f);
     gtk_grid_attach(GTK_GRID(grid),lo_error[i],4,i+2,1,1);
+    g_signal_connect(lo_error[i],"changed",G_CALLBACK(lo_error_cb),GINT_TO_POINTER(i));
+
+    tx_lo_frequency[i]=gtk_entry_new();
+    gtk_entry_set_width_chars(GTK_ENTRY(tx_lo_frequency[i]),7);
+    sprintf(f,"%5.3f",(double)xvtr->txFrequencyLO/1000000.0);
+    gtk_entry_set_text(GTK_ENTRY(tx_lo_frequency[i]),f);
+    gtk_grid_attach(GTK_GRID(grid),tx_lo_frequency[i],5,i+2,1,1);
+    g_signal_connect(tx_lo_frequency[i],"changed",G_CALLBACK(tx_lo_frequency_cb),GINT_TO_POINTER(i));
+
+    tx_lo_error[i]=gtk_entry_new();
+    gtk_entry_set_width_chars(GTK_ENTRY(tx_lo_error[i]),9);
+    sprintf(f,"%lld",xvtr->txErrorLO);
+    gtk_entry_set_text(GTK_ENTRY(tx_lo_error[i]),f);
+    gtk_grid_attach(GTK_GRID(grid),tx_lo_error[i],6,i+2,1,1);
+    g_signal_connect(tx_lo_error[i],"changed",G_CALLBACK(tx_lo_error_cb),GINT_TO_POINTER(i));
 
     disable_pa[i]=gtk_check_button_new();
     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(disable_pa[i]),xvtr->disablePA);
-    gtk_grid_attach(GTK_GRID(grid),disable_pa[i],5,i+2,1,1);
+    gtk_grid_attach(GTK_GRID(grid),disable_pa[i],7,i+2,1,1);
     
   }