]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
v1.2 source update
authorJohn Melton - G0ORX <john.d.melton@googlemail.c>
Sun, 12 Nov 2017 10:16:54 +0000 (10:16 +0000)
committerJohn Melton - G0ORX <john.d.melton@googlemail.c>
Sun, 12 Nov 2017 10:16:54 +0000 (10:16 +0000)
108 files changed:
Makefile
about_menu.c [new file with mode: 0644]
about_menu.h [new file with mode: 0644]
agc_menu.c
ant_menu.c
audio.c
audio_menu.c [deleted file]
audio_waterfall.c [new file with mode: 0644]
audio_waterfall.h [new file with mode: 0644]
band.c
band.h
band_menu.c
band_menu.h
bandstack_menu.c
button_text.c
channel.h
cw_menu.c
discovered.h
discovery.c
discovery.h
display_menu.c
diversity_menu.c
dsp_menu.c
encoder_menu.c
equalizer_menu.c
error_handler.c [new file with mode: 0644]
error_handler.h [new file with mode: 0644]
exit_menu.c
ext.c [new file with mode: 0644]
ext.h [new file with mode: 0644]
fft_menu.c
filter.c
filter_menu.c
fm_menu.c
freedv.c
freedv.h
freedv_menu.c
freqent_menu.c
frequency.c
frequency.h
general_menu.c
gpio.c
gpio.h
gpio_mraa.c
i2c.c
i2c.h
led.c
led.h
main.c
main.h
meter.c
meter.h
meter_menu.c
mode.c
mode.h
mode_menu.c
new_discovery.c
new_menu.c
new_menu.h
new_protocol.c
new_protocol.h
noise_menu.c
oc_menu.c
old_discovery.c
old_protocol.c
old_protocol.h
pa_menu.c
property.c
property.h
ps_menu.c [new file with mode: 0644]
ps_menu.h [new file with mode: 0644]
radio.c
radio.h
radio_menu.c
radio_menu.h
radioberry.c
receiver.c
receiver.h
rigctl.c
rigctl.h
rigctl_menu.c [new file with mode: 0644]
rigctl_menu.h [new file with mode: 0644]
rit.c [deleted file]
rx_menu.c
rx_panadapter.c
signal.c [deleted file]
sliders.c
sliders.h
soundio.c
splash.c [deleted file]
step_menu.c
store_menu.c
test_menu.c
toolbar.c
toolbar.h
transmitter.c
transmitter.h
tx_menu.c
tx_menu.h
tx_panadapter.c
update.c
vfo.c
vfo.h
vfo_menu.c
vox.c
vox_menu.c
waterfall.c
xvtr_menu.c

index 91e27b203e3b0a36b84c773c9bb01679282627aa..2c4197c34f54ed7cd28307912dd9cd8ec0a60407 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -6,6 +6,9 @@ GIT_VERSION := $(shell git describe --abbrev=0 --tags)
 # uncomment the line below to include GPIO
 GPIO_INCLUDE=GPIO
 
+# uncomment the line below to include MCP23017 I2C
+#I2C_INCLUDE=I2C
+
 # uncomment the line below to include USB Ozy support
 # USBOZY_INCLUDE=USBOZY
 
@@ -13,7 +16,10 @@ GPIO_INCLUDE=GPIO
 #PSK_INCLUDE=PSK
 
 # uncomment the line to below include support for FreeDV codec2
-#FREEDV_INCLUDE=FREEDV
+FREEDV_INCLUDE=FREEDV
+
+# uncomment the line below to include Pure Signal support
+#PURESIGNAL_INCLUDE=PURESIGNAL
 
 # uncomment the line to below include support for sx1509 i2c expander
 #SX1509_INCLUDE=sx1509
@@ -21,22 +27,35 @@ GPIO_INCLUDE=GPIO
 # uncomment the line to below include support local CW keyer
 #LOCALCW_INCLUDE=LOCALCW
 
-# uncomment the line below to include MCP23017 I2C
-#I2C_INCLUDE=I2C
-
-#uncomment the line below for the platform being compiled on
-UNAME_N=raspberrypi
-#UNAME_N=odroid
-#UNAME_N=up
-#UNAME_N=pine64
-#UNAME_N=jetsen
-
 CC=gcc
 LINK=gcc
 
 # uncomment the line below for various debug facilities
 #DEBUG_OPTION=-D DEBUG
 
+ifeq ($(PURESIGNAL_INCLUDE),PURESIGNAL)
+PURESIGNAL_OPTIONS=-D PURESIGNAL
+PURESIGNAL_SOURCES= \
+ps_menu.c
+PURESIGNAL_HEADERS= \
+ps_menu.h
+PURESIGNAL_OBJS= \
+ps_menu.o
+endif
+
+ifeq ($(REMOTE_INCLUDE),REMOTE)
+REMOTE_OPTIONS=-D REMOTE
+REMOTE_SOURCES= \
+remote_radio.c \
+remote_receiver.c
+REMOTE_HEADERS= \
+remote_radio.h \
+remote_receiver.h
+REMOTE_OBJS= \
+remote_radio.o \
+remote_receiver.o
+endif
+
 ifeq ($(USBOZY_INCLUDE),USBOZY)
 USBOZY_OPTIONS=-D USBOZY
 USBOZY_LIBS=-lusb-1.0
@@ -152,7 +171,7 @@ GTKLIBS=`pkg-config --libs gtk+-3.0`
 AUDIO_LIBS=-lasound
 #AUDIO_LIBS=-lsoundio
 
-OPTIONS=-g -Wno-deprecated-declarations -D $(UNAME_N) $(RADIOBERRY_OPTIONS) $(USBOZY_OPTIONS) $(I2C_OPTIONS) $(GPIO_OPTIONS) $(LIMESDR_OPTIONS) $(FREEDV_OPTIONS) $(LOCALCW_OPTIONS) $(PSK_OPTIONS) -D GIT_DATE='"$(GIT_DATE)"' -D GIT_VERSION='"$(GIT_VERSION)"' $(DEBUG_OPTION) -O3
+OPTIONS=-g -Wno-deprecated-declarations $(PURESIGNAL_OPTIONS) $(REMOTE_OPTIONS) $(RADIOBERRY_OPTIONS) $(USBOZY_OPTIONS) $(I2C_OPTIONS) $(GPIO_OPTIONS) $(LIMESDR_OPTIONS) $(FREEDV_OPTIONS) $(LOCALCW_OPTIONS) $(PSK_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)
 INCLUDES=$(GTKINCLUDES)
@@ -163,6 +182,7 @@ PROGRAM=pihpsdr
 
 SOURCES= \
 audio.c \
+audio_waterfall.c \
 band.c \
 configure.c \
 frequency.c \
@@ -171,6 +191,7 @@ discovery.c \
 filter.c \
 main.c \
 new_menu.c \
+about_menu.c \
 exit_menu.c \
 radio_menu.c \
 rx_menu.c \
@@ -210,6 +231,7 @@ property.c \
 radio.c \
 receiver.c \
 rigctl.c \
+rigctl_menu.c \
 toolbar.c \
 transmitter.c \
 sliders.c \
@@ -222,11 +244,14 @@ update.c \
 store.c \
 store_menu.c \
 memory.c \
-led.c
+led.c \
+ext.c \
+error_handler.c
 
 
 HEADERS= \
 audio.h \
+audio_waterfall.h \
 agc.h \
 alex.h \
 band.h \
@@ -238,6 +263,7 @@ discovered.h \
 discovery.h \
 filter.h \
 new_menu.h \
+about_menu.h \
 rx_menu.h \
 exit_menu.h \
 radio_menu.h \
@@ -276,6 +302,7 @@ property.h \
 radio.h \
 receiver.h \
 rigctl.h \
+rigctl_menu.h \
 toolbar.h \
 transmitter.h \
 sliders.h \
@@ -288,11 +315,14 @@ update.h \
 store.h \
 store_menu.h \
 memory.h \
-led.h
+led.h \
+ext.h \
+error_handler.h
 
 
 OBJS= \
 audio.o \
+audio_waterfall.o \
 band.o \
 configure.o \
 frequency.o \
@@ -302,6 +332,7 @@ filter.o \
 version.o \
 main.o \
 new_menu.o \
+about_menu.o \
 rx_menu.o \
 exit_menu.o \
 radio_menu.o \
@@ -341,6 +372,7 @@ property.o \
 radio.o \
 receiver.o \
 rigctl.o \
+rigctl_menu.o \
 toolbar.o \
 transmitter.o \
 sliders.o \
@@ -352,15 +384,17 @@ update.o \
 store.o \
 store_menu.o \
 memory.o \
-led.o
+led.o \
+ext.o \
+error_handler.o
 
-all: prebuild  $(PROGRAM) $(HEADERS) $(RADIOBERRY_HEADERS) $(USBOZY_HEADERS) $(LIMESDR_HEADERS) $(FREEDV_HEADERS) $(LOCALCW_HEADERS) $(I2C_HEADERS) $(GPIO_HEADERS) $(PSK_HEADERS) $(SOURCES) $(USBOZY_SOURCES) $(LIMESDR_SOURCES) $(FREEDV_SOURCES) $(I2C_SOURCES) $(GPIO_SOURCES) $(PSK_SOURCES) $(RADIOBERRY_SOURCES)
+all: prebuild  $(PROGRAM) $(HEADERS) $(REMOTE_HEADERS) $(RADIOBERRY_HEADERS) $(USBOZY_HEADERS) $(LIMESDR_HEADERS) $(FREEDV_HEADERS) $(LOCALCW_HEADERS) $(I2C_HEADERS) $(GPIO_HEADERS) $(PSK_HEADERS) $(PURESIGNAL_HEADERS) $(SOURCES) $(REMOTE_SOURCES) $(USBOZY_SOURCES) $(LIMESDR_SOURCES) $(FREEDV_SOURCES) $(I2C_SOURCES) $(GPIO_SOURCES) $(PSK_SOURCES) $(RADIOBERRY_SOURCES) $(PURESIGNAL_SOURCES)
 
 prebuild:
        rm -f version.o
 
-$(PROGRAM):  $(OBJS) $(USBOZY_OBJS) $(LIMESDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(I2C_OBJS) $(GPIO_OBJS) $(PSK_OBJS) $(RADIOBERRY_OBJS)
-       $(LINK) -o $(PROGRAM) $(OBJS) $(USBOZY_OBJS) $(I2C_OBJS) $(GPIO_OBJS) $(LIMESDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(PSK_OBJS) $(LIBS) $(RADIOBERRY_OBJS)
+$(PROGRAM):  $(OBJS) $(REMOTE_OBJS) $(USBOZY_OBJS) $(LIMESDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(I2C_OBJS) $(GPIO_OBJS) $(PSK_OBJS) $(RADIOBERRY_OBJS)  $(PURESIGNAL_OBJS)
+       $(LINK) -o $(PROGRAM) $(OBJS) $(REMOTE_OBJS) $(USBOZY_OBJS) $(I2C_OBJS) $(GPIO_OBJS) $(LIMESDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(PSK_OBJS) $(LIBS) $(RADIOBERRY_OBJS) $(PURESIGNAL_OBJS)
 
 .c.o:
        $(COMPILE) -c -o $@ $<
@@ -371,17 +405,5 @@ clean:
        -rm -f $(PROGRAM)
 
 install:
-       if [ ! -d ~/pihpsdr ];then \
-               mkdir ~/pihpsdr; \
-               if [ -d "./release/pihpsdr" ];then  \
-                       cp ./release/pihpsdr/* ~/pihpsdr; \
-               fi \
-       fi
-       cp pihpsdr ~/pihpsdr
-       if [ -d "./release" ];then  \
-               cp pihpsdr ./release/pihpsdr; \
-               cd release; echo $(GIT_VERSION) > pihpsdr/latest; \
-               cd release; tar cvf pihpsdr_$(GIT_VERSION).tar pihpsdr; \
-               cd release; tar cvf pihpsdr.tar pihpsdr; \
-       fi
+       cp pihpsdr /usr/local/bin
 
diff --git a/about_menu.c b/about_menu.c
new file mode 100644 (file)
index 0000000..4cd0a12
--- /dev/null
@@ -0,0 +1,167 @@
+/* Copyright (C)
+* 2017 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#include <gtk/gtk.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <wdsp.h>
+
+#include "new_menu.h"
+#include "about_menu.h"
+#include "discovered.h"
+#include "radio.h"
+#include "version.h"
+
+static GtkWidget *parent_window=NULL;
+static GtkWidget *dialog=NULL;
+static GtkWidget *label;
+
+static void cleanup() {
+  if(dialog!=NULL) {
+    gtk_widget_destroy(dialog);
+    dialog=NULL;
+    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;
+}
+
+void about_menu(GtkWidget *parent) {
+  int i;
+  char text[2048];
+  char addr[64];
+  char interface_addr[64];
+
+  parent_window=parent;
+
+  dialog=gtk_dialog_new();
+  gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  char title[64];
+  sprintf(title,"piHPSDR - About");
+  gtk_window_set_title(GTK_WINDOW(dialog),title);
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
+
+  GdkRGBA color;
+  color.red = 1.0;
+  color.green = 1.0;
+  color.blue = 1.0;
+  color.alpha = 1.0;
+  gtk_widget_override_background_color(dialog,GTK_STATE_FLAG_NORMAL,&color);
+
+  GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+
+  GtkWidget *grid=gtk_grid_new();
+
+  gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+  //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
+  gtk_grid_set_column_spacing (GTK_GRID(grid),4);
+  //gtk_grid_set_row_spacing (GTK_GRID(grid),4);
+
+  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,row,1,1);
+  row++;
+
+  int lines=0;
+
+  sprintf(text,"piHPSDR by John Melton G0ORX/N6LYT");
+  lines++;
+  sprintf(text,"%s\n\nWith help from:",text);
+  lines++;
+  sprintf(text,"%s\n    Steve Wilson, KA6S, RIGCTL (CAT over TCP)",text);
+  lines++;
+  sprintf(text,"%s\n    Laurence Barker, G8NJJ, USB OZY Support",text);
+  lines++;
+  sprintf(text,"%s\n    Johan Maas, PA3GSB, RadioBerry support",text);
+  lines++;
+  sprintf(text,"%s\n    Ken Hopper, N9VV, Testing and Documentation",text);
+  lines++;
+  lines++;
+
+  sprintf(text,"%s\n\nBuild date: %s", text, build_date);
+  lines++;
+
+  sprintf(text,"%s\nBuild version: %s", text, version);
+  lines++;
+
+  sprintf(text,"%s\n\nWDSP v%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);
+  lines++;
+
+  switch(radio->protocol) {
+    case ORIGINAL_PROTOCOL:
+    case NEW_PROTOCOL:
+#ifdef USBOZY
+      if(d->device==DEVICE_OZY) {
+        sprintf(text,"%s\nDevice OZY: USB /dev/ozy",text,radio->protocol==ORIGINAL_PROTOCOL?"1":"2",radio->software_version/10,radio->software_version%10);
+      } else {
+#endif
+        
+        strcpy(addr,inet_ntoa(radio->info.network.address.sin_addr));
+        strcpy(interface_addr,inet_ntoa(radio->info.network.interface_address.sin_addr));
+        sprintf(text,"%s\nDevice Mac Address: %02X:%02X:%02X:%02X:%02X:%02X",text,
+                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(text,"%s\nDevice IP Address: %s on %s (%s)",text,addr,radio->info.network.interface_name,interface_addr);
+
+#ifdef USBOZY
+      }
+#endif
+      break;
+  }
+  lines++;
+
+#ifdef FREEDV
+  sprintf(text,"%s\n\nIncludes: FREEDV",text);
+  lines++;
+#endif
+
+  label=gtk_label_new(text);
+  gtk_label_set_justify(GTK_LABEL(label),GTK_JUSTIFY_LEFT);
+  gtk_grid_attach(GTK_GRID(grid),label,1,row,4,1);
+  gtk_container_add(GTK_CONTAINER(content),grid);
+
+  sub_menu=dialog;
+
+  gtk_widget_show_all(dialog);
+
+}
diff --git a/about_menu.h b/about_menu.h
new file mode 100644 (file)
index 0000000..5fb30d3
--- /dev/null
@@ -0,0 +1,20 @@
+/* Copyright (C)
+* 2017 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+extern void about_menu(GtkWidget *parent);
index 1f8485c646a36520bae912ab989b66f3058bdf18..f41a5a314165daa5e9b219bf76e3bea248308cf8 100644 (file)
@@ -19,6 +19,8 @@
 
 #include <gtk/gtk.h>
 #include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "new_menu.h"
@@ -35,20 +37,29 @@ static GtkWidget *parent_window=NULL;
 
 static GtkWidget *dialog=NULL;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 gboolean agc_select_cb (GtkWidget *widget, gpointer        data) {
-  active_receiver->agc=(int)data;
+  active_receiver->agc=(uintptr_t)data;
   //wdsp_set_agc(CHANNEL_RX0, agc);
   set_agc(active_receiver, active_receiver->agc);
-  vfo_update(NULL);
+  vfo_update();
 }
 
 void agc_menu(GtkWidget *parent) {
@@ -60,7 +71,11 @@ void agc_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  char title[64];
+  sprintf(title,"piHPSDR - AGC (RX %d VFO %s)",active_receiver->id,active_receiver->id==0?"A":"B");
+  gtk_window_set_title(GTK_WINDOW(dialog),title);
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -78,49 +93,55 @@ void agc_menu(GtkWidget *parent) {
   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 AGC");
+  GtkWidget *close_b=gtk_button_new_with_label("Close");
   g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
   gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
 
-  char label[32];
-  sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B");
-  GtkWidget *rx_label=gtk_label_new(label);
-  gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1);
+  int row=1;
+  int col=0;
 
   GtkWidget *b_off=gtk_radio_button_new_with_label(NULL,"Off");
   //gtk_widget_override_font(b_off, pango_font_description_from_string("Arial 16"));
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_off), active_receiver->agc==AGC_OFF);
   gtk_widget_show(b_off);
-  gtk_grid_attach(GTK_GRID(grid),b_off,0,1,2,1);
-  g_signal_connect(b_off,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_OFF);
+  gtk_grid_attach(GTK_GRID(grid),b_off,col,row,1,1);
+  g_signal_connect(b_off,"pressed",G_CALLBACK(agc_select_cb),(gpointer)(long)AGC_OFF);
+
+  col++;
 
   GtkWidget *b_long=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_off),"Long");
   //gtk_widget_override_font(b_long, pango_font_description_from_string("Arial 16"));
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_long), active_receiver->agc==AGC_LONG);
   gtk_widget_show(b_long);
-  gtk_grid_attach(GTK_GRID(grid),b_long,0,2,2,1);
-  g_signal_connect(b_long,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_LONG);
+  gtk_grid_attach(GTK_GRID(grid),b_long,col,row,1,1);
+  g_signal_connect(b_long,"pressed",G_CALLBACK(agc_select_cb),(gpointer)(long)AGC_LONG);
+
+  col++;
 
   GtkWidget *b_slow=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_long),"Slow");
   //gtk_widget_override_font(b_slow, pango_font_description_from_string("Arial 16"));
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_slow), active_receiver->agc==AGC_SLOW);
   gtk_widget_show(b_slow);
-  gtk_grid_attach(GTK_GRID(grid),b_slow,0,3,2,1);
-  g_signal_connect(b_slow,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_SLOW);
+  gtk_grid_attach(GTK_GRID(grid),b_slow,col,row,1,1);
+  g_signal_connect(b_slow,"pressed",G_CALLBACK(agc_select_cb),(gpointer)(long)AGC_SLOW);
+
+  col++;
 
   GtkWidget *b_medium=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_slow),"Medium");
   //gtk_widget_override_font(b_medium, pango_font_description_from_string("Arial 16"));
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_medium), active_receiver->agc==AGC_MEDIUM);
   gtk_widget_show(b_medium);
-  gtk_grid_attach(GTK_GRID(grid),b_medium,0,4,2,1);
-  g_signal_connect(b_medium,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_MEDIUM);
+  gtk_grid_attach(GTK_GRID(grid),b_medium,col,row,1,1);
+  g_signal_connect(b_medium,"pressed",G_CALLBACK(agc_select_cb),(gpointer)(long)AGC_MEDIUM);
+
+  col++;
 
   GtkWidget *b_fast=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_medium),"Fast");
   //gtk_widget_override_font(b_fast, pango_font_description_from_string("Arial 16"));
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_fast), active_receiver->agc==AGC_FAST);
   gtk_widget_show(b_fast);
-  gtk_grid_attach(GTK_GRID(grid),b_fast,0,5,2,1);
-  g_signal_connect(b_fast,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_FAST);
+  gtk_grid_attach(GTK_GRID(grid),b_fast,col,row,1,1);
+  g_signal_connect(b_fast,"pressed",G_CALLBACK(agc_select_cb),(gpointer)(long)AGC_FAST);
 
   gtk_container_add(GTK_CONTAINER(content),grid);
 
index 9cef50323f84e8b843f7ef1f8aba49864797f338..5641e52a4089873a554589890654fd618f38ad22 100644 (file)
@@ -20,6 +20,8 @@
 #include <gtk/gtk.h>
 #include <semaphore.h>
 #include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "new_menu.h"
 #include "radio.h"
 
 static GtkWidget *parent_window=NULL;
-
 static GtkWidget *menu_b=NULL;
-
 static GtkWidget *dialog=NULL;
+static GtkWidget *grid=NULL;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 rx_ant_cb(GtkWidget *widget, gpointer data) {
-  int b=((int)data)>>4;
-  int ant=((int)data)&0xF;
+  int b=((uintptr_t)data)>>4;
+  int ant=((uintptr_t)data)&0xF;
   BAND *band=band_get_band(b);
   band->alexRxAntenna=ant;
   if(active_receiver->id==0) {
@@ -53,7 +63,7 @@ static void rx_ant_cb(GtkWidget *widget, gpointer data) {
 }
 
 static void rx_lime_ant_cb(GtkWidget *widget, gpointer data) {
-  int ant=((int)data)&0xF;
+  int ant=((uintptr_t)data)&0xF;
   BAND *band=band_get_current_band();
   band->alexRxAntenna=ant;
   if(active_receiver->id==0) {
@@ -62,8 +72,8 @@ static void rx_lime_ant_cb(GtkWidget *widget, gpointer data) {
 }
 
 static void tx_ant_cb(GtkWidget *widget, gpointer data) {
-  int b=((int)data)>>4;
-  int ant=((int)data)&0xF;
+  int b=((uintptr_t)data)>>4;
+  int ant=((uintptr_t)data)&0xF;
   BAND *band=band_get_band(b);
   band->alexTxAntenna=ant;
   if(active_receiver->id==0) {
@@ -71,14 +81,175 @@ static void tx_ant_cb(GtkWidget *widget, gpointer data) {
   }
 }
 
-void ant_menu(GtkWidget *parent) {
+static void show_hf() {
+  int i;
+    for(i=0;i<BANDS;i++) {
+      BAND *band=band_get_band(i);
+      if(strlen(band->title)>0) {
+        GtkWidget *band_label=gtk_label_new(band->title);
+        //gtk_widget_override_font(band_label, pango_font_description_from_string("Arial 18"));
+        gtk_widget_show(band_label);
+        gtk_grid_attach(GTK_GRID(grid),band_label,0,i+2,1,1);
+
+        GtkWidget *rx1_b=gtk_radio_button_new(NULL);
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx1_b), band->alexRxAntenna==0);
+        gtk_widget_show(rx1_b);
+        gtk_grid_attach(GTK_GRID(grid),rx1_b,1,i+2,1,1);
+        g_signal_connect(rx1_b,"pressed",G_CALLBACK(rx_ant_cb),(gpointer)(long)((i<<4)+0));
+
+        GtkWidget *rx2_b=gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(rx1_b));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx2_b), band->alexRxAntenna==1);
+        gtk_widget_show(rx2_b);
+        gtk_grid_attach(GTK_GRID(grid),rx2_b,2,i+2,1,1);
+        g_signal_connect(rx2_b,"pressed",G_CALLBACK(rx_ant_cb),(gpointer)(long)((i<<4)+1));
+
+        GtkWidget *rx3_b=gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(rx2_b));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx3_b), band->alexRxAntenna==2);
+        gtk_widget_show(rx3_b);
+        gtk_grid_attach(GTK_GRID(grid),rx3_b,3,i+2,1,1);
+        g_signal_connect(rx3_b,"pressed",G_CALLBACK(rx_ant_cb),(gpointer)(long)((i<<4)+2));
+
+        GtkWidget *ext1_b=gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(rx3_b));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ext1_b), band->alexRxAntenna==3);
+        gtk_widget_show(ext1_b);
+        gtk_grid_attach(GTK_GRID(grid),ext1_b,4,i+2,1,1);
+        g_signal_connect(ext1_b,"pressed",G_CALLBACK(rx_ant_cb),(gpointer)(long)((i<<4)+3));
+
+        GtkWidget *ext2_b=gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(ext1_b));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ext2_b), band->alexRxAntenna==4);
+        gtk_widget_show(ext2_b);
+        gtk_grid_attach(GTK_GRID(grid),ext2_b,5,i+2,1,1);
+        g_signal_connect(ext2_b,"pressed",G_CALLBACK(rx_ant_cb),(gpointer)(long)((i<<4)+4));
+
+        GtkWidget *xvtr_b=gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(ext2_b));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (xvtr_b), band->alexRxAntenna==5);
+        gtk_widget_show(xvtr_b);
+        gtk_grid_attach(GTK_GRID(grid),xvtr_b,6,i+2,1,1);
+        g_signal_connect(xvtr_b,"pressed",G_CALLBACK(rx_ant_cb),(gpointer)(long)((i<<4)+5));
+
+        GtkWidget *ant_band_label=gtk_label_new(band->title);
+        //gtk_widget_override_font(ant_band_label, pango_font_description_from_string("Arial 18"));
+        gtk_widget_show(ant_band_label);
+        gtk_grid_attach(GTK_GRID(grid),ant_band_label,7,i+2,1,1);
+  
+        GtkWidget *tx1_b=gtk_radio_button_new(NULL);
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tx1_b), band->alexTxAntenna==0);
+        gtk_widget_show(tx1_b);
+        gtk_grid_attach(GTK_GRID(grid),tx1_b,8,i+2,1,1);
+        g_signal_connect(tx1_b,"pressed",G_CALLBACK(tx_ant_cb),(gpointer)(long)((i<<4)+0));
+  
+        GtkWidget *tx2_b=gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(tx1_b));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tx2_b), band->alexTxAntenna==1);
+        gtk_widget_show(tx2_b);
+        gtk_grid_attach(GTK_GRID(grid),tx2_b,9,i+2,1,1);
+        g_signal_connect(tx2_b,"pressed",G_CALLBACK(tx_ant_cb),(gpointer)(long)((i<<4)+1));
+  
+        GtkWidget *tx3_b=gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(tx2_b));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tx3_b), band->alexTxAntenna==2);
+        gtk_widget_show(tx3_b);
+        gtk_grid_attach(GTK_GRID(grid),tx3_b,10,i+2,1,1);
+        g_signal_connect(tx3_b,"pressed",G_CALLBACK(tx_ant_cb),(gpointer)(long)((i<<4)+2));
+      }
+    }
+}
+
+static void show_xvtr() {
+  int i;
+    for(i=0;i<XVTRS;i++) {
+      BAND *band=band_get_band(BANDS+i);
+      if(strlen(band->title)>0) {
+        GtkWidget *band_label=gtk_label_new(band->title);
+        //gtk_widget_override_font(band_label, pango_font_description_from_string("Arial 18"));
+        gtk_widget_show(band_label);
+        gtk_grid_attach(GTK_GRID(grid),band_label,0,i+2,1,1);
+
+        GtkWidget *rx1_b=gtk_radio_button_new(NULL);
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx1_b), band->alexRxAntenna==0);
+        gtk_widget_show(rx1_b);
+        gtk_grid_attach(GTK_GRID(grid),rx1_b,1,i+2,1,1);
+        g_signal_connect(rx1_b,"pressed",G_CALLBACK(rx_ant_cb),(gpointer)(long)(((i+BANDS)<<4)+0));
+
+        GtkWidget *rx2_b=gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(rx1_b));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx2_b), band->alexRxAntenna==1);
+        gtk_widget_show(rx2_b);
+        gtk_grid_attach(GTK_GRID(grid),rx2_b,2,i+2,1,1);
+        g_signal_connect(rx2_b,"pressed",G_CALLBACK(rx_ant_cb),(gpointer)(long)(((i+BANDS)<<4)+1));
+
+        GtkWidget *rx3_b=gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(rx2_b));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx3_b), band->alexRxAntenna==2);
+        gtk_widget_show(rx3_b);
+        gtk_grid_attach(GTK_GRID(grid),rx3_b,3,i+2,1,1);
+        g_signal_connect(rx3_b,"pressed",G_CALLBACK(rx_ant_cb),(gpointer)(long)(((i+BANDS)<<4)+2));
+
+        GtkWidget *ext1_b=gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(rx3_b));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ext1_b), band->alexRxAntenna==3);
+        gtk_widget_show(ext1_b);
+        gtk_grid_attach(GTK_GRID(grid),ext1_b,4,i+2,1,1);
+        g_signal_connect(ext1_b,"pressed",G_CALLBACK(rx_ant_cb),(gpointer)(long)(((i+BANDS)<<4)+3));
+
+        GtkWidget *ext2_b=gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(ext1_b));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ext2_b), band->alexRxAntenna==4);
+        gtk_widget_show(ext2_b);
+        gtk_grid_attach(GTK_GRID(grid),ext2_b,5,i+2,1,1);
+        g_signal_connect(ext2_b,"pressed",G_CALLBACK(rx_ant_cb),(gpointer)(long)(((i+BANDS)<<4)+4));
+
+        GtkWidget *xvtr_b=gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(ext2_b));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (xvtr_b), band->alexRxAntenna==5);
+        gtk_widget_show(xvtr_b);
+        gtk_grid_attach(GTK_GRID(grid),xvtr_b,6,i+2,1,1);
+        g_signal_connect(xvtr_b,"pressed",G_CALLBACK(rx_ant_cb),(gpointer)(long)(((i+BANDS)<<4)+5));
+
+        GtkWidget *ant_band_label=gtk_label_new(band->title);
+        //gtk_widget_override_font(ant_band_label, pango_font_description_from_string("Arial 18"));
+        gtk_widget_show(ant_band_label);
+        gtk_grid_attach(GTK_GRID(grid),ant_band_label,7,i+2,1,1);
+  
+        GtkWidget *tx1_b=gtk_radio_button_new(NULL);
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tx1_b), band->alexTxAntenna==0);
+        gtk_widget_show(tx1_b);
+        gtk_grid_attach(GTK_GRID(grid),tx1_b,8,i+2,1,1);
+        g_signal_connect(tx1_b,"pressed",G_CALLBACK(tx_ant_cb),(gpointer)(long)(((i+BANDS)<<4)+0));
+  
+        GtkWidget *tx2_b=gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(tx1_b));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tx2_b), band->alexTxAntenna==1);
+        gtk_widget_show(tx2_b);
+        gtk_grid_attach(GTK_GRID(grid),tx2_b,9,i+2,1,1);
+        g_signal_connect(tx2_b,"pressed",G_CALLBACK(tx_ant_cb),(gpointer)(long)(((i+BANDS)<<4)+1));
+  
+        GtkWidget *tx3_b=gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(tx2_b));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tx3_b), band->alexTxAntenna==2);
+        gtk_widget_show(tx3_b);
+        gtk_grid_attach(GTK_GRID(grid),tx3_b,10,i+2,1,1);
+        g_signal_connect(tx3_b,"pressed",G_CALLBACK(tx_ant_cb),(gpointer)(long)(((i+BANDS)<<4)+2));
+      }
+    }
+}
+
+static void hf_rb_cb(GtkWidget *widget,GdkEventButton *event, gpointer data) {
   int i;
+  for(i=XVTRS-1;i>=0;i--) {
+    gtk_grid_remove_row (GTK_GRID(grid),i+2);
+  }
+  show_hf();
+}
 
+static void xvtr_rb_cb(GtkWidget *widget,GdkEventButton *event, gpointer data) {
+  int i;
+  for(i=BANDS-1;i>=0;i--) {
+    gtk_grid_remove_row (GTK_GRID(grid),i+2);
+  }
+  show_xvtr();
+}
+
+
+void ant_menu(GtkWidget *parent) {
   parent_window=parent;
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - ANT");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -89,16 +260,26 @@ void ant_menu(GtkWidget *parent) {
 
   GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
 
-  GtkWidget *grid=gtk_grid_new();
+  grid=gtk_grid_new();
   gtk_grid_set_column_spacing (GTK_GRID(grid),10);
   //gtk_grid_set_row_spacing (GTK_GRID(grid),10);
   //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
   //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
 
-  GtkWidget *close_b=gtk_button_new_with_label("Close ANT");
+  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);
 
+  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);
+
+
   if(protocol==ORIGINAL_PROTOCOL || protocol==NEW_PROTOCOL) {
     GtkWidget *rx_ant_label=gtk_label_new("Receive");
     //gtk_widget_override_font(rx_ant_label, pango_font_description_from_string("Arial 18"));
@@ -155,75 +336,7 @@ void ant_menu(GtkWidget *parent) {
     gtk_widget_show(tx3_label);
     gtk_grid_attach(GTK_GRID(grid),tx3_label,10,1,1,1);
 
-    for(i=0;i<BANDS+XVTRS;i++) {
-      BAND *band=band_get_band(i);
-      if(strlen(band->title)>0) {
-
-        GtkWidget *band_label=gtk_label_new(band->title);
-        //gtk_widget_override_font(band_label, pango_font_description_from_string("Arial 18"));
-        gtk_widget_show(band_label);
-        gtk_grid_attach(GTK_GRID(grid),band_label,0,i+2,1,1);
-
-        GtkWidget *rx1_b=gtk_radio_button_new(NULL);
-        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx1_b), band->alexRxAntenna==0);
-        gtk_widget_show(rx1_b);
-        gtk_grid_attach(GTK_GRID(grid),rx1_b,1,i+2,1,1);
-        g_signal_connect(rx1_b,"pressed",G_CALLBACK(rx_ant_cb),(gpointer)((i<<4)+0));
-
-        GtkWidget *rx2_b=gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(rx1_b));
-        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx2_b), band->alexRxAntenna==1);
-        gtk_widget_show(rx2_b);
-        gtk_grid_attach(GTK_GRID(grid),rx2_b,2,i+2,1,1);
-        g_signal_connect(rx2_b,"pressed",G_CALLBACK(rx_ant_cb),(gpointer)((i<<4)+1));
-
-        GtkWidget *rx3_b=gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(rx2_b));
-        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx3_b), band->alexRxAntenna==2);
-        gtk_widget_show(rx3_b);
-        gtk_grid_attach(GTK_GRID(grid),rx3_b,3,i+2,1,1);
-        g_signal_connect(rx3_b,"pressed",G_CALLBACK(rx_ant_cb),(gpointer)((i<<4)+2));
-
-        GtkWidget *ext1_b=gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(rx3_b));
-        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ext1_b), band->alexRxAntenna==3);
-        gtk_widget_show(ext1_b);
-        gtk_grid_attach(GTK_GRID(grid),ext1_b,4,i+2,1,1);
-        g_signal_connect(ext1_b,"pressed",G_CALLBACK(rx_ant_cb),(gpointer)((i<<4)+3));
-
-        GtkWidget *ext2_b=gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(ext1_b));
-        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ext2_b), band->alexRxAntenna==4);
-        gtk_widget_show(ext2_b);
-        gtk_grid_attach(GTK_GRID(grid),ext2_b,5,i+2,1,1);
-        g_signal_connect(ext2_b,"pressed",G_CALLBACK(rx_ant_cb),(gpointer)((i<<4)+4));
-
-        GtkWidget *xvtr_b=gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(ext2_b));
-        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (xvtr_b), band->alexRxAntenna==5);
-        gtk_widget_show(xvtr_b);
-        gtk_grid_attach(GTK_GRID(grid),xvtr_b,6,i+2,1,1);
-        g_signal_connect(xvtr_b,"pressed",G_CALLBACK(rx_ant_cb),(gpointer)((i<<4)+5));
-
-        GtkWidget *ant_band_label=gtk_label_new(band->title);
-        //gtk_widget_override_font(ant_band_label, pango_font_description_from_string("Arial 18"));
-        gtk_widget_show(ant_band_label);
-        gtk_grid_attach(GTK_GRID(grid),ant_band_label,7,i+2,1,1);
-  
-        GtkWidget *tx1_b=gtk_radio_button_new(NULL);
-        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tx1_b), band->alexTxAntenna==0);
-        gtk_widget_show(tx1_b);
-        gtk_grid_attach(GTK_GRID(grid),tx1_b,8,i+2,1,1);
-        g_signal_connect(tx1_b,"pressed",G_CALLBACK(tx_ant_cb),(gpointer)((i<<4)+0));
-  
-        GtkWidget *tx2_b=gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(tx1_b));
-        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tx2_b), band->alexTxAntenna==1);
-        gtk_widget_show(tx2_b);
-        gtk_grid_attach(GTK_GRID(grid),tx2_b,9,i+2,1,1);
-        g_signal_connect(tx2_b,"pressed",G_CALLBACK(tx_ant_cb),(gpointer)((i<<4)+1));
-  
-        GtkWidget *tx3_b=gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(tx2_b));
-        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tx3_b), band->alexTxAntenna==2);
-        gtk_widget_show(tx3_b);
-        gtk_grid_attach(GTK_GRID(grid),tx3_b,10,i+2,1,1);
-        g_signal_connect(tx3_b,"pressed",G_CALLBACK(tx_ant_cb),(gpointer)((i<<4)+2));
-      }
-    }
+    show_hf();
   }
 
 #ifdef LIMESDR
@@ -234,25 +347,25 @@ void ant_menu(GtkWidget *parent) {
     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)0);
+    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)+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)2);
+    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)3);
+    g_signal_connect(rx1_lnaw,"pressed",G_CALLBACK(rx_lime_ant_cb),(gpointer)(long)3);
   }
 #endif
 
diff --git a/audio.c b/audio.c
index 0a0fab659786d589a053399d45ebcb411481fcca..b689bd7c8f00bca32807b9f87414e164a6c4cb23 100644 (file)
--- a/audio.c
+++ b/audio.c
@@ -26,7 +26,6 @@
 #include <string.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <pthread.h>
 #include <sched.h>
 #include <semaphore.h>
 
@@ -68,11 +67,11 @@ static int running=FALSE;
 
 static void *mic_read_thread(void *arg);
 
-char *input_devices[16];
+char *input_devices[32];
 int n_input_devices=0;
 //int n_selected_input_device=-1;
 
-char *output_devices[16];
+char *output_devices[32];
 int n_output_devices=0;
 //int n_selected_output_device=-1;
 
@@ -83,6 +82,7 @@ int audio_open_output(RECEIVER *rx) {
   int dir=0;
 
 
+fprintf(stderr,"audio_open_output: rx=%d audio_device=%d\n",rx->id,rx->audio_device);
   if(rx->audio_device<0 || rx->audio_device>=n_output_devices) {
     rx->audio_device=-1;
     return -1;
@@ -108,28 +108,33 @@ fprintf(stderr,"audio_open_output: selected=%d:%s\n",rx->audio_device,selected);
     return -1;
   }
 
+fprintf(stderr,"audio_open_output: handle=%p\n",rx->playback_handle);
 
   if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
     fprintf (stderr, "audio_open_output: cannot allocate hardware parameter structure (%s)\n",
             snd_strerror (err));
+    audio_close_output(rx);
     return -1;
   }
 
   if ((err = snd_pcm_hw_params_any (rx->playback_handle, hw_params)) < 0) {
     fprintf (stderr, "audio_open_output: cannot initialize hardware parameter structure (%s)\n",
             snd_strerror (err));
+    audio_close_output(rx);
     return -1;
   }
 
   if ((err = snd_pcm_hw_params_set_access (rx->playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
     fprintf (stderr, "audio_open_output: cannot set access type (%s)\n",
             snd_strerror (err));
+    audio_close_output(rx);
     return -1;
 }
        
   if ((err = snd_pcm_hw_params_set_format (rx->playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
     fprintf (stderr, "audio_open_output: cannot set sample format (%s)\n",
             snd_strerror (err));
+    audio_close_output(rx);
     return -1;
   }
        
@@ -137,18 +142,21 @@ fprintf(stderr,"audio_open_output: selected=%d:%s\n",rx->audio_device,selected);
   if ((err = snd_pcm_hw_params_set_rate_near (rx->playback_handle, hw_params, &rate, &dir)) < 0) {
     fprintf (stderr, "audio_open_output: cannot set sample rate (%s)\n",
             snd_strerror (err));
+    audio_close_output(rx);
     return -1;
   }
        
   if ((err = snd_pcm_hw_params_set_channels (rx->playback_handle, hw_params, 2)) < 0) {
     fprintf (stderr, "audio_open_output: cannot set channel count (%s)\n",
             snd_strerror (err));
+    audio_close_output(rx);
     return -1;
   }
        
   if ((err = snd_pcm_hw_params (rx->playback_handle, hw_params)) < 0) {
     fprintf (stderr, "audio_open_output: cannot set parameters (%s)\n",
             snd_strerror (err));
+    audio_close_output(rx);
     return -1;
   }
        
@@ -157,6 +165,7 @@ fprintf(stderr,"audio_open_output: selected=%d:%s\n",rx->audio_device,selected);
   rx->playback_offset=0;
   rx->playback_buffer=(unsigned char *)malloc(OUTPUT_BUFFER_SIZE);
 
+fprintf(stderr,"audio_open_output: rx=%d audio_device=%d handle=%p buffer=%p\n",rx->id,rx->audio_device,rx->playback_handle,rx->playback_buffer);
   return 0;
 }
        
@@ -173,7 +182,7 @@ fprintf(stderr,"audio_open_input: %d\n",transmitter->input_device);
   }
 
   int i;
-  char hw[16];
+  char hw[64];
   char *selected=input_devices[transmitter->input_device];
   fprintf(stderr,"audio_open_input: selected=%d:%s\n",transmitter->input_device,selected);
   
@@ -213,42 +222,49 @@ fprintf(stderr,"audio_open_input: %d\n",transmitter->input_device);
   if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
     fprintf (stderr, "audio_open_input: cannot allocate hardware parameter structure (%s)\n",
             snd_strerror (err));
+    audio_close_input();
     return -1;
   }
 
   if ((err = snd_pcm_hw_params_any (record_handle, hw_params)) < 0) {
     fprintf (stderr, "audio_open_input: cannot initialize hardware parameter structure (%s)\n",
             snd_strerror (err));
+    audio_close_input();
     return -1;
   }
 
   if ((err = snd_pcm_hw_params_set_access (record_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
     fprintf (stderr, "audio_open_input: cannot set access type (%s)\n",
             snd_strerror (err));
+    audio_close_input();
     return -1;
 }
 
   if ((err = snd_pcm_hw_params_set_format (record_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
     fprintf (stderr, "audio_open_input: cannot set sample format (%s)\n",
             snd_strerror (err));
+    audio_close_input();
     return -1;
   }
 
   if ((err = snd_pcm_hw_params_set_rate_near (record_handle, hw_params, &rate, &dir)) < 0) {
     fprintf (stderr, "audio_open_input: cannot set sample rate (%s)\n",
             snd_strerror (err));
+    audio_close_input();
     return -1;
   }
 
   if ((err = snd_pcm_hw_params_set_channels (record_handle, hw_params, 1)) < 0) {
     fprintf (stderr, "audio_open_input: cannot set channel count (%s)\n",
             snd_strerror (err));
+    audio_close_input();
     return -1;
   }
 
   if ((err = snd_pcm_hw_params (record_handle, hw_params)) < 0) {
     fprintf (stderr, "audio_open_input: cannot set parameters (%s)\n",
             snd_strerror (err));
+    audio_close_input();
     return -1;
   }
 
@@ -268,6 +284,7 @@ fprintf(stderr,"audio_open_input: %d\n",transmitter->input_device);
 }
 
 void audio_close_output(RECEIVER *rx) {
+fprintf(stderr,"audio_close_output: rx=%d handle=%p buffer=%p\n",rx->id,rx->playback_handle,rx->playback_buffer);
   if(rx->playback_handle!=NULL) {
     snd_pcm_close (rx->playback_handle);
     rx->playback_handle=NULL;
@@ -332,12 +349,12 @@ int audio_write(RECEIVER *rx,short left_sample,short right_sample) {
   return 0;
 }
 
-static gpointer mic_read_thread(gpointer arg) {
+static void *mic_read_thread(gpointer arg) {
   int rc;
   if ((rc = snd_pcm_prepare (record_handle)) < 0) {
     fprintf (stderr, "mic_read_thread: cannot prepare audio interface for use (%s)\n",
             snd_strerror (rc));
-    return;
+    return NULL;
   }
 fprintf(stderr,"mic_read_thread: mic_buffer_size=%d\n",mic_buffer_size);
   while(running) {
@@ -371,7 +388,7 @@ fprintf(stderr,"mic_read_thread: mic_buffer_size=%d\n",mic_buffer_size);
     }
   }
 fprintf(stderr,"mic_read_thread: exiting\n");
-
+  return NULL;
 }
 
 void audio_get_cards() {
diff --git a/audio_menu.c b/audio_menu.c
deleted file mode 100644 (file)
index 4725411..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-/* Copyright (C)
-* 2015 - John Melton, G0ORX/N6LYT
-*
-* This program is free software; you can redistribute it and/or
-* modify it under the terms of the GNU General Public License
-* as published by the Free Software Foundation; either version 2
-* of the License, or (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software
-* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-*
-*/
-
-#include <gtk/gtk.h>
-#include <semaphore.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "new_menu.h"
-#include "audio_menu.h"
-#include "audio.h"
-#include "channel.h"
-#include "radio.h"
-#include "sliders.h"
-#include "wdsp.h"
-
-static GtkWidget *parent_window=NULL;
-
-static GtkWidget *menu_b=NULL;
-
-static GtkWidget *dialog=NULL;
-
-GtkWidget *linein_b;
-GtkWidget *micboost_b;
-
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
-  if(dialog!=NULL) {
-    gtk_widget_destroy(dialog);
-    dialog=NULL;
-    sub_menu=NULL;
-  }
-  return TRUE;
-}
-
-static void binaural_cb(GtkWidget *widget, gpointer data) {
-  binaural=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
-  SetRXAPanelBinaural(active_receiver->id, binaural);
-}
-
-static void micboost_cb(GtkWidget *widget, gpointer data) {
-  mic_boost=mic_boost==1?0:1;
-}
-
-static void linein_cb(GtkWidget *widget, gpointer data) {
-  mic_linein=mic_linein==1?0:1;
-  g_idle_add(linein_changed,NULL);
-}
-
-static void local_audio_cb(GtkWidget *widget, gpointer data) {
-  if(gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
-    if(audio_open_output()==0) {
-      local_audio=1;
-    } else {
-      local_audio=0;
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
-    }
-  } else {
-    if(local_audio) {
-      local_audio=0;
-      audio_close_output();
-    }
-  }
-}
-
-static void local_output_changed_cb(GtkWidget *widget, gpointer data) {
-  n_selected_output_device=(int)(long)data;
-
-  if(local_audio) {
-    audio_close_output();
-    if(audio_open_output()==0) {
-      local_audio=1;
-    }
-  }
-}
-
-static void local_microphone_cb(GtkWidget *widget, gpointer data) {
-fprintf(stderr,"local_microphone_cb: %d\n",local_microphone);
-  if(gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
-    if(audio_open_input()==0) {
-      local_microphone=1;
-      gtk_widget_hide(linein_b);
-      gtk_widget_hide(micboost_b);
-    } else {
-      local_microphone=0;
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
-      gtk_widget_show(linein_b);
-      gtk_widget_show(micboost_b);
-    }
-  } else {
-    if(local_microphone) {
-      local_microphone=0;
-      audio_close_input();
-      gtk_widget_show(linein_b);
-      gtk_widget_show(micboost_b);
-    }
-  }
-}
-
-static void local_input_changed_cb(GtkWidget *widget, gpointer data) {
-  n_selected_input_device=(int)(long)data;
-fprintf(stderr,"local_input_changed_cb: %d selected=%d\n",local_microphone,n_selected_input_device);
-  if(local_microphone) {
-    audio_close_input();
-    if(audio_open_input()==0) {
-      local_microphone=1;
-    } else {
-      local_microphone=0;
-    }
-  }
-}
-
-void audio_menu(GtkWidget *parent) {
-  int i;
-
-  parent_window=parent;
-
-  dialog=gtk_dialog_new();
-  gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
-
-  GdkRGBA color;
-  color.red = 1.0;
-  color.green = 1.0;
-  color.blue = 1.0;
-  color.alpha = 1.0;
-  gtk_widget_override_background_color(dialog,GTK_STATE_FLAG_NORMAL,&color);
-
-  GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
-
-  GtkWidget *grid=gtk_grid_new();
-  gtk_grid_set_column_spacing (GTK_GRID(grid),10);
-  gtk_grid_set_row_spacing (GTK_GRID(grid),5);
-  //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
-  //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
-
-  GtkWidget *close_b=gtk_button_new_with_label("Close Audio");
-  g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
-  gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
-
-  GtkWidget *binaural_b=gtk_check_button_new_with_label("Binaural");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (binaural_b), binaural);
-  gtk_grid_attach(GTK_GRID(grid),binaural_b,1,0,1,1);
-  g_signal_connect(binaural_b,"toggled",G_CALLBACK(binaural_cb),NULL);
-
-  int row=0;
-
-#ifdef RADIOBERRY
-       if(protocol==ORIGINAL_PROTOCOL || protocol==NEW_PROTOCOL || protocol==RADIOBERRY_PROTOCOL) {
-#else
-        if(protocol==ORIGINAL_PROTOCOL || protocol==NEW_PROTOCOL) {
-#endif  
-    linein_b=gtk_check_button_new_with_label("Mic Line In (ACC connector)");
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (linein_b), mic_linein);
-    gtk_grid_attach(GTK_GRID(grid),linein_b,0,++row,1,1);
-    g_signal_connect(linein_b,"toggled",G_CALLBACK(linein_cb),NULL);
-
-    micboost_b=gtk_check_button_new_with_label("Mic Boost (radio only)");
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (micboost_b), mic_boost);
-    gtk_grid_attach(GTK_GRID(grid),micboost_b,0,++row,1,1);
-    g_signal_connect(micboost_b,"toggled",G_CALLBACK(micboost_cb),NULL);
-
-  }
-
-
-
-  if(n_input_devices>0) {
-    GtkWidget *local_microphone_b=gtk_check_button_new_with_label("Local Microphone Input");
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (local_microphone_b), local_microphone);
-    gtk_widget_show(local_microphone_b);
-    gtk_grid_attach(GTK_GRID(grid),local_microphone_b,0,++row,1,1);
-    g_signal_connect(local_microphone_b,"toggled",G_CALLBACK(local_microphone_cb),NULL);
-
-    if(n_selected_input_device==-1) n_selected_input_device=0;
-
-    for(i=0;i<n_input_devices;i++) {
-      GtkWidget *input;
-      if(i==0) {
-        input=gtk_radio_button_new_with_label(NULL,input_devices[i]);
-      } else {
-        input=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(input),input_devices[i]);
-      }
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (input), n_selected_input_device==i);
-      gtk_widget_show(input);
-      gtk_grid_attach(GTK_GRID(grid),input,0,++row,1,1);
-      g_signal_connect(input,"pressed",G_CALLBACK(local_input_changed_cb),(gpointer *)i);
-    }
-  }
-
-  row=0;
-
-  if(n_output_devices>0) {
-    GtkWidget *local_audio_b=gtk_check_button_new_with_label("Local Audio Output");
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (local_audio_b), local_audio);
-    gtk_widget_show(local_audio_b);
-    gtk_grid_attach(GTK_GRID(grid),local_audio_b,1,++row,1,1);
-    g_signal_connect(local_audio_b,"toggled",G_CALLBACK(local_audio_cb),NULL);
-
-    if(n_selected_output_device==-1) n_selected_output_device=0;
-
-    for(i=0;i<n_output_devices;i++) {
-      GtkWidget *output;
-      if(i==0) {
-        output=gtk_radio_button_new_with_label(NULL,output_devices[i]);
-      } else {
-        output=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(output),output_devices[i]);
-      }
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (output), n_selected_output_device==i);
-      gtk_widget_show(output);
-      gtk_grid_attach(GTK_GRID(grid),output,1,++row,1,1);
-      g_signal_connect(output,"pressed",G_CALLBACK(local_output_changed_cb),(gpointer *)i);
-    }
-  }
-
-  gtk_container_add(GTK_CONTAINER(content),grid);
-
-  sub_menu=dialog;
-
-  gtk_widget_show_all(dialog);
-
-#ifdef RADIOBERRY
-       if(local_microphone && (protocol==ORIGINAL_PROTOCOL || protocol==NEW_PROTOCOL || protocol==RADIOBERRY_PROTOCOL)) {
-#else
-        if(local_microphone && (protocol==ORIGINAL_PROTOCOL || protocol==NEW_PROTOCOL)) {
-#endif
-    gtk_widget_hide(linein_b);
-    gtk_widget_hide(micboost_b);
-  }
-}
-
diff --git a/audio_waterfall.c b/audio_waterfall.c
new file mode 100644 (file)
index 0000000..48ed0b9
--- /dev/null
@@ -0,0 +1,290 @@
+/* Copyright (C)
+* 2017 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <math.h>
+#include <unistd.h>
+#include <semaphore.h>
+#include <string.h>
+
+#include <wdsp.h>
+
+#include "channel.h"
+#include "filter.h"
+#include "radio.h"
+#include "vfo.h"
+#include "audio_waterfall.h"
+#include "receiver.h"
+
+#define min(x,y) (x<y?x:y)
+
+
+static GtkWidget *waterfall;
+static GdkPixbuf *pixbuf = NULL;
+
+float *audio_samples=NULL;
+int audio_samples_index=0;
+
+static int colorLowR=0; // black
+static int colorLowG=0;
+static int colorLowB=0;
+
+static int colorMidR=255; // red
+static int colorMidG=0;
+static int colorMidB=0;
+
+static int colorHighR=255; // yellow
+static int colorHighG=255;
+static int colorHighB=0;
+
+static int sample_rate;
+static gfloat hz_per_pixel;
+static int cursor_frequency=0;
+static int cursor_x=0;
+static int header=20;
+
+// fixed for freedv waterfall?
+static int audio_waterfall_low=30;
+static int audio_waterfall_high=90;
+
+static int display_width;
+static int waterfall_height;
+
+/* Create a new surface of the appropriate size to store our scribbles */
+static gboolean
+waterfall_configure_event_cb (GtkWidget         *widget,
+            GdkEventConfigure *event,
+            gpointer           data)
+{
+  int width=gtk_widget_get_allocated_width (widget);
+  int height=gtk_widget_get_allocated_height (widget);
+fprintf(stderr,"audio: waterfall_configure_event: width=%d height=%d\n",width,height);
+  pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height);
+  char *pixels = gdk_pixbuf_get_pixels (pixbuf);
+
+  memset(pixels, 0, width*height*3);
+
+  if(cursor_frequency!=0) {
+    hz_per_pixel=(double)(sample_rate/2)/(double)display_width;
+    cursor_x=(int)((double)cursor_frequency/hz_per_pixel);
+fprintf(stderr,"audio: waterfall_configure_event: cursor_x=%d hz_per_pizel=%f\n",cursor_x,hz_per_pixel);
+  }
+
+  return TRUE;
+}
+
+/* Redraw the screen from the surface. Note that the ::draw
+ * signal receives a ready-to-be-used cairo_t that is already
+ * clipped to only draw the exposed areas of the widget
+ */
+static gboolean
+waterfall_draw_cb (GtkWidget *widget,
+ cairo_t   *cr,
+ gpointer   data)
+{
+  cairo_text_extents_t extents;
+  char text[16];
+
+//fprintf(stderr,"waterfall_draw_cb\n");
+  gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
+  cairo_paint (cr);
+
+  // draw the sursor
+  if(cursor_x!=0) {
+    cairo_set_source_rgb (cr, 1, 0, 0);
+    sprintf(text,"%d Hz",cursor_frequency);
+    cairo_select_font_face(cr, "FreeMono",
+                            CAIRO_FONT_SLANT_NORMAL,
+                            CAIRO_FONT_WEIGHT_BOLD);
+    cairo_set_font_size(cr, 12);
+    cairo_text_extents(cr, text, &extents);
+    cairo_move_to(cr, (double)cursor_x-(extents.width/2.0), 18.0);
+    cairo_show_text(cr,text);
+    cairo_set_line_width(cr, 1.0);
+    cairo_move_to(cr, cursor_x,  header);
+    cairo_line_to(cr, cursor_x,  waterfall_height);
+    cairo_stroke(cr);
+  }
+
+  cairo_set_source_rgb (cr, 1, 1, 1);
+  cairo_rectangle(cr, 0.0, 0.0, (double)(display_width-1), (double)(waterfall_height-1));
+  cairo_stroke(cr);
+  return TRUE;
+}
+
+void audio_waterfall_update() {
+
+  int i;
+
+  if(pixbuf) {
+    char *pixels = gdk_pixbuf_get_pixels (pixbuf);
+
+    int width=gdk_pixbuf_get_width(pixbuf);
+    int height=gdk_pixbuf_get_height(pixbuf);
+    int rowstride=gdk_pixbuf_get_rowstride(pixbuf);
+    int channels=gdk_pixbuf_get_n_channels(pixbuf);
+
+//fprintf(stderr,"audio_waterfall_update: width=%d height=%d rowsstride=%d channels=%d\n",width,height,rowstride,channels);
+
+    memmove(&pixels[rowstride*(header+1)],&pixels[rowstride*header],(height-(header+1))*rowstride);
+
+    float sample;
+    char *p;
+    int average=0;
+    p=&pixels[rowstride*header];
+    for(i=0;i<width;i++) {
+        sample=audio_samples[i];
+        if(sample<(float)audio_waterfall_low) {
+            *p++=colorLowR;
+            *p++=colorLowG;
+            *p++=colorLowB;
+        } else if(sample>(float)audio_waterfall_high) {
+            *p++=colorHighR;
+            *p++=colorHighG;
+            *p++=colorHighB;
+        } else {
+            float range=(float)audio_waterfall_high-(float)audio_waterfall_low;
+            float offset=sample-(float)audio_waterfall_low;
+            float percent=offset/range;
+            if(percent<(2.0f/9.0f)) {
+                float local_percent = percent / (2.0f/9.0f);
+                *p++ = (int)((1.0f-local_percent)*colorLowR);
+                *p++ = (int)((1.0f-local_percent)*colorLowG);
+                *p++ = (int)(colorLowB + local_percent*(255-colorLowB));
+            } else if(percent<(3.0f/9.0f)) {
+                float local_percent = (percent - 2.0f/9.0f) / (1.0f/9.0f);
+                *p++ = 0;
+                *p++ = (int)(local_percent*255);
+                *p++ = 255;
+            } else if(percent<(4.0f/9.0f)) {
+                 float local_percent = (percent - 3.0f/9.0f) / (1.0f/9.0f);
+                 *p++ = 0;
+                 *p++ = 255;
+                 *p++ = (int)((1.0f-local_percent)*255);
+            } else if(percent<(5.0f/9.0f)) {
+                 float local_percent = (percent - 4.0f/9.0f) / (1.0f/9.0f);
+                 *p++ = (int)(local_percent*255);
+                 *p++ = 255;
+                 *p++ = 0;
+            } else if(percent<(7.0f/9.0f)) {
+                 float local_percent = (percent - 5.0f/9.0f) / (2.0f/9.0f);
+                 *p++ = 255;
+                 *p++ = (int)((1.0f-local_percent)*255);
+                 *p++ = 0;
+            } else if(percent<(8.0f/9.0f)) {
+                 float local_percent = (percent - 7.0f/9.0f) / (1.0f/9.0f);
+                 *p++ = 255;
+                 *p++ = 0;
+                 *p++ = (int)(local_percent*255);
+            } else {
+                 float local_percent = (percent - 8.0f/9.0f) / (1.0f/9.0f);
+                 *p++ = (int)((0.75f + 0.25f*(1.0f-local_percent))*255.0f);
+                 *p++ = (int)(local_percent*255.0f*0.5f);
+                 *p++ = 255;
+            }
+        }
+        average+=(int)sample;
+        audio_waterfall_low=(average/width)+10;
+        audio_waterfall_high=audio_waterfall_low+50;
+    }
+    gtk_widget_queue_draw (waterfall);
+  }
+}
+
+void audio_waterfall_setup(int rate,int cursor) {
+  sample_rate=rate;
+  cursor_frequency=cursor;
+  hz_per_pixel=(double)(sample_rate/2)/(double)display_width;
+  cursor_x=(int)((double)cursor/hz_per_pixel);
+fprintf(stderr,"audio_waterfall_setup: sample_rate=%d cursor=%d width=%d hz_per_pixel=%f\n",sample_rate,cursor,display_width,hz_per_pixel);
+}
+
+
+static void initAnalyzer(RECEIVER *rx,int channel, int buffer_size, int pixels) {
+    int flp[] = {0};
+    double keep_time = 0.1;
+    int n_pixout=1;
+    int spur_elimination_ffts = 1;
+    int data_type = 0;
+    int fft_size = 1024;
+    int window_type = 4;
+    double kaiser_pi = 14.0;
+    int overlap = 0;
+    int clip = 0;
+    int span_clip_l = 0;
+    int span_clip_h = 0;
+    int stitches = 1;
+    int calibration_data_set = 0;
+    double span_min_freq = 0.0;
+    double span_max_freq = 0.0;
+
+    int max_w = fft_size + (int) min(keep_time * (double) rx->fps, keep_time * (double) fft_size * (double) rx->fps);
+
+    SetAnalyzer(channel,
+            n_pixout,
+            spur_elimination_ffts, //number of LO frequencies = number of ffts used in elimination
+            data_type, //0 for real input data (I only); 1 for complex input data (I & Q)
+            flp, //vector with one elt for each LO frequency, 1 if high-side LO, 0 otherwise
+            fft_size, //size of the fft, i.e., number of input samples
+            buffer_size, //number of samples transferred for each OpenBuffer()/CloseBuffer()
+            window_type, //integer specifying which window function to use
+            kaiser_pi, //PiAlpha parameter for Kaiser window
+            overlap, //number of samples each fft (other than the first) is to re-use from the previous
+            clip, //number of fft output bins to be clipped from EACH side of each sub-span
+            span_clip_l, //number of bins to clip from low end of entire span
+            span_clip_h, //number of bins to clip from high end of entire span
+            pixels, //number of pixel values to return.  may be either <= or > number of bins
+            stitches, //number of sub-spans to concatenate to form a complete span
+            calibration_data_set, //identifier of which set of calibration data to use
+            span_min_freq, //frequency at first pixel value8192
+            span_max_freq, //frequency at last pixel value
+            max_w //max samples to hold in input ring buffers
+    );
+
+}
+
+GtkWidget* audio_waterfall_init(int width,int height) {
+  int success;
+
+fprintf(stderr,"audio_waterfall_init: width=%d height=%d\n",width,height);
+  display_width=width;
+  waterfall_height=height;
+
+  audio_samples=(float *)malloc(sizeof(float)*width);
+
+  //waterfall_frame = gtk_frame_new (NULL);
+  waterfall = gtk_drawing_area_new ();
+  gtk_widget_set_size_request (waterfall, width, height);
+
+  /* Signals used to handle the backing surface */
+  g_signal_connect (waterfall, "draw",
+            G_CALLBACK (waterfall_draw_cb), NULL);
+  g_signal_connect (waterfall,"configure-event",
+            G_CALLBACK (waterfall_configure_event_cb), NULL);
+
+  XCreateAnalyzer(CHANNEL_AUDIO, &success, 262144, 1, 1, "");
+  if (success != 0) {
+    fprintf(stderr, "XCreateAnalyzer CHANNEL_AUDIO failed: %d\n" ,success);
+  }
+  initAnalyzer(active_receiver,CHANNEL_AUDIO,AUDIO_WATERFALL_SAMPLES,width);
+
+  return waterfall;
+}
diff --git a/audio_waterfall.h b/audio_waterfall.h
new file mode 100644 (file)
index 0000000..75388e2
--- /dev/null
@@ -0,0 +1,33 @@
+/* Copyright (C)
+* 2017 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#ifndef _FREEDV_WATERFALL_H
+#define _FREEDV_WATERFALL_H
+
+#define AUDIO_WATERFALL_SAMPLES 256
+
+extern float *audio_samples;
+extern int audio_samples_index;
+
+extern void audio_waterfall_update();
+extern GtkWidget* audio_waterfall_init(int width,int height);
+extern void audio_waterfall_setup(int sample_rate,int cursor);
+
+#endif
+
diff --git a/band.c b/band.c
index c3fa969d04e009d873e7cfdc4913180b63217876..cb058df7c9a2d6df8262d5245c7f912099aaa936 100644 (file)
--- a/band.c
+++ b/band.c
@@ -56,12 +56,25 @@ BANDSTACK_ENTRY bandstack_entries80[] =
      {3751000LL,modeLSB,filterF5,-2800,-200,-2800,-200},
      {3850000LL,modeLSB,filterF5,-2800,-200,-2800,-200}};
 
-BANDSTACK_ENTRY bandstack_entries60[] =
-    {{5330500LL,modeUSB,filterF5,-2800,-200,-2800,-200},
-     {5346500LL,modeUSB,filterF5,-2800,-200,-2800,-200},
-     {5366500LL,modeUSB,filterF5,-2800,-200,-2800,-200},
-     {5371500LL,modeUSB,filterF5,-2800,-200,-2800,-200},
-     {5403500LL,modeUSB,filterF5,-2800,-200,-2800,-200}};
+BANDSTACK_ENTRY bandstack_entries60_OTHER[] =
+    {{5332000LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+     {5348000LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+     {5358500LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+     {5373000LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+     {5405000LL,modeUSB,filterF5,-2800,-200,-2800,-200}};
+
+BANDSTACK_ENTRY bandstack_entries60_UK[] =
+    {{5261250LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+     {5280000LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+     {5290250LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+     {5302500LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+     {5318000LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+     {5335500LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+     {5356000LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+     {5368250LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+     {5380000LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+     {5398250LL,modeUSB,filterF5,-2800,-200,-2800,-200},
+     {5405000LL,modeUSB,filterF5,-2800,-200,-2800,-200}};
 
 BANDSTACK_ENTRY bandstack_entries40[] =
     {{7001000LL,modeCWL,filterF6,-2800,-200,-2800,-200},
@@ -79,7 +92,7 @@ BANDSTACK_ENTRY bandstack_entries20[] =
      {14230000LL,modeUSB,filterF5,200,2800,200,2800},
      {14336000LL,modeUSB,filterF5,200,2800,200,2800}};
 
-BANDSTACK_ENTRY bandstack_entries18[] =
+BANDSTACK_ENTRY bandstack_entries17[] =
     {{18068600LL,modeCWU,filterF6,200,2800,200,2800},
      {18125000LL,modeUSB,filterF5,200,2800,200,2800},
      {18140000LL,modeUSB,filterF5,200,2800,200,2800}};
@@ -99,7 +112,7 @@ BANDSTACK_ENTRY bandstack_entries10[] =
      {28300000LL,modeUSB,filterF5,200,2800,200,2800},
      {28400000LL,modeUSB,filterF5,200,2800,200,2800}};
 
-BANDSTACK_ENTRY bandstack_entries50[] =
+BANDSTACK_ENTRY bandstack_entries6[] =
     {{50010000LL,modeCWU,filterF6,200,2800,200,2800},
      {50125000LL,modeUSB,filterF5,200,2800,200,2800},
      {50200000LL,modeUSB,filterF5,200,2800,200,2800}};
@@ -171,15 +184,15 @@ BANDSTACK_ENTRY bandstack_entriesWWV[] =
 
 BANDSTACK bandstack160={3,1,bandstack_entries160};
 BANDSTACK bandstack80={3,1,bandstack_entries80};
-BANDSTACK bandstack60={5,1,bandstack_entries60};
+BANDSTACK bandstack60={5,1,bandstack_entries60_OTHER};
 BANDSTACK bandstack40={3,1,bandstack_entries40};
 BANDSTACK bandstack30={3,1,bandstack_entries30};
 BANDSTACK bandstack20={4,1,bandstack_entries20};
-BANDSTACK bandstack18={3,1,bandstack_entries18};
+BANDSTACK bandstack17={3,1,bandstack_entries17};
 BANDSTACK bandstack15={3,1,bandstack_entries15};
 BANDSTACK bandstack12={3,1,bandstack_entries12};
 BANDSTACK bandstack10={3,1,bandstack_entries10};
-BANDSTACK bandstack50={3,1,bandstack_entries50};
+BANDSTACK bandstack6={3,1,bandstack_entries6};
 #ifdef LIMESDR
 BANDSTACK bandstack70={3,1,bandstack_entries70};
 BANDSTACK bandstack144={6,1,bandstack_entries144};
@@ -203,71 +216,109 @@ BANDSTACK bandstack472={2,0,bandstack_entries472};
 /* ----------------------------------------------------------------------------*/
 
 BANDSTACK_ENTRY bandstack_entries_xvtr_0[] =
-    {{0LL,modeUSB,filterF6,150,2550,150,2550}};
+    {{0LL,modeUSB,filterF6,150,2550,150,2550},
+     {0LL,modeUSB,filterF6,150,2550,150,2550},
+     {0LL,modeUSB,filterF6,150,2550,150,2550}};
 BANDSTACK_ENTRY bandstack_entries_xvtr_1[] =
-    {{0LL,modeUSB,filterF6,150,2550,150,2550}};
+    {{0LL,modeUSB,filterF6,150,2550,150,2550},
+     {0LL,modeUSB,filterF6,150,2550,150,2550},
+     {0LL,modeUSB,filterF6,150,2550,150,2550}};
 BANDSTACK_ENTRY bandstack_entries_xvtr_2[] =
-    {{0LL,modeUSB,filterF6,150,2550,150,2550}};
+    {{0LL,modeUSB,filterF6,150,2550,150,2550},
+     {0LL,modeUSB,filterF6,150,2550,150,2550},
+     {0LL,modeUSB,filterF6,150,2550,150,2550}};
 BANDSTACK_ENTRY bandstack_entries_xvtr_3[] =
-    {{0LL,modeUSB,filterF6,150,2550,150,2550}};
+    {{0LL,modeUSB,filterF6,150,2550,150,2550},
+     {0LL,modeUSB,filterF6,150,2550,150,2550},
+     {0LL,modeUSB,filterF6,150,2550,150,2550}};
 BANDSTACK_ENTRY bandstack_entries_xvtr_4[] =
-    {{0LL,modeUSB,filterF6,150,2550,150,2550}};
+    {{0LL,modeUSB,filterF6,150,2550,150,2550},
+     {0LL,modeUSB,filterF6,150,2550,150,2550},
+     {0LL,modeUSB,filterF6,150,2550,150,2550}};
 BANDSTACK_ENTRY bandstack_entries_xvtr_5[] =
-    {{0LL,modeUSB,filterF6,150,2550,150,2550}};
+    {{0LL,modeUSB,filterF6,150,2550,150,2550},
+     {0LL,modeUSB,filterF6,150,2550,150,2550},
+     {0LL,modeUSB,filterF6,150,2550,150,2550}};
 BANDSTACK_ENTRY bandstack_entries_xvtr_6[] =
-    {{0LL,modeUSB,filterF6,150,2550,150,2550}};
+    {{0LL,modeUSB,filterF6,150,2550,150,2550},
+     {0LL,modeUSB,filterF6,150,2550,150,2550},
+     {0LL,modeUSB,filterF6,150,2550,150,2550}};
 BANDSTACK_ENTRY bandstack_entries_xvtr_7[] =
-    {{0LL,modeUSB,filterF6,150,2550,150,2550}};
+    {{0LL,modeUSB,filterF6,150,2550,150,2550},
+     {0LL,modeUSB,filterF6,150,2550,150,2550},
+     {0LL,modeUSB,filterF6,150,2550,150,2550}};
 
-BANDSTACK bandstack_xvtr_0={1,0,bandstack_entries_xvtr_0};
-BANDSTACK bandstack_xvtr_1={1,0,bandstack_entries_xvtr_1};
-BANDSTACK bandstack_xvtr_2={1,0,bandstack_entries_xvtr_2};
-BANDSTACK bandstack_xvtr_3={1,0,bandstack_entries_xvtr_3};
-BANDSTACK bandstack_xvtr_4={1,0,bandstack_entries_xvtr_4};
-BANDSTACK bandstack_xvtr_5={1,0,bandstack_entries_xvtr_5};
-BANDSTACK bandstack_xvtr_6={1,0,bandstack_entries_xvtr_6};
-BANDSTACK bandstack_xvtr_7={1,0,bandstack_entries_xvtr_7};
+BANDSTACK bandstack_xvtr_0={3,0,bandstack_entries_xvtr_0};
+BANDSTACK bandstack_xvtr_1={3,0,bandstack_entries_xvtr_1};
+BANDSTACK bandstack_xvtr_2={3,0,bandstack_entries_xvtr_2};
+BANDSTACK bandstack_xvtr_3={3,0,bandstack_entries_xvtr_3};
+BANDSTACK bandstack_xvtr_4={3,0,bandstack_entries_xvtr_4};
+BANDSTACK bandstack_xvtr_5={3,0,bandstack_entries_xvtr_5};
+BANDSTACK bandstack_xvtr_6={3,0,bandstack_entries_xvtr_6};
+BANDSTACK bandstack_xvtr_7={3,0,bandstack_entries_xvtr_7};
 
 
 
 BAND bands[BANDS+XVTRS] = 
-    {{"160",&bandstack160,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,1800000LL,2000000LL,0LL,0},
-     {"80",&bandstack80,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,3500000LL,4000000LL,0LL,0},
-     {"60",&bandstack60,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,5330500LL,5403500LL,0LL,0},
-     {"40",&bandstack40,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,7000000LL,7300000LL,0LL,0},
-     {"30",&bandstack30,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,10100000LL,10150000LL,0LL,0},
-     {"20",&bandstack20,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,14000000LL,14350000LL,0LL,0},
-     {"18",&bandstack18,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,18068000LL,18168000LL,0LL,0},
-     {"15",&bandstack15,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,21000000LL,21450000LL,0LL,0},
-     {"12",&bandstack12,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,24890000LL,24990000LL,0LL,0},
-     {"10",&bandstack10,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,28000000LL,29700000LL,0LL,0},
-     {"50",&bandstack50,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,50000000LL,54000000LL,0LL,0},
+    {{"160",&bandstack160,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,1800000LL,2000000LL,0LL,0LL,0},
+     {"80",&bandstack80,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,3500000LL,4000000LL,0LL,0LL,0},
+     {"60",&bandstack60,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,5330500LL,5403500LL,0LL,0LL,0},
+     {"40",&bandstack40,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,7000000LL,7300000LL,0LL,0LL,0},
+     {"30",&bandstack30,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,10100000LL,10150000LL,0LL,0LL,0},
+     {"20",&bandstack20,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,14000000LL,14350000LL,0LL,0LL,0},
+     {"17",&bandstack17,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,18068000LL,18168000LL,0LL,0LL,0},
+     {"15",&bandstack15,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,21000000LL,21450000LL,0LL,0LL,0},
+     {"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
-     {"70",&bandstack70,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0},
-     {"144",&bandstack144,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,144000000LL,148000000LL,0LL,0},
-     {"220",&bandstack144,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,222000000LL,224980000LL,0LL,0},
-     {"430",&bandstack430,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,420000000LL,450000000LL,0LL,0},
-     {"902",&bandstack430,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,902000000LL,928000000LL,0LL,0},
-     {"1240",&bandstack1240,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,1240000000LL,1300000000LL,0LL,0},
-     {"2300",&bandstack2300,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,2300000000LL,2450000000LL,0LL,0},
-     {"3400",&bandstack3400,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,3400000000LL,3410000000LL,0LL,0},
-     {"AIR",&bandstackAIR,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0},
+     {"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},
+     {"430",&bandstack430,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,420000000LL,450000000LL,0LL,0LL,0},
+     {"902",&bandstack430,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,902000000LL,928000000LL,0LL,0LL,0},
+     {"1240",&bandstack1240,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,1240000000LL,1300000000LL,0LL,0LL,0},
+     {"2300",&bandstack2300,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,2300000000LL,2450000000LL,0LL,0LL,0},
+     {"3400",&bandstack3400,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,3400000000LL,3410000000LL,0LL,0LL,0},
+     {"AIR",&bandstackAIR,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0LL,0},
 #endif
-     {"GEN",&bandstackGEN,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0},
-     {"WWV",&bandstackWWV,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0},
-     {"136kHz",&bandstack136,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,135700LL,137800LL,0LL,0},
-     {"472kHz",&bandstack472,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,472000LL,479000LL,0LL,0},
+     {"GEN",&bandstackGEN,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0LL,0},
+     {"WWV",&bandstackWWV,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0LL,0},
+     {"136kHz",&bandstack136,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,135700LL,137800LL,0LL,0LL,0},
+     {"472kHz",&bandstack472,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,472000LL,479000LL,0LL,0LL,0},
 // XVTRS
-     {"",&bandstack_xvtr_0,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0},
-     {"",&bandstack_xvtr_1,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0},
-     {"",&bandstack_xvtr_2,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0},
-     {"",&bandstack_xvtr_3,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0},
-     {"",&bandstack_xvtr_4,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0},
-     {"",&bandstack_xvtr_5,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0},
-     {"",&bandstack_xvtr_6,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0},
-     {"",&bandstack_xvtr_7,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0}
+     {"",&bandstack_xvtr_0,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0LL,0},
+     {"",&bandstack_xvtr_1,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0LL,0},
+     {"",&bandstack_xvtr_2,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0LL,0},
+     {"",&bandstack_xvtr_3,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0LL,0},
+     {"",&bandstack_xvtr_4,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0LL,0},
+     {"",&bandstack_xvtr_5,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0LL,0},
+     {"",&bandstack_xvtr_6,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0LL,0},
+     {"",&bandstack_xvtr_7,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0LL,0}
     };
 
+CHANNEL band_channels_60m_UK[UK_CHANNEL_ENTRIES] =
+     {{5261250LL,5500LL},
+      {5280000LL,8000LL},
+      {5290250LL,3500LL},
+      {5302500LL,9000LL},
+      {5318000LL,10000LL},
+      {5335500LL,5000LL},
+      {5356000LL,4000LL},
+      {5368250LL,12500LL},
+      {5380000LL,4000LL},
+      {5398250LL,6500LL},
+      {5405000LL,3000LL}};
+
+CHANNEL band_channels_60m_OTHER[OTHER_CHANNEL_ENTRIES] =
+     {{5332000LL,2800LL},
+      {5348000LL,2800LL},
+      {5358500LL,2800LL},
+      {5373000LL,2800LL},
+      {5405000LL,2800LL}};
+
+int channel_entries;
+CHANNEL *band_channels_60m;
 
 BANDSTACK *bandstack_get_bandstack(int band) {
     return bands[band].bandstack;
@@ -386,6 +437,10 @@ void bandSaveState() {
         sprintf(name,"band.%d.frequencyLO",b);
         setProperty(name,value);
 
+        sprintf(value,"%lld",bands[b].errorLO);
+        sprintf(name,"band.%d.errorLO",b);
+        setProperty(name,value);
+
         sprintf(value,"%d",bands[b].disablePA);
         sprintf(name,"band.%d.disablePA",b);
         setProperty(name,value);
@@ -438,8 +493,6 @@ void bandRestoreState() {
     BANDSTACK_ENTRY* entry;
     int current;
 
-fprintf(stderr,"bandRestoreState: restore bands\n");
-
     for(b=0;b<BANDS+XVTRS;b++) {
         sprintf(name,"band.%d.title",b);
         value=getProperty(name);
@@ -501,6 +554,10 @@ fprintf(stderr,"bandRestoreState: restore bands\n");
         value=getProperty(name);
         if(value) bands[b].frequencyLO=atoll(value);
 
+        sprintf(name,"band.%d.errorLO",b);
+        value=getProperty(name);
+        if(value) bands[b].errorLO=atoll(value);
+
         sprintf(name,"band.%d.disablePA",b);
         value=getProperty(name);
         if(value) bands[b].disablePA=atoi(value);
diff --git a/band.h b/band.h
index 36532946560449839a128ec011ef9ff96f9280d2..7f46c581b483ada1f6bcab6983640cec0748e1cc 100644 (file)
--- a/band.h
+++ b/band.h
@@ -75,14 +75,37 @@ struct _BAND {
     long long frequencyMin;
     long long frequencyMax;
     long long frequencyLO;
+    long long errorLO;
     int disablePA;
 };
 
 typedef struct _BAND BAND;
 
+struct _CHANNEL {
+    long long frequency;
+    long long width;
+};
+
+typedef struct _CHANNEL CHANNEL;
+
+
+
 int band;
 gboolean displayHF;
 
+#define UK_CHANNEL_ENTRIES 11
+#define OTHER_CHANNEL_ENTRIES 5
+
+extern int channel_entries;
+extern CHANNEL *band_channels_60m;
+
+extern CHANNEL band_channels_60m_UK[UK_CHANNEL_ENTRIES];
+extern CHANNEL band_channels_60m_OTHER[OTHER_CHANNEL_ENTRIES];
+
+extern BANDSTACK bandstack60;
+extern BANDSTACK_ENTRY bandstack_entries60_OTHER[];
+extern BANDSTACK_ENTRY bandstack_entries60_UK[];
+
 extern int band_get_current();
 extern BAND *band_get_current_band();
 extern BAND *band_get_band(int b);
@@ -96,4 +119,7 @@ extern BANDSTACK_ENTRY *bandstack_entry_next();
 extern BANDSTACK_ENTRY *bandstack_entry_previous();
 extern BANDSTACK_ENTRY *bandstack_entry_get_current();
 
+extern void bandSaveState();
+extern void bandRestoreState();
+
 #endif
index d55ceff8ae5f5a2599e6012d78ccdfe4800b44a5..ff020c2bea60cef4dcdf25e7bfad0fb853fec841 100644 (file)
@@ -19,6 +19,8 @@
 
 #include <gtk/gtk.h>
 #include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "new_menu.h"
@@ -37,30 +39,33 @@ static GtkWidget *dialog=NULL;
 
 static GtkWidget *last_band;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     sub_menu=NULL;
   }
+}
+
+static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  cleanup();
   return TRUE;
 }
 
-static gboolean band_select_cb (GtkWidget *widget, gpointer        data) {
+static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
+  cleanup();
+  return FALSE;
+}
+
+gboolean band_select_cb (GtkWidget *widget, gpointer        data) {
   GtkWidget *label;
-  int b=(int)data;
+  int b=(uintptr_t)data;
   set_button_text_color(last_band,"black");
   last_band=widget;
   set_button_text_color(last_band,"orange");
-
   vfo_band_changed(b);
 }
 
-int band_update(void *data) {
-  band_select_cb(NULL,(gpointer)data);
-  return 0;
-}
-
 void band_menu(GtkWidget *parent) {
   GtkWidget *b;
   int i;
@@ -70,7 +75,11 @@ void band_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  char title[64];
+  sprintf(title,"piHPSDR - Band (RX %d VFO %s)",active_receiver->id,active_receiver->id==0?"A":"B");
+  gtk_window_set_title(GTK_WINDOW(dialog),title);
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -88,15 +97,10 @@ void band_menu(GtkWidget *parent) {
   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 Band");
+  GtkWidget *close_b=gtk_button_new_with_label("Close");
   g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
   gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
 
-  char label[32];
-  sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B");
-  GtkWidget *rx_label=gtk_label_new(label);
-  gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1);
-
   for(i=0;i<BANDS+XVTRS;i++) {
 #ifdef LIMESDR
     if(protocol!=LIMESDR_PROTOCOL) {
@@ -117,7 +121,7 @@ void band_menu(GtkWidget *parent) {
       }
       gtk_widget_show(b);
       gtk_grid_attach(GTK_GRID(grid),b,i%5,1+(i/5),1,1);
-      g_signal_connect(b,"clicked",G_CALLBACK(band_select_cb),(gpointer *)i);
+      g_signal_connect(b,"clicked",G_CALLBACK(band_select_cb),(gpointer)(long)i);
     }
   }
 
index f77fc1a421985f50de9dfe946df6c44369dd5ed8..b9019aff8ca18fb3c5be58a21885af5796270306 100644 (file)
@@ -17,5 +17,6 @@
 *
 */
 
-void band_menu(GtkWidget *parent);
-int band_update(void *data);
+extern void band_menu(GtkWidget *parent);
+extern gboolean band_select_cb (GtkWidget *widget, gpointer        data);
+
index 001ea453c47f8124e9d305ee29df251b11c8bd84..d5a1b4f3909b09d212442708d2e3e0d657633cdb 100644 (file)
@@ -19,6 +19,8 @@
 
 #include <gtk/gtk.h>
 #include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "new_menu.h"
@@ -37,17 +39,26 @@ static GtkWidget *dialog=NULL;
 
 static GtkWidget *last_bandstack;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 gboolean bandstack_select_cb (GtkWidget *widget, gpointer        data) {
-  int b=(int)data;
+  int b=(uintptr_t)data;
   set_button_text_color(last_bandstack,"black");
   last_bandstack=widget;
   set_button_text_color(last_bandstack,"orange");
@@ -62,7 +73,11 @@ void bandstack_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  char title[64];
+  sprintf(title,"piHPSDR - Band Stack (RX %d VFO %s)",active_receiver->id,active_receiver->id==0?"A":"B");
+  gtk_window_set_title(GTK_WINDOW(dialog),title);
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -80,18 +95,16 @@ void bandstack_menu(GtkWidget *parent) {
   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 Band Stack");
+  GtkWidget *close_b=gtk_button_new_with_label("Close");
   g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
   gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
 
-  char label[32];
-  sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B");
-  GtkWidget *rx_label=gtk_label_new(label);
-  gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1);
-
   BAND *band=band_get_band(vfo[active_receiver->id].band);
   BANDSTACK *bandstack=band->bandstack;
 
+  char label[32];
+  int row=1;
+  int col=0;
   for(i=0;i<bandstack->entries;i++) {
     BANDSTACK_ENTRY *entry=&bandstack->entry[i];
     sprintf(label,"%lld %s",entry->frequency,mode_string[entry->mode]);
@@ -103,8 +116,13 @@ void bandstack_menu(GtkWidget *parent) {
       last_bandstack=b;
     }
     gtk_widget_show(b);
-    gtk_grid_attach(GTK_GRID(grid),b,i/5,1+(i%5),1,1);
-    g_signal_connect(b,"clicked",G_CALLBACK(bandstack_select_cb),(gpointer *)i);
+    gtk_grid_attach(GTK_GRID(grid),b,col,row,1,1);
+    g_signal_connect(b,"clicked",G_CALLBACK(bandstack_select_cb),(gpointer)(long)i);
+    col++;
+    if(col>=5) {
+      col=0;
+      row++;
+    }
   }
 
   gtk_container_add(GTK_CONTAINER(content),grid);
index 913c4429ee666d6780b24aff8132433bc937e69b..8a1afd5e0afbb98d04dd30057925901123817116 100644 (file)
@@ -6,7 +6,11 @@ void set_button_text_color(GtkWidget *widget,char *color) {
   gchar tmp[64];
   style_context = gtk_widget_get_style_context(widget);
   gtk_style_context_add_provider(style_context, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
-  g_snprintf(tmp, sizeof tmp, "GtkButton, GtkLabel { color: %s; }", color);
+  if(gtk_minor_version>=20)  {
+    g_snprintf(tmp, sizeof tmp, "button, label { color: %s; }", color);
+  } else {
+    g_snprintf(tmp, sizeof tmp, "GtkButton, GtkLabel { color: %s; }", color);
+  }
   gtk_css_provider_load_from_data(GTK_CSS_PROVIDER(provider), tmp, -1, NULL);
   g_object_unref (provider);
 }
index 48da4d03f87d628111e257026968ca3a1303587c..43b2dff461d57f4a23e7db97f50cac17603fa320 100644 (file)
--- a/channel.h
+++ b/channel.h
@@ -31,8 +31,9 @@
 #define CHANNEL_TX 8
 #define CHANNEL_BS 9
 #define CHANNEL_SUBRX 10
+#define CHANNEL_AUDIO 11
 #ifdef PSK
-#define CHANNEL_PSK 11
+#define CHANNEL_PSK 12
 #endif
 
 #endif
index 176d1ec509823f2d2a8c8d5997b47791d12c4b77..c2a57387313fc9ca6be8512177d85381d654b1b3 100644 (file)
--- a/cw_menu.c
+++ b/cw_menu.c
@@ -20,6 +20,8 @@
 #include <gtk/gtk.h>
 #include <semaphore.h>
 #include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "new_menu.h"
@@ -29,6 +31,8 @@
 #include "filter.h"
 #include "radio.h"
 #include "receiver.h"
+#include "new_protocol.h"
+#include "old_protocol.h"
 
 static GtkWidget *parent_window=NULL;
 
@@ -36,15 +40,24 @@ static GtkWidget *menu_b=NULL;
 
 static GtkWidget *dialog=NULL;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 cw_keyer_internal_cb(GtkWidget *widget, gpointer data) {
   cw_keyer_internal=cw_keyer_internal==1?0:1;
   cw_changed();
@@ -81,7 +94,7 @@ static void cw_keys_reversed_cb(GtkWidget *widget, gpointer data) {
 }
 
 static void cw_keyer_mode_cb(GtkWidget *widget, gpointer data) {
-  cw_keyer_mode=(int)data;
+  cw_keyer_mode=(uintptr_t)data;
   cw_changed();
 }
 
@@ -102,6 +115,7 @@ static void cw_keyer_sidetone_frequency_value_changed_cb(GtkWidget *widget, gpoi
   }
 */
   cw_changed();
+  receiver_filter_changed(active_receiver);
 }
 
 void cw_menu(GtkWidget *parent) {
@@ -111,7 +125,9 @@ void cw_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - CW");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -128,7 +144,7 @@ void cw_menu(GtkWidget *parent) {
   //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
   //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
 
-  GtkWidget *close_b=gtk_button_new_with_label("Close CW");
+  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);
 
index d44fcde4d5e62734b68aaa86e3e0b2e49b3db22c..c99f84ffac56afdc691f02a3c4b8dc938a9ad471 100644 (file)
@@ -68,6 +68,9 @@
 #ifdef RADIOBERRY
 #define RADIOBERRY_PROTOCOL 3
 #endif
+#ifdef REMOTE
+#define REMOTE_PROTOCOL 4
+#endif
 
 struct _DISCOVERED {
     int protocol;
index 95baeb351ee0cfd4b765727673c2f9e1380dfc56..0d4239bea05e35d1ebc35fe52755890afd78fda6 100644 (file)
@@ -30,6 +30,8 @@
 
 #include "discovered.h"
 #include "discovery.h"
+#include "old_discovery.h"
+#include "new_discovery.h"
 #include "main.h"
 #include "radio.h"
 #ifdef USBOZY
 #ifdef RADIOBERRY
 #include "radioberry.h"
 #endif
+#ifdef REMOTE
+#include "remote_radio.h"
+#endif
+#include "ext.h"
 
 static GtkWidget *discovery_dialog;
 static DISCOVERED *d;
 
-int discovery(void *data);
-
 static gboolean start_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
 fprintf(stderr,"start_cb: %p\n",data);
   radio=(DISCOVERED *)data;
@@ -64,7 +68,7 @@ static gboolean gpio_cb (GtkWidget *widget, GdkEventButton *event, gpointer data
 
 static gboolean discover_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   gtk_widget_destroy(discovery_dialog);
-  g_idle_add(discovery,NULL);
+  g_idle_add(ext_discovery,NULL);
   return TRUE;
 }
 
@@ -74,7 +78,7 @@ static gboolean exit_cb (GtkWidget *widget, GdkEventButton *event, gpointer data
   return TRUE;
 }
 
-int discovery(void *data) {
+void discovery() {
 fprintf(stderr,"discovery\n");
   selected_device=0;
   devices=0;
@@ -99,10 +103,10 @@ fprintf(stderr,"discovery\n");
 #endif
 
 
-  status_text("Old Protocol ... Discovering Devices");
+  status_text("Protocol 1 ... Discovering Devices");
   old_discovery();
 
-  status_text("New Protocol ... Discovering Devices");
+  status_text("Protocol 2 ... Discovering Devices");
   new_discovery();
 
 #ifdef LIMESDR
@@ -121,9 +125,10 @@ fprintf(stderr,"discovery\n");
     gdk_window_set_cursor(gtk_widget_get_window(top_window),gdk_cursor_new(GDK_ARROW));
     discovery_dialog = gtk_dialog_new();
     gtk_window_set_transient_for(GTK_WINDOW(discovery_dialog),GTK_WINDOW(top_window));
-    gtk_window_set_decorated(GTK_WINDOW(discovery_dialog),FALSE);
+    gtk_window_set_title(GTK_WINDOW(discovery_dialog),"piHPSDR - Discovery");
+    //gtk_window_set_decorated(GTK_WINDOW(discovery_dialog),FALSE);
 
-    gtk_widget_override_font(discovery_dialog, pango_font_description_from_string("FreeMono 16"));
+    //gtk_widget_override_font(discovery_dialog, pango_font_description_from_string("FreeMono 16"));
 
     GdkRGBA color;
     color.red = 1.0;
@@ -144,20 +149,14 @@ fprintf(stderr,"discovery\n");
     GtkWidget *label=gtk_label_new("No devices found!");
     gtk_grid_attach(GTK_GRID(grid),label,0,0,2,1);
 
-#ifdef GPIO
-    GtkWidget *gpio_b=gtk_button_new_with_label("Config GPIO");
-    g_signal_connect (gpio_b, "button-press-event", G_CALLBACK(gpio_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),gpio_b,0,1,1,1);
-#endif
+    GtkWidget *exit_b=gtk_button_new_with_label("Exit");
+    g_signal_connect (exit_b, "button-press-event", G_CALLBACK(exit_cb), NULL);
+    gtk_grid_attach(GTK_GRID(grid),exit_b,0,1,1,1);
 
     GtkWidget *discover_b=gtk_button_new_with_label("Retry Discovery");
     g_signal_connect (discover_b, "button-press-event", G_CALLBACK(discover_cb), NULL);
     gtk_grid_attach(GTK_GRID(grid),discover_b,1,1,1,1);
 
-    GtkWidget *exit_b=gtk_button_new_with_label("Exit");
-    g_signal_connect (exit_b, "button-press-event", G_CALLBACK(exit_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),exit_b,2,1,1,1);
-
     gtk_container_add (GTK_CONTAINER (content), grid);
     gtk_widget_show_all(discovery_dialog);
   } else {
@@ -165,9 +164,10 @@ fprintf(stderr,"discovery\n");
     gdk_window_set_cursor(gtk_widget_get_window(top_window),gdk_cursor_new(GDK_ARROW));
     discovery_dialog = gtk_dialog_new();
     gtk_window_set_transient_for(GTK_WINDOW(discovery_dialog),GTK_WINDOW(top_window));
-    gtk_window_set_decorated(GTK_WINDOW(discovery_dialog),FALSE);
+    gtk_window_set_title(GTK_WINDOW(discovery_dialog),"piHPSDR - Discovery");
+    //gtk_window_set_decorated(GTK_WINDOW(discovery_dialog),FALSE);
 
-    gtk_widget_override_font(discovery_dialog, pango_font_description_from_string("FreeMono 16"));
+    //gtk_widget_override_font(discovery_dialog, pango_font_description_from_string("FreeMono 16"));
 
     GdkRGBA color;
     color.red = 1.0;
@@ -182,35 +182,29 @@ fprintf(stderr,"discovery\n");
 
     GtkWidget *grid=gtk_grid_new();
     gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
-    gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+    //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
     gtk_grid_set_row_spacing (GTK_GRID(grid),10);
 
     int i;
     char version[16];
-    char text[128];
+    char text[256];
     for(i=0;i<devices;i++) {
       d=&discovered[i];
-fprintf(stderr,"%p protocol=%d name=%s\n",d,d->protocol,d->name);
-      if(d->protocol==ORIGINAL_PROTOCOL) {
-        sprintf(version,"%d.%d",
-                        d->software_version/10,
-                        d->software_version%10);
-      } else {
-        sprintf(version,"%d.%d",
+fprintf(stderr,"%p Protocol=%d name=%s\n",d,d->protocol,d->name);
+      sprintf(version,"v%d.%d",
                         d->software_version/10,
                         d->software_version%10);
-      }
       switch(d->protocol) {
         case ORIGINAL_PROTOCOL:
         case NEW_PROTOCOL:
 #ifdef USBOZY
           if(d->device==DEVICE_OZY) {
-            sprintf(text,"%s (%s) on USB /dev/ozy\n", d->name, d->protocol==ORIGINAL_PROTOCOL?"old":"new");
+            sprintf(text,"%s (%s) on USB /dev/ozy", d->name, d->protocol==ORIGINAL_PROTOCOL?"Protocol 1":"Protocol 2");
           } else {
 #endif
-            sprintf(text,"%s (%s %s) %s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n",
+            sprintf(text,"%s (%s %s) %s (%02X:%02X:%02X:%02X:%02X:%02X) on %s",
                           d->name,
-                          d->protocol==ORIGINAL_PROTOCOL?"old":"new",
+                          d->protocol==ORIGINAL_PROTOCOL?"Protocol 1":"Protocol 2",
                           version,
                           inet_ntoa(d->info.network.address.sin_addr),
                           d->info.network.mac_address[0],
@@ -226,7 +220,7 @@ fprintf(stderr,"%p protocol=%d name=%s\n",d,d->protocol,d->name);
           break;
 #ifdef LIMESDR
         case LIMESDR_PROTOCOL:
-          sprintf(text,"%s\n",
+          sprintf(text,"%s",
                         d->name);
           break;
 #endif
@@ -266,6 +260,7 @@ fprintf(stderr,"%p protocol=%d name=%s\n",d,d->protocol,d->name);
     g_signal_connect (gpio_b, "button-press-event", G_CALLBACK(gpio_cb), NULL);
     gtk_grid_attach(GTK_GRID(grid),gpio_b,0,i,1,1);
 #endif
+
     GtkWidget *discover_b=gtk_button_new_with_label("Discover");
     g_signal_connect (discover_b, "button-press-event", G_CALLBACK(discover_cb), NULL);
     gtk_grid_attach(GTK_GRID(grid),discover_b,1,i,1,1);
@@ -279,8 +274,6 @@ fprintf(stderr,"%p protocol=%d name=%s\n",d,d->protocol,d->name);
 fprintf(stderr,"showing device dialog\n");
   }
 
-  return 0;
-
 }
 
 
index 74600f02124ef3124a2ba2b3b556520aa76633f2..fdc38ad0b5a7667e3b22975d06140b5ff7433b30 100644 (file)
@@ -17,4 +17,4 @@
 *
 */
 
-int discovery(void *data);
+extern void discovery();
index 027e0e49572de2046a3c8c4ee7f0550853c52bfd..d9a5276d7e76995813393e46b31d438ce9dad3bb 100644 (file)
@@ -20,6 +20,8 @@
 #include <gtk/gtk.h>
 #include <semaphore.h>
 #include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "new_menu.h"
@@ -34,22 +36,31 @@ static GtkWidget *menu_b=NULL;
 
 static GtkWidget *dialog=NULL;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 detector_mode_cb(GtkWidget *widget, gpointer data) {
-  display_detector_mode=(int)data;
+  display_detector_mode=(uintptr_t)data;
   SetDisplayDetectorMode(active_receiver->id, 0, display_detector_mode);
 }
 
 static void average_mode_cb(GtkWidget *widget, gpointer data) {
-  display_average_mode=(int)data;
+  display_average_mode=(uintptr_t)data;
   SetDisplayAverageMode(active_receiver->id, 0, display_average_mode);
 }
 
@@ -115,7 +126,9 @@ void display_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - Display");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -132,7 +145,7 @@ void display_menu(GtkWidget *parent) {
   //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
   //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
 
-  GtkWidget *close_b=gtk_button_new_with_label("Close Display");
+  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);
 
index 009a206e5c1ce46f54bc4c33d75baba9c55fa181..fc60b4788cf599a01ae687d66b433394bc9b3b3e 100644 (file)
@@ -20,6 +20,7 @@
 #include <gtk/gtk.h>
 #include <semaphore.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <pthread.h>
 
@@ -34,15 +35,24 @@ static GtkWidget *dialog=NULL;
 
 static GtkWidget *level;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 diversity_cb(GtkWidget *widget, gpointer data) {
   diversity_enabled=diversity_enabled==1?0:1;
   SetEXTDIVRun(0,diversity_enabled);
@@ -50,12 +60,12 @@ static void diversity_cb(GtkWidget *widget, gpointer data) {
 
 static void i_rotate_value_changed_cb(GtkWidget *widget, gpointer data) {
   i_rotate[1]=gtk_range_get_value(GTK_RANGE(widget));
-  SetEXTDIVRotate (0, 2, &i_rotate, &q_rotate);
+  SetEXTDIVRotate (0, 2, &i_rotate[0], &q_rotate[0]);
 }
 
 static void q_rotate_value_changed_cb(GtkWidget *widget, gpointer data) {
   q_rotate[1]=gtk_range_get_value(GTK_RANGE(widget));
-  SetEXTDIVRotate (0, 2, &i_rotate, &q_rotate);
+  SetEXTDIVRotate (0, 2, &i_rotate[0], &q_rotate[0]);
 }
 
 void diversity_menu(GtkWidget *parent) {
@@ -65,7 +75,9 @@ void diversity_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - Diversity");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -82,7 +94,7 @@ void diversity_menu(GtkWidget *parent) {
   //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
   //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
 
-  GtkWidget *close_b=gtk_button_new_with_label("Close Diversity");
+  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);
 
index 690a90e4fb086bbd85e3facaf3fb25d7ea5dc839..09ce55331e3a78bb71d0986be7807303715a5c5d 100644 (file)
@@ -20,6 +20,8 @@
 #include <gtk/gtk.h>
 #include <semaphore.h>
 #include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "new_menu.h"
@@ -36,15 +38,24 @@ static GtkWidget *menu_b=NULL;
 
 static GtkWidget *dialog=NULL;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 agc_hang_threshold_value_changed_cb(GtkWidget *widget, gpointer data) {
   active_receiver->agc_hang_threshold=(int)gtk_range_get_value(GTK_RANGE(widget));
   if(active_receiver->agc==AGC_LONG || active_receiver->agc==AGC_SLOW) {
@@ -53,18 +64,18 @@ static void agc_hang_threshold_value_changed_cb(GtkWidget *widget, gpointer data
 }
 
 static void pre_post_agc_cb(GtkWidget *widget, gpointer data) {
-  active_receiver->nr_agc=(int)data;
+  active_receiver->nr_agc=(uintptr_t)data;
   SetRXAEMNRPosition(active_receiver->id, active_receiver->nr_agc);
 
 }
 
 static void nr2_gain_cb(GtkWidget *widget, gpointer data) {
-  active_receiver->nr2_gain_method==(int)data;
+  active_receiver->nr2_gain_method==(uintptr_t)data;
   SetRXAEMNRgainMethod(active_receiver->id, active_receiver->nr2_gain_method);
 }
 
 static void nr2_npe_method_cb(GtkWidget *widget, gpointer data) {
-  active_receiver->nr2_npe_method=(int)data;
+  active_receiver->nr2_npe_method=(uintptr_t)data;
   SetRXAEMNRnpeMethod(active_receiver->id, active_receiver->nr2_npe_method);
 }
 
@@ -84,7 +95,9 @@ void dsp_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - DSP");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -101,7 +114,7 @@ void dsp_menu(GtkWidget *parent) {
   //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
   //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
 
-  GtkWidget *close_b=gtk_button_new_with_label("Close DSP");
+  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);
 
index f2dabf7f88e4507d9190c1652dfcf1b479680ac9..1fb47244d4d2e9a6be3e7e77e9f69ef91a4124ef 100644 (file)
@@ -48,20 +48,29 @@ static GtkWidget *b_cw_speed;
 static GtkWidget *b_cw_frequency;
 static GtkWidget *b_panadapter_high;
 static GtkWidget *b_panadapter_low;
+static GtkWidget *b_squelch;
+static GtkWidget *b_compression;
 
 static int encoder;
 
-
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     sub_menu=NULL;
   }
-  active_menu=NO_MENU;
+}
+
+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;
+}
+
 void encoder_select(int pos) {
   int action;
   GtkWidget *button;
@@ -70,11 +79,11 @@ void encoder_select(int pos) {
       if(pos>0) {
         e1_encoder_action--;
         if(e1_encoder_action<0) {
-          e1_encoder_action=ENCODER_LAST;
+          e1_encoder_action=ENCODER_LAST-1;
         }
       } if(pos<0) {
         e1_encoder_action++;
-        if(e1_encoder_action>ENCODER_LAST) {
+        if(e1_encoder_action>=ENCODER_LAST) {
           e1_encoder_action=0;
         }
       }
@@ -84,11 +93,11 @@ void encoder_select(int pos) {
       if(pos>0) {
         e2_encoder_action--;
         if(e2_encoder_action<0) {
-          e2_encoder_action=ENCODER_LAST;
+          e2_encoder_action=ENCODER_LAST-1;
         }
       } if(pos<0) {
         e2_encoder_action++;
-        if(e2_encoder_action>ENCODER_LAST) {
+        if(e2_encoder_action>=ENCODER_LAST) {
           e2_encoder_action=0;
         }
       }
@@ -98,11 +107,11 @@ void encoder_select(int pos) {
       if(pos>0) {
         e3_encoder_action--;
         if(e3_encoder_action<0) {
-          e3_encoder_action=ENCODER_LAST;
+          e3_encoder_action=ENCODER_LAST-1;
         }
       } if(pos<0) {
         e3_encoder_action++;
-        if(e3_encoder_action>ENCODER_LAST) {
+        if(e3_encoder_action>=ENCODER_LAST) {
           e3_encoder_action=0;
         }
       }
@@ -126,9 +135,11 @@ void encoder_select(int pos) {
     case ENCODER_DRIVE:
       button=b_drive;
       break;
+/*
     case ENCODER_TUNE_DRIVE:
       button=b_tune_drive;
       break;
+*/
     case ENCODER_RIT:
       button=b_rit;
       break;
@@ -144,6 +155,12 @@ void encoder_select(int pos) {
     case ENCODER_PANADAPTER_LOW:
       button=b_panadapter_low;
       break;
+    case ENCODER_SQUELCH:
+      button=b_squelch;
+      break;
+    case ENCODER_COMP:
+      button=b_compression;
+      break;
   }
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
 
@@ -187,7 +204,11 @@ void encoder_menu(GtkWidget *parent,int e) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  char title[32];
+  sprintf(title,"piHPSDR - Encoder E%d Action:",encoder);
+  gtk_window_set_title(GTK_WINDOW(dialog),title);
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -205,81 +226,111 @@ void encoder_menu(GtkWidget *parent,int e) {
   gtk_grid_set_column_spacing (GTK_GRID(grid),5);
   gtk_grid_set_row_spacing (GTK_GRID(grid),5);
 
+  int row=0;
+  int col=0;
+
   GtkWidget *close_b=gtk_button_new_with_label("Close");
   g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
-  gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
+  gtk_grid_attach(GTK_GRID(grid),close_b,col,row,1,1);
 
-  char label_text[32];
-  sprintf(label_text,"Encoder E%d Action:",encoder);
-  GtkWidget *label=gtk_label_new(label_text);
-  gtk_grid_attach(GTK_GRID(grid),label,0,1,2,1);
+  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,0,2,2,1);
+  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);
 
+  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,0,3,2,1);
+  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);
 
+  row++;
+
   b_attenuation=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_agc_gain),"Attenuation");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_attenuation), encoder_action==ENCODER_ATTENUATION);
   gtk_widget_show(b_attenuation);
-  gtk_grid_attach(GTK_GRID(grid),b_attenuation,0,4,2,1);
+  gtk_grid_attach(GTK_GRID(grid),b_attenuation,col,row,2,1);
   g_signal_connect(b_attenuation,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_ATTENUATION);
 
+  row++;
+
   b_mic_gain=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_attenuation),"Mic Gain");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_mic_gain), encoder_action==ENCODER_MIC_GAIN);
   gtk_widget_show(b_mic_gain);
-  gtk_grid_attach(GTK_GRID(grid),b_mic_gain,0,5,2,1);
+  gtk_grid_attach(GTK_GRID(grid),b_mic_gain,col,row,2,1);
   g_signal_connect(b_mic_gain,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_MIC_GAIN);
 
+  row++;
+
   b_drive=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_mic_gain),"Drive");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_drive), encoder_action==ENCODER_DRIVE);
   gtk_widget_show(b_drive);
-  gtk_grid_attach(GTK_GRID(grid),b_drive,0,6,2,1);
+  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_tune_drive=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_drive),"Tune Drive");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_tune_drive), encoder_action==ENCODER_TUNE_DRIVE);
-  gtk_widget_show(b_tune_drive);
-  gtk_grid_attach(GTK_GRID(grid),b_tune_drive,0,7,2,1);
-  g_signal_connect(b_tune_drive,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_TUNE_DRIVE);
+  row++;
 
-  b_rit=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_tune_drive),"RIT");
+  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,2,2,2,1);
+  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);
 
+  col=2;
+  row=1;
+
   b_cw_speed=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_rit),"CW Speed");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_cw_speed), encoder_action==ENCODER_CW_SPEED);
   gtk_widget_show(b_cw_speed);
-  gtk_grid_attach(GTK_GRID(grid),b_cw_speed,2,3,2,1);
+  gtk_grid_attach(GTK_GRID(grid),b_cw_speed,col,row,2,1);
   g_signal_connect(b_cw_speed,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_CW_SPEED);
 
+  row++;
+
   b_cw_frequency=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_cw_speed),"CW Freq");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_cw_frequency), encoder_action==ENCODER_CW_FREQUENCY);
   gtk_widget_show(b_cw_frequency);
-  gtk_grid_attach(GTK_GRID(grid),b_cw_frequency,2,4,2,1);
+  gtk_grid_attach(GTK_GRID(grid),b_cw_frequency,col,row,2,1);
   g_signal_connect(b_cw_frequency,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_CW_FREQUENCY);
 
+  row++;
+
   b_panadapter_high=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_cw_frequency),"Panadapter High");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_panadapter_high), encoder_action==ENCODER_PANADAPTER_HIGH);
   gtk_widget_show(b_panadapter_high);
-  gtk_grid_attach(GTK_GRID(grid),b_panadapter_high,2,6,2,1);
+  gtk_grid_attach(GTK_GRID(grid),b_panadapter_high,col,row,2,1);
   g_signal_connect(b_panadapter_high,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_PANADAPTER_HIGH);
 
-  b_panadapter_low=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_cw_frequency),"Panadapter Low");
+  row++;
+
+  b_panadapter_low=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_panadapter_high),"Panadapter Low");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_panadapter_low), encoder_action==ENCODER_PANADAPTER_LOW);
   gtk_widget_show(b_panadapter_low);
-  gtk_grid_attach(GTK_GRID(grid),b_panadapter_low,2,7,2,1);
+  gtk_grid_attach(GTK_GRID(grid),b_panadapter_low,col,row,2,1);
   g_signal_connect(b_panadapter_low,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_PANADAPTER_LOW);
 
+  row++;
+
+  b_squelch=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_panadapter_low),"Squelch");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_squelch), encoder_action==ENCODER_SQUELCH);
+  gtk_widget_show(b_squelch);
+  gtk_grid_attach(GTK_GRID(grid),b_squelch,col,row,2,1);
+  g_signal_connect(b_squelch,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_SQUELCH);
+
+  row++;
+
+  b_compression=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_squelch),"COMP");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_compression), encoder_action==ENCODER_COMP);
+  gtk_widget_show(b_compression);
+  gtk_grid_attach(GTK_GRID(grid),b_compression,col,row,2,1);
+  g_signal_connect(b_compression,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_COMP);
+
   gtk_container_add(GTK_CONTAINER(content),grid);
 
   sub_menu=dialog;
index f2c7582e53f267d0fa2afd020e3947c1a7f5e13c..514e77d609607eb803e006feca7f776f56a71f8a 100644 (file)
@@ -20,6 +20,8 @@
 #include <gtk/gtk.h>
 #include <semaphore.h>
 #include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include <wdsp.h>
@@ -40,15 +42,24 @@ static GtkWidget *high_scale;
 
 static gboolean tx_menu=TRUE;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 gboolean tx_rb_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
     tx_menu=TRUE;
@@ -83,8 +94,8 @@ static gboolean enable_cb (GtkWidget *widget, GdkEventButton *event, gpointer da
   }
 }
 
-static gboolean rx_value_changed_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
-  int i=(int)data;
+static void value_changed_cb (GtkWidget *widget, gpointer data) {
+  int i=(uintptr_t)data;
   if(tx_menu) {
     tx_equalizer[i]=(int)gtk_range_get_value(GTK_RANGE(widget));
     SetTXAGrphEQ(transmitter->id, tx_equalizer);
@@ -101,7 +112,9 @@ void equalizer_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - Equalizer");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -118,7 +131,7 @@ void equalizer_menu(GtkWidget *parent) {
   gtk_grid_set_row_homogeneous(GTK_GRID(grid),FALSE);
   gtk_grid_set_column_homogeneous(GTK_GRID(grid),FALSE);
 
-  GtkWidget *close_b=gtk_button_new_with_label("Close Equalizer");
+  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);
 
@@ -153,7 +166,7 @@ void equalizer_menu(GtkWidget *parent) {
 
   preamp_scale=gtk_scale_new_with_range(GTK_ORIENTATION_VERTICAL,-12.0,15.0,1.0);
   gtk_range_set_value(GTK_RANGE(preamp_scale),(double)tx_equalizer[0]);
-  g_signal_connect(preamp_scale,"value-changed",G_CALLBACK(rx_value_changed_cb),(gpointer)0);
+  g_signal_connect(preamp_scale,"value-changed",G_CALLBACK(value_changed_cb),(gpointer)0);
   gtk_grid_attach(GTK_GRID(grid),preamp_scale,0,3,1,10);
   gtk_widget_set_size_request(preamp_scale,10,270);
   gtk_scale_add_mark(GTK_SCALE(preamp_scale),-12.0,GTK_POS_LEFT,"-12dB");
@@ -169,7 +182,7 @@ void equalizer_menu(GtkWidget *parent) {
 
   low_scale=gtk_scale_new_with_range(GTK_ORIENTATION_VERTICAL,-12.0,15.0,1.0);
   gtk_range_set_value(GTK_RANGE(low_scale),(double)tx_equalizer[1]);
-  g_signal_connect(low_scale,"value-changed",G_CALLBACK(rx_value_changed_cb),(gpointer)1);
+  g_signal_connect(low_scale,"value-changed",G_CALLBACK(value_changed_cb),(gpointer)1);
   gtk_grid_attach(GTK_GRID(grid),low_scale,1,3,1,10);
   gtk_scale_add_mark(GTK_SCALE(low_scale),-12.0,GTK_POS_LEFT,"-12dB");
   gtk_scale_add_mark(GTK_SCALE(low_scale),-9.0,GTK_POS_LEFT,NULL);
@@ -184,7 +197,7 @@ void equalizer_menu(GtkWidget *parent) {
 
   mid_scale=gtk_scale_new_with_range(GTK_ORIENTATION_VERTICAL,-12.0,15.0,1.0);
   gtk_range_set_value(GTK_RANGE(mid_scale),(double)tx_equalizer[2]);
-  g_signal_connect(mid_scale,"value-changed",G_CALLBACK(rx_value_changed_cb),(gpointer)2);
+  g_signal_connect(mid_scale,"value-changed",G_CALLBACK(value_changed_cb),(gpointer)2);
   gtk_grid_attach(GTK_GRID(grid),mid_scale,2,3,1,10);
   gtk_scale_add_mark(GTK_SCALE(mid_scale),-12.0,GTK_POS_LEFT,"-12dB");
   gtk_scale_add_mark(GTK_SCALE(mid_scale),-9.0,GTK_POS_LEFT,NULL);
@@ -199,7 +212,7 @@ void equalizer_menu(GtkWidget *parent) {
 
   high_scale=gtk_scale_new_with_range(GTK_ORIENTATION_VERTICAL,-12.0,15.0,1.0);
   gtk_range_set_value(GTK_RANGE(high_scale),(double)tx_equalizer[3]);
-  g_signal_connect(high_scale,"value-changed",G_CALLBACK(rx_value_changed_cb),(gpointer)3);
+  g_signal_connect(high_scale,"value-changed",G_CALLBACK(value_changed_cb),(gpointer)3);
   gtk_grid_attach(GTK_GRID(grid),high_scale,3,3,1,10);
   gtk_scale_add_mark(GTK_SCALE(high_scale),-12.0,GTK_POS_LEFT,"-12dB");
   gtk_scale_add_mark(GTK_SCALE(high_scale),-9.0,GTK_POS_LEFT,NULL);
diff --git a/error_handler.c b/error_handler.c
new file mode 100644 (file)
index 0000000..5c7313e
--- /dev/null
@@ -0,0 +1,36 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <gtk/gtk.h>
+
+#include "error_handler.h"
+#include "main.h"
+
+static GtkWidget *dialog;
+static gint timer;
+
+int timeout_cb(gpointer data) {
+  gtk_widget_destroy(dialog);
+  exit(1);
+}
+
+int show_error(void *data) {
+  dialog=gtk_dialog_new_with_buttons("ERROR",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+  GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+  GtkWidget *label=gtk_label_new((char *)data);
+  gtk_container_add(GTK_CONTAINER(content),label);
+  gtk_widget_show(label);
+  timer=g_timeout_add(5000,timeout_cb,NULL);
+  int result=gtk_dialog_run(GTK_DIALOG(dialog));
+}
+
+void error_handler(char *text,char *err) {
+  char message[1024];
+  sprintf(message,"ERROR: %s: %s\n",text,err);
+  fprintf(stderr,"%s\n",message);
+
+  sprintf(message,"ERROR\n\n    %s:\n\n    %s\n\npiHPSDR will terminate in 5 seconds",text,err);
+
+  g_idle_add(show_error,message);
+
+}
diff --git a/error_handler.h b/error_handler.h
new file mode 100644 (file)
index 0000000..884d067
--- /dev/null
@@ -0,0 +1 @@
+extern void error_handler(char *text,char *err);
index c9506465ac8cfc97befa83ad3bcadb67c1b0edac..409ef13ea4b514ded001f3cd8cae5e897c775dff 100644 (file)
@@ -25,6 +25,8 @@
 #include "new_menu.h"
 #include "exit_menu.h"
 #include "radio.h"
+#include "new_protocol.h"
+#include "old_protocol.h"
 
 static GtkWidget *parent_window=NULL;
 
@@ -32,15 +34,24 @@ static GtkWidget *menu_b=NULL;
 
 static GtkWidget *dialog=NULL;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 gboolean exit_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
 #ifdef GPIO
   gpio_close();
@@ -90,7 +101,7 @@ static gboolean reboot_cb (GtkWidget *widget, GdkEventButton *event, gpointer da
 #endif
   }
   radioSaveState();
-  system("reboot");
+  int rc=system("reboot");
   _exit(0);
 }
 
@@ -117,7 +128,7 @@ static gboolean shutdown_cb (GtkWidget *widget, GdkEventButton *event, gpointer
 #endif
   }
   radioSaveState();
-  system("shutdown -h -P now");
+  int rc=system("shutdown -h -P now");
   _exit(0);
 }
 
@@ -127,7 +138,9 @@ void exit_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - Exit");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
diff --git a/ext.c b/ext.c
new file mode 100644 (file)
index 0000000..f42a714
--- /dev/null
+++ b/ext.c
@@ -0,0 +1,156 @@
+/* Copyright (C)
+* 2017 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <gtk/gtk.h>
+#include "discovery.h"
+#include "receiver.h"
+#include "sliders.h"
+#include "toolbar.h"
+#include "band_menu.h"
+#include "vfo.h"
+#include "radio.h"
+#include "new_menu.h"
+#ifdef PURESIGNAL
+#include "ps_menu.h"
+#endif
+
+// The following calls functions can be called usig g_idle_add
+
+int ext_discovery(void *data) {
+  discovery();
+  return 0;
+}
+
+int ext_set_frequency(void *data) {
+  setFrequency(*(long long *)data);
+  free(data);
+}
+
+int ext_vfo_update(void *data) {
+  vfo_update();
+  return 0;
+}
+
+int ext_vfo_filter_changed(void *data) {
+  vfo_filter_changed((uintptr_t)data);
+  return 0;
+}
+
+int ext_band_update(void *data) {
+  if(data==NULL) {
+    start_band();
+  } else {
+    band_select_cb(NULL,data);
+  }
+  return 0;
+}
+
+int ext_mode_update(void *data) {
+  start_mode();
+}
+
+int ext_filter_update(void *data) {
+  start_filter();
+}
+
+int ext_noise_update(void *data) {
+  start_noise();
+}
+
+int ext_ptt_update(void *data) {
+  ptt_update((uintptr_t)data);
+  return 0;
+}
+
+int ext_mox_update(void *data) {
+  mox_update((uintptr_t)data);
+  return 0;
+}
+
+int ext_tune_update(void *data) {
+  tune_update((uintptr_t)data);
+  return 0;
+}
+
+int ext_vox_changed(void *data) {
+  vox_changed((uintptr_t)data);
+  return 0;
+}
+
+int ext_update_agc_gain(void *data) {
+  update_agc_gain(*(double *)data);
+  free(data);
+  return 0;
+}
+
+int ext_update_af_gain(void *data) {
+  update_af_gain();
+  return 0;
+}
+
+int ext_calc_drive_level(void *data) {
+  calcDriveLevel();
+  return 0;
+}
+
+int ext_vfo_band_changed(void *data) {
+  vfo_band_changed((uintptr_t)data);
+  return 0;
+}
+
+int ext_radio_change_sample_rate(void *data) {
+  radio_change_sample_rate((uintptr_t)data);
+  return 0;
+}
+
+int ext_cw_setup() {
+  radio_cw_setup();
+  return 0;
+}
+
+int ext_cw_key(void *data) {
+  radio_cw_key((uintptr_t)data);
+  return 0;
+}
+
+int ext_update_squelch(void *data) {
+  set_squelch(active_receiver);
+  return 0;
+}
+
+int ext_sliders_update(void *data) {
+  sliders_update();
+  return 0;
+}
+
+#ifdef PURESIGNAL
+int ext_tx_set_ps(void *data) {
+  tx_set_ps(transmitter,(uintptr_t)data);
+  return 0;
+}
+
+int ext_ps_twotone(void *data) {
+  ps_twotone((uintptr_t)data);
+  return 0;
+}
+#endif
diff --git a/ext.h b/ext.h
new file mode 100644 (file)
index 0000000..adf7264
--- /dev/null
+++ b/ext.h
@@ -0,0 +1,52 @@
+/* Copyright (C)
+* 2017 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+
+// The following calls functions can be called usig g_idle_add
+
+extern int ext_discovery(void *data);
+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_ptt_update(void *data);
+extern int ext_mox_update(void *data);
+extern int ext_tune_update(void *data);
+extern int ext_linein_changed(void *data);
+extern int ext_vox_changed(void *data);
+extern int ext_sliders_mode_changed(void *data);
+extern int ext_update_agc_gain(void *data);
+extern int ext_update_af_gain(void *data);
+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_cw_setup();
+extern int ext_cw_key(void *data);
+
+extern int ext_update_squelch(void *data);
+
+extern int ext_sliders_update(void *data);
+
+extern int ext_mode_update(void *data);
+extern int ext_filter_update(void *data);
+extern int ext_noise_update(void *data);
+
+extern int ext_tx_set_ps(void *data);
+extern int ext_ps_twotone(void *data);
index 5f7bca7d008d551b5b5838480fcb266333514e80..30f5b02186ea01646be8d66113c90be9beb25fa2 100644 (file)
@@ -20,6 +20,8 @@
 #include <gtk/gtk.h>
 #include <semaphore.h>
 #include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "new_menu.h"
@@ -32,17 +34,26 @@ static GtkWidget *menu_b=NULL;
 
 static GtkWidget *dialog=NULL;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 filter_type_cb(GtkWidget *widget, gpointer data) {
-  set_filter_type((int)data);
+  set_filter_type((uintptr_t)data);
 }
 
 #ifdef SET_FILTER_SIZE
@@ -56,7 +67,9 @@ void fft_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - FFT");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -77,53 +90,71 @@ void fft_menu(GtkWidget *parent) {
   g_signal_connect (close_b, "button_press_event", G_CALLBACK(close_cb), NULL);
   gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
 
-  int x=0;
+  int row=1;
+  int col=0;
 
   GtkWidget *filter_type_label=gtk_label_new("Filter Type: ");
-  gtk_grid_attach(GTK_GRID(grid),filter_type_label,x,1,1,1);
+  gtk_grid_attach(GTK_GRID(grid),filter_type_label,col,row,1,1);
   
+  row++;
+  col=0;
+
   GtkWidget *linear_phase=gtk_radio_button_new_with_label(NULL,"Linear Phase");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (linear_phase), receiver[0]->low_latency==0);
-  gtk_grid_attach(GTK_GRID(grid),linear_phase,x,2,1,1);
+  gtk_grid_attach(GTK_GRID(grid),linear_phase,col,row,1,1);
   g_signal_connect(linear_phase,"pressed",G_CALLBACK(filter_type_cb),(gpointer *)0);
 
+  col++;
+
   GtkWidget *low_latency=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(linear_phase),"Low Latency");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_latency), receiver[0]->low_latency==1);
-  gtk_grid_attach(GTK_GRID(grid),low_latency,x,3,1,1);
+  gtk_grid_attach(GTK_GRID(grid),low_latency,col,row,1,1);
   g_signal_connect(low_latency,"pressed",G_CALLBACK(filter_type_cb),(gpointer *)1);
 
-  x++;
-
 #ifdef SET_FILTER_SIZE
+
+  row++;
+  col=0;
+
   GtkWidget *filter_size_label=gtk_label_new("Filter Size: ");
-  gtk_grid_attach(GTK_GRID(grid),filter_size_label,x,1,1,1);
+  gtk_grid_attach(GTK_GRID(grid),filter_size_label,col,row,1,1);
   
+  row++;
+  col=0;
+
   GtkWidget *filter_1024=gtk_radio_button_new_with_label(NULL,"1024");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (filter_1024), receiver[0]->fft_size==1024);
-  gtk_grid_attach(GTK_GRID(grid),filter_1024,x,2,1,1);
+  gtk_grid_attach(GTK_GRID(grid),filter_1024,col,row,1,1);
   g_signal_connect(filter_1024,"pressed",G_CALLBACK(filter_size_cb),(gpointer *)1024);
 
+  col++;
+
   GtkWidget *filter_2048=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(filter_1024),"2048");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (filter_2048), receiver[0]->fft_size==2048);
-  gtk_grid_attach(GTK_GRID(grid),filter_2048,x,3,1,1);
+  gtk_grid_attach(GTK_GRID(grid),filter_2048,col,row,1,1);
   g_signal_connect(filter_2048,"pressed",G_CALLBACK(filter_size_cb),(gpointer *)2048);
 
+  col++;
+
   GtkWidget *filter_4096=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(filter_2048),"4096");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (filter_4096), receiver[0]->fft_size==4096);
-  gtk_grid_attach(GTK_GRID(grid),filter_4096,x,4,1,1);
+  gtk_grid_attach(GTK_GRID(grid),filter_4096,col,row,1,1);
   g_signal_connect(filter_4096,"pressed",G_CALLBACK(filter_size_cb),(gpointer *)4096);
 
+  col++;
+
   GtkWidget *filter_8192=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(filter_4096),"8192");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (filter_8192), receiver[0]->fft_size==8192);
-  gtk_grid_attach(GTK_GRID(grid),filter_8192,x,5,1,1);
+  gtk_grid_attach(GTK_GRID(grid),filter_8192,col,row,1,1);
   g_signal_connect(filter_8192,"pressed",G_CALLBACK(filter_size_cb),(gpointer *)8192);
 
+  col++;
+
   GtkWidget *filter_16384=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(filter_8192),"16384");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (filter_16384), receiver[0]->fft_size==16384);
-  gtk_grid_attach(GTK_GRID(grid),filter_16384,x,6,1,1);
+  gtk_grid_attach(GTK_GRID(grid),filter_16384,col,row,1,1);
   g_signal_connect(filter_16384,"pressed",G_CALLBACK(filter_size_cb),(gpointer *)16394);
 
-  x++;
 #endif
   gtk_container_add(GTK_CONTAINER(content),grid);
 
index 63d959c50137aa87bfbe4d7632d86850186b1358..86c1ad8310f1ef81e7bdc0875a739f9db0e57e55 100644 (file)
--- a/filter.c
+++ b/filter.c
@@ -18,6 +18,8 @@
 */
 
 #include <stdio.h>
+#include <stdlib.h>
+
 #include "filter.h"
 #include "property.h"
 
@@ -201,23 +203,6 @@ FILTER filterDRM[FILTERS]={
     {-3300,3300,"Var2"}
     };
 
-#ifdef FREEDV
-FILTER filterFREEDV[FILTERS]={
-    {150,5150,"5.0k"},
-    {150,4550,"4.4k"},
-    {150,3950,"3.8k"},
-    {150,3450,"3.3k"},
-    {150,3050,"2.9k"},
-    {150,2850,"2.7k"},
-    {150,2550,"2.4k"},
-    {150,2250,"2.1k"},
-    {150,1950,"1.8k"},
-    {150,1150,"1.0k"},
-    {150,2850,"Var1"},
-    {150,2850,"Var2"}
-    };
-#endif
-
 #ifdef PSK
 FILTER filterPSK[FILTERS]={
     {150,5150,"5.0k"},
@@ -249,9 +234,6 @@ FILTER *filters[]={
     ,filterDIGL
     ,filterSAM
     ,filterDRM
-#ifdef FREEDV
-    ,filterFREEDV
-#endif
 #ifdef PSK
     ,filterPSK
 #endif
index f0aa005068e83b272324eaa822fa5db6b902a81b..aee2b6840d4e54b4a9ff4ce04dbaf1ac2274f866 100644 (file)
@@ -17,6 +17,8 @@
 
 #include <gtk/gtk.h>
 #include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "new_menu.h"
@@ -36,17 +38,26 @@ static GtkWidget *dialog=NULL;
 
 static GtkWidget *last_filter;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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;
+}
+
 int filter_select(void *data) {
-  int f=(int)data;
+  int f=(uintptr_t)data;
   vfo_filter_changed(f);
   return 0;
 }
@@ -59,23 +70,27 @@ static gboolean filter_select_cb (GtkWidget *widget, gpointer        data) {
 }
 
 static gboolean deviation_select_cb (GtkWidget *widget, gpointer data) {
-  deviation=(int)data;
-  if(deviation==2500) {
+  active_receiver->deviation=(uintptr_t)data;
+  transmitter->deviation=(uintptr_t)data;
+  if(active_receiver->deviation==2500) {
     //setFilter(-4000,4000);
     set_filter(active_receiver,-4000,4000);
+    tx_set_filter(transmitter,-4000,4000);
   } else {
     //setFilter(-8000,8000);
     set_filter(active_receiver,-8000,8000);
+    tx_set_filter(transmitter,-8000,8000);
   }
-  set_deviation(active_receiver,(double)deviation);
+  set_deviation(active_receiver);
+  transmitter_set_deviation(transmitter);
   set_button_text_color(last_filter,"black");
   last_filter=widget;
   set_button_text_color(last_filter,"orange");
-  vfo_update(NULL);
+  vfo_update();
 }
 
 static void var_spin_low_cb (GtkWidget *widget, gpointer data) {
-  int f=(int)data;
+  int f=(uintptr_t)data;
   int id=active_receiver->id;
 
   FILTER *mode_filters=filters[vfo[id].mode];
@@ -86,12 +101,13 @@ static void var_spin_low_cb (GtkWidget *widget, gpointer data) {
     filter->high=filter->low;
   }
   if(f==vfo[id].filter) {
-    receiver_filter_changed(receiver[id]);
+    vfo_filter_changed(f);
+    //receiver_filter_changed(receiver[id]);
   }
 }
 
 static void var_spin_high_cb (GtkWidget *widget, gpointer data) {
-  int f=(int)data;
+  int f=(uintptr_t)data;
   int id=active_receiver->id;
 
   FILTER *mode_filters=filters[vfo[id].mode];
@@ -99,7 +115,8 @@ static void var_spin_high_cb (GtkWidget *widget, gpointer data) {
 
   filter->high=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
   if(f==vfo[id].filter) {
-    receiver_filter_changed(receiver[id]);
+    vfo_filter_changed(f);
+    //receiver_filter_changed(receiver[id]);
   }
 }
 
@@ -111,7 +128,11 @@ void filter_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  char title[64];
+  sprintf(title,"piHPSDR - Filter (RX %d VFO %s)",active_receiver->id,active_receiver->id==0?"A":"B");
+  gtk_window_set_title(GTK_WINDOW(dialog),title);
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -129,45 +150,40 @@ void filter_menu(GtkWidget *parent) {
   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 Filter");
+  GtkWidget *close_b=gtk_button_new_with_label("Close");
   g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
   gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
 
-  char label[32];
-  sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B");
-  GtkWidget *rx_label=gtk_label_new(label);
-  gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1);
-
   BAND *band=band_get_band(vfo[active_receiver->id].band);
   BANDSTACK *bandstack=band->bandstack;
   BANDSTACK_ENTRY *entry=&bandstack->entry[vfo[active_receiver->id].bandstack];
   FILTER* band_filters=filters[vfo[active_receiver->id].mode];
   FILTER* band_filter=&band_filters[vfo[active_receiver->id].filter];
 
-  switch(entry->mode) {
+  switch(vfo[active_receiver->id].mode) {
     case modeFMN:
       {
       GtkWidget *l=gtk_label_new("Deviation:");
       gtk_grid_attach(GTK_GRID(grid),l,0,1,1,1);
 
       GtkWidget *b=gtk_button_new_with_label("2.5K");
-      if(deviation==2500) {
+      if(active_receiver->deviation==2500) {
         set_button_text_color(b,"orange");
         last_filter=b;
       } else {
         set_button_text_color(b,"black");
       }
-      g_signal_connect(b,"pressed",G_CALLBACK(deviation_select_cb),(gpointer *)2500);
+      g_signal_connect(b,"pressed",G_CALLBACK(deviation_select_cb),(gpointer)(long)2500);
       gtk_grid_attach(GTK_GRID(grid),b,1,1,1,1);
 
       b=gtk_button_new_with_label("5.0K");
-      if(deviation==5000) {
+      if(active_receiver->deviation==5000) {
         set_button_text_color(b,"orange");
         last_filter=b;
       } else {
         set_button_text_color(b,"black");
       }
-      g_signal_connect(b,"pressed",G_CALLBACK(deviation_select_cb),(gpointer *)5000);
+      g_signal_connect(b,"pressed",G_CALLBACK(deviation_select_cb),(gpointer)(long)5000);
       gtk_grid_attach(GTK_GRID(grid),b,2,1,1,1);
       }
       break;
@@ -183,7 +199,7 @@ void filter_menu(GtkWidget *parent) {
           set_button_text_color(b,"black");
         }
         gtk_grid_attach(GTK_GRID(grid),b,i%5,1+(i/5),1,1);
-        g_signal_connect(b,"pressed",G_CALLBACK(filter_select_cb),(gpointer *)i);
+        g_signal_connect(b,"pressed",G_CALLBACK(filter_select_cb),(gpointer)(long)i);
       }
 
       // last 2 are var1 and var2
@@ -197,18 +213,18 @@ void filter_menu(GtkWidget *parent) {
         set_button_text_color(b,"black");
       }
       gtk_grid_attach(GTK_GRID(grid),b,0,row,1,1);
-      g_signal_connect(b,"pressed",G_CALLBACK(filter_select_cb),(gpointer *)i);
+      g_signal_connect(b,"pressed",G_CALLBACK(filter_select_cb),(gpointer)(long)i);
 
       GtkWidget *var1_spin_low=gtk_spin_button_new_with_range(-8000.0,+8000.0,1.0);
       gtk_spin_button_set_value(GTK_SPIN_BUTTON(var1_spin_low),(double)band_filter->low);
       gtk_grid_attach(GTK_GRID(grid),var1_spin_low,1,row,1,1);
-      g_signal_connect(var1_spin_low,"value-changed",G_CALLBACK(var_spin_low_cb),(gpointer *)i);
+      g_signal_connect(var1_spin_low,"value-changed",G_CALLBACK(var_spin_low_cb),(gpointer)(long)i);
 
       if(vfo[active_receiver->id].mode!=modeCWL && vfo[active_receiver->id].mode!=modeCWU) {
         GtkWidget *var1_spin_high=gtk_spin_button_new_with_range(-8000.0,+8000.0,1.0);
         gtk_spin_button_set_value(GTK_SPIN_BUTTON(var1_spin_high),(double)band_filter->high);
         gtk_grid_attach(GTK_GRID(grid),var1_spin_high,2,row,1,1);
-        g_signal_connect(var1_spin_high,"value-changed",G_CALLBACK(var_spin_high_cb),(gpointer *)i);
+        g_signal_connect(var1_spin_high,"value-changed",G_CALLBACK(var_spin_high_cb),(gpointer)(long)i);
       }
 
       row++;
@@ -222,18 +238,18 @@ void filter_menu(GtkWidget *parent) {
         set_button_text_color(b,"black");
       }
       gtk_grid_attach(GTK_GRID(grid),b,0,row,1,1);
-      g_signal_connect(b,"pressed",G_CALLBACK(filter_select_cb),(gpointer *)i);
+      g_signal_connect(b,"pressed",G_CALLBACK(filter_select_cb),(gpointer)(long)i);
       
       GtkWidget *var2_spin_low=gtk_spin_button_new_with_range(-8000.0,+8000.0,1.0);
       gtk_spin_button_set_value(GTK_SPIN_BUTTON(var2_spin_low),(double)band_filter->low);
       gtk_grid_attach(GTK_GRID(grid),var2_spin_low,1,row,1,1);
-      g_signal_connect(var2_spin_low,"value-changed",G_CALLBACK(var_spin_low_cb),(gpointer *)i);
+      g_signal_connect(var2_spin_low,"value-changed",G_CALLBACK(var_spin_low_cb),(gpointer)(long)i);
 
       if(vfo[active_receiver->id].mode!=modeCWL && vfo[active_receiver->id].mode!=modeCWU) {
         GtkWidget *var2_spin_high=gtk_spin_button_new_with_range(-8000.0,+8000.0,1.0);
         gtk_spin_button_set_value(GTK_SPIN_BUTTON(var2_spin_high),(double)band_filter->high);
         gtk_grid_attach(GTK_GRID(grid),var2_spin_high,2,row,1,1);
-        g_signal_connect(var2_spin_high,"value-changed",G_CALLBACK(var_spin_high_cb),(gpointer *)i);
+        g_signal_connect(var2_spin_high,"value-changed",G_CALLBACK(var_spin_high_cb),(gpointer)(long)i);
       }
 
       break;
index d3d884792fc4a70e653dae7362d1351bd1f7fcd2..0593c8999012eeb745600b3059ce44388cbfb2a8 100644 (file)
--- a/fm_menu.c
+++ b/fm_menu.c
@@ -32,15 +32,24 @@ static GtkWidget *dialog=NULL;
 
 static GtkWidget *last_band;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 gboolean emp_cb (GtkWidget *widget, gpointer data) {
   if(gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
     pre_emphasize=1;
@@ -58,7 +67,9 @@ void fm_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - FM");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -76,7 +87,7 @@ void fm_menu(GtkWidget *parent) {
   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 FM");
+  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);
 
index 8843a85d7515f4a8868abe8ca8e1a3fb96c0bdaf..1c0627e214831ae6aaed20f841b1bf70a42233d1 100644 (file)
--- a/freedv.c
+++ b/freedv.c
@@ -2,8 +2,17 @@
 #include <stdlib.h>
 #include <string.h>
 #include <codec2/freedv_api.h>
+#include <wdsp.h>
 
+#include "freedv.h"
+#include "audio_waterfall.h"
+#include "channel.h"
+#include "property.h"
 #include "radio.h"
+#include "receiver.h"
+#include "transmitter.h"
+
+#define min(x,y) (x<y?x:y)
 
 static struct freedv* modem;
 
@@ -22,10 +31,66 @@ int nin;
 int freedv_sync;
 float freedv_snr;
 
-int freedv_tx_text_index=0;
+int freedv_rate;
+int freedv_resample;
+
+int freedv_mode=FREEDV_MODE_1600;
+
+int freedv_sq_enable=1;
+double freedv_snr_sq_threshold=0.0;
+
+double freedv_audio_gain=0.2;
+
+static int initialized=0;
+
+static char *mode_string[]={
+"1600",
+"700",
+"700B",
+"2400A",
+"2400B",
+"800XA",
+"700C"};
+
+char* freedv_get_mode_string() {
+  return mode_string[freedv_mode];
+}
+
+void freedv_save_state() {
+  char name[128];
+  char value[128];
+
+  sprintf(name,"freedv_mode");
+  sprintf(value,"%d",freedv_mode);
+  setProperty(name,value);
+  sprintf(name,"freedv_audio_gain");
+  sprintf(value,"%f",freedv_audio_gain);
+  setProperty(name,value);
+}
+
+void freedv_restore_state() {
+  char name[128];
+  char *value;
+
+  sprintf(name,"freedv_mode");
+  value=getProperty(name);
+  if(value) freedv_mode=atoi(value);
+  sprintf(name,"freedv_audio_gain");
+  value=getProperty(name);
+  if(value) freedv_audio_gain=atof(value);
+}
 
-char freedv_text_data[64];
-int freedv_text_data_index=0;
+void freedv_set_mode(RECEIVER *rx,int m) {
+  if(initialized) {
+    g_mutex_lock(&rx->freedv_mutex);
+    close_freedv(rx);
+    freedv_mode=m;
+    init_freedv(rx);
+    g_mutex_unlock(&rx->freedv_mutex);
+  } else {
+    freedv_mode=m;
+  }
+}
 
 static void text_data(char c) {
   int i;
@@ -33,9 +98,9 @@ static void text_data(char c) {
     c='|';
   }
   for(i=0;i<62;i++) {
-    freedv_text_data[i]=freedv_text_data[i+1];
+    active_receiver->freedv_text_data[i]=active_receiver->freedv_text_data[i+1];
   }
-  freedv_text_data[62]=c;
+  active_receiver->freedv_text_data[62]=c;
 }
 
 static void my_put_next_rx_char(void *callback_state, char c) {
@@ -47,37 +112,86 @@ static void my_put_next_rx_char(void *callback_state, char c) {
 
 
 static char my_get_next_tx_char(void *callback_state){
-  char c=freedv_tx_text_data[freedv_tx_text_index++];
+  char c=transmitter->freedv_text_data[transmitter->freedv_text_index++];
   if(c==0) {
     c=0x0D;
-    freedv_tx_text_index=0;
+    transmitter->freedv_text_index=0;
   }
 //fprintf(stderr,"freedv: my_get_next_tx_char=%c\n",c);
-  text_data(c);
+  //text_data(c);
   return c;
 }
 
-void init_freedv() {
-  int i;
+static void initAnalyzer(RECEIVER *rx,int channel, int buffer_size, int pixels) {
+    int flp[] = {0};
+    double keep_time = 0.1;
+    int n_pixout=1;
+    int spur_elimination_ffts = 1;
+    int data_type = 0;
+    int fft_size = 1024;
+    int window_type = 4;
+    double kaiser_pi = 14.0;
+    int overlap = 0;
+    int clip = 0;
+    int span_clip_l = 0;
+    int span_clip_h = 0;
+    int stitches = 1;
+    int calibration_data_set = 0;
+    double span_min_freq = 0.0;
+    double span_max_freq = 0.0;
+
+    int max_w = fft_size + (int) min(keep_time * (double) rx->fps, keep_time * (double) fft_size * (double) rx->fps);
+
+    SetAnalyzer(channel,
+            n_pixout,
+            spur_elimination_ffts, //number of LO frequencies = number of ffts used in elimination
+            data_type, //0 for real input data (I only); 1 for complex input data (I & Q)
+            flp, //vector with one elt for each LO frequency, 1 if high-side LO, 0 otherwise
+            fft_size, //size of the fft, i.e., number of input samples
+            buffer_size, //number of samples transferred for each OpenBuffer()/CloseBuffer()
+            window_type, //integer specifying which window function to use
+            kaiser_pi, //PiAlpha parameter for Kaiser window
+            overlap, //number of samples each fft (other than the first) is to re-use from the previous
+            clip, //number of fft output bins to be clipped from EACH side of each sub-span
+            span_clip_l, //number of bins to clip from low end of entire span
+            span_clip_h, //number of bins to clip from high end of entire span
+            pixels, //number of pixel values to return.  may be either <= or > number of bins
+            stitches, //number of sub-spans to concatenate to form a complete span
+            calibration_data_set, //identifier of which set of calibration data to use
+            span_min_freq, //frequency at first pixel value8192
+            span_max_freq, //frequency at last pixel value
+            max_w //max samples to hold in input ring buffers
+    );
+
+}
+
+void init_freedv(RECEIVER *rx) {
+  int i, success;
 fprintf(stderr,"init_freedv\n");
 
-  modem=freedv_open(FREEDV_MODE_1600);
+  modem=freedv_open(freedv_mode);
   if(modem==NULL) {
     fprintf(stderr,"freedv_open: modem is null\n");
     return;
   }
 
-  freedv_set_snr_squelch_thresh(modem, -100.0);
-  freedv_set_squelch_en(modem, 1);
+  freedv_set_snr_squelch_thresh(modem, (float)freedv_snr_sq_threshold);
+  freedv_set_squelch_en(modem, freedv_sq_enable);
 
   n_speech_samples = freedv_get_n_speech_samples(modem);
   n_max_modem_samples = freedv_get_n_max_modem_samples(modem);
   n_nom_modem_samples = freedv_get_n_nom_modem_samples(modem);
-fprintf(stderr,"n_speech_samples=%d n_max_modem_samples=%d\n",n_speech_samples, n_max_modem_samples);
+fprintf(stderr,"n_speech_samples=%d n_max_modem_samples=%d n_nom_modem_samples=%d\n",n_speech_samples, n_max_modem_samples,n_nom_modem_samples);
   speech_out = (short*)malloc(sizeof(short)*n_speech_samples);
   demod_in = (short*)malloc(sizeof(short)*n_max_modem_samples);
   speech_in = (short*)malloc(sizeof(short)*n_speech_samples);
   mod_out = (short*)malloc(sizeof(short)*n_nom_modem_samples);
+  //spectrum = (float*)malloc(sizeof(float)*n_nom_modem_samples);
+
+  for(i=0;i<63;i++) {
+    rx->freedv_text_data[i]=' ';
+  }
+  rx->freedv_text_data[63]=0;
 
   nin = freedv_nin(modem);
   rx_samples_in=0;
@@ -86,49 +200,111 @@ fprintf(stderr,"n_speech_samples=%d n_max_modem_samples=%d\n",n_speech_samples,
   //freedv_set_callback_protocol(modem, &my_put_next_rx_proto, NULL, NULL);
   //freedv_set_callback_data(modem, my_datarx, my_datatx, NULL);
 
-  int rate=freedv_get_modem_sample_rate(modem);
-fprintf(stderr,"freedv modem sample rate=%d\n",rate);
+  freedv_rate=freedv_get_modem_sample_rate(modem);
+  freedv_resample=48000/freedv_rate;
+fprintf(stderr,"freedv modem sample nin=%d rate=%d resample=%d\n",nin, freedv_rate, freedv_resample);
 
-  for(i=0;i<63;i++) {
-    freedv_text_data[i]=' ';
+  SetRXAPanelGain1 (rx->id, freedv_audio_gain);
+/*
+  XCreateAnalyzer(CHANNEL_AUDIO, &success, 262144, 1, 1, "");
+  if (success != 0) {
+    fprintf(stderr, "XCreateAnalyzer CHANNEL_AUDIO failed: %d\n" ,success);
   }
-  freedv_text_data[63]=0;
+  initAnalyzer(rx,CHANNEL_AUDIO,n_nom_modem_samples,200);
+
+  audio_waterfall_setup(freedv_rate,1500);
+*/
+
+  initialized=1;
 }
 
-void close_freedv() {
-fprintf(stderr,"freedv_close\n");
+void close_freedv(RECEIVER *rx) {
+fprintf(stderr,"freedv_close rx=%p\n",rx);
+  initialized=0;
   if(modem!=NULL) {
     freedv_close(modem);
   } else {
     fprintf(stderr,"freedv_close: modem is null\n");
   }
+  modem=NULL;
+/*
+  DestroyAnalyzer(CHANNEL_AUDIO);
+*/
+  SetRXAPanelGain1 (rx->id, rx->volume);
 }
 
 int demod_sample_freedv(short sample) {
   int nout=0;
-  demod_in[rx_samples_in]=sample;
-  rx_samples_in++;
-  if(rx_samples_in==nin) {
-    nout=freedv_rx(modem,speech_out,demod_in);
-    nin=freedv_nin(modem);
-    rx_samples_in=0;
-    freedv_get_modem_stats(modem, &freedv_sync, &freedv_snr);
-  } 
+  if(initialized) {
+    demod_in[rx_samples_in]=sample;
+    rx_samples_in++;
+    if(rx_samples_in==nin) {
+      nout=freedv_rx(modem,speech_out,demod_in);
+      nin=freedv_nin(modem);
+      rx_samples_in=0;
+      freedv_get_modem_stats(modem, &freedv_sync, &freedv_snr);
+    } 
+#ifdef AUDIO_WATERFALL
+    if(audio_samples!=NULL) {
+      audio_samples[audio_samples_index]=(float)sample;
+      audio_samples_index++;
+      if(audio_samples_index>=AUDIO_WATERFALL_SAMPLES) {
+        Spectrum(CHANNEL_AUDIO,0,0,audio_samples,audio_samples);
+        audio_samples_index=0;
+      }
+    }
+#endif
+  }
   return nout;
 }
 
 int mod_sample_freedv(short sample) {
+  int i;
   int nout=0;
-  speech_in[tx_samples_in]=sample;
-  tx_samples_in++;
-  if(tx_samples_in==n_speech_samples) {
-    freedv_tx(modem,mod_out,speech_in);
-    tx_samples_in=0;
-    nout=n_nom_modem_samples;
-  } 
+  if(initialized) {
+    speech_in[tx_samples_in]=sample;
+    tx_samples_in++;
+    if(tx_samples_in==n_speech_samples) {
+      freedv_tx(modem,mod_out,speech_in);
+      tx_samples_in=0;
+      nout=n_nom_modem_samples;
+#ifdef AUDIO_WATERFALL
+      for(i=0;i<n_nom_modem_samples;i++) {
+        audio_samples[audio_samples_index]=(float)mod_out[i];
+        audio_samples_index++;
+        if(audio_samples_index>=AUDIO_WATERFALL_SAMPLES) {
+          Spectrum(CHANNEL_AUDIO,0,0,audio_samples,audio_samples);
+          audio_samples_index=0;
+        }
+      }
+#endif
+    } 
+  }
   return nout;
 }
 
 void freedv_reset_tx_text_index() {
-  freedv_tx_text_index=0;
+  transmitter->freedv_text_index=0;
+}
+
+void freedv_set_sq_enable(int state) {
+fprintf(stderr,"freedv_set_sq_enable: state=%d modem=%p\n", state,modem);
+  freedv_sq_enable=state;
+  if(modem!=NULL) {
+    freedv_set_squelch_en(modem, freedv_sq_enable);
+  }
+}
+
+void freedv_set_sq_threshold(double threshold) {
+  freedv_snr_sq_threshold=threshold;
+  if(modem!=NULL) {
+    freedv_set_snr_squelch_thresh(modem, freedv_snr_sq_threshold);
+  }
+}
+
+void freedv_set_audio_gain(double gain) {
+  freedv_audio_gain=gain;
+  if(modem!=NULL) {
+    SetRXAPanelGain1 (active_receiver->id, freedv_audio_gain);
+  }
 }
index 36bdd2b3cb092964f2df21d0d05044fc923bb8fe..26fe515e58d26a66a563c1ac7e33175aed825813 100644 (file)
--- a/freedv.h
+++ b/freedv.h
@@ -20,6 +20,8 @@
 #ifndef _FREEDV_H
 #define _FREEDV_H
 
+#include "receiver.h"
+
 extern int n_speech_samples;
 extern int n_max_modem_samples;
 extern short *demod_in;
@@ -30,12 +32,37 @@ extern short *mod_out;
 extern int freedv_sync;
 extern float freedv_snr;
 
+extern int freedv_rate;
+extern int freedv_resample;
+
+extern int freedv_mode;
+
 extern char freedv_text_data[64];
 
-void init_freedv();
-void close_freedv();
-int demod_sample_freedv(short sample);
-int mod_sample_freedv(short sample);
-void reset_freedv_tx_text_index();
+extern int freedv_sq_enable;
+extern double freedv_snr_sq_threshold;
+
+extern double freedv_audio_gain;
+
+extern float *freedv_samples;
+
+extern void freedv_save_state();
+extern void freedv_restore_state();
+extern void init_freedv(RECEIVER *rx);
+extern void close_freedv(RECEIVER *rx);
+extern int demod_sample_freedv(short sample);
+extern int mod_sample_freedv(short sample);
+extern void freedv_reset_tx_text_index();
+extern void freedv_set_mode(RECEIVER *rx,int m);
+extern void init_freedv(RECEIVER *rx);
+extern void close_freedv(RECEIVER *rx);
+extern int demod_sample_freedv(short sample);
+extern int mod_sample_freedv(short sample);
+extern void freedv_reset_tx_text_index();
+extern void freedv_set_mode(RECEIVER *rx,int m);
+extern void freedv_set_sq_enable(int state);
+extern void freedv_set_sq_threshold(double threshold);
+extern void freedv_set_audio_gain(double gain);
+extern char* freedv_get_mode_string();
 
 #endif
index 4ffbbdfb88ce39f27647aa229c3aceb7dfc75080..bceb94808f55771a6e25d30a686a631be9e268f2 100644 (file)
@@ -1,4 +1,5 @@
-/* Copyright (C)
+/*
+* Copyright (C)
 * 2015 - John Melton, G0ORX/N6LYT
 *
 * This program is free software; you can redistribute it and/or
 #include <gtk/gtk.h>
 #include <semaphore.h>
 #include <stdio.h>
+#include <stdint.h>
 #include <string.h>
+#include <codec2/freedv_api.h>
+#include <wdsp.h>
 
 #include "new_menu.h"
 #include "freedv_menu.h"
 #include "freedv.h"
 #include "radio.h"
+#include "receiver.h"
+#include "vfo.h"
+#include "ext.h"
 
 static GtkWidget *parent_window=NULL;
 
@@ -33,17 +40,47 @@ static GtkWidget *menu_b=NULL;
 
 static GtkWidget *dialog=NULL;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 freedv_text_changed_cb(GtkWidget *widget, gpointer data) {
-  strcpy(freedv_tx_text_data,gtk_entry_get_text(GTK_ENTRY(widget)));
+  strcpy(transmitter->freedv_text_data,gtk_entry_get_text(GTK_ENTRY(widget)));
+}
+
+static void enable_cb(GtkWidget *widget, gpointer data) {
+  set_freedv(gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)));
+}
+
+static void sq_enable_cb(GtkWidget *widget, gpointer data) {
+  freedv_set_sq_enable(gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)));
+}
+
+static void sq_spin_cb (GtkWidget *widget, gpointer data) {
+  freedv_set_sq_threshold(gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget)));
+}
+
+static void audio_spin_cb (GtkWidget *widget, gpointer data) {
+  freedv_set_audio_gain(gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget)));
+}
+
+static void mode_cb(GtkWidget *widget, gpointer data) {
+  int mode=(uintptr_t)data;
+  freedv_set_mode(active_receiver,mode);
 }
 
 void freedv_menu(GtkWidget *parent) {
@@ -53,7 +90,9 @@ void freedv_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - FreeDV");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -71,19 +110,84 @@ void freedv_menu(GtkWidget *parent) {
   gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
   gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
 
-  GtkWidget *close_b=gtk_button_new_with_label("Close FreeDV");
+  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);
 
-  GtkWidget *freedv_text_label=gtk_label_new("FreeDV Text Message: ");
+  GtkWidget *freedv_text_label=gtk_label_new("Tx Message: ");
   gtk_grid_attach(GTK_GRID(grid),freedv_text_label,0,1,1,1);
 
   GtkWidget *freedv_text=gtk_entry_new();
-  gtk_entry_set_text(GTK_ENTRY(freedv_text),freedv_tx_text_data);
-  gtk_grid_attach(GTK_GRID(grid),freedv_text,0,2,2,1);
+  gtk_entry_set_text(GTK_ENTRY(freedv_text),transmitter->freedv_text_data);
+  gtk_grid_attach(GTK_GRID(grid),freedv_text,1,1,3,1);
   g_signal_connect(freedv_text,"changed",G_CALLBACK(freedv_text_changed_cb),NULL);
 
 
+  GtkWidget *enable=gtk_check_button_new_with_label("Enable FreeDV");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (enable), active_receiver->freedv);
+  gtk_grid_attach(GTK_GRID(grid),enable,0,2,1,1);
+  g_signal_connect(enable,"toggled",G_CALLBACK(enable_cb),NULL);
+
+  GtkWidget *sq_enable=gtk_check_button_new_with_label("SNR Squelch Enable (dB)");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sq_enable), freedv_sq_enable);
+  gtk_grid_attach(GTK_GRID(grid),sq_enable,1,2,1,1);
+  g_signal_connect(sq_enable,"toggled",G_CALLBACK(sq_enable_cb),NULL);
+
+  GtkWidget *sq_spin=gtk_spin_button_new_with_range(-5.0,15.0,0.5);
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON(sq_spin),freedv_snr_sq_threshold);
+  gtk_grid_attach(GTK_GRID(grid),sq_spin,2,2,1,1);
+  g_signal_connect(sq_spin,"value-changed",G_CALLBACK(sq_spin_cb),NULL);
+
+  GtkWidget *mode_1600=gtk_radio_button_new_with_label(NULL,"1600");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mode_1600), freedv_mode==FREEDV_MODE_1600);
+  gtk_widget_show(mode_1600);
+  gtk_grid_attach(GTK_GRID(grid),mode_1600,0,4,1,1);
+  g_signal_connect(mode_1600,"pressed",G_CALLBACK(mode_cb),(gpointer *)FREEDV_MODE_1600);
+
+  GtkWidget *mode_700=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(mode_1600),"700");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mode_700), freedv_mode==FREEDV_MODE_700);
+  gtk_widget_show(mode_700);
+  gtk_grid_attach(GTK_GRID(grid),mode_700,1,4,1,1);
+  g_signal_connect(mode_700,"pressed",G_CALLBACK(mode_cb),(gpointer *)FREEDV_MODE_700);
+
+  GtkWidget *mode_700B=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(mode_700),"700B");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mode_700B), freedv_mode==FREEDV_MODE_700B);
+  gtk_widget_show(mode_700B);
+  gtk_grid_attach(GTK_GRID(grid),mode_700B,2,4,1,1);
+  g_signal_connect(mode_700B,"pressed",G_CALLBACK(mode_cb),(gpointer *)FREEDV_MODE_700B);
+
+  GtkWidget *mode_2400A=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(mode_700B),"2400A");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mode_2400A), freedv_mode==FREEDV_MODE_2400A);
+  gtk_widget_show(mode_2400A);
+  gtk_grid_attach(GTK_GRID(grid),mode_2400A,0,5,1,1);
+  g_signal_connect(mode_2400A,"pressed",G_CALLBACK(mode_cb),(gpointer *)FREEDV_MODE_2400A);
+
+  GtkWidget *mode_2400B=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(mode_2400A),"2400B");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mode_2400B), freedv_mode==FREEDV_MODE_2400B);
+  gtk_widget_show(mode_2400B);
+  gtk_grid_attach(GTK_GRID(grid),mode_2400B,1,5,1,1);
+  g_signal_connect(mode_2400B,"pressed",G_CALLBACK(mode_cb),(gpointer *)FREEDV_MODE_2400B);
+
+  GtkWidget *mode_800XA=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(mode_2400B),"800XA");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mode_800XA), freedv_mode==FREEDV_MODE_800XA);
+  gtk_widget_show(mode_800XA);
+  gtk_grid_attach(GTK_GRID(grid),mode_800XA,2,5,1,1);
+  g_signal_connect(mode_800XA,"pressed",G_CALLBACK(mode_cb),(gpointer *)FREEDV_MODE_800XA);
+
+  GtkWidget *mode_700C=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(mode_800XA),"700C");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mode_700C), freedv_mode==FREEDV_MODE_700C);
+  gtk_widget_show(mode_700C);
+  gtk_grid_attach(GTK_GRID(grid),mode_700C,3,5,1,1);
+  g_signal_connect(mode_700C,"pressed",G_CALLBACK(mode_cb),(gpointer *)FREEDV_MODE_700C);
+
+  GtkWidget *freedv_audio_label=gtk_label_new("Audio Gain: ");
+  gtk_grid_attach(GTK_GRID(grid),freedv_audio_label,0,6,1,1);
+
+  GtkWidget *audio_spin=gtk_spin_button_new_with_range(0.0,1.0,0.1);
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON(audio_spin),freedv_audio_gain);
+  gtk_grid_attach(GTK_GRID(grid),audio_spin,1,6,1,1);
+  g_signal_connect(audio_spin,"value-changed",G_CALLBACK(audio_spin_cb),NULL);
+
   gtk_container_add(GTK_CONTAINER(content),grid);
 
   sub_menu=dialog;
index 987de813da3194af31bb21ef5d7405c97ffd880e..004d984827410e8feeb598b532ea5f1b4194c7bb 100644 (file)
 */
 
 #include <gtk/gtk.h>
+#include <ctype.h>
 #include <stdio.h>
-#include <string.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include "new_menu.h"
 #include "band.h"
@@ -29,6 +30,7 @@
 #include "radio.h"
 #include "receiver.h"
 #include "vfo.h"
+#include "button_text.h"
 
 static GtkWidget *parent_window=NULL;
 static GtkWidget *dialog=NULL;
@@ -42,13 +44,22 @@ static char *btn_labels[] = {"1","2","3","4",
                              "HZ","KZ","MZ","CR"
                             };
 
+static void cleanup() {
+  if(dialog!=NULL) {
+    gtk_widget_destroy(dialog);
+    dialog=NULL;
+    sub_menu=NULL;
+  }
+}
+
 static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
-    if(dialog!=NULL) {
-        gtk_widget_destroy(dialog);
-        dialog=NULL;
-        sub_menu=NULL;
-    }
-    return TRUE;
+  cleanup();
+  return TRUE;
+}
+
+static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
+  cleanup();
+  return FALSE;
 }
 
 static gboolean freqent_select_cb (GtkWidget *widget, gpointer data) {
@@ -131,12 +142,12 @@ static gboolean freqent_select_cb (GtkWidget *widget, gpointer data) {
               }
             }
             setFrequency(f);
-            vfo_update(NULL);
+            vfo_update();
       
             set = 1;
         }
     }
-    vfo_update(NULL);
+    vfo_update();
 }
 
 static GtkWidget *last_mode;
@@ -148,7 +159,11 @@ void freqent_menu(GtkWidget *parent) {
 
     dialog=gtk_dialog_new();
     gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-    gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+    //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+    char title[64];
+    sprintf(title,"piHPSDR - Frequency Entry (RX %d VFO %s)",active_receiver->id,active_receiver->id==0?"A":"B");
+    gtk_window_set_title(GTK_WINDOW(dialog),title);
+    g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
     GdkRGBA color;
     color.red = 1.0;
@@ -166,7 +181,7 @@ void freqent_menu(GtkWidget *parent) {
     gtk_grid_set_column_spacing (GTK_GRID(grid),4);
     gtk_grid_set_row_spacing (GTK_GRID(grid),4);
 
-    GtkWidget *close_b=gtk_button_new_with_label("Close FreqEntry");
+    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);
 
@@ -175,11 +190,6 @@ void freqent_menu(GtkWidget *parent) {
     gtk_misc_set_alignment (GTK_MISC (label), 1, .5);
     gtk_grid_attach(GTK_GRID(grid),label,1,0,2,1);
 
-    char label[32];
-    sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B");
-    GtkWidget *rx_label=gtk_label_new(label);
-    gtk_grid_attach(GTK_GRID(grid),rx_label,3,0,1,1);
-
     GtkWidget *step_rb=NULL;
     for (i=0; i<16; i++) {
         GtkWidget *b=gtk_button_new_with_label(btn_labels[i]);
index 04a89f2823c94d0afe4fcf881a522c4d2cca2ed5..98cbdf99631f44759a777babc9ce0d55ce18e4c9 100644 (file)
@@ -82,11 +82,8 @@ struct frequency_info frequencyInfo[]=
 
         {5000000LL, 5000000LL, "WWV",                              bandWWV,FALSE}, 
 
-        {5330500LL, 5330500LL, "60M Channel 1",                    band60, TRUE},
-        {5346500LL, 5346500LL, "60M Channel 2",                    band60, TRUE},
-        {5366500LL, 5366500LL, "60M Channel 3",                    band60, TRUE},
-        {5371500LL, 5371500LL, "60M Channel 4",                    band60, TRUE},
-        {5403500LL, 5403500LL, "60M Channel 5",                    band60, TRUE},
+        {5261250LL, 5408000LL, "60M",                              band60, TRUE},
+        {5261250LL, 5408000LL, "60M",                              band60, FALSE},
 
         {5900000LL, 6200000LL, "49M Short Wave",                   bandGen,FALSE}, 
 
@@ -396,23 +393,46 @@ struct frequency_info frequencyInfo[]=
 * 
 * @return 
 */
-char* getFrequencyInfo(long long frequency) {
+char* getFrequencyInfo(long long frequency,int filter_low,int filter_high) {
 
     char* result=outOfBand;
 
+    long long flow=frequency+(long long)filter_low;
+    long long fhigh=frequency+(long long)filter_high;
+
+//fprintf(stderr,"getFrequency: frequency=%lld filter_low=%d filter_high=%d flow=%lld fhigh=%lld\n",
+//    frequency,filter_low,filter_high,flow,fhigh);
+
     info=frequencyInfo;
 
     while(info->minFrequency!=0) {
-        if(frequency<info->minFrequency) {
+        if(flow<info->minFrequency) {
             info=0;
             break;
-        } else if(frequency>=info->minFrequency && frequency<=info->maxFrequency) {
-            result=info->info;
+        } else if(flow>=info->minFrequency && fhigh<=info->maxFrequency) {
+            if(info->band==band60) {
+              int i;
+              for(i=0;i<channel_entries;i++) {
+//fprintf(stderr,"channel: %d frequency=%lld width=%lld\n",i,band_channels_60m[i].frequency,band_channels_60m[i].width);
+                if(flow>=band_channels_60m[i].frequency && fhigh<=(band_channels_60m[i].frequency+band_channels_60m[i].width)) {
+                  result=info->info;
+                  break;
+                }
+              }
+              if(i>=channel_entries) {
+                info++;
+              }
+              break;
+            } else {
+              result=info->info;
+            }
             break;
         }
         info++;
     }
 
+//fprintf(stderr,"info: %s tx=%d\n", info->info, info->transmit);
+
     return result;
 }
 
@@ -425,6 +445,7 @@ char* getFrequencyInfo(long long frequency) {
 * @return 
 */
 int getBand(long long frequency) {
+
     int result=bandGen;
 
     info=frequencyInfo;
index 9c9199f008d7fdb2002c8baeb26bcc83b06bdfc6..6dcb1433a49690319f4f265938737b8192894403 100644 (file)
@@ -40,8 +40,8 @@ struct frequency_info {
     };
 
 
-char* getFrequencyInfo(long long frequency);
-int getBand(long long frequency);
-int canTransmit();
+extern char* getFrequencyInfo(long long frequency,int filter_low,int filter_high);
+extern int getBand(long long frequency);
+extern int canTransmit();
 
 #endif
index 185bc896467ee054a8654fb7fb5e64c0f415bde7..9645c55433a5b9174a65914b8c20ced4301a2e79 100644 (file)
@@ -35,15 +35,24 @@ static GtkWidget *menu_b=NULL;
 
 static GtkWidget *dialog=NULL;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 vfo_divisor_value_changed_cb(GtkWidget *widget, gpointer data) {
   vfo_encoder_divisor=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
 }
@@ -146,7 +155,9 @@ void general_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - General");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -163,7 +174,7 @@ void general_menu(GtkWidget *parent) {
   //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
   //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
 
-  GtkWidget *close_b=gtk_button_new_with_label("Close General");
+  GtkWidget *close_b=gtk_button_new_with_label("Close");
   g_signal_connect (close_b, "button_press_event", G_CALLBACK(close_cb), NULL);
   gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
 
diff --git a/gpio.c b/gpio.c
index 67c756f9016ecbbb579fe32a10ae00d15a38c6fd..ffed31e6f38440110c5c9a433c0fe256fe64fc1d 100644 (file)
--- a/gpio.c
+++ b/gpio.c
@@ -220,7 +220,9 @@ char *encoder_string[] = {
 "CW SPEED",
 "CW FREQUENCY",
 "PANADAPTER HIGH",
-"PANADAPTER LOW"
+"PANADAPTER LOW",
+"SQUELCH",
+"COMP"
 };
 
 static int mox_pressed(void *data) {
@@ -397,7 +399,6 @@ static void moxAlert() {
     int level1=digitalRead(MOX_BUTTON);
     usleep(20000);
     int level2=digitalRead(MOX_BUTTON);
-fprintf(stderr,"moxAlert: level1=%d level2=%d\n",level1,level2);
     if(level1==0 && level2==0) {
       g_idle_add(mox_pressed,(gpointer)NULL);
     }
@@ -962,7 +963,7 @@ static encoder_changed(int action,int pos) {
       if(protocol==NEW_PROTOCOL) {
         schedule_high_priority();
       }
-      vfo_update(NULL);
+      vfo_update();
       break;
     case ENCODER_CW_SPEED:
       value=(double)cw_keyer_speed;
@@ -973,7 +974,7 @@ static encoder_changed(int action,int pos) {
         value=60.0;
       }
       cw_keyer_speed=(int)value;
-      vfo_update(NULL);
+      vfo_update();
       break;
     case ENCODER_CW_FREQUENCY:
       value=(double)cw_keyer_sidetone_frequency;
@@ -984,7 +985,7 @@ static encoder_changed(int action,int pos) {
         value=1000.0;
       }
       cw_keyer_sidetone_frequency=(int)value;
-      vfo_update(NULL);
+      vfo_update();
       break;
     case ENCODER_PANADAPTER_HIGH:
       value=(double)active_receiver->panadapter_high;
@@ -996,6 +997,28 @@ static encoder_changed(int action,int pos) {
       value+=(double)pos;
       active_receiver->panadapter_low=(int)value;
       break;
+    case ENCODER_SQUELCH:
+      value=active_receiver->squelch;
+      value+=(double)pos;
+      if(value<0.0) {
+        value=0.0;
+      } else if(value>100.0) {
+        value=100.0;
+      }
+      active_receiver->squelch=value;
+      set_squelch(active_receiver);
+      break;
+    case ENCODER_COMP:
+      value=(double)transmitter->compressor_level;
+      value+=(double)pos;
+      if(value<0.0) {
+        value=0.0;
+      } else if(value>20.0) {
+        value=20.0;
+      }
+      transmitter->compressor_level=(int)value;
+      set_compression(transmitter);
+      break;
   }
 }
 
diff --git a/gpio.h b/gpio.h
index e6fd12046bce1fb48a458a76d607730f3839a6ad..2aa643a025f529aa858ac4b70841ba89507502f8 100644 (file)
--- a/gpio.h
+++ b/gpio.h
@@ -17,8 +17,8 @@
 *
 */
 
-#ifndef GPIO_H
-#define GPIO_H
+#ifndef _GPIO_H
+#define _GPIO_H
 
 enum {
   ENCODER_AF_GAIN=0,
@@ -26,18 +26,20 @@ enum {
   ENCODER_ATTENUATION,
   ENCODER_MIC_GAIN,
   ENCODER_DRIVE,
-  ENCODER_TUNE_DRIVE,
+//  ENCODER_TUNE_DRIVE,
   ENCODER_RIT,
   ENCODER_CW_SPEED,
   ENCODER_CW_FREQUENCY,
   ENCODER_PANADAPTER_HIGH,
-  ENCODER_PANADAPTER_LOW
+  ENCODER_PANADAPTER_LOW,
+  ENCODER_SQUELCH,
+  ENCODER_COMP,
+  ENCODER_LAST
 };
 
 
-#define ENCODER_LAST ENCODER_PANADAPTER_LOW
 
-extern char *encoder_string[ENCODER_LAST+1];
+extern char *encoder_string[ENCODER_LAST];
 
 extern int e1_encoder_action;
 extern int e2_encoder_action;
index 8b054aef2847cbfdc2f616a693f0683d834998d6..9cc2bb28fc1fc6857afa5586f7f65fdb2f20ff87 100644 (file)
@@ -774,7 +774,7 @@ static int vfo_encoder_changed(void *data) {
     //entry->frequency=entry->frequency+(pos*step);
     //setFrequency(entry->frequency);
     setFrequency(entry->frequency+ddsOffset+(pos*step));
-    vfo_update(NULL);
+    vfo_update();
   }
   free(data);
   return 0;
diff --git a/i2c.c b/i2c.c
index d33dbec12d4bbf5ffb1a92d518d0bbcf79dcfddb..fac927a73af3753af40016cf39d97b7524c46b5c 100644 (file)
--- a/i2c.c
+++ b/i2c.c
@@ -6,7 +6,6 @@
 #include <linux/i2c-dev.h>
 #include <sys/ioctl.h>
 #include <fcntl.h>
-#include <pthread.h>
 
 #include <gtk/gtk.h>
 #include "i2c.h"
 #include "radio.h"
 #include "toolbar.h"
 #include "vfo.h"
+#include "ext.h"
 
 #define I2C_DEVICE "/dev/i2c-1"
 #define ADDRESS_1 0X20
 #define ADDRESS_2 0X23
 
-//static pthread_t i2c_thread_id;
-static GThread *i2c_thread_id;
-
 static int write_byte_data(unsigned char addr,unsigned char reg, unsigned char data) {
   int fd;
   int rc;
@@ -54,7 +51,7 @@ static unsigned char read_byte_data(unsigned char addr,unsigned char reg) {
   int rc;
 
   if((fd=open(I2C_DEVICE, O_RDWR))<0) {
-    fprintf(stderr,"c$cannot open %s: %s\n",I2C_DEVICE,strerror(errno));
+    fprintf(stderr,"cannot open %s: %s\n",I2C_DEVICE,strerror(errno));
     exit(1);
   }
 
@@ -74,149 +71,121 @@ static unsigned char read_byte_data(unsigned char addr,unsigned char reg) {
   return rc;
 }
 
+static unsigned int read_word_data(unsigned char addr,unsigned char reg) {
+  int fd;
+  int rc;
+
+  if((fd=open(I2C_DEVICE, O_RDWR))<0) {
+    fprintf(stderr,"c$cannot open %s: %s\n",I2C_DEVICE,strerror(errno));
+    exit(1);
+  }
+
+  if(ioctl(fd,I2C_SLAVE,addr)<0) {
+    fprintf(stderr,"cannot aquire access to I2C device at 0x%x\n",addr);
+    exit(1);
+  }
+
+  rc=i2c_smbus_read_word_data(fd,reg);
+  if(rc<0) {
+    fprintf(stderr,"i2c_smbus_read_word_data failed: 0x%2X: %s\n",reg,strerror(errno));
+    exit(1);
+  }
+
+  close(fd);
+
+  return rc;
+}
+
+
 static void frequencyStep(int pos) {
-  BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
-  setFrequency(entry->frequency+ddsOffset+(pos*step));
-  vfo_update(NULL);
+  vfo_step(pos);
 }
 
-static void *i2c_thread(void *arg) {
-  int rc_1_a;
-  int rc_1_b;
-  int prev_rc_1_a=0;
-  int prev_rc_1_b=0;
-  int rc_2_a;
-  int rc_2_b;
-  int prev_rc_2_a=0;
-  int prev_rc_2_b=0;
-
-  while(1) {
-    rc_1_a=read_byte_data(ADDRESS_1,0x12);
-    if(rc_1_a!=0 && rc_1_a!=prev_rc_1_a) {
-      fprintf(stderr,"Dev 1: GPIOA: 0x%02X\n",rc_1_a);
-      switch(rc_1_a) {
-        case 0x01:
-          g_idle_add(band_update,(void *)band160);
-          break;
-        case 0x02:
-          g_idle_add(band_update,(void *)band80);
-          break;
-        case 0x04:
-          g_idle_add(band_update,(void *)band60);
-          break;
-        case 0x08:
-          g_idle_add(band_update,(void *)band40);
-          break;
-        case 0x10:
-          g_idle_add(band_update,(void *)band30);
-          break;
-        case 0x20:
-          g_idle_add(band_update,(void *)band20);
-          break;
-        case 0x40:
-          g_idle_add(band_update,(void *)band17);
-          break;
-        case 0x80:
-          g_idle_add(band_update,(void *)band15);
-          break;
-      }
-    }
-    prev_rc_1_a=rc_1_a;
-
-    rc_1_b=read_byte_data(ADDRESS_1,0x13);
-    if(rc_1_b!=0 && rc_1_b!=prev_rc_1_b) {
-      fprintf(stderr,"Dev 1: GPIOB: 0x%02X\n",rc_1_b);
-      switch(rc_1_b) {
-        case 0x01:
-          g_idle_add(band_update,(void *)band12);
-          break;
-        case 0x02:
-          g_idle_add(band_update,(void *)band10);
-          break;
-        case 0x04:
-          g_idle_add(band_update,(void *)band6);
-          break;
-        case 0x08:
-          g_idle_add(band_update,(void *)bandGen);
-          break;
-        case 0x10:
-          frequencyStep(+1);
-          break;
-        case 0x20:
-          break;
-        case 0x40:
-          break;
-        case 0x80:
-          frequencyStep(-1);
-          break;
-      }
-    }
-    prev_rc_1_b=rc_1_b;
-
-    rc_2_a=read_byte_data(ADDRESS_2,0x12);
-    if(rc_2_a!=0 && rc_2_a!=prev_rc_2_a) {
-      fprintf(stderr,"Dev 2: GPIOA: 0x%02X\n",rc_2_a);
-      switch(rc_2_a) {
-        case 0x01:
-          break;
-        case 0x02:
-          mox_cb(NULL,NULL);
-          break;
-        case 0x04:
-          tune_cb(NULL,NULL);
-          break;
-        case 0x08:
-          break;
-        case 0x10:
-          break;
-        case 0x20:
-          break;
-        case 0x40:
-          break;
-        case 0x80:
-          break;
+void i2c_interrupt() {
+  int flags;
+  int ints;
+
+  do {
+    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) {
+        switch(ints) {
+          case 0x0001:
+            g_idle_add(ext_mox_update,NULL);
+            break;
+          case 0x0002:
+            g_idle_add(ext_tune_update,NULL);
+            break;
+          case 0x0004:
+            g_idle_add(ext_band_update,NULL);
+            break;
+          case 0x0008:
+            g_idle_add(ext_band_update,(void *)band40);
+            break;
+          case 0x0010:
+            g_idle_add(ext_band_update,(void *)band30);
+            break;
+          case 0x0020:
+            g_idle_add(ext_band_update,(void *)band20);
+            break;
+          case 0x0040:
+            g_idle_add(ext_band_update,(void *)band17);
+            break;
+          case 0x0080:
+            g_idle_add(ext_band_update,(void *)band15);
+            break;
+          case 0x0100:
+            g_idle_add(ext_band_update,(void *)band12);
+            break;
+          case 0x0200:
+            g_idle_add(ext_band_update,(void *)band10);
+            break;
+          case 0x0400:
+            g_idle_add(ext_band_update,(void *)band6);
+            break;
+          case 0x0800:
+            g_idle_add(ext_band_update,(void *)bandGen);
+            break;
+          case 0x1000:
+            g_idle_add(ext_band_update,(void *)band12);
+            break;
+          case 0x2000:
+            g_idle_add(ext_band_update,(void *)band10);
+            break;
+          case 0x4000:
+            g_idle_add(ext_band_update,(void *)band6);
+            break;
+          case 0x8000:
+            g_idle_add(ext_band_update,(void *)bandGen);
+            break;
+        }
       }
     }
-    prev_rc_2_a=rc_2_a;
-
-    rc_2_b=read_byte_data(ADDRESS_2,0x13);
-    if(rc_2_b!=0 && rc_2_b!=prev_rc_2_b) {
-      fprintf(stderr,"Dev 2: GPIOB: 0x%02X\n",rc_2_b);
-      switch(rc_2_b) {
-        case 0x01:
-          break;
-        case 0x02:
-          break;
-        case 0x04:
-          break;
-        case 0x08:
-          break;
-        case 0x10:
-          break;
-        case 0x20:
-          break;
-        case 0x40:
-          break;
-        case 0x80:
-          break;
-      }
-    }
-    prev_rc_2_b=rc_2_b;
-
-    usleep(200);
-  }
-
+  } while(flags!=0);
 }
 
 void i2c_init() {
 
+  int flags, ints;
+
 fprintf(stderr,"i2c_init\n");
   // setup i2c
-  if(write_byte_data(ADDRESS_1,0x0A,0x22)<0) return;
+  if(write_byte_data(ADDRESS_1,0x0A,0x44)<0) return;
+  if(write_byte_data(ADDRESS_1,0x0B,0x44)<0) return;
 
-  // set GPIOA/B for input
-  if(write_byte_data(ADDRESS_1,0x00,0xFF)<0) return;
-  if(write_byte_data(ADDRESS_1,0x01,0xFF)<0) return;
+  // disable interrupt
+  if(write_byte_data(ADDRESS_1,0x04,0x00)<0) return;
+  if(write_byte_data(ADDRESS_1,0x05,0x00)<0) return;
+
+  // clear defaults
+  if(write_byte_data(ADDRESS_1,0x06,0x00)<0) return;
+  if(write_byte_data(ADDRESS_1,0x07,0x00)<0) return;
+
+  // OLAT
+  if(write_byte_data(ADDRESS_1,0x14,0x00)<0) return;
+  if(write_byte_data(ADDRESS_1,0x15,0x00)<0) return;
 
   // set GPIOA for pullups
   if(write_byte_data(ADDRESS_1,0x0C,0xFF)<0) return;
@@ -226,33 +195,25 @@ fprintf(stderr,"i2c_init\n");
   if(write_byte_data(ADDRESS_1,0x02,0xFF)<0) return;
   if(write_byte_data(ADDRESS_1,0x03,0xFF)<0) return;
 
-  // setup i2c
-  if(write_byte_data(ADDRESS_2,0x0A,0x22)<0) return;
-
   // set GPIOA/B for input
-  if(write_byte_data(ADDRESS_2,0x00,0xFF)<0) return;
-  if(write_byte_data(ADDRESS_2,0x01,0xFF)<0) return;
-
-  // set GPIOA for pullups
-  if(write_byte_data(ADDRESS_2,0x0C,0xFF)<0) return;
-  if(write_byte_data(ADDRESS_2,0x0D,0xFF)<0) return;
-
-  // reverse polarity
-  if(write_byte_data(ADDRESS_2,0x02,0xFF)<0) return;
-  if(write_byte_data(ADDRESS_2,0x03,0xFF)<0) return;
+  if(write_byte_data(ADDRESS_1,0x00,0xFF)<0) return;
+  if(write_byte_data(ADDRESS_1,0x01,0xFF)<0) return;
 
-/*
-  int rc;
-  rc=pthread_create(&i2c_thread_id,NULL,i2c_thread,NULL);
-  if(rc != 0) {
-    fprintf(stderr,"i2c_init: pthread_create failed on i2c_thread: rc=%d\n", rc);
-  }
-*/
-  i2c_thread_id = g_thread_new( "i2c", i2c_thread, NULL);
-  if( ! i2c_thread_id )
-  {
-    fprintf(stderr,"g_thread_new failed on i2c_thread\n");
-  }
+  // INTCON
+  if(write_byte_data(ADDRESS_1,0x08,0x00)<0) return;
+  if(write_byte_data(ADDRESS_1,0x09,0x00)<0) return;
 
+  // setup for an MCP23017 interrupt
+  if(write_byte_data(ADDRESS_1,0x04,0xFF)<0) return;
+  if(write_byte_data(ADDRESS_1,0x05,0xFF)<0) return;
 
+  // flush any interrupts
+  do {
+    flags=read_word_data(ADDRESS_1,0x0E);
+    if(flags) {
+      ints=read_word_data(ADDRESS_1,0x10);
+      fprintf(stderr,"flush interrupt: flags=%04X ints=%04X\n",flags,ints);
+    }
+  } while(flags!=0);
+  
 }
diff --git a/i2c.h b/i2c.h
index 14ec8860887759cebf5bbfd5afc8b0fa42929f56..e06808d7e2fe88732d72d4a51d47e57ebeb1f2cb 100644 (file)
--- a/i2c.h
+++ b/i2c.h
@@ -1,2 +1,3 @@
 
 void i2c_init();
+void i2c_interrupt();
diff --git a/led.c b/led.c
index 00d656129bc22c712ea6d677ea30b54f1687564a..98525ba65e0cd835efe0a05329fc85d5f6aca56e 100644 (file)
--- a/led.c
+++ b/led.c
 
 #include <gtk/gtk.h>
 
-static GtkWidget *led;
-
-static double red=0.0;
-static double green=1.0;
-static double blue=0.0;
-
-
-static gboolean draw_cb (GtkWidget *widget, cairo_t *cr, gpointer data) {
-  cairo_set_source_rgb(cr, red, green, blue);
+static gboolean draw_led_cb (GtkWidget *widget, cairo_t *cr, gpointer data) {
+  GdkRGBA *color=(GdkRGBA *)data;
+//fprintf(stderr,"draw_led_cb: %p color=%p r=%f g=%f b=%f\n",widget,color,color->red,color->green,color->blue);
+  cairo_set_source_rgb(cr, color->red, color->green, color->blue);
   cairo_paint(cr);      
   return FALSE;
 }
 
-void led_set_color(double r,double g,double b) {
-  red=r;
-  green=g;
-  blue=b;
+void led_set_color(GtkWidget *led) {
+//fprintf(stderr,"led_set_color: %p\n",led);
   gtk_widget_queue_draw (led);
 }
 
-GtkWidget *create_led(int width,int height) {
-  led=gtk_drawing_area_new();
+GtkWidget *create_led(int width,int height,GdkRGBA *color) {
+  GtkWidget *led=gtk_drawing_area_new();
   gtk_widget_set_size_request(led,width,height);
+  g_signal_connect (led, "draw", G_CALLBACK (draw_led_cb), (gpointer)color);
 
-  g_signal_connect (led, "draw", G_CALLBACK (draw_cb), NULL);
-
+fprintf(stderr,"create_led: %p: color=%p\n",led,color);
   return led;
 }
diff --git a/led.h b/led.h
index 905ef2254707c1cc2a287b1fee601d6af1e3fac4..fef24a6c1a2ca03335ded5987e2659962b06e47d 100644 (file)
--- a/led.h
+++ b/led.h
@@ -18,5 +18,6 @@
 */
 
 
-extern GtkWidget *create_led(int width,int height);
-extern void led_set_color(double r,double g,double b);
+extern GtkWidget *create_led(int width,int height,GdkRGBA *color);
+extern void led_set_color(GtkWidget *led);
+
diff --git a/main.c b/main.c
index 8398ffa4261e8e430c4d3bd94197be8e725e4c25..16628ff65eb38330b524066b6af1d58d2939423f 100644 (file)
--- a/main.c
+++ b/main.c
@@ -25,6 +25,7 @@
 #include <string.h>
 #include <semaphore.h>
 #include <sys/socket.h>
+#include <sys/types.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
@@ -48,6 +49,9 @@
 #include "i2c.h"
 #endif
 #include "discovery.h"
+#include "new_protocol.h"
+#include "old_protocol.h"
+#include "ext.h"
 
 struct utsname unameData;
 
@@ -87,34 +91,37 @@ static gint save_cb(gpointer data) {
 static pthread_t wisdom_thread_id;
 
 static void* wisdom_thread(void *arg) {
+fprintf(stderr,"Creating wisdom file: %s\n", (char *)arg);
   status_text("Creating FFTW Wisdom file ...");
   WDSPwisdom ((char *)arg);
   sem_post(&wisdom_sem);
 }
 
 gboolean main_delete (GtkWidget *widget) {
+  if(radio!=NULL) {
 #ifdef GPIO
-  gpio_close();
+    gpio_close();
 #endif
-  switch(protocol) {
-    case ORIGINAL_PROTOCOL:
-      old_protocol_stop();
-      break;
-    case NEW_PROTOCOL:
-      new_protocol_stop();
-      break;
+    switch(protocol) {
+      case ORIGINAL_PROTOCOL:
+        old_protocol_stop();
+        break;
+      case NEW_PROTOCOL:
+        new_protocol_stop();
+        break;
 #ifdef LIMESDR
-    case LIMESDR_PROTOCOL:
-      lime_protocol_stop();
-      break;
+      case LIMESDR_PROTOCOL:
+        lime_protocol_stop();
+        break;
 #endif
 #ifdef RADIOBERRY
-       case RADIOBERRY_PROTOCOL:
-               radioberry_protocol_stop();
-               break;
+      case RADIOBERRY_PROTOCOL:
+        radioberry_protocol_stop();
+        break;
 #endif
+    }
+    radioSaveState();
   }
-  radioSaveState();
   _exit(0);
 }
 
@@ -149,7 +156,7 @@ static int init(void *data) {
       }
   }
 
-  g_idle_add(discovery,NULL);
+  g_idle_add(ext_discovery,NULL);
   return 0;
 }
 
@@ -160,6 +167,7 @@ static void activate_pihpsdr(GtkApplication *app, gpointer data) {
 
   fprintf(stderr,"Build: %s %s\n",build_date,version);
 
+  fprintf(stderr,"GTK+ version %d.%d.%d\n", gtk_major_version, gtk_minor_version, gtk_micro_version);
   uname(&unameData);
   fprintf(stderr,"sysname: %s\n",unameData.sysname);
   fprintf(stderr,"nodename: %s\n",unameData.nodename);
@@ -179,6 +187,18 @@ static void activate_pihpsdr(GtkApplication *app, gpointer data) {
 
 fprintf(stderr,"width=%d height=%d\n", display_width, display_height);
   if(display_width>800 || display_height>480) {
+/*
+    if(display_width>1600) {
+      display_width=1600;
+    } else {
+      display_width=800;
+    }
+    if(display_height>960) {
+      display_height=960;
+    } else {
+      display_height=480;
+    }
+*/
     display_width=800;
     display_height=480;
     full_screen=0;
@@ -193,9 +213,17 @@ fprintf(stderr,"full screen\n");
     gtk_window_fullscreen(GTK_WINDOW(top_window));
   }
   gtk_widget_set_size_request(top_window, display_width, display_height);
-  gtk_window_set_title (GTK_WINDOW (top_window), "pihpsdr");
+  gtk_window_set_title (GTK_WINDOW (top_window), "piHPSDR");
   gtk_window_set_position(GTK_WINDOW(top_window),GTK_WIN_POS_CENTER_ALWAYS);
   gtk_window_set_resizable(GTK_WINDOW(top_window), FALSE);
+  fprintf(stderr,"setting top window icon\n");
+  GError *error;
+  if(!gtk_window_set_icon_from_file (GTK_WINDOW(top_window), "hpsdr.png", &error)) {
+    fprintf(stderr,"Warning: failed to set icon for top_window\n");
+    if(error!=NULL) {
+      fprintf(stderr,"%s\n",error->message);
+    }
+  }
   g_signal_connect (top_window, "delete-event", G_CALLBACK (main_delete), NULL);
   //g_signal_connect (top_window,"draw", G_CALLBACK (main_draw_cb), NULL);
 
@@ -219,7 +247,7 @@ fprintf(stderr,"add image to grid\n");
 fprintf(stderr,"create pi label\n");
   char build[64];
   sprintf(build,"build: %s %s",build_date, version);
-  GtkWidget *pi_label=gtk_label_new("pihpsdr by John Melton g0orx/n6lyt");
+  GtkWidget *pi_label=gtk_label_new("piHPSDR by John Melton g0orx/n6lyt");
   gtk_label_set_justify(GTK_LABEL(pi_label),GTK_JUSTIFY_LEFT);
   gtk_widget_show(pi_label);
 fprintf(stderr,"add pi label to grid\n");
@@ -235,7 +263,7 @@ fprintf(stderr,"add build label to grid\n");
 fprintf(stderr,"create status\n");
   status=gtk_label_new("");
   gtk_label_set_justify(GTK_LABEL(status),GTK_JUSTIFY_LEFT);
-  gtk_widget_override_font(status, pango_font_description_from_string("FreeMono 18"));
+  //gtk_widget_override_font(status, pango_font_description_from_string("FreeMono 18"));
   gtk_widget_show(status);
 fprintf(stderr,"add status to grid\n");
   gtk_grid_attach(GTK_GRID(grid), status, 1, 3, 1, 1);
@@ -261,7 +289,13 @@ int main(int argc,char **argv) {
   GtkApplication *pihpsdr;
   int status;
 
-  pihpsdr=gtk_application_new("org.g0orx.pihpsdr", G_APPLICATION_FLAGS_NONE);
+  char name[1024];
+
+  sprintf(name,"org.g0orx.pihpsdr.pid%d",getpid());
+
+fprintf(stderr,"gtk_application_new: %s\n",name);
+
+  pihpsdr=gtk_application_new(name, G_APPLICATION_FLAGS_NONE);
   g_signal_connect(pihpsdr, "activate", G_CALLBACK(activate_pihpsdr), NULL);
   status=g_application_run(G_APPLICATION(pihpsdr), argc, argv);
 fprintf(stderr,"exiting ...\n");
diff --git a/main.h b/main.h
index 49a76c916ec4a83197f2e6042c552179c87e117f..5a8d6057a4df26521d3c594faa69fcd9fe652a46 100644 (file)
--- a/main.h
+++ b/main.h
 #ifndef _MAIN_H
 #define _MAIN_H
 
-#define DISPLAY_INCREMENT (display_height/32)
-#define MENU_HEIGHT (DISPLAY_INCREMENT*2)
-#define MENU_WIDTH ((display_width/32)*3)
-#define VFO_HEIGHT (DISPLAY_INCREMENT*4)
-#define VFO_WIDTH (display_width-METER_WIDTH-MENU_WIDTH)
-#define METER_HEIGHT (DISPLAY_INCREMENT*4)
-#define METER_WIDTH ((display_width/32)*8)
-#define PANADAPTER_HEIGHT (DISPLAY_INCREMENT*8)
-#define SLIDERS_HEIGHT (DISPLAY_INCREMENT*6)
-#define TOOLBAR_HEIGHT (DISPLAY_INCREMENT*2)
-#define WATERFALL_HEIGHT (display_height-(VFO_HEIGHT+PANADAPTER_HEIGHT+SLIDERS_HEIGHT+TOOLBAR_HEIGHT))
-#ifdef PSK
-#define PSK_WATERFALL_HEIGHT (DISPLAY_INCREMENT*6)
-#define PSK_HEIGHT (display_height-(VFO_HEIGHT+PSK_WATERFALL_HEIGHT+SLIDERS_HEIGHT+TOOLBAR_HEIGHT))
-#endif
-
 #include <sys/utsname.h>
 extern struct utsname unameData;
 
diff --git a/meter.c b/meter.c
index 426d1c09da7969a631430f491854362b1db7bf09..cd6c9cb8390d63c206f9f2bde7ba64e613558612 100644 (file)
--- a/meter.c
+++ b/meter.c
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <math.h>
 
 #include "meter.h"
 #include "wdsp.h"
 #include "radio.h"
 #include "version.h"
 #include "mode.h"
+#include "vox.h"
 #ifdef FREEDV
 #include "freedv.h"
+#include "vfo.h"
 #endif
 #ifdef PSK
 #include "psk.h"
@@ -54,12 +57,13 @@ meter_clear_surface (void)
   cairo_t *cr;
   cr = cairo_create (meter_surface);
 
-  cairo_set_source_rgb (cr, 0, 0, 0);
+  cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
   cairo_fill (cr);
 
   cairo_destroy (cr);
 }
 
+static gboolean
 meter_configure_event_cb (GtkWidget         *widget,
             GdkEventConfigure *event,
             gpointer           data)
@@ -75,7 +79,7 @@ meter_configure_event_cb (GtkWidget         *widget,
   /* Initialize the surface to black */
   cairo_t *cr;
   cr = cairo_create (meter_surface);
-  cairo_set_source_rgb (cr, 0, 0, 0);
+  cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
   cairo_paint (cr);
   cairo_destroy (cr);
 
@@ -88,9 +92,9 @@ meter_configure_event_cb (GtkWidget         *widget,
  */
 static gboolean
 meter_draw_cb (GtkWidget *widget, cairo_t   *cr, gpointer   data) {
-  cairo_set_source_surface (cr, meter_surface, 00);
+  cairo_set_source_surface (cr, meter_surface, 0.0, 0.0);
   cairo_paint (cr);
-  return TRUE;
+  return FALSE;
 }
 
 /*
@@ -182,6 +186,7 @@ meter_press_event_cb (GtkWidget *widget,
 
 
 GtkWidget* meter_init(int width,int height,GtkWidget *parent) {
+  GError *error;
 
 fprintf(stderr,"meter_init: width=%d height=%d\n",width,height);
   meter_width=width;
@@ -216,21 +221,294 @@ void meter_update(int meter_type,double value,double reverse,double exciter,doub
   cairo_t *cr;
   cr = cairo_create (meter_surface);
 
+if(analog_meter) {
+  cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+  cairo_paint (cr);
+
+  cairo_set_font_size(cr, 12);
+
+  switch(meter_type) {
+    case SMETER:
+      {
+      double level=value+(double)get_attenuation();
+      offset=210.0;
+
+      int i;
+      double x;
+      double y;
+      double angle;
+      double radians;
+      double cx=(double)meter_width/2.0;
+      double cy=(double)meter_width/2.0;
+      double radius=cy-20.0;
+
+      cairo_set_line_width(cr, 1.0);
+      cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
+      cairo_arc(cr, cx, cy, radius, 216.0*M_PI/180.0, 324.0*M_PI/180.0);
+      cairo_stroke(cr);
+
+      cairo_set_line_width(cr, 2.0);
+      cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
+      cairo_arc(cr, cx, cy, radius+2, 264.0*M_PI/180.0, 324.0*M_PI/180.0);
+      cairo_stroke(cr);
+
+      cairo_set_line_width(cr, 1.0);
+      cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
+
+      for(i=1;i<10;i++) {
+        angle=((double)i*6.0)+offset;
+        radians=angle*M_PI/180.0;
+
+        if((i%2)==1) {
+          cairo_arc(cr, cx, cy, radius+4, radians, radians);
+          cairo_get_current_point(cr, &x, &y);
+          cairo_arc(cr, cx, cy, radius, radians, radians);
+          cairo_line_to(cr, x, y);
+          cairo_stroke(cr);
+
+          sprintf(sf,"%d",i);
+          cairo_arc(cr, cx, cy, radius+5, radians, radians);
+          cairo_get_current_point(cr, &x, &y);
+          cairo_new_path(cr);
+          x-=4.0;
+          cairo_move_to(cr, x, y);
+          cairo_show_text(cr, sf);
+        } else {
+          cairo_arc(cr, cx, cy, radius+2, radians, radians);
+          cairo_get_current_point(cr, &x, &y);
+          cairo_arc(cr, cx, cy, radius, radians, radians);
+          cairo_line_to(cr, x, y);
+          cairo_stroke(cr);
+        }
+        cairo_new_path(cr);
+      }
+
+      for(i=20;i<=60;i+=20) {
+        angle=((double)i+54.0)+offset;
+        radians=angle*M_PI/180.0;
+        cairo_arc(cr, cx, cy, radius+4, radians, radians);
+        cairo_get_current_point(cr, &x, &y);
+        cairo_arc(cr, cx, cy, radius, radians, radians);
+        cairo_line_to(cr, x, y);
+        cairo_stroke(cr);
+
+        sprintf(sf,"+%d",i);
+        cairo_arc(cr, cx, cy, radius+5, radians, radians);
+        cairo_get_current_point(cr, &x, &y);
+        cairo_new_path(cr);
+        x-=4.0;
+        cairo_move_to(cr, x, y);
+        cairo_show_text(cr, sf);
+        cairo_new_path(cr);
+      }
+
+
+
+      cairo_set_line_width(cr, 1.0);
+      cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
+
+      angle=level+127.0+offset;
+      radians=angle*M_PI/180.0;
+      cairo_arc(cr, cx, cy, radius+8, radians, radians);
+      cairo_line_to(cr, cx, cy);
+      cairo_stroke(cr);
+
+      cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+      sprintf(sf,"%d dBm",(int)level);
+      cairo_move_to(cr, 80, meter_height-2);
+      cairo_show_text(cr, sf);
+
+#ifdef FREEDV
+      if(active_receiver->freedv) {
+        if(freedv_sync) {
+          cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);
+        } else {
+          cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
+        }
+        sprintf(sf,"SNR: %3.2f",freedv_snr);
+        cairo_move_to(cr, 70, meter_height-12);
+        cairo_show_text(cr, sf);
+      }
+#endif
+
+
+      }
+      break;
+    case POWER:
+      {
+      double level=value;
+      offset=220.0;
+
+      int i;
+      double x;
+      double y;
+      double angle;
+      double radians;
+      double cx=(double)meter_width/2.0;
+      double cy=(double)meter_width/2.0;
+      double radius=cy-20.0;
+
+      cairo_set_line_width(cr, 1.0);
+      cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
+      cairo_arc(cr, cx, cy, radius, 220.0*M_PI/180.0, 320.0*M_PI/180.0);
+      cairo_stroke(cr);
+
+      cairo_set_line_width(cr, 1.0);
+      cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
+
+      for(i=0;i<=100;i++) {
+        angle=(double)i+offset;
+        radians=angle*M_PI/180.0;
+
+        switch(i) {
+          //case 5:
+          case 0:
+          case 25:
+          case 50:
+          case 75:
+          case 100:
+            cairo_arc(cr, cx, cy, radius+4, radians, radians);
+            cairo_get_current_point(cr, &x, &y);
+            cairo_arc(cr, cx, cy, radius, radians, radians);
+            cairo_line_to(cr, x, y);
+            cairo_stroke(cr);
+
+            sprintf(sf,"%d",i*2);
+            cairo_arc(cr, cx, cy, radius+5, radians, radians);
+            cairo_get_current_point(cr, &x, &y);
+            cairo_new_path(cr);
+            x-=6.0;
+            cairo_move_to(cr, x, y);
+            cairo_show_text(cr, sf);
+            break;
+          default:
+            if((i%5)==0) {
+              cairo_arc(cr, cx, cy, radius+2, radians, radians);
+              cairo_get_current_point(cr, &x, &y);
+              cairo_arc(cr, cx, cy, radius, radians, radians);
+              cairo_line_to(cr, x, y);
+              cairo_stroke(cr);
+            }
+            break;
+        }
+        cairo_new_path(cr);
+      }
+
+      cairo_set_line_width(cr, 1.0);
+      cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
+
+      if((int)value>max_level || max_count==10) {
+          max_level=(int)value;
+          max_count=0;
+      }
+      max_count++;
+
+      angle=(max_level/2.0)+offset;
+      radians=angle*M_PI/180.0;
+      cairo_arc(cr, cx, cy, radius+8, radians, radians);
+      cairo_line_to(cr, cx, cy);
+      cairo_stroke(cr);
+
+
+      cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+      sprintf(sf,"%d W",(int)max_level);
+      cairo_move_to(cr, 80, meter_height-22);
+      cairo_show_text(cr, sf);
+
+      double swr=(max_level+reverse)/(max_level-reverse);
+      if(swr<0.0) swr=1.0;
+      sprintf(sf,"SWR: %1.1f:1",swr);
+      cairo_move_to(cr, 60, meter_height-12);
+      cairo_show_text(cr, sf);
+
+      sprintf(sf,"ALC: %2.1f dB",alc);
+      cairo_move_to(cr, 60, meter_height-2);
+      cairo_show_text(cr, sf);
+
+
+      }
+      break;
+  }
+
+  if((meter_type==POWER) || (vox_enabled)) {
+    offset=((double)meter_width-100.0)/2.0;
+    double peak=vox_get_peak();
+    peak=peak*100.0;
+    cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);
+    cairo_rectangle(cr, offset, 0.0, peak, 5.0);
+    cairo_fill(cr);
+
+    cairo_select_font_face(cr, "FreeMono",
+                CAIRO_FONT_SLANT_NORMAL,
+                CAIRO_FONT_WEIGHT_BOLD);
+    cairo_set_font_size(cr, 10);
+    cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
+    cairo_move_to(cr, 0.0, 8.0);
+    cairo_show_text(cr, "Mic Lvl");
+    
+
+    cairo_move_to(cr, offset, 0.0);
+    cairo_line_to(cr, offset, 5.0);
+    cairo_stroke(cr);
+    cairo_move_to(cr, offset+50.0, 0.0);
+    cairo_line_to(cr, offset+50.0, 5.0);
+    cairo_stroke(cr);
+    cairo_move_to(cr, offset+100.0, 0.0);
+    cairo_line_to(cr, offset+100.0, 5.0);
+    cairo_stroke(cr);
+    cairo_move_to(cr, offset, 5.0);
+    cairo_line_to(cr, offset+100.0, 5.0);
+    cairo_stroke(cr);
+
+    if(vox_enabled) {
+      cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
+      cairo_move_to(cr,offset+(vox_threshold*100.0),0.0);
+      cairo_line_to(cr,offset+(vox_threshold*100.0),5.0);
+      cairo_stroke(cr);
+    }
+  }
+
+} else {
   // clear the meter
-  cairo_set_source_rgb (cr, 0, 0, 0);
+  cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
   cairo_paint (cr);
 
-  //sprintf(text,"Version: %s %s", build_date, version);
-  sprintf(text,"Version: %s", version);
   cairo_select_font_face(cr, "FreeMono",
                 CAIRO_FONT_SLANT_NORMAL,
                 CAIRO_FONT_WEIGHT_BOLD);
-
-  cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
   cairo_set_font_size(cr, 12);
-  cairo_move_to(cr, 5, 15);
-  cairo_show_text(cr, text);
 
+  cairo_set_line_width(cr, 1.0);
+
+  cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
+  cairo_move_to(cr, 5.0, 15.0);
+  cairo_line_to(cr, 5.0, 5.0);
+  cairo_move_to(cr, 5.0+25.0, 15.0);
+  cairo_line_to(cr, 5.0+25.0, 10.0);
+  cairo_move_to(cr, 5.0+50.0, 15.0);
+  cairo_line_to(cr, 5.0+50.0, 5.0);
+  cairo_move_to(cr, 5.0+75.0, 15.0);
+  cairo_line_to(cr, 5.0+75.0, 10.0);
+  cairo_move_to(cr, 5.0+100.0, 15.0);
+  cairo_line_to(cr, 5.0+100.0, 5.0);
+  cairo_stroke(cr);
+
+  double peak=vox_get_peak();
+  peak=peak*100.0;
+  cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);
+  cairo_rectangle(cr, 5.0, 5.0, peak, 5.0);
+  cairo_fill(cr);
+
+  if(vox_enabled) {
+    cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
+    cairo_move_to(cr,5.0+(vox_threshold*100.0),5.0);
+    cairo_line_to(cr,5.0+(vox_threshold*100.0),15.0);
+    cairo_stroke(cr);
+  }
+
+  cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
+  cairo_move_to(cr, 115.0, 15.0);
+  cairo_show_text(cr, "Mic Level");
 
   if(last_meter_type!=meter_type) {
     last_meter_type=meter_type;
@@ -243,7 +521,7 @@ void meter_update(int meter_type,double value,double reverse,double exciter,doub
     }
   }
 
-  cairo_set_source_rgb(cr, 1, 1, 1);
+  cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
   switch(meter_type) {
     case SMETER:
       // value is dBm
@@ -256,7 +534,7 @@ void meter_update(int meter_type,double value,double reverse,double exciter,doub
         int db=1;
         int i;
         cairo_set_line_width(cr, 1.0);
-        cairo_set_source_rgb(cr, 1, 1, 1);
+        cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
         for(i=0;i<54;i++) {
           cairo_move_to(cr,offset+(double)(i*db),(double)meter_height-10);
           if(i%18==0) {
@@ -267,13 +545,13 @@ void meter_update(int meter_type,double value,double reverse,double exciter,doub
         }
         cairo_stroke(cr);
 
-        cairo_set_font_size(cr, 12);
-        cairo_move_to(cr, offset+(double)(18*db)-3.0, (double)meter_height);
+        cairo_set_font_size(cr, 10);
+        cairo_move_to(cr, offset+(double)(18*db)-3.0, (double)meter_height-1);
         cairo_show_text(cr, "3");
-        cairo_move_to(cr, offset+(double)(36*db)-3.0, (double)meter_height);
+        cairo_move_to(cr, offset+(double)(36*db)-3.0, (double)meter_height-1);
         cairo_show_text(cr, "6");
 
-        cairo_set_source_rgb(cr, 1, 0, 0);
+        cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
         cairo_move_to(cr,offset+(double)(54*db),(double)meter_height-10);
         cairo_line_to(cr,offset+(double)(54*db),(double)(meter_height-20));
         cairo_move_to(cr,offset+(double)(74*db),(double)meter_height-10);
@@ -284,16 +562,16 @@ void meter_update(int meter_type,double value,double reverse,double exciter,doub
         cairo_line_to(cr,offset+(double)(114*db),(double)(meter_height-20));
         cairo_stroke(cr);
 
-        cairo_move_to(cr, offset+(double)(54*db)-3.0, (double)meter_height);
+        cairo_move_to(cr, offset+(double)(54*db)-3.0, (double)meter_height-1);
         cairo_show_text(cr, "9");
-        cairo_move_to(cr, offset+(double)(74*db)-12.0, (double)meter_height);
+        cairo_move_to(cr, offset+(double)(74*db)-12.0, (double)meter_height-1);
         cairo_show_text(cr, "+20");
-        cairo_move_to(cr, offset+(double)(94*db)-9.0, (double)meter_height);
+        cairo_move_to(cr, offset+(double)(94*db)-9.0, (double)meter_height-1);
         cairo_show_text(cr, "+40");
-        cairo_move_to(cr, offset+(double)(114*db)-6.0, (double)meter_height);
+        cairo_move_to(cr, offset+(double)(114*db)-6.0, (double)meter_height-1);
         cairo_show_text(cr, "+60");
 
-        cairo_set_source_rgb(cr, 0, 1, 0);
+        cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);
         cairo_rectangle(cr, offset+0.0, (double)(meter_height-40), (double)((level+127.0)*db), 20.0);
         cairo_fill(cr);
 
@@ -303,7 +581,7 @@ void meter_update(int meter_type,double value,double reverse,double exciter,doub
         }
 
         if(max_level!=0) {
-          cairo_set_source_rgb(cr, 1, 1, 0);
+          cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
           cairo_move_to(cr,offset+(double)((max_level+127.0)*db),(double)meter_height-20);
           cairo_line_to(cr,offset+(double)((max_level+127.0)*db),(double)(meter_height-40));
         }
@@ -323,15 +601,15 @@ void meter_update(int meter_type,double value,double reverse,double exciter,doub
       cairo_show_text(cr, sf);
 
 #ifdef FREEDV
-      if(active_receiver->mode==modeFREEDV) {
+      if(active_receiver->freedv) {
         if(freedv_sync) {
-          cairo_set_source_rgb(cr, 0, 1, 0);
+          cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);
         } else {
-          cairo_set_source_rgb(cr, 1, 0, 0);
+          cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
         }
         cairo_set_font_size(cr, 12);
         sprintf(sf,"SNR: %3.2f",freedv_snr);
-        cairo_move_to(cr, text_location, 30);
+        cairo_move_to(cr, text_location, meter_height-10);
         cairo_show_text(cr, sf);
       }
 #endif
@@ -342,7 +620,7 @@ void meter_update(int meter_type,double value,double reverse,double exciter,doub
       int i;
       offset=5.0;
       cairo_set_line_width(cr, 1.0);
-      cairo_set_source_rgb(cr, 1, 1, 1);
+      cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
       for(i=0;i<11;i++) {
         cairo_move_to(cr,offset+(double)(i*20),(double)meter_height-10);
         if((i%2)==0) {
@@ -356,11 +634,11 @@ void meter_update(int meter_type,double value,double reverse,double exciter,doub
       }
       cairo_stroke(cr);
 
-      cairo_set_source_rgb(cr, 0, 1, 0);
+      cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);
       cairo_rectangle(cr, offset+0.0, (double)(meter_height-40), value*2, 20.0);
       cairo_fill(cr);
 
-      cairo_set_source_rgb(cr, 0, 1, 0);
+      cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);
       cairo_set_font_size(cr, 12);
       sprintf(sf,"Level: %d",(int)value);
       cairo_move_to(cr, 210, 45);
@@ -406,6 +684,7 @@ void meter_update(int meter_type,double value,double reverse,double exciter,doub
       break;
   }
 
+}
   cairo_destroy(cr);
   gtk_widget_queue_draw (meter);
 }
diff --git a/meter.h b/meter.h
index 868dc6ca507580ff7c24bc645a043a575584c1a4..aa98deb82c0c5321e68d179a6ebfb5a53faf8a83 100644 (file)
--- a/meter.h
+++ b/meter.h
@@ -29,7 +29,7 @@
 #endif
 
 
-GtkWidget* meter_init(int width,int height,GtkWidget *parent);
-void meter_update(int meter_type,double value,double reverse,double exciter,double alc);
+extern GtkWidget* meter_init(int width,int height,GtkWidget *parent);
+extern void meter_update(int meter_type,double value,double reverse,double exciter,double alc);
 
 #endif
index e43361d41ef817fe1498cdaf65d2637be67688a8..e962a9743e39cc3796eb5f09d0ecee4c798b7759 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <gtk/gtk.h>
 #include <string.h>
+#include <stdint.h>
 #include <stdlib.h>
 #include <unistd.h>
 
 static GtkWidget *parent_window=NULL;
 static GtkWidget *dialog=NULL;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 smeter_select_cb (GtkWidget *widget, gpointer        data) {
-  smeter=(int)data;
+  smeter=(uintptr_t)data;
 }
 
 static void alc_meter_select_cb (GtkWidget *widget, gpointer        data) {
-  alc=(int)data;
+  alc=(uintptr_t)data;
+}
+
+static void analog_cb(GtkWidget *widget, gpointer data) {
+  analog_meter=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
 }
 
+
 void meter_menu (GtkWidget *parent) {
   parent_window=parent;
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - Meter");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -73,35 +90,40 @@ void meter_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 *analog_b=gtk_check_button_new_with_label("Analog Meter");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (analog_b), analog_meter);
+  gtk_grid_attach(GTK_GRID(grid),analog_b,1,0,1,1);
+  g_signal_connect(analog_b,"toggled",G_CALLBACK(analog_cb),NULL);
+
   GtkWidget *smeter_peak=gtk_radio_button_new_with_label(NULL,"S Meter Peak");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (smeter_peak), smeter==RXA_S_PK);
   gtk_widget_show(smeter_peak);
   gtk_grid_attach(GTK_GRID(grid),smeter_peak,0,1,1,1);
-  g_signal_connect(smeter_peak,"pressed",G_CALLBACK(smeter_select_cb),(gpointer *)RXA_S_PK);
+  g_signal_connect(smeter_peak,"pressed",G_CALLBACK(smeter_select_cb),(gpointer)(long)RXA_S_PK);
 
   GtkWidget *smeter_average=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(smeter_peak),"S Meter Average");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (smeter_average), smeter==RXA_S_AV);
   gtk_widget_show(smeter_average);
   gtk_grid_attach(GTK_GRID(grid),smeter_average,0,2,1,1);
-  g_signal_connect(smeter_average,"pressed",G_CALLBACK(smeter_select_cb),(gpointer *)RXA_S_AV);
+  g_signal_connect(smeter_average,"pressed",G_CALLBACK(smeter_select_cb),(gpointer)(long)RXA_S_AV);
 
   GtkWidget *alc_peak=gtk_radio_button_new_with_label(NULL,"ALC Peak");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (alc_peak), alc==TXA_ALC_PK);
   gtk_widget_show(alc_peak);
   gtk_grid_attach(GTK_GRID(grid),alc_peak,1,1,1,1);
-  g_signal_connect(alc_peak,"pressed",G_CALLBACK(alc_meter_select_cb),(gpointer *)TXA_ALC_PK);
+  g_signal_connect(alc_peak,"pressed",G_CALLBACK(alc_meter_select_cb),(gpointer)(long)TXA_ALC_PK);
 
   GtkWidget *alc_average=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(alc_peak),"ALC Average");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (alc_average), alc==TXA_ALC_AV);
   gtk_widget_show(alc_average);
   gtk_grid_attach(GTK_GRID(grid),alc_average,1,2,1,1);
-  g_signal_connect(alc_average,"pressed",G_CALLBACK(alc_meter_select_cb),(gpointer *)TXA_ALC_AV);
+  g_signal_connect(alc_average,"pressed",G_CALLBACK(alc_meter_select_cb),(gpointer)(long)TXA_ALC_AV);
 
   GtkWidget *alc_gain=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(alc_average),"ALC Gain");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (alc_gain), alc==TXA_ALC_GAIN);
   gtk_widget_show(alc_gain);
   gtk_grid_attach(GTK_GRID(grid),alc_gain,1,3,1,1);
-  g_signal_connect(alc_gain,"pressed",G_CALLBACK(alc_meter_select_cb),(gpointer *)TXA_ALC_GAIN);
+  g_signal_connect(alc_gain,"pressed",G_CALLBACK(alc_meter_select_cb),(gpointer)(long)TXA_ALC_GAIN);
 
   gtk_container_add(GTK_CONTAINER(content),grid);
 
diff --git a/mode.c b/mode.c
index 37bd12b8ab97f32c2b326998f55288950553366e..349d7cafe3d046418770b7b785e34c061d07454c 100644 (file)
--- a/mode.c
+++ b/mode.c
@@ -30,12 +30,8 @@ char *mode_string[]={
   ,"DIGL"
   ,"SAM"
   ,"DRM"
-#ifdef FREEDV
-  ,"FREEDV"
-#endif
 #ifdef PSK
   ,"PSK"
 #endif
 };
 
-//int mode;
diff --git a/mode.h b/mode.h
index ec688105f16e73472c342e7c0fadf1457e2733fd..22ca810915bc1694ce5bd7d07d3defe4f8a403cc 100644 (file)
--- a/mode.h
+++ b/mode.h
 #define modeDIGL 9
 #define modeSAM 10
 #define modeDRM 11
-#ifdef FREEDV
-#ifdef PSK
-#define modeFREEDV 12
-#define modePSK 13
-#define MODES 14
-#else
-#define modeFREEDV 12
-#define MODES 13
-#endif
-#else
 #ifdef PSK
 #define modePSK 12
 #define MODES 13
 #else
 #define MODES 12
 #endif
-#endif
 
 char *mode_string[MODES];
 
-//extern int mode;
 #endif
index de525c607405b375f6fcdb789500bacf06267160..b2c02bb394639bacb7b71ac2645de8c959bacdbc 100644 (file)
@@ -19,6 +19,8 @@
 
 #include <gtk/gtk.h>
 #include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "new_menu.h"
@@ -38,17 +40,26 @@ static GtkWidget *dialog=NULL;
 
 static GtkWidget *last_mode;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 gboolean mode_select_cb (GtkWidget *widget, gpointer        data) {
-  int m=(int)data;
+  int m=(uintptr_t)data;
   set_button_text_color(last_mode,"black");
   last_mode=widget;
   set_button_text_color(last_mode,"orange");
@@ -64,7 +75,11 @@ void mode_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  char title[64];
+  sprintf(title,"piHPSDR - Mode (RX %d VFO %s)",active_receiver->id,active_receiver->id==0?"A":"B");
+  gtk_window_set_title(GTK_WINDOW(dialog),title);
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -82,15 +97,10 @@ void mode_menu(GtkWidget *parent) {
   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 Mode");
+  GtkWidget *close_b=gtk_button_new_with_label("Close");
   g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
   gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
 
-  char label[32];
-  sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B");
-  GtkWidget *rx_label=gtk_label_new(label);
-  gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1);
-
   int mode=vfo[active_receiver->id].mode;
 
   for(i=0;i<MODES;i++) {
@@ -103,7 +113,7 @@ void mode_menu(GtkWidget *parent) {
     }
     gtk_widget_show(b);
     gtk_grid_attach(GTK_GRID(grid),b,i%5,1+(i/5),1,1);
-    g_signal_connect(b,"pressed",G_CALLBACK(mode_select_cb),(gpointer *)i);
+    g_signal_connect(b,"pressed",G_CALLBACK(mode_select_cb),(gpointer)(long)i);
   }
   gtk_container_add(GTK_CONTAINER(content),grid);
 
index 110d3ebf2930ff3c7d22533dd06cfdd1daec3e80..8ab5f888c1152d690b70afe6141b36d684d8c09e 100644 (file)
@@ -30,7 +30,6 @@
 #include <net/if.h>
 #include <netinet/in.h>
 #include <ifaddrs.h>
-#include <pthread.h>
 #include <string.h>
 #include <errno.h>
 
@@ -49,9 +48,7 @@ static struct sockaddr_in discovery_addr;
 
 void new_discover(struct ifaddrs* iface);
 
-//static pthread_t discover_thread_id;
 static GThread *discover_thread_id;
-//void* new_discover_receive_thread(void* arg);
 gpointer new_discover_receive_thread(gpointer data);
 
 void print_device(int i) {
@@ -115,6 +112,7 @@ void new_discover(struct ifaddrs* iface) {
 
     int optval = 1;
     setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+    setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
 
     sa = (struct sockaddr_in *) iface->ifa_addr;
     mask = (struct sockaddr_in *) iface->ifa_netmask;
@@ -150,13 +148,6 @@ void new_discover(struct ifaddrs* iface) {
     to_addr.sin_addr.s_addr=htonl(INADDR_BROADCAST);
 
     // start a receive thread to collect discovery response packets
-/*
-    rc=pthread_create(&discover_thread_id,NULL,new_discover_receive_thread,NULL);
-    if(rc != 0) {
-        fprintf(stderr,"pthread_create failed on new_discover_receive_thread: rc=%d\n", rc);
-        exit(-1);
-    }
-*/
     discover_thread_id = g_thread_new( "new discover receive", new_discover_receive_thread, NULL);
     if( ! discover_thread_id )
     {
@@ -184,10 +175,6 @@ void new_discover(struct ifaddrs* iface) {
     }
 
     // wait for receive thread to complete
-/*
-    void* status;
-    pthread_join(discover_thread_id,&status);
-*/
     g_thread_join(discover_thread_id);
 
     close(discovery_socket);
@@ -287,6 +274,5 @@ gpointer new_discover_receive_thread(gpointer data) {
         }
     }
     fprintf(stderr,"new_discover: exiting new_discover_receive_thread\n");
-    //pthread_exit(NULL);
     g_thread_exit(NULL);
 }
index f45d20cde17fbb055cd695cf6e8161316daa1587..7365ae3d652e806c49488d3f524e1f5b29c942e5 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "audio.h"
 #include "new_menu.h"
+#include "about_menu.h"
 #include "exit_menu.h"
 #include "radio_menu.h"
 #include "rx_menu.h"
 #include "display_menu.h"
 #include "dsp_menu.h"
 #include "pa_menu.h"
+#include "rigctl_menu.h"
 #include "oc_menu.h"
+#include "cw_menu.h"
+#include "store_menu.h"
 #ifdef FREEDV
 #include "freedv_menu.h"
 #endif
@@ -51,9 +55,8 @@
 #include "diversity_menu.h"
 #include "freqent_menu.h"
 #include "tx_menu.h"
-#ifdef GPIO
+#include "ps_menu.h"
 #include "encoder_menu.h"
-#endif
 #include "vfo_menu.h"
 #include "fft_menu.h"
 #include "main.h"
@@ -67,7 +70,15 @@ GtkWidget *sub_menu=NULL;
 
 int active_menu=NO_MENU;
 
-static cleanup() {
+int menu_active_receiver_changed(void *data) {
+  if(sub_menu!=NULL) {
+    gtk_widget_destroy(sub_menu);
+    sub_menu=NULL;
+  }
+  return FALSE;
+}
+
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
@@ -79,11 +90,21 @@ static cleanup() {
   active_menu=NO_MENU;
 }
 
+static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
+  cleanup();
+  return FALSE;
+}
+
 static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   cleanup();
   return TRUE;
 }
 
+static gboolean about_b_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  cleanup();
+  about_menu(top_window);
+  return TRUE;
+}
 
 static gboolean exit_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   cleanup();
@@ -127,6 +148,13 @@ static gboolean pa_cb (GtkWidget *widget, GdkEventButton *event, gpointer data)
   return TRUE;
 }
 
+static gboolean rigctl_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  cleanup();
+  fprintf(stderr, "new_menu: calling rigctl_menu\n");
+  rigctl_menu(top_window);
+  return TRUE;
+}
+
 static gboolean cw_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   cleanup();
   cw_menu(top_window);
@@ -333,10 +361,21 @@ static gboolean tx_cb (GtkWidget *widget, GdkEventButton *event, gpointer data)
   return TRUE;
 }
 
+#ifdef PURESIGNAL
+void start_ps() {
+  cleanup();
+  ps_menu(top_window);
+}
+
+static gboolean ps_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+  start_ps();
+  return TRUE;
+}
+#endif
+
 #ifdef GPIO
 void start_encoder(int encoder) {
   int old_menu=active_menu;
-fprintf(stderr,"start_encoder: encoder=%d active_menu=%d\n",encoder,active_menu);
   cleanup();
   switch(encoder) {
     case 1:
@@ -390,7 +429,9 @@ void new_menu()
 
     dialog=gtk_dialog_new();
     gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(top_window));
-    gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+    //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+    gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - Menu");
+    g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
     GdkRGBA color;
     color.red = 1.0;
@@ -407,7 +448,7 @@ void new_menu()
     gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
     gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
   
-    GtkWidget *close_b=gtk_button_new_with_label("Close Menu");
+    GtkWidget *close_b=gtk_button_new_with_label("Close");
     g_signal_connect (close_b, "button-press-event", G_CALLBACK(close_cb), NULL);
     gtk_grid_attach(GTK_GRID(grid),close_b,0,0,2,1);
 
@@ -432,6 +473,13 @@ void new_menu()
     gtk_grid_attach(GTK_GRID(grid),tx_b,(i%5),i/5,1,1);
     i++;
 
+#ifdef PURESIGNAL
+      GtkWidget *ps_b=gtk_button_new_with_label("PS");
+      g_signal_connect (ps_b, "button-press-event", G_CALLBACK(ps_cb), NULL);
+      gtk_grid_attach(GTK_GRID(grid),ps_b,(i%5),i/5,1,1);
+      i++;
+#endif
+
     GtkWidget *pa_b=gtk_button_new_with_label("PA");
     g_signal_connect (pa_b, "button-press-event", G_CALLBACK(pa_cb), NULL);
     gtk_grid_attach(GTK_GRID(grid),pa_b,(i%5),i/5,1,1);
@@ -499,6 +547,16 @@ void new_menu()
     gtk_grid_attach(GTK_GRID(grid),fft_b,(i%5),i/5,1,1);
     i++;
 
+    GtkWidget *rigctl_b=gtk_button_new_with_label("RIGCTL");
+    g_signal_connect (rigctl_b, "button-press-event", G_CALLBACK(rigctl_cb), NULL);
+    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);
+    i++;
+
 #ifdef DIVERSITY
     if(RECEIVERS==2) {
       GtkWidget *diversity_b=gtk_button_new_with_label("Diversity");
index ea2217979ae2ba62ae28e214d468be20e3efccc2..a32faedfc65446b0c839852289c379d05bd2e8bf 100644 (file)
@@ -13,9 +13,14 @@ extern void start_mode();
 extern void start_filter();
 extern void start_noise();
 extern void start_encoder();
+extern void start_vfo();
+extern void start_agc();
+extern void start_store();
 
 extern void encoder_step(int encoder,int step);
 
+extern int menu_active_receiver_changed(void *data);
+
 enum {
   NO_MENU = 0,
   E1_MENU,
index bfda6776cb664477a1b1c621af8ff04f27306b26..e573ae034fc9636c188a9464c731fe83740cf668 100644 (file)
 
 #include <gtk/gtk.h>
 
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <sys/time.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include "iambic.h"
 #endif
 #include "vox.h"
+#include "ext.h"
 
 #define min(x,y) (x<y?x:y)
 
 #define PI 3.1415926535897932F
 
-int data_socket;
+int data_socket=-1;
 
 static int running;
 
@@ -129,10 +132,23 @@ static float phase = 0.0F;
 static long response_sequence;
 static int response;
 
-static sem_t send_high_priority_sem;
-static int send_high_priority=0;
-static sem_t send_general_sem;
-static int send_general=0;
+//static sem_t send_high_priority_sem;
+//static int send_high_priority=0;
+//static sem_t send_general_sem;
+//static int send_general=0;
+
+static sem_t command_response_sem_ready;
+static sem_t command_response_sem_buffer;
+static GThread *command_response_thread_id;
+static sem_t high_priority_sem_ready;
+static sem_t high_priority_sem_buffer;
+static GThread *high_priority_thread_id;
+static sem_t mic_line_sem_ready;
+static sem_t mic_line_sem_buffer;
+static GThread *mic_line_thread_id;
+static sem_t iq_sem_ready[MAX_RECEIVERS];
+static sem_t iq_sem_buffer[MAX_RECEIVERS];
+static GThread *iq_thread_id[MAX_RECEIVERS];
 
 static int samples[MAX_RECEIVERS];
 #ifdef INCLUDED
@@ -145,30 +161,46 @@ static long audiosequence;
 static unsigned char audiobuffer[260]; // was 1444
 static int audioindex;
 
-#ifdef FREEDV
-static int freedv_samples=0;
-static int freedv_resample=6;  // convert from 48000 to 8000
-#endif
 #ifdef PSK
 static int psk_samples=0;
 static int psk_resample=6;  // convert from 48000 to 8000
 #endif
 
+#define NET_BUFFER_SIZE 2048
+// Network buffers
 static struct sockaddr_in addr;
 static int length;
-static unsigned char buffer[2048];
-static int bytesread;
-
-static void new_protocol_high_priority(int run);
-//static void* new_protocol_thread(void* arg);
+//static unsigned char buffer[NET_BUFFER_SIZE];
+static unsigned char *iq_buffer[MAX_RECEIVERS];
+static unsigned char *command_response_buffer;
+static unsigned char *high_priority_buffer;
+static unsigned char *mic_line_buffer;
+static int mic_bytes_read;
+
+static unsigned char general_buffer[60];
+static unsigned char high_priority_buffer_to_radio[1444];
+static unsigned char transmit_specific_buffer[60];
+static unsigned char receive_specific_buffer[1444];
+
+static void new_protocol_high_priority();
+static void new_protocol_general();
+static void new_protocol_receive_specific();
 static gpointer new_protocol_thread(gpointer data);
-//static void* new_protocol_timer_thread(void* arg);
 static gpointer new_protocol_timer_thread(gpointer data);
-static void  process_iq_data(RECEIVER *rx,unsigned char *buffer);
-static void  process_command_response(unsigned char *buffer);
-static void  process_high_priority(unsigned char *buffer);
-static void  process_mic_data(unsigned char *buffer,int bytes);
-static void full_tx_buffer();
+static gpointer command_response_thread(gpointer data);
+static gpointer high_priority_thread(gpointer data);
+static gpointer mic_line_thread(gpointer data);
+static gpointer iq_thread(gpointer data);
+#ifdef PURESIGNAL
+static gpointer ps_iq_thread(gpointer data);
+#endif
+static void  process_iq_data(RECEIVER *rx);
+#ifdef PURESIGNAL
+static void  process_ps_iq_data(RECEIVER *rx);
+#endif
+static void  process_command_response();
+static void  process_high_priority();
+static void  process_mic_data(int bytes);
 
 #ifdef INCLUDED
 static void new_protocol_calc_buffers() {
@@ -196,15 +228,15 @@ static void new_protocol_calc_buffers() {
 #endif
 
 void schedule_high_priority() {
-    sem_wait(&send_high_priority_sem);
-    send_high_priority=1;
-    sem_post(&send_high_priority_sem);
+    new_protocol_high_priority();
 }
 
 void schedule_general() {
-    sem_wait(&send_general_sem);
-    send_general=1;
-    sem_post(&send_general_sem);
+    new_protocol_general();
+}
+
+void schedule_receive_specific() {
+    new_protocol_receive_specific();
 }
 
 void filter_board_changed() {
@@ -230,7 +262,9 @@ void cw_changed() {
 }
 
 void new_protocol_init(int pixels) {
+    int i;
     int rc;
+    int ddc;
     spectrumWIDTH=pixels;
 
     fprintf(stderr,"new_protocol_init: MIC_SAMPLES=%d\n",MIC_SAMPLES);
@@ -261,8 +295,112 @@ void new_protocol_init(int pixels) {
 #endif
 
     rc=sem_init(&response_sem, 0, 0);
-    rc=sem_init(&send_high_priority_sem, 0, 1);
-    rc=sem_init(&send_general_sem, 0, 1);
+    //rc=sem_init(&send_high_priority_sem, 0, 1);
+    //rc=sem_init(&send_general_sem, 0, 1);
+
+    rc=sem_init(&command_response_sem_ready, 0, 0);
+    rc=sem_init(&command_response_sem_buffer, 0, 0);
+    command_response_thread_id = g_thread_new( "command_response thread",command_response_thread, NULL);
+    if( ! command_response_thread_id ) {
+      fprintf(stderr,"g_thread_new failed on command_response_thread\n");
+      exit( -1 );
+    }
+    fprintf(stderr, "command_response_thread: id=%p\n",command_response_thread_id);
+    rc=sem_init(&high_priority_sem_ready, 0, 0);
+    rc=sem_init(&high_priority_sem_buffer, 0, 0);
+    high_priority_thread_id = g_thread_new( "high_priority thread", high_priority_thread, NULL);
+    if( ! high_priority_thread_id ) {
+      fprintf(stderr,"g_thread_new failed on high_priority_thread\n");
+      exit( -1 );
+    }
+    fprintf(stderr, "high_priority_thread: id=%p\n",high_priority_thread_id);
+    rc=sem_init(&mic_line_sem_ready, 0, 0);
+    rc=sem_init(&mic_line_sem_buffer, 0, 0);
+    mic_line_thread_id = g_thread_new( "mic_line thread", mic_line_thread, NULL);
+    if( ! mic_line_thread_id ) {
+      fprintf(stderr,"g_thread_new failed on mic_line_thread\n");
+      exit( -1 );
+    }
+    fprintf(stderr, "mic_line_thread: id=%p\n",mic_line_thread_id);
+
+    for(i=0;i<RECEIVERS;i++) {
+      ddc=receiver[i]->ddc;
+      rc=sem_init(&iq_sem_ready[ddc], 0, 0);
+      rc=sem_init(&iq_sem_buffer[ddc], 0, 0);
+      iq_thread_id[ddc] = g_thread_new( "iq thread", iq_thread, (gpointer)(long)i);
+      if( ! iq_thread_id ) {
+        fprintf(stderr,"g_thread_new failed for iq_thread: rx=%d\n",i);
+        exit( -1 );
+      }
+      fprintf(stderr, "iq_thread: rx=%d ddc=%d thread=%p\n",i, ddc, iq_thread_id);
+    }
+
+#ifdef PURESIGNAL
+    // for PS the two feedback streams are synced on the one DDC
+    if(device!=NEW_DEVICE_HERMES) {
+      ddc=receiver[PS_TX_FEEDBACK]->ddc;
+      rc=sem_init(&iq_sem_ready[ddc], 0, 0);
+      rc=sem_init(&iq_sem_buffer[ddc], 0, 0);
+      iq_thread_id[ddc] = g_thread_new( "ps iq thread", ps_iq_thread, (gpointer)(long)PS_TX_FEEDBACK);
+      if( ! iq_thread_id ) {
+        fprintf(stderr,"g_thread_new failed for ps_iq_thread: rx=%d\n",PS_TX_FEEDBACK);
+        exit( -1 );
+      }
+      fprintf(stderr, "iq_thread: id=%p\n",iq_thread_id);
+    }
+#endif
+
+data_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
+    if(data_socket<0) {
+        fprintf(stderr,"metis: create socket failed for data_socket\n");
+        exit(-1);
+    }
+
+    int optval = 1;
+    setsockopt(data_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+    setsockopt(data_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
+
+    // bind to the interface
+    if(bind(data_socket,(struct sockaddr*)&radio->info.network.interface_address,radio->info.network.interface_length)<0) {
+        fprintf(stderr,"metis: bind socket failed for data_socket\n");
+        exit(-1);
+    }
+
+fprintf(stderr,"new_protocol_thread: date_socket %d bound to interface\n",data_socket);
+
+    memcpy(&base_addr,&radio->info.network.address,radio->info.network.address_length);
+    base_addr_length=radio->info.network.address_length;
+    base_addr.sin_port=htons(GENERAL_REGISTERS_FROM_HOST_PORT);
+
+    memcpy(&receiver_addr,&radio->info.network.address,radio->info.network.address_length);
+    receiver_addr_length=radio->info.network.address_length;
+    receiver_addr.sin_port=htons(RECEIVER_SPECIFIC_REGISTERS_FROM_HOST_PORT);
+
+    memcpy(&transmitter_addr,&radio->info.network.address,radio->info.network.address_length);
+    transmitter_addr_length=radio->info.network.address_length;
+    transmitter_addr.sin_port=htons(TRANSMITTER_SPECIFIC_REGISTERS_FROM_HOST_PORT);
+
+    memcpy(&high_priority_addr,&radio->info.network.address,radio->info.network.address_length);
+    high_priority_addr_length=radio->info.network.address_length;
+    high_priority_addr.sin_port=htons(HIGH_PRIORITY_FROM_HOST_PORT);
+
+fprintf(stderr,"new_protocol_thread: high_priority_addr setup for port %d\n",HIGH_PRIORITY_FROM_HOST_PORT);
+
+    memcpy(&audio_addr,&radio->info.network.address,radio->info.network.address_length);
+    audio_addr_length=radio->info.network.address_length;
+    audio_addr.sin_port=htons(AUDIO_FROM_HOST_PORT);
+
+    memcpy(&iq_addr,&radio->info.network.address,radio->info.network.address_length);
+    iq_addr_length=radio->info.network.address_length;
+    iq_addr.sin_port=htons(TX_IQ_FROM_HOST_PORT);
+
+
+    for(i=0;i<MAX_RECEIVERS;i++) {
+        memcpy(&data_addr[i],&radio->info.network.address,radio->info.network.address_length);
+        data_addr_length[i]=radio->info.network.address_length;
+        data_addr[i].sin_port=htons(RX_IQ_TO_HOST_PORT_0+i);
+        samples[i]=0;
+    }
 
     new_protocol_thread_id = g_thread_new( "new protocol", new_protocol_thread, NULL);
     if( ! new_protocol_thread_id )
@@ -272,47 +410,50 @@ void new_protocol_init(int pixels) {
     }
     fprintf(stderr, "new_protocol_thread: id=%p\n",new_protocol_thread_id);
 
-
 }
 
 static void new_protocol_general() {
-    unsigned char buffer[60];
-    BAND *band=band_get_current_band();
+    BAND *band;
 
-    memset(buffer, 0, sizeof(buffer));
+    if(split) {
+      band=band_get_band(vfo[VFO_B].band);
+    } else {
+      band=band_get_band(vfo[VFO_A].band);
+    }
+    memset(general_buffer, 0, sizeof(general_buffer));
 
-    buffer[0]=general_sequence>>24;
-    buffer[1]=general_sequence>>16;
-    buffer[2]=general_sequence>>8;
-    buffer[3]=general_sequence;
+    general_buffer[0]=general_sequence>>24;
+    general_buffer[1]=general_sequence>>16;
+    general_buffer[2]=general_sequence>>8;
+    general_buffer[3]=general_sequence;
 
     // use defaults apart from
-    buffer[37]=0x08;  //  phase word (not frequency)
-    buffer[38]=0x01;  //  enable hardware timer
+    general_buffer[37]=0x08;  //  phase word (not frequency)
+    general_buffer[38]=0x01;  //  enable hardware timer
 
-    
-    
     if(band->disablePA) {
-      buffer[58]=0x00;
+      general_buffer[58]=0x00;
     } else {
-      buffer[58]=0x01;  // enable PA
+      general_buffer[58]=0x01;  // enable PA
     }
 
+fprintf(stderr,"new_protocol_general: PA Enable=%02X\n",general_buffer[58]);
+
     if(filter_board==APOLLO) {
-      buffer[58]|=0x02; // enable APOLLO tuner
+      general_buffer[58]|=0x02; // enable APOLLO tuner
     }
 
     if(filter_board==ALEX) {
       if(device==NEW_DEVICE_ORION2) {
-        buffer[59]=0x03;  // enable Alex 0 and 1
+        general_buffer[59]=0x03;  // enable Alex 0 and 1
       } else {
-        buffer[59]=0x01;  // enable Alex 0
+        general_buffer[59]=0x01;  // enable Alex 0
       }
     }
 
-fprintf(stderr,"Alex Enable=%02X\n",buffer[59]);
+fprintf(stderr,"Alex Enable=%02X\n",general_buffer[59]);
 
-    if(sendto(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&base_addr,base_addr_length)<0) {
+    if(sendto(data_socket,general_buffer,sizeof(general_buffer),0,(struct sockaddr*)&base_addr,base_addr_length)<0) {
         fprintf(stderr,"sendto socket failed for general\n");
         exit(1);
     }
@@ -320,124 +461,165 @@ fprintf(stderr,"Alex Enable=%02X\n",buffer[59]);
     general_sequence++;
 }
 
-static void new_protocol_high_priority(int run) {
+static void new_protocol_high_priority() {
     int i, r;
-    unsigned char buffer[1444];
     BAND *band;
+    int xvtr;
     long long rxFrequency;
     long long txFrequency;
     long phase;
     int mode;
+    int ddc;
+
+    if(data_socket==-1) {
+      return;
+    }
 
-    memset(buffer, 0, sizeof(buffer));
+    memset(high_priority_buffer_to_radio, 0, sizeof(high_priority_buffer_to_radio));
 
-    buffer[0]=high_priority_sequence>>24;
-    buffer[1]=high_priority_sequence>>16;
-    buffer[2]=high_priority_sequence>>8;
-    buffer[3]=high_priority_sequence;
+    high_priority_buffer_to_radio[0]=high_priority_sequence>>24;
+    high_priority_buffer_to_radio[1]=high_priority_sequence>>16;
+    high_priority_buffer_to_radio[2]=high_priority_sequence>>8;
+    high_priority_buffer_to_radio[3]=high_priority_sequence;
 
     if(split) {
       mode=vfo[1].mode;
     } else {
       mode=vfo[0].mode;
     }
-    buffer[4]=run;
+    high_priority_buffer_to_radio[4]=running;
     if(mode==modeCWU || mode==modeCWL) {
       if(tune) {
-        buffer[4]|=0x02;
+        high_priority_buffer_to_radio[4]|=0x02;
       }
 #ifdef LOCALCW
       if (cw_keyer_internal == 0) {
         // set the ptt if we're not in breakin mode and mox is on
-        if(cw_breakin == 0 && getMox()) buffer[4]|=0x02;
-        buffer[5]|=(keyer_out) ? 0x01 : 0;
-        //buffer[5]|=(*kdot) ? 0x02 : 0;
-        //buffer[5]|=(*kdash) ? 0x04 : 0;
-        buffer[5]|=(key_state==SENDDOT) ? 0x02 : 0;
-        buffer[5]|=(key_state==SENDDASH) ? 0x04 : 0;
+        if(cw_breakin == 0 && getMox()) high_priority_buffer_to_radio[4]|=0x02;
+        high_priority_buffer_to_radio[5]|=(keyer_out) ? 0x01 : 0;
+        //high_priority_buffer_to_radio[5]|=(*kdot) ? 0x02 : 0;
+        //high_priority_buffer_to_radio[5]|=(*kdash) ? 0x04 : 0;
+        high_priority_buffer_to_radio[5]|=(key_state==SENDDOT) ? 0x02 : 0;
+        high_priority_buffer_to_radio[5]|=(key_state==SENDDASH) ? 0x04 : 0;
       }
 #endif
     } else {
       if(isTransmitting()) {
-        buffer[4]|=0x02;
+        high_priority_buffer_to_radio[4]|=0x02;
       }
     }
 
 // rx
 
     for(r=0;r<receivers;r++) {
-      //long long rxFrequency=ddsFrequency;
-      //rxFrequency=receiver[r]->dds_frequency;
+      int ddc=receiver[r]->ddc;
       int v=receiver[r]->id;
       rxFrequency=vfo[v].frequency-vfo[v].lo;
       if(vfo[v].rit_enabled) {
         rxFrequency+=vfo[v].rit;
       }
-      if(vfo[v].mode==modeCWU) {
-        rxFrequency-=cw_keyer_sidetone_frequency;
-      } else if(vfo[v].mode==modeCWL) {
-        rxFrequency+=cw_keyer_sidetone_frequency;
+
+/*
+      switch(vfo[v].mode) {
+        case modeCWU:
+          rxFrequency-=cw_keyer_sidetone_frequency;
+          break;
+        case modeCWL:
+          rxFrequency+=cw_keyer_sidetone_frequency;
+          break;
+        default:
+          break;
       }
+*/
       phase=(long)((4294967296.0*(double)rxFrequency)/122880000.0);
-
-      i=r;
-      //if(device==NEW_DEVICE_ORION2 && r==1) i=3;
-      buffer[9+(i*4)]=phase>>24;
-      buffer[10+(i*4)]=phase>>16;
-      buffer[11+(i*4)]=phase>>8;
-      buffer[12+(i*4)]=phase;
+      high_priority_buffer_to_radio[9+(ddc*4)]=phase>>24;
+      high_priority_buffer_to_radio[10+(ddc*4)]=phase>>16;
+      high_priority_buffer_to_radio[11+(ddc*4)]=phase>>8;
+      high_priority_buffer_to_radio[12+(ddc*4)]=phase;
     }
 
     // tx
-    band=band_get_band(vfo[VFO_A].band);
-    rxFrequency=vfo[VFO_A].frequency-vfo[VFO_A].lo;
-    txFrequency=vfo[VFO_A].frequency-vfo[VFO_A].lo;
-    if(split) {
-      band=band_get_band(vfo[VFO_B].band);
+    if(active_receiver->id==VFO_A) {
+      txFrequency=vfo[VFO_A].frequency-vfo[VFO_A].lo;
+      if(split) {
+        txFrequency=vfo[VFO_B].frequency-vfo[VFO_B].lo;
+      }
+    } else {
       txFrequency=vfo[VFO_B].frequency-vfo[VFO_B].lo;
+      if(split) {
+        txFrequency=vfo[VFO_A].frequency-vfo[VFO_A].lo;
+      }
     }
 
+    switch(vfo[active_receiver->id].mode) {
+        case modeCWU:
+          txFrequency+=cw_keyer_sidetone_frequency;
+          break;
+        case modeCWL:
+          txFrequency-=cw_keyer_sidetone_frequency;
+          break;
+        default:
+          break;
+      }
+
     phase=(long)((4294967296.0*(double)txFrequency)/122880000.0);
 
-    buffer[329]=phase>>24;
-    buffer[330]=phase>>16;
-    buffer[331]=phase>>8;
-    buffer[332]=phase;
+#ifdef PURESIGNAL
+    if(isTransmitting() && transmitter->puresignal) {
+      // set puresignal rx to transmit frequency
+      high_priority_buffer_to_radio[9]=phase>>24;
+      high_priority_buffer_to_radio[10]=phase>>16;
+      high_priority_buffer_to_radio[11]=phase>>8;
+      high_priority_buffer_to_radio[12]=phase;
+
+      high_priority_buffer_to_radio[13]=phase>>24;
+      high_priority_buffer_to_radio[14]=phase>>16;
+      high_priority_buffer_to_radio[15]=phase>>8;
+      high_priority_buffer_to_radio[16]=phase;
+    }
+#endif
+
+    high_priority_buffer_to_radio[329]=phase>>24;
+    high_priority_buffer_to_radio[330]=phase>>16;
+    high_priority_buffer_to_radio[331]=phase>>8;
+    high_priority_buffer_to_radio[332]=phase;
 
     int power=0;
     if(isTransmitting()) {
-      if(tune) {
-        power=tune_drive_level;
+      if(tune && !transmitter->tune_use_drive) {
+        power=(int)((double)transmitter->drive_level/100.0*(double)transmitter->tune_percent);
       } else {
-        power=drive_level;
+        power=transmitter->drive_level;
       }
     }
 
-    buffer[345]=power&0xFF;
+    high_priority_buffer_to_radio[345]=power&0xFF;
 
     if(isTransmitting()) {
 
       if(split) {
         band=band_get_band(vfo[VFO_B].band);
+        xvtr=vfo[VFO_B].band>=BANDS;
       } else {
         band=band_get_band(vfo[VFO_A].band);
+        xvtr=vfo[VFO_A].band>=BANDS;
       }
-      buffer[1401]=band->OCtx<<1;
+      high_priority_buffer_to_radio[1401]=band->OCtx<<1;
       if(tune) {
         if(OCmemory_tune_time!=0) {
           struct timeval te;
           gettimeofday(&te,NULL);
           long long now=te.tv_sec*1000LL+te.tv_usec/1000;
           if(tune_timeout>now) {
-            buffer[1401]|=OCtune<<1;
+            high_priority_buffer_to_radio[1401]|=OCtune<<1;
           }
         } else {
-          buffer[1401]|=OCtune<<1;
+          high_priority_buffer_to_radio[1401]|=OCtune<<1;
         }
       }
     } else {
       band=band_get_band(vfo[VFO_A].band);
-      buffer[1401]=band->OCrx<<1;
+      high_priority_buffer_to_radio[1401]=band->OCrx<<1;
     }
 
     if((protocol==ORIGINAL_PROTOCOL && device==DEVICE_METIS) ||
@@ -446,7 +628,7 @@ static void new_protocol_high_priority(int run) {
 #endif
        (protocol==NEW_PROTOCOL && device==NEW_DEVICE_ATLAS)) {
       for(r=0;r<receivers;r++) {
-        buffer[1403]|=receiver[i]->preamp;
+        high_priority_buffer_to_radio[1403]|=receiver[i]->preamp;
       }
     }
 
@@ -455,40 +637,87 @@ static void new_protocol_high_priority(int run) {
 
     if(isTransmitting()) {
       filters=0x08000000;
+#ifdef PURESIGNAL
+      if(transmitter->puresignal) {
+        filters|=0x00040000;
+      }
+#endif
     }
 
-    if(rxFrequency<1800000L) {
-        filters|=ALEX_BYPASS_HPF;
-    } else if(rxFrequency<6500000L) {
-        filters|=ALEX_1_5MHZ_HPF;
-    } else if(rxFrequency<9500000L) {
-        filters|=ALEX_6_5MHZ_HPF;
-    } else if(rxFrequency<13000000L) {
-        filters|=ALEX_9_5MHZ_HPF;
-    } else if(rxFrequency<20000000L) {
-        filters|=ALEX_13MHZ_HPF;
-    } else {
-        filters|=ALEX_20MHZ_HPF;
+    rxFrequency=vfo[VFO_A].frequency-vfo[VFO_A].lo;
+    switch(device) {
+      case NEW_DEVICE_ORION2:
+        if(rxFrequency<1500000L) {
+          filters|=ALEX_BYPASS_HPF;
+        } else if(rxFrequency<2100000L) {
+          filters|=ALEX_1_5MHZ_HPF;
+        } else if(rxFrequency<5500000L) {
+          filters|=ALEX_6_5MHZ_HPF;
+        } else if(rxFrequency<11000000L) {
+          filters|=ALEX_9_5MHZ_HPF;
+        } else if(rxFrequency<22000000L) {
+          filters|=ALEX_13MHZ_HPF;
+        } else if(rxFrequency<35000000L) {
+          filters|=ALEX_20MHZ_HPF;
+        } else {
+          filters|=ALEX_6M_PREAMP;
+        }
+        break;
+      default:
+        if(rxFrequency<1800000L) {
+          filters|=ALEX_BYPASS_HPF;
+        } else if(rxFrequency<6500000L) {
+          filters|=ALEX_1_5MHZ_HPF;
+        } else if(rxFrequency<9500000L) {
+          filters|=ALEX_6_5MHZ_HPF;
+        } else if(rxFrequency<13000000L) {
+          filters|=ALEX_9_5MHZ_HPF;
+        } else if(rxFrequency<20000000L) {
+          filters|=ALEX_13MHZ_HPF;
+        } else if(rxFrequency<50000000L) {
+          filters|=ALEX_20MHZ_HPF;
+        } else {
+          filters|=ALEX_6M_PREAMP;
+        }
+        break;
     }
 
-    if(rxFrequency>30000000L) {
-        filters|=ALEX_6M_PREAMP;
-    }
+    switch(device) {
+      case NEW_DEVICE_ORION2:
+        if(txFrequency>32000000) {
+          filters|=ALEX_6_BYPASS_LPF;
+        } else if(txFrequency>22000000) {
+          filters|=ALEX_12_10_LPF;
+        } else if(txFrequency>15000000) {
+          filters|=ALEX_17_15_LPF;
+        } else if(txFrequency>8000000) {
+          filters|=ALEX_30_20_LPF;
+        } else if(txFrequency>4500000) {
+          filters|=ALEX_60_40_LPF;
+        } else if(txFrequency>2400000) {
+          filters|=ALEX_80_LPF;
+        } else {
+          filters|=ALEX_160_LPF;
+        }
+        break;
+      default:
+        if(txFrequency>35600000) {
+          filters|=ALEX_6_BYPASS_LPF;
+        } else if(txFrequency>24000000) {
+          filters|=ALEX_12_10_LPF;
+        } else if(txFrequency>16500000) {
+          filters|=ALEX_17_15_LPF;
+        } else if(txFrequency>8000000) {
+          filters|=ALEX_30_20_LPF;
+        } else if(txFrequency>5000000) {
+          filters|=ALEX_60_40_LPF;
+        } else if(txFrequency>2500000) {
+          filters|=ALEX_80_LPF;
+        } else {
+          filters|=ALEX_160_LPF;
+        }
+        break;
 
-    if(txFrequency>32000000) {
-        filters|=ALEX_6_BYPASS_LPF;
-    } else if(txFrequency>22000000) {
-        filters|=ALEX_12_10_LPF;
-    } else if(txFrequency>15000000) {
-        filters|=ALEX_17_15_LPF;
-    } else if(txFrequency>8000000) {
-        filters|=ALEX_30_20_LPF;
-    } else if(txFrequency>4500000) {
-        filters|=ALEX_60_40_LPF;
-    } else if(txFrequency>2400000) {
-        filters|=ALEX_80_LPF;
-    } else {
-        filters|=ALEX_160_LPF;
     }
 
     switch(receiver[0]->alex_antenna) {
@@ -505,7 +734,9 @@ static void new_protocol_high_priority(int run) {
           filters|=ALEX_RX_ANTENNA_EXT1;
           break;
         case 5:  // XVTR
-          filters|=ALEX_RX_ANTENNA_XVTR;
+          if(!xvtr) {
+            filters|=ALEX_RX_ANTENNA_XVTR;
+          }
           break;
         default:
           // invalid value - set to 0
@@ -514,22 +745,23 @@ static void new_protocol_high_priority(int run) {
     }
 
     if(isTransmitting()) {
-      switch(transmitter->alex_antenna) {
-        case 0:  // ANT 1
-          filters|=ALEX_TX_ANTENNA_1;
-          break;
-        case 1:  // ANT 2
-          filters|=ALEX_TX_ANTENNA_2;
-          break;
-        case 2:  // ANT 3
-          filters|=ALEX_TX_ANTENNA_3;
-          break;
-        default:
-          // invalid value - set to 0
-          filters|=ALEX_TX_ANTENNA_1;
-          band->alexRxAntenna=0;
-          break;
-         
+      if(!xvtr) {
+        switch(transmitter->alex_antenna) {
+          case 0:  // ANT 1
+            filters|=ALEX_TX_ANTENNA_1;
+            break;
+          case 1:  // ANT 2
+            filters|=ALEX_TX_ANTENNA_2;
+            break;
+          case 2:  // ANT 3
+            filters|=ALEX_TX_ANTENNA_3;
+            break;
+          default:
+            // invalid value - set to 0
+            filters|=ALEX_TX_ANTENNA_1;
+            band->alexRxAntenna=0;
+            break;
+        }
       }
     } else {
       switch(receiver[0]->alex_antenna) {
@@ -545,142 +777,175 @@ static void new_protocol_high_priority(int run) {
         case 3:  // EXT 1
         case 4:  // EXT 2
         case 5:  // XVTR
-          switch(transmitter->alex_antenna) {
-            case 0:  // ANT 1
-              filters|=ALEX_TX_ANTENNA_1;
-              break;
-            case 1:  // ANT 2
-              filters|=ALEX_TX_ANTENNA_2;
-              break;
-            case 2:  // ANT 3
-              filters|=ALEX_TX_ANTENNA_3;
-              break;
+          if(!xvtr) {
+            switch(transmitter->alex_antenna) {
+              case 0:  // ANT 1
+                filters|=ALEX_TX_ANTENNA_1;
+                break;
+              case 1:  // ANT 2
+                filters|=ALEX_TX_ANTENNA_2;
+                break;
+              case 2:  // ANT 3
+                filters|=ALEX_TX_ANTENNA_3;
+                break;
+            }
           }
           break;
       }
     }
 
-    buffer[1432]=(filters>>24)&0xFF;
-    buffer[1433]=(filters>>16)&0xFF;
-    buffer[1434]=(filters>>8)&0xFF;
-    buffer[1435]=filters&0xFF;
-//fprintf(stderr,"HPF: 0: %02X %02X for %lld\n",buffer[1434],buffer[1435],rxFrequency);
+    high_priority_buffer_to_radio[1432]=(filters>>24)&0xFF;
+    high_priority_buffer_to_radio[1433]=(filters>>16)&0xFF;
+    high_priority_buffer_to_radio[1434]=(filters>>8)&0xFF;
+    high_priority_buffer_to_radio[1435]=filters&0xFF;
+
+//fprintf(stderr,"filters: txrx0: %02X %02X %02X %02X for rx=%lld tx=%lld\n",high_priority_buffer_to_radio[1432],high_priority_buffer_to_radio[1433],high_priority_buffer_to_radio[1434],high_priority_buffer_to_radio[1435],rxFrequency,txFrequency);
 
     filters=0x00000000;
     rxFrequency=vfo[VFO_B].frequency-vfo[VFO_B].lo;
-    if(rxFrequency<1800000L) {
-        filters|=ALEX_BYPASS_HPF;
-    } else if(rxFrequency<6500000L) {
-        filters|=ALEX_1_5MHZ_HPF;
-    } else if(rxFrequency<9500000L) {
-        filters|=ALEX_6_5MHZ_HPF;
-    } else if(rxFrequency<13000000L) {
-        filters|=ALEX_9_5MHZ_HPF;
-    } else if(rxFrequency<20000000L) {
-        filters|=ALEX_13MHZ_HPF;
-    } else {
-        filters|=ALEX_20MHZ_HPF;
-    }
 
-    if(rxFrequency>30000000L) {
-        filters|=ALEX_6M_PREAMP;
+    switch(device) {
+      case NEW_DEVICE_ORION2:
+        if(rxFrequency<1500000L) {
+          filters|=ALEX_BYPASS_HPF;
+        } else if(rxFrequency<2100000L) {
+          filters|=ALEX_1_5MHZ_HPF;
+        } else if(rxFrequency<5500000L) {
+          filters|=ALEX_6_5MHZ_HPF;
+        } else if(rxFrequency<11000000L) {
+          filters|=ALEX_9_5MHZ_HPF;
+        } else if(rxFrequency<22000000L) {
+          filters|=ALEX_13MHZ_HPF;
+        } else if(rxFrequency<35000000L) {
+          filters|=ALEX_20MHZ_HPF;
+        } else {
+          filters|=ALEX_6M_PREAMP;
+        }
+        break;
+      default:
+        if(rxFrequency<1800000L) {
+          filters|=ALEX_BYPASS_HPF;
+        } else if(rxFrequency<6500000L) {
+          filters|=ALEX_1_5MHZ_HPF;
+        } else if(rxFrequency<9500000L) {
+          filters|=ALEX_6_5MHZ_HPF;
+        } else if(rxFrequency<13000000L) {
+          filters|=ALEX_9_5MHZ_HPF;
+        } else if(rxFrequency<20000000L) {
+          filters|=ALEX_13MHZ_HPF;
+        } else if(rxFrequency<50000000L) {
+          filters|=ALEX_20MHZ_HPF;
+        } else {
+          filters|=ALEX_6M_PREAMP;
+        }
+        break;
     }
 
+    //high_priority_buffer_to_radio[1428]=(filters>>24)&0xFF;
+    //high_priority_buffer_to_radio[1429]=(filters>>16)&0xFF;
+    high_priority_buffer_to_radio[1430]=(filters>>8)&0xFF;
+    high_priority_buffer_to_radio[1431]=filters&0xFF;
 
-    buffer[1428]=(filters>>24)&0xFF;
-    buffer[1429]=(filters>>16)&0xFF;
-    buffer[1430]=(filters>>8)&0xFF;
-    buffer[1431]=filters&0xFF;
+//fprintf(stderr,"filters: rx1: %02X %02X for rx=%lld\n",high_priority_buffer_to_radio[1430],high_priority_buffer_to_radio[1431],rxFrequency);
 
-//fprintf(stderr,"HPF: 1: %02X %02X for %lld\n",buffer[1430],buffer[1431],rxFrequency);
-// rx_frequency
+//fprintf(stderr,"new_protocol_high_priority: OC=%02X filters=%04X for frequency=%lld\n", high_priority_buffer_to_radio[1401], filters, rxFrequency);
 
-//fprintf(stderr,"new_protocol_high_priority: OC=%02X filters=%04X for frequency=%lld\n", buffer[1401], filters, rxFrequency);
 
-    for(r=0;r<receivers;r++) {
-      i=r;
-      //if(device==NEW_DEVICE_ORION2 && r==1) i=3;
-      buffer[1443-i]=receiver[r]->attenuation;
+    if(isTransmitting()) {
+      high_priority_buffer_to_radio[1443]=transmitter->attenuation;
+    } else {
+      for(r=0;r<receivers;r++) {
+        i=r;
+        high_priority_buffer_to_radio[1443-i]=receiver[r]->attenuation;
+      }
     }
 
-    if(sendto(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&high_priority_addr,high_priority_addr_length)<0) {
-        fprintf(stderr,"sendto socket failed for high priority\n");
-        exit(1);
+    int rc;
+    if((rc=sendto(data_socket,high_priority_buffer_to_radio,sizeof(high_priority_buffer_to_radio),0,(struct sockaddr*)&high_priority_addr,high_priority_addr_length))<0) {
+        fprintf(stderr,"sendto socket failed for high priority: rc=%d errno=%d\n",rc,errno);
+        abort();
+        //exit(1);
     }
 
     high_priority_sequence++;
 }
 
+static unsigned char last_50=0;
+
 static void new_protocol_transmit_specific() {
-    unsigned char buffer[60];
     int mode;
 
-    memset(buffer, 0, sizeof(buffer));
+    memset(transmit_specific_buffer, 0, sizeof(transmit_specific_buffer));
 
-    buffer[0]=tx_specific_sequence>>24;
-    buffer[1]=tx_specific_sequence>>16;
-    buffer[2]=tx_specific_sequence>>8;
-    buffer[3]=tx_specific_sequence;
+    transmit_specific_buffer[0]=tx_specific_sequence>>24;
+    transmit_specific_buffer[1]=tx_specific_sequence>>16;
+    transmit_specific_buffer[2]=tx_specific_sequence>>8;
+    transmit_specific_buffer[3]=tx_specific_sequence;
 
     if(split) {
       mode=vfo[1].mode;
     } else {
       mode=vfo[0].mode;
     }
-    buffer[4]=1; // 1 DAC
-    buffer[5]=0; //  default no CW
+    transmit_specific_buffer[4]=1; // 1 DAC
+    transmit_specific_buffer[5]=0; //  default no CW
     // may be using local pihpsdr OR hpsdr CW
     if(mode==modeCWU || mode==modeCWL) {
-        buffer[5]|=0x02;
+        transmit_specific_buffer[5]|=0x02;
     }
     if(cw_keys_reversed) {
-        buffer[5]|=0x04;
+        transmit_specific_buffer[5]|=0x04;
     }
     if(cw_keyer_mode==KEYER_MODE_A) {
-        buffer[5]|=0x08;
+        transmit_specific_buffer[5]|=0x08;
     }
     if(cw_keyer_mode==KEYER_MODE_B) {
-        buffer[5]|=0x28;
+        transmit_specific_buffer[5]|=0x28;
     }
     if(cw_keyer_sidetone_volume!=0) {
-        buffer[5]|=0x10;
+        transmit_specific_buffer[5]|=0x10;
     }
     if(cw_keyer_spacing) {
-        buffer[5]|=0x40;
+        transmit_specific_buffer[5]|=0x40;
     }
     if(cw_breakin) {
-        buffer[5]|=0x80;
-    }
-
-    buffer[6]=cw_keyer_sidetone_volume; // sidetone off
-    buffer[7]=cw_keyer_sidetone_frequency>>8;
-    buffer[8]=cw_keyer_sidetone_frequency; // sidetone frequency
-    buffer[9]=cw_keyer_speed; // cw keyer speed
-    buffer[10]=cw_keyer_weight; // cw weight
-    buffer[11]=cw_keyer_hang_time>>8;
-    buffer[12]=cw_keyer_hang_time; // cw hang delay
-    buffer[13]=0; // rf delay
-    buffer[50]=0;
+        transmit_specific_buffer[5]|=0x80;
+    }
+
+    transmit_specific_buffer[6]=cw_keyer_sidetone_volume; // sidetone off
+    transmit_specific_buffer[7]=cw_keyer_sidetone_frequency>>8;
+    transmit_specific_buffer[8]=cw_keyer_sidetone_frequency; // sidetone frequency
+    transmit_specific_buffer[9]=cw_keyer_speed; // cw keyer speed
+    transmit_specific_buffer[10]=cw_keyer_weight; // cw weight
+    transmit_specific_buffer[11]=cw_keyer_hang_time>>8;
+    transmit_specific_buffer[12]=cw_keyer_hang_time; // cw hang delay
+    transmit_specific_buffer[13]=0; // rf delay
+    transmit_specific_buffer[50]=0;
     if(mic_linein) {
-      buffer[50]|=0x01;
+      transmit_specific_buffer[50]|=0x01;
     }
     if(mic_boost) {
-      buffer[50]|=0x02;
+      transmit_specific_buffer[50]|=0x02;
     }
     if(mic_ptt_enabled==0) {  // set if disabled
-      buffer[50]|=0x04;
+      transmit_specific_buffer[50]|=0x04;
     }
     if(mic_ptt_tip_bias_ring) {
-      buffer[50]|=0x08;
+      transmit_specific_buffer[50]|=0x08;
     }
     if(mic_bias_enabled) {
-      buffer[50]|=0x10;
+      transmit_specific_buffer[50]|=0x10;
+    }
+
+    if(last_50!=transmit_specific_buffer[50]) {
+      last_50=transmit_specific_buffer[50];
+fprintf(stderr,"tx_specific: 50=%02X\n",transmit_specific_buffer[50]);
     }
 
     // 0..31
-    buffer[51]=linein_gain;
+    transmit_specific_buffer[51]=linein_gain;
 
-    if(sendto(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&transmitter_addr,transmitter_addr_length)<0) {
+    if(sendto(data_socket,transmit_specific_buffer,sizeof(transmit_specific_buffer),0,(struct sockaddr*)&transmitter_addr,transmitter_addr_length)<0) {
         fprintf(stderr,"sendto socket failed for tx specific\n");
         exit(1);
     }
@@ -690,32 +955,57 @@ static void new_protocol_transmit_specific() {
 }
 
 static void new_protocol_receive_specific() {
-    unsigned char buffer[1444];
     int i;
+    int ddc;
 
-    memset(buffer, 0, sizeof(buffer));
+    memset(receive_specific_buffer, 0, sizeof(receive_specific_buffer));
 
-    buffer[0]=rx_specific_sequence>>24;
-    buffer[1]=rx_specific_sequence>>16;
-    buffer[2]=rx_specific_sequence>>8;
-    buffer[3]=rx_specific_sequence;
+    receive_specific_buffer[0]=rx_specific_sequence>>24;
+    receive_specific_buffer[1]=rx_specific_sequence>>16;
+    receive_specific_buffer[2]=rx_specific_sequence>>8;
+    receive_specific_buffer[3]=rx_specific_sequence;
 
-    buffer[4]=2; // 2 ADCs
+    receive_specific_buffer[4]=2; // 2 ADCs
 
     for(i=0;i<receivers;i++) {
-      int r=i;
-      //if(device==NEW_DEVICE_ORION2 && r==1) r=3;
-      buffer[5]|=receiver[i]->dither<<r; // dither enable
-      buffer[6]|=receiver[i]->random<<r; // random enable
-      buffer[7]|=(1<<r); // DDC enbale
-      buffer[17+(r*6)]=receiver[i]->adc;
-      buffer[18+(r*6)]=((receiver[i]->sample_rate/1000)>>8)&0xFF;
-      buffer[19+(r*6)]=(receiver[i]->sample_rate/1000)&0xFF;
-      buffer[22+(r*6)]=24;
+      ddc=receiver[i]->ddc;
+      receive_specific_buffer[5]|=receiver[i]->dither<<ddc; // dither enable
+      receive_specific_buffer[6]|=receiver[i]->random<<ddc; // random enable
+      receive_specific_buffer[7]|=(1<<ddc); // DDC enable
+      receive_specific_buffer[17+(ddc*6)]=receiver[i]->adc;
+      receive_specific_buffer[18+(ddc*6)]=((receiver[i]->sample_rate/1000)>>8)&0xFF;
+      receive_specific_buffer[19+(ddc*6)]=(receiver[i]->sample_rate/1000)&0xFF;
+      receive_specific_buffer[22+(ddc*6)]=24;
     }
 
+#ifdef PURESIGNAL
+    if(transmitter->puresignal && isTransmitting()) {
+      int ps_rate=192000;
+
+      ddc=receiver[PS_RX_FEEDBACK]->ddc;
+      receive_specific_buffer[5]|=receiver[PS_RX_FEEDBACK]->dither<<ddc; // dither enable
+      receive_specific_buffer[6]|=receiver[PS_RX_FEEDBACK]->random<<ddc; // random enable
+      receive_specific_buffer[17+(ddc*6)]=receiver[PS_RX_FEEDBACK]->adc;
+      receive_specific_buffer[18+(ddc*6)]=((ps_rate/1000)>>8)&0xFF;
+      receive_specific_buffer[19+(ddc*6)]=(ps_rate/1000)&0xFF;
+      receive_specific_buffer[22+(ddc*6)]=24;
+
+      ddc=receiver[PS_TX_FEEDBACK]->ddc;
+      receive_specific_buffer[5]|=receiver[PS_TX_FEEDBACK]->dither<<ddc; // dither enable
+      receive_specific_buffer[6]|=receiver[PS_TX_FEEDBACK]->random<<ddc; // random enable
+      receive_specific_buffer[17+(ddc*6)]=receiver[PS_TX_FEEDBACK]->adc;
+      receive_specific_buffer[18+(ddc*6)]=((ps_rate/1000)>>8)&0xFF;
+      receive_specific_buffer[19+(ddc*6)]=(ps_rate/1000)&0xFF;
+      receive_specific_buffer[22+(ddc*6)]=24;
+      receive_specific_buffer[1363]=0x02; // sync DDC1 to DDC0
+
+      ddc=0;
+      receive_specific_buffer[7]|=(1<<ddc); // DDC enable
+    }
+#endif
 
-    if(sendto(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&receiver_addr,receiver_addr_length)<0) {
+//fprintf(stderr,"new_protocol_receive_specific: enable=%02X\n",receive_specific_buffer[7]);
+    if(sendto(data_socket,receive_specific_buffer,sizeof(receive_specific_buffer),0,(struct sockaddr*)&receiver_addr,receiver_addr_length)<0) {
         fprintf(stderr,"sendto socket failed for start\n");
         exit(1);
     }
@@ -724,7 +1014,6 @@ static void new_protocol_receive_specific() {
 }
 
 static void new_protocol_start() {
-    running=1;
     new_protocol_transmit_specific();
     new_protocol_receive_specific();
     new_protocol_timer_thread_id = g_thread_new( "new protocol timer", new_protocol_timer_thread, NULL);
@@ -738,12 +1027,13 @@ static void new_protocol_start() {
 }
 
 void new_protocol_stop() {
-    new_protocol_high_priority(0);
+    running=0;
+    new_protocol_high_priority();
     usleep(100000); // 100 ms
 }
 
 void new_protocol_run() {
-    new_protocol_high_priority(1);
+    new_protocol_high_priority();
 }
 
 double calibrate(int v) {
@@ -754,11 +1044,13 @@ double calibrate(int v) {
     return (v1*v1)/0.095;
 }
 
-//void* new_protocol_thread(void* arg) {
 static gpointer new_protocol_thread(gpointer data) {
 
     int i;
+    int ddc;
     short sourceport;
+    unsigned char *buffer;
+    int bytesread;
 
 fprintf(stderr,"new_protocol_thread\n");
 
@@ -766,6 +1058,7 @@ fprintf(stderr,"new_protocol_thread\n");
     iqindex=4;
 
 
+/*
     data_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
     if(data_socket<0) {
         fprintf(stderr,"metis: create socket failed for data_socket\n");
@@ -774,6 +1067,7 @@ fprintf(stderr,"new_protocol_thread\n");
 
     int optval = 1;
     setsockopt(data_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+    setsockopt(data_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
 
     // bind to the interface
     if(bind(data_socket,(struct sockaddr*)&radio->info.network.interface_address,radio->info.network.interface_length)<0) {
@@ -781,6 +1075,8 @@ fprintf(stderr,"new_protocol_thread\n");
         exit(-1);
     }
 
+fprintf(stderr,"new_protocol_thread: date_socket %d bound to interface\n");
+
     memcpy(&base_addr,&radio->info.network.address,radio->info.network.address_length);
     base_addr_length=radio->info.network.address_length;
     base_addr.sin_port=htons(GENERAL_REGISTERS_FROM_HOST_PORT);
@@ -797,6 +1093,8 @@ fprintf(stderr,"new_protocol_thread\n");
     high_priority_addr_length=radio->info.network.address_length;
     high_priority_addr.sin_port=htons(HIGH_PRIORITY_FROM_HOST_PORT);
 
+fprintf(stderr,"new_protocol_thread: high_priority_addr setup for port %d\n",HIGH_PRIORITY_FROM_HOST_PORT);
+
     memcpy(&audio_addr,&radio->info.network.address,radio->info.network.address_length);
     audio_addr_length=radio->info.network.address_length;
     audio_addr.sin_port=htons(AUDIO_FROM_HOST_PORT);
@@ -812,25 +1110,26 @@ fprintf(stderr,"new_protocol_thread\n");
         data_addr[i].sin_port=htons(RX_IQ_TO_HOST_PORT_0+i);
         samples[i]=0;
     }
-
+*/
     audioindex=4; // leave space for sequence
     audiosequence=0L;
 
+    running=1;
     new_protocol_general();
     new_protocol_start();
-    new_protocol_high_priority(1);
+    new_protocol_high_priority();
 
     while(running) {
-        bytesread=recvfrom(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&addr,&length);
+
+        buffer=malloc(NET_BUFFER_SIZE);
+        bytesread=recvfrom(data_socket,buffer,NET_BUFFER_SIZE,0,(struct sockaddr*)&addr,&length);
         if(bytesread<0) {
             fprintf(stderr,"recvfrom socket failed for new_protocol_thread");
-            exit(1);
+            exit(-1);
         }
 
         short sourceport=ntohs(addr.sin_port);
 
-//fprintf(stderr,"received packet length %d from port %d\n",bytesread,sourceport);
-
         switch(sourceport) {
             case RX_IQ_TO_HOST_PORT_0:
             case RX_IQ_TO_HOST_PORT_1:
@@ -840,49 +1139,103 @@ fprintf(stderr,"new_protocol_thread\n");
             case RX_IQ_TO_HOST_PORT_5:
             case RX_IQ_TO_HOST_PORT_6:
             case RX_IQ_TO_HOST_PORT_7:
-              i=sourceport-RX_IQ_TO_HOST_PORT_0;
-              //if(device==NEW_DEVICE_ORION2 && i==3) {
-              //  i=1;
-              //}
-              process_iq_data(receiver[i],buffer);
+              ddc=sourceport-RX_IQ_TO_HOST_PORT_0;
+//fprintf(stderr,"iq packet from port=%d ddc=%d\n",sourceport,ddc);
+              if(ddc>=MAX_RECEIVERS)  {
+                fprintf(stderr,"unexpected iq data from ddc %d\n",ddc);
+              } else {
+                sem_wait(&iq_sem_ready[ddc]);
+                iq_buffer[ddc]=buffer;
+                sem_post(&iq_sem_buffer[ddc]);
+              }
               break;
             case COMMAND_RESPONCE_TO_HOST_PORT:
-              process_command_response(buffer);
+              sem_wait(&command_response_sem_ready);
+              command_response_buffer=buffer;
+              sem_post(&command_response_sem_buffer);
+              //process_command_response();
               break;
             case HIGH_PRIORITY_TO_HOST_PORT:
-              process_high_priority(buffer);
+              sem_wait(&high_priority_sem_ready);
+              high_priority_buffer=buffer;
+              sem_post(&high_priority_sem_buffer);
+              //process_high_priority();
               break;
             case MIC_LINE_TO_HOST_PORT:
-              if(!transmitter->local_microphone) {
-                process_mic_data(buffer,bytesread);
-              }
+              sem_wait(&mic_line_sem_ready);
+              mic_line_buffer=buffer;
+              mic_bytes_read=bytesread;
+              sem_post(&mic_line_sem_buffer);
               break;
             default:
+fprintf(stderr,"new_protocol_thread: Unknown port %d\n",sourceport);
+              free(buffer);
               break;
         }
+    }
 
-        if(running) {
-           sem_wait(&send_high_priority_sem);
-           if(send_high_priority==1) {
-               new_protocol_high_priority(1);
-               send_high_priority=0;
-           }
-           sem_post(&send_high_priority_sem);
+    close(data_socket);
+}
 
-           sem_wait(&send_general_sem);
-           if(send_general==1) {
-               new_protocol_general();
-               send_general=0;
-           }
-           sem_post(&send_general_sem);
-       }
-        
+static gpointer command_response_thread(gpointer data) {
+  while(1) {
+fprintf(stderr,"command_response_thread\n");
+    sem_post(&command_response_sem_ready);
+    sem_wait(&command_response_sem_buffer);
+    process_command_response();
+    free(command_response_buffer);
+  }
+}
+
+static gpointer high_priority_thread(gpointer data) {
+fprintf(stderr,"high_priority_thread\n");
+  while(1) {
+    sem_post(&high_priority_sem_ready);
+    sem_wait(&high_priority_sem_buffer);
+    process_high_priority();
+    free(high_priority_buffer);
+  }
+}
+
+static gpointer mic_line_thread(gpointer data) {
+fprintf(stderr,"mic_line_thread\n");
+  while(1) {
+    sem_post(&mic_line_sem_ready);
+    sem_wait(&mic_line_sem_buffer);
+    if(!transmitter->local_microphone) {
+      process_mic_data(mic_bytes_read);
     }
+    free(mic_line_buffer);
+  }
+}
 
-    close(data_socket);
+static gpointer iq_thread(gpointer data) {
+  int rx=(uintptr_t)data;
+  int ddc=receiver[rx]->ddc;
+fprintf(stderr,"iq_thread: rx=%d ddc=%d\n",rx,ddc);
+  while(1) {
+    sem_post(&iq_sem_ready[ddc]);
+    sem_wait(&iq_sem_buffer[ddc]);
+    process_iq_data(receiver[rx]);
+    free(iq_buffer[ddc]);
+  }
 }
 
-static void process_iq_data(RECEIVER *rx,unsigned char *buffer) {
+#ifdef PURESIGNAL
+static gpointer ps_iq_thread(gpointer data) {
+  int rx=(uintptr_t)data;
+  int ddc=receiver[rx]->ddc;
+fprintf(stderr,"ps_iq_thread: rx=%d ddc=%d\n",rx,ddc);
+  while(1) {
+    sem_post(&iq_sem_ready[ddc]);
+    sem_wait(&iq_sem_buffer[ddc]);
+    process_ps_iq_data(receiver[rx]);
+    free(iq_buffer[ddc]);
+  }
+}
+#endif
+
+static void process_iq_data(RECEIVER *rx) {
   long sequence;
   long long timestamp;
   int bitspersample;
@@ -892,8 +1245,18 @@ static void process_iq_data(RECEIVER *rx,unsigned char *buffer) {
   int rightsample;
   double leftsampledouble;
   double rightsampledouble;
+  unsigned char *buffer;
+
+  buffer=iq_buffer[rx->ddc];
 
   sequence=((buffer[0]&0xFF)<<24)+((buffer[1]&0xFF)<<16)+((buffer[2]&0xFF)<<8)+(buffer[3]&0xFF);
+
+  if(rx->iq_sequence!=sequence) {
+    //fprintf(stderr,"rx %d sequence error: expected %ld got %ld\n",rx->id,rx->iq_sequence,sequence);
+    rx->iq_sequence=sequence;
+  }
+  rx->iq_sequence++;
+
   timestamp=((long long)(buffer[4]&0xFF)<<56)+((long long)(buffer[5]&0xFF)<<48)+((long long)(buffer[6]&0xFF)<<40)+((long long)(buffer[7]&0xFF)<<32);
   ((long long)(buffer[8]&0xFF)<<24)+((long long)(buffer[9]&0xFF)<<16)+((long long)(buffer[10]&0xFF)<<8)+(long long)(buffer[11]&0xFF);
   bitspersample=((buffer[12]&0xFF)<<8)+(buffer[13]&0xFF);
@@ -910,16 +1273,110 @@ static void process_iq_data(RECEIVER *rx,unsigned char *buffer) {
     rightsample |= (int)((((unsigned char)buffer[b++])<<8)&0xFF00);
     rightsample |= (int)((unsigned char)buffer[b++]&0xFF);
 
-    leftsampledouble=(double)leftsample/8388607.0; // for 24 bits
-    rightsampledouble=(double)rightsample/8388607.0; // for 24 bits
+    //leftsampledouble=(double)leftsample/8388607.0; // for 24 bits
+    //rightsampledouble=(double)rightsample/8388607.0; // for 24 bits
+    leftsampledouble=(double)leftsample/16777215.0; // for 24 bits
+    rightsampledouble=(double)rightsample/16777215.0; // for 24 bits
 
     add_iq_samples(rx, leftsampledouble,rightsampledouble);
   }
 }
 
-static void process_command_response(unsigned char *buffer) {
-    response_sequence=((buffer[0]&0xFF)<<24)+((buffer[1]&0xFF)<<16)+((buffer[2]&0xFF)<<8)+(buffer[3]&0xFF);
-    response=buffer[4]&0xFF;
+#ifdef PURESIGNAL
+static void process_ps_iq_data(RECEIVER *rx) {
+  long sequence;
+  long long timestamp;
+  int bitspersample;
+  int samplesperframe;
+  int b;
+  int leftsample0;
+  int rightsample0;
+  double leftsampledouble0;
+  double rightsampledouble0;
+  int leftsample1;
+  int rightsample1;
+  double leftsampledouble1;
+  double rightsampledouble1;
+  unsigned char *buffer;
+
+  int min_sample0;
+  int max_sample0;
+  int min_sample1;
+  int max_sample1;
+
+  buffer=iq_buffer[rx->ddc];
+
+  sequence=((buffer[0]&0xFF)<<24)+((buffer[1]&0xFF)<<16)+((buffer[2]&0xFF)<<8)+(buffer[3]&0xFF);
+
+  if(rx->iq_sequence!=sequence) {
+    //fprintf(stderr,"rx %d sequence error: expected %ld got %ld\n",rx->id,rx->iq_sequence,sequence);
+    rx->iq_sequence=sequence;
+  }
+  rx->iq_sequence++;
+
+  timestamp=((long long)(buffer[4]&0xFF)<<56)+((long long)(buffer[5]&0xFF)<<48)+((long long)(buffer[6]&0xFF)<<40)+((long long)(buffer[7]&0xFF)<<32);
+  ((long long)(buffer[8]&0xFF)<<24)+((long long)(buffer[9]&0xFF)<<16)+((long long)(buffer[10]&0xFF)<<8)+(long long)(buffer[11]&0xFF);
+  bitspersample=((buffer[12]&0xFF)<<8)+(buffer[13]&0xFF);
+  samplesperframe=((buffer[14]&0xFF)<<8)+(buffer[15]&0xFF);
+
+//fprintf(stderr,"process_ps_iq_data: rx=%d seq=%ld bitspersample=%d samplesperframe=%d\n",rx->id, sequence,bitspersample,samplesperframe);
+  b=16;
+  int i;
+  for(i=0;i<samplesperframe;i+=2) {
+    leftsample0   = (int)((signed char) buffer[b++])<<16;
+    leftsample0  |= (int)((((unsigned char)buffer[b++])<<8)&0xFF00);
+    leftsample0  |= (int)((unsigned char)buffer[b++]&0xFF);
+    rightsample0  = (int)((signed char)buffer[b++]) << 16;
+    rightsample0 |= (int)((((unsigned char)buffer[b++])<<8)&0xFF00);
+    rightsample0 |= (int)((unsigned char)buffer[b++]&0xFF);
+
+    leftsampledouble0=(double)leftsample0/8388607.0; // for 24 bits
+    rightsampledouble0=(double)rightsample0/8388607.0; // for 24 bits
+
+    leftsample1   = (int)((signed char) buffer[b++])<<16;
+    leftsample1  |= (int)((((unsigned char)buffer[b++])<<8)&0xFF00);
+    leftsample1  |= (int)((unsigned char)buffer[b++]&0xFF);
+    rightsample1  = (int)((signed char)buffer[b++]) << 16;
+    rightsample1 |= (int)((((unsigned char)buffer[b++])<<8)&0xFF00);
+    rightsample1 |= (int)((unsigned char)buffer[b++]&0xFF);
+
+    leftsampledouble1=(double)leftsample1/8388607.0; // for 24 bits
+    rightsampledouble1=(double)rightsample1/8388607.0; // for 24 bits
+
+    add_ps_iq_samples(transmitter, leftsampledouble0,rightsampledouble0,leftsampledouble1,rightsampledouble1);
+
+//fprintf(stderr,"%06x,%06x %06x,%06x\n",leftsample0,rightsample0,leftsample1,rightsample1);
+/*
+    if(i==0) {
+      min_sample0=leftsample0;
+      max_sample0=leftsample0;
+      min_sample1=leftsample1;
+      max_sample1=leftsample1;
+    } else {
+      if(leftsample0<min_sample0) {
+        min_sample0=leftsample0;
+      }
+      if(leftsample0>max_sample0) {
+        max_sample0=leftsample0;
+      }
+      if(leftsample1<min_sample1) {
+        min_sample1=leftsample1;
+      }
+      if(leftsample1>max_sample1) {
+        max_sample1=leftsample1;
+      }
+    }
+*/
+  }
+//fprintf(stderr,"0 - min=%d max=%d  1 - min=%d max=%d\n",min_sample0,max_sample0,min_sample1,max_sample1);
+
+}
+#endif
+
+
+static void process_command_response() {
+    response_sequence=((command_response_buffer[0]&0xFF)<<24)+((command_response_buffer[1]&0xFF)<<16)+((command_response_buffer[2]&0xFF)<<8)+(command_response_buffer[3]&0xFF);
+    response=command_response_buffer[4]&0xFF;
     fprintf(stderr,"response_sequence=%ld response=%d\n",response_sequence,response);
     sem_post(&response_sem);
 }
@@ -930,16 +1387,19 @@ static void process_high_priority(unsigned char *buffer) {
     int previous_dot;
     int previous_dash;
 
-    sequence=((buffer[0]&0xFF)<<24)+((buffer[1]&0xFF)<<16)+((buffer[2]&0xFF)<<8)+(buffer[3]&0xFF);
+    int id=active_receiver->id;
+
+    sequence=((high_priority_buffer[0]&0xFF)<<24)+((high_priority_buffer[1]&0xFF)<<16)+((high_priority_buffer[2]&0xFF)<<8)+(high_priority_buffer[3]&0xFF);
 
     previous_ptt=ptt;
     previous_dot=dot;
     previous_dash=dash;
 
-    ptt=buffer[4]&0x01;
-    dot=(buffer[4]>>1)&0x01;
-    dash=(buffer[4]>>2)&0x01;
+    ptt=high_priority_buffer[4]&0x01;
+    dot=(high_priority_buffer[4]>>1)&0x01;
+    dash=(high_priority_buffer[4]>>2)&0x01;
 
+/*
 if(ptt!=previous_ptt) {
   fprintf(stderr,"ptt=%d\n",ptt);
 }
@@ -949,35 +1409,74 @@ if(dot!=previous_dot) {
 if(dash!=previous_dash) {
   fprintf(stderr,"dash=%d\n",dash);
 }
-    pll_locked=(buffer[4]>>3)&0x01;
+*/
+    pll_locked=(high_priority_buffer[4]>>3)&0x01;
 
 
-    adc_overload=buffer[5]&0x01;
-    exciter_power=((buffer[6]&0xFF)<<8)|(buffer[7]&0xFF);
-    alex_forward_power=((buffer[14]&0xFF)<<8)|(buffer[15]&0xFF);
-    alex_reverse_power=((buffer[22]&0xFF)<<8)|(buffer[23]&0xFF);
-    supply_volts=((buffer[49]&0xFF)<<8)|(buffer[50]&0xFF);
+    adc_overload=high_priority_buffer[5]&0x01;
+    exciter_power=((high_priority_buffer[6]&0xFF)<<8)|(high_priority_buffer[7]&0xFF);
+    alex_forward_power=((high_priority_buffer[14]&0xFF)<<8)|(high_priority_buffer[15]&0xFF);
+    alex_reverse_power=((high_priority_buffer[22]&0xFF)<<8)|(high_priority_buffer[23]&0xFF);
+    supply_volts=((high_priority_buffer[49]&0xFF)<<8)|(high_priority_buffer[50]&0xFF);
 
-    if(previous_ptt!=ptt) {
-        g_idle_add(ptt_update,(gpointer)ptt);
+    if(previous_ptt!=ptt && vfo[id].mode!=modeCWU && vfo[id].mode!=modeCWL) {
+      g_idle_add(ext_ptt_update,(gpointer)(long)(ptt));
+    } else if(previous_dot!=dot && (vfo[id].mode==modeCWU || vfo[id].mode==modeCWL)) {
+      g_idle_add(ext_ptt_update,(gpointer)(long)(dot));
+    } else if(previous_dash!=dash && (vfo[id].mode==modeCWU || vfo[id].mode==modeCWL)) {
+      g_idle_add(ext_ptt_update,(gpointer)(long)(dash));
     }
 
 }
 
-static void process_mic_data(unsigned char *buffer,int bytes) {
+static void process_mic_data(int bytes) {
   long sequence;
   int b;
+  int i;
   short sample;
 
-  sequence=((buffer[0]&0xFF)<<24)+((buffer[1]&0xFF)<<16)+((buffer[2]&0xFF)<<8)+(buffer[3]&0xFF);
+  sequence=((mic_line_buffer[0]&0xFF)<<24)+((mic_line_buffer[1]&0xFF)<<16)+((mic_line_buffer[2]&0xFF)<<8)+(mic_line_buffer[3]&0xFF);
   b=4;
+  for(i=0;i<MIC_SAMPLES;i++) {
+    sample=(short)((mic_line_buffer[b++]<<8) | (mic_line_buffer[b++]&0xFF));
+#ifdef FREEDV
+    if(active_receiver->freedv) {
+      add_freedv_mic_sample(transmitter,sample);
+    } else {
+#endif
+      add_mic_sample(transmitter,sample);
+#ifdef FREEDV
+    }
+#endif
+  }
+}
+
+void new_protocol_process_local_mic(unsigned char *buffer,int le) {
+  int b;
   int i;
+  short sample;
+
+  b=0;
   for(i=0;i<MIC_SAMPLES;i++) {
-    sample=(short)((buffer[b++]<<8) | (buffer[b++]&0xFF));
-    add_mic_sample(transmitter,sample);
+    if(le) {
+      sample = (short)((buffer[b++]&0xFF) | (buffer[b++]<<8));
+    } else {
+      sample = (short)((buffer[b++]<<8) | (buffer[b++]&0xFF));
+    }
+#ifdef FREEDV
+    if(active_receiver->freedv) {
+      add_freedv_mic_sample(transmitter,sample);
+    } else {
+#endif
+      add_mic_sample(transmitter,sample);
+#ifdef FREEDV
+    }
+#endif
   }
+
 }
 
+
 void new_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right_audio_sample) {
   int rc;
 
@@ -999,7 +1498,7 @@ void new_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right
 
     rc=sendto(data_socket,audiobuffer,sizeof(audiobuffer),0,(struct sockaddr*)&audio_addr,audio_addr_length);
     if(rc!=sizeof(audiobuffer)) {
-      fprintf(stderr,"sendto socket failed for %d bytes of audio: %d\n",sizeof(audiobuffer),rc);
+      fprintf(stderr,"sendto socket failed for %ld bytes of audio: %d\n",sizeof(audiobuffer),rc);
     }
     audioindex=4;
     audiosequence++;
@@ -1030,38 +1529,22 @@ void new_protocol_iq_samples(int isample,int qsample) {
   }
 }
 
-void new_protocol_process_local_mic(unsigned char *buffer,int le) {
-  int b;
-  short micsample;
-  double micsampledouble;
-  double gain=pow(10.0, mic_gain / 20.0);
-
-  b=0;
-  int i,j,s;
-  for(i=0;i<MIC_SAMPLES;i++) {
-    if(le) {
-      micsample = (short)((buffer[b++]&0xFF) | (buffer[b++]<<8));
-    } else {
-      micsample = (short)((buffer[b++]<<8) | (buffer[b++]&0xFF));
-    }
-    add_mic_sample(transmitter,micsample);
-  }
-
-}
-
 void* new_protocol_timer_thread(void* arg) {
-  int count=0;
+  int specific=0;
 fprintf(stderr,"new_protocol_timer_thread\n");
   while(running) {
     usleep(100000); // 100ms
-    if(running) {
-      if(count==0) {
-        new_protocol_transmit_specific();
-        count=1;
-      } else {
-        new_protocol_receive_specific();
-        count=0;
-      }
-    }
+//    if(running) {
+//      switch(specific) {
+//        case 0:
+          new_protocol_transmit_specific();
+//          specific=1;
+//          break;
+//        case 1:
+          new_protocol_receive_specific();
+//          specific=0;
+//          break;
+//      }
+//    }
   }
 }
index ec3dd9f7dd413da8b15c770501df338b3d29a753..fa0906782551378b75b5d974ee744d694b3930ac 100644 (file)
@@ -66,22 +66,23 @@ extern int send_high_priority;
 extern int send_general;
 */
 
-void schedule_high_priority();
-void schedule_general();
+extern void schedule_high_priority();
+extern void schedule_general();
+extern void schedule_receive_specific();
 
-void new_protocol_init(int pixels);
-void new_protocol_stop();
-void new_protocol_run();
+extern void new_protocol_init(int pixels);
+extern void new_protocol_stop();
+extern void new_protocol_run();
 
-void filter_board_changed();
-void pa_changed();
-void tuner_changed();
-void cw_changed();
+extern void filter_board_changed();
+extern void pa_changed();
+extern void tuner_changed();
+extern void cw_changed();
 
-void setMox(int state);
-int getMox();
-void setTune(int state);
-int getTune();
+extern void setMox(int state);
+extern int getMox();
+extern void setTune(int state);
+extern int getTune();
 
 extern void new_protocol_process_local_mic(unsigned char *buffer,int le);
 extern void new_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right_audio_sample);
index 81ff5c0bda0c6ea10de0ae29ecd90da074aee693..d26f0d227dcd1f2165e650e38f686f48e75dcda1 100644 (file)
 
 #include <gtk/gtk.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 
+#include <wdsp.h>
+
 #include "new_menu.h"
 #include "noise_menu.h"
 #include "channel.h"
@@ -38,40 +41,77 @@ static GtkWidget *dialog=NULL;
 
 static GtkWidget *last_filter;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 update_noise() {
+  SetEXTANBRun(active_receiver->id, active_receiver->nb);
+  SetEXTNOBRun(active_receiver->id, active_receiver->nb2);
   SetRXAANRRun(active_receiver->id, active_receiver->nr);
   SetRXAEMNRRun(active_receiver->id, active_receiver->nr2);
   SetRXAANFRun(active_receiver->id, active_receiver->anf);
   SetRXASNBARun(active_receiver->id, active_receiver->snb);
-  vfo_update(NULL);
+  vfo_update();
+}
+
+static void nb_none_cb(GtkWidget *widget, gpointer data) {
+  active_receiver->nb=0;
+  active_receiver->nb2=0;
+  update_noise();
+}
+
+static void nb_cb(GtkWidget *widget, gpointer data) {
+  active_receiver->nb=1;
+  active_receiver->nb2=0;
+  update_noise();
+}
+
+static void nr_none_cb(GtkWidget *widget, gpointer data) {
+  active_receiver->nr=0;
+  active_receiver->nr2=0;
+  update_noise();
 }
 
 static void nr_cb(GtkWidget *widget, gpointer data) {
-  active_receiver->nr=active_receiver->nr==1?0:1;
+  active_receiver->nr=1;
+  active_receiver->nr2=0;
+  update_noise();
+}
+
+static void nb2_cb(GtkWidget *widget, gpointer data) {
+  active_receiver->nb=0;
+  active_receiver->nb2=1;
   update_noise();
 }
 
 static void nr2_cb(GtkWidget *widget, gpointer data) {
-  active_receiver->nr2=active_receiver->nr2==1?0:1;
+  active_receiver->nr=0;
+  active_receiver->nr2=2;
   update_noise();
 }
 
 static void anf_cb(GtkWidget *widget, gpointer data) {
-  active_receiver->anf=active_receiver->anf==1?0:1;
+  active_receiver->anf=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
   update_noise();
 }
 
 static void snb_cb(GtkWidget *widget, gpointer data) {
-  active_receiver->snb=active_receiver->snb==1?0:1;
+  active_receiver->snb=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
   update_noise();
 }
 
@@ -83,7 +123,11 @@ void noise_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  char title[64];
+  sprintf(title,"piHPSDR - Noise (RX %d VFO %s)",active_receiver->id,active_receiver->id==0?"A":"B");
+  gtk_window_set_title(GTK_WINDOW(dialog),title);
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -101,39 +145,90 @@ void noise_menu(GtkWidget *parent) {
   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 Noise");
+  GtkWidget *close_b=gtk_button_new_with_label("Close");
   g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
   gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
 
-  char label[32];
-  sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B");
-  GtkWidget *rx_label=gtk_label_new(label);
-  gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1);
+  int row=1;
+  int col=0;
+
+  GtkWidget *nb_title=gtk_label_new("Noise Blanker");
+  gtk_widget_show(nb_title);
+  gtk_grid_attach(GTK_GRID(grid),nb_title,col,row,1,1);
+
+  col++;
+
+  GtkWidget *nr_title=gtk_label_new("Noise Reduction");
+  gtk_widget_show(nr_title);
+  gtk_grid_attach(GTK_GRID(grid),nr_title,col,row,1,1);
+
+  row++;
+  col=0;
+
+  GtkWidget *b_nb_none=gtk_radio_button_new_with_label(NULL, "None");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nb_none), active_receiver->nb==0 && active_receiver->nb2==0);
+  gtk_widget_show(b_nb_none);
+  gtk_grid_attach(GTK_GRID(grid),b_nb_none,col,row,1,1);
+  g_signal_connect(b_nb_none,"pressed",G_CALLBACK(nb_none_cb),NULL);
+
+  col++;
 
-  GtkWidget *b_nr=gtk_check_button_new_with_label("NR");
+  GtkWidget *b_nr_none=gtk_radio_button_new_with_label(NULL, "None");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr_none), active_receiver->nr==0 && active_receiver->nr2==0);
+  gtk_widget_show(b_nr_none);
+  gtk_grid_attach(GTK_GRID(grid),b_nr_none,col,row,1,1);
+  g_signal_connect(b_nr_none,"pressed",G_CALLBACK(nr_none_cb),NULL);
+
+  col++;
+
+  GtkWidget *b_snb=gtk_check_button_new_with_label("SNB");
+  //gtk_widget_override_font(b_snb, pango_font_description_from_string("Arial 16"));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_snb), active_receiver->snb);
+  gtk_widget_show(b_snb);
+  gtk_grid_attach(GTK_GRID(grid),b_snb,col,row,1,1);
+  g_signal_connect(b_snb,"toggled",G_CALLBACK(snb_cb),NULL);
+
+  row++;
+  col=0;
+
+  GtkWidget *b_nb=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_nb_none),"NB");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nb), active_receiver->nb);
+  gtk_widget_show(b_nb);
+  gtk_grid_attach(GTK_GRID(grid),b_nb,col,row,1,1);
+  g_signal_connect(b_nb,"pressed",G_CALLBACK(nb_cb),NULL);
+
+  col++;
+
+  GtkWidget *b_nr=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_nr_none),"NR");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr), active_receiver->nr);
   gtk_widget_show(b_nr);
-  gtk_grid_attach(GTK_GRID(grid),b_nr,0,2,2,1);
-  g_signal_connect(b_nr,"toggled",G_CALLBACK(nr_cb),NULL);
+  gtk_grid_attach(GTK_GRID(grid),b_nr,col,row,1,1);
+  g_signal_connect(b_nr,"pressed",G_CALLBACK(nr_cb),NULL);
 
-  GtkWidget *b_nr2=gtk_check_button_new_with_label("NR2");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr2), active_receiver->nr2);
-  gtk_widget_show(b_nr2);
-  gtk_grid_attach(GTK_GRID(grid),b_nr2,0,3,2,1);
-  g_signal_connect(b_nr2,"toggled",G_CALLBACK(nr2_cb),NULL);
+  col++;
 
   GtkWidget *b_anf=gtk_check_button_new_with_label("ANF");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_anf), active_receiver->anf);
   gtk_widget_show(b_anf);
-  gtk_grid_attach(GTK_GRID(grid),b_anf,0,4,2,1);
+  gtk_grid_attach(GTK_GRID(grid),b_anf,col,row,1,1);
   g_signal_connect(b_anf,"toggled",G_CALLBACK(anf_cb),NULL);
-  GtkWidget *b_snb=gtk_check_button_new_with_label("SNB");
-  //gtk_widget_override_font(b_snb, pango_font_description_from_string("Arial 16"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_snb), active_receiver->snb);
-  gtk_widget_show(b_snb);
-  gtk_grid_attach(GTK_GRID(grid),b_snb,0,5,2,1);
-  g_signal_connect(b_snb,"toggled",G_CALLBACK(snb_cb),NULL);
+
+  row++;
+  col=0;
+
+  GtkWidget *b_nb2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_nb),"NB2");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nb2), active_receiver->nb2);
+  gtk_widget_show(b_nb2);
+  gtk_grid_attach(GTK_GRID(grid),b_nb2,col,row,1,1);
+  g_signal_connect(b_nb2,"pressed",G_CALLBACK(nb2_cb),NULL);
+
+  col++;
+
+  GtkWidget *b_nr2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_nr),"NR2");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr2), active_receiver->nr2);
+  gtk_widget_show(b_nr2);
+  gtk_grid_attach(GTK_GRID(grid),b_nr2,col,row,1,1);
+  g_signal_connect(b_nr2,"pressed",G_CALLBACK(nr2_cb),NULL);
 
   gtk_container_add(GTK_CONTAINER(content),grid);
 
index 73fc5677e1b7043eea5355ff352a2ac02c5641ba..a7f8ee398c2e28feeb39b6ce2584c41e3510376b 100644 (file)
--- a/oc_menu.c
+++ b/oc_menu.c
@@ -20,6 +20,8 @@
 #include <gtk/gtk.h>
 #include <semaphore.h>
 #include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "new_menu.h"
@@ -28,6 +30,7 @@
 #include "bandstack.h"
 #include "filter.h"
 #include "radio.h"
+#include "new_protocol.h"
 
 static GtkWidget *parent_window=NULL;
 
@@ -35,18 +38,27 @@ static GtkWidget *menu_b=NULL;
 
 static GtkWidget *dialog=NULL;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 oc_rx_cb(GtkWidget *widget, gpointer data) {
-  int b=((int)data)>>4;
-  int oc=((int)data)&0xF;
+  int b=((uintptr_t)data)>>4;
+  int oc=((uintptr_t)data)&0xF;
   BAND *band=band_get_band(b);
   int mask=0x01<<(oc-1);
 fprintf(stderr,"oc_rx_cb: band=%d oc=%d mask=%d\n",b,oc,mask);
@@ -62,8 +74,8 @@ fprintf(stderr,"oc_rx_cb: band=%d oc=%d mask=%d\n",b,oc,mask);
 }
 
 static void oc_tx_cb(GtkWidget *widget, gpointer data) {
-  int b=((int)data)>>4;
-  int oc=((int)data)&0xF;
+  int b=((uintptr_t)data)>>4;
+  int oc=((uintptr_t)data)&0xF;
   BAND *band=band_get_band(b);
   int mask=0x01<<(oc-1);
 
@@ -80,7 +92,7 @@ fprintf(stderr,"oc_tx_cb: band=%d oc=%d mask=%d\n",b,oc,mask);
 }
 
 static void oc_tune_cb(GtkWidget *widget, gpointer data) {
-  int oc=((int)data)&0xF;
+  int oc=((uintptr_t)data)&0xF;
   int mask=0x01<<(oc-1);
 fprintf(stderr,"oc_tune_cb: oc=%d mask=%d\n",oc,mask);
   if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
@@ -105,7 +117,9 @@ void oc_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - Open Collector Output");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -122,7 +136,7 @@ void oc_menu(GtkWidget *parent) {
   //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
   //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
 
-  GtkWidget *close_b=gtk_button_new_with_label("Close OC");
+  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);
 
@@ -159,9 +173,9 @@ void oc_menu(GtkWidget *parent) {
     gtk_grid_attach(GTK_GRID(grid),oc_tx_title,i+7,2,1,1);
   }
 
-  for(i=0;i<BANDS;i++) {
+  for(i=0;i<BANDS+XVTRS;i++) {
     BAND *band=band_get_band(i);
-
+    if(strlen(band->title)>0) {
     GtkWidget *band_label=gtk_label_new(band->title);
     //gtk_widget_override_font(band_label, pango_font_description_from_string("Arial 18"));
     gtk_widget_show(band_label);
@@ -175,17 +189,18 @@ void oc_menu(GtkWidget *parent) {
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (oc_rx_b), (band->OCrx&mask)==mask);
       gtk_widget_show(oc_rx_b);
       gtk_grid_attach(GTK_GRID(grid),oc_rx_b,j,i+3,1,1);
-      g_signal_connect(oc_rx_b,"toggled",G_CALLBACK(oc_rx_cb),(gpointer)(j+(i<<4)));
+      g_signal_connect(oc_rx_b,"toggled",G_CALLBACK(oc_rx_cb),(gpointer)(long)(j+(i<<4)));
 
       GtkWidget *oc_tx_b=gtk_check_button_new();
       //gtk_widget_override_font(oc_tx_b, pango_font_description_from_string("Arial 18"));
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (oc_tx_b), (band->OCtx&mask)==mask);
       gtk_widget_show(oc_tx_b);
       gtk_grid_attach(GTK_GRID(grid),oc_tx_b,j+7,i+3,1,1);
-      g_signal_connect(oc_tx_b,"toggled",G_CALLBACK(oc_tx_cb),(gpointer)(j+(i<<4)));
+      g_signal_connect(oc_tx_b,"toggled",G_CALLBACK(oc_tx_cb),(gpointer)(long)(j+(i<<4)));
 
     }
   }
+  }
 
   int mask;
   for(j=1;j<8;j++) {
@@ -202,7 +217,7 @@ void oc_menu(GtkWidget *parent) {
     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (oc_tune_b), (OCtune&mask)==mask);
     gtk_widget_show(oc_tune_b);
     gtk_grid_attach(GTK_GRID(grid),oc_tune_b,19,j+1,1,1);
-    g_signal_connect(oc_tune_b,"toggled",G_CALLBACK(oc_tune_cb),(gpointer)j);
+    g_signal_connect(oc_tune_b,"toggled",G_CALLBACK(oc_tune_cb),(gpointer)(long)j);
   }
 
   GtkWidget *oc_full_tune_time_title=gtk_label_new("Full Tune(ms):");
index 33c44cb18ead7ed82e4dea8b402d43e4fcf70c84..87992da38037ee42efa45d177c2cef4e73542a64 100644 (file)
@@ -29,7 +29,6 @@
 #include <net/if_arp.h>
 #include <net/if.h>
 #include <ifaddrs.h>
-#include <pthread.h>
 #include <string.h>
 #include <errno.h>
 
@@ -45,8 +44,6 @@ static int interface_length;
 static int discovery_socket;
 static struct sockaddr_in discovery_addr;
 
-//static pthread_t discover_thread_id;
-//static void* discover_receive_thread(void* arg);
 static GThread *discover_thread_id;
 static gpointer discover_receive_thread(gpointer data);
 
@@ -67,6 +64,7 @@ static void discover(struct ifaddrs* iface) {
 
     int optval = 1;
     setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+    setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
 
     sa = (struct sockaddr_in *) iface->ifa_addr;
     mask = (struct sockaddr_in *) iface->ifa_netmask;
@@ -99,13 +97,6 @@ static void discover(struct ifaddrs* iface) {
     to_addr.sin_addr.s_addr=htonl(INADDR_BROADCAST);
 
     // start a receive thread to collect discovery response packets
-/*
-    rc=pthread_create(&discover_thread_id,NULL,discover_receive_thread,NULL);
-    if(rc != 0) {
-        fprintf(stderr,"pthread_create failed on discover_receive_thread: rc=%d\n", rc);
-        exit(-1);
-    }
-*/
     discover_thread_id = g_thread_new( "old discover receive", discover_receive_thread, NULL);
     if( ! discover_thread_id )
     {
@@ -131,10 +122,6 @@ static void discover(struct ifaddrs* iface) {
     }
 
     // wait for receive thread to complete
-/*
-    void* status;
-    pthread_join(discover_thread_id,&status);
-*/
     g_thread_join(discover_thread_id);
 
     close(discovery_socket);
@@ -230,7 +217,6 @@ fprintf(stderr,"discover_receive_thread\n");
 
     }
     fprintf(stderr,"discovery: exiting discover_receive_thread\n");
-    //pthread_exit(NULL);
     g_thread_exit(NULL);
 }
 
index bf0f3efdcfd7e5fed291d4b0cff8310911985308..4dbbb3655d2bd7e027660b978bf743f59689b86e 100644 (file)
@@ -56,6 +56,8 @@
 #include "psk.h"
 #endif
 #include "vox.h"
+#include "ext.h"
+#include "error_handler.h"
 
 #define min(x,y) (x<y?x:y)
 
@@ -135,7 +137,6 @@ static int samples=0;
 static int mic_samples=0;
 static int mic_sample_divisor=1;
 #ifdef FREEDV
-static int freedv_samples=0;
 static int freedv_divisor=6;
 #endif
 #ifdef PSK
@@ -143,25 +144,8 @@ static int psk_samples=0;
 static int psk_divisor=6;
 #endif
 
-//static float left_input_buffer[BUFFER_SIZE];
-//static float right_input_buffer[BUFFER_SIZE];
-//static double iqinputbuffer[MAX_RECEIVERS][MAX_BUFFER_SIZE*2];
-
-//static float mic_left_buffer[MAX_BUFFER_SIZE];
-//static float mic_right_buffer[MAX_BUFFER_SIZE];
 static double micinputbuffer[MAX_BUFFER_SIZE*2];
 
-//static float left_output_buffer[OUTPUT_BUFFER_SIZE];
-//static float right_output_buffer[OUTPUT_BUFFER_SIZE];
-//static double audiooutputbuffer[MAX_BUFFER_SIZE*2];
-
-//static float left_subrx_output_buffer[OUTPUT_BUFFER_SIZE];
-//static float right_subrx_output_buffer[OUTPUT_BUFFER_SIZE];
-
-//static float left_tx_buffer[OUTPUT_BUFFER_SIZE];
-//static float right_tx_buffer[OUTPUT_BUFFER_SIZE];
-//static double iqoutputbuffer[MAX_BUFFER_SIZE*2];
-
 static int left_rx_sample;
 static int right_rx_sample;
 static int left_tx_sample;
@@ -170,7 +154,7 @@ static int right_tx_sample;
 static unsigned char output_buffer[OZY_BUFFER_SIZE];
 static int output_buffer_index=8;
 
-static int command=0;
+static int command=1;
 
 static GThread *receive_thread_id;
 static void start_receive_thread();
@@ -183,9 +167,6 @@ static unsigned char metis_buffer[1032];
 static long send_sequence=-1;
 static int metis_offset=8;
 
-static int frequencyChanged=0;
-static sem_t frequency_changed_sem;
-
 static int metis_write(unsigned char ep,char* buffer,int length);
 static void metis_start_stop(int command);
 static void metis_send_buffer(char* buffer,int length);
@@ -214,10 +195,6 @@ static unsigned char ep6_inbuffer[EP6_BUFFER_SIZE];
 static unsigned char usb_buffer_block = 0;
 #endif
 
-void schedule_frequency_changed() {
-    frequencyChanged=1;
-}
-
 void old_protocol_stop() {
   metis_start_stop(0);
 }
@@ -355,8 +332,22 @@ static void start_receive_thread() {
       }
 
       int optval = 1;
-      setsockopt(data_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+      if(setsockopt(data_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))<0) {
+        perror("data_socket: SO_REUSEADDR");
+      }
+      if(setsockopt(data_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval))<0) {
+        perror("data_socket: SO_REUSEPORT");
+      }
 
+/*
+      // set a timeout for receive
+      struct timeval tv;
+      tv.tv_sec=1;
+      tv.tv_usec=0;
+      if(setsockopt(data_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))<0) {
+        perror("data_socket: SO_RCVTIMEO");
+      }
+*/
       // bind to the interface
       if(bind(data_socket,(struct sockaddr*)&radio->info.network.interface_address,radio->info.network.interface_length)<0) {
         perror("old_protocol: bind socket failed for data_socket\n");
@@ -403,8 +394,13 @@ static gpointer receive_thread(gpointer arg) {
       default:
         bytes_read=recvfrom(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&addr,&length);
         if(bytes_read<0) {
-          perror("recvfrom socket failed for old_protocol: receive_thread");
-          exit(1);
+          if(errno==EAGAIN) {
+            error_handler("old_protocol: receiver_thread: recvfrom socket failed","Radio not sending data");
+          } else {
+            error_handler("old_protocol: receiver_thread: recvfrom socket failed",strerror(errno));
+          }
+          running=0;
+          continue;
         }
 
         if(buffer[0]==0xEF && buffer[1]==0xFE) {
@@ -473,6 +469,17 @@ static void process_ozy_input_buffer(char  *buffer) {
   double right_sample_double;
   double mic_sample_double;
   double gain=pow(10.0, mic_gain / 20.0);
+  int left_sample_1;
+  int right_sample_1;
+  double left_sample_double_rx;
+  double right_sample_double_rx;
+  double left_sample_double_tx;
+  double right_sample_double_tx;
+  int nreceivers;
+
+  int id=active_receiver->id;
+
+  int tx_vfo=split?VFO_B:VFO_A;
 
   if(buffer[b++]==SYNC && buffer[b++]==SYNC && buffer[b++]==SYNC) {
     // extract control bytes
@@ -489,6 +496,7 @@ static void process_ozy_input_buffer(char  *buffer) {
     dash=(control_in[0]&0x02)==0x02;
     dot=(control_in[0]&0x04)==0x04;
 
+/*
 if(ptt!=previous_ptt) {
   fprintf(stderr,"ptt=%d\n",ptt);
 }
@@ -498,9 +506,24 @@ if(dot!=previous_dot) {
 if(dash!=previous_dash) {
   fprintf(stderr,"dash=%d\n",dash);
 }
+    if(previous_ptt!=ptt && vfo[tx_vfo].mode!=modeCWU && vfo[tx_vfo].mode!=modeCWL) {
+      g_idle_add(ext_ptt_update,(gpointer)(long)(ptt));
+    } else if(previous_dot!=dot && (vfo[tx_vfo].mode==modeCWU || vfo[tx_vfo].mode==modeCWL)) {
+      g_idle_add(ext_ptt_update,(gpointer)(long)(dot));
+    } else if(previous_dash!=dash && (vfo[tx_vfo].mode==modeCWU || vfo[tx_vfo].mode==modeCWL)) {
+      g_idle_add(ext_ptt_update,(gpointer)(long)(dash));
+    }
+*/
+
+    if(vfo[tx_vfo].mode==modeCWL || vfo[tx_vfo].mode==modeCWU) {
+      if(dot==0 && dash==0) {
+        ptt=0;
+      }
+    }
 
-    if(previous_ptt!=ptt || dot!=previous_dot || dash!=previous_dash) {
-      g_idle_add(ptt_update,(gpointer)(ptt | dot | dash));
+    if(previous_ptt!=ptt) {
+//fprintf(stderr,"ptt=%d previous_ptt=%d dot=%d dash=%d vfo=%d mode=%d\n",ptt,previous_ptt,dot,dash,tx_vfo,vfo[tx_vfo].mode);
+      g_idle_add(ext_ptt_update,(gpointer)(long)(ptt));
     }
 
     switch((control_in[0]>>3)&0x1F) {
@@ -537,10 +560,15 @@ if(dash!=previous_dash) {
     }
 
 
-    int iq_samples=(512-8)/((RECEIVERS*6)+2);
+#ifdef PURESIGNAL
+    nreceivers=(RECEIVERS*2)+1;
+#else
+    nreceivers=RECEIVERS;
+#endif
+    int iq_samples=(512-8)/((nreceivers*6)+2);
 
     for(i=0;i<iq_samples;i++) {
-      for(r=0;r<RECEIVERS;r++) {
+      for(r=0;r<nreceivers;r++) {
         left_sample   = (int)((signed char) buffer[b++])<<16;
         left_sample  |= (int)((((unsigned char)buffer[b++])<<8)&0xFF00);
         left_sample  |= (int)((unsigned char)buffer[b++]&0xFF);
@@ -551,14 +579,81 @@ if(dash!=previous_dash) {
         left_sample_double=(double)left_sample/8388607.0; // 24 bit sample 2^23-1
         right_sample_double=(double)right_sample/8388607.0; // 24 bit sample 2^23-1
 
+#ifdef PURESIGNAL
+        if(!isTransmitting() || (isTransmitting() && !transmitter->puresignal)) {
+          switch(r) {
+            case 0:
+              add_iq_samples(receiver[0], left_sample_double,right_sample_double);
+              break;
+            case 1:
+              break;
+            case 2:
+              add_iq_samples(receiver[1], left_sample_double,right_sample_double);
+              break;
+            case 3:
+              break;
+            case 4:
+              break;
+          }
+        } else {
+          switch(r) {
+            case 0:
+              if(device==DEVICE_METIS)  {
+                left_sample_double_rx=left_sample_double;
+                right_sample_double_rx=right_sample_double;
+              }
+              break;
+            case 1:
+              if(device==DEVICE_METIS)  {
+                left_sample_double_tx=left_sample_double;
+                right_sample_double_tx=right_sample_double;
+                add_ps_iq_samples(transmitter, left_sample_double_rx,right_sample_double_rx,left_sample_double_tx,right_sample_double_tx);
+              }
+              break;
+            case 2:
+              if(device==DEVICE_HERMES)  {
+                left_sample_double_rx=left_sample_double;
+                right_sample_double_rx=right_sample_double;
+              }
+              break;
+            case 3:
+              if(device==DEVICE_METIS)  {
+                left_sample_double_tx=left_sample_double;
+                right_sample_double_tx=right_sample_double;
+                add_ps_iq_samples(transmitter, left_sample_double_tx,right_sample_double_tx,left_sample_double_rx,right_sample_double_rx);
+              } else if(device==DEVICE_ANGELIA || device==DEVICE_ORION || device==DEVICE_ORION2) {
+                left_sample_double_rx=left_sample_double;
+                right_sample_double_rx=right_sample_double;
+              }
+              break;
+            case 4:
+              if(device==DEVICE_ANGELIA || device==DEVICE_ORION || device==DEVICE_ORION2) {
+                left_sample_double_tx=left_sample_double;
+                right_sample_double_tx=right_sample_double;
+                add_ps_iq_samples(transmitter, left_sample_double_tx,right_sample_double_tx,left_sample_double_rx,right_sample_double_rx);
+              }
+              break;
+          }
+        }
+#else
         add_iq_samples(receiver[r], left_sample_double,right_sample_double);
+#endif
       }
+
       mic_sample  = (short)(buffer[b++]<<8);
       mic_sample |= (short)(buffer[b++]&0xFF);
       if(!transmitter->local_microphone) {
         mic_samples++;
         if(mic_samples>=mic_sample_divisor) { // reduce to 48000
-          add_mic_sample(transmitter,mic_sample);
+#ifdef FREEDV
+          if(active_receiver->freedv) {
+            add_freedv_mic_sample(transmitter,mic_sample);
+          } else {
+#endif
+            add_mic_sample(transmitter,mic_sample);
+#ifdef FREEDV
+          }
+#endif
           mic_samples=0;
         }
       }
@@ -615,17 +710,26 @@ void old_protocol_iq_samples(int isample,int qsample) {
 
 void old_protocol_process_local_mic(unsigned char *buffer,int le) {
   int b;
-  short mic_sample;
+  int i;
+  short sample;
+
 // always 48000 samples per second
   b=0;
-  int i,j,s;
   for(i=0;i<720;i++) {
     if(le) {
-      mic_sample = (short)((buffer[b++]&0xFF) | (buffer[b++]<<8));
+      sample = (short)((buffer[b++]&0xFF) | (buffer[b++]<<8));
     } else {
-      mic_sample = (short)((buffer[b++]<<8) | (buffer[b++]&0xFF));
+      sample = (short)((buffer[b++]<<8) | (buffer[b++]&0xFF));
     }
-    add_mic_sample(transmitter,mic_sample);
+#ifdef FREEDV
+    if(active_receiver->freedv) {
+      add_freedv_mic_sample(transmitter,sample);
+    } else {
+#endif
+      add_mic_sample(transmitter,sample);
+#ifdef FREEDV
+    }
+#endif
   }
 }
 
@@ -641,313 +745,398 @@ void ozy_send_buffer() {
   int mode;
   int i;
   BAND *band;
+  int nreceivers;
 
   output_buffer[SYNC0]=SYNC;
   output_buffer[SYNC1]=SYNC;
   output_buffer[SYNC2]=SYNC;
 
-  switch(command) {
-    case 0:
-      {
-   
-      output_buffer[C0]=0x00;
-
-      output_buffer[C1]=0x00;
-      switch(active_receiver->sample_rate) {
-        case 48000:
-          output_buffer[C1]|=SPEED_48K;
-          break;
-        case 96000:
-          output_buffer[C1]|=SPEED_96K;
-          break;
-        case 192000:
-          output_buffer[C1]|=SPEED_192K;
-          break;
-        case 384000:
-          output_buffer[C1]|=SPEED_384K;
-          break;
-      }
+  if(metis_offset==8) {
+    output_buffer[C0]=0x00;
+    output_buffer[C1]=0x00;
+    switch(active_receiver->sample_rate) {
+      case 48000:
+        output_buffer[C1]|=SPEED_48K;
+        break;
+      case 96000:
+        output_buffer[C1]|=SPEED_96K;
+        break;
+      case 192000:
+        output_buffer[C1]|=SPEED_192K;
+        break;
+      case 384000:
+        output_buffer[C1]|=SPEED_384K;
+        break;
+    }
 
 // set more bits for Atlas based device
 // CONFIG_BOTH seems to be critical to getting ozy to respond
 #ifdef USBOZY
-      if ((device == DEVICE_OZY) || (device == DEVICE_METIS))
+    if ((device == DEVICE_OZY) || (device == DEVICE_METIS))
 #else
-      if (device == DEVICE_METIS)
+    if (device == DEVICE_METIS)
 #endif
-      {
-        if (atlas_mic_source)
-          output_buffer[C1] |= PENELOPE_MIC;
-        output_buffer[C1] |= CONFIG_BOTH;
-        if (atlas_clock_source_128mhz)
-          output_buffer[C1] |= MERCURY_122_88MHZ_SOURCE;
-        output_buffer[C1] |= ((atlas_clock_source_10mhz & 3) << 2);
-      }
+    {
+      if (atlas_mic_source)
+        output_buffer[C1] |= PENELOPE_MIC;
+      output_buffer[C1] |= CONFIG_BOTH;
+      if (atlas_clock_source_128mhz)
+        output_buffer[C1] |= MERCURY_122_88MHZ_SOURCE;
+      output_buffer[C1] |= ((atlas_clock_source_10mhz & 3) << 2);
+    }
 
-      output_buffer[C2]=0x00;
-      if(classE) {
-        output_buffer[C2]|=0x01;
+    output_buffer[C2]=0x00;
+    if(classE) {
+      output_buffer[C2]|=0x01;
+    }
+    band=band_get_band(vfo[VFO_A].band);
+    if(isTransmitting()) {
+      if(split) {
+        band=band_get_band(vfo[VFO_B].band);
       }
-      band=band_get_band(vfo[VFO_A].band);
-      if(isTransmitting()) {
-        if(split) {
-          band=band_get_band(vfo[VFO_B].band);
-        }
-        output_buffer[C2]|=band->OCtx<<1;
-        if(tune) {
-          if(OCmemory_tune_time!=0) {
-            struct timeval te;
-            gettimeofday(&te,NULL);
-            long long now=te.tv_sec*1000LL+te.tv_usec/1000;
-            if(tune_timeout>now) {
-              output_buffer[C2]|=OCtune<<1;
-            }
-          } else {
+      output_buffer[C2]|=band->OCtx<<1;
+      if(tune) {
+        if(OCmemory_tune_time!=0) {
+          struct timeval te;
+          gettimeofday(&te,NULL);
+          long long now=te.tv_sec*1000LL+te.tv_usec/1000;
+          if(tune_timeout>now) {
             output_buffer[C2]|=OCtune<<1;
           }
+        } else {
+          output_buffer[C2]|=OCtune<<1;
         }
-      } else {
-        output_buffer[C2]|=band->OCrx<<1;
       }
+    } else {
+      output_buffer[C2]|=band->OCrx<<1;
+    }
 
 // TODO - add Alex Attenuation and Alex Antenna
-      output_buffer[C3]=0x00;
-      if(active_receiver->random) {
-        output_buffer[C3]|=LT2208_RANDOM_ON;
-      }
-      if(active_receiver->dither) {
-        output_buffer[C3]|=LT2208_DITHER_ON;
-      }
-      if(active_receiver->preamp) {
-        output_buffer[C3]|=LT2208_GAIN_ON;
-      }
+    output_buffer[C3]=0x00;
+    if(active_receiver->random) {
+      output_buffer[C3]|=LT2208_RANDOM_ON;
+    }
+    if(active_receiver->dither) {
+      output_buffer[C3]|=LT2208_DITHER_ON;
+    }
+    if(active_receiver->preamp) {
+      output_buffer[C3]|=LT2208_GAIN_ON;
+    }
+
+    switch(receiver[0]->alex_antenna) {
+      case 0:  // ANT 1
+        break;
+      case 1:  // ANT 2
+        break;
+      case 2:  // ANT 3
+        break;
+      case 3:  // EXT 1
+        //output_buffer[C3]|=0xA0;
+        output_buffer[C3]|=0xC0;
+        break;
+      case 4:  // EXT 2
+        //output_buffer[C3]|=0xC0;
+        output_buffer[C3]|=0xA0;
+        break;
+      case 5:  // XVTR
+        output_buffer[C3]|=0xE0;
+        break;
+      default:
+        break;
+    }
+
 
+// TODO - add Alex TX relay, duplex, receivers Mercury board frequency
+    output_buffer[C4]=0x04;  // duplex
+#ifdef PURESIGNAL
+    nreceivers=(RECEIVERS*2)-1;
+    nreceivers+=1; // for PS TX Feedback
+#else
+    nreceivers=RECEIVERS-1;
+#endif
+    output_buffer[C4]|=nreceivers<<3;
+    
+    if(isTransmitting()) {
+      switch(transmitter->alex_antenna) {
+        case 0:  // ANT 1
+          output_buffer[C4]|=0x00;
+          break;
+        case 1:  // ANT 2
+          output_buffer[C4]|=0x01;
+          break;
+        case 2:  // ANT 3
+          output_buffer[C4]|=0x02;
+          break;
+        default:
+          break;
+      }
+    } else {
       switch(receiver[0]->alex_antenna) {
         case 0:  // ANT 1
+          output_buffer[C4]|=0x00;
           break;
         case 1:  // ANT 2
+          output_buffer[C4]|=0x01;
           break;
         case 2:  // ANT 3
+          output_buffer[C4]|=0x02;
           break;
         case 3:  // EXT 1
-          //output_buffer[C3]|=0xA0;
-          output_buffer[C3]|=0xC0;
-          break;
         case 4:  // EXT 2
-          //output_buffer[C3]|=0xC0;
-          output_buffer[C3]|=0xA0;
-          break;
         case 5:  // XVTR
-          output_buffer[C3]|=0xE0;
-          break;
-        default:
+          switch(transmitter->alex_antenna) {
+            case 0:  // ANT 1
+              output_buffer[C4]|=0x00;
+              break;
+            case 1:  // ANT 2
+              output_buffer[C4]|=0x01;
+              break;
+            case 2:  // ANT 3
+              output_buffer[C4]|=0x02;
+              break;
+          }
           break;
       }
-
-
-// TODO - add Alex TX relay, duplex, receivers Mercury board frequency
-      output_buffer[C4]=0x04;  // duplex
-      output_buffer[C4]|=(RECEIVERS-1)<<3;
-    
-      if(isTransmitting()) {
-        switch(transmitter->alex_antenna) {
-          case 0:  // ANT 1
-            output_buffer[C4]|=0x00;
-            break;
-          case 1:  // ANT 2
-            output_buffer[C4]|=0x01;
-            break;
-          case 2:  // ANT 3
-            output_buffer[C4]|=0x02;
-            break;
-          default:
-            break;
+    }
+  } else {
+    switch(command) {
+      case 1: // tx frequency
+        output_buffer[C0]=0x02;
+        long long txFrequency;
+        if(active_receiver->id==VFO_A) {
+          if(split) {
+            txFrequency=vfo[VFO_B].frequency-vfo[VFO_B].lo+vfo[VFO_B].offset;
+          } else {
+            txFrequency=vfo[VFO_A].frequency-vfo[VFO_A].lo+vfo[VFO_A].offset;
+          }
+        } else {
+          if(split) {
+            txFrequency=vfo[VFO_A].frequency-vfo[VFO_A].lo+vfo[VFO_A].offset;
+          } else {
+            txFrequency=vfo[VFO_B].frequency-vfo[VFO_B].lo+vfo[VFO_B].offset;
+          }
         }
-      } else {
-        switch(receiver[0]->alex_antenna) {
-          case 0:  // ANT 1
-            output_buffer[C4]|=0x00;
-            break;
-          case 1:  // ANT 2
-            output_buffer[C4]|=0x01;
-            break;
-          case 2:  // ANT 3
-            output_buffer[C4]|=0x02;
-            break;
-          case 3:  // EXT 1
-          case 4:  // EXT 2
-          case 5:  // XVTR
-            switch(transmitter->alex_antenna) {
-              case 0:  // ANT 1
-                output_buffer[C4]|=0x00;
-                break;
-              case 1:  // ANT 2
-                output_buffer[C4]|=0x01;
-                break;
-              case 2:  // ANT 3
-                output_buffer[C4]|=0x02;
-                break;
+        output_buffer[C1]=txFrequency>>24;
+        output_buffer[C2]=txFrequency>>16;
+        output_buffer[C3]=txFrequency>>8;
+        output_buffer[C4]=txFrequency;
+        break;
+      case 2: // rx frequency
+#ifdef PURESIGNAL
+        nreceivers=(RECEIVERS*2)+1;
+#else
+        nreceivers=RECEIVERS;
+#endif
+        if(current_rx<nreceivers) {
+          output_buffer[C0]=0x04+(current_rx*2);
+#ifdef PURESIGNAL
+          int v=receiver[current_rx/2]->id;
+          if(isTransmitting() && transmitter->puresignal) {
+            long long txFrequency;
+            if(active_receiver->id==VFO_A) {
+              if(split) {
+                txFrequency=vfo[VFO_B].frequency-vfo[VFO_B].lo+vfo[VFO_B].offset;
+              } else {
+                txFrequency=vfo[VFO_A].frequency-vfo[VFO_A].lo+vfo[VFO_A].offset;
+              }
+            } else {
+              if(split) {
+                txFrequency=vfo[VFO_A].frequency-vfo[VFO_A].lo+vfo[VFO_A].offset;
+              } else {
+                txFrequency=vfo[VFO_B].frequency-vfo[VFO_B].lo+vfo[VFO_B].offset;
+              }
+            }
+            output_buffer[C1]=txFrequency>>24;
+            output_buffer[C2]=txFrequency>>16;
+            output_buffer[C3]=txFrequency>>8;
+            output_buffer[C4]=txFrequency;
+          } else {
+#else
+          int v=receiver[current_rx]->id;
+#endif
+            long long rxFrequency=vfo[v].frequency-vfo[v].lo;
+            if(vfo[v].rit_enabled) {
+              rxFrequency+=vfo[v].rit;
+            }
+            if(vfo[v].mode==modeCWU) {
+              rxFrequency-=(long long)cw_keyer_sidetone_frequency;
+            } else if(vfo[v].mode==modeCWL) {
+              rxFrequency+=(long long)cw_keyer_sidetone_frequency;
             }
-            break;
+            output_buffer[C1]=rxFrequency>>24;
+            output_buffer[C2]=rxFrequency>>16;
+            output_buffer[C3]=rxFrequency>>8;
+            output_buffer[C4]=rxFrequency;
+#ifdef PURESIGNAL
+          }
+#endif
+          current_rx++;
         }
-      }
-      }
-      break;
-    case 1: // tx frequency
-      output_buffer[C0]=0x02;
-      long long txFrequency;
-      if(split) {
-        txFrequency=vfo[VFO_B].frequency-vfo[VFO_A].lo+vfo[VFO_B].offset;
-      } else {
-        txFrequency=vfo[VFO_A].frequency-vfo[VFO_B].lo+vfo[VFO_A].offset;
-      }
-      output_buffer[C1]=txFrequency>>24;
-      output_buffer[C2]=txFrequency>>16;
-      output_buffer[C3]=txFrequency>>8;
-      output_buffer[C4]=txFrequency;
-      break;
-    case 2: // rx frequency
-      if(current_rx<receivers) {
-        output_buffer[C0]=0x04+(current_rx*2);
-        int v=receiver[current_rx]->id;
-        long long rxFrequency=vfo[v].frequency-vfo[v].lo;
-        if(vfo[v].rit_enabled) {
-          rxFrequency+=vfo[v].rit;
+        if(current_rx>=nreceivers) {
+          current_rx=0;
         }
-        if(vfo[active_receiver->id].mode==modeCWU) {
-          rxFrequency-=(long long)cw_keyer_sidetone_frequency;
-        } else if(vfo[active_receiver->id].mode==modeCWL) {
-          rxFrequency+=(long long)cw_keyer_sidetone_frequency;
+        break;
+      case 3:
+        {
+        BAND *band=band_get_current_band();
+        int power=0;
+        if(isTransmitting()) {
+          if(tune && !transmitter->tune_use_drive) {
+            power=(int)((double)transmitter->drive_level/100.0*(double)transmitter->tune_percent);
+          } else {
+            power=transmitter->drive_level;
+          }
         }
-        output_buffer[C1]=rxFrequency>>24;
-        output_buffer[C2]=rxFrequency>>16;
-        output_buffer[C3]=rxFrequency>>8;
-        output_buffer[C4]=rxFrequency;
-        current_rx++;
-      }
-      if(current_rx>=receivers) {
-        current_rx=0;
-      }
-      break;
-    case 3:
-      {
-      BAND *band=band_get_current_band();
-      int power=0;
-      if(isTransmitting()) {
-        if(tune) {
-          power=tune_drive_level;
-        } else {
-          power=drive_level;
+  
+        output_buffer[C0]=0x12;
+        output_buffer[C1]=power&0xFF;
+        output_buffer[C2]=0x00;
+        if(mic_boost) {
+          output_buffer[C2]|=0x01;
+        }
+        if(mic_linein) {
+          output_buffer[C2]|=0x02;
+        }
+        if(filter_board==APOLLO) {
+          output_buffer[C2]|=0x2C;
+        }
+        if((filter_board==APOLLO) && tune) {
+          output_buffer[C2]|=0x10;
+        }
+        output_buffer[C3]=0x00;
+        if(band_get_current()==band6) {
+          output_buffer[C3]=output_buffer[C3]|0x40; // Alex 6M low noise amplifier
+        }
+        if(band->disablePA) {
+          output_buffer[C3]=output_buffer[C3]|0x80; // disable PA
         }
-      }
-
-      output_buffer[C0]=0x12;
-      output_buffer[C1]=power&0xFF;
-      output_buffer[C2]=0x00;
-      if(mic_boost) {
-        output_buffer[C2]|=0x01;
-      }
-      if(mic_linein) {
-        output_buffer[C2]|=0x02;
-      }
-      if(filter_board==APOLLO) {
-        output_buffer[C2]|=0x2C;
-      }
-      if((filter_board==APOLLO) && tune) {
-        output_buffer[C2]|=0x10;
-      }
-      output_buffer[C3]=0x00;
-      if(band_get_current()==band6) {
-        output_buffer[C3]=output_buffer[C3]|0x40; // Alex 6M low noise amplifier
-      }
-      if(band->disablePA) {
-        output_buffer[C3]=output_buffer[C3]|0x80; // disable PA
-      }
-      output_buffer[C4]=0x00;
-      }
-      break;
-    case 4:
-      output_buffer[C0]=0x14;
-      output_buffer[C1]=0x00;
-      for(i=0;i<receivers;i++) {
-        output_buffer[C1]|=(receiver[i]->preamp<<i);
-      }
-      if(mic_ptt_enabled==0) {
-        output_buffer[C1]|=0x40;
-      }
-      if(mic_bias_enabled) {
-        output_buffer[C1]|=0x20;
-      }
-      if(mic_ptt_tip_bias_ring) {
-        output_buffer[C1]|=0x10;
-      }
-      output_buffer[C2]=linein_gain;
-      output_buffer[C3]=0x00;
-
-      if(radio->device==DEVICE_HERMES || radio->device==DEVICE_ANGELIA || radio->device==DEVICE_ORION || radio->device==DEVICE_ORION2) {
-        output_buffer[C4]=0x20|receiver[0]->attenuation;
-      } else {
         output_buffer[C4]=0x00;
-      }
-      break;
-    case 5:
-      // need to add adc 2 and 3 attenuation
-      output_buffer[C0]=0x16;
-      output_buffer[C1]=0x00;
-      if(receivers==2) {
+        }
+        break;
+      case 4:
+        output_buffer[C0]=0x14;
+        output_buffer[C1]=0x00;
+        for(i=0;i<receivers;i++) {
+          output_buffer[C1]|=(receiver[i]->preamp<<i);
+        }
+        if(mic_ptt_enabled==0) {
+          output_buffer[C1]|=0x40;
+        }
+        if(mic_bias_enabled) {
+          output_buffer[C1]|=0x20;
+        }
+        if(mic_ptt_tip_bias_ring) {
+          output_buffer[C1]|=0x10;
+        }
+        output_buffer[C2]=0x00;
+        output_buffer[C2]|=linein_gain;
+#ifdef PURESIGNAL
+        if(transmitter->puresignal) {
+          output_buffer[C2]|=0x40;
+        }
+#endif
+        output_buffer[C3]=0x00;
+  
         if(radio->device==DEVICE_HERMES || radio->device==DEVICE_ANGELIA || radio->device==DEVICE_ORION || radio->device==DEVICE_ORION2) {
-          output_buffer[C1]=0x20|receiver[1]->attenuation;
+          output_buffer[C4]=0x20|receiver[0]->attenuation;
+        } else {
+          output_buffer[C4]=0x00;
         }
-      }
-      output_buffer[C2]=0x00;
-      if(cw_keys_reversed!=0) {
-        output_buffer[C2]|=0x40;
-      }
-      output_buffer[C3]=cw_keyer_speed | (cw_keyer_mode<<6);
-      output_buffer[C4]=cw_keyer_weight | (cw_keyer_spacing<<7);
-      break;
-    case 6:
-      // need to add tx attenuation and rx ADC selection
-      output_buffer[C0]=0x1C;
-      output_buffer[C1]=0x00;
-      output_buffer[C2]=0x00;
-      output_buffer[C3]=0x00;
-      output_buffer[C4]=0x00;
-      break;
-    case 7:
-      output_buffer[C0]=0x1E;
-      if(split) {
-        mode=vfo[1].mode;
-      } else {
-        mode=vfo[0].mode;
-      }
-      if(mode!=modeCWU && mode!=modeCWL) {
-        // output_buffer[C1]|=0x00;
-      } else {
-        if((tune==1) || (vox==1) || (cw_keyer_internal==0)) {
-          output_buffer[C1]|=0x00;
-        } else if(mox==1) {
-          output_buffer[C1]|=0x01;
+        break;
+      case 5:
+        // need to add adc 2 and 3 attenuation
+        output_buffer[C0]=0x16;
+        output_buffer[C1]=0x00;
+        if(receivers==2) {
+          if(radio->device==DEVICE_HERMES || radio->device==DEVICE_ANGELIA || radio->device==DEVICE_ORION || radio->device==DEVICE_ORION2) {
+            output_buffer[C1]=0x20|receiver[1]->attenuation;
+          }
+        }
+        output_buffer[C2]=0x00;
+        if(cw_keys_reversed!=0) {
+          output_buffer[C2]|=0x40;
+        }
+        output_buffer[C3]=cw_keyer_speed | (cw_keyer_mode<<6);
+        output_buffer[C4]=cw_keyer_weight | (cw_keyer_spacing<<7);
+        break;
+      case 6:
+        // need to add tx attenuation and rx ADC selection
+        output_buffer[C0]=0x1C;
+        output_buffer[C1]=0x00;
+#ifdef PURESIGNAL
+        output_buffer[C1]|=receiver[0]->adc;
+        output_buffer[C1]|=(receiver[0]->adc<<2);
+        output_buffer[C1]|=receiver[1]->adc<<4;
+        output_buffer[C1]|=(receiver[1]->adc<<6);
+        output_buffer[C2]=0x00;
+        if(transmitter->puresignal) {
+          output_buffer[C2]|=receiver[2]->adc;
         }
+#else
+        output_buffer[C1]|=receiver[0]->adc;
+        output_buffer[C1]|=(receiver[1]->adc<<2);
+#endif
+        output_buffer[C3]=0x00;
+        output_buffer[C3]|=transmitter->attenuation;
+        output_buffer[C4]=0x00;
+        break;
+      case 7:
+        output_buffer[C0]=0x1E;
+        if(split) {
+          mode=vfo[1].mode;
+        } else {
+          mode=vfo[0].mode;
+        }
+        output_buffer[C1]=0x00;
+        if(mode!=modeCWU && mode!=modeCWL) {
+          // output_buffer[C1]|=0x00;
+        } else {
+          if((tune==1) || (vox==1) || (cw_keyer_internal==0)) {
+            output_buffer[C1]|=0x00;
+          } else {
+            output_buffer[C1]|=0x01;
+          }
+        }
+        output_buffer[C2]=cw_keyer_sidetone_volume;
+        output_buffer[C3]=cw_keyer_ptt_delay;
+        output_buffer[C4]=0x00;
+        break;
+      case 8:
+        output_buffer[C0]=0x20;
+        output_buffer[C1]=(cw_keyer_hang_time>>2) & 0xFF;
+        output_buffer[C2]=cw_keyer_hang_time & 0x03;
+        output_buffer[C3]=(cw_keyer_sidetone_frequency>>4) & 0xFF;
+        output_buffer[C4]=cw_keyer_sidetone_frequency & 0x0F;
+        break;
+      case 9:
+        output_buffer[C0]=0x22;
+        output_buffer[C1]=(eer_pwm_min>>2) & 0xFF;
+        output_buffer[C2]=eer_pwm_min & 0x03;
+        output_buffer[C3]=(eer_pwm_max>>3) & 0xFF;
+        output_buffer[C4]=eer_pwm_max & 0x03;
+        break;
+      case 10:
+        output_buffer[C0]=0x24;
+        output_buffer[C1]=0x00;
+        if(isTransmitting()) {
+          output_buffer[C1]|=0x80; // ground RX1 on transmit
+        }
+        output_buffer[C2]=0x00;
+        if(receiver[0]->alex_antenna==5) { // XVTR
+          output_buffer[C2]=0x02;
+        }
+        output_buffer[C3]=0x00;
+        output_buffer[C4]=0x00;
+        break;
+    }
+
+    if(current_rx==0) {
+      command++;
+      if(command>10) {
+        command=1;
       }
-      output_buffer[C2]=cw_keyer_sidetone_volume;
-      output_buffer[C3]=cw_keyer_ptt_delay;
-      output_buffer[C4]=0x00;
-      break;
-    case 8:
-      output_buffer[C0]=0x20;
-      output_buffer[C1]=(cw_keyer_hang_time>>2) & 0xFF;
-      output_buffer[C2]=cw_keyer_hang_time & 0x03;
-      output_buffer[C3]=(cw_keyer_sidetone_frequency>>4) & 0xFF;
-      output_buffer[C4]=cw_keyer_sidetone_frequency & 0x0F;
-      break;
-    case 9:
-      output_buffer[C0]=0x22;
-      output_buffer[C1]=(eer_pwm_min>>2) & 0xFF;
-      output_buffer[C2]=eer_pwm_min & 0x03;
-      output_buffer[C3]=(eer_pwm_max>>3) & 0xFF;
-      output_buffer[C4]=eer_pwm_max & 0x03;
-      break;
+    }
+  
   }
 
   // set mox
@@ -976,11 +1165,6 @@ void ozy_send_buffer() {
 #endif
   metis_write(0x02,output_buffer,OZY_BUFFER_SIZE);
 
-  command++;
-  if(command>9) {
-    command=0;
-  }
-
   //fprintf(stderr,"C0=%02X C1=%02X C2=%02X C3=%02X C4=%02X\n",
   //                output_buffer[C0],output_buffer[C1],output_buffer[C2],output_buffer[C3],output_buffer[C4]);
 }
@@ -1052,15 +1236,23 @@ static int metis_write(unsigned char ep,char* buffer,int length) {
 }
 
 static void metis_restart() {
+  // reset metis frame
+  metis_offset==8;
+
+  // reset current rx
+  current_rx=0;
+
   // send commands twice
-  command=0;
+  command=1;
   do {
     ozy_send_buffer();
-  } while (command!=0);
+  } while (command!=1);
 
   do {
     ozy_send_buffer();
-  } while (command!=0);
+  } while (command!=1);
+
+  sleep(1);
 
   // start the data flowing
   metis_start_stop(1);
index 45107ee8dc4d74c2709e5a8286810aec91208bb1..f179090afcc36ce58ce865a6d814ab43a4a64519 100644 (file)
@@ -26,7 +26,6 @@ extern void old_protocol_run();
 extern void old_protocol_init(int rx,int pixels,int rate);
 extern void old_protocol_set_mic_sample_rate(int rate);
 
-extern void schedule_frequency_changed();
 extern void old_protocol_process_local_mic(unsigned char *buffer,int le);
 extern void old_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right_audio_sample);
 extern void old_protocol_iq_samples(int isample,int qsample);
index 67cb6e64d9443334db7907a97862ce1f119c6316..aee51f6e39d41625dc3dc16afc71c7370563943b 100644 (file)
--- a/pa_menu.c
+++ b/pa_menu.c
@@ -34,15 +34,24 @@ static GtkWidget *menu_b=NULL;
 
 static GtkWidget *dialog=NULL;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 pa_value_changed_cb(GtkWidget *widget, gpointer data) {
   BAND *band=(BAND *)data;
   band->pa_calibration=gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget));
@@ -52,7 +61,6 @@ static void pa_value_changed_cb(GtkWidget *widget, gpointer data) {
   BAND *current=band_get_band(b);
   if(band==current) {
     calcDriveLevel();
-    calcTuneDriveLevel();
   }
 }
 
@@ -67,7 +75,9 @@ void pa_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - PA Calibration");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -84,7 +94,7 @@ void pa_menu(GtkWidget *parent) {
   //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
   //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
 
-  GtkWidget *close_b=gtk_button_new_with_label("Close PA Gain(dB)");
+  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);
 
index d960b1873ab955f0dacbb0614b17cdbdcd461243..110a60029ca43250dc3996192841cbb896158e3a 100644 (file)
@@ -75,7 +75,7 @@ void loadProperties(char* filename) {
 * @param filename
 */
 void saveProperties(char* filename) {
-    PROPERTY* property=properties;
+    PROPERTY* property;
     FILE* f=fopen(filename,"w+");
     char line[512];
     char version[32];
@@ -84,8 +84,9 @@ void saveProperties(char* filename) {
         return;
     }
 
-    sprintf(line,"%s=%0.2f\n","property_version",PROPERTY_VERSION);
-    fwrite(line,1,strlen(line),f);
+    sprintf(line,"%0.2f",PROPERTY_VERSION);
+    setProperty("property_version",line);
+    property=properties;
     while(property) {
         sprintf(line,"%s=%s\n",property->name,property->value);
         fwrite(line,1,strlen(line),f);
index 3fb103af6b22324ba3c5f584581f6f5fca3e8e9e..83e29ec0b0b3f65d182990e067f966d56929bdaa 100644 (file)
@@ -34,8 +34,10 @@ struct _PROPERTY {
     PROPERTY* next_property;
 };
 
-void loadProperties(char* filename);
-char* getProperty(char* name);
-void setProperty(char* name,char* value);
+extern void loadProperties(char* filename);
+extern char* getProperty(char* name);
+extern void setProperty(char* name,char* value);
+
+extern void saveProperties(char* filename);
 
 #endif
diff --git a/ps_menu.c b/ps_menu.c
new file mode 100644 (file)
index 0000000..46bee20
--- /dev/null
+++ b/ps_menu.c
@@ -0,0 +1,525 @@
+/*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#include <gtk/gtk.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wdsp.h>
+
+#include "button_text.h"
+//#include "led.h"
+#include "new_menu.h"
+#include "radio.h"
+#include "toolbar.h"
+#include "transmitter.h"
+#include "new_protocol.h"
+#include "vfo.h"
+#include "ext.h"
+
+static GtkWidget *parent_window=NULL;
+static GtkWidget *dialog=NULL;
+static GtkWidget *feedback_l;
+static GtkWidget *correcting_l;
+static GtkWidget *get_pk;
+static GtkWidget *set_pk;
+
+static GThread *info_thread_id;
+
+static int running=0;
+
+#define INFO_SIZE 16
+
+static GtkWidget *entry[INFO_SIZE];
+
+// results from GetPSDisp
+static double ps_x[4096];
+static double ps_ym[4096];
+static double ps_yc[4096];
+static double ps_ys[4096];
+static double ps_cm[64];
+static double ps_cc[64];
+static double ps_cs[64];
+
+static void destroy_cb(GtkWidget *widget, gpointer data) {
+//fprintf(stderr,"ps_menu: destroy_cb\n");
+  running=0;
+}
+
+static void cleanup() {
+  if(transmitter->twotone) {
+    tx_set_twotone(transmitter,0);
+  }
+  if(dialog!=NULL) {
+    gtk_widget_destroy(dialog);
+    dialog=NULL;
+    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 int deltadb=0;
+
+static gpointer info_thread(gpointer arg) {
+  static int info[16];
+  int i;
+  gchar *label;
+  static int old5=0;
+  static int old5_2=0;
+  static int old14=0;
+  int display;
+  int counter=0;
+  int state=0;
+  int save_auto_on;
+  int save_single_on;
+
+  if(transmitter->auto_on) {
+    transmitter->attenuation=31;
+  } else {
+    transmitter->attenuation=0;
+  }
+
+  running=1;
+  while(running) {
+    GetPSInfo(transmitter->id,&info[0]);
+    for(i=0;i<INFO_SIZE;i++) {
+      label=NULL;
+      display=1;
+      switch(i) {
+        case 0:
+          label=g_strdup_printf("%d",info[i]);
+          display=0;
+          break;
+        case 1:
+          label=g_strdup_printf("%d",info[i]);
+          display=0;
+          break;
+        case 2:
+          label=g_strdup_printf("%d",info[i]);
+          display=0;
+          break;
+        case 3:
+          label=g_strdup_printf("%d",info[i]);
+          display=0;
+          break;
+        case 4:
+          label=g_strdup_printf("%d",info[i]);
+          break;
+        case 5:
+          label=g_strdup_printf("%d",info[i]);
+          if(info[i]!=old5) {
+            old5=info[5];
+            if(info[4]>181)  {
+              gtk_label_set_markup(GTK_LABEL(feedback_l),"<span color='black'>Feedback Lvl</span>");
+            } else if(info[4]>128)  {
+              gtk_label_set_markup(GTK_LABEL(feedback_l),"<span color='green'>Feedback Lvl</span>");
+            } else if(info[4]>90)  {
+              gtk_label_set_markup(GTK_LABEL(feedback_l),"<span color='yellow'>Feedback Lvl</span>");
+            } else {
+              gtk_label_set_markup(GTK_LABEL(feedback_l),"<span color='red'>Feedback Lvl</span>");
+            }
+          }
+          break;
+        case 6:
+          label=g_strdup_printf("%d",info[i]);
+          break;
+        case 13:
+          label=g_strdup_printf("%d",info[i]);
+          break;
+        case 14:
+          label=g_strdup_printf("%d",info[i]);
+          if(info[14]!=old14) {
+            old14=info[14];
+            if(info[14]==0) {
+              gtk_label_set_markup(GTK_LABEL(correcting_l),"<span color='black'>Correcting</span>");
+            } else {
+              gtk_label_set_markup(GTK_LABEL(correcting_l),"<span color='green'>Correcting</span>");
+            }
+          }
+          display=0;
+          break;
+        case 15:
+          switch(info[i]) {
+            case 0:
+              label=g_strdup_printf("RESET");
+              break;
+            case 1:
+              label=g_strdup_printf("WAIT");
+              break;
+            case 2:
+              label=g_strdup_printf("MOXDELAY");
+              break;
+            case 3:
+              label=g_strdup_printf("SETUP");
+              break;
+            case 4:
+              label=g_strdup_printf("COLLECT");
+              break;
+            case 5:
+              label=g_strdup_printf("MOXCHECK");
+              break;
+            case 6:
+              label=g_strdup_printf("CALC");
+              break;
+            case 7:
+              label=g_strdup_printf("DELAY");
+              break;
+            case 8:
+              label=g_strdup_printf("STAYON");
+              break;
+            case 9:
+              label=g_strdup_printf("TUNRON");
+              break;
+            default:
+              label=g_strdup_printf("UNKNOWN %d=%d",i,info[i]);
+              break;
+          }
+          break;
+        default:
+          label=g_strdup_printf("info %d=%d",i,info[i]);
+          display=0;
+          break;
+      }
+      if(display) {
+        if(entry[i]!=NULL) {
+          gtk_entry_set_text(GTK_ENTRY(entry[i]),label);
+        } else {
+fprintf(stderr,"ps_menu: entry %d is NULL\n", i);
+        }
+      }
+
+      if(label!=NULL) {
+        g_free(label);
+        label=NULL;
+      }
+
+    }
+
+    double pk;
+    gchar *pk_label;
+
+    GetPSMaxTX(transmitter->id,&pk);
+    pk_label=g_strdup_printf("%f",pk);
+    gtk_entry_set_text(GTK_ENTRY(get_pk),pk_label);
+    if(pk_label!=NULL) {
+      g_free(pk_label);
+      pk_label=NULL;
+    }
+
+
+    counter++;
+    if(counter==10) { // every 100ms
+      double ddb;
+      int newcal=info[5]!=old5_2;
+      old5_2=info[5];
+      switch(state) {
+        case 0:
+          if(transmitter->auto_on && newcal && (info[4]>181 || (info[4]<=128 && transmitter->attenuation>0))) {
+            if(info[4]<=256) {
+              ddb= 20.0 * log10((double)info[4]/152.293);
+              if(isnan(ddb)) {
+                ddb=31.1;
+              }
+              if(ddb<-100.0) {
+                ddb=-100.0;
+              }
+              if(ddb > 100.0) {
+                ddb=100.0;
+              }
+            } else {
+              ddb=31.1;
+            }
+            deltadb=(int)ddb;
+            save_auto_on=transmitter->auto_on;
+            save_single_on=transmitter->single_on;
+            SetPSControl(transmitter->id, 1, 0, 0, 0);
+            state=1;
+          }
+          break;
+        case 1:
+          if((deltadb+transmitter->attenuation)>0) {
+            transmitter->attenuation+=deltadb;
+          } else {
+            transmitter->attenuation=0;
+          }
+          state=2;
+          break;
+        case 2:
+          state=0;
+          SetPSControl(transmitter->id, 0, save_single_on, save_auto_on, 0);
+          break;
+      }
+      counter=0;
+    }
+    usleep(10000); // 10 ms
+  }
+  gtk_entry_set_text(GTK_ENTRY(entry[15]),"");
+}
+
+static void enable_cb(GtkWidget *widget, gpointer data) {
+  g_idle_add(ext_tx_set_ps,(gpointer)(long)gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)));
+}
+
+static void auto_cb(GtkWidget *widget, gpointer data) {
+  transmitter->auto_on=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+  if(transmitter->auto_on) {
+    transmitter->attenuation=31;
+  } else {
+    transmitter->attenuation=0;
+  }
+}
+
+static void calibrate_cb(GtkWidget *widget, gpointer data) {
+  transmitter->puresignal=1;
+  SetPSControl(transmitter->id, 0, 1, 0, 0);
+}
+
+static void feedback_cb(GtkWidget *widget, gpointer data) {
+  if(transmitter->feedback==0)  {
+    transmitter->feedback=1;
+    set_button_text_color(widget,"red");
+  } else {
+    transmitter->feedback=0;
+    set_button_text_color(widget,"black");
+  }
+}
+
+static void reset_cb(GtkWidget *widget, gpointer data) {
+  transmitter->attenuation=0;
+  SetPSControl(transmitter->id, 1, 0, 0, 0);
+}
+
+void ps_twotone(int state) {
+  tx_set_twotone(transmitter,state);
+  if(transmitter->twotone) {
+    //set_button_text_color(widget,"red");
+  } else {
+    //set_button_text_color(widget,"black");
+  }
+  if(state && transmitter->puresignal) {
+    info_thread_id=g_thread_new( "PS info", info_thread, NULL);
+  } else {
+    running=0;
+  }
+}
+
+static void twotone_cb(GtkWidget *widget, gpointer data) {
+  int state=transmitter->twotone?0:1;
+  //g_idle_add(ext_ps_twotone,(gpointer)(long)state);
+  tx_set_twotone(transmitter,state);
+  if(state) {
+    set_button_text_color(widget,"red");
+  } else {
+    set_button_text_color(widget,"black");
+  }
+  if(state && transmitter->puresignal) {
+    info_thread_id=g_thread_new( "PS info", info_thread, NULL);
+  } else {
+    running=0;
+  }
+}
+
+void ps_menu(GtkWidget *parent) {
+  GtkWidget *b;
+  int i;
+
+  parent_window=parent;
+
+  dialog=gtk_dialog_new();
+  g_signal_connect (dialog, "destroy", G_CALLBACK(destroy_cb), NULL);
+  gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - Pure Signal");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
+
+  GdkRGBA color;
+  color.red = 1.0;
+  color.green = 1.0;
+  color.blue = 1.0;
+  color.alpha = 1.0;
+  gtk_widget_override_background_color(dialog,GTK_STATE_FLAG_NORMAL,&color);
+
+  GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+
+  GtkWidget *grid=gtk_grid_new();
+
+  //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+  //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
+  gtk_grid_set_column_spacing (GTK_GRID(grid),5);
+  gtk_grid_set_row_spacing (GTK_GRID(grid),5);
+
+  int row=0;
+  int col=0;
+
+  GtkWidget *close_b=gtk_button_new_with_label("Close");
+  g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
+  gtk_grid_attach(GTK_GRID(grid),close_b,col,row,1,1);
+
+  row++;
+  col=0;
+
+  GtkWidget *enable_b=gtk_check_button_new_with_label("Enable PS");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (enable_b), transmitter->puresignal);
+  gtk_grid_attach(GTK_GRID(grid),enable_b,col,row,1,1);
+  g_signal_connect(enable_b,"toggled",G_CALLBACK(enable_cb),NULL);
+
+  col++;
+
+  GtkWidget *twotone_b=gtk_button_new_with_label("Two Tone");
+  gtk_widget_show(twotone_b);
+  gtk_grid_attach(GTK_GRID(grid),twotone_b,col,row,1,1);
+  g_signal_connect(twotone_b,"pressed",G_CALLBACK(twotone_cb),NULL);
+  if(transmitter->twotone) {
+    set_button_text_color(twotone_b,"red");
+  }
+
+  
+  col++;
+
+  GtkWidget *auto_b=gtk_check_button_new_with_label("Auto Attenuate");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (auto_b), transmitter->auto_on);
+  gtk_grid_attach(GTK_GRID(grid),auto_b,col,row,1,1);
+  g_signal_connect(auto_b,"toggled",G_CALLBACK(auto_cb),NULL);
+  
+  col++;
+
+  GtkWidget *reset_b=gtk_button_new_with_label("Reset");
+  gtk_widget_show(reset_b);
+  gtk_grid_attach(GTK_GRID(grid),reset_b,col,row,1,1);
+  g_signal_connect(reset_b,"pressed",G_CALLBACK(reset_cb),NULL);
+
+  col++;
+
+  GtkWidget *feedback_b=gtk_button_new_with_label("MON");
+  gtk_widget_show(feedback_b);
+  gtk_grid_attach(GTK_GRID(grid),feedback_b,col,row,1,1);
+  g_signal_connect(feedback_b,"pressed",G_CALLBACK(feedback_cb),NULL);
+  if(transmitter->feedback)  {
+    set_button_text_color(feedback_b,"red");
+  }
+
+
+  row++;
+  col=0;
+
+  feedback_l=gtk_label_new("Feedback Lvl");
+  gtk_widget_show(feedback_l);
+  gtk_grid_attach(GTK_GRID(grid),feedback_l,col,row,1,1);
+
+  col++;
+
+  correcting_l=gtk_label_new("Correcting");
+  gtk_widget_show(correcting_l);
+  gtk_grid_attach(GTK_GRID(grid),correcting_l,col,row,1,1);
+
+  row++;
+  col=0;
+
+  for(i=0;i<INFO_SIZE;i++) {
+    int display=1;
+    char label[16];
+    switch(i) {
+      //case 0:
+      //  strcpy(label,"bldr.rx");
+      //  break;
+      //case 1:
+      //  strcpy(label,"bldr.cm");
+      //  break;
+      //case 2:
+      //  strcpy(label,"bldr.cc");
+      //  break;
+      //case 3:
+      //  strcpy(label,"bldr.cs");
+      //  break;
+      case 4:
+        strcpy(label,"feedbk");
+        break;
+      case 5:
+        strcpy(label,"cor.cnt");
+        break;
+      case 6:
+        strcpy(label,"sln.chk");
+        break;
+      case 13:
+        strcpy(label,"dg.cnt");
+        break;
+      case 15:
+        strcpy(label,"status");
+        break;
+      default:
+        display=0;
+        sprintf(label,"Info %d:", i);
+        break;
+    }
+    if(display) {
+      GtkWidget *lbl=gtk_label_new(label);
+      entry[i]=gtk_entry_new();
+      gtk_grid_attach(GTK_GRID(grid),lbl,col,row,1,1);
+      col++;
+      gtk_grid_attach(GTK_GRID(grid),entry[i],col,row,1,1);
+      col++;
+      if(col>=6) {
+        row++;
+        col=0;
+      }
+    } else {
+      entry[i]=NULL;
+    }
+  }
+
+  row++;
+  col=0;
+  GtkWidget *lbl=gtk_label_new("GetPk");
+  gtk_grid_attach(GTK_GRID(grid),lbl,col,row,1,1);
+  col++;
+
+  get_pk=gtk_entry_new();
+  gtk_grid_attach(GTK_GRID(grid),get_pk,col,row,1,1);
+  col++;
+
+  lbl=gtk_label_new("SetPk");
+  gtk_grid_attach(GTK_GRID(grid),lbl,col,row,1,1);
+  col++;
+
+  double pk;
+  char pk_text[16];
+  GetPSHWPeak(transmitter->id,&pk);
+  sprintf(pk_text,"%f",pk);
+  set_pk=gtk_entry_new();
+  gtk_entry_set_text(GTK_ENTRY(set_pk),pk_text);
+  gtk_grid_attach(GTK_GRID(grid),set_pk,col,row,1,1);
+
+  gtk_container_add(GTK_CONTAINER(content),grid);
+  sub_menu=dialog;
+
+  //if(transmitter->puresignal) {
+  //  info_thread_id=g_thread_new( "PS info", info_thread, NULL);
+  //}
+
+  gtk_widget_show_all(dialog);
+
+}
diff --git a/ps_menu.h b/ps_menu.h
new file mode 100644 (file)
index 0000000..e35d831
--- /dev/null
+++ b/ps_menu.h
@@ -0,0 +1,20 @@
+/*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+extern void ps_menu(GtkWidget *parent);
+
+extern void ps_twotone(int state);
diff --git a/radio.c b/radio.c
index b908abfe048181a66bf73d0c852000cd6b765128..18f7fcb15c8253a94f1ffa7754ff3246fd08ffd9 100644 (file)
--- a/radio.c
+++ b/radio.c
@@ -1,4 +1,4 @@
-/* Copyright (C)
+/* Copyrieht (C)
 * 2015 - John Melton, G0ORX/N6LYT
 *
 * This program is free software; you can redistribute it and/or
@@ -23,6 +23,9 @@
 #include <string.h>
 #include <semaphore.h>
 #include <math.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 
 #include <wdsp.h>
 
@@ -39,6 +42,7 @@
 #include "agc.h"
 #include "band.h"
 #include "property.h"
+#include "new_menu.h"
 #include "new_protocol.h"
 #include "old_protocol.h"
 #ifdef RADIOBERRY
 #ifdef FREEDV
 #include "freedv.h"
 #endif
+#include "audio_waterfall.h"
 #ifdef GPIO
 #include "gpio.h"
 #endif
 #include "vfo.h"
+#include "vox.h"
 #include "meter.h"
 #include "rx_panadapter.h"
 #include "tx_panadapter.h"
 #include "waterfall.h"
 #include "sliders.h"
 #include "toolbar.h"
+#include "rigctl.h"
+#include "ext.h"
 
 #define min(x,y) (x<y?x:y)
 #define max(x,y) (x<y?y:x)
 
-#define DISPLAY_INCREMENT (display_height/32)
-#define MENU_HEIGHT (DISPLAY_INCREMENT*2)
-#define MENU_WIDTH ((display_width/32)*3)
-#define VFO_HEIGHT (DISPLAY_INCREMENT*4)
+#define MENU_HEIGHT (30)
+#define MENU_WIDTH (64)
+#define VFO_HEIGHT (60)
 #define VFO_WIDTH (display_width-METER_WIDTH-MENU_WIDTH)
-#define METER_HEIGHT (DISPLAY_INCREMENT*4)
-#define METER_WIDTH ((display_width/32)*8)
-#define PANADAPTER_HEIGHT (DISPLAY_INCREMENT*8)
-#define SLIDERS_HEIGHT (DISPLAY_INCREMENT*6)
-#define TOOLBAR_HEIGHT (DISPLAY_INCREMENT*2)
-#define WATERFALL_HEIGHT (display_height-(VFO_HEIGHT+PANADAPTER_HEIGHT+SLIDERS_HEIGHT+TOOLBAR_HEIGHT))
+#define METER_HEIGHT (60)
+#define METER_WIDTH (200)
+#define PANADAPTER_HEIGHT (105)
+#define SLIDERS_HEIGHT (90)
+#define TOOLBAR_HEIGHT (30)
+#define WATERFALL_HEIGHT (105)
 #ifdef PSK
-#define PSK_WATERFALL_HEIGHT (DISPLAY_INCREMENT*6)
+#define PSK_WATERFALL_HEIGHT (90)
 #define PSK_HEIGHT (display_height-(VFO_HEIGHT+PSK_WATERFALL_HEIGHT+SLIDERS_HEIGHT+TOOLBAR_HEIGHT))
 #endif
 
+#ifdef FREEDV
+#define FREEDV_WATERFALL_HEIGHT (105)
+#endif
+
 static GtkWidget *fixed;
 static GtkWidget *vfo_panel;
 static GtkWidget *meter;
@@ -93,17 +104,24 @@ static GtkWidget *waterfall;
 static GtkWidget *psk;
 static GtkWidget *psk_waterfall;
 #endif
+static GtkWidget *audio_waterfall;
 
 #ifdef GPIO
 static GtkWidget *encoders;
 static cairo_surface_t *encoders_surface = NULL;
 #endif
+#ifdef WIRIINGPI
+static GtkWidget *encoders;
+static cairo_surface_t *encoders_surface = NULL;
+#endif
+
+int region=REGION_OTHER;
 
 int echo=0;
 
 static gint save_timer_id;
 
-DISCOVERED *radio;
+DISCOVERED *radio=NULL;
 
 char property_path[128];
 sem_t property_sem;
@@ -126,10 +144,10 @@ int classE=0;
 int tx_out_of_band=0;
 
 int tx_cfir=0;
-int tx_alc=1;
 int tx_leveler=0;
+int alc=TXA_ALC_AV;
 
-double tone_level=0.0;
+double tone_level=0.2;
 
 int filter_board=ALEX;
 //int pa=PA_ENABLED;
@@ -148,7 +166,6 @@ double display_average_time=120.0;
 
 int waterfall_high=-100;
 int waterfall_low=-150;
-int waterfall_automatic=1;
 
 int display_sliders=1;
 
@@ -163,11 +180,11 @@ int mic_bias_enabled=0;
 int mic_ptt_enabled=0;
 int mic_ptt_tip_bias_ring=0;
 
-double tune_drive=10;
-double drive=50;
+//double tune_drive=10;
+//double drive=50;
 
-int drive_level=0;
-int tune_drive_level=0;
+//int drive_level=0;
+//int tune_drive_level=0;
 
 int receivers=RECEIVERS;
 
@@ -240,8 +257,8 @@ int OCfull_tune_time=2800; // ms
 int OCmemory_tune_time=550; // ms
 long long tune_timeout;
 
+int analog_meter=0;
 int smeter=RXA_S_AV;
-int alc=TXA_ALC_PK;
 
 int local_audio=0;
 int local_microphone=0;
@@ -252,10 +269,7 @@ int eer_pwm_max=800;
 int tx_filter_low=150;
 int tx_filter_high=2850;
 
-#ifdef FREEDV
-char freedv_tx_text_data[64];
-#endif
-
+static int pre_tune_mode;
 static int pre_tune_filter_low;
 static int pre_tune_filter_high;
 
@@ -265,7 +279,6 @@ int tx_equalizer[4]={0,0,0,0};
 int enable_rx_equalizer=0;
 int rx_equalizer[4]={0,0,0,0};
 
-int deviation=2500;
 int pre_emphasize=0;
 
 int vox_setting=0;
@@ -279,9 +292,13 @@ int diversity_enabled=0;
 double i_rotate[2]={1.0,1.0};
 double q_rotate[2]={0.0,0.0};
 
+double meter_calibration=0.0;
+double display_calibration=0.0;
+
 void reconfigure_radio() {
   int i;
   int y;
+//fprintf(stderr,"reconfigure_radio: receivers=%d\n",receivers);
   int rx_height=display_height-VFO_HEIGHT-TOOLBAR_HEIGHT;
   if(display_sliders) {
     rx_height-=SLIDERS_HEIGHT;
@@ -291,6 +308,8 @@ void reconfigure_radio() {
   for(i=0;i<receivers;i++) {
     reconfigure_receiver(receiver[i],rx_height/receivers);
     gtk_fixed_move(GTK_FIXED(fixed),receiver[i]->panel,0,y);
+    receiver[i]->x=0;
+    receiver[i]->y=y;
     y+=rx_height/receivers;
   }
 
@@ -302,8 +321,6 @@ void reconfigure_radio() {
       gtk_fixed_move(GTK_FIXED(fixed),sliders,0,y);
     }
     gtk_widget_show_all(sliders);
-    // force change of sliders for mic or linein
-    g_idle_add(linein_changed,NULL);
   } else {
     if(sliders!=NULL) {
       gtk_container_remove(GTK_CONTAINER(fixed),sliders); 
@@ -334,7 +351,7 @@ void start_radio() {
   int i;
   int x;
   int y;
-fprintf(stderr,"start_radio: selected radio=%p device=%d\n",radio,radio->device);
+//fprintf(stderr,"start_radio: selected radio=%p device=%d\n",radio,radio->device);
   gdk_window_set_cursor(gtk_widget_get_window(top_window),gdk_cursor_new(GDK_WATCH));
 
   int rc;
@@ -345,7 +362,47 @@ fprintf(stderr,"start_radio: selected radio=%p device=%d\n",radio,radio->device)
   }
   sem_post(&property_sem);
 
-  status_text("starting radio ...");
+  char text[256];
+  //for(i=0;i<devices;i++) {
+    switch(radio->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, radio->protocol==ORIGINAL_PROTOCOL?"Protocol 1":"Protocol 2");
+        } else {
+#endif
+          sprintf(text,"Starting %s (%s v%d.%d)",
+                        radio->name,
+                        radio->protocol==ORIGINAL_PROTOCOL?"Protocol 1":"Protocol 2",
+                        radio->software_version/10,
+                        radio->software_version%10);
+        break;
+    }
+  //}
+
+
+
+  status_text(text);
+
+  sprintf(text,"piHPSDR: %s (%s v%d.%d) %s (%02X:%02X:%02X:%02X:%02X:%02X) 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));
+
+  gtk_window_set_title (GTK_WINDOW (top_window), text);
+
   protocol=radio->protocol;
   device=radio->device;
 
@@ -381,19 +438,50 @@ fprintf(stderr,"start_radio: selected radio=%p device=%d\n",radio,radio->device)
 #endif
   }
 
+  switch(radio->protocol) {
+    case ORIGINAL_PROTOCOL:
+      switch(radio->device) {
+        case DEVICE_ORION2:
+          //meter_calibration=3.0;
+          //display_calibration=3.36;
+          break;
+        default:
+          //meter_calibration=-2.44;
+          //display_calibration=-2.1;
+          break;
+      }
+      break;
+    case NEW_PROTOCOL:
+      switch(radio->device) {
+        case NEW_DEVICE_ORION2:
+          //meter_calibration=3.0;
+          //display_calibration=3.36;
+          break;
+        default:
+          //meter_calibration=-2.44;
+          //display_calibration=-2.1;
+          break;
+      }
+      break;
+  }
+
+//fprintf(stderr,"meter_calibration=%f display_calibration=%f\n", meter_calibration, display_calibration);
   radioRestoreState();
 
+  radio_change_region(region);
+
   y=0;
 
   fixed=gtk_fixed_new();
   gtk_container_remove(GTK_CONTAINER(top_window),grid);
   gtk_container_add(GTK_CONTAINER(top_window), fixed);
 
-fprintf(stderr,"radio: vfo_init\n");
+//fprintf(stderr,"radio: vfo_init\n");
   vfo_panel = vfo_init(VFO_WIDTH,VFO_HEIGHT,top_window);
   gtk_fixed_put(GTK_FIXED(fixed),vfo_panel,0,y);
 
-fprintf(stderr,"radio: meter_init\n");
+//fprintf(stderr,"radio: meter_init\n");
   meter = meter_init(METER_WIDTH,METER_HEIGHT,top_window);
   gtk_fixed_put(GTK_FIXED(fixed),meter,VFO_WIDTH,y);
 
@@ -422,37 +510,52 @@ fprintf(stderr,"radio: meter_init\n");
 
 
 fprintf(stderr,"Create %d receivers: height=%d\n",receivers,rx_height);
-  for(i=0;i<MAX_RECEIVERS;i++) {
+  for(i=0;i<RECEIVERS;i++) {
     receiver[i]=create_receiver(i, buffer_size, fft_size, display_width, updates_per_second, display_width, rx_height);
-    g_object_ref((gpointer)receiver[i]->panel);
+    setSquelch(receiver[i]);
     if(i<receivers) {
+      receiver[i]->x=0;
+      receiver[i]->y=y;
       gtk_fixed_put(GTK_FIXED(fixed),receiver[i]->panel,0,y);
-fprintf(stderr,"receiver %d: height=%d y=%d\n",receiver[i]->id,rx_height,y);
+      g_object_ref((gpointer)receiver[i]->panel);
       set_displaying(receiver[i],1);
       y+=rx_height;
     } else {
       set_displaying(receiver[i],0);
     }
   }
+
+  if((protocol==ORIGINAL_PROTOCOL) && (RECEIVERS==2) && (receiver[0]->sample_rate!=receiver[1]->sample_rate)) {
+    receiver[1]->sample_rate=receiver[0]->sample_rate;
+  }
+
   active_receiver=receiver[0];
 
   fprintf(stderr,"Create transmitter\n");
   transmitter=create_transmitter(CHANNEL_TX, buffer_size, fft_size, updates_per_second, display_width, tx_height);
-  g_object_ref((gpointer)transmitter->panel);
+  transmitter->x=0;
+  transmitter->y=VFO_HEIGHT;
+  //gtk_fixed_put(GTK_FIXED(fixed),transmitter->panel,0,VFO_HEIGHT);
+
+#ifdef PURESIGNAL
+  tx_set_ps_sample_rate(transmitter,protocol==NEW_PROTOCOL?192000:active_receiver->sample_rate);
+  if(((protocol==ORIGINAL_PROTOCOL) && (device!=DEVICE_METIS)) || ((protocol==NEW_PROTOCOL) && (device!=NEW_DEVICE_ATLAS))) {
+    receiver[PS_TX_FEEDBACK]=create_pure_signal_receiver(PS_TX_FEEDBACK, buffer_size,protocol==ORIGINAL_PROTOCOL?active_receiver->sample_rate:192000,display_width);
+    receiver[PS_RX_FEEDBACK]=create_pure_signal_receiver(PS_RX_FEEDBACK, buffer_size,protocol==ORIGINAL_PROTOCOL?active_receiver->sample_rate:192000,display_width);
+  }
+#endif
 
+#ifdef AUDIO_WATERFALL
+  audio_waterfall=audio_waterfall_init(200,100);
+  gtk_fixed_put(GTK_FIXED(fixed),audio_waterfall,0,VFO_HEIGHT+20);
+#endif
   
-  #ifdef GPIO
+#ifdef GPIO
   if(gpio_init()<0) {
     fprintf(stderr,"GPIO failed to initialize\n");
   }
-#ifdef LOCALCW
-  // init local keyer if enabled
-  else if (cw_keyer_internal == 0)
-    keyer_update();
-#endif
 #endif
   
-  
   switch(radio->protocol) {
     case ORIGINAL_PROTOCOL:
       old_protocol_init(0,display_width,receiver[0]->sample_rate);
@@ -474,9 +577,9 @@ fprintf(stderr,"receiver %d: height=%d y=%d\n",receiver[i]->id,rx_height,y);
 
 
 
-#ifdef I2C
-  i2c_init();
-#endif
+//#ifdef I2C
+//  i2c_init();
+//#endif
 
   if(display_sliders) {
 fprintf(stderr,"create sliders\n");
@@ -485,17 +588,21 @@ fprintf(stderr,"create sliders\n");
     y+=SLIDERS_HEIGHT;
   }
 
+
   toolbar = toolbar_init(display_width,TOOLBAR_HEIGHT,top_window);
   gtk_fixed_put(GTK_FIXED(fixed),toolbar,0,y);
   y+=TOOLBAR_HEIGHT;
 
   gtk_widget_show_all (fixed);
+//#ifdef FREEDV
+//  if(!active_receiver->freedv) {
+//    gtk_widget_hide(audio_waterfall);
+//  }
+//#endif
 
-  // force change of sliders for mic or linein
-  g_idle_add(linein_changed,NULL);
+  
 
   // save every 30 seconds
-fprintf(stderr,"start save timer\n");
   save_timer_id=gdk_threads_add_timeout(30000, save_cb, NULL);
 
 #ifdef PSK
@@ -506,36 +613,36 @@ fprintf(stderr,"start save timer\n");
   }
 #endif
 
-  launch_rigctl();
+  if(rigctl_enable) {
+    launch_rigctl();
+  }
 
   calcDriveLevel();
-  calcTuneDriveLevel();
+
+#ifdef PURESIGNAL
+  if(transmitter->puresignal) {
+    tx_set_ps(transmitter,transmitter->puresignal);
+  }
+#endif
 
   if(protocol==NEW_PROTOCOL) {
     schedule_high_priority();
   }
 
-  g_idle_add(vfo_update,(gpointer)NULL);
+  g_idle_add(ext_vfo_update,(gpointer)NULL);
 
-fprintf(stderr,"set cursor\n");
   gdk_window_set_cursor(gtk_widget_get_window(top_window),gdk_cursor_new(GDK_ARROW));
 
-for(i=0;i<MAX_VFOS;i++) {
-  fprintf(stderr,"start_radio: vfo %d band=%d bandstack=%d frequency=%lld mode=%d filter=%d rit=%lld lo=%lld offset=%lld\n",
-    i,
-    vfo[i].band,
-    vfo[i].bandstack,
-    vfo[i].frequency,
-    vfo[i].mode,
-    vfo[i].filter,
-    vfo[i].rit,
-    vfo[i].lo,
-    vfo[i].offset);
-}
 }
 
+void disable_rigctl() {
+   fprintf(stderr,"RIGCTL: disable_rigctl()\n");
+   close_rigctl_ports();
+}
 
 void radio_change_receivers(int r) {
+  fprintf(stderr,"radio_change_receivers: from %d to %d\n",receivers,r);
   switch(r) {
     case 1:
       if(receivers==2) {
@@ -552,6 +659,9 @@ void radio_change_receivers(int r) {
   }
   reconfigure_radio();
   active_receiver=receiver[0];
+  if(protocol==NEW_PROTOCOL) {
+    schedule_high_priority();
+  }
 }
 
 void radio_change_sample_rate(int rate) {
@@ -564,6 +674,9 @@ void radio_change_sample_rate(int rate) {
       }
       old_protocol_set_mic_sample_rate(rate);
       old_protocol_run();
+#ifdef PURESIGNAL
+      tx_set_ps_sample_rate(transmitter,rate);
+#endif
       break;
 #ifdef LIMESDR
     case LIMESDR_PROTOCOL:
@@ -575,53 +688,79 @@ void radio_change_sample_rate(int rate) {
 
 static void rxtx(int state) {
   int i;
-  int y=VFO_HEIGHT;
-
-fprintf(stderr,"rxtx: state=%d\n",state);
 
   if(state) {
     // switch to tx
+#ifdef FREEDV
+    if(active_receiver->freedv) {
+      freedv_reset_tx_text_index();
+    }
+#endif
+#ifdef PURESIGNAL
+    RECEIVER *rx_feedback=receiver[PS_RX_FEEDBACK];
+    RECEIVER *tx_feedback=receiver[PS_TX_FEEDBACK];
+
+    rx_feedback->samples=0;
+    tx_feedback->samples=0;
+#endif
+
     for(i=0;i<receivers;i++) {
       SetChannelState(receiver[i]->id,0,i==(receivers-1));
       set_displaying(receiver[i],0);
       if(protocol==NEW_PROTOCOL) {
         schedule_high_priority();
+        schedule_receive_specific();
+      }
+      g_object_ref((gpointer)receiver[i]->panel);
+      g_object_ref((gpointer)receiver[i]->panadapter);
+      if(receiver[i]->waterfall!=NULL) {
+        g_object_ref((gpointer)receiver[i]->waterfall);
       }
       gtk_container_remove(GTK_CONTAINER(fixed),receiver[i]->panel);
     }
-    gtk_fixed_put(GTK_FIXED(fixed),transmitter->panel,0,y);
+//#ifdef FREEDV
+//    if(active_receiver->freedv) {
+//      gtk_widget_show(audio_waterfall);
+//    }
+//#endif
+    gtk_fixed_put(GTK_FIXED(fixed),transmitter->panel,transmitter->x,transmitter->y);
     SetChannelState(transmitter->id,1,0);
     tx_set_displaying(transmitter,1);
-#ifdef FREEDV
-    if(active_receiver->mode==modeFREEDV) {
-      freedv_reset_tx_text_index();
-    }
-#endif
   } else {
     SetChannelState(transmitter->id,0,1);
     if(protocol==NEW_PROTOCOL) {
       schedule_high_priority();
+      schedule_receive_specific();
     }
     tx_set_displaying(transmitter,0);
+    g_object_ref((gpointer)transmitter->panel);
+    g_object_ref((gpointer)transmitter->panadapter);
     gtk_container_remove(GTK_CONTAINER(fixed),transmitter->panel);
-    int rx_height=display_height-VFO_HEIGHT-TOOLBAR_HEIGHT;
-    if(display_sliders) {
-      rx_height-=SLIDERS_HEIGHT;
-    }
+//#ifdef FREEDV
+//    if(active_receiver->freedv) {
+//      gtk_widget_hide(audio_waterfall);
+//    }
+//#endif
     for(i=0;i<receivers;i++) {
+      gtk_fixed_put(GTK_FIXED(fixed),receiver[i]->panel,receiver[i]->x,receiver[i]->y);
       SetChannelState(receiver[i]->id,1,0);
       set_displaying(receiver[i],1);
-      gtk_fixed_put(GTK_FIXED(fixed),receiver[i]->panel,0,y);
-      y+=(rx_height/receivers);
     }
+//#ifdef FREEDV
+//    if(active_receiver->freedv) {
+//      gtk_widget_show(audio_waterfall);
+//    }
+//#endif
   }
 
-  gtk_widget_show_all(fixed);
-  g_idle_add(linein_changed,NULL);
+#ifdef PURESIGNAL
+  if(transmitter->puresignal) {
+    SetPSMox(transmitter->id,state);
+  }
+#endif
 }
 
 void setMox(int state) {
-fprintf(stderr,"setMox: %d\n",state);
   if(mox!=state) {
     mox=state;
     if(vox_enabled && vox) {
@@ -641,12 +780,11 @@ void setVox(int state) {
     vox=state;
     rxtx(state);
   }
-  g_idle_add(vfo_update,(gpointer)NULL);
+  g_idle_add(ext_vfo_update,(gpointer)NULL);
 }
 
-int vox_changed(void *data) {
-  setVox((int)data);
-  return 0;
+void vox_changed(int state) {
+  setVox(state);
 }
 
 
@@ -687,63 +825,50 @@ void setTune(int state) {
         }
       }
 
-      int mode=vfo[VFO_A].mode;;
+      int mode=vfo[VFO_A].mode;
       if(split) {
         mode=vfo[VFO_B].mode;
       }
-      double freq=(double)cw_keyer_sidetone_frequency;
-      
-      pre_tune_filter_low=transmitter->filter_low;
-      pre_tune_filter_high=transmitter->filter_high;
+      pre_tune_mode=mode;
 
       switch(mode) {
-        case modeUSB:
-        case modeCWU:
-        case modeDIGU:
-          SetTXAPostGenToneFreq(transmitter->id,(double)cw_keyer_sidetone_frequency);
-          transmitter->filter_low=cw_keyer_sidetone_frequency-100;
-          transmitter->filter_high=cw_keyer_sidetone_frequency+100;
-          freq=(double)(cw_keyer_sidetone_frequency+100);
-          break;
         case modeLSB:
         case modeCWL:
         case modeDIGL:
           SetTXAPostGenToneFreq(transmitter->id,-(double)cw_keyer_sidetone_frequency);
-          transmitter->filter_low=-cw_keyer_sidetone_frequency-100;
-          transmitter->filter_high=-cw_keyer_sidetone_frequency+100;
-          freq=(double)(-cw_keyer_sidetone_frequency-100);
-          break;
-        case modeDSB:
-          SetTXAPostGenToneFreq(transmitter->id,(double)cw_keyer_sidetone_frequency);
-          transmitter->filter_low=cw_keyer_sidetone_frequency-100;
-          transmitter->filter_high=cw_keyer_sidetone_frequency+100;
-          freq=(double)(cw_keyer_sidetone_frequency+100);
           break;
-        case modeAM:
-        case modeSAM:
-        case modeFMN:
+        default:
           SetTXAPostGenToneFreq(transmitter->id,(double)cw_keyer_sidetone_frequency);
-          transmitter->filter_low=cw_keyer_sidetone_frequency-100;
-          transmitter->filter_high=cw_keyer_sidetone_frequency+100;
-          freq=(double)(cw_keyer_sidetone_frequency+100);
           break;
       }
 
-      SetTXABandpassFreqs(transmitter->id,transmitter->filter_low,transmitter->filter_high);
-
-      
-      SetTXAMode(transmitter->id,modeDIGU);
-      SetTXAPostGenMode(transmitter->id,0);
       SetTXAPostGenToneMag(transmitter->id,0.99999);
+      SetTXAPostGenMode(transmitter->id,0);
       SetTXAPostGenRun(transmitter->id,1);
+
+      switch(mode) {
+        case modeCWL:
+          cw_keyer_internal=0;
+          tx_set_mode(transmitter,modeLSB);
+          break;
+        case modeCWU:
+          cw_keyer_internal=0;
+          tx_set_mode(transmitter,modeUSB);
+          break;
+      }
+      rxtx(tune);
     } else {
+      rxtx(tune);
       SetTXAPostGenRun(transmitter->id,0);
-      SetTXAMode(transmitter->id,transmitter->mode);
-      transmitter->filter_low=pre_tune_filter_low;
-      transmitter->filter_high=pre_tune_filter_high;
-      SetTXABandpassFreqs(transmitter->id,transmitter->filter_low,transmitter->filter_high);
+      switch(pre_tune_mode) {
+        case modeCWL:
+        case modeCWU:
+          tx_set_mode(transmitter,pre_tune_mode);
+          cw_keyer_internal=1;
+          break;
+      }
+
     }
-    rxtx(tune);
   }
 }
 
@@ -751,8 +876,31 @@ int getTune() {
   return tune;
 }
 
+void radio_cw_setup() {
+  int mode=vfo[VFO_A].mode;;
+  if(split) {
+    mode=vfo[VFO_B].mode;
+  }
+
+  double freq=(double)cw_keyer_sidetone_frequency;
+  switch(mode) {
+    case modeCWU:
+      SetTXAPostGenToneFreq(transmitter->id,(double)cw_keyer_sidetone_frequency);
+      break;
+    case modeLSB:
+      SetTXAPostGenToneFreq(transmitter->id,-(double)cw_keyer_sidetone_frequency);
+      break;
+  }
+  SetTXAPostGenMode(transmitter->id,0);
+  SetTXAPostGenToneMag(transmitter->id,0.99999);
+}
+
+void radio_cw_key(int state) {
+  SetTXAPostGenRun(transmitter->id,state);
+}
+
 int isTransmitting() {
-  return ptt || mox || vox || tune;
+  return ptt | mox | vox | tune;
 }
 
 void setFrequency(long long f) {
@@ -803,7 +951,6 @@ fprintf(stderr,"setFrequency: %lld\n",f);
 #ifdef RADIOBERRY
        case RADIOBERRY_PROTOCOL:
 #endif
-      schedule_frequency_changed();
       break;
 #ifdef LIMESDR
     case LIMESDR_PROTOCOL:
@@ -820,7 +967,7 @@ long long getFrequency() {
 }
 
 double getDrive() {
-    return drive;
+    return transmitter->drive;
 }
 
 static int calcLevel(double d) {
@@ -843,35 +990,36 @@ static int calcLevel(double d) {
   }
 
   level=(int)(actual_volts*255.0);
+
+//fprintf(stderr,"calcLevel: %f calib=%f level=%d\n",d, gbb, level);
   return level;
 }
 
 void calcDriveLevel() {
-    drive_level=calcLevel(drive);
+    transmitter->drive_level=calcLevel(transmitter->drive);
     if(mox && protocol==NEW_PROTOCOL) {
       schedule_high_priority();
     }
+//fprintf(stderr,"calcDriveLevel: drive=%d drive_level=%d\n",transmitter->drive,transmitter->drive_level);
 }
 
 void setDrive(double value) {
-    drive=value;
+    transmitter->drive=value;
     calcDriveLevel();
 }
 
 double getTuneDrive() {
-    return tune_drive;
+    return transmitter->tune_percent;
 }
 
-void calcTuneDriveLevel() {
-    tune_drive_level=calcLevel(tune_drive);
-    if(tune  && protocol==NEW_PROTOCOL) {
-      schedule_high_priority();
-    }
-}
+void setSquelch(RECEIVER *rx) {
+  double am_sq=((rx->squelch/100.0)*160.0)-160.0;
+  SetRXAAMSQThreshold(rx->id, am_sq);
+  SetRXAAMSQRun(rx->id, rx->squelch_enable);
 
-void setTuneDrive(double value) {
-    tune_drive=value;
-    calcTuneDriveLevel();
+  double fm_sq=pow(10.0, -2.0*rx->squelch/100.0);
+  SetRXAFMSQThreshold(rx->id, fm_sq);
+  SetRXAFMSQRun(rx->id, rx->squelch_enable);
 }
 
 void set_attenuation(int value) {
@@ -928,6 +1076,8 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path);
     sem_wait(&property_sem);
     loadProperties(property_path);
 
+    value=getProperty("region");
+    if(value) region=atoi(value);
     value=getProperty("buffer_size");
     if(value) buffer_size=atoi(value);
     value=getProperty("fft_size");
@@ -968,14 +1118,6 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path);
     if(value) waterfall_high=atoi(value);
     value=getProperty("waterfall_low");
     if(value) waterfall_low=atoi(value);
-    value=getProperty("waterfall_automatic");
-    if(value) waterfall_automatic=atoi(value);
-//    value=getProperty("volume");
-//    if(value) volume=atof(value);
-    value=getProperty("drive");
-    if(value) drive=atof(value);
-    value=getProperty("tune_drive");
-    if(value) tune_drive=atof(value);
     value=getProperty("mic_gain");
     if(value) mic_gain=atof(value);
     value=getProperty("mic_boost");
@@ -1032,11 +1174,8 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path);
     if(value) OCfull_tune_time=atoi(value);
     value=getProperty("OCmemory_tune_time");
     if(value) OCmemory_tune_time=atoi(value);
-#ifdef FREEDV
-    strcpy(freedv_tx_text_data,"NO TEXT DATA");
-    value=getProperty("freedv_tx_text_data");
-    if(value) strcpy(freedv_tx_text_data,value);
-#endif
+    value=getProperty("analog_meter");
+    if(value) analog_meter=atoi(value);
     value=getProperty("smeter");
     if(value) smeter=atoi(value);
     value=getProperty("alc");
@@ -1073,8 +1212,6 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path);
     if(value) rx_equalizer[3]=atoi(value);
     value=getProperty("rit_increment");
     if(value) rit_increment=atoi(value);
-    value=getProperty("deviation");
-    if(value) deviation=atoi(value);
     value=getProperty("pre_emphasize");
     if(value) pre_emphasize=atoi(value);
 
@@ -1101,6 +1238,9 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path);
     value=getProperty("filterB");
     if(value) filterB=atoi(value);
 
+    value=getProperty("tone_level");
+    if(value) tone_level=atof(value);
+
 #ifdef GPIO
     value=getProperty("e1_encoder_action");
     if(value) e1_encoder_action=atoi(value);
@@ -1117,6 +1257,13 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path);
     bandRestoreState();
     memRestoreState();
     vfo_restore_state();
+#ifdef FREEDV
+    freedv_restore_state();
+#endif
+    value=getProperty("rigctl_enable");
+    if(value) rigctl_enable=atoi(value);
+    value=getProperty("rigctl_port_base");
+    if(value) rigctl_port_base=atoi(value);
 
     sem_post(&property_sem);
 }
@@ -1126,6 +1273,8 @@ void radioSaveState() {
     char value[80];
 
     sem_wait(&property_sem);
+    sprintf(value,"%d",region);
+    setProperty("region",value);
     sprintf(value,"%d",buffer_size);
     setProperty("buffer_size",value);
     sprintf(value,"%d",fft_size);
@@ -1136,12 +1285,6 @@ void radioSaveState() {
     setProperty("filter_board",value);
     sprintf(value,"%d",tx_out_of_band);
     setProperty("tx_out_of_band",value);
-/*
-    sprintf(value,"%d",apollo_tuner);
-    setProperty("apollo_tuner",value);
-    sprintf(value,"%d",pa);
-    setProperty("pa",value);
-*/
     sprintf(value,"%d",updates_per_second);
     setProperty("updates_per_second",value);
     sprintf(value,"%d",display_filled);
@@ -1158,24 +1301,12 @@ 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);
     setProperty("waterfall_low",value);
-    sprintf(value,"%d",waterfall_automatic);
-    setProperty("waterfall_automatic",value);
-//    sprintf(value,"%f",volume);
-//    setProperty("volume",value);
     sprintf(value,"%f",mic_gain);
     setProperty("mic_gain",value);
-    sprintf(value,"%f",drive);
-    setProperty("drive",value);
-    sprintf(value,"%f",tune_drive);
-    setProperty("tune_drive",value);
     sprintf(value,"%d",mic_boost);
     setProperty("mic_boost",value);
     sprintf(value,"%d",mic_linein);
@@ -1227,11 +1358,8 @@ void radioSaveState() {
     setProperty("OCfull_tune_time",value);
     sprintf(value,"%d",OCmemory_tune_time);
     setProperty("OCmemory_tune_time",value);
-#ifdef FREEDV
-    if(strlen(freedv_tx_text_data)>0) {
-      setProperty("freedv_tx_text_data",freedv_tx_text_data);
-    }
-#endif
+    sprintf(value,"%d",analog_meter);
+    setProperty("analog_meter",value);
     sprintf(value,"%d",smeter);
     setProperty("smeter",value);
     sprintf(value,"%d",alc);
@@ -1244,8 +1372,6 @@ void radioSaveState() {
 #endif
     sprintf(value,"%d",local_microphone);
     setProperty("local_microphone",value);
-//    sprintf(value,"%d",n_selected_input_device);
-//    setProperty("n_selected_input_device",value);
 
     sprintf(value,"%d",enable_tx_equalizer);
     setProperty("enable_tx_equalizer",value);
@@ -1269,8 +1395,6 @@ void radioSaveState() {
     setProperty("rx_equalizer.3",value);
     sprintf(value,"%d",rit_increment);
     setProperty("rit_increment",value);
-    sprintf(value,"%d",deviation);
-    setProperty("deviation",value);
     sprintf(value,"%d",pre_emphasize);
     setProperty("pre_emphasize",value);
 
@@ -1278,10 +1402,6 @@ void radioSaveState() {
     setProperty("vox_enabled",value);
     sprintf(value,"%f",vox_threshold);
     setProperty("vox_threshold",value);
-/*
-    sprintf(value,"%f",vox_gain);
-    setProperty("vox_gain",value);
-*/
     sprintf(value,"%f",vox_hang);
     setProperty("vox_hang",value);
 
@@ -1295,6 +1415,9 @@ void radioSaveState() {
     sprintf(value,"%d",filterB);
     setProperty("filterB",value);
 
+    sprintf(value,"%f",tone_level);
+    setProperty("tone_level",value);
+
 #ifdef GPIO
     sprintf(value,"%d",e1_encoder_action);
     setProperty("e1_encoder_action",value);
@@ -1312,10 +1435,19 @@ void radioSaveState() {
       receiver_save_state(receiver[i]);
     }
     transmitter_save_state(transmitter);
+#ifdef FREEDV
+    freedv_save_state();
+#endif
 
     filterSaveState();
     bandSaveState();
     memSaveState();
+
+    sprintf(value,"%d",rigctl_enable);
+    setProperty("rigctl_enable",value);
+    sprintf(value,"%d",rigctl_port_base);
+    setProperty("rigctl_port_base",value);
+
     saveProperties(property_path);
     sem_post(&property_sem);
 }
@@ -1354,3 +1486,38 @@ void set_filter_size(int filter_size) {
   transmitter->fft_size=filter_size;
   TXASetNC(transmitter->id, filter_size);
 }
+
+#ifdef FREEDV
+void set_freedv(int state) {
+fprintf(stderr,"set_freedv: rx=%p state=%d\n",active_receiver,state);
+  g_mutex_lock(&active_receiver->freedv_mutex);
+  active_receiver->freedv=state;
+  if(active_receiver->freedv) {
+    SetRXAPanelRun(active_receiver->id, 0);
+    init_freedv(active_receiver);
+    transmitter->freedv_samples=0;
+  } else {
+    SetRXAPanelRun(active_receiver->id, 1);
+    close_freedv(active_receiver);
+  }
+  g_mutex_unlock(&active_receiver->freedv_mutex);
+  g_idle_add(ext_vfo_update,NULL);
+}
+#endif
+
+void radio_change_region(int r) {
+  region=r;
+  if(region==REGION_UK) {
+    channel_entries=UK_CHANNEL_ENTRIES;
+    band_channels_60m=&band_channels_60m_UK[0];
+    bandstack60.entries=UK_CHANNEL_ENTRIES;
+    bandstack60.current_entry=0;
+    bandstack60.entry=bandstack_entries60_UK;
+  } else {
+    channel_entries=OTHER_CHANNEL_ENTRIES;
+    band_channels_60m=&band_channels_60m_OTHER[0];
+    bandstack60.entries=OTHER_CHANNEL_ENTRIES;
+    bandstack60.current_entry=0;
+    bandstack60.entry=bandstack_entries60_OTHER;
+  }
+}
diff --git a/radio.h b/radio.h
index c3bc0df049d0a6ef9893bc7e839acdb5ebdb9870..5ca4ca02c88b623100eeeab8915f92c5a79eb912 100644 (file)
--- a/radio.h
+++ b/radio.h
@@ -53,9 +53,18 @@ extern char property_path[];
 #define ALEX 1
 #define APOLLO 2
 
-// specify how many receivers (only 1 or 2 for now)
-#define MAX_RECEIVERS 2
+#define REGION_OTHER 0
+#define REGION_UK 1
+
+extern int region;
+
+// specify how many receivers
+#define MAX_RECEIVERS 8
 #define RECEIVERS 2
+#ifdef PURESIGNAL
+#define PS_TX_FEEDBACK (RECEIVERS)
+#define PS_RX_FEEDBACK (RECEIVERS+1)
+#endif
 
 extern RECEIVER *receiver[];
 extern RECEIVER *active_receiver;
@@ -90,7 +99,6 @@ extern int classE;
 extern int tx_out_of_band;
 
 extern int tx_cfir;
-extern int tx_alc;
 extern int tx_leveler;
 
 extern double tone_level;
@@ -110,10 +118,7 @@ extern int display_average_mode;
 extern double display_average_time;
 
 
-extern int display_waterfall;
-extern int waterfall_high;
-extern int waterfall_low;
-extern int waterfall_automatic;
+//extern int display_waterfall;
 
 extern int display_sliders;
 extern int display_toolbar;
@@ -128,11 +133,11 @@ extern int mic_bias_enabled;
 extern int mic_ptt_enabled;
 extern int mic_ptt_tip_bias_ring;
 
-extern double tune_drive;
-extern double drive;
+//extern double tune_drive;
+//extern double drive;
 
-extern int tune_drive_level;
-extern int drive_level;
+//extern int tune_drive_level;
+//extern int drive_level;
 
 int receivers;
 
@@ -206,10 +211,7 @@ extern int OCfull_tune_time;
 extern int OCmemory_tune_time;
 extern long long tune_timeout;
 
-#ifdef FREEDV
-extern char freedv_tx_text_data[64];
-#endif
-
+extern int analog_meter;
 extern int smeter;
 extern int alc;
 
@@ -230,7 +232,6 @@ extern int tx_equalizer[4];
 extern int enable_rx_equalizer;
 extern int rx_equalizer[4];
 
-extern int deviation;
 extern int pre_emphasize;
 
 extern int vox_setting;
@@ -244,9 +245,12 @@ extern int diversity_enabled;
 extern double i_rotate[2];
 extern double q_rotate[2];
 
+extern double meter_calibration;
+extern double display_calibration;
+
 extern void reconfigure_radio();
 extern void start_radio();
-extern void init_radio();
+//extern void init_radio();
 extern void radio_change_receivers(int r);
 extern void radio_change_sample_rate(int rate);
 extern void setMox(int state);
@@ -254,13 +258,14 @@ extern int getMox();
 extern void setTune(int state);
 extern int getTune();
 extern void setVox(int state);
-extern int vox_changed(void *data);
+extern void vox_changed(int state);
 extern double getDrive();
 extern void setDrive(double d);
 extern void calcDriveLevel();
 extern double getTuneDrive();
 extern void setTuneDrive(double d);
 extern void calcTuneDriveLevel();
+extern void setSquelch(RECEIVER *rx);
 
 extern void set_attenuation(int value);
 extern int get_attenuation();
@@ -280,4 +285,17 @@ extern void calculate_display_average();
 
 extern void set_filter_type(int filter_type);
 extern void set_filter_size(int filter_size);
+
+extern void radio_cw_setup();
+
+extern void radio_cw_key(int state);
+
+#ifdef FREEDV
+extern void set_freedv(int state);
+#endif
+
+extern void radio_change_region(int region);
+
+extern void disable_rigctl();
+
 #endif
index 8e62c11d011064326edd95f583d8c8207ff63cab..7d4dd17f55f29a56ddf16964cf27e68a5ca67c25 100644 (file)
@@ -20,6 +20,8 @@
 #include <gtk/gtk.h>
 #include <semaphore.h>
 #include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "new_menu.h"
@@ -28,6 +30,8 @@
 #include "filter.h"
 #include "radio.h"
 #include "receiver.h"
+#include "new_protocol.h"
+#include "old_protocol.h"
 
 static GtkWidget *parent_window=NULL;
 
@@ -35,15 +39,24 @@ static GtkWidget *menu_b=NULL;
 
 static GtkWidget *dialog=NULL;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 vfo_divisor_value_changed_cb(GtkWidget *widget, gpointer data) {
   vfo_encoder_divisor=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
 }
@@ -142,19 +155,26 @@ static void apollo_cb(GtkWidget *widget, gpointer data) {
 }
 
 static void sample_rate_cb(GtkWidget *widget, gpointer data) {
-  radio_change_sample_rate((int)data);
+  radio_change_sample_rate((uintptr_t)data);
 }
 
 static void receivers_cb(GtkWidget *widget, gpointer data) {
-  radio_change_receivers((int)data);
+  radio_change_receivers((uintptr_t)data);
+}
+
+static void region_cb(GtkWidget *widget, gpointer data) {
+  radio_change_region(gtk_combo_box_get_active (GTK_COMBO_BOX(widget)));
+/*
+  radio_change_region((uintptr_t)data);
+*/
 }
 
 static void rit_cb(GtkWidget *widget,gpointer data) {
-  rit_increment=(int)data;
+  rit_increment=(uintptr_t)data;
 }
 
 static void ck10mhz_cb(GtkWidget *widget, gpointer data) {
-  atlas_clock_source_10mhz = (int)data;
+  atlas_clock_source_10mhz = (uintptr_t)data;
 }
 
 static void ck128mhz_cb(GtkWidget *widget, gpointer data) {
@@ -174,7 +194,9 @@ void radio_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - Radio");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -195,6 +217,28 @@ void radio_menu(GtkWidget *parent) {
   g_signal_connect (close_b, "button_press_event", G_CALLBACK(close_cb), NULL);
   gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
 
+  GtkWidget *region_label=gtk_label_new("Region: ");
+  gtk_grid_attach(GTK_GRID(grid),region_label,1,0,1,1);
+  
+  GtkWidget *region_combo=gtk_combo_box_text_new();
+  gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(region_combo),NULL,"Other");
+  gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(region_combo),NULL,"UK");
+  gtk_combo_box_set_active(GTK_COMBO_BOX(region_combo),region);
+  gtk_grid_attach(GTK_GRID(grid),region_combo,2,0,1,1);
+  g_signal_connect(region_combo,"changed",G_CALLBACK(region_cb),NULL);
+
+/*
+  GtkWidget *uk_region=gtk_radio_button_new_with_label(NULL,"UK");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (uk_region), region==REGION_UK);
+  gtk_grid_attach(GTK_GRID(grid),uk_region,2,0,1,1);
+  g_signal_connect(uk_region,"pressed",G_CALLBACK(region_cb),(gpointer)REGION_UK);
+
+  GtkWidget *other_region=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(uk_region),"Other");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (other_region),region==REGION_OTHER);
+  gtk_grid_attach(GTK_GRID(grid),other_region,3,0,1,1);
+  g_signal_connect(other_region,"pressed",G_CALLBACK(region_cb),(gpointer)REGION_OTHER);
+*/
+
   int x=0;
 
   GtkWidget *receivers_label=gtk_label_new("Receivers: ");
@@ -277,8 +321,6 @@ void radio_menu(GtkWidget *parent) {
       }
       break;
 #endif
-     
-
   }
 
 
@@ -327,10 +369,10 @@ void radio_menu(GtkWidget *parent) {
   }
 
 
-  GtkWidget *rit_label=gtk_label_new("RIT step: ");
+  GtkWidget *rit_label=gtk_label_new("RIT step (Hz): ");
   gtk_grid_attach(GTK_GRID(grid),rit_label,x,1,1,1);
 
-  GtkWidget *rit_1=gtk_radio_button_new_with_label(NULL,"1 Hz");
+  GtkWidget *rit_1=gtk_radio_button_new_with_label(NULL,"1");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rit_1), rit_increment==1);
   gtk_grid_attach(GTK_GRID(grid),rit_1,x,2,1,1);
   g_signal_connect(rit_1,"pressed",G_CALLBACK(rit_cb),(gpointer *)1);
index 9cd8b93a0ac2097ef7b4b22dcd5a0ecae5a33453..bd4381241f7dbddf36ec67b01f90d530366d6ec7 100644 (file)
@@ -17,4 +17,4 @@
 *
 */
 
-extern void general_menu(GtkWidget *parent);
+extern void radio_menu(GtkWidget *parent);
index b4cf2f7d26b785ceabbbb4b96616759c47ebcbb5..712e7243ef11a9e860a9a429cd84a0f94cf7f684 100644 (file)
 #include "receiver.h"
 #include "transmitter.h"
 #include "vfo.h"
+
 #include <pigpio.h>
 
+#define OUTPUT_BUFFER_SIZE 1024
 #define SPEED_48K                 0x00
 #define SPEED_96K                 0x01
 #define SPEED_192K                0x02
@@ -63,28 +65,28 @@ static pthread_t radioberry_thread_id;
 static void start_radioberry_thread();
 static void *radioberry_thread(void* arg);
 
-static void setSampleSpeed(int r);
-static void handleReceiveStream(int r);
+static void setSampleSpeed();
+static void handleReceiveStream();
 
-struct timeval rx1_t0;
-struct timeval rx1_t1;
-struct timeval rx2_t0;
-struct timeval rx2_t1;
+struct timeval t0;
+struct timeval t1;
 struct timeval t10;
 struct timeval t11;
 struct timeval t20;
 struct timeval t21;
 float elapsed;
 
+#define RADIOSTATE_RX   0
+#define RADIOSTATE_TX   1
+static int radiostate = RADIOSTATE_RX;
+
 void spiWriter();
-void rx1_spiReader();
-void rx2_spiReader();
+void spiReader();
 
 
 int prev_drive_level;
 
-static int rx1_count =0;
-static int rx2_count =0;
+static int rxcount =0;
 static int txcount =0;
 
 sem_t mutex;
@@ -94,8 +96,7 @@ static int psk_samples=0;
 static int psk_divisor=6;
 #endif
 
-static int rx1_spi_handler;
-static int rx2_spi_handler;
+static int h;
 
 
 float timedifference_msec(struct timeval t0, struct timeval t1)
@@ -118,25 +119,20 @@ void radioberry_protocol_init(int rx,int pixels) {
        }
 #endif  
  
-       gpioSetMode(13, PI_INPUT);      //rx1_FIFOEmpty
-       gpioSetMode(16, PI_INPUT);      //rx2_FIFOEmpty
+       gpioSetMode(13, PI_INPUT); 
        gpioSetMode(20, PI_INPUT); 
        gpioSetMode(21, PI_OUTPUT); 
    
-       rx1_spi_handler = spiOpen(0, 15625000, 49155);  //channel 0
-       if (rx1_spi_handler < 0) {
-               fprintf(stderr,"radioberry_protocol: spi bus rx1 could not be initialized. \n");
+       h = spiOpen(0, 15625000, 49155); 
+       if (h < 0) {
+               fprintf(stderr,"radioberry_protocol: spi bus could not be initialized. \n");
                exit(-1);
        }
        
-       rx2_spi_handler = spiOpen(1, 15625000, 49155);  //channel 1
-       if (rx2_spi_handler < 0) {
-               fprintf(stderr,"radioberry_protocol: spi bus rx2 could not be initialized. \n");
-               exit(-1);
-       }
-
        printf("init done \n");
+  
+       setSampleSpeed();
+
        if(transmitter->local_microphone) {
                if(audio_open_input()!=0) {
                  fprintf(stderr,"audio_open_input failed\n");
@@ -163,52 +159,38 @@ static void *radioberry_thread(void* arg) {
        running=1;
 
        gettimeofday(&t20, 0);
-       gettimeofday(&rx1_t0, 0);
-       gettimeofday(&rx2_t0, 0);
+       gettimeofday(&t0, 0);
        
        gpioSetMode(13, PI_INPUT); 
-       gpioSetMode(16, PI_INPUT); 
        gpioSetMode(20, PI_INPUT); 
        gpioSetMode(21, PI_OUTPUT); 
        
        while(running) {
        
-               if (!isTransmitting()) 
+               sem_wait(&mutex); 
+               
+               if (isTransmitting()) 
+                       radiostate = RADIOSTATE_TX;
+               else
+                       radiostate = RADIOSTATE_RX;
+               
+               if(radiostate == RADIOSTATE_TX) {
+                       gpioWrite(21, 1); 
+               }
+               else 
                {
-                       sem_wait(&mutex);
-                       
                        gpioWrite(21, 0);
-                       
-                       //possible to use different sample rates per receiver... 
-                       //if the sample rate differs between the receivers.. the highest sample rate 
-                       //must be called an extra time.
-                       if (receivers==1){
-                               rx1_spiReader();
-                       } else {
-                               if (receiver[0]->sample_rate == receiver[1]->sample_rate) {
-                                       rx1_spiReader();
-                                       rx2_spiReader();
-                               } else {
-                                       if (receiver[0]->sample_rate > receiver[1]->sample_rate) {
-                                                       rx1_spiReader();
-                                                       rx1_spiReader();
-                                                       rx2_spiReader();
-                                       } else {
-                                                       rx1_spiReader();
-                                                       rx2_spiReader();
-                                                       rx2_spiReader();
-                                       }
-                               }
-                       }
+                       spiReader();
+                       handleReceiveStream();
                        sem_post(&mutex);
                }
        }
 }
 
 void radioberry_protocol_iq_samples(int isample,int qsample) {
+
+       if(radiostate == RADIOSTATE_TX) {
        
-               sem_wait(&mutex);
-               
                tx_iqdata[0] = 0;
                tx_iqdata[1] = drive / 6.4;  // convert drive level from 0-255 to 0-39 )
                if (prev_drive_level != drive) {
@@ -221,8 +203,10 @@ void radioberry_protocol_iq_samples(int isample,int qsample) {
                tx_iqdata[5] = qsample;
 
                spiWriter();
-
+               
                sem_post(&mutex);
+       }
+
 }
 
 void *radioberry_protocol_process_local_mic(unsigned char *buffer,int le) {
@@ -238,15 +222,20 @@ void *radioberry_protocol_process_local_mic(unsigned char *buffer,int le) {
                } else {
                        mic_sample = (short)((buffer[b++]<<8) | (buffer[b++]&0xFF));
                }
-               add_mic_sample(transmitter,mic_sample);
+                if(active_receiver->freedv) {
+                 add_freedv_mic_sample(transmitter,mic_sample);
+                } else {
+                 add_mic_sample(transmitter,mic_sample);
+                }
        }
 }
 
-static void handleReceiveStream(int r) {
+static void handleReceiveStream() {
        int left_sample;
        int right_sample;
        double left_sample_double;
        double right_sample_double;
+       int r;
   
        left_sample   = (int)((signed char) iqdata[0]) << 16;
        left_sample  += (int)((unsigned char)iqdata[1]) << 8;
@@ -258,14 +247,13 @@ static void handleReceiveStream(int r) {
        left_sample_double=(double)left_sample/8388607.0; // 24 bit sample 2^23-1
     right_sample_double=(double)right_sample/8388607.0; // 24 bit sample 2^23-1
        
-       // add the samples to the receiver..
-       add_iq_samples(receiver[r], left_sample_double,right_sample_double);
-       
+       for(r=0;r<RECEIVERS;r++) {
+               add_iq_samples(receiver[r], left_sample_double,right_sample_double);
+       }
 }
 
-void setSampleSpeed(int r) {
-       
-     switch(receiver[r]->sample_rate) {
+void setSampleSpeed() {
+     switch(active_receiver->sample_rate) {
         case 48000:
           sampleSpeed=SPEED_48K;
           break;
@@ -285,10 +273,8 @@ void radioberry_protocol_stop() {
   
        running=FALSE;
 
-       if (rx1_spi_handler !=0)
-               spiClose(rx1_spi_handler);
-       if (rx2_spi_handler !=0)
-               spiClose(rx2_spi_handler);
+       if (h !=0)
+               spiClose(h);
                
 #ifndef GPIO 
        gpioTerminate();
@@ -296,110 +282,47 @@ void radioberry_protocol_stop() {
        
 }
 
-void rx1_spiReader() {
+void spiReader() {
        // wait till rxFIFO buffer is filled with at least one element
        while ( gpioRead(13) == 1) {};
        
-       setSampleSpeed(0);
-
-       long long rxFrequency=vfo[0].frequency-vfo[0].lo;
-       if(vfo[0].rit_enabled) {
-         rxFrequency+=vfo[0].rit;
-       }
-       if (active_receiver->id==0) {
-               if(vfo[0].mode==modeCWU) {
-                       rxFrequency-=(long long)cw_keyer_sidetone_frequency;
-               } else if(vfo[0].mode==modeCWL) {
-                       rxFrequency+=(long long)cw_keyer_sidetone_frequency;
-               }
-       }
+       setSampleSpeed();
        
-       iqdata[0] = (sampleSpeed & 0x03);
-       iqdata[1] = (((active_receiver->random << 6) & 0x40) | ((active_receiver->dither <<5) & 0x20) |  (attenuation & 0x1F));
-       iqdata[2] = ((rxFrequency >> 24) & 0xFF);
-       iqdata[3] = ((rxFrequency >> 16) & 0xFF);
-       iqdata[4] = ((rxFrequency >> 8) & 0xFF);
-       iqdata[5] = (rxFrequency & 0xFF);
-                       
-       spiXfer(rx1_spi_handler, iqdata, iqdata, 6);
-       
-       //firmware: tdata(56'h00010203040506) -> 0-1-2-3-4-5-6 (element 0 contains 0; second element contains 1)
-       rx1_count ++;
-       if (rx1_count == 48000) {
-               rx1_count = 0;
-               gettimeofday(&rx1_t1, 0);
-               elapsed = timedifference_msec(rx1_t0, rx1_t1);
-               printf("Code rx1 mode spi executed in %f milliseconds.\n", elapsed);
-               gettimeofday(&rx1_t0, 0);
+       int v=receiver[0]->id;
+       long long rxFrequency=vfo[v].frequency-vfo[v].lo;
+       if(vfo[v].rit_enabled) {
+         rxFrequency+=vfo[v].rit;
        }
-       
-       handleReceiveStream(0);
-}
-
-void rx2_spiReader() {
-
-       // wait till rx2FIFO buffer is filled with at least one element
-       while ( gpioRead(16) == 1) {};
-       
-       setSampleSpeed(1);
-       
-       long long rxFrequency=vfo[1].frequency-vfo[1].lo;
-       if(vfo[1].rit_enabled) {
-         rxFrequency+=vfo[1].rit;
-       }
-       if (active_receiver->id==1) {
-               if(vfo[1].mode==modeCWU) {
-                       rxFrequency-=(long long)cw_keyer_sidetone_frequency;
-               } else if(vfo[1].mode==modeCWL) {
-                       rxFrequency+=(long long)cw_keyer_sidetone_frequency;
-               }
+       if(vfo[active_receiver->id].mode==modeCWU) {
+         rxFrequency-=(long long)cw_keyer_sidetone_frequency;
+       } else if(vfo[active_receiver->id].mode==modeCWL) {
+         rxFrequency+=(long long)cw_keyer_sidetone_frequency;
        }
        
        iqdata[0] = (sampleSpeed & 0x03);
-       iqdata[1] = 0x00;       //not used by firmware; the active receiver settings are set via rx1
+       iqdata[1] = (((active_receiver->random << 6) & 0x40) | ((active_receiver->dither <<5) & 0x20) |  (attenuation & 0x1F));
        iqdata[2] = ((rxFrequency >> 24) & 0xFF);
        iqdata[3] = ((rxFrequency >> 16) & 0xFF);
        iqdata[4] = ((rxFrequency >> 8) & 0xFF);
        iqdata[5] = (rxFrequency & 0xFF);
                        
-       spiXfer(rx2_spi_handler, iqdata, iqdata, 6);
+       spiXfer(h, iqdata, iqdata, 6);
        
        //firmware: tdata(56'h00010203040506) -> 0-1-2-3-4-5-6 (element 0 contains 0; second element contains 1)
-       rx2_count ++;
-       if (rx2_count == 48000) {
-               rx2_count = 0;
-               gettimeofday(&rx2_t1, 0);
-               elapsed = timedifference_msec(rx2_t0, rx2_t1);
-               printf("Code rx2 mode spi executed in %f milliseconds.\n", elapsed);
-               gettimeofday(&rx2_t0, 0);
+       rxcount ++;
+       if (rxcount == 48000) {
+               rxcount = 0;
+               gettimeofday(&t1, 0);
+               elapsed = timedifference_msec(t0, t1);
+               printf("Code rx mode spi executed in %f milliseconds.\n", elapsed);
+               gettimeofday(&t0, 0);
        }
-       
-       handleReceiveStream(1);
 }
 
-
 void spiWriter() {
-
-       gpioWrite(21, 1); 
-
        while ( gpioRead(20) == 1) {};
 
-       spiXfer(rx1_spi_handler, tx_iqdata, tx_iqdata, 6);
-       
-       long long txFrequency;
-       if(split) {
-               txFrequency=vfo[VFO_B].frequency-vfo[VFO_A].lo+vfo[VFO_B].offset;
-       } else {
-               txFrequency=vfo[VFO_A].frequency-vfo[VFO_B].lo+vfo[VFO_A].offset;
-       }
-       tx_iqdata[0] = 0x00;
-       tx_iqdata[1] = 0x00;
-       tx_iqdata[2] = ((txFrequency >> 24) & 0xFF);
-       tx_iqdata[3] = ((txFrequency >> 16) & 0xFF);
-       tx_iqdata[4] = ((txFrequency >> 8) & 0xFF);
-       tx_iqdata[5] = (txFrequency & 0xFF);
-                               
-       spiXfer(rx2_spi_handler, tx_iqdata, tx_iqdata, 6);
+       spiXfer(h, tx_iqdata, tx_iqdata, 6);
        
        txcount ++;
        if (txcount == 48000) {
index 6bad5f3ec3326e75e73cb3189bc04ea375483354..197252c0f65230533b04602b30ba908c90738a68 100644 (file)
 #include <wdsp.h>
 
 #include "agc.h"
+#include "audio.h"
 #include "band.h"
 #include "bandstack.h"
+#include "channel.h"
 #include "discovered.h"
 #include "filter.h"
 #include "main.h"
@@ -40,6 +42,7 @@
 #include "property.h"
 #include "radio.h"
 #include "receiver.h"
+#include "transmitter.h"
 #include "vfo.h"
 #include "meter.h"
 #include "rx_panadapter.h"
 #ifdef FREEDV
 #include "freedv.h"
 #endif
+#include "audio_waterfall.h"
 #ifdef RADIOBERRY
 #include "radioberry.h"
 #endif
+#include "ext.h"
+#include "new_menu.h"
 
 
 #define min(x,y) (x<y?x:y)
 #define max(x,y) (x<y?y:x)
 
-#ifdef FREEDV
-static int freedv_samples=0;
-static int freedv_resample=6;  // convert from 48000 to 8000
-#endif
 #ifdef PSK
 static int psk_samples=0;
 static int psk_resample=6;  // convert from 48000 to 8000
@@ -70,6 +72,14 @@ static gboolean has_moved=FALSE;
 static gboolean pressed=FALSE;
 static gboolean making_active=FALSE;
 
+static int waterfall_samples=0;
+static int waterfall_resample=6;
+
+void receiver_weak_notify(gpointer data,GObject  *obj) {
+  RECEIVER *rx=(RECEIVER *)data;
+  fprintf(stderr,"receiver_weak_notify: id=%d obj=%p\n",rx->id, obj);
+}
+
 gboolean receiver_button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data) {
   RECEIVER *rx=(RECEIVER *)data;
   if(rx==active_receiver) {
@@ -90,8 +100,9 @@ gboolean receiver_button_release_event(GtkWidget *widget, GdkEventButton *event,
   if(making_active) {
     active_receiver=rx;
     making_active=FALSE;
-    g_idle_add(vfo_update,NULL);
-    g_idle_add(active_receiver_changed,NULL);
+    g_idle_add(menu_active_receiver_changed,NULL);
+    g_idle_add(ext_vfo_update,NULL);
+    g_idle_add(sliders_active_receiver_changed,NULL);
   } else {
     int display_width=gtk_widget_get_allocated_width (rx->panadapter);
     int display_height=gtk_widget_get_allocated_height (rx->panadapter);
@@ -223,6 +234,12 @@ void receiver_save_state(RECEIVER *rx) {
   sprintf(name,"receiver.%d.preamp",rx->id);
   sprintf(value,"%d",rx->preamp);
   setProperty(name,value);
+  sprintf(name,"receiver.%d.nb",rx->id);
+  sprintf(value,"%d",rx->nb);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.nb2",rx->id);
+  sprintf(value,"%d",rx->nb2);
+  setProperty(name,value);
   sprintf(name,"receiver.%d.nr",rx->id);
   sprintf(value,"%d",rx->nr);
   setProperty(name,value);
@@ -260,10 +277,30 @@ void receiver_save_state(RECEIVER *rx) {
   sprintf(name,"receiver.%d.audio_device",rx->id);
   sprintf(value,"%d",rx->audio_device);
   setProperty(name,value);
+  sprintf(name,"receiver.%d.mute_radio",rx->id);
+  sprintf(value,"%d",rx->mute_radio);
+  setProperty(name,value);
 
   sprintf(name,"receiver.%d.low_latency",rx->id);
   sprintf(value,"%d",rx->low_latency);
   setProperty(name,value);
+
+  sprintf(name,"receiver.%d.deviation",rx->id);
+  sprintf(value,"%d",rx->deviation);
+  setProperty(name,value);
+
+  sprintf(name,"receiver.%d.squelch_enable",rx->id);
+  sprintf(value,"%d",rx->squelch_enable);
+  setProperty(name,value);
+  sprintf(name,"receiver.%d.squelch",rx->id);
+  sprintf(value,"%f",rx->squelch);
+  setProperty(name,value);
+
+#ifdef FREEDV
+  sprintf(name,"receiver.%d.freedv",rx->id);
+  sprintf(value,"%d",rx->freedv);
+  setProperty(name,value);
+#endif
 }
 
 void receiver_restore_state(RECEIVER *rx) {
@@ -356,6 +393,12 @@ fprintf(stderr,"receiver_restore_state: id=%d\n",rx->id);
   sprintf(name,"receiver.%d.preamp",rx->id);
   value=getProperty(name);
   if(value) rx->preamp=atoi(value);
+  sprintf(name,"receiver.%d.nb",rx->id);
+  value=getProperty(name);
+  if(value) rx->nb=atoi(value);
+  sprintf(name,"receiver.%d.nb2",rx->id);
+  value=getProperty(name);
+  if(value) rx->nb2=atoi(value);
   sprintf(name,"receiver.%d.nr",rx->id);
   value=getProperty(name);
   if(value) rx->nr=atoi(value);
@@ -393,9 +436,29 @@ fprintf(stderr,"receiver_restore_state: id=%d\n",rx->id);
   sprintf(name,"receiver.%d.audio_device",rx->id);
   value=getProperty(name);
   if(value) rx->audio_device=atoi(value);
+  sprintf(name,"receiver.%d.mute_radio",rx->id);
+  value=getProperty(name);
+  if(value) rx->mute_radio=atoi(value);
   sprintf(name,"receiver.%d.low_latency",rx->id);
   value=getProperty(name);
   if(value) rx->low_latency=atoi(value);
+
+  sprintf(name,"receiver.%d.deviation",rx->id);
+  value=getProperty(name);
+  if(value) rx->deviation=atoi(value);
+
+  sprintf(name,"receiver.%d.squelch_enable",rx->id);
+  value=getProperty(name);
+  if(value) rx->squelch_enable=atoi(value);
+  sprintf(name,"receiver.%d.squelch",rx->id);
+  value=getProperty(name);
+  if(value) rx->squelch=atof(value);
+
+#ifdef FREEDV
+  sprintf(name,"receiver.%d.freedv",rx->id);
+  value=getProperty(name);
+  if(value) rx->freedv=atoi(value);
+#endif
 }
 
 void reconfigure_receiver(RECEIVER *rx,int height) {
@@ -459,6 +522,8 @@ static gint update_display(gpointer data) {
   RECEIVER *rx=(RECEIVER *)data;
   int rc;
 
+//fprintf(stderr,"update_display: %d displaying=%d\n",rx->id,rx->displaying);
+
   if(rx->displaying) {
     GetPixels(rx->id,0,rx->pixel_samples,&rc);
     if(rc) {
@@ -479,8 +544,18 @@ static gint update_display(gpointer data) {
       }
     }
 
+#ifdef AUDIO_SAMPLES
+    if(audio_samples!=NULL) {
+      GetPixels(CHANNEL_AUDIO,0,audio_samples,&rc);
+      if(rc) {
+        //audio_waterfall_update();
+      }
+    }
+#endif
+
+
     if(active_receiver==rx) {
-      double m=GetRXAMeter(rx->id,smeter);
+      double m=GetRXAMeter(rx->id,smeter)+meter_calibration;
       meter_update(SMETER,m,0.0,0.0,0.0);
     }
     return TRUE;
@@ -497,14 +572,6 @@ void set_displaying(RECEIVER *rx,int state) {
 
 void set_mode(RECEIVER *rx,int m) {
   int local_mode=m;
-#ifdef FREEDV
-  if(vfo[rx->d].mode!=modeFREEDV && m==modeFREEDV) {
-    local_mode=modeUSB;
-    init_freedv();
-  } else if(vfo[rx->id].mode==modeFREEDV && m!=modeFREEDV) {
-    close_freedv();
-  }
-#endif
 #ifdef PSK
   if(vfo[rx->id].mode!=modePSK && m==modePSK) {
     local_mode=modeUSB;
@@ -534,8 +601,8 @@ void set_filter(RECEIVER *rx,int low,int high) {
   RXASetPassband(rx->id,(double)rx->filter_low,(double)rx->filter_high);
 }
 
-void set_deviation(RECEIVER *rx,double deviation) {
-  SetRXAFMDeviation(rx->id, deviation);
+void set_deviation(RECEIVER *rx) {
+  SetRXAFMDeviation(rx->id, (double)rx->deviation);
 }
 
 void set_agc(RECEIVER *rx, int agc) {
@@ -643,8 +710,9 @@ static void init_analyzer(RECEIVER *rx) {
 static void create_visual(RECEIVER *rx) {
   int y=0;
 
-fprintf(stderr,"receiver: create_visual: id=%d width=%d height=%d\n",rx->id, rx->width, rx->height);
   rx->panel=gtk_fixed_new();
+fprintf(stderr,"receiver: create_visual: id=%d width=%d height=%d %p\n",rx->id, rx->width, rx->height, rx->panel);
+  g_object_weak_ref(G_OBJECT(rx->panel),receiver_weak_notify,(gpointer)rx);
   gtk_widget_set_size_request (rx->panel, rx->width, rx->height);
 
   rx->panadapter=NULL;
@@ -655,27 +723,128 @@ fprintf(stderr,"receiver: create_visual: id=%d width=%d height=%d\n",rx->id, rx-
     height=height/2;
   }
 
-fprintf(stderr,"receiver: panadapter_init: height=%d y=%d\n",height,y);
   rx_panadapter_init(rx, rx->width,height);
+fprintf(stderr,"receiver: panadapter_init: height=%d y=%d %p\n",height,y,rx->panadapter);
+  g_object_weak_ref(G_OBJECT(rx->panadapter),receiver_weak_notify,(gpointer)rx);
   gtk_fixed_put(GTK_FIXED(rx->panel),rx->panadapter,0,y);
   y+=height;
 
   if(rx->display_waterfall) {
-fprintf(stderr,"receiver: waterfall_init: height=%d y=%d\n",height,y);
     waterfall_init(rx,rx->width,height);
+fprintf(stderr,"receiver: waterfall_init: height=%d y=%d %p\n",height,y,rx->waterfall);
+    g_object_weak_ref(G_OBJECT(rx->waterfall),receiver_weak_notify,(gpointer)rx);
     gtk_fixed_put(GTK_FIXED(rx->panel),rx->waterfall,0,y);
   }
+
+  gtk_widget_show_all(rx->panel);
 }
 
+#ifdef PURESIGNAL
+RECEIVER *create_pure_signal_receiver(int id, int buffer_size,int sample_rate,int pixels) {
+fprintf(stderr,"create_pure_signal_receiver: id=%d buffer_size=%d\n",id,buffer_size);
+  RECEIVER *rx=malloc(sizeof(RECEIVER));
+  rx->id=id;
+
+  rx->ddc=4;
+  rx->adc=0;  // one more than actual adc
+
+  rx->sample_rate=sample_rate;
+  rx->buffer_size=buffer_size;
+  rx->fft_size=fft_size;
+  rx->pixels=0;
+  rx->fps=0;
+
+  rx->width=0;
+  rx->height=0;
+  rx->display_panadapter=0;
+  rx->display_waterfall=0;
+
+  // allocate buffers
+  rx->iq_sequence=0;
+  rx->iq_input_buffer=malloc(sizeof(double)*2*rx->buffer_size);
+  rx->audio_buffer=NULL;
+  rx->audio_sequence=0L;
+  rx->pixel_samples=malloc(sizeof(float)*pixels);
+
+  rx->samples=0;
+  rx->displaying=0;
+  rx->display_panadapter=0;
+  rx->display_waterfall=0;
+
+  rx->panadapter_high=-40;
+  rx->panadapter_low=-140;
+
+  rx->volume=0.0;
+  rx->attenuation=0;
+
+  rx->dither=0;
+  rx->random=0;
+  rx->preamp=0;
+
+  rx->nb=0;
+  rx->nb2=0;
+  rx->nr=0;
+  rx->nr2=0;
+  rx->anf=0;
+  rx->snb=0;
+
+  rx->nr_agc=0;
+  rx->nr2_gain_method=2;
+  rx->nr2_npe_method=0;
+  rx->nr2_ae=1;
+  
+  rx->alex_antenna=0;
+  rx->alex_attenuation=0;
+
+  rx->agc=AGC_MEDIUM;
+  rx->agc_gain=80.0;
+  rx->agc_slope=35.0;
+  rx->agc_hang_threshold=0.0;
+  
+  rx->playback_handle=NULL;
+  rx->playback_buffer=NULL;
+  rx->local_audio=0;
+  rx->mute_when_not_active=0;
+  rx->audio_channel=STEREO;
+  rx->audio_device=-1;
+  rx->mute_radio=0;
+
+  rx->low_latency=0;
+
+  int result;
+  XCreateAnalyzer(rx->id, &result, 262144, 1, 1, "");
+  if(result != 0) {
+    fprintf(stderr, "XCreateAnalyzer id=%d failed: %d\n", rx->id, result);
+  } else {
+    init_analyzer(rx);
+  }
+
+  SetDisplayDetectorMode(rx->id, 0, display_detector_mode);
+  SetDisplayAverageMode(rx->id, 0,  display_average_mode);
+
+  return rx;
+}
+#endif
+
 RECEIVER *create_receiver(int id, int buffer_size, int fft_size, int pixels, int fps, int width, int height) {
 fprintf(stderr,"create_receiver: id=%d buffer_size=%d fft_size=%d pixels=%d fps=%d\n",id,buffer_size, fft_size, pixels, fps);
   RECEIVER *rx=malloc(sizeof(RECEIVER));
   rx->id=id;
   switch(id) {
     case 0:
+      if(protocol==NEW_PROTOCOL && device==NEW_DEVICE_HERMES) {
+        rx->ddc=0;
+      } else {
+        rx->ddc=2;
+      }
       rx->adc=0;
       break;
     default:
+      if(protocol==NEW_PROTOCOL && device==NEW_DEVICE_HERMES) {
+        rx->ddc=1;
+      } else {
+        rx->ddc=3;
+      }
       switch(protocol) {
         case ORIGINAL_PROTOCOL:
 #ifdef RADIOBERRY
@@ -708,24 +877,22 @@ fprintf(stderr,"create_receiver: id=%d buffer_size=%d fft_size=%d pixels=%d fps=
           break;
       }
   }
-fprintf(stderr,"create_receiver: id=%d default adc=%d\n",rx->id, rx->adc);
+fprintf(stderr,"create_receiver: id=%d default ddc=%d adc=%d\n",rx->id, rx->ddc, rx->adc);
   rx->sample_rate=48000;
   rx->buffer_size=buffer_size;
   rx->fft_size=fft_size;
   rx->pixels=pixels;
   rx->fps=fps;
 
-  BAND *b=band_get_band(vfo[rx->id].band);
 
 //  rx->dds_offset=0;
 //  rx->rit=0;
 
   rx->width=width;
   rx->height=height;
-  rx->display_panadapter=1;
-  rx->display_waterfall=1;
 
   // allocate buffers
+  rx->iq_sequence=0;
   rx->iq_input_buffer=malloc(sizeof(double)*2*rx->buffer_size);
   rx->audio_buffer=malloc(AUDIO_BUFFER_SIZE);
   rx->audio_sequence=0L;
@@ -739,13 +906,19 @@ fprintf(stderr,"create_receiver: id=%d default adc=%d\n",rx->id, rx->adc);
   rx->panadapter_high=-40;
   rx->panadapter_low=-140;
 
-  rx->volume=0.2;
+  rx->waterfall_high=-40;
+  rx->waterfall_low=-140;
+  rx->waterfall_automatic=1;
+
+  rx->volume=0.1;
   rx->attenuation=0;
 
   rx->dither=0;
   rx->random=0;
   rx->preamp=0;
 
+  rx->nb=0;
+  rx->nb2=0;
   rx->nr=0;
   rx->nr2=0;
   rx->anf=0;
@@ -756,6 +929,7 @@ fprintf(stderr,"create_receiver: id=%d default adc=%d\n",rx->id, rx->adc);
   rx->nr2_npe_method=0;
   rx->nr2_ae=1;
   
+  BAND *b=band_get_band(vfo[rx->id].band);
   rx->alex_antenna=b->alexRxAntenna;
   rx->alex_attenuation=b->alexAttenuation;
 
@@ -772,17 +946,36 @@ fprintf(stderr,"create_receiver: id=%d default adc=%d\n",rx->id, rx->adc);
 
   rx->low_latency=0;
 
+  rx->squelch_enable=0;
+  rx->squelch=0;
+
+  rx->filter_high=525;
+  rx->filter_low=275;
+#ifdef FREEDV
+  g_mutex_init(&rx->freedv_mutex);
+  rx->freedv=0;
+  rx->freedv_samples=0;
+  strcpy(rx->freedv_text_data,"");
+  rx->freedv_text_index=0;
+#endif
+
+  rx->deviation=2500;
+
+  rx->mute_radio=0;
+
   receiver_restore_state(rx);
 
   int scale=rx->sample_rate/48000;
   rx->output_samples=rx->buffer_size/scale;
   rx->audio_output_buffer=malloc(sizeof(double)*2*rx->output_samples);
+
 fprintf(stderr,"create_receiver: id=%d output_samples=%d\n",rx->id,rx->output_samples);
 
   rx->hz_per_pixel=(double)rx->sample_rate/(double)rx->width;
+
   // setup wdsp for this receiver
 
-fprintf(stderr,"create_receiver: id=%d after restore adc=%d\n",rx->id, rx->adc);
+fprintf(stderr,"create_receiver: id=%d after restore ddc=%d adc=%d\n",rx->id, rx->ddc, rx->adc);
 
 fprintf(stderr,"create_receiver: OpenChannel id=%d buffer_size=%d fft_size=%d sample_rate=%d\n",
         rx->id,
@@ -799,26 +992,22 @@ fprintf(stderr,"create_receiver: OpenChannel id=%d buffer_size=%d fft_size=%d sa
               1, // run
               0.010, 0.025, 0.0, 0.010, 0);
 
+  create_anbEXT(rx->id,1,rx->buffer_size,rx->sample_rate,0.0001,0.0001,0.0001,0.05,20);
+  create_nobEXT(rx->id,1,0,rx->buffer_size,rx->sample_rate,0.0001,0.0001,0.0001,0.05,20);
+  
 fprintf(stderr,"RXASetNC %d\n",rx->fft_size);
   RXASetNC(rx->id, rx->fft_size);
 fprintf(stderr,"RXASetMP %d\n",rx->low_latency);
   RXASetMP(rx->id, rx->low_latency);
 
-  b=band_get_band(vfo[rx->id].band);
-  BANDSTACK *bs=b->bandstack;
-  BANDSTACK_ENTRY *entry=&bs->entry[vfo[rx->id].bandstack];
-  FILTER *band_filters=filters[vfo[rx->id].mode];
-  FILTER *band_filter=&band_filters[vfo[rx->id].filter];
-  set_filter(rx,band_filter->low,band_filter->high);
-  
-
-  SetRXAFMDeviation(rx->id,(double)deviation);
-
   set_agc(rx, rx->agc);
 
   SetRXAAMDSBMode(rx->id, 0);
   SetRXAShiftRun(rx->id, 0);
 
+  SetEXTANBRun(rx->id, rx->nb);
+  SetEXTNOBRun(rx->id, rx->nb2);
+
   SetRXAEMNRPosition(rx->id, rx->nr_agc);
   SetRXAEMNRgainMethod(rx->id, rx->nr2_gain_method);
   SetRXAEMNRnpeMethod(rx->id, rx->nr2_npe_method);
@@ -830,9 +1019,18 @@ fprintf(stderr,"RXASetMP %d\n",rx->low_latency);
   SetRXAANFRun(rx->id, rx->anf);
   SetRXASNBARun(rx->id, rx->snb);
 
+
   SetRXAPanelGain1(rx->id, rx->volume);
   SetRXAPanelBinaural(rx->id, binaural);
-  SetRXAPanelRun(rx->id, 1);
+#ifdef FREEDV
+  if(rx->freedv) {
+    SetRXAPanelRun(rx->id, 0);
+  } else {
+#endif
+    SetRXAPanelRun(rx->id, 1);
+#ifdef FREEDV
+  }
+#endif
 
   if(enable_rx_equalizer) {
     SetRXAGrphEQ(rx->id, rx_equalizer);
@@ -843,9 +1041,12 @@ fprintf(stderr,"RXASetMP %d\n",rx->low_latency);
 
   // setup for diversity
   create_divEXT(0,0,2,rx->buffer_size);
-  SetEXTDIVRotate(0, 2, &i_rotate, &q_rotate);
+  SetEXTDIVRotate(0, 2, &i_rotate[0], &q_rotate[0]);
   SetEXTDIVRun(0,diversity_enabled);
   
+  receiver_mode_changed(rx);
+  //set_mode(rx,vfo[rx->id].mode);
+  //set_filter(rx,rx->filter_low,rx->filter_high);
 
   int result;
   XCreateAnalyzer(rx->id, &result, 262144, 1, 1, "");
@@ -858,6 +1059,12 @@ fprintf(stderr,"RXASetMP %d\n",rx->low_latency);
   SetDisplayDetectorMode(rx->id, 0, display_detector_mode);
   SetDisplayAverageMode(rx->id, 0,  display_average_mode);
    
+#ifdef FREEDV
+  if(rx->freedv) {
+    init_freedv(rx);
+  }
+#endif
+
   calculate_display_average(rx);
 
   create_visual(rx);
@@ -875,21 +1082,19 @@ void receiver_change_adc(RECEIVER *rx,int adc) {
 
 void receiver_change_sample_rate(RECEIVER *rx,int sample_rate) {
 
-  rx->sample_rate=sample_rate;
-
   SetChannelState(rx->id,0,1);
 
+  rx->sample_rate=sample_rate;
   int scale=rx->sample_rate/48000;
   rx->output_samples=rx->buffer_size/scale;
   free(rx->audio_output_buffer);
   rx->audio_output_buffer=malloc(sizeof(double)*2*rx->output_samples);
   rx->audio_buffer=malloc(AUDIO_BUFFER_SIZE);
   rx->hz_per_pixel=(double)rx->sample_rate/(double)rx->width;
-
   SetInputSamplerate(rx->id, sample_rate);
-
   init_analyzer(rx);
-
+  SetEXTANBSamplerate (rx->id, sample_rate);
+  SetEXTNOBSamplerate (rx->id, sample_rate);
 fprintf(stderr,"receiver_change_sample_rate: id=%d rate=%d buffer_size=%d output_samples=%d\n",rx->id, rx->sample_rate, rx->buffer_size, rx->output_samples);
   SetChannelState(rx->id,1,0);
 }
@@ -905,20 +1110,31 @@ void receiver_frequency_changed(RECEIVER *rx) {
   }
 }
 
-void receiver_mode_changed(RECEIVER *rx) {
-  set_mode(rx,vfo[rx->id].mode);
+void receiver_filter_changed(RECEIVER *rx) {
+  int m=vfo[rx->id].mode;
+  if(m==modeFMN) {
+    if(rx->deviation==2500) {
+      set_filter(rx,-4000,4000);
+    } else {
+      set_filter(rx,-8000,8000);
+    }
+    set_deviation(rx);
+  } else {
+    FILTER *mode_filters=filters[m];
+    FILTER *filter=&mode_filters[vfo[rx->id].filter];
+    set_filter(rx,filter->low,filter->high);
+  }
 }
 
-void receiver_filter_changed(RECEIVER *rx) {
-  FILTER *mode_filters=filters[vfo[rx->id].mode];
-  FILTER *filter=&mode_filters[vfo[rx->id].filter];
-  set_filter(rx,filter->low,filter->high);
+void receiver_mode_changed(RECEIVER *rx) {
+  set_mode(rx,vfo[rx->id].mode);
+  receiver_filter_changed(rx);
 }
 
 void receiver_vfo_changed(RECEIVER *rx) {
   receiver_frequency_changed(rx);
   receiver_mode_changed(rx);
-  receiver_filter_changed(rx);
+  //receiver_filter_changed(rx);
 }
 
 #ifdef FREEDV
@@ -928,50 +1144,71 @@ static void process_freedv_rx_buffer(RECEIVER *rx) {
   int i;
   int demod_samples;
   for(i=0;i<rx->output_samples;i++) {
-    if(freedv_samples==0) {
-      left_audio_sample=(short)(rx->audio_output_buffer[i*2]*32767.0);
-      right_audio_sample=(short)(rx->audio_output_buffer[(i*2)+1]*32767.0);
-      demod_samples=demod_sample_freedv(left_audio_sample);
+    if(rx->freedv_samples==0) {
+      if(isTransmitting()) {
+        left_audio_sample=0;
+        right_audio_sample=0;
+      } else {
+        left_audio_sample=(short)(rx->audio_output_buffer[i*2]*32767.0);
+        right_audio_sample=(short)(rx->audio_output_buffer[(i*2)+1]*32767.0);
+      }
+      demod_samples=demod_sample_freedv((left_audio_sample+right_audio_sample)/2);
       if(demod_samples!=0) {
         int s;
         int t;
         for(s=0;s<demod_samples;s++) {
           if(freedv_sync) {
-            left_audio_sample=right_audio_sample=(short)((double)speech_out[s]);
+            left_audio_sample=right_audio_sample=(short)((double)speech_out[s]*rx->volume);
           } else {
-            left_audio_sample=right_audio_sample=0;
+            left_audio_sample=right_audio_sample=(short)((double)speech_out[s]*rx->volume);
+            //left_audio_sample=right_audio_sample=0;
           }
-          for(t=0;t<6;t++) { // 8k to 48k
-            if(local_audio) {
-                audio_write(left_audio_sample,right_audio_sample);
-                left_audio_sample=0;
-                right_audio_sample=0;
+          for(t=0;t<freedv_resample;t++) { // 8k to 48k
+
+            if(rx->local_audio) {
+              if(rx!=active_receiver && rx->mute_when_not_active) {
+                audio_write(rx,0,0);
+              } else {
+                switch(rx->audio_channel) {
+                  case STEREO:
+                    audio_write(rx,left_audio_sample,right_audio_sample);
+                    break;
+                  case LEFT:
+                    audio_write(rx,left_audio_sample,0);
+                    break;
+                  case RIGHT:
+                    audio_write(rx,0,right_audio_sample);
+                    break;
+                }
+              }
             }
 
-            switch(protocol) {
-              case ORIGINAL_PROTOCOL:
-                old_protocol_audio_samples(left_audio_sample,right_audio_sample);
-                break;
-              case NEW_PROTOCOL:
-                new_protocol_audio_samples(left_audio_sample,right_audio_sample);
-                break;
+            if(rx==active_receiver) {
+              switch(protocol) {
+                case ORIGINAL_PROTOCOL:
+                  old_protocol_audio_samples(rx,left_audio_sample,right_audio_sample);
+                  break;
+                case NEW_PROTOCOL:
+                  new_protocol_audio_samples(rx,left_audio_sample,right_audio_sample);
+                  break;
 #ifdef LIMESDR
-              case LIMESDR_PROTOCOL:
-                break;
+                case LIMESDR_PROTOCOL:
+                  break;
 #endif
 #ifdef RADIOBERRY
-                       case RADIOBERRY_PROTOCOL:
-                               //no audio stream to radioberry hardware, using local audio of rpi.
-                               break;
+                case RADIOBERRY_PROTOCOL:
+                  //no audio stream to radioberry hardware, using local audio of rpi.
+                  break;
 #endif
+              }
             }
           }
         }
       }
-      freedv_samples++;
-      if(freedv_samples==freedv_resample) {
-        freedv_samples=0;
-      }
+    }
+    rx->freedv_samples++;
+    if(rx->freedv_samples>=freedv_resample) {
+      rx->freedv_samples=0;
     }
   }
 }
@@ -1022,11 +1259,19 @@ static void process_rx_buffer(RECEIVER *rx) {
     if(rx==active_receiver) {
       switch(protocol) {
         case ORIGINAL_PROTOCOL:
-          old_protocol_audio_samples(rx,left_audio_sample,right_audio_sample);
+          if(rx->mute_radio) {
+            old_protocol_audio_samples(rx,(short)0,(short)0);
+          } else {
+            old_protocol_audio_samples(rx,left_audio_sample,right_audio_sample);
+          }
           break;
         case NEW_PROTOCOL:
           if(!(echo&&isTransmitting())) {
-            new_protocol_audio_samples(rx,left_audio_sample,right_audio_sample);
+            if(rx->mute_radio) {
+              new_protocol_audio_samples(rx,(short)0,(short)0);
+            } else {
+              new_protocol_audio_samples(rx,left_audio_sample,right_audio_sample);
+            }
           }
           break;
 #ifdef LIMESDR
@@ -1039,6 +1284,24 @@ static void process_rx_buffer(RECEIVER *rx) {
                break;
 #endif
       }
+
+#ifdef AUDIO_WATERFALL
+      if(audio_samples!=NULL) {
+        if(waterfall_samples==0) {
+          audio_samples[audio_samples_index]=(float)left_audio_sample;
+          audio_samples_index++;
+          if(audio_samples_index>=AUDIO_WATERFALL_SAMPLES) {
+            //Spectrum(CHANNEL_AUDIO,0,0,audio_samples,audio_samples);
+            audio_samples_index=0;
+          }
+        }
+        waterfall_samples++;
+        if(waterfall_samples==waterfall_resample) {
+          waterfall_samples=0;
+        }
+      }
+#endif
+
     }
 
   }
@@ -1048,6 +1311,14 @@ void full_rx_buffer(RECEIVER *rx) {
   int j;
   int error;
 
+  // noise blanker works on origianl IQ samples
+  if(rx->nb) {
+     xanbEXT (rx->id, rx->iq_input_buffer, rx->iq_input_buffer);
+  }
+  if(rx->nb2) {
+     xnobEXT (rx->id, rx->iq_input_buffer, rx->iq_input_buffer);
+  }
+
   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);
@@ -1057,23 +1328,27 @@ void full_rx_buffer(RECEIVER *rx) {
     Spectrum0(1, rx->id, 0, 0, rx->iq_input_buffer);
   }
 
-  switch(vfo[rx->id].mode) {
 #ifdef FREEDV
-    case modeFREEDV:
-      process_freedv_rx_buffer(rx);
-      break;
+  g_mutex_lock(&rx->freedv_mutex);
+  if(rx->freedv) {
+    process_freedv_rx_buffer(rx);
+  } else {
 #endif
-    default:
-      process_rx_buffer(rx);
-      break;
+    process_rx_buffer(rx);
+#ifdef FREEDV
   }
+  g_mutex_unlock(&rx->freedv_mutex);
+#endif
 }
 
+static int rx_buffer_seen=0;
+static int tx_buffer_seen=0;
+
 void add_iq_samples(RECEIVER *rx, double i_sample,double q_sample) {
   rx->iq_input_buffer[rx->samples*2]=i_sample;
   rx->iq_input_buffer[(rx->samples*2)+1]=q_sample;
   rx->samples=rx->samples+1;
-  if(rx->samples==rx->buffer_size) {
+  if(rx->samples>=rx->buffer_size) {
     full_rx_buffer(rx);
     rx->samples=0;
   }
index 40cfc69b0665f43499e308bfec53c4710475bb52..58546af924ed947cb01d6f9059afcd33a971458c 100644 (file)
@@ -35,6 +35,7 @@ typedef enum _audio_t audio_t;
 typedef struct _receiver {
   int id;
 
+  int ddc;
   int adc;
 
   double volume;
@@ -51,6 +52,7 @@ typedef struct _receiver {
   int pixels;
   int samples;
   int output_samples;
+  long iq_sequence;
   double *iq_input_buffer;
   double *audio_output_buffer;
   unsigned char *audio_buffer;
@@ -63,17 +65,12 @@ typedef struct _receiver {
 
   double hz_per_pixel;
 
-//  long long frequency;
-//  long long display_frequency;
-//  long long dds_frequency;
-//  long long dds_offset;
-
-//  int rit;
-
   int dither;
   int random;
   int preamp;
 
+  int nb;
+  int nb2;
   int nr;
   int nr2;
   int anf;
@@ -105,23 +102,42 @@ typedef struct _receiver {
   int waterfall_low;
   int waterfall_high;
   int waterfall_automatic;
-
   cairo_surface_t *panadapter_surface;
   GdkPixbuf *pixbuf;
-
   int local_audio;
   int mute_when_not_active;
   int audio_device;
   snd_pcm_t *playback_handle;
   int playback_offset;
   unsigned char *playback_buffer;
-
   int low_latency;
 
+  int squelch_enable;
+  double squelch;
+
+  int deviation;
+
+  long long waterfall_frequency;
+  int waterfall_sample_rate;
+
+  int mute_radio;
+
+#ifdef FREEDV
+  GMutex freedv_mutex;
+  int freedv;
+  int freedv_samples;
+  char freedv_text_data[64];
+  int freedv_text_index;
+#endif
+
+  int x;
+  int y;
 } RECEIVER;
 
+extern RECEIVER *create_pure_signal_receiver(int id, int buffer_size,int sample_rate,int pixels);
 extern RECEIVER *create_receiver(int id, int buffer_size, int fft_size, int pixels, int fps, int width, int height);
 extern void receiver_change_sample_rate(RECEIVER *rx,int sample_rate);
+extern void receiver_change_adc(RECEIVER *rx,int adc);
 extern void receiver_frequency_changed(RECEIVER *rx);
 extern void receiver_mode_changed(RECEIVER *rx);
 extern void receiver_filter_changed(RECEIVER *rx);
@@ -131,7 +147,7 @@ extern void set_mode(RECEIVER* rx,int m);
 extern void set_filter(RECEIVER *rx,int low,int high);
 extern void set_agc(RECEIVER *rx, int agc);
 extern void set_offset(RECEIVER *rx, long long offset);
-extern void set_deviation(RECEIVER *rx, double deviation);
+extern void set_deviation(RECEIVER *rx);
 
 extern void add_iq_samples(RECEIVER *rx, double i_sample,double q_sample);
 
@@ -144,4 +160,6 @@ extern gboolean receiver_button_release_event(GtkWidget *widget, GdkEventButton
 extern gboolean receiver_motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data);
 extern gboolean receiver_scroll_event(GtkWidget *widget, GdkEventScroll *event, gpointer data);
 
+extern void set_displaying(RECEIVER *rx,int state);
+
 #endif
index 90b76dd27b84209ea4dbe4513d7d5c0008d3cb0f..adb52a4c7874feaac470bbb57e405f25aecad444 100644 (file)
--- a/rigctl.c
+++ b/rigctl.c
  */
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
+#include <errno.h>
+#include <fcntl.h> 
+#include <string.h>
+#include <termios.h>
 #include <unistd.h>
 //#include <semaphore.h>
 #include <stdio.h>
+#include <stdint.h>
 #include <stdlib.h>
+#include "receiver.h"
 #include "toolbar.h"
+#include "band_menu.h"
 #include "sliders.h"
 #include "rigctl.h"
 #include "radio.h"
-#include "receiver.h"
 #include "channel.h"
 #include "filter.h"
-#include <string.h>
 #include "mode.h"
 #include "filter.h"
 #include "band.h"
 #include "bandstack.h"
+#include "filter_menu.h"
 #include "vfo.h"
 #include "sliders.h"
-#include <pthread.h>
+#include "transmitter.h"
 #include "agc.h"
 #include <wdsp.h>
 #include "store.h"
+#include "ext.h"
+#include "rigctl_menu.h"
+#include <math.h>
 
 // IP stuff below
 #include <sys/socket.h>
@@ -52,6 +61,9 @@
 //#undef RIGCTL_DEBUG
 #define RIGCTL_DEBUG
 
+int rigctl_port_base=19090;
+int rigctl_enable=0;
+
 // the port client will be connecting to
 // 2-26-17 K5JAE - Changed the defines to const ints to allow use via pointers.
 static const int TelnetPortA = 19090;
@@ -61,8 +73,10 @@ static const int TelnetPortC = 19092;
 // max number of bytes we can get at once
 #define MAXDATASIZE 300
 
-int init_server ();
 void parse_cmd ();
+int cw_busy = 0; // Used to signal that the system is in a busy state for sending CW - assert busy back to the user
+int cw_reset = 0; // Signals reset the transceiver
+int connect_cnt = 0;
 
 int rigctlGetFilterLow();
 int rigctlGetFilterHigh();
@@ -70,27 +84,50 @@ int rigctlSetFilterLow(int val);
 int rigctlSetFilterHigh(int val);
 int new_level;
 int active_transmitter = 0;
+int rigctl_busy = 0;  // Used to tell rigctl_menu that launch has already occured
 
 int cat_control;
 
 extern int enable_tx_equalizer;
+//extern int serial_baud_rate;
+//extern int serial_parity;
 
-/*
-pthread_mutex_t mutex_a = PTHREAD_MUTEX_INITIALIZER;
-pthread_mutex_t mutex_b = PTHREAD_MUTEX_INITIALIZER;
-*/
 typedef struct {GMutex m; } GT_MUTEX;
 GT_MUTEX * mutex_a;
 GT_MUTEX * mutex_b;
+GT_MUTEX * mutex_c;
+GT_MUTEX * mutex_d;
+
+int mutex_b_exists = 0;
+
 
 FILE * out;
 int  output;
 FILTER * band_filter;
 
-//static pthread_t rigctl_a_thread_id, rigctl_b_thread_id, rigctl_c_thread_id;
-static GThread *rigctl_a_thread_id, *rigctl_b_thread_id, *rigctl_c_thread_id;
+#define MAX_CLIENTS 3
+static GThread *rigctl_server_thread_id = NULL;
+static int server_running;
+
+static GThread *serial_server_thread_id = NULL;
+
+static int server_socket=-1;
+static int server_address_length;
+static struct sockaddr_in server_address;
+
+typedef struct _client {
+  int socket;
+  int address_length;
+  struct sockaddr_in address;
+  GThread *thread_id;
+} CLIENT;
 
-int squelch=100; //local sim of squelch level
+int fd;  // Serial port file descriptor
+
+static CLIENT client[MAX_CLIENTS];
+
+int squelch=-160; //local sim of squelch level
+int fine = 0;     // FINE status for TS-2000 decides whether rit_increment is 1Hz/10Hz.
 
 
 int read_size;
@@ -115,10 +152,261 @@ int  mox_state = 0;
 int ctcss_tone;  // Numbers 01-38 are legal values - set by CN command, read by CT command
 int ctcss_mode;  // Numbers 0/1 - on off.
 
+static gpointer rigctl_client (gpointer data);
+
+void close_rigctl_ports() {
+  int i;
+  struct linger linger = { 0 };
+  linger.l_onoff = 1;
+  linger.l_linger = 0;
+
+  fprintf(stderr,"close_rigctl_ports: server_socket=%d\n",server_socket);
+  server_running=0;
+  for(i=0;i<MAX_CLIENTS;i++) {
+      if(client[i].socket!=-1) {
+        fprintf(stderr,"setting SO_LINGER to 0 for client_socket: %d\n",client[i].socket);
+        if(setsockopt(client[i].socket,SOL_SOCKET,SO_LINGER,(const char *)&linger,sizeof(linger))==-1) {
+          perror("setsockopt(...,SO_LINGER,...) failed for client");
+        }
+        fprintf(stderr,"closing client socket: %d\n",client[i].socket);
+        close(client[i].socket);
+        client[i].socket=-1;
+      }
+  }
+
+  if(server_socket>=0) {
+     fprintf(stderr,"setting SO_LINGER to 0 for server_socket: %d\n",server_socket);
+    if(setsockopt(server_socket,SOL_SOCKET,SO_LINGER,(const char *)&linger,sizeof(linger))==-1) {
+      perror("setsockopt(...,SO_LINGER,...) failed for server");
+    }
+    fprintf(stderr,"closing server_socket: %d\n",server_socket);
+    close(server_socket);
+    server_socket=-1;
+  }
+}
+//
+// Used to convert transmitter->ctcss_frequency into 1-39 value for TS2000.
+// This COULD be done with a simple table lookup - but I've already written the code
+// so at this point...
+//
+int convert_ctcss() {
+        int local_tone = 1; 
+        if(transmitter->ctcss_frequency == (double) 67.0) {
+           local_tone = 1; 
+        } else if (transmitter->ctcss_frequency == (double) 71.9) {
+           local_tone = 2; 
+        } else if (transmitter->ctcss_frequency == (double) 74.4) {
+           local_tone = 3; 
+        } else if (transmitter->ctcss_frequency == (double) 77.0) {
+           local_tone = 4; 
+        } else if (transmitter->ctcss_frequency == (double) 79.7) {
+           local_tone = 5; 
+        } else if (transmitter->ctcss_frequency == (double) 82.5) {
+           local_tone = 6; 
+        } else if (transmitter->ctcss_frequency == (double) 85.4) {
+           local_tone = 7; 
+        } else if (transmitter->ctcss_frequency == (double) 88.5) {
+           local_tone = 8; 
+        } else if (transmitter->ctcss_frequency == (double) 91.5) {
+           local_tone = 9; 
+        } else if (transmitter->ctcss_frequency == (double) 94.8) {
+           local_tone = 10; 
+        } else if (transmitter->ctcss_frequency == (double) 97.4) {
+           local_tone = 11; 
+        } else if (transmitter->ctcss_frequency == (double) 100.0) {
+           local_tone = 12; 
+        } else if (transmitter->ctcss_frequency == (double) 103.5) {
+           local_tone = 13; 
+        } else if (transmitter->ctcss_frequency == (double) 107.2) {
+           local_tone = 14; 
+        } else if (transmitter->ctcss_frequency == (double) 110.9) {
+           local_tone = 15; 
+        } else if (transmitter->ctcss_frequency == (double) 114.8) {
+           local_tone = 16; 
+        } else if (transmitter->ctcss_frequency == (double) 118.8) {
+           local_tone = 17; 
+        } else if (transmitter->ctcss_frequency == (double) 123.0) {
+           local_tone = 18; 
+        } else if (transmitter->ctcss_frequency == (double) 127.3) {
+           local_tone = 19; 
+        } else if (transmitter->ctcss_frequency == (double) 131.8) {
+           local_tone = 20; 
+        } else if (transmitter->ctcss_frequency == (double) 136.5) {
+           local_tone = 21; 
+        } else if (transmitter->ctcss_frequency == (double) 141.3) {
+           local_tone = 22; 
+        } else if (transmitter->ctcss_frequency == (double) 146.2) {
+           local_tone = 23; 
+        } else if (transmitter->ctcss_frequency == (double) 151.4) {
+           local_tone = 24; 
+        } else if (transmitter->ctcss_frequency == (double) 156.7) {
+           local_tone = 25; 
+        } else if (transmitter->ctcss_frequency == (double) 162.2) {
+           local_tone = 26; 
+        } else if (transmitter->ctcss_frequency == (double) 167.9) {
+           local_tone = 27; 
+        } else if (transmitter->ctcss_frequency == (double) 173.8) {
+           local_tone = 28; 
+        } else if (transmitter->ctcss_frequency == (double) 179.9) {
+           local_tone = 29; 
+        } else if (transmitter->ctcss_frequency == (double) 186.2) {
+           local_tone = 30; 
+        } else if (transmitter->ctcss_frequency == (double) 192.8) {
+           local_tone = 31; 
+        } else if (transmitter->ctcss_frequency == (double) 203.5) {
+           local_tone = 32; 
+        } else if (transmitter->ctcss_frequency == (double) 210.7) {
+           local_tone = 33; 
+        } else if (transmitter->ctcss_frequency == (double) 218.1) {
+           local_tone = 34; 
+        } else if (transmitter->ctcss_frequency == (double) 225.7) {
+           local_tone = 35; 
+        } else if (transmitter->ctcss_frequency == (double) 233.6) {
+           local_tone = 36; 
+        } else if (transmitter->ctcss_frequency == (double) 241.8) {
+           local_tone = 37; 
+        } else if (transmitter->ctcss_frequency == (double) 250.3) {
+           local_tone = 38; 
+        } else if (transmitter->ctcss_frequency == (double) 1750.0) {
+           local_tone = 39; 
+        }
+        return(local_tone);
+}
 int vfo_sm=0;   // VFO State Machine - this keeps track of
 
 // Now my stuff
 //
+void send_dash() {
+       //long delay = (1200000L * ((long)cw_keyer_weight/10L))/(long)cw_keyer_speed ;
+       int dot_delay = 1200/cw_keyer_speed;
+       int delay = (dot_delay * 3 * cw_keyer_weight)/50;
+       g_idle_add(ext_cw_key, (gpointer)(long)1);
+       usleep((long)delay*3000L);
+       g_idle_add(ext_cw_key, (gpointer)(long)0);
+       usleep((long)delay * 1000L);
+       //fprintf(stderr,"_%d",mox);
+       
+}
+void send_dot() {
+       int dot_delay = 1200/cw_keyer_speed;
+       g_idle_add(ext_cw_key, (gpointer)(long)1);
+       usleep((long)dot_delay * 1000L);
+       g_idle_add(ext_cw_key, (gpointer)(long)0);
+       usleep((long)dot_delay* 1000L);
+       //fprintf(stderr,".%d",mox);
+}
+void send_space() {
+       int dot_delay = 1200/cw_keyer_speed;
+       usleep((long)dot_delay* 7000L);
+       //fprintf(stderr," %d",mox);
+}
+
+void rigctl_send_cw_char(char cw_char) {
+    char pattern[9],*ptr;
+    strcpy(pattern,"");
+    ptr = &pattern[0];
+    switch (cw_char) {
+       case 'a':
+       case 'A': strcpy(pattern,".-"); break;
+       case 'b': 
+       case 'B': strcpy(pattern,"-..."); break;
+       case 'c': 
+       case 'C': strcpy(pattern,"-.-."); break;
+       case 'd': 
+       case 'D': strcpy(pattern,"-.."); break;
+       case 'e': 
+       case 'E': strcpy(pattern,"."); break;
+       case 'f': 
+       case 'F': strcpy(pattern,"..-."); break;
+       case 'g': 
+       case 'G': strcpy(pattern,"--."); break;
+       case 'h': 
+       case 'H': strcpy(pattern,"...."); break;
+       case 'i': 
+       case 'I': strcpy(pattern,".."); break;
+       case 'j': 
+       case 'J': strcpy(pattern,".---"); break;
+       case 'k': 
+       case 'K': strcpy(pattern,"-.-"); break;
+       case 'l': 
+       case 'L': strcpy(pattern,".-.."); break;
+       case 'm': 
+       case 'M': strcpy(pattern,"--"); break;
+       case 'n': 
+       case 'N': strcpy(pattern,"-."); break;
+       case 'o': 
+       case 'O': strcpy(pattern,"---"); break;
+       case 'p': 
+       case 'P': strcpy(pattern,".--."); break;
+       case 'q': 
+       case 'Q': strcpy(pattern,"-.--"); break;
+       case 'r': 
+       case 'R': strcpy(pattern,".-."); break;
+       case 's': 
+       case 'S': strcpy(pattern,"..."); break;
+       case 't': 
+       case 'T': strcpy(pattern,"-"); break;
+       case 'u': 
+       case 'U': strcpy(pattern,"..-"); break;
+       case 'v': 
+       case 'V': strcpy(pattern,"...-"); break;
+       case 'w': 
+       case 'W': strcpy(pattern,".--"); break;
+       case 'x': 
+       case 'X': strcpy(pattern,"-..-"); break;
+       case 'z': 
+       case 'Z': strcpy(pattern,"--.."); break;
+       case '0': strcpy(pattern,"-----"); break;
+       case '1': strcpy(pattern,".----"); break;
+       case '2': strcpy(pattern,"..---"); break;
+       case '3': strcpy(pattern,"...--"); break;
+       case '4': strcpy(pattern,"....-"); break;
+       case '5': strcpy(pattern,".....");break;
+       case '6': strcpy(pattern,"-....");break;
+       case '7': strcpy(pattern,"--...");break;
+       case '8': strcpy(pattern,"---..");break;
+       case '9': strcpy(pattern,"----.");break;
+       case '.': strcpy(pattern,".-.-.-");break;
+       case '/': strcpy(pattern,"-..-.");break;
+       case ',': strcpy(pattern,"--..--");break;
+       case '!': strcpy(pattern,"-.-.--");break;
+       case ')': strcpy(pattern,"-.--.-");break;
+       case '(': strcpy(pattern,"-.--.-");break;
+       case '&': strcpy(pattern,".-...");break;
+       case ':': strcpy(pattern,"---..");break;
+       case '+': strcpy(pattern,".-.-.");break;
+       case '-': strcpy(pattern,"-....-");break;
+       case '_': strcpy(pattern,".--.-.");break;
+       case '@': strcpy(pattern,"..--.-");break;
+       case ' ': strcpy(pattern," ");break;
+       default:  strcpy(pattern," ");
+    }
+    //fprintf(stderr,"Sending %c:",cw_char);
+    g_idle_add(ext_cw_key, (gpointer)(long)0);
+     
+    while(*ptr != '\0') {
+       if(*ptr == '-') {
+          send_dash();
+       }
+       if(*ptr == '.') {
+          send_dot();
+       }
+       if(*ptr == ' ') {
+          send_space();
+       }
+       ptr++;
+    }
+    // Need a delay HERE between characters
+    long delay = (1200000L * ((long)cw_keyer_weight/10L))/(long)cw_keyer_speed ;
+    usleep(delay*3L);
+    //fprintf(stderr,"\n");
+}
+void gui_vfo_move_to(gpointer data) {
+   long long freq = *(long long *) data;
+   fprintf(stderr,"GUI: %11lld\n",freq);
+   return;
+   //vfo_move_to(freq);
+}
 
 // This looks up the frequency of the Active receiver with 
 // protection for 1 versus 2 receivers
@@ -136,32 +424,107 @@ void send_resp (int client_sock,char * msg) {
     #ifdef  RIGCTL_DEBUG
         fprintf(stderr,"RIGCTL: RESP=%s\n",msg);
     #endif
-    write(client_sock, msg, strlen(msg));
+    if(client_sock == -1) { // Serial port 
+       int bytes=write(fd,msg,strlen(msg));   
+    } else {  // TCP/IP port
+       int bytes=write(client_sock, msg, strlen(msg));
+    }
 }
 
 //
 // 2-25-17 - K5JAE - removed duplicate rigctl
 //
 
-//static void * rigctl_a (void * arg) {
-static gpointer rigctl (gpointer data) {
+static gpointer rigctl_server(gpointer data) {
+  int port=(uintptr_t)data;
+  int rc;
+  int on=1;
+  int i;
+
+  fprintf(stderr,"rigctl_server: starting server on port %d\n",port);
+
+  server_socket=socket(AF_INET,SOCK_STREAM,0);
+  if(server_socket<0) {
+    perror("rigctl_server: listen socket failed");
+    return NULL;
+  }
+
+  setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+  setsockopt(server_socket, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
+
+  // bind to listening port
+  memset(&server_address,0,sizeof(server_address));
+  server_address.sin_family=AF_INET;
+  server_address.sin_addr.s_addr=INADDR_ANY;
+  server_address.sin_port=htons(port);
+  if(bind(server_socket,(struct sockaddr*)&server_address,sizeof(server_address))<0) {
+    perror("rigctl_server: listen socket bind failed");
+    close(server_socket);
+    return NULL;
+  }
+
+  for(i=0;i<MAX_CLIENTS;i++) {
+    client[i].socket=-1;
+  }
+  server_running=1;
+  while(server_running) {
+    // listen with a max queue of 3
+    if(listen(server_socket,3)<0) {
+      perror("rigctl_server: listen failed");
+      close(server_socket);
+      return NULL;
+    }
+
+    // find a spare thread
+    for(i=0;i<MAX_CLIENTS;i++) {
+      if(client[i].socket==-1) {
+
+        int client_socket;
+        struct sockaddr_in client_address;
+        int client_address_length;
+        fprintf(stderr,"Using client: %d\n",i);
+
+        client[i].socket=accept(server_socket,(struct sockaddr*)&client[i].address,&client[i].address_length);
+        if(client[i].socket<0) {
+          perror("rigctl_server: client accept failed");
+          continue;
+        }
+
+        client[i].thread_id = g_thread_new("rigctl client", rigctl_client, (gpointer)&client[i]);
+        if(client[i].thread_id==NULL) {
+          fprintf(stderr,"g_thread_new failed (n rigctl_client\n");
+          fprintf(stderr,"setting SO_LINGER to 0 for client_socket: %d\n",client[i].socket);
+          struct linger linger = { 0 };
+          linger.l_onoff = 1;
+          linger.l_linger = 0;
+          if(setsockopt(client[i].socket,SOL_SOCKET,SO_LINGER,(const char *)&linger,sizeof(linger))==-1) {
+            perror("setsockopt(...,SO_LINGER,...) failed for client");
+          }
+          close(client[i].socket);
+        }
+      }
+    }
+  }
+
+  close(server_socket);
+  return NULL;
+}
+
+static gpointer rigctl_client (gpointer data) {
    int len;
    int c;
-   int socket_desc; 
-   struct sockaddr_in client;
-   struct sockaddr_in server;
+   
+   CLIENT *client=(CLIENT *)data;
 
-   // user data void* is really an int* of the port
-   int port = *((int*) data);
-   int client_sock = init_server(&socket_desc, &client, &server, port);
+   fprintf(stderr,"rigctl_client: starting rigctl_client: socket=%d\n",client->socket);
 
    g_mutex_lock(&mutex_a->m);
    cat_control++;
 //#ifdef RIGCTL_DEBUG
-fprintf(stderr,"RIGCTL: CTLA INC cat_contro=%d\n",cat_control);
+   fprintf(stderr,"RIGCTL: CTLA INC cat_contro=%d\n",cat_control);
 //#endif
    g_mutex_unlock(&mutex_a->m);
-   g_idle_add(vfo_update,NULL);
+   g_idle_add(ext_vfo_update,NULL);
 
    int save_flag = 0; // Used to concatenate two cmd lines together
    int semi_number = 0;
@@ -171,10 +534,9 @@ fprintf(stderr,"RIGCTL: CTLA INC cat_contro=%d\n",cat_control);
    int numbytes;
    char  cmd_input[MAXDATASIZE] ;
    char cmd_save[80];
+   char cw_check_buf[4];
 
-  for(;;) {
-    fprintf(stderr,"RIGCTL - New run on server port: %d\n", port);
-    while((numbytes=recv(client_sock , cmd_input , MAXDATASIZE-2 , 0)) > 0 ) {
+    while(server_running && (numbytes=recv(client->socket , cmd_input , MAXDATASIZE-2 , 0)) > 0 ) {
          for(i=0;i<numbytes;i++)  { work_buf[i] = cmd_input[i]; }
          work_buf[i+1] = '\0';
          #ifdef RIGCTL_DEBUG
@@ -203,17 +565,48 @@ fprintf(stderr,"RIGCTL: CTLA INC cat_contro=%d\n",cat_control);
            strcpy(cmd_input,cmd_save);      // Cat them together and replace cmd_input
            numbytes = strlen(cmd_input);
         } 
+
         if(save_flag != 1) {
            work_ptr = strtok(cmd_input,";");
            while(work_ptr != NULL) {
-               /*
-               pthread_mutex_lock (& mutex_b);
-               */
+               if(cw_busy == 1) {
+                  if(strlen(work_ptr)>2) {
+                     cw_check_buf[0] = work_ptr[0];
+                     cw_check_buf[1] = work_ptr[1];
+                     cw_check_buf[2] = '\0';
+                     if(strcmp("ZZ",cw_check_buf)==0) {
+                          if(strlen(work_ptr)>4) {
+                             cw_check_buf[0] = work_ptr[2];
+                             cw_check_buf[1] = work_ptr[3];
+                             cw_check_buf[2] = '\0';
+                          } else {
+                             send_resp(client->socket,"?;");
+                          }
+                     } 
+                   } else {
+                       // Illegal Command
+                       send_resp(client->socket,"?;");
+                   } 
+                   // Got here because we have a legal command in cw_check_buf
+                   // Look for RESET and BUSY which re respond to else - send ?;
+                   if(strcmp("BY",cw_check_buf)==0) {
+                      send_resp(client->socket,"BY11;"); // Indicate that we are BUSY
+                   } else if (strcmp("SR",cw_check_buf) == 0) {
+                      // Reset the transceiver
+                      g_mutex_lock(&mutex_c->m);
+                      cw_reset = 1;
+                      g_mutex_unlock(&mutex_c->m);
+                      // Wait till BUSY clears
+                      while(cw_busy);
+                      g_mutex_lock(&mutex_c->m);
+                      cw_reset = 0;
+                      g_mutex_unlock(&mutex_c->m);
+                   }
+
+               }
+               // Lock so only one user goes into this at a time
                g_mutex_lock(&mutex_b->m);
-               parse_cmd(work_ptr,strlen(work_ptr),client_sock);
-               /*
-               pthread_mutex_unlock (& mutex_b);
-               */
+               parse_cmd(work_ptr,strlen(work_ptr),client->socket);
                g_mutex_unlock(&mutex_b->m);
                work_ptr = strtok(NULL,";");
            }
@@ -224,35 +617,27 @@ fprintf(stderr,"RIGCTL: CTLA INC cat_contro=%d\n",cat_control);
         }
        // Got here because socket closed 
     }
-    if(numbytes == 0) {
-         fprintf(stderr,"RIGCTL: Client disconnected\n");
-         close(client_sock);
-
-         // Decrement CAT_CONTROL
-         g_mutex_lock(&mutex_a->m);
-         cat_control--;
-#ifdef RIGCTL_DEBUG
-fprintf(stderr,"RIGCTL: CTLA DEC - cat_control=%d\n",cat_control);
-#endif
-         g_mutex_unlock(&mutex_a->m);
-         g_idle_add(vfo_update,NULL);
-
-         //sleep(1);
-         c = sizeof(struct sockaddr_in);
-         client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);
-
-         // Increment CAT_CONTROL
-         g_mutex_lock(&mutex_a->m);
-         cat_control++;
+fprintf(stderr,"RIGCTL: Leaving rigctl_client thread");
+  if(client->socket!=-1) {
+    fprintf(stderr,"setting SO_LINGER to 0 for client_socket: %d\n",client->socket);
+    struct linger linger = { 0 };
+    linger.l_onoff = 1;
+    linger.l_linger = 0;
+    if(setsockopt(client->socket,SOL_SOCKET,SO_LINGER,(const char *)&linger,sizeof(linger))==-1) {
+      perror("setsockopt(...,SO_LINGER,...) failed for client");
+    }
+    close(client->socket);
+    client->socket=-1;
+    // Decrement CAT_CONTROL
+    g_mutex_lock(&mutex_a->m);
+    cat_control--;
 #ifdef RIGCTL_DEBUG
-fprintf(stderr,"RIGCTL: CTLA INC - cat_control=%d\n",cat_control);
+    fprintf(stderr,"RIGCTL: CTLA DEC - cat_control=%d\n",cat_control);
 #endif
-         g_mutex_unlock(&mutex_a->m);
-         g_idle_add(vfo_update,NULL);
-
-         //sleep(1);
-    }
- }
+    g_mutex_unlock(&mutex_a->m);
+    g_idle_add(ext_vfo_update,NULL);
+  }
+  return NULL; 
 }
 
 // 
@@ -279,81 +664,287 @@ int rit_on () {
       }
   }
 }
+//
+// TS-2000 parser
+//   -- Now extended with zzid_flag to indicate PSDR extended command set
+// 
 void parse_cmd ( char * cmd_input,int len,int client_sock) {
         int work_int;     
         int new_low, new_high;
+        int zzid_flag;
         double meter;
-        char msg[80];
-        char buf[80];
+        double forward;
+        double reverse;
+        double vswr;
+        char msg[200];
+        char buf[200];
         BANDSTACK_ENTRY *entry;
         // Parse the cmd_input
         //int space = command.indexOf(' ');
         //char cmd_char = com_head->cmd_string[0]; // Assume the command is first thing!
         char cmd_str[3];
+
         cmd_str[0] = cmd_input[0];
         cmd_str[1] = cmd_input[1];
         cmd_str[2] = '\0';
-        if(strcmp(cmd_str,"AC")==0)       { // Sets or reads the internal antenna tuner status
-                                                   // P1 0:RX-AT Thru, 1: RX-AT IN
-                                                   // P2 0: TX-AT Thru 1: TX-AT In
-                                                   // 
-                                             if(len <= 2) {
-                                               send_resp(client_sock,"AC000;");
-                                             }
+
+        // Added support for PSDR extended command set - they all start
+        // with ZZ so:
+        //
+        // Check to see if first part of string is ZZ - if so
+        //    strip the ZZ out and set the zzid_flag = 1;
+       #ifdef  RIGCTL_DEBUG
+        fprintf(stderr,"RIGCTL: CMD=%s\n",cmd_input);
+       #endif
+        zzid_flag = 0;  // Set to indicate we haven't seen ZZ
+        char * zzid_ptr;
+        char temp[80];
+        int cnt;
+        if(strcmp(cmd_str,"ZZ")==0) {
+           
+           #ifdef  RIGCTL_DEBUG
+           fprintf(stderr,"RIGCTL: Init=%s\n",cmd_str);
+           #endif
+
+           // Adjust the Parse input like there hadn't been a ZZ in front - but 
+           // set the ZZ flag to indicate we saw it.
+           zzid_ptr = &temp[0];
+
+           // It is 4AM and this was the only safe way for me to get a strcpy to work
+           // so - there ya go...
+           for(cnt=2; cnt<=len;cnt++) { 
+               //fprintf(stderr,"[%d]=%c:",cnt,cmd_input[cnt]);
+               *zzid_ptr++= cmd_input[cnt]; 
+           }
+           temp[len+1] = '\0';
+
+           strcpy(cmd_input,temp);
+           #ifdef  RIGCTL_DEBUG
+           fprintf(stderr,"RIGCTL: Cmd_input=%s\n",cmd_input);
+           #endif
+           // 
+           cmd_str[0] = cmd_input[0];
+           cmd_str[1] = cmd_input[1];
+           cmd_str[2] = '\0';
+           zzid_flag = 1;
+           len = strlen (temp);
+        }
+        
+        if(strcmp(cmd_str,"AC")==0)       {  
+                                            // TS-2000 - AC - STEP Command 
+                                            // PiHPSDR - ZZAC - Step Command 
+                                             if(zzid_flag ==1) { // Set or Read the Step Size (replaces ZZST)
+                                                   if(len <= 2) {
+                                                       switch(step) {
+                                                          case  1: work_int = 0; break;  
+                                                          case  10: work_int = 1; break;  
+                                                          case  25: work_int = 2; break;  
+                                                          case  50: work_int = 3; break;  
+                                                          case  100: work_int = 4; break;  
+                                                          case  250: work_int = 5; break;  
+                                                          case  500: work_int = 6; break;  
+                                                          case  1000: work_int = 7; break;  
+                                                          case  2500: work_int = 8; break;  
+                                                          case  5000: work_int = 9; break;  
+                                                          case  6250: work_int = 10; break;  
+                                                          case  9000: work_int = 11; break;  
+                                                          case  10000: work_int = 12; break;  
+                                                          case  12500: work_int = 13; break;  
+                                                          case  15000: work_int = 14; break;  
+                                                          case  20000: work_int = 15; break;  
+                                                          case  25000: work_int = 16; break;  
+                                                          case  30000: work_int = 17; break;  
+                                                          case  50000: work_int = 18; break;  
+                                                          case  100000: work_int = 19; break;  
+                                                          default: 
+                                                              work_int = 0;
+                                                              fprintf(stderr,"RIGCTL: ERROR  step out of range\n");
+                                                              send_resp(client_sock,"?;");
+                                                              break;
+                                                          }
+                                                          #ifdef  RIGCTL_DEBUG
+                                                          fprintf(stderr,"RESP: ZZAC%02d;",work_int);
+                                                          #endif
+                                                          sprintf(msg,"ZZAC%02d;",work_int);
+                                                          send_resp(client_sock,msg);
+                                              
+                                                    } else { // Legal vals between 00 and 22.
+                                                       switch(atoi(&cmd_input[2])) {
+                                                          case  0: step = 1; break;  
+                                                          case  1: step = 10; break;  
+                                                          case  2: step = 25; break;  
+                                                          case  3: step = 50; break;  
+                                                          case  4: step = 100; break;  
+                                                          case  5: step = 250; break;  
+                                                          case  6: step = 500; break;  
+                                                          case  7: step = 1000; break;  
+                                                          case  8: step = 2500; break;  
+                                                          case  9: step = 5000; break;  
+                                                          case  10: step = 6250; break;  
+                                                          case  11: step = 9000; break;  
+                                                          case  12: step = 10000; break;  
+                                                          case  13: step = 12500; break;  
+                                                          case  14: step = 15000; break;  
+                                                          case  15: step = 20000; break;  
+                                                          case  16: step = 25000; break;  
+                                                          case  17: step = 30000; break;  
+                                                          case  18: step = 50000; break;  
+                                                          case  19: step = 100000; break;  
+                                                          default: 
+                                                              fprintf(stderr,"RIGCTL: ERROR - ZZAC out of range\n");
+                                                              send_resp(client_sock,"?;");
+                                                          }
+                                                       }
+                                                 } else { // Sets or reads the internal antenna tuner status
+                                                      // P1 0:RX-AT Thru, 1: RX-AT IN
+                                                      // P2 0: TX-AT Thru 1: TX-AT In
+                                                      // 
+                                                        if(len <= 2) {
+                                                          send_resp(client_sock,"AC000;");
+                                                        }
+                                              }
                                           }
-        else if(strcmp(cmd_str,"AG")==0) {  // Set Audio Gain - 
+        else if((strcmp(cmd_str,"AD")==0) && (zzid_flag==1)) { 
+                                            // PiHPSDR - ZZAD - Move VFO A Down by step
+                                              vfo_step(-1);
+                                              g_idle_add(ext_vfo_update,NULL);
+                                         }
+        else if(strcmp(cmd_str,"AG")==0) {  
+                                            if(zzid_flag == 1) { 
+                                            // PiHPSDR - ZZAG - Set/read Audio Gain
+                                            // Values are 000-100 
+                                                if(len<=2) { // Send ZZAGxxx; - active_receiver->volume 0.00-1.00
+                                                     sprintf(msg,"ZZAG%03d;",(int) (roundf(active_receiver->volume *100.0)));
+                                                     send_resp(client_sock,msg);
+                                                } else { // Set Audio Gain
+                                                    work_int = atoi(&cmd_input[2]);
+                                                    active_receiver->volume = ((double) work_int)/100.0;
+                                                    g_idle_add(ext_update_af_gain,NULL);               
+                                                }
+                                             } else { 
+                                            // TS-2000 - AG - Set Audio Gain 
                                             // AG123; Value of 0-
                                             // AG1 = Sub receiver - what is the value set
                                             // Response - AG<0/1>123; Where 123 is 0-260
-                                            int lcl_receiver;
-                                            if(receivers == 1) {
-                                                lcl_receiver = 0;
-                                            } else {
-                                                lcl_receiver = active_receiver->id;
-                                            }
-                                            if(len>4) { // Set Audio Gain
-                                               active_receiver->volume = (double) atoi(&cmd_input[3])/260; 
-                                               g_idle_add(update_af_gain,NULL);               
-                                            } else { // Read Audio Gain
-                                              sprintf(msg,"AG%1d%03d;",lcl_receiver,(int) (2.6 * active_receiver->volume));
-                                              send_resp(client_sock,msg);
-                                            }
+                                                int lcl_receiver;
+                                                if(receivers == 1) {
+                                                    lcl_receiver = 0;
+                                                } else {
+                                                    lcl_receiver = active_receiver->id;
+                                                }
+                                                if(len>4) { // Set Audio Gain
+                                                   if((atoi(&cmd_input[3]) >=0) && (atoi(&cmd_input[3])<=260)) {
+                                                      active_receiver->volume = ((double) atoi(&cmd_input[3]))/260; 
+                                                      g_idle_add(ext_update_af_gain,NULL);               
+                                                   } else {
+                                                     send_resp(client_sock,"?;");
+                                                   }
+                                                } else { // Read Audio Gain
+                                                  sprintf(msg,"AG%1d%03d;",lcl_receiver,(int) (260 * active_receiver->volume));
+                                                  send_resp(client_sock,msg);
+                                                }
+                                             }
                                           }
-        else if(strcmp(cmd_str,"AI")==0)  {  // Allow rebroadcast of set frequency after set - not supported
+        else if((strcmp(cmd_str,"AI")==0) && (zzid_flag == 0))  {  
+                                            // TS-2000 - AI- Allow rebroadcast of set frequency after set - not supported
                                              if(len <=2) {
                                                 //send_resp(client_sock,"AI0;");
                                                 send_resp(client_sock,"?;");
                                              } 
                                           }
-        else if(strcmp(cmd_str,"AL")==0)  {  // Set/Reads the auto Notch level 
+        else if((strcmp(cmd_str,"AL")==0) && (zzid_flag == 0))  {  
+                                            // TS-2000 - AL - Set/Reads the auto Notch level - not supported
                                              if(len <=2) {
                                                 //send_resp(client_sock,"AL000;");
                                                 send_resp(client_sock,"?;");
                                              } 
                                           }
-        else if(strcmp(cmd_str,"AM")==0)  {  // Sets or reads the Auto Mode
+        else if((strcmp(cmd_str,"AM")==0) && (zzid_flag == 0))  {  
+                                            // TS-2000 - AM - Sets or reads the Auto Mode - not supported
                                              if(len <=2) {
                                                 //send_resp(client_sock,"AM0;");
                                                 send_resp(client_sock,"?;");
                                              } 
                                           }
-        else if(strcmp(cmd_str,"AN")==0)  {  // Selects the antenna connector (ANT1/2)
+        else if((strcmp(cmd_str,"AN")==0) && (zzid_flag == 0)) {  
+                                            // TS-2000 - AN - Selects the antenna connector (ANT1/2) - not supported
                                              if(len <=2) {
                                                 //send_resp(client_sock,"AN0;");
                                                 send_resp(client_sock,"?;");
                                              } 
                                           }
-        else if(strcmp(cmd_str,"AR")==0)  {  // Sets or reads the ASC function on/off
-                                             if(len <=2) {
-                                                //send_resp(client_sock,"AR0;");
-                                                send_resp(client_sock,"?;");
-                                             } 
+        else if((strcmp(cmd_str,"AP")==0) && (zzid_flag == 1)) { 
+                                            // PiHPSDR - ZZAP - Set/Read Power Amp Settings.
+                                            //                  format - P1P1P1 P2P2.P2 
+                                            //                  P1 - Band P2 - 3.1 float WITH decimal point required!
+                                               #ifdef  RIGCTL_DEBUG
+                                               fprintf(stderr,"RIGCTL: ZZAP len=%d\n",len);
+                                               #endif
+                                               if(len<=5) { // Read Command
+                                                 work_int = lookup_band(atoi(&cmd_input[2]));
+                                                 #ifdef  RIGCTL_DEBUG
+                                                 fprintf(stderr,"RIGCTL ZZAP work_int=%d\n",work_int);
+                                                 #endif
+                                                 BAND *band = band_get_band(work_int);
+                                                 sprintf(msg,"ZZAP%03d%3.1f;",atoi(&cmd_input[2]),band->pa_calibration);
+                                                 send_resp(client_sock,msg);
+                                              } else {
+                                                 /* isolate the command band from the value */ 
+                                                 char lcl_char = cmd_input[5];;
+                                                 cmd_input[5]='\0'; // Make a temp string
+                                                 work_int = atoi(&cmd_input[2]);
+                                                 cmd_input[5] = lcl_char; // Restore the orig string..
+                                                 double lcl_float = atof(&cmd_input[5]);
+                                                 #ifdef  RIGCTL_DEBUG
+                                                 fprintf(stderr,"RIGCTL ZZAP - band=%d setting=%3.1f\n",work_int, lcl_float); 
+                                                 #endif 
+                                                 work_int = lookup_band(work_int);
+
+                                                 // Sequence below lifted from pa_menu
+                                                 BAND *band = band_get_band(work_int);
+                                                 band->pa_calibration = lcl_float;
+                                                 work_int = VFO_A;
+                                                 if(split) work_int = VFO_B;
+                                                 int b = vfo[work_int].band;
+                                                 BAND *current = band_get_band(b);
+                                                 if(band == current) {
+                                                     g_idle_add( ext_calc_drive_level,(gpointer) NULL);
+                                                     //g_idle_add( ext_calc_tune_drive_level,(gpointer) NULL);
+                                                 } 
+                                              } 
+                                          }
+        else if(strcmp(cmd_str,"AR")==0)  { 
+                                            if(zzid_flag ==1) { 
+                                            // PiHPSDR - ZZAR - Set or reads the RX1 AGC Threshold Control
+                                                 if(len <=2) { // Read Response
+                                                    // X is +/- sign
+                                                    if(active_receiver->agc_gain >=0) {
+                                                       sprintf(msg,"ZZAR+%03d;",(int)active_receiver->agc_gain);
+                                                    } else {
+                                                       sprintf(msg,"ZZAR-%03d;",abs((int)active_receiver->agc_gain));
+                                                    }
+                                                    send_resp(client_sock,msg);
+                                                 } else {
+                                                    double new_gain = (double) atoi(&cmd_input[2]);
+                                                    double *p_gain=malloc(sizeof(double));
+                                                    *p_gain=new_gain;
+                                                    g_idle_add(ext_update_agc_gain,(gpointer)p_gain);
+                                                 } 
+                                            } else {     
+                                            // TS-2000 - AR - Sets or reads the ASC function on/off - not supported
+                                                 if(len <=2) {
+                                                    //send_resp(client_sock,"AR0;");
+                                                    send_resp(client_sock,"?;");
+                                                 } 
+                                            }
                                           }
-        else if(strcmp(cmd_str,"AS")==0)  {  // Sets/reads automode function parameters
-                                             // AS<P1><2xP2><11P3><P4>;
-                                             // AS<P1><2xP2><11P3><P4>;
+        else if((strcmp(cmd_str,"AS")==0) && (zzid_flag == 0))  {  
+                                            // TS-2000 - AS - Sets/reads automode function parameters
+                                            // AS<P1><2xP2><11P3><P4>;
+                                            // AS<P1><2xP2><11P3><P4>;
                                              if(len < 6) {  
-                                             /*   sprintf(msg,"AS%1d%02d%011lld%01d;",
+                                            /*   sprintf(msg,"AS%1d%02d%011lld%01d;",
                                                              0, // P1
                                                              0, // Automode 
                                                              getFrequency(),
@@ -363,95 +954,553 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                                
                                              } 
                                           }
-        else if(strcmp(cmd_str,"BC")==0)  {  // Beat Cancellor OFF
+        else if((strcmp(cmd_str,"AU")==0) && (zzid_flag==1)) { 
+                                            // PiHPSDR - ZZAU - Move VFO A Up by step
+                                              vfo_step(1);
+                                              g_idle_add(ext_vfo_update,NULL);
+                                         }
+        else if((strcmp(cmd_str,"BC")==0) && (zzid_flag == 0))  {  
+                                            // TS-2000 - BC - Beat Cancellor OFF - not supported
                                              if(len <=2) {
                                                 //send_resp(client_sock,"BC0;");
                                                 send_resp(client_sock,"?;");
                                              } 
                                           }
-        else if(strcmp(cmd_str,"BD")==0)  {  // Moves down the frequency band
-                                             // No response 
+        else if(strcmp(cmd_str,"BD")==0)  {  
+                                            // PiHPSDR - ZZBD - Moves down the frequency band selector
+                                            // TS-2000 - BD - Moves down the frequency band selector
+                                            // No response 
+                                             // This reacts to both BD and ZZBD - only works for active receiver
+                                             int cur_band = vfo[active_receiver->id].band;
+                                             #ifdef  RIGCTL_DEBUG
+                                             fprintf(stderr,"RIGCTL: BD - current band=%d\n",cur_band);
+                                             #endif
+                                             if(cur_band == 0) {
+                                                #ifdef LIMESDR
+                                                    cur_band = band472;
+                                                #else
+                                                    cur_band = band6;
+                                                #endif
+                                             } else {
+                                                --cur_band;
+                                             } 
+                                             #ifdef  RIGCTL_DEBUG
+                                             fprintf(stderr,"RIGCTL: BD - new band=%d\n",cur_band);
+                                             #endif 
+                                             g_idle_add(ext_vfo_band_changed,(gpointer)(long)cur_band);
                                           }
-        else if(strcmp(cmd_str,"BP")==0)  {  // Reads the manual beat canceller frequency setting
+        else if((strcmp(cmd_str,"BP")==0) && (zzid_flag == 0))  {  
+                                            // TS-2000 - BP - Reads the manual beat canceller freq - not supported 
                                              if(len <=2) {
                                                 //send_resp(client_sock,"BP000;");
                                                 send_resp(client_sock,"?;");
                                              } 
                                           }
-        else if(strcmp(cmd_str,"BS")==0)  {  // Sets or reads Beat Canceller status
-                                             if(len <=2) {
-                                                //send_resp(client_sock,"BS0;");
-                                                send_resp(client_sock,"?;");
-                                             } 
+        else if(strcmp(cmd_str,"BS")==0)  {  
+                                            if(zzid_flag == 1) {
+                                            // PiHPSDR - ZZBS - Read the RX1 Band switch
+                                                 int cur_band = vfo[active_receiver->id].band;
+                                                 #ifdef  RIGCTL_DEBUG
+                                                 fprintf(stderr,"RIGCTL: BS - band=%d\n",cur_band);
+                                                 #endif 
+                         
+                                                 switch(cur_band) {
+                                                    case 0:  work_int = 160;  break;
+                                                    case 1:  work_int = 80;  break;
+                                                    case 2:  work_int = 60;  break;
+                                                    case 3:  work_int = 40;  break;
+                                                    case 4:  work_int = 30;  break;
+                                                    case 5:  work_int = 20;  break;
+                                                    case 6:  work_int = 17;  break;
+                                                    case 7:  work_int = 15;  break;
+                                                    case 8:  work_int = 12;  break;
+                                                    case 9:  work_int = 10;  break;
+                                                    case 10:  work_int = 6;  break;
+                                                    case 11: work_int = 888; break;
+                                                    case 12: work_int = 999; break;
+                                                    case 13: work_int = 136; break;
+                                                    case 14: work_int = 472; break;
+                                                    }
+                                                 sprintf(msg,"ZZBS%03d;",work_int);
+                                                 send_resp(client_sock,msg);
+
+                                             } else {
+                                                 // Sets or reads Beat Canceller status
+                                                if(len <=2) {
+                                                   //send_resp(client_sock,"BS0;");
+                                                   send_resp(client_sock,"?;");
+                                                } 
+                                             }
                                           }
-        else if(strcmp(cmd_str,"BU")==0)  {  // Moves Up the frequency band
+        else if(strcmp(cmd_str,"BU")==0)  {  
+                                            // PiHPSDR - ZZBU - Moves Up the frequency band
+                                            // TS-2000 - BU - Moves Up the frequency band
                                              // No response 
+                                             int cur_band = vfo[active_receiver->id].band;
+                                             #ifdef  RIGCTL_DEBUG
+                                             fprintf(stderr,"RIGCTL: BU - Max Band = %d current band=%d\n",BANDS,cur_band);
+                                             #endif
+                                             if(cur_band >= 10) {
+                                                    cur_band = band160;
+                                             } else {
+                                                ++cur_band;
+                                             } 
+                                             #ifdef  RIGCTL_DEBUG
+                                             fprintf(stderr,"RIGCTL: BU - new band=%d\n",cur_band);
+                                             #endif
+                                             g_idle_add(ext_vfo_band_changed,(gpointer)(long)cur_band);
                                           }
-        else if(strcmp(cmd_str,"BY")==0)  {  // Read the busy signal status
+        else if((strcmp(cmd_str,"BY")==0) && (zzid_flag == 0))  {
+                                            // TS-2000 - BY - Read the busy signal status
                                              if(len <=2) {
                                                 //send_resp(client_sock,"BY00;");
                                                 send_resp(client_sock,"?;");
                                              } 
                                           }
-        else if(strcmp(cmd_str,"CA")==0)  {  // Sets/reads cw auto tune function status
+        else if((strcmp(cmd_str,"CA")==0) && (zzid_flag == 0))  {
+                                            // TS-2000 - CA - Sets/reads cw auto tune f(x) status - not supported
                                              if(len <=2) {
                                                 //send_resp(client_sock,"CA0;");
                                                 send_resp(client_sock,"?;");
                                              } 
                                           }
-        else if(strcmp(cmd_str,"CG")==0)  {  // Sets/reads the carrier gain status
-                                             // 0-100 legal values
-                                             if(len <=2) {
+        else if((strcmp(cmd_str,"CB")==0) && (zzid_flag==1)) {
+                                            // PIHPSDR - ZZCB - Sets/reads CW Break In checkbox status
+                                            // P1 = 0 for disabled, 1 for enabled
+                                            if(len <= 2) {
+                                                 sprintf(msg,"ZZCB%01d;",cw_breakin);
+                                                 send_resp(client_sock,msg);
+                                            } else {
+                                                cw_breakin = atoi(&cmd_input[2]);
+                                            }
+                                          }
+        else if((strcmp(cmd_str,"CG")==0) && (zzid_flag == 0))  { 
+                                            // TS-2000 - CD - Sets/Reads the carrier gain status - not supported
+                                            // 0-100 legal values
+                                            if(len <=2) {
                                                 //send_resp(client_sock,"CG000;");
                                                 send_resp(client_sock,"?;");
-                                             } 
+                                            } 
+                                          }
+        else if((strcmp(cmd_str,"CH")==0) && (zzid_flag == 0)) { 
+                                            // TS-2000 - CH - Sets the current frequency to call Channel -no response 
                                           }
-        else if(strcmp(cmd_str,"CH")==0)  {  // Sets the current frequency to call Channel
-                                             // No response
+        else if((strcmp(cmd_str,"CI")==0) && (zzid_flag == 0)) { 
+                                            // TS-2000 - CI - In VFO md or Mem recall md, sets freq 2 call channel - no response
                                           }
-        else if(strcmp(cmd_str,"CI")==0)  {  // While in VFO mode or memory recall mode, sets freq to the call channel
-                                             // No response
+        else if((strcmp(cmd_str,"CL")==0) && (zzid_flag == 1)) {  
+                                            // PiHPSDR - ZZCL - CW Pitch set
+                                            // 0200 - 1200
+                                             if(len <=2) {
+                                                 sprintf(msg,"ZZCL%04d;",cw_keyer_sidetone_frequency);
+                                                 send_resp(client_sock,msg);
+                                             } else {
+                                                int local_freq = atoi(&cmd_input[2]);
+                                                if((local_freq >= 200) && (local_freq <=1200)) {
+                                                   cw_keyer_sidetone_frequency = atoi(&cmd_input[2]);
+                                                   g_idle_add(ext_vfo_update,NULL);
+                                                } else {
+                                                   fprintf(stderr,"RIGCTL: ZZCL illegal freq=%d\n",local_freq);
+                                                }
+                                             }
                                           }
-        else if(strcmp(cmd_str,"CM")==0)  {  // Sets or reads the packet cluster tune f(x) on/off
-                                             // 0-100 legal values
+        else if((strcmp(cmd_str,"CM")==0) && (zzid_flag == 0)) {  
+                                            // TS-2000 - CM - Sets or reads the packet cluster tune f(x) on/off -not supported
+                                            // 0-100 legal values
                                              if(len <=2) {
                                                 //send_resp(client_sock,"CM0;");
                                                 send_resp(client_sock,"?;");
                                              } 
                                           }
-        else if(strcmp(cmd_str,"CN")==0)  {  // Sets and reads CTSS function - 01-38 legal values
-                                             // Stored locally in rigctl - not used.
-                                             if(len <=2) {
-                                                sprintf(msg,"CN%02d;",ctcss_tone);
-                                                send_resp(client_sock,msg);
-                                                send_resp(client_sock,"?;");
-                                             } else {
+        else if((strcmp(cmd_str,"CN")==0) && (zzid_flag == 0))  {  
+                                            // TS-2000 - CN - Sets and reads CTSS function - 01-38 legal values
+                                            // Stored locally in rigctl - not used.
+                                            if(len >2) {
                                                 ctcss_tone = atoi(&cmd_input[2]);
-                                             }
+                                                if((ctcss_tone > 0) && (ctcss_tone <= 39)) {
+                                                    switch(ctcss_tone) {
+                                                      case  1: transmitter->ctcss_frequency = (double) 67.0;break;
+                                                      case  2: transmitter->ctcss_frequency = (double) 71.9;break;
+                                                      case  3: transmitter->ctcss_frequency = (double) 74.4;break;
+                                                      case  4: transmitter->ctcss_frequency = (double) 77.0;break;
+                                                      case  5: transmitter->ctcss_frequency = (double) 79.7;break;
+                                                      case  6: transmitter->ctcss_frequency = (double) 82.5;break;
+                                                      case  7: transmitter->ctcss_frequency = (double) 85.4;break;
+                                                      case  8: transmitter->ctcss_frequency = (double) 88.5;break;
+                                                      case  9: transmitter->ctcss_frequency = (double) 91.5;break;
+                                                      case 10: transmitter->ctcss_frequency = (double) 94.8;break;
+                                                      case 11: transmitter->ctcss_frequency = (double) 97.4;break;
+                                                      case 12: transmitter->ctcss_frequency = (double) 100.0;break;
+                                                      case 13: transmitter->ctcss_frequency = (double) 103.5;break;
+                                                      case 14: transmitter->ctcss_frequency = (double) 107.2;break;
+                                                      case 15: transmitter->ctcss_frequency = (double) 110.9;break;
+                                                      case 16: transmitter->ctcss_frequency = (double) 114.8;break;
+                                                      case 17: transmitter->ctcss_frequency = (double) 118.8;break;
+                                                      case 18: transmitter->ctcss_frequency = (double) 123.0;break;
+                                                      case 19: transmitter->ctcss_frequency = (double) 127.3;break;
+                                                      case 20: transmitter->ctcss_frequency = (double) 131.8;break;
+                                                      case 21: transmitter->ctcss_frequency = (double) 136.5;break;
+                                                      case 22: transmitter->ctcss_frequency = (double) 141.3;break;
+                                                      case 23: transmitter->ctcss_frequency = (double) 146.2;break;
+                                                      case 24: transmitter->ctcss_frequency = (double) 151.4;break;
+                                                      case 25: transmitter->ctcss_frequency = (double) 156.7;break;
+                                                      case 26: transmitter->ctcss_frequency = (double) 162.2;break;
+                                                      case 27: transmitter->ctcss_frequency = (double) 167.9;break;
+                                                      case 28: transmitter->ctcss_frequency = (double) 173.8;break;
+                                                      case 29: transmitter->ctcss_frequency = (double) 179.9;break;
+                                                      case 30: transmitter->ctcss_frequency = (double) 186.2;break;
+                                                      case 31: transmitter->ctcss_frequency = (double) 192.8;break;
+                                                      case 32: transmitter->ctcss_frequency = (double) 203.5;break;
+                                                      case 33: transmitter->ctcss_frequency = (double) 210.7;break;
+                                                      case 34: transmitter->ctcss_frequency = (double) 218.1;break;
+                                                      case 35: transmitter->ctcss_frequency = (double) 225.7;break;
+                                                      case 36: transmitter->ctcss_frequency = (double) 233.6;break;
+                                                      case 37: transmitter->ctcss_frequency = (double) 241.8;break;
+                                                      case 38: transmitter->ctcss_frequency = (double) 250.3;break;
+                                                      case 39: transmitter->ctcss_frequency = (double) 1750.0;break;
+                                                    }
+                                                    transmitter_set_ctcss(transmitter,transmitter->ctcss,transmitter->ctcss_frequency);
+                                                  }
+                                               } else {
+                                                    ctcss_tone = -1; 
+                                                    if(transmitter->ctcss_frequency == (double) 67.0) {
+                                                       ctcss_tone = 1; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 71.9) {
+                                                       ctcss_tone = 2; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 74.4) {
+                                                       ctcss_tone = 3; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 77.0) {
+                                                       ctcss_tone = 4; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 79.7) {
+                                                       ctcss_tone = 5; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 82.5) {
+                                                       ctcss_tone = 6; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 85.4) {
+                                                       ctcss_tone = 7; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 88.5) {
+                                                       ctcss_tone = 8; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 91.5) {
+                                                       ctcss_tone = 9; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 94.8) {
+                                                       ctcss_tone = 10; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 97.4) {
+                                                       ctcss_tone = 11; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 100.0) {
+                                                       ctcss_tone = 12; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 103.5) {
+                                                       ctcss_tone = 13; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 107.2) {
+                                                       ctcss_tone = 14; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 110.9) {
+                                                       ctcss_tone = 15; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 114.8) {
+                                                       ctcss_tone = 16; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 118.8) {
+                                                       ctcss_tone = 17; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 123.0) {
+                                                       ctcss_tone = 18; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 127.3) {
+                                                       ctcss_tone = 19; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 131.8) {
+                                                       ctcss_tone = 20; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 136.5) {
+                                                       ctcss_tone = 21; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 141.3) {
+                                                       ctcss_tone = 22; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 146.2) {
+                                                       ctcss_tone = 23; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 151.4) {
+                                                       ctcss_tone = 24; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 156.7) {
+                                                       ctcss_tone = 25; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 162.2) {
+                                                       ctcss_tone = 26; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 167.9) {
+                                                       ctcss_tone = 27; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 173.8) {
+                                                       ctcss_tone = 28; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 179.9) {
+                                                       ctcss_tone = 29; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 186.2) {
+                                                       ctcss_tone = 30; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 192.8) {
+                                                       ctcss_tone = 31; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 203.5) {
+                                                       ctcss_tone = 32; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 210.7) {
+                                                       ctcss_tone = 33; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 218.1) {
+                                                       ctcss_tone = 34; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 225.7) {
+                                                       ctcss_tone = 35; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 233.6) {
+                                                       ctcss_tone = 36; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 241.8) {
+                                                       ctcss_tone = 37; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 250.3) {
+                                                       ctcss_tone = 38; 
+                                                    } else if (transmitter->ctcss_frequency == (double) 1750.0) {
+                                                       ctcss_tone = 39; 
+                                                    } else {
+                                                       send_resp(client_sock,"?;");
+                                                    }
+                                                    if(ctcss_tone != -1) {
+                                                       sprintf(msg,"CN%02d;",ctcss_tone);
+                                                       send_resp(client_sock,msg);
+                                                    }
+                                                }
                                           }
-        else if(strcmp(cmd_str,"CT")==0)  {  // Sets and reads CTSS function status
-                                             // Stored locally in rigctl - not used.
-                                             if(len <=2) {
-                                                sprintf(msg,"CT%01d;",ctcss_mode);
+        // ZZCS - Keyer Speed implemented within "KS" command
+        else if((strcmp(cmd_str,"CT")==0) && (zzid_flag == 0))  {  
+                                            // TS-2000 - CS - Sets and reads CTSS function status 
+                                            // Stored locally in rigctl - not used.
+                                            if(len <=2) {
+                                                sprintf(msg,"CT%01d;",transmitter->ctcss);
                                                 send_resp(client_sock,msg);
-                                             } else {
-                                                ctcss_mode = atoi(&cmd_input[2]);
-                                             }
+                                            } else {
+                                                if((atoi(&cmd_input[2]) == 0) ||(atoi(&cmd_input[2]) == 1)) {
+                                                   transmitter->ctcss = atoi(&cmd_input[2]);
+                                                   transmitter_set_ctcss(transmitter,transmitter->ctcss,transmitter->ctcss_frequency);
+                                                } else {
+                                                   send_resp(client_sock,"?;");
+                                                }
+                                            }
                                           }
-        else if(strcmp(cmd_str,"DC")==0)  {  // Sets/Reads TX band status
-                                             if(len <=2) {
+        else if((strcmp(cmd_str,"DA")==0) && (zzid_flag == 1))  { 
+                                            // PiHPSDR - DA - Set/Clear Waterfall Automatic on Display Menu
+                                            if(len <=2) {
+                                                sprintf(msg,"ZZDA%0d;",active_receiver->waterfall_automatic);
+                                                send_resp(client_sock,msg);
+                                            } else {
+                                               if((cmd_input[2] == '0') || (cmd_input[2] == '1')) {
+                                                  active_receiver->waterfall_automatic = atoi(&cmd_input[2]);
+                                               }  else {
+                                                  send_resp(client_sock,"?;");
+                                               }
+                                            } 
+                                          }
+        else if((strcmp(cmd_str,"DC")==0) && (zzid_flag == 0))  { 
+                                            // TS-2000 - DC - Sets/Reads TX band status
+                                            if(len <=2) {
                                                 //send_resp(client_sock,"DC00;");
                                                 send_resp(client_sock,"?;");
-                                             } 
+                                            } 
+                                          }
+        else if(strcmp(cmd_str,"DN")==0)  {  
+                                            // TS-2000 - DN - Emulate Mic down key  - Not supported
+                                            // PiHPSDR - ZZDN - Set/Read Waterfall Lo Limit 
+                                             int lcl_waterfall_low;
+                                             #ifdef  RIGCTL_DEBUG
+                                             fprintf(stderr,"RIGCTL: DN - init val=%d\n",active_receiver->waterfall_low);
+                                             #endif
+                                             if(zzid_flag == 1) { // ZZDN
+                                               if(len<=2) {
+                                                  if(active_receiver->waterfall_low <0) {
+                                                     sprintf(msg,"ZZDN-%03d;",abs(active_receiver->waterfall_low));
+                                                  } else {
+                                                     sprintf(msg,"ZZDN+%03d;",active_receiver->waterfall_low);
+                                                  }
+                                                  send_resp(client_sock,msg);
+                                               } else {
+                                                  lcl_waterfall_low = atoi(&cmd_input[3]);
+                                                  if((lcl_waterfall_low >= -200) && (lcl_waterfall_low <=200)) {
+                                                     if(cmd_input[2]=='-') {
+                                                         //waterfall_low = lcl_waterfall_low;
+                                                         active_receiver->waterfall_low = -lcl_waterfall_low;
+                                                     } else {
+                                                         active_receiver->waterfall_low =  lcl_waterfall_low;
+                                                     }
+                                                     #ifdef  RIGCTL_DEBUG
+                                                     fprintf(stderr,"RIGCTL: DN - fin val=%d\n",active_receiver->waterfall_low);
+                                                     #endif
+                                                  } else {
+                                                    fprintf(stderr,"RIGCTL: ZZDN illegal val=%d\n",lcl_waterfall_low);
+                                                    send_resp(client_sock,"?;");
+                                                  }
+                                               }
+                                             }
                                           }
-        else if(strcmp(cmd_str,"DN")==0)  {  // Emulate Mic down key 
+        else if((strcmp(cmd_str,"DO")==0) && zzid_flag == 1)  {  
+                                            // PiHPSDR - ZZDO - Set/Read Waterfall Hi Limit 
+                                             if(zzid_flag == 1) { // ZZDO
+                                               if(len<=2) {
+                                                  if(active_receiver->waterfall_high <0) {
+                                                     sprintf(msg,"ZZDO-%03d;",abs(active_receiver->waterfall_high));
+                                                  } else {
+                                                     sprintf(msg,"ZZDO+%03d;",active_receiver->waterfall_high);
+                                                  }
+                                                  send_resp(client_sock,msg);
+                                               } else {
+                                                  int lcl_waterfall_high = atoi(&cmd_input[3]);
+                                                  if((lcl_waterfall_high >= -200) && (lcl_waterfall_high <=200)) {
+                                                     if(cmd_input[2]=='-') {
+                                                         active_receiver->waterfall_high = -lcl_waterfall_high;
+                                                     } else {
+                                                         active_receiver->waterfall_high =  lcl_waterfall_high;
+                                                     }
+                                                  } else {
+                                                    fprintf(stderr,"RIGCTL: ZZDO illegal val=%d\n",lcl_waterfall_high);
+                                                    send_resp(client_sock,"?;");
+                                                  }
+                                               }
+                                             }
                                           }
-        else if(strcmp(cmd_str,"DQ")==0)  {  // ETs/and reads the DCS function status
+        else if((strcmp(cmd_str,"DQ")==0) && (zzid_flag == 0)) {  
+                                            // TS-2000 - DQ - ETs/and reads the DCS function status - not supported
                                              if(len <=2) {
                                                 //send_resp(client_sock,"DQ0;");
                                                 send_resp(client_sock,"?;");
                                              } 
                                           }
+        else if((strcmp(cmd_str,"DU")==0) && zzid_flag ==1)   {  
+                                            // PiHPSDR - ZZDU - Read Status Word - NOT compatible with PSDR!!
+                                             int smeter = (int) GetRXAMeter(active_receiver->id, smeter) ;
+                                             sprintf(msg,"ZZDU%1d%1d%1d%1d%1d%1d%1d%1d%1d%06d%1d%03d%1c%1d%1d%1d%1c%06lld%1d%011lld%011lld%c%03d%1d%1d%1d%1d;",
+                                                              split,  //P1
+                                                              tune,   // P2,
+                                                              mox,    // P3 
+                                                              receivers, // P4
+                                                              active_receiver->id, // P5
+                                                              active_receiver->alex_antenna, // P6
+                                                              rit_on(),  // P7 
+                                                              active_receiver->agc, // P8
+                                                              vfo[active_receiver->id].mode, //P9
+                                                              (int) step,  // P10
+                                                              vfo[active_receiver->id].band, // P11 6d
+                                                              ((int) transmitter->drive)*100, // P12
+                                                              (int)active_receiver->agc_gain >=0 ? '+' : '-', // P13 sign
+                                                              (int)active_receiver->agc_gain, // P13 3d
+                                                              (int)active_receiver->volume, // P14 3d
+                                                              vfo[active_receiver->id].rit_enabled,
+                                                              vfo[active_receiver->id].rit >=0 ? '+' : '-', // P15 sign
+                                                              vfo[active_receiver->id].rit, // P15 6d
+                                                              vfo[active_receiver->id].ctun, // P16 1d
+                                                              vfo[active_receiver->id].frequency, // P17 11d
+                                                              vfo[active_receiver->id].ctun_frequency, // P18 11d
+                                                              smeter>=0 ? '+': '-',
+                                                              abs(smeter),
+                                                              active_receiver->nr  , active_receiver->nr2  ,
+                                                              active_receiver->anf , active_receiver->snb);
+                                                  send_resp(client_sock,msg);
+                                          }
+
+        else if((strcmp(cmd_str,"EA")==0) && zzid_flag ==1)   {  
+                                            // PiHPSDR - ZZEA - sets/reads RX EQ values
+                                            if(len<=2) {
+                                                    sprintf(msg,"ZZEA%1d%1c%03d%1c%03d%1c%03d%1c%03d;",
+                                                             enable_rx_equalizer,
+                                                             rx_equalizer[0]>=0? '+' : '-',
+                                                             abs((int) rx_equalizer[0]),
+                                                             rx_equalizer[1]>=0? '+' : '-',
+                                                             abs((int) rx_equalizer[1]),
+                                                             rx_equalizer[2]>=0? '+' : '-',
+                                                             abs((int) rx_equalizer[2]),
+                                                             rx_equalizer[3]>=0? '+' : '-',
+                                                             abs((int) rx_equalizer[3]));
+                                                     send_resp(client_sock,msg);
+                                           
+                                            } else {
+                                                 //if(len !=19) {
+                                                 //    fprintf(stderr,"RIGCTL: ZZEA - incorrect number of arguments\n"); 
+                                                 //    send_resp(client_sock,"?;");
+                                                 //    return;
+                                                // }
+                                                 double work_do;
+                                                 enable_rx_equalizer = atoi(&cmd_input[2]); 
+                                                 work_do = (double) atoi(&cmd_input[3]); 
+                                                 if((work_do < -12) || (work_do > 15)) {
+                                                     fprintf(stderr,"RIGCTL: ZZEA - Preamp arg out of range=%d \n",(int) work_do); 
+                                                     send_resp(client_sock,"?;");
+                                                     return;
+                                                 }
+                                                 rx_equalizer[0]  = work_do;
+
+                                                 work_do = (double) atoi(&cmd_input[7]); 
+                                                 if((work_do < -12) || (work_do > 15)) {
+                                                     fprintf(stderr,"RIGCTL: ZZEA - Low arg out of range=%d \n",(int) work_do); 
+                                                     send_resp(client_sock,"?;");
+                                                     return;
+                                                 }
+                                                 rx_equalizer[1]  = work_do;
+
+                                                 work_do  = (double) atoi(&cmd_input[11]); 
+                                                 if((work_do < -12) || (work_do > 15)) {
+                                                     fprintf(stderr,"RIGCTL: ZZEA - Mid arg out of range=%d \n",(int) work_do); 
+                                                     send_resp(client_sock,"?;");
+                                                     return;
+                                                 }
+                                                 rx_equalizer[2]  = work_do;
+
+                                                 work_do  = (double) atoi(&cmd_input[15]); 
+                                                 if((work_do < -12) || (work_do > 15)) {
+                                                     fprintf(stderr,"RIGCTL: ZZEA - Hi arg out of range=%d \n",(int) work_do); 
+                                                     send_resp(client_sock,"?;");
+                                                     return;
+                                                 }
+                                                 rx_equalizer[3]  = work_do;
+
+                                                 SetRXAGrphEQ(active_receiver->id, rx_equalizer);
+                                            }
+                                          }
+        else if((strcmp(cmd_str,"EB")==0) && zzid_flag ==1)   {  
+                                            // PiHPSDR - ZZEB - sets/reads TX EQ values
+                                             if(len<=2) {
+                                                    sprintf(msg,"ZZEB%1d%1c%03d%1c%03d%1c%03d%1c%03d;",
+                                                             enable_tx_equalizer,
+                                                             tx_equalizer[0]>=0? '+' : '-',
+                                                             abs((int) tx_equalizer[0]),
+                                                             tx_equalizer[1]>=0? '+' : '-',
+                                                             abs((int) tx_equalizer[1]),
+                                                             tx_equalizer[2]>=0? '+' : '-',
+                                                             abs((int) tx_equalizer[2]),
+                                                             tx_equalizer[3]>=0? '+' : '-',
+                                                             abs((int) tx_equalizer[3]));
+                                                     send_resp(client_sock,msg);
+                                           
+                                             } else {
+                                                 if(len !=19) {
+                                                     fprintf(stderr,"RIGCTL: ZZEB - incorrect number of arguments\n"); 
+                                                     send_resp(client_sock,"?;");
+                                                     return;
+                                                 }
+                                                 double work_do;
+                                                 enable_tx_equalizer = atoi(&cmd_input[2]); 
+
+                                                 work_do = (double) atoi(&cmd_input[3]); 
+                                                 if((work_do < -12) || (work_do > 15)) {
+                                                     fprintf(stderr,"RIGCTL: ZZEB - Preamp arg out of range=%d \n",(int) work_do); 
+                                                     send_resp(client_sock,"?;");
+                                                     return;
+                                                 }
+                                                 tx_equalizer[0]  = work_do;
+
+                                                 work_do = (double) atoi(&cmd_input[7]); 
+                                                 if((work_do < -12) || (work_do > 15)) {
+                                                     fprintf(stderr,"RIGCTL: ZZEB - Low arg out of range=%d \n",(int) work_do); 
+                                                     send_resp(client_sock,"?;");
+                                                     return;
+                                                 }
+                                                 tx_equalizer[1]  = work_do;
+
+                                                 work_do  = (double) atoi(&cmd_input[11]); 
+                                                 if((work_do < -12) || (work_do > 15)) {
+                                                     fprintf(stderr,"RIGCTL: ZZEB - Mid arg out of range=%d \n",(int) work_do); 
+                                                     send_resp(client_sock,"?;");
+                                                     return;
+                                                 }
+                                                 tx_equalizer[2]  = work_do;
+
+                                                 work_do  = (double) atoi(&cmd_input[15]); 
+                                                 if((work_do < -12) || (work_do > 15)) {
+                                                     fprintf(stderr,"RIGCTL: ZZEB - Hi arg out of range=%d \n",(int) work_do); 
+                                                     send_resp(client_sock,"?;");
+                                                     return;
+                                                 }
+                                                 tx_equalizer[3]  = work_do;
+
+                                                 SetTXAGrphEQ(transmitter->id, tx_equalizer);
+                                             }
+                                          }
         else if(strcmp(cmd_str,"EX")==0)  {  // Set/reads the extension menu
                                              // This routine only can look up specific information;
                                              // And only performs reads at this point..
@@ -493,30 +1542,71 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                                                 }
                                             }
                                           }
-        else if(strcmp(cmd_str,"FA")==0) {  // VFO A frequency
+        else if(strcmp(cmd_str,"FA")==0) { 
+                                            // PiHPSDR - ZZFA - VFO A frequency 
+                                            // TS2000 - FA - VFO A frequency
                                             // LEN=7 - set frequency
                                             // Next data will be rest of freq
                                             if(len == 13) { //We are receiving freq info
                                                new_freqA = atoll(&cmd_input[2]);
-                                               set_band(new_freqA,(int)-1);
+                                               long long *p=malloc(sizeof(long long));
+                                               *p= new_freqA;
+                                               g_idle_add(ext_set_frequency,(gpointer)p);
+                                               g_idle_add(ext_vfo_update,NULL);
+                                               //g_idle_add(set_band,(gpointer) p_int);
+                                               //long long * freq_p;
+                                               //*freq_p=new_freqA;
                                                //setFrequency(new_freqA);
-                                               //g_idle_add(vfo_update,NULL);
+                                               //g_idle_add(gui_vfo_move_to,(gpointer)freq_p);
+                                               return;
                                             } else {
                                                if(len==2) {
-                                                  //sprintf(msg,"FA%011lld;",getFrequency());
-                                                  sprintf(msg,"FA%011lld;",vfo[VFO_A].frequency);
+                                                  if(zzid_flag == 0) {
+                                                     if(vfo[VFO_A].ctun == 1) {
+                                                        sprintf(msg,"FA%011lld;",vfo[VFO_A].frequency+vfo[VFO_A].offset);
+                                                     } else {
+                                                        sprintf(msg,"FA%011lld;",vfo[VFO_A].frequency);
+                                                     }
+                                                  } else {
+                                                     if(vfo[VFO_A].ctun == 1) {
+                                                        sprintf(msg,"ZZFA%011lld;",vfo[VFO_A].frequency+vfo[VFO_A].offset);
+                                                     } else {
+                                                        sprintf(msg,"ZZFA%011lld;",vfo[VFO_A].frequency);
+                                                     }
+                                                  }
+                                                  fprintf(stderr,"RIGCTL: FA=%s\n",msg);
                                                   send_resp(client_sock,msg);
                                                }
                                             }
                                          }
-        else if(strcmp(cmd_str,"FB")==0) {  // VFO B frequency
+        else if(strcmp(cmd_str,"FB")==0) {  
+                                            // TS-2000 - FB - VFO B frequency
+                                            // PiHPSDR - ZZFB - VFO B frequency 
                                             if(len==13) { //We are receiving freq info
-                                               new_freqB = atoll(&cmd_input[2]); 
-                                               set_freqB(new_freqB);
+                                               new_freqB = atoll(&cmd_input[2]);
+                                               long long *p=malloc(sizeof(long long));
+                                               *p=new_freqB;
+                                               g_idle_add(ext_set_frequency,(gpointer)p);
+                                               g_idle_add(ext_vfo_update,NULL);
+                                               //new_freqB = atoll(&cmd_input[2]); 
+                                               //set_freqB(new_freqB);
                                                //setFrequency(new_freqA);
-                                               //g_idle_add(vfo_update,NULL);
+                                               //g_idle_add(ext_vfo_update,NULL);
                                             } else if(len == 2) {
-                                               sprintf(msg,"FB%011lld;",vfo[VFO_B].frequency);
+                                               if(zzid_flag == 0) {
+                                                  if(vfo[VFO_B].ctun == 1) {
+                                                     sprintf(msg,"FB%011lld;",vfo[VFO_B].frequency + vfo[VFO_B].offset);
+                                                  } else {
+                                                     sprintf(msg,"FB%011lld;",vfo[VFO_B].frequency);
+                                                  }
+                                               } else {
+                                                  if(vfo[VFO_B].ctun == 1) {
+                                                     sprintf(msg,"ZZFB%011lld;",vfo[VFO_B].frequency + vfo[VFO_B].offset);
+                                                  } else {
+                                                     sprintf(msg,"ZZFB%011lld;",vfo[VFO_B].frequency);
+                                                  }
+                                               }
+                                               fprintf(stderr,"RIGCTL: FB=%s\n",msg);
                                                send_resp(client_sock,msg);
                                             }
                                          }
@@ -533,10 +1623,71 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                                                send_resp(client_sock,"?;");
                                             }
                                          }
-        else if(strcmp(cmd_str,"FD")==0)  {  // Read the filter display dot pattern
-                                              send_resp(client_sock,"FD00000000;");
+        else if((strcmp(cmd_str,"FD")==0) & (zzid_flag==0))  {  
+                                            // TS-2000 - FD - Read the filter display dot pattern
+                                            send_resp(client_sock,"FD00000000;");
+                                          }
+        else if((strcmp(cmd_str,"FH")==0) & (zzid_flag==1))  {
+                                            // PiHPSDR - ZZFH - Set/Read Selected current DSP Filter Low High
+                                            // P1 = (0)XXXX 5 chars --9999-09999
+                                            if(len<=2) {
+                                               sprintf(msg,"ZZFH%05d;",active_receiver->filter_high);
+                                               send_resp(client_sock,msg);
+                                            } else {
+                                               // Insure that we have a variable filter selected!
+                                               if(vfo[active_receiver->id].filter > 9) {
+                                                  work_int = atoi(&cmd_input[2]); 
+                                                  if((work_int >= -9999) && (work_int <=9999)) {
+                                                      active_receiver->filter_high = work_int;
+                                                  } else {
+                                                     fprintf(stderr,"RIGCTL Warning ZZFH Value=%d out of range\n",work_int);
+                                                     send_resp(client_sock,"?;");
+                                                  }
+                                               } else {
+                                                  fprintf(stderr,"RIGCTL Warning ZZFH not applied - VAR1/2 not selected\n");
+                                                  send_resp(client_sock,"?;");
+                                               }
+                                            } 
                                           }
-        else if(strcmp(cmd_str,"FR")==0)  {  // Set/reads the extension menu
+        else if((strcmp(cmd_str,"FI")==0) & (zzid_flag==1))  {
+                                            // PiHPSDR - ZZFI - Set/Read current DSP filter selected filter
+                                            if(len<=2) {
+                                               sprintf(msg,"ZZFI%02d;",vfo[active_receiver->id].filter);
+                                               send_resp(client_sock,msg);
+                                            } else {
+                                               work_int = atoi(&cmd_input[2]);
+                                               if((work_int >=0) && (work_int<=11)) {
+                                                  g_idle_add(filter_select,(gpointer)(long)work_int);
+                                               } else { 
+                                                  fprintf(stderr,"RIGCTL: ERROR ZZFI incorrect filter value=%d",work_int);
+                                                  send_resp(client_sock,"?;");
+                                               }
+                                            } 
+                                          }
+        else if((strcmp(cmd_str,"FL")==0) & (zzid_flag==1))  {
+                                            // PiHPSDR - ZZFL - Set/Read Selected current DSP Filter Low 
+                                            // P1 = (0)XXXX 5 chars --9999-09999
+                                            if(len<=2) {
+                                               sprintf(msg,"ZZFL%05d;",active_receiver->filter_low);
+                                               send_resp(client_sock,msg);
+                                            } else {
+                                               // Insure that we have a variable filter selected!
+                                               if(vfo[active_receiver->id].filter > 9) {
+                                                  work_int = atoi(&cmd_input[2]); 
+                                                  if((work_int >= -9999) && (work_int <=9999)) {
+                                                      active_receiver->filter_low = work_int;
+                                                  } else {
+                                                     fprintf(stderr,"RIGCTL Warning ZZFH Value=%d out of range\n",work_int);
+                                                     send_resp(client_sock,"?;");
+                                                  }
+                                               } else {
+                                                  fprintf(stderr,"RIGCTL Warning ZZFH not applied - VAR1/2 not selected\n");
+                                                  send_resp(client_sock,"?;");
+                                               }
+                                            } 
+                                          }
+        else if((strcmp(cmd_str,"FR")==0) && (zzid_flag == 0))  { 
+                                            // TS-2000 - FR - Set/reads the extension menu
                                              if(len <=2) {
                                                 if(receivers == 1) {
                                                    sprintf(msg,"FR0;");
@@ -552,42 +1703,81 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                                                  if(active_receiver->id != lcl_cmd) {
                                                     //active_receiver->id = lcl_cmd; 
                                                     active_receiver = receiver[lcl_cmd];
-                                                    g_idle_add(vfo_update,NULL);
-                                                    g_idle_add(active_receiver_changed,NULL);
+                                                    g_idle_add(ext_vfo_update,NULL);
+                                                    // SDW
+                                                    //g_idle_add(active_receiver_changed,NULL);
                                                  } 
                                              }
                                           }
-        else if(strcmp(cmd_str,"FS")==0)  {  // Set/reads fine funct status
+        else if((strcmp(cmd_str,"FS")==0) && (zzid_flag == 0)) {  
+                                            // TS-2000 - FS - Set/reads fine funct status -
                                              if(len <=2) {
-                                                send_resp(client_sock,"FS0;");
-                                             } 
+                                                sprintf(msg,"FS%1d;",fine);
+                                                send_resp(client_sock,msg);
+                                             } else {
+                                                int lcl_fine;
+                                                lcl_fine = atoi(&cmd_input[2]); 
+                                                if((lcl_fine >=0) && (lcl_fine <=1)) {
+                                                    fine = lcl_fine;
+                                                } else {
+                                                   send_resp(client_sock,"?;");
+                                                }
+                                             }
                                           }
-        else if(strcmp(cmd_str,"FT")==0)  { // Sel or reads the transmitters VFO, M, ch or Call comm   
+        else if(strcmp(cmd_str,"FT")==0)  { 
+                                            // TS-2000 - FT - Set/Read Active Transmitter
+                                            // PiHPSDR - ZZFT - Set/Read Active Transmitter
                                              if(len <=2) {
-                                                   sprintf(msg,"FT%1d",active_transmitter);
-                                                   send_resp(client_sock,msg); 
+                                                 if(zzid_flag == 0) {
+                                                   sprintf(msg,"FT%1d;",active_transmitter);
+                                                 } else {
+                                                   sprintf(msg,"ZZFT%1d;",active_transmitter);
+                                                 }
+                                                 send_resp(client_sock,msg); 
                                              } else {
                                                  lcl_cmd = atoi(&cmd_input[2]);                
-                                                 if(lcl_cmd != active_receiver->id) {
-                                                     split = 1;
+                                                 if((lcl_cmd ==0) ||(lcl_cmd == 1)) {
+                                                    if(lcl_cmd != active_receiver->id) {
+                                                        split = 1;
+                                                    } else {
+                                                        split = 0;
+                                                    }
+                                                    active_transmitter = lcl_cmd;
+                                                    #ifdef  RIGCTL_DEBUG
+                                                    fprintf(stderr,"RIGCTL: FT New=%d\n",active_transmitter); 
+                                                    #endif
+                                                    g_idle_add(ext_vfo_update,NULL);
                                                  } else {
-                                                     split = 0;
+                                                    send_resp(client_sock,"?;");
                                                  }
-                                                 active_transmitter = lcl_cmd;
-                                                 g_idle_add(vfo_update,NULL);
                                              } 
                                           }  
-        else if(strcmp(cmd_str,"FW")==0)  { // Sets/Reas DSP receive filter width in hz 0-9999hz 
-                                             // CW - legal values  50  80  100 150 200 300 400 500 600 1000 2000
-                                             //      PiHPSDR map   50  100 100 100 250 250 400 500 600 1000
-                                             //                    25                                   750
-                                             entry= (BANDSTACK_ENTRY *) 
+        else if((strcmp(cmd_str,"FW")==0) & (zzid_flag==0)) {  
+                                            // TS-2000 - FW - Sets/Read DSP receive filter width in hz 0-9999hz 
+                                            // CW - legal values  50  80  100 150 200 300 400 500 600 1000 2000
+                                            //      Pi HPSDR map  50  100 100 100 250 250 400 500 600 1000
+                                            //                    25                                   750
+                                             /*entry= (BANDSTACK_ENTRY *)
                                                          bandstack_entry_get_current();
                                              FILTER* band_filters=filters[entry->mode];
-                                             FILTER* band_filter=&band_filters[entry->filter];
-                                             if(len <=2) {
+                                             FILTER* band_filter=&band_filters[entry->filter];*/
+                                             BAND *band=band_get_band(vfo[active_receiver->id].band);
+                                             BANDSTACK *bandstack=band->bandstack;
+                                             BANDSTACK_ENTRY *entry=&bandstack->entry[vfo[active_receiver->id].bandstack];
+                                             FILTER* band_filters=filters[vfo[active_receiver->id].mode];
+                                             FILTER* band_filter=&band_filters[vfo[active_receiver->id].filter];
+                                             int cur_rad_mode= vfo[active_receiver->id].mode;
+                                             // SDW1
+                                             #ifdef  RIGCTL_DEBUG
+                                             fprintf(stderr,"RIGCTL: FW - active recv mode =%d\n",cur_rad_mode);
+                                             #endif
+                                             if((cur_rad_mode == modeCWL) || (cur_rad_mode == modeCWU)) {
+                                               if(len <=2) {
                                                 // CW filter high and low are always the same and the filter value is 2*filter val
-                                                int filter_val = band_filter->high * 2;
+                                                int filter_val = abs(band_filter->high * 2);
+                                                #ifdef  RIGCTL_DEBUG
+                                                fprintf(stderr,"RIGCTL: Filter Value=%d\n",filter_val);
+                                                #endif
                                                 switch(filter_val) {
                                                  case 25:  
                                                  case 50:
@@ -625,39 +1815,50 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                                                     fprintf(stderr,"RIGCTL: FW Filter Act=%d work_int=%d\n",band_filter->high,work_int);
                                                 #endif
                                                 send_resp(client_sock,msg);
-                                             } else {
-                                               // Try to set filters here!
-                                               // CW - legal values  50  80  100 150 200 300 400 500 600 1000 2000
-                                               //      PiHPSDR map   50  100 100 100 250 250 400 500 600 1000
-                                               //                    25                                   750
-                                               work_int = atoi(&cmd_input[2]);
-                                               switch (work_int) {
-
-                                                    case 50:  new_low = 25; new_high = 25; break;
-                                                    case 80:  new_low = 50; new_high = 50; break;
-                                                    case 100:  new_low = 50; new_high = 50; break;
-                                                    case 150:  new_low = 50; new_high = 50; break;
-                                                    case 200:  new_low = 125; new_high = 125; break;
-                                                    case 300:  new_low = 125; new_high = 125; break;
-                                                    case 400:  new_low = 200; new_high = 200; break;
-                                                    case 500:  new_low = 250; new_high = 250; break;
-                                                    case 600:  new_low = 300; new_high = 300; break;
-                                                    case 1000:  new_low = 500; new_high = 500; break;
-                                                    case 2000:  new_low = 500; new_high = 500; break;
+                                               } else {
+                                                 // Try to set filters here!
+                                                 // CW - legal values  50  80  100 150 200 300 400 500 600 1000 2000
+                                                 //      Pi HPSDR map  50  100 100 100 250 250 400 500 600 1000
+                                                 //                    25                                   750
+                                                 work_int = atoi(&cmd_input[2]);
+                                                 int f=5;
+                                                 switch (work_int) {
+
+                                                    case 50:  new_low = 25; new_high = 25; f=8; break;
+                                                    case 80:  new_low = 50; new_high = 50; f=7; break;
+                                                    case 100:  new_low = 50; new_high = 50; f=7; break;
+                                                    case 150:  new_low = 50; new_high = 50; f=7; break;
+                                                    case 200:  new_low = 125; new_high = 125; f=6; break;
+                                                    case 300:  new_low = 125; new_high = 125; f=6; break;
+                                                    case 400:  new_low = 200; new_high = 200; f=5; break;
+                                                    case 500:  new_low = 250; new_high = 250; f=4; break;
+                                                    case 600:  new_low = 300; new_high = 300; f=3; break;
+                                                    case 1000:  new_low = 500; new_high = 500; f=0; break;
+                                                    case 2000:  new_low = 500; new_high = 500; f=0; break;
                                                     default: new_low  = band_filter->low;
                                                              new_high = band_filter->high;
+                                                             f=10;
 
-                                               }
+                                                 }
                                                #ifdef  RIGCTL_DEBUG
-                                                   fprintf(stderr,"RIGCTL: FW Filter new_low=%d new_high=%d\n",new_low,new_high);
+                                                 fprintf(stderr,"RIGCTL: FW Filter new_low=%d new_high=%d f=%d\n",new_low,new_high,f);
                                                #endif
                                                // entry->filter = new_low * 2 ;
                                                //setFilter(new_low,new_high);
-                                               set_filter(active_receiver,new_low,new_high);
-                                               g_idle_add(vfo_update,NULL);
-                                             }
+                                               //set_filter(active_receiver,new_low,new_high);
+                                               //g_idle_add(ext_vfo_update,NULL);
+                                               g_idle_add(ext_vfo_filter_changed,(gpointer)(long)f);
+                                              }
+                                            } else {
+                                                /* Not in CW mode */
+                                                send_resp(client_sock,"?;");
+                                            }
                                           }  
-        else if(strcmp(cmd_str,"GT")==0)  { // Sets/Read AGC constant status 000-020
+        else if(strcmp(cmd_str,"GT")==0)  { 
+                                            // TS-2000 - GT - Sets/Reads AGC Constant
+                                            // PiHPSDR - ZZGT - AGC Constant 0-4 are legal values
+                                           if(zzid_flag == 0) {
+                                            // Sets/Read AGC constant status 000-020
                                             // Map 000 - Off, 001-4 - Fast, 4-9 - Medium 10-14 Slow 15-20 Long
                                              //fprintf(stderr,"GT command seen\n");
                                              int agc_resp = 0;
@@ -671,15 +1872,18 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                                                    case AGC_LONG:   agc_resp = 20; break;
                                                    default: agc_resp = 0;
                                                 }
-                                               
-                                                sprintf(msg,"GT%03d;",agc_resp);
+                                                if(zzid_flag == 0) { 
+                                                   sprintf(msg,"GT%03d;",agc_resp);
+                                                } else {
+                                                   sprintf(msg,"ZZGT%03d;",agc_resp);
+                                                }
                                                 send_resp(client_sock,msg);
                                              } else {
                                                 //fprintf(stderr,"GT command Set\n");
                                                 agc_resp = atoi(&cmd_input[2]);
                                                 
                                                 // AGC powers of 84 is broken Hamlib... 
-                                                // Hamlib TS-2000 is broken here
+                                                // Hamlib TS 2000 is broken here
                     
                                                 if(agc_resp == 0) {
                                                    active_receiver->agc = AGC_OFF;
@@ -696,15 +1900,34 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                                                    active_receiver->agc = AGC_LONG;
                                                    // fprintf(stderr,"GT command LONG\n");
                                                 }
-                                                g_idle_add(vfo_update,NULL);
+                                                g_idle_add(ext_vfo_update,NULL);
 
                                              }
+                                            } else {
+                                                if(len<=2) {
+                                                   sprintf(msg,"ZZGT%01d;",active_receiver->agc);
+                                                   send_resp(client_sock,msg);
+                                                } else {
+                                                   int lcl_agc = atoi(&cmd_input[2]);
+                                                   if(lcl_agc >= AGC_OFF && lcl_agc<=AGC_FAST) {
+                                                      active_receiver->agc = lcl_agc;
+                                                      g_idle_add(ext_vfo_update,NULL);
+                                                   }
+                                                }
+                                           }
                                           }  
-        else if(strcmp(cmd_str,"ID")==0)  { // Read ID - Default to TS-2000 which is type 019.
-                                            sprintf(msg,"ID019;");
-                                            send_resp(client_sock,msg);
-                                          }
-        else if(strcmp(cmd_str,"IF")==0) {  // Reads Transceiver status
+        else if(strcmp(cmd_str,"ID")==0)  { 
+                                            // TS-2000 - ID - Read ID - Default to TS-2000 which is type 019.
+                                            // PiHPSDR - ZZID - Read ID - 240, i.e. hamlib number
+                                              if(zzid_flag == 0) {
+                                                   sprintf(msg,"ID019;");
+                                              } else {
+                                                   sprintf(msg,"ZZID240;");
+                                              } 
+                                              send_resp(client_sock,msg);
+                                          }
+        else if((strcmp(cmd_str,"IF")==0) && (zzid_flag == 0)) {  
+                                            // TS-2000 - IF - Reads Transceiver status
                                             // IF
                                             //  P1: FFFFFFFFFFF -11 chars : Frequency in Hz (blanks are "0")
                                             //  P2: OFFS        - 4 chars : Offset in powers of 10
@@ -724,7 +1947,7 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
 
                                             // convert first half of the msg
                                                       // IF     P1    P2  P3  P4  P5  P6
-                                            sprintf(msg,"IF%011lld%04lld%06d%01d%01d%01d",
+                                            sprintf(msg,"IF%011lld%04lld%06lld%01d%01d%01d",
                                                          //getFrequency(),
                                                          rigctl_getFrequency(), // P1
                                                          step,  // P2
@@ -743,8 +1966,8 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                                                          0,  // P10
                                                          0,  // P11
                                                          ft_read(), // P12
-                                                         ctcss_tone,  // P13
-                                                         0,  // P14
+                                                         transmitter->ctcss,  // P14
+                                                         convert_ctcss(),  // P13
                                                          0); // P15
                                             send_resp(client_sock,msg);
                                          }
@@ -753,53 +1976,103 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                                                 send_resp(client_sock,"IS00000;");
                                              } 
                                           }  
-        else if(strcmp(cmd_str,"KS")==0)  { // Sets/Reads keying freq - 0-060 max
+        else if((strcmp(cmd_str,"KS")==0) && (zzid_flag == 0) || 
+                (strcmp(cmd_str,"CS")==0) && (zzid_flag==1))  { 
+                                            // TS-2000 - KS - Set/Reads keying speed 0-060 max
+                                            // PiHPSDR - ZZCS - Sets/Reads Keying speed
                                              if(len <=2) {
-                                                sprintf(msg,"KS%03d;",cw_keyer_speed);
+                                                if(zzid_flag ==0) {
+                                                    sprintf(msg,"KS%03d;",cw_keyer_speed);
+                                                } else {
+                                                    sprintf(msg,"ZZCS%02d;",cw_keyer_speed);
+                                                }
                                                 send_resp(client_sock,msg);
                                              } else {
                                                 int key_speed;
                                                 key_speed = atoi(&cmd_input[2]);
-                                                if(key_speed >1 && key_speed <= 60) {
+                                                #ifdef  RIGCTL_DEBUG
+                                                fprintf(stderr,"RIGCTL: Set CW speed=%d",key_speed);
+                                                #endif
+                                                if(key_speed >= 1 && key_speed <= 60) {
                                                    cw_keyer_speed=key_speed;
-                                                   g_idle_add(vfo_update,NULL);
+                                                   g_idle_add(ext_vfo_update,NULL);
+                                                } else {
+                                                   send_resp(client_sock,"?;");
                                                 } 
                                             }
                                           }  
-        else if(strcmp(cmd_str,"KY")==0)  { // Convert char to morse code
+        else if((strcmp(cmd_str,"KY")==0) && (zzid_flag == 0)) { 
+                                            // TS-2000 - KY - Convert char to morse code - not supported
+                                             int index = 2;
+                                             long delay = 1200000L/(long)cw_keyer_speed; // uS
+                                             #ifdef  RIGCTL_DEBUG
+                                             fprintf(stderr,"RIGCTL: KY DELAY=%ld, cw_keyer_speed=%d cw_keyer_weight=%d\n",delay,cw_keyer_speed,cw_keyer_weight); 
+                                             #endif
                                              if(len <=2) {
                                                 send_resp(client_sock,"KY0;");
+                                             } else {
+                                               // Set CW BUSY flag
+                                               g_mutex_lock(&mutex_c->m);
+                                               cw_busy = 1;
+                                               g_mutex_unlock(&mutex_c->m);
+                                               while((cmd_input[index] != '\0') && (!cw_reset)) {
+                                                  //fprintf(stderr,"send=%c\n",cmd_input[index]);
+                                                  rigctl_send_cw_char(cmd_input[index]);
+                                                  //fprintf(stderr,"RIGCTL: 0 mox=%d\n",mox);
+                                                  index++;
+                                               } 
+                                             #ifdef  RIGCTL_DEBUG
+                                               fprintf(stderr,"RIGCTL: KY - Done sending cw\n");
+                                               fprintf(stderr,"RIGCTL: 1 mox=%d\n",mox);
+                                             #endif
                                              } 
+                                             g_mutex_lock(&mutex_c->m);
+                                             cw_busy = 0;
+                                             g_mutex_unlock(&mutex_c->m);
+                                             #ifdef  RIGCTL_DEBUG
+                                             fprintf(stderr,"RIGCTL: 2 mox=%d\n",mox);
+                                             #endif
                                           }  
-        else if(strcmp(cmd_str,"LK")==0)  { // Set/read key lock function status
+        else if(strcmp(cmd_str,"LK")==0)  { 
+                                            // TS-2000 - LK - Set/read key lock function status
+                                            // PiHPSDR - ZZLK - Set/read key lock function status
                                              if(len <=2) {
-                                                sprintf(msg,"LK%01d%01d;",locked,locked);
+                                                if(zzid_flag == 0) {
+                                                   sprintf(msg,"LK%01d%01d;",locked,locked);
+                                                } else {
+                                                   sprintf(msg,"ZZLK%01d%01d;",locked,locked);
+                                                }
                                                 send_resp(client_sock,msg);
                                              }  else {
-                                                  if(cmd_input[3] == '0') {
-                                                      locked = 0;
-                                                  } else if(cmd_input[3] == '1') {
+                                                  if((cmd_input[2] == '1') || (cmd_input[3]=='1'))  {
                                                       locked = 1;
+                                                  } else {
+                                                      locked = 0;
                                                   }
-                                                  g_idle_add(vfo_update,NULL);
+                                                  g_idle_add(ext_vfo_update,NULL);
                                              }
                                           }  
-        else if(strcmp(cmd_str,"LM")==0)  { // Set/read DRU 3A unit or elect keyer recording status
+        else if(strcmp(cmd_str,"LM")==0)  { 
+                                            // TS-2000 - LM - Set/Read DRU 3A keyer recording status - not supported
                                              if(len <=2) {
-                                                send_resp(client_sock,"LM0;");
+                                                send_resp(client_sock,"?;");
                                              } 
                                           }  
-        else if(strcmp(cmd_str,"LT")==0)  { // Set/read Alt function
+        else if(strcmp(cmd_str,"LT")==0)  { 
+                                            // TS-2000 - LT - Set/read Alt function - not supported
                                              if(len <=2) {
-                                                send_resp(client_sock,"LT0;");
+                                                send_resp(client_sock,"?;");
                                              } 
                                           }  
-        else if(strcmp(cmd_str,"MC")==0) {  // Recalls or reads memory channel
+        else if(strcmp(cmd_str,"MC")==0) {  
+                                            // TS-2000 - MC - Recalls or reads memory channel - not supported
                                              if(len <=2) {
-                                               send_resp(client_sock,"MC000;"); // Link this to band stack at some point
+                                               send_resp(client_sock,"?;"); // Link this to band stack at some point
                                              }
                                          }
-        else if(strcmp(cmd_str,"MD")==0) {  // Mode - digit selects mode
+        else if((strcmp(cmd_str,"MD")==0) && (zzid_flag == 0)) {  
+                                            // TS-2000 - MD - Set/Read Mode
+                                            // Mode - digit selects mode
                                             // 1 = LSB
                                             // 2 = USB
                                             // 3 = CWU
@@ -847,22 +2120,22 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                                             entry= (BANDSTACK_ENTRY *) 
                                                   bandstack_entry_get_current();
                                             entry->mode=new_mode;
-                                            //  BUG - kills the system when there is some
+                                            // BUG - kills the system when there is some
                                             // GPIO activity and Mode sets occur. Used twittling the
                                            // frequency along with setting mode between USB/LSB with
                                            // flrig. Tried doing the g_idle_add trick - but don't know the
                                            // the magic to get that to compile without warnings 
                                             //setMode(entry->mode);
                                             set_mode(active_receiver,entry->mode);
-                                            // Moved the vfo_update down after filter updated. (John G0ORX)
-                                            //g_idle_add(vfo_update,NULL);
+                                            // Moved the ext_vfo_update down after filter updated. (John G0ORX)
+                                            //g_idle_add(ext_vfo_update,NULL);
                                             
                                             FILTER* band_filters=filters[entry->mode];
                                             FILTER* band_filter=&band_filters[entry->filter];
                                             //setFilter(band_filter->low,band_filter->high);
                                             set_filter(active_receiver,band_filter->low,band_filter->high);
                                             /* Need a way to update VFO info here..*/
-                                            g_idle_add(vfo_update,NULL);
+                                            g_idle_add(ext_vfo_update,NULL);
                                             }  else {     // Read Mode
                                                int curr_mode;
                                                switch (vfo[active_receiver->id].mode) {
@@ -876,158 +2149,461 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                                                           break;
                                                   case modeFMN: curr_mode = 4; // FMN
                                                           break;
-                                                  case modeAM: curr_mode = 5; // AM
-                                                          break;
-                                                  case modeDIGU: curr_mode = 9; // DIGU
-                                                          break;
-                                                  case modeDIGL: curr_mode = 6; // DIGL
-                                                          break;
-                                                  default: 
-                                                          #ifdef RIGCTL_DEBUG
-                                                            fprintf(stderr,
-                                                            "RIGCTL: MD command doesn't support %d\n",
-                                                            vfo[active_receiver->id].mode);
-                                                          #endif
-                                                          break;
+                                                         case modeAM: curr_mode = 5; // AM
+                                                                 break;
+                                                         case modeDIGU: curr_mode = 9; // DIGU
+                                                                 break;
+                                                         case modeDIGL: curr_mode = 6; // DIGL
+                                                                 break;
+                                                         default: 
+                                                                 #ifdef RIGCTL_DEBUG
+                                                                   fprintf(stderr,
+                                                                   "RIGCTL: MD command doesn't support %d\n",
+                                                                   vfo[active_receiver->id].mode);
+                                                                 #endif
+                                                                 break;
+                                                      }
+                                                      sprintf(msg,"MD%1d;",curr_mode);
+                                                      send_resp(client_sock,msg);
+                                                   }
+                                                }
+               else if((strcmp(cmd_str,"MD")==0) && (zzid_flag == 1)) {  
+                                                   // PiHPSDR - ZZMD - Set/Read Modulation Mode
+                                                   if(len <= 2) { // Set Mode
+                                                      sprintf(msg,"ZZMD%02d;",vfo[active_receiver->id].mode);
+                                                      send_resp(client_sock,msg);
+                                                   } else {
+                                                      work_int = atoi(&cmd_input[2]);
+                                                      if((work_int >=0) && (work_int <=11)) {
+                                                         // Other stuff to switch modes goes here..
+                                                         // since new_mode has the interpreted command in 
+                                                         // in it now.
+                                                         entry= (BANDSTACK_ENTRY *) 
+                                                            bandstack_entry_get_current();
+                                                         entry->mode=work_int;
+                                                         set_mode(active_receiver,entry->mode);
+                                                         FILTER* band_filters=filters[entry->mode];
+                                                         FILTER* band_filter=&band_filters[entry->filter];
+                                                         //setFilter(band_filter->low,band_filter->high);
+                                                         set_filter(active_receiver,band_filter->low,band_filter->high);
+                                                         /* Need a way to update VFO info here..*/
+                                                         g_idle_add(ext_vfo_update,NULL);
+                                                      } else {
+                                                         fprintf(stderr,"RIGCTL: Error - ZZMD - Illegal cmd received=%d",work_int);
+                                                      }
+                                                   } 
+                                                }
+               else if((strcmp(cmd_str,"MF")==0) && (zzid_flag == 0)) {  
+                                                   // TS-2000 - MF - Set/read menu A/B - not supported
+                                                    if(len <=2) {
+                                                      send_resp(client_sock,"?;"); 
+                                                    }
+                                                }
+               else if(strcmp(cmd_str,"MG")==0) {  
+                                                   // PiHPSDR - ZZMG - Mic Gain P1=+/-P2=2digits (-10-50)
+                                                   // TS-2000 - MG - Mike Gain - 3 digits
+                                                   if(zzid_flag == 0) {
+                                                      if(len <=2) {
+                                                         work_int = (int) ((mic_gain +10.0)* 100.0/60.0);
+                                                          if(zzid_flag == 0) {
+                                                            sprintf(msg,"MG%03d;",work_int);
+                                                          } else {
+                                                            sprintf(msg,"ZZMG%03d;",work_int);
+                                                          }
+                                                         send_resp(client_sock,msg);
+                                                      } else {
+                                                         int tval = atoi(&cmd_input[2]);                
+                                                         new_vol = (double) (tval * 60/100) - 10; 
+                                                         //set_mic_gain(new_vol); 
+                                                         double *p_mic_gain=malloc(sizeof(double));
+                                                         *p_mic_gain=new_vol;
+                                                         g_idle_add(update_mic_gain,(void *)p_mic_gain);
+                                                      }
+                                                   } else {
+                                                      if(len <=2) {
+                                                         sprintf(msg,"ZZMG%c%02d;",mic_gain>=0 ? '+' : '-',abs((int)mic_gain));
+                                                         send_resp(client_sock,msg);
+                                                      } else {
+                                                         int new_vol = atoi(&cmd_input[2]);                
+                                                          if((new_vol >= -10) && (new_vol <= 50)) {
+                                                            double *p_mic_gain=malloc(sizeof(double));
+                                                            *p_mic_gain=new_vol;
+                                                            g_idle_add(update_mic_gain,(void *)p_mic_gain);
+                                                          } else {
+                                                             send_resp(client_sock,"?;");
+                                                          }
+                                                      }
+                                                   }
+                                                }
+               else if((strcmp(cmd_str,"ML")==0) && (zzid_flag == 0)) {  
+                                                   // TS-2000 - ML - Set/read the monitor function level - not supported
+                                                    if(len <=2) {
+                                                      send_resp(client_sock,"?;"); 
+                                                    }
+                                                }
+               else if(strcmp(cmd_str,"MO")==0) {  
+                                                   // TS-2000 - MO - Set Monitor on/off - not supported
+                                                    if(len <=2) {
+                                                      send_resp(client_sock,"?;"); 
+                                                    }
+                                                }
+               else if((strcmp(cmd_str,"MR")==0) && (zzid_flag == 0)) {  
+                                                    #ifdef RIGCTL_DEBUG
+                                                    fprintf(stderr,"RIGCTL: Command seen\n"); 
+                                                     #endif
+        
+                                                    // TS-2000 - MR - Read Memory Channel data
+                                                    sprintf(msg,"MR%1d%1d%02d%011lld%1d%1d%1d%02d%02d%03d%1d%1d%09d%02d%1d%08d;",
+                                                             0, // P1 - Rx Freq - 1 Tx Freq
+                                                             0, // P2 Bankd and channel number -- see MC comment
+                                                             0, // P3 - see MC comment 
+                                                             rigctl_getFrequency(), // P4 - frequency
+                                                             rigctlGetMode(), // P5 - Mode
+                                                             locked, // P6 - Locked status
+                                                             transmitter->ctcss, // P7 - O-off, 1-tone, 2-CTCSS, 3 =DCS
+                                                             convert_ctcss(),    // P8 - Tone Number - see page 35
+                                                             convert_ctcss(),    // P9 - CTCSS tone number - see CN command
+                                                             0, // P10 - DCS code - see QC command 
+                                                             0, // P11 - Reverse status
+                                                             0, // P12 - Shift status - see OS command
+                                                             0, // P13 - Offset freq - see OS command
+                                                             0, // P14 - Step Size - see ST command
+                                                             0, // P15 - Memory Group Number (0-9)
+                                                             0);  // P16 - Memory Name - 8 char max
+                                                      send_resp(client_sock,msg);
+                                                      //send_resp(client_sock,"?;");
+                                                }
+               else if((strcmp(cmd_str,"MT")==0) && (zzid_flag == 1)) {  
+                                                   #ifdef RIGCTL_DEBUG
+                                                   fprintf(stderr,"RIGCTL: MT Command seen\n");
+                                                    #endif
+                                                   // PiHPSDR - ZZMT - Read TX Meter Mode
+                                                   // Mapped from PSDR
+                                                   // 0= ALC Peak
+                                                   // 1= ALC Average
+                                                   // 2= ALG Gain
+                                                      int * p_alc; 
+                                                     if(len<=2) { 
+                                                         switch((int)alc) {
+                                                            case TXA_ALC_PK:  work_int = 0; break;
+                                                            case TXA_ALC_AV:  work_int = 1; break;
+                                                            case TXA_ALC_GAIN: work_int = 2; break;
+                                                            default: work_int = 0;
+                                                         }
+                                                         sprintf(msg,"ZZMT%01d;",(int)work_int);
+                                                         send_resp(client_sock,msg);
+                                                     } else {
+                                                         work_int = atoi(&cmd_input[2]);
+                                                         switch (work_int)  {
+                                                             case 0: work_int = TXA_ALC_PK; break;
+                                                             case 1: work_int = TXA_ALC_AV; break;
+                                                             case 2: work_int = TXA_ALC_GAIN; break;
+                                                             default: work_int = TXA_ALC_PK;
+                                                           }
+                                                          p_alc=(int *) malloc(sizeof(double));
+                                                          *p_alc=work_int;
+                                                          g_idle_add(set_alc,(gpointer )p_alc);
+                                                     }
+                                                }
+               else if(strcmp(cmd_str,"MU")==0) {   if(zzid_flag == 1) {  
+                                                   #ifdef RIGCTL_DEBUG
+                                                   fprintf(stderr,"RIGCTL: MU Command seen\n");
+                                                    #endif
+                                                   // PiHPSDR - ZZMU - Sets or Read the MultiRX status
+                                                        if(len<=2) {
+                                                           #ifdef RIGCTL_DEBUG
+                                                           fprintf(stderr,"ZZMU =%d\n",receivers);
+                                                            #endif
+                                                           sprintf(msg,"ZZMU%1d;",receivers);
+                                                           send_resp(client_sock,msg);
+                                                        } else {
+                                                          int lcl_rcvr = atoi(&cmd_input[2]);
+                                                          #ifdef RIGCTL_DEBUG
+                                                          fprintf(stderr,"ZZMU Set=%d\n",lcl_rcvr);
+                                                           #endif
+                                                          /*if (lcl_rcvr <1 || lcl_rcvr >2) {
+                                                             fprintf(stderr,"RIGCTL: ZZMU - illegal recevier number\n");
+                                                             return;
+                                                          }*/
+                                                          g_idle_add(ext_radio_change_sample_rate,(gpointer)(long)lcl_rcvr);
+                                                          g_idle_add(ext_vfo_update,NULL);
+                                                        }
+        
+                                                    } else { 
+                                                   // TS-2000 - MU - Set/Read Memory Group Data - not supported
+                                                        if(len <=2) {
+                                                          send_resp(client_sock,"MU0000000000;"); 
+                                                        }
+                                                    }
+                                                }
+               else if((strcmp(cmd_str,"MW")==0) && (zzid_flag == 0)) {  
+                                                   #ifdef RIGCTL_DEBUG
+                                                   fprintf(stderr,"RIGCTL: MW Command seen\n");
+                                                    #endif
+                                                   // TS-2000 - MW - Store Data to Memory Channel -not supported
+                                                }
+               else if(strcmp(cmd_str,"NB")==0) {  
+                                                   // PiHPSDR - ZZNB - Set/Read Noise Blanker func status (on/off)
+                                                   // TS-2000 - NB - Set/Read Noise Blanker func status (on/off)
+                                                    if(len <=2) {
+                                                       if (zzid_flag == 0) {
+                                                         sprintf(msg,"NB%1d;",active_receiver->snb);
+                                                       } else {
+                                                         sprintf(msg,"ZZNB%1d;",active_receiver->snb);
+                                                       }
+                                                      send_resp(client_sock,msg);
+                                                    } else {
+                                                      if(cmd_input[2]=='0') { // Turn off ANF
+                                                         active_receiver->snb=0;
+                                                      } else { // Turn on ANF
+                                                         active_receiver->snb=1;
+                                                      }
+                                                      // Update filters
+                                                      SetRXASNBARun(active_receiver->id, active_receiver->snb);
+                                                      g_idle_add(ext_vfo_update,NULL);
+                                                    }
+                                                }
+               else if((strcmp(cmd_str,"NE")==0) && (zzid_flag == 1)) {  
+                                                   // PiHPSDR - ZZNE - NPS AE FIlter - DSP Menu
+                                                   //   P1 - 0=Off
+                                                   //   P1 - 1=On
+                                                      if(len<=2) {
+                                                        sprintf(msg,"ZZNE%1d;",(int) active_receiver->nr2_ae); 
+                                                        send_resp(client_sock,msg);
+                                                      } else {
+                                                        work_int = atoi(&cmd_input[2]);
+                                                        if(work_int >=0 && work_int <=1) {
+                                                          active_receiver->nr2_ae = work_int; 
+                                                          SetRXAEMNRaeRun(active_receiver->id, active_receiver->nr2_ae);
+                                                        } else {
+                                                          fprintf(stderr,"RIGCTL: ZZNE - ERROR illegal value=%d s/b 0 to 2\n",work_int);
+                                                          send_resp(client_sock,"?;");
+                                                        }
+                                                      }
+                                                  }
+               else if((strcmp(cmd_str,"NG")==0) && (zzid_flag == 1)) {  
+                                                   // PiHPSDR - ZZNG - NR Pre AGC/Post AGC- DSP Menu
+                                                      if(len<=2) {
+                                                        sprintf(msg,"ZZNG%1d;",(int) active_receiver->nr_agc); 
+                                                        send_resp(client_sock,msg);
+                                                      } else {
+                                                        work_int = atoi(&cmd_input[2]);
+                                                        if(work_int >=0 && work_int <=1) {
+                                                            active_receiver->nr_agc = atoi(&cmd_input[2]);
+                                                            SetRXAEMNRPosition(active_receiver->id, active_receiver->nr_agc);
+                                                        } else { 
+                                                          fprintf(stderr,"RIGCTL: ZZNG - illegal value=%d s/b 0 or 1\n",work_int);
+                                                          send_resp(client_sock,"?;");
+                                                        }
+                                                      }
+                                                  }
+
+               else if((strcmp(cmd_str,"NM")==0) && (zzid_flag == 1)) {  
+                                                   // PiHPSDR - ZZNM - NR2 Gain Method - DSP Menu
+                                                   //   P1 - 0=Linear
+                                                   //   P1 - 1=Log
+                                                                       //   P1 - 2=Gamma
+                                                      if(len<=2) {
+                                                        sprintf(msg,"ZZNM%1d;",(int) active_receiver->nr2_gain_method); 
+                                                        send_resp(client_sock,msg);
+                                                      } else {
+                                                        work_int = atoi(&cmd_input[2]);
+                                                        if(work_int >=0 && work_int <=2) {
+                                                          active_receiver->nr2_gain_method = work_int; 
+                                                          SetRXAEMNRgainMethod(active_receiver->id, active_receiver->nr2_gain_method);
+                                                        } else {
+                                                          fprintf(stderr,"RIGCTL: ZZNM - illegal value=%d s/b 0 to 2\n",work_int);
+                                                          send_resp(client_sock,"?;");
+                                                        }
+                                                      }
+                                                }
+               else if(strcmp(cmd_str,"AB")==0) { 
+                                                   #ifdef RIGCTL_DEBUG
+                                                     fprintf(stderr,"RIGCTL: Command seen\n"); 
+                                                    #endif
+                                                 }
+               else if((strcmp(cmd_str,"NP")==0) && (zzid_flag == 1)) {  
+                                                   // PiHPSDR - ZZNP - NPS Method - DSP Menu
+                                                   //   P1 - 0=OSMS
+                                                   //   P1 - 1=MMSE
+                                                      if(len<=2) {
+                                                        sprintf(msg,"ZZNP%1d;",(int) active_receiver->nr2_npe_method); 
+                                                        send_resp(client_sock,msg);
+                                                      } else {
+                                                        work_int = atoi(&cmd_input[2]);
+                                                        if(work_int >=0 && work_int <=1) {
+                                                          active_receiver->nr2_npe_method = work_int; 
+                                                          SetRXAEMNRnpeMethod(active_receiver->id, active_receiver->nr2_npe_method);
+                                                        } else {
+                                                          fprintf(stderr, "RIGCTL: ZZNP - ERROR illegal value=%d s/b 0 to 2\n",work_int);
+                                                          send_resp(client_sock,"?;");
+                                                        }
+                                                      }
+                                                }
+               else if(strcmp(cmd_str,"NL")==0) {if(zzid_flag == 0) { 
+                                                   // TS-2000 - NL - Set/Read Noise Reduction  Level - Not Supported
+                                                    if(len <=2) {
+                                                      send_resp(client_sock,"?;"); 
+                                                    }
+                                                 } else {
+                                                   // PiHPSDR - ZZNL - AGC Hang Threshold - DSP Menu slider
+                                                    //         P1P1P1 - 0 - 100
+                                                    if(len <=2) {
+                                                       sprintf(msg,"ZZNL%03d;",(int) active_receiver->agc_hang_threshold);
+                                                       send_resp(client_sock,msg);
+                                                    } else {
+                                                       work_int = atoi(&cmd_input[2]);
+                                                       if((work_int >= 0) && (work_int<=100)) {
+                                                          active_receiver->agc_hang_threshold = work_int;
+                                                          if(active_receiver->agc==AGC_LONG || active_receiver->agc==AGC_SLOW) {
+                                                              SetRXAAGCHangThreshold(active_receiver->id, (int)active_receiver->agc_hang_threshold);
+                                                          }
+                                                       }
+                                                    }
+                                                 }
+                                                }
+               else if(strcmp(cmd_str,"NR")==0) {  
+                                                   // TS-2000 - NR - Set/Read Noise Reduction function status
+                                                   // PiHPSDR - ZZNR - Set/Read Noise Reduction function status
+                                                   if(len <=2) {
+                                                      if(zzid_flag == 0) {
+                                                         if (active_receiver->nr==1 & active_receiver->nr2==0) { 
+                                                            send_resp(client_sock,"NR1;"); 
+                                                         } else if (active_receiver->nr==1 & active_receiver->nr2==1) { 
+                                                           send_resp(client_sock,"NR2;"); 
+                                                         } else {
+                                                           send_resp(client_sock,"NR0;"); 
+                                                         }
+                                                      } else {
+                                                         if (active_receiver->nr==1 & active_receiver->nr2==0) { 
+                                                            send_resp(client_sock,"ZZNR1;"); 
+                                                         } else if (active_receiver->nr==1 & active_receiver->nr2==1) { 
+                                                           send_resp(client_sock,"ZZNR2;"); 
+                                                         } else {
+                                                           send_resp(client_sock,"ZZNR0;"); 
+                                                         }
+                                                      }
+                                                    } else {
+                                                      if((atoi(&cmd_input[2]) >=0) && (atoi(&cmd_input[2]) <=2)) {
+                                                         if(cmd_input[2] == '0') {
+                                                            active_receiver->nr = 0;
+                                                            active_receiver->nr2 = 0;
+                                                         } else if(cmd_input[2] == '1') {
+                                                            active_receiver->nr = 1;
+                                                         } else if(cmd_input[2] == '2') {
+                                                           active_receiver->nr2 = 1;
+                                                         }
+                                                         SetRXAANRRun(active_receiver->id, active_receiver->nr);
+                                                         SetRXAEMNRRun(active_receiver->id, active_receiver->nr2);
+                                                         g_idle_add(ext_vfo_update,NULL);
+                                                      } else {
+                                                        send_resp(client_sock,"?;"); 
+                                                      }
+                                                   } 
+                                         }
+        else if(strcmp(cmd_str,"NT")==0) {  
+                                            // TS-2000 - NT - Set/Read autonotch function - 
+                                            // PiHPSDR - ZZNT - Sets/reads ANF status
+                                             if(len <=2) {
+                                               if(zzid_flag == 0) {
+                                                  sprintf(msg,"NT%1d;",active_receiver->anf);
+                                               } else {
+                                                  sprintf(msg,"ZZNT%1d;",active_receiver->anf);
                                                }
-                                               sprintf(msg,"MD%1d;",curr_mode);
-                                               send_resp(client_sock,msg);
-                                            }
-                                         }
-        else if(strcmp(cmd_str,"MF")==0) {  // Set/read menu A/B
-                                             if(len <=2) {
-                                               send_resp(client_sock,"MF0;"); 
-                                             }
-                                         }
-        else if(strcmp(cmd_str,"MG")==0) {  // Mike Gain - 3 digit value 
-                                            if(len <=2) {
-                                               work_int = (int) ((mic_gain +10.0)* 100.0/60.0);
-                                               sprintf(msg,"MG%03d;",work_int);
-                                               send_resp(client_sock,msg);
-                                            } else {
-                                               int tval = atoi(&cmd_input[2]);                
-                                               new_vol = (double) (tval * 60/100) - 10; 
-                                               //set_mic_gain(new_vol); 
-                                               double *p_mic_gain=malloc(sizeof(double));
-                                               *p_mic_gain=new_vol;
-                                               g_idle_add(update_mic_gain,(void *)p_mic_gain);
-                                            }
-                                         }
-        else if(strcmp(cmd_str,"ML")==0) {  // Set/read the monitor function level
-                                             if(len <=2) {
-                                               send_resp(client_sock,"ML000;"); 
-                                             }
-                                         }
-        else if(strcmp(cmd_str,"MO")==0) {  // Set Monitor on/off
-                                             if(len <=2) {
-                                               send_resp(client_sock,"MO0;"); 
-                                             }
-                                         }
-        /* Not supported */
-        else if(strcmp(cmd_str,"MR")==0) {  // Read Memory Channel data
-                                             sprintf(msg,"MR%1d%02d%02d%011lld%1d%1d%1d%02d%02d%03d%1d%1d%09d%02d%1d%08d;",
-                                                      0, // P1 - Rx Freq - 1 Tx Freq
-                                                      0, // P2 Bankd and channel number -- see MC comment
-                                                      0, // P3 - see MC comment 
-                                                      rigctl_getFrequency(), // P4 - frequency
-                                                      rigctlGetMode(), // P5 - Mode
-                                                      locked, // P6 - Locked status
-                                                      0, // P7 - O-off, 1-tone, 2-CTCSS, 3 =DCS
-                                                      0, // P8 - Tone Number - see page 35
-                                                      ctcss_tone, // P9 - CTCSS tone number - see CN command
-                                                      0, // P10 - DCS code - see QC command 
-                                                      0, // P11 - Reverse status
-                                                      0, // P12 - Shift status - see OS command
-                                                      0, // P13 - Offset freq - see OS command
-                                                      0, // P14 - Step Size - see ST command
-                                                      0, // P15 - Memory Group Number (0-9)
-                                                      0);  // P16 - Memory Name - 8 char max
-                                               //send_resp(client_sock,msg);
-                                               send_resp(client_sock,"?;");
-                                         }
-        else if(strcmp(cmd_str,"MU")==0) {  // Set/Read Memory Group Data
-                                             if(len <=2) {
-                                               send_resp(client_sock,"MU0000000000;"); 
-                                             }
-                                         }
-        else if(strcmp(cmd_str,"MW")==0) {  // Store Data to Memory Channel
-                                         }
-        else if(strcmp(cmd_str,"NB")==0) {  // Set/Read Noise Blanker func status (on/off)
-                                             if(len <=2) {
-                                               sprintf(msg,"NB%1d;",active_receiver->snb);
                                                send_resp(client_sock,msg);
                                              } else {
-                                               if(cmd_input[2]=='0') { // Turn off ANF
-                                                  active_receiver->snb=0;
-                                               } else { // Turn on ANF
-                                                  active_receiver->snb=1;
+                                               if((atoi(&cmd_input[2]) >=0) && (atoi(&cmd_input[2]) <=1)) {
+                                                  if(cmd_input[2] == '0') { // Clear ANF
+                                                    active_receiver->anf = 0;
+                                                  } else { // Set ANF
+                                                    active_receiver->anf = 1;
+                                                  }
+                                               } else {
+                                                  send_resp(client_sock,"?;"); 
                                                }
-                                               // Update filters
-                                               SetRXASNBARun(active_receiver->id, active_receiver->snb);
-                                               g_idle_add(vfo_update,NULL);
                                              }
-                                         }
-        else if(strcmp(cmd_str,"NL")==0) {  // Set/Read Noise Reduction  Level
-                                             if(len <=2) {
-                                               send_resp(client_sock,"NL000;"); 
+                                             SetRXAANFRun(active_receiver->id, active_receiver->anf);
+                                             g_idle_add(ext_vfo_update,NULL);
+                                         }
+        else if((strcmp(cmd_str,"OA")==0) && (zzid_flag ==1)) {  
+                                            // PiHPSDR - ZZOA - Set/Read RX Antenna by band
+                                            //           P1P1P1 - Band
+                                            //           P2 - 1,2,3,EXT1,EXT2, XVTR
+                                             int int_band;
+                                             int b;
+                                             if(len<=5) {
+                                                int_band = atoi(&cmd_input[2]);
+                                               #ifdef RIGCTL_DEBUG
+                                                fprintf(stderr,"RIGCTL OA band =%d\n",int_band);
+                                                #endif
+                                                //b = lookup_band(int_band);
+                                                BAND *band=band_get_band(int_band);
+                                                work_int = band->alexRxAntenna;
+                                                sprintf(msg,"ZZOA%03d%1d;",int_band,work_int);
+                                                send_resp(client_sock,msg);
+                                             } else {
+                                                char lcl_char = cmd_input[5];
+                                                cmd_input[5] = '\0';
+                                                b = atoi(&cmd_input[2]);
+                                                //b = lookup_band(int_band);
+                                                cmd_input[5] = lcl_char;
+                                                work_int = atoi(&cmd_input[5]);
+                                                if(work_int >=0 && work_int <=5) {
+                                                  #ifdef RIGCTL_DEBUG
+                                                   fprintf(stderr,"RIGCTL ZZOA Band=%d Val=%d\n",b,work_int);
+                                                   #endif
+                                                   BAND *band=band_get_band(b);
+                                                   band->alexRxAntenna = work_int;
+                                                } else {
+                                                   fprintf(stderr,"RIGCTL ZZOA illegal val Band=%d Val=%d\n",int_band,work_int);
+                                                }
                                              }
                                          }
-        else if(strcmp(cmd_str,"NR")==0) {  // Set/Read Noise Reduction function status
-                                            if(len <=2) {
-/*
-                                              if(nr_none == 1) {
-                                                  send_resp(client_sock,"NR0;"); 
-                                              } else if ((nr_none == 0) && (nr==1)) { 
-                                                  send_resp(client_sock,"NR1;"); 
-                                              } else if (nr2 == 1) { 
-                                                  send_resp(client_sock,"NR2;"); 
-                                              } else {
-                                                  send_resp(client_sock,"NR0;"); 
-                                              }
-*/
+        else if((strcmp(cmd_str,"OB")==0) && (zzid_flag ==1)) {  
+                                            // PiHPSDR - ZZOB - Set/Read TX Antenna by band
+                                            //           P1P1P1 - Band
+                                            //           P2 - 1,2,3
+                                             int int_band;
+                                             int b ;
+                                             if(len<=5) {
+                                                int_band = atoi(&cmd_input[2]);
+                                                //b = lookup_band(int_band);
+                                                b = int_band;
+                                                BAND *band=band_get_band(b);
+                                                work_int = band->alexTxAntenna;
+                                                sprintf(msg,"ZZOB%03d%1d;",int_band,work_int);
+                                                send_resp(client_sock,msg);
 
-                                              // FIX now allow multiple set
-                                              if (active_receiver->nr==1) { 
-                                                send_resp(client_sock,"NR1;"); 
-                                              } else {
-                                                send_resp(client_sock,"NR0;"); 
-                                              }
-                                            } else {
-                                               if(cmd_input[2] == '0') {
-                                                  active_receiver->nr = 0;
-                                                  active_receiver->nr2 = 0;
-                                               } else if(cmd_input[2] == '1') {
-                                                  active_receiver->nr = 1;
-                                               } else if(cmd_input[2] == '2') {
-                                                  active_receiver->nr2 = 1;
-                                               }
-                                               SetRXAANRRun(active_receiver->id, active_receiver->nr);
-                                               SetRXAEMNRRun(active_receiver->id, active_receiver->nr2);
-                                               g_idle_add(vfo_update,NULL);
-                                            } 
-                                         }
-        else if(strcmp(cmd_str,"NT")==0) {  // Set/Read autonotch function
-                                             if(len <=2) {
-                                               sprintf(msg,"NT%1d;",active_receiver->anf);
-                                               send_resp(client_sock,msg);
                                              } else {
-                                               if(cmd_input[2] == '0') { // Clear ANF
-                                                 active_receiver->anf = 0;
-                                               } else { // Set ANF
-                                                 active_receiver->anf = 1;
-                                               }
+                                                char lcl_char = cmd_input[5];
+                                                cmd_input[5] = '\0';
+                                                int_band = atoi(&cmd_input[2]);
+                                                //b = lookup_band(int_band);
+                                                b = int_band;
+                                                cmd_input[5] = lcl_char;
+                                                work_int = atoi(&cmd_input[5]);
+                                                if(work_int >=0 && work_int <=2) {
+                                                  #ifdef RIGCTL_DEBUG
+                                                   fprintf(stderr,"RIGCTL ZZOB Band=%d Val=%d\n",int_band,work_int);
+                                                   #endif
+                                                   BAND *band=band_get_band(b);
+                                                   band->alexTxAntenna = work_int;
+                                                } else {
+                                                   fprintf(stderr,"RIGCTL ZZOB illegal val Band=%d Val=%d\n",int_band,work_int);
+                                                }
                                              }
-                                             SetRXAANFRun(active_receiver->id, active_receiver->anf);
-                                             g_idle_add(vfo_update,NULL);
                                          }
-        else if(strcmp(cmd_str,"OF")==0) {  // Set/Read Offset freq (9 digits - hz)
+        else if((strcmp(cmd_str,"OF")==0) && (zzid_flag == 0)) {  
+                                            // TS-2000 - OF - Set/Read Offset freq (9 digits - hz) -not supported
                                              if(len <=2) {
-                                               send_resp(client_sock,"OF000000000;"); 
+                                               //send_resp(client_sock,"OF000000000;"); 
+                                               send_resp(client_sock,"?;"); 
                                              }
                                          }
         /* Not Supported */
-        else if(strcmp(cmd_str,"OI")==0) {  // Read Memory Channel Data
-                                             if(len <=2) {
+        else if((strcmp(cmd_str,"OI")==0) && (zzid_flag == 0)) {  
+                                            // TS-2000 - OI - Read Memory Channel Data - not supported
+                                             /*if(len <=2) {
                                                sprintf(msg,"OI%011lld%04d%06d%1d%1d%1d%02d%1d%1d%1d%1d%1d%1d%02d%1d;",
                                                   rigctl_getFrequency(),
                                                   0, // P2 - Freq Step size
@@ -1043,146 +2619,295 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                                                   0, // P13 Off, 1, 2, 
                                                   0,// P14 Tone freq - See TN command
                                                   0,0);
+                                              */
                                                send_resp(client_sock,"?;");
-                                             }
                                          }
-        else if(strcmp(cmd_str,"OS")==0) {  // Set/Read Offset freq (9 digits - hz)
+        else if(strcmp(cmd_str,"OS")==0) {  
+                                            // TS-2000 - OS - Set/Read Offset freq (9 digits - hz) -not supported
                                              if(len <=2) {
                                                //send_resp(client_sock,"OS0;"); 
                                                send_resp(client_sock,"?;"); 
                                              }
                                          }
-        else if(strcmp(cmd_str,"PA")==0) {  // Set/Read Preamp function status
+        else if(strcmp(cmd_str,"PA")==0) { 
+                                            // TS-2000 - PA - Set/Read Preamp function status
+                                            // PiHPSDR - ZZPA - Set/Read Preamp function status
                                              if(len <=2) {
-                                               sprintf(msg,"PA0%1d;",enable_tx_equalizer);
+                                                if(zzid_flag == 0) {
+                                                   sprintf(msg,"PA%1d%1d;",active_receiver->preamp,active_receiver->preamp);
+                                                } else {
+                                                   sprintf(msg,"ZZPA%1d;",active_receiver->preamp);
+                                                }
                                                send_resp(client_sock,msg);
                                              } else {
-                                                if(cmd_input[2] =='0') {
-                                                  enable_tx_equalizer=0;
-                                                  SetTXAEQRun(transmitter->id, enable_tx_equalizer);
+                                                work_int = atoi(&cmd_input[2]);
+                                                if((work_int >= 0) && (work_int <= 1)) {
+                                                    active_receiver->preamp = work_int;  
                                                 } else {
-                                                  enable_tx_equalizer=1;
-                                                  SetTXAEQRun(transmitter->id, enable_tx_equalizer);
+                                                    send_resp(client_sock,"?;");
                                                 }
                                              }
                                          }
-        else if(strcmp(cmd_str,"PB")==0) {  // Set/Read DRU-3A Playback status
+        else if(strcmp(cmd_str,"PB")==0) { 
+                                            // TS-2000 - PB - DRU-3A Playback status - not supported
                                              if(len <=2) {
-                                               send_resp(client_sock,"PB0;"); 
+                                               send_resp(client_sock,"?;"); 
                                              }
                                          }
-        else if(strcmp(cmd_str,"PC")==0) {  // Set/Read Drive Power output
+        else if(strcmp(cmd_str,"PC")==0) {  
+                                            // TS-2000 - PC - Set/Read Drive Power output
+                                            // PiHPSDR - ZZPC - Set/Read Drive Power output
                                             if(len<=2) {
-                                              sprintf(msg,"PC%03d;",(int) drive);
+                                                if(zzid_flag == 0) {
+                                                  sprintf(msg,"PC%03d;",(int) transmitter->drive);
+                                                } else {
+                                                  sprintf(msg,"ZZPC%03d;",(int) transmitter->drive);
+                                                }
                                               send_resp(client_sock,msg); 
                                             } else {
-                                               // Power Control - 3 digit number- 0 to 100
-                                               //Scales to 0.00-1.00
+                                              int lcl_pc = atoi(&cmd_input[2]); 
+                                             #ifdef RIGCTL_DEBUG
+                                              fprintf(stderr,"RIGCTL: PC received=%d\n",lcl_pc);
+                                              #endif
+                                              if((lcl_pc >=0) && (lcl_pc<=100)) {
+                                                  // Power Control - 3 digit number- 0 to 100
+                                                  //Scales to 0.00-1.00
                                                 
-                                               double drive_val = 
-                                                   (double)(atoi(&cmd_input[2])); 
-                                               // setDrive(drive_val);
-                                               double *p_drive=malloc(sizeof(double));
-                                               *p_drive=drive_val;
-                                               g_idle_add(update_drive,(gpointer)p_drive);
-                                               //set_drive(drive_val);
+                                                  double drive_val = 
+                                                      (double)(atoi(&cmd_input[2])); 
+                                                  // setDrive(drive_val);
+                                                  double *p_drive=malloc(sizeof(double));
+                                                  *p_drive=drive_val;
+                                                  g_idle_add(update_drive,(gpointer)p_drive);
+                                                  //set_drive(drive_val);
+                                              } else {
+                                                  fprintf(stderr,"RIGCTL: PC received=%d - Illegal value\n",lcl_pc);
+                                                  send_resp(client_sock,"?;");
+                                              }
                                             }
                                          }
-        else if(strcmp(cmd_str,"PI")==0) {  // STore the programmable memory channel
+        else if((strcmp(cmd_str,"PI")==0) && (zzid_flag == 0)) 
+                                         {  
+                                            // TS-2000 - PI - Store the programmable memory channel - not supported
                                          }
-        else if(strcmp(cmd_str,"PK")==0) {  // Reads the packet cluster data
-                                             //  send_resp(client_sock,"PK000000000000000000000000000000000000000000000000;"); 
+        else if(strcmp(cmd_str,"PK")==0) {  
+                                            // TS-2000 - PK - Reads the packet cluster data - not supported
+                                            //  send_resp(client_sock,"PK000000000000000000000000000000000000000000000000;"); 
                                              send_resp(client_sock,"?;"); 
                                             
                                          }
-        else if(strcmp(cmd_str,"PL")==0) {  // Set/Read Speech processor level
+        else if((strcmp(cmd_str,"PL")==0) && (zzid_flag == 0)) {  
+                                            // TS-2000 - PL - Set/Read Speech processor level 
+                                            // PL 000 000 ;
                                             // P1 000 - min-100 max
                                             // P2 000 - min - 100 max
+                                             double lcl_comp_level;
                                              if(len <=2) {
                                              //  send_resp(client_sock,"PL000000;"); 
-                                                send_resp(client_sock,"?;"); 
+                                                lcl_comp_level = 100 *(transmitter->compressor_level)/20;
+                                                sprintf(msg,"PL%03d000;",(int)lcl_comp_level);
+                                                send_resp(client_sock,msg); 
+                                             } else {
+                                                // Isolate 1st command
+                                                cmd_input[5] = '\0';
+                                                lcl_comp_level = 20.0 *(((double)atoi(&cmd_input[2]))/100.0);
+                                               #ifdef RIGCTL_DEBUG
+                                                fprintf(stderr,"RIGCTL - PR new level=%f4.1",lcl_comp_level);
+                                                #endif
+                                                transmitter_set_compressor_level(transmitter,lcl_comp_level);
+                                                g_idle_add(ext_vfo_update,NULL);
+                                                //transmitter->compressor_level = lcl_comp_level;
                                              }
                                          }
-        else if(strcmp(cmd_str,"PM")==0) {  // Recalls the Programmable memory
+        else if((strcmp(cmd_str,"PM")==0) && ( zzid_flag == 0)) {  
+                                            // TS-2000 - PM - Recalls the Programmable memory - not supported
                                              if(len <=2) {
                                                //send_resp(client_sock,"PM0;"); 
                                                send_resp(client_sock,"?;"); 
                                              }
                                          }
-        else if(strcmp(cmd_str,"PR")==0) {  // Sets/reads the speech processor function on/off
+        else if((strcmp(cmd_str,"PR")==0) && (zzid_flag == 0)) {  
+                                            // TS-2000 - PR - Sets/reads the speech processor function on/off 
                                             // 0 - off, 1=on
                                              if(len <=2) {
-                                               //send_resp(client_sock,"PR0;"); 
-                                               send_resp(client_sock,"?;"); 
+                                               sprintf(msg,"PR%01d;",transmitter->compressor);
+                                               send_resp(client_sock,msg);
+                                             } else {
+                                               transmitter_set_compressor(transmitter,atoi(&cmd_input[2]));
+                                               g_idle_add(ext_vfo_update,NULL);
+                                               //transmitter->compressor = atoi(&cmd_input[2]);
                                              }
                                          }
-        else if(strcmp(cmd_str,"PS")==0) {  // Sets/reads Power on/off state
+        else if(strcmp(cmd_str,"PS")==0) {  
+                                            // PiHPSDR - ZZPS - Sets/reads Power on/off state- always on
+                                            // TS-2000 - PS - Sets/reads Power on/off state
                                             // 0 - off, 1=on
                                              if(len <=2) {
                                                send_resp(client_sock,"PS1;"); // Lets pretend we're powered up ;-) 
                                              }
                                          }
-        else if(strcmp(cmd_str,"QC")==0) {  // Sets/reads DCS code
+        else if(strcmp(cmd_str,"PZ")==0) {   if(zzid_flag == 1) {  
+                                            // PiHPSDR - ZZPZ - Sets/Reads  Radio Sample Rate
+                                            // Valid values are 048000, 096000, 192000, 384000
+                                               #ifdef RIGCTL_DEBUG
+                                                 fprintf(stderr,"ZZPZ command\n");
+                                                #endif 
+                                                 if(len<=2) {
+                                                 sprintf(msg,"ZZPZ%06d;",active_receiver->sample_rate);
+                                                 send_resp(client_sock,msg);
+                                                 } else {
+                                                   long lcl_rate = atoi(&cmd_input[2]);
+                                                  #ifdef RIGCTL_DEBUG
+                                                   fprintf(stderr,"ZZPZ Set=%ld\n",lcl_rate);
+                                                   #endif
+                                                   if (lcl_rate !=48000L && lcl_rate !=96000L  &&
+                                                       lcl_rate !=192000L && lcl_rate != 384000L) {
+                                                      fprintf(stderr,"RIGCTL: ZZPZ - illegal frequency=%ld\n",lcl_rate);
+                                                      send_resp(client_sock,"?;");
+                                                      return;
+                                                   }
+                                                   
+                                                   g_idle_add(ext_radio_change_sample_rate,(gpointer)(long)lcl_rate);
+                                                   g_idle_add(ext_vfo_update,NULL);
+                                                 }
+                                              } 
+                                         }
+        else if(strcmp(cmd_str,"QC")==0) {  
+                                            // TS-2000 - QC - Sets/reads DCS code - not supported
                                             // Codes numbered from 000 to 103.
                                              if(len <=2) {
-                                               //send_resp(client_sock,"QC000;"); // Lets pretend we're powered up ;-) 
+                                               //send_resp(client_sock,"QC000;"); 
                                                send_resp(client_sock,"?;"); 
                                              }
                                          }
-        else if(strcmp(cmd_str,"QI")==0) {  // Store the settings in quick memory
+        else if(strcmp(cmd_str,"QI")==0) {  
+                                            // TS-2000 - QI - Store the settings in quick memory - not supported
                                          }
-        else if(strcmp(cmd_str,"QR")==0) {  // Send the Quick memory channel data
+        else if(strcmp(cmd_str,"QR")==0) {  
+                                            // TS-2000 - QR - Send the Quick memory channel data - not supported
                                             // P1 - Quick mem off, 1 quick mem on
                                             // P2 - Quick mem channel number
                                              if(len <=2) {
-                                               //send_resp(client_sock,"QR00;"); // Lets pretend we're powered up ;-) 
+                                               //send_resp(client_sock,"QR00;"); 
                                                send_resp(client_sock,"?;"); 
                                              }
                                          }
-        else if(strcmp(cmd_str,"RA")==0) {  // Sets/reads Attenuator function status
+        else if((strcmp(cmd_str,"RA")==0) && (zzid_flag == 0)) {  
+                                            // TS-2000 - RA - Sets/reads Attenuator function status
                                             // 00-off, 1-99 -on - Main and sub receivers reported
+                                            int lcl_attenuation;
+                                            float calc_atten;
                                              if(len <=2) {
                                                //send_resp(client_sock,"RA0000;"); 
-                                               send_resp(client_sock,"?;"); 
+                                               calc_atten = round((float)active_receiver->attenuation*99.0/30.0);
+                                               if(calc_atten > 99.0) {
+                                                  calc_atten = 99.0;
+                                               } 
+                                               sprintf(msg,"RA%02d%02d;",(int)calc_atten,(int)calc_atten); 
+                                               send_resp(client_sock,msg);
+                                             } else {
+                                                lcl_attenuation = atoi(&cmd_input[2]); 
+                                                if((lcl_attenuation >=0) && (lcl_attenuation <= 99)) {
+                                                  lcl_attenuation = (int)((float)lcl_attenuation * 30.0/99.0);
+                                                 #ifdef RIGCTL_DEBUG
+                                                  fprintf(stderr,"RIGCTL: lcl_att=%d\n",lcl_attenuation);
+                                                  #endif
+                                                  //set_attenuation(lcl_attenuation);
+                                                  set_attenuation_value((double) lcl_attenuation);
+                                                  g_idle_add(ext_vfo_update,NULL);
+                                                } else {
+                                                  send_resp(client_sock,"?;"); 
+                                                }
                                              }
                                          }
-        else if(strcmp(cmd_str,"RC")==0) {  // Clears the RIT offset freq
-                                         }
-        else if(strcmp(cmd_str,"RD")==0) {  // Move the RIT offset freq down, slow down the scan speed in scan mode
-                                             if(len <=2) {
-                                               vfo[active_receiver->id].rit = vfo[active_receiver->id].rit-rit_increment;
-                                               sprintf(msg,"RD%1d;",rit_on());
-                                               send_resp(client_sock,msg);
+        else if(strcmp(cmd_str,"RC")==0) {  
+                                            // TS-2000 - RC - Clears the RIT offset freq
+                                            // PiHPSDR - ZZRC - Clears the RIT offset freq
+                                            vfo[active_receiver->id].rit = 0;
+                                            g_idle_add(ext_vfo_update,NULL);
+                                         }
+        else if(strcmp(cmd_str,"RD")==0) {  // 
+                                            // TS-2000 - RD - Move the RIT offset freq down - P1=rit_increment! 
+                                            //                P1=No Argument - decrement frequency
+                                            //                P1=NonZero - load rit offset
+                                            //                FS controls fine variable 1 or 0. rit increment 1 hz or 10hz
+                                            // PiHPSDR - ZZRD - Move the RIT offset freq down by rit_increment
+                                             int lcl_rit;
+                                             int lcl_rit_increment = fine ? 1 : 10;
+                                             if(len <=2) {
+                                               vfo[active_receiver->id].rit = vfo[active_receiver->id].rit-lcl_rit_increment;
                                              } else {
                                                 if(len > 3) {
-                                                   // Non scan mode when RDxxxxx; - 
-                                                   vfo[active_receiver->id].rit = vfo[active_receiver->id].rit-rit_increment;
+                                                   lcl_rit = atoi(&cmd_input[2]);   
+                                                   if((lcl_rit >=0) &&(lcl_rit <=99999)) {
+                                                       vfo[active_receiver->id].rit = -lcl_rit;
+                                                   } else {
+                                                       send_resp(client_sock,"?;");
+                                                   }
                                                 } 
                                              }
-                                             g_idle_add(vfo_update,NULL);
-                                         }
-        else if(strcmp(cmd_str,"RG")==0) {  // RF Gain - 3 digit number
-                                            // RG123; 0-255 value
-                                            // Scale from -20 - 120
-                                            if(len>4) { // Set Audio Gain
-                                               int base_value = atoi(&cmd_input[2]);
-                                               double new_gain = ((((double) base_value)/255) * 140) - 20; 
-                                               //set_agc_gain(new_gain);               
-                                               double *p_gain=malloc(sizeof(double));
-                                               *p_gain=new_gain;
-                                               g_idle_add(update_agc_gain,(gpointer)p_gain);
-                                            } else { // Read Audio Gain
-                                              sprintf(msg,"RG%03d;",((256 * (int) active_receiver->agc_gain)/140)+36);
-                                              send_resp(client_sock,msg);
+                                             g_idle_add(ext_vfo_update,NULL);
+                                         }
+        else if((strcmp(cmd_str,"RF")==0) && (zzid_flag == 1)) {  
+                                            // PiHPSDR - ZZRR - Read Forward Power
+                                            forward = transmitter->fwd;
+                                            sprintf(msg,"RF%09.7f;",forward);
+                                            send_resp(client_sock,msg);
+                                         }
+        else if(strcmp(cmd_str,"RG")==0) {  
+                                            // TS-2000 - RG - RF Gain Control
+                                            // PiHPSDR - ZZRG - AGC Gain Control -20 to 120 legal range
+                                            // TS 2000 settings 0-255 value scaled to -20 to 120 range
+                                            if(zzid_flag == 0) {
+                                              if(len>4) { // Set Audio Gain
+                                                 int base_value = atoi(&cmd_input[2]);
+                                                 double new_gain = roundf(((((double) base_value+1)/256.0) * 141.0))- 21.0; 
+                                                 //set_agc_gain(new_gain);               
+                                                 double *p_gain=malloc(sizeof(double));
+                                                 *p_gain=new_gain;
+                                                 g_idle_add(ext_update_agc_gain,(gpointer)p_gain);
+                                              } else { // Read Audio Gain
+                                                 double lcl_gain = (active_receiver->agc_gain+21.0)/141.0;
+                                                 sprintf(msg,"RG%03d;",(int)((256.0 * lcl_gain) -1));
+                                                 send_resp(client_sock,msg);
+                                              }
+                                            } else {
+                                              // Pi HPSDR  version
+                                              if(len <= 2) {
+                                                 if(active_receiver->agc_gain<0) {
+                                                    sprintf(msg,"ZZRG-%03d;",(int) abs((int)active_receiver->agc_gain));
+                                                 } else {
+                                                     sprintf(msg,"ZZRG+%03d;",(int)active_receiver->agc_gain);
+                                                 }
+                                                 send_resp(client_sock,msg);
+                                                 
+                                              } else {
+                                                 work_int = atoi(&cmd_input[3]);
+                                                 if(cmd_input[2] == '-') {  // Negative number found
+                                                    work_int = -work_int;
+                                                 }
+                                                 if((work_int >= -20) && (work_int <=120)) {
+                                                    double *p_gain=malloc(sizeof(double));
+                                                    *p_gain=(double) work_int;
+                                                    g_idle_add(ext_update_agc_gain,(gpointer)p_gain);
+                                                 } else {
+                                                    fprintf(stderr,"RIGCTL: ZZRG ERROR - Illegal AGC Value=%d\n", work_int);
+                                                    send_resp(client_sock,"?;");
+                                                 }
+                                              }
                                             }
+                                            g_idle_add(ext_vfo_update,NULL);
                                          }
-        else if(strcmp(cmd_str,"RL")==0) {  // Set/read Noise reduction level
+        else if((strcmp(cmd_str,"RL")==0) && (zzid_flag == 0)) {  
+                                            // TS-2000 - RL - Set/read Noise reduction level - not supported
                                              if(len <=2) {
                                                //send_resp(client_sock,"RL00;"); 
                                                send_resp(client_sock,"?;"); 
                                              }
                                          }
-        else if(strcmp(cmd_str,"RM")==0) {  // Set/read Meter function
+        else if((strcmp(cmd_str,"RM")==0) && (zzid_flag == 0)) {  
+                                            // TS-2000 - RM - Set/read Meter function - not supported
                                             // P1- 0, unsel, 1 SWR, 2 Comp, 3 ALC
                                             // P2 - 4 dig - Meter value in dots - 000-0030
                                              if(len <=2) {
@@ -1190,88 +2915,147 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                                                send_resp(client_sock,"?;"); 
                                              }
                                          }
-        else if(strcmp(cmd_str,"RT")==0) {  // Set/read the RIT function status
+        else if((strcmp(cmd_str,"RR")==0) && (zzid_flag == 1)) {  
+                                            // PiHPSDR - ZZRR - Read Reverse Power
+                                            reverse = transmitter->rev;
+                                            sprintf(msg,"RR%09.7f;",reverse);
+                                            send_resp(client_sock,msg);
+                                         }
+        else if((strcmp(cmd_str,"RS")==0) && (zzid_flag == 1)) {  
+                                            // PiHPSDR - ZZRS - Read SWR
+                                            forward = transmitter->fwd;
+                                            reverse = transmitter->rev;
+                                            vswr = (forward+reverse)/(forward-reverse);
+                                            sprintf(msg,"RS%04.2f;",vswr);
+                                            send_resp(client_sock,msg);
+                                         }   
+        else if(strcmp(cmd_str,"RT")==0) {  
+                                            // TS-2000 - RT - Set/read the RIT function status
+                                            // PiHPSDR - ZZRT - Set/read the RIT function status
+                                             int lcl_rit_val;
                                              if(len <=2) {
-                                               sprintf(msg,"RT%01d;",rit_on());
-                                               send_resp(client_sock,msg); 
+                                                if(zzid_flag == 0) {
+                                                    sprintf(msg,"RT%01d;",rit_on());
+                                                } else {
+                                                    sprintf(msg,"ZZRT%01d;",rit_on());
+                                                }
+                                                send_resp(client_sock,msg); 
                                              } else {
-                                                if(atoi(&cmd_input[2]) == 0) {
-                                                   vfo[active_receiver->id].rit = 0;
+                                                lcl_rit_val = atoi(&cmd_input[2]);
+                                                if((lcl_rit_val >=0) && (lcl_rit_val <=1)) {
+                                                   vfo[active_receiver->id].rit = lcl_rit_val;
+                                                } else {
+                                                   send_resp(client_sock,"?;"); 
                                                 }
                                              }
                                          }
-        else if(strcmp(cmd_str,"RU")==0) {  // Set/move RIT frequency up
+        else if(strcmp(cmd_str,"RU")==0) {  
+                                            // TS-2000 - RU - Set/move RIT frequency up
+                                            // PiHPSDR - ZZRU - Set/move RIT frequency up
+                                             int lcl_incr;
                                              if(len <=2) {
-                                               vfo[active_receiver->id].rit = vfo[active_receiver->id].rit+rit_increment;
-                                               sprintf(msg,"RU%01d;",rit_on());
-                                               send_resp(client_sock,msg);
+                                               lcl_incr = fine ? 1 : 10;
+                                               vfo[active_receiver->id].rit = vfo[active_receiver->id].rit+lcl_incr;
                                              } else {
                                                 if(len > 3) {
-                                                   vfo[active_receiver->id].rit = vfo[active_receiver->id].rit+rit_increment;
+                                                   lcl_incr = atoi(&cmd_input[2]);    
+                                                   if((lcl_incr >=0) && (lcl_incr <= 99999)) {
+                                                      vfo[active_receiver->id].rit = lcl_incr;
+                                                   } else {
+                                                      send_resp(client_sock,"?;"); 
+                                                   }
                                                 } 
                                              }
-                                             g_idle_add(vfo_update,NULL);
+                                             g_idle_add(ext_vfo_update,NULL);
                                          }
-        else if(strcmp(cmd_str,"RX")==0) {  // Unkey Xmitter
+        else if(strcmp(cmd_str,"RX")==0) {  
+                                            // TS-2000 - RX - Unkey Xmitter
+                                            // PiHPSDR - ZZRX - Unkey Xmitter
                                             //setMox(0);
-                                            mox_state=0;
-                                            g_idle_add(mox_update,(gpointer)mox_state); 
-                                            g_idle_add(vfo_update,NULL);
+                                            if(!((vfo[active_receiver->id].mode == modeCWL) ||
+                                                 (vfo[active_receiver->id].mode == modeCWU))) {
+                                              #ifdef RIGCTL_DEBUG
+                                               fprintf(stderr, "RIGCTL: Inside RX command\n");
+                                               #endif
+                                               mox_state=0;
+                                               g_idle_add(ext_mox_update,(gpointer)(long)mox_state); 
+                                               g_idle_add(ext_vfo_update,NULL);
+                                            } else {
+                                               // Clear External MOX in CW mode
+                                               g_idle_add(ext_mox_update,(gpointer)(long)0); // Turn on xmitter (set Mox)
+                                            }
                                          }
-        else if(strcmp(cmd_str,"SA")==0) {  // Set/reads satellite mode status
+        else if(strcmp(cmd_str,"SA")==0) {  
+                                            // TS-2000 - SA - Set/reads satellite mode status - not supported
                                             // 0-main, 1=sub
                                              if(len <=2) {
                                                //send_resp(client_sock,"SA000000000000000;"); 
                                                send_resp(client_sock,"?;"); 
                                              }
                                          }
-        else if(strcmp(cmd_str,"SB")==0) {  // Set/read the SUB TF-W status
+        else if(strcmp(cmd_str,"SB")==0) {  
+                                            // TS-2000 - SB - Set/read the SUB TF-W status - not supported
                                              if(len <=2) {
                                                //send_resp(client_sock,"SB0;"); 
                                                send_resp(client_sock,"?;"); 
                                              }
                                          }
-        else if(strcmp(cmd_str,"SC")==0) {  // Set/read the Scan function status
+        else if(strcmp(cmd_str,"SC")==0) {  
+                                            // TS-2000 - SC - Set/read the Scan function status - not supported
                                              if(len <=2) {
                                                //send_resp(client_sock,"SC0;"); 
                                                send_resp(client_sock,"?;"); 
                                              }
                                          }
-        else if(strcmp(cmd_str,"SD")==0) {  // Set/read CW break-in time delay
+        else if((strcmp(cmd_str,"SD")==0) && (zzid_flag == 0) ||  
+                (strcmp(cmd_str,"CD")==0) && (zzid_flag ==1)) {  
+                                            // PiHPSDR - ZZCD - Set/Read CW Keyer Hang Time
+                                            // TS-2000 - SD - Set/Read Break In Delay
+                                            // 
                                             // 0000-1000 ms (in steps of 50 ms) 0000 is full break in
-                                             int local_cw_breakin=cw_keyer_hang_time;
-                                             // Limit report value to 1000 for TS-2000
-                                             if(local_cw_breakin > 1000) { local_cw_breakin = 1000; }
-                                             if(len <=2) {
-                                               sprintf(msg,"SD%04d;",local_cw_breakin);
-                                               send_resp(client_sock,msg);
-                                             } else {
-                                               local_cw_breakin = atoi(&cmd_input[2]); 
-                                               if(cw_keyer_hang_time <= 1000) {
-                                                  if(local_cw_breakin==0) {
-                                                      cw_breakin = 1;
-                                                  }  else {
-                                                      cw_breakin = 0;
-                                                  } 
-                                                  cw_keyer_hang_time = local_cw_breakin; 
-                                               }
-                                             }
+                                                int local_cw_breakin=cw_keyer_hang_time;
+                                                // Limit report value to 1000 for TS 2000
+                                                if(local_cw_breakin > 1000) { local_cw_breakin = 1000; }
+                                                if(len <=2) {
+                                                  if(zzid_flag == 0) { // TS 2000
+                                                       sprintf(msg,"SD%04d;",local_cw_breakin);
+                                                  } else {   // ZZ command response
+                                                       sprintf(msg,"ZZCD%04d;",local_cw_breakin);
+                                                  }
+                                                  send_resp(client_sock,msg);
+                                                } else {
+                                                  local_cw_breakin = atoi(&cmd_input[2]); 
+                                                  if(cw_keyer_hang_time <= 1000) {
+                                                     if(local_cw_breakin==0) {
+                                                         cw_breakin = 1;
+                                                     }  else {
+                                                         cw_breakin = 0;
+                                                     } 
+                                                     cw_keyer_hang_time = local_cw_breakin; 
+                                                 }
+                                                }
+                                             
                                          }
-        else if(strcmp(cmd_str,"SH")==0) {  // Set/read the DSP filter settings
+        else if(strcmp(cmd_str,"SH")==0) {  
+                                            // TS-2000 - SH - Set/read the DSP filter settings - not supported
                                              if(len <=2) {
                                               // send_resp(client_sock,"SH00;"); 
                                                send_resp(client_sock,"?;"); 
                                              }
                                          }
-        else if(strcmp(cmd_str,"SI")==0) {  // Enters the satellite memory name
+        else if(strcmp(cmd_str,"SI")==0) {  
+                                            // TS-2000 - SI - Enters the satellite memory name - not supported
                                          }
-        else if(strcmp(cmd_str,"SL")==0) {  // Set/read the DSP filter settings - this appears twice? See SH
+        else if(strcmp(cmd_str,"SL")==0) {  
+                                            // TS-2000 - SL - Set/read the DSP filter settings - not supported
                                              if(len <=2) {
                                                //send_resp(client_sock,"SL00;");
                                                send_resp(client_sock,"?;"); 
                                              } 
                                          }
-        else if(strcmp(cmd_str,"SM")==0) {  // Read SMETER
+        else if(strcmp(cmd_str,"SM")==0) {  
+                                            // PiHPSDR - ZZSM - Read SMeter - same range as TS 2000
+                                            // TI-2000 - SM - Read SMETER
                                             // SMx;  x=0 RX1, x=1 RX2 
                                             // meter is in dbm - value will be 0<260
                                             // Translate to 00-30 for main, 0-15 fo sub
@@ -1307,35 +3091,69 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                                                if(new_level < 0) { new_level = 0; }
                                                if(new_level > 15) { new_level = 15;}
                                             }
-                                            sprintf(msg,"SM%1c%04d;",
-                                                cmd_input[2],new_level);
+                                            if(zzid_flag == 0) {
+                                               sprintf(msg,"SM%1c%04d;",
+                                                           cmd_input[2],new_level);
+                                            } else {
+                                               sprintf(msg,"ZZSM%1c%04d;",
+                                                           cmd_input[2],new_level);
+                                            }
                                             send_resp(client_sock,msg);
                                          }   
-        else if(strcmp(cmd_str,"SQ")==0) {  // Set/read the squelch level
+
+        else if(strcmp(cmd_str,"SQ")==0) {  
+                                            // TS-2000 - SQ - Set/read the squelch level - not supported
                                             // P1 - 0- main, 1=sub
                                             // P2 - 0-255
+                                            float float_sq;
+                                             
                                              if(len <=3) {
-                                               sprintf(msg,"SQ%04d;",squelch);
-                                               send_resp(client_sock,msg);
-                                             } else {
-                                                squelch = atoi(&cmd_input[2]);
+                                                 float_sq = (float) active_receiver->squelch;
+                                                 float_sq = roundf((float_sq/100.0)*256.0);
+                                                #ifdef RIGCTL_DEBUG
+                                                     fprintf(stderr,"RIGCTL: float_sq=%6.2f\n",
+                                                                  float_sq); 
+                                                #endif
+                                                 sprintf(msg,"SQ0%03d;",(int) float_sq);
+                                                 send_resp(client_sock,msg);
+                                             } else {  // Set the value
+                                               int lcl_sq = atoi(&cmd_input[3]); // Note we skip the first char!
+                                               if((lcl_sq >= 0) && (lcl_sq <=255)) {
+                                                   float_sq = roundf(((float)lcl_sq/256.0)*100);
+                                                   active_receiver->squelch = (int)float_sq; 
+                                                  #ifdef RIGCTL_DEBUG
+                                                     fprintf(stderr,"RIGCTL: SetSq float_sq=%6.2f\n",
+                                                                  float_sq); 
+                                                  #endif
+                                                
+                                                 //setSquelch(active_receiver);
+                                                 g_idle_add(ext_update_squelch,NULL);
+                                                 g_idle_add(ext_vfo_update,NULL);
+                                               } else {
+                                                 send_resp(client_sock,"?;");
+                                               }
                                              }
+                                           }
+
+        else if(strcmp(cmd_str,"SR")==0) {  
+                                            // TS-2000 - SR - Resets the transceiver - not supported
                                          }
-        else if(strcmp(cmd_str,"SR")==0) {  // Resets the transceiver
-                                         }
-        else if(strcmp(cmd_str,"SS")==0) {  // Set/read Scan pause freq
+        else if(strcmp(cmd_str,"SS")==0) {  
+                                            // TS-2000 - SS - Set/read Scan pause freq - not supported
                                              if(len <=2) {
                                                //send_resp(client_sock,"SS0;"); 
                                                send_resp(client_sock,"?;"); 
                                              }
                                          }
-        else if(strcmp(cmd_str,"ST")==0) {  // Set/read the multi/ch control freq steps
+        else if(strcmp(cmd_str,"ST")==0) {  
+                                            // TS-2000 - ST - Set/read the multi/ch control freq steps
+                                            // PiHPSDR - ZZST - Set/read the multi/ch control freq steps
                                             // SSB/CW/FSK - values 00-03
                                             // 00: 1KHz, 01: 2.5Khz 02:5KHz 03: 10Khz
                                             // AM/FM mode 00-09
                                             // 00: 5KHz, 
                                             // 01: 6.25KHz, 
-                                            // 02:10Khz, 
+                                            // 02: 10Khz, 
                                             // 03: 12.5Khz,
                                             // 04: 15Khz, 
                                             // 05: 20Khz, 
@@ -1343,6 +3161,7 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                                             // 07: 30Khz
                                             // 08: 50Khz
                                             // 09: 100Khz 
+                                            if(zzid_flag == 0) {
                                              int coded_step_val;
                                              entry= (BANDSTACK_ENTRY *) 
                                                 bandstack_entry_get_current();
@@ -1391,7 +3210,11 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                                                         }
                                                         break;
                                                  } 
-                                                 sprintf(msg,"ST%02d;",coded_step_val);
+                                                 if(zzid_flag == 0) {
+                                                    sprintf(msg,"ST%02d;",coded_step_val);
+                                                 } else {
+                                                    sprintf(msg,"ZZST%02d;",coded_step_val);
+                                                 }
                                                  send_resp(client_sock,msg); 
                                              } else {
                                                  coded_step_val = atoi(&cmd_input[2]);   
@@ -1424,83 +3247,210 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                                                          } 
                                                      default: break; // No change if not a valid number
                                                  } 
-                                                 g_idle_add(vfo_update,NULL);
                                              }
+                                            } else {
+                                                // Pi HPSDR handling
+                                               if(len <= 2) {
+                                                   sprintf(msg,"ZZST%06lld;", step);
+                                                   send_resp(client_sock,msg);
+                                                }  else {
+                                                   int okay= 0;
+                                                   work_int = atoi(&cmd_input[2]);
+                                                   switch(work_int) {
+                                                         case 100000: okay = 1; break;
+                                                         case  50000: okay = 1; break;
+                                                         case  30000: okay = 1; break;
+                                                         case  25000: okay = 1; break;
+                                                         case  20000: okay = 1; break;
+                                                         case  15000: okay = 1; break;
+                                                         case  12500: okay = 1; break;
+                                                         case  10000: okay = 1; break;
+                                                         case   9000: okay = 1; break;
+                                                         case   6250: okay = 1; break;
+                                                         case   5000: okay = 1; break;
+                                                         case   2500: okay = 1; break;
+                                                         case   1000: okay = 1; break;
+                                                         case    500: okay = 1; break;
+                                                         case    250: okay = 1; break;
+                                                         case    100: okay = 1; break;
+                                                         case     50: okay = 1; break;
+                                                         case     10: okay = 1; break;
+                                                         case      1: okay = 1; break;
+                                                         default:     okay = 0; break;
+                                                   }
+                                                   if(okay == 0) {
+                                                         fprintf(stderr,"RIGCTL: ZZST ERROR - illegal  step val=%d\n",work_int);
+                                                         send_resp(client_sock,"?;");
+                                                   } else {
+                                                      step = work_int; 
+                                                   }
+                                                }
+                                            }
+                                            g_idle_add(ext_vfo_update,NULL);
                                          }
-        else if(strcmp(cmd_str,"SU")==0) {  // Set/read the scan pause freq
+        else if((strcmp(cmd_str,"SU")==0) && (zzid_flag == 0)) {
+                                            // TS-2000 - SU - Set/read the scan pause freq - not supported
                                              if(len <=2) {
                                                //send_resp(client_sock,"SU00000000000;"); 
                                                send_resp(client_sock,"?;"); 
                                              }
                                          }
-        else if(strcmp(cmd_str,"SV")==0) {  // Execute the memory transfer function
+        else if((strcmp(cmd_str,"SV")==0) && (zzid_flag == 0)) {  
+                                            // TS-2000 - SV - Execute the memory transfer function - not supported
                                          }
-        else if(strcmp(cmd_str,"TC")==0) {  // Set/read the internal TNC mode
+        else if((strcmp(cmd_str,"TC")==0) && (zzid_flag == 0)) {  
+                                            // TS-2000 - TC - Set/read the internal TNC mode - not supported
                                              if(len <=2) {
                                                //send_resp(client_sock,"TC00;"); 
                                                send_resp(client_sock,"?;"); 
                                              }
                                          }
-        else if(strcmp(cmd_str,"TD")==0) {  // Sends the DTMF memory channel
+        else if((strcmp(cmd_str,"TD")==0) && (zzid_flag == 0)) {  
+                                            // TS-2000 - TD - Sends the DTMF memory channel - not supported
                                          }
-        else if(strcmp(cmd_str,"TI")==0) {  // Reads the TNC LED status
+        else if((strcmp(cmd_str,"TI")==0) && (zzid_flag == 0)) {  
+                                            // TS-2000 - TI - Reads the TNC LED status - not supported
                                              if(len <=2) {
                                                //send_resp(client_sock,"TI00;"); 
                                                send_resp(client_sock,"?;"); 
                                              }
                                          }
-        else if(strcmp(cmd_str,"TN")==0) {  // Set/Read sub tone freq
+        else if((strcmp(cmd_str,"TN")==0) && (zzid_flag == 0))  {  
+                                            // TS-2000 - TN - Set/Read sub tone freq - not supported
                                              if(len <=2) {
                                                //send_resp(client_sock,"TN00;"); 
                                                send_resp(client_sock,"?;"); 
                                              }
                                          }
-        else if(strcmp(cmd_str,"TO")==0) {  // Set/Read tone function
+        else if((strcmp(cmd_str,"TO")==0) && (zzid_flag == 0)) {  
+                                            // TI-2000 - TO - Set/Read tone function - not supported
                                              if(len <=2) {
                                                //send_resp(client_sock,"TO0;"); 
                                                send_resp(client_sock,"?;"); 
                                              }
                                          }
-        else if(strcmp(cmd_str,"TS")==0) {  // Set/Read TF Set function status
+        else if((strcmp(cmd_str,"TS")==0) && (zzid_flag == 0)) {  
+                                            // TI-2000 - TS - Set/Read TF Set function status
                                              if(len <=2) {
                                                //send_resp(client_sock,"TS0;"); 
                                                send_resp(client_sock,"?;"); 
                                              }
                                          }
-        else if(strcmp(cmd_str,"TX")==0) {  // Key Xmitter - P1 - transmit on main/sub freq
-
-                                             /*if(len >=3) { 
-                                               // K5JAE: The TS-2000 real hardware does not respond 
-                                               // to this command, thus hamlib is not expecting response.
-                                               //send_resp(client_sock,"TX0;"); 
-                                             }*/
-                                            mox_state=1;
-                                            g_idle_add(mox_update,(gpointer)mox_state); 
-                                            g_idle_add(vfo_update,NULL);
+        else if(strcmp(cmd_str,"TX")==0)  { 
+                                            // TS-2000 - TX - Key Xmitter - P1 - transmit on main/sub freq
+                                            // PiHPSDR - ZZTX - Key Xmitter - P1 - transmit on main/sub freq
+                                            if(!((vfo[active_receiver->id].mode == modeCWL) ||
+                                                 (vfo[active_receiver->id].mode == modeCWU))) {
+                                                 //*if(len >=3) { 
+                                                 // K5JAE: The TS 2000 real hardware does not respond 
+                                                 // to this command, thus hamlib is not expecting response.
+                                                 //send_resp(client_sock,"TX0;");  */
+                                               mox_state = 1;
+                                               g_idle_add(ext_mox_update,(gpointer)(long)mox_state); 
+                                               g_idle_add(ext_vfo_update,NULL);
+                                            } else {
+                                              g_idle_add(ext_cw_setup,NULL);    // Initialize for external transmit
+                                              g_idle_add(ext_mox_update,(gpointer)(long)1); // Turn on External MOX
+                                            }
                                          }
-        else if(strcmp(cmd_str,"TY")==0) {  // Set/Read uP firmware type
+        else if(strcmp(cmd_str,"TY")==0) {  
+                                            // TI-2000 - TY -- Set/Read uP firmware type
                                              if(len <=2) {
                                                send_resp(client_sock,"TY000;"); 
                                              }
                                          }
-        else if(strcmp(cmd_str,"UL")==0) {  // Detects the PLL unlock status - this should never occur - xmit only
+        else if((strcmp(cmd_str,"UA")==0) && (zzid_flag == 1)) {  
+                                            // PiHPSDR - ZZUA - Xvrt Set/Read 
+                                            //        RW P1 - 1 Char - Entry number 0-7
+                                            //         W P1 - Disable PA - 1 char
+                                            //         W P2 - 15 Char -  Title - 16th char with last being '\0'
+                                            //         W P3 - 11 Chars - Min Freq HZ
+                                            //         W P4 - 11 Chars - Max Freq HZ
+                                            //         W P5 - 11 Chars - Low Freq HZ
+                                            char lcl_buf[] = "                "; 
+                                            char tempc;
+                                            if(len<=3) {
+                                               work_int = atoi(&cmd_input[2]);
+                                               if((work_int >=0) && (work_int <=7)) {
+                                                  BAND *xvtr=band_get_band(BANDS+work_int);
+                                                  BANDSTACK *bandstack=xvtr->bandstack;
+                                                  BANDSTACK_ENTRY *entry=bandstack->entry;
+                                                  strcpy(lcl_buf,xvtr->title);
+                                                  lcl_buf[strlen(lcl_buf)] = ' '; // Replace the last entry with ' ';
+                                                  lcl_buf[15] = '\0';
+                                                  sprintf(msg,"ZZUA%1d%1d%s%011lld%011lld%011lld;",work_int,xvtr->disablePA,lcl_buf,
+                                                                              xvtr->frequencyMin,xvtr->frequencyMax,xvtr->frequencyLO);
+                                                  send_resp(client_sock,msg);
+                                               }
+                                            } else if(len==52) {
+                                              
+                                               tempc = cmd_input[3];
+                                               cmd_input[3] = '\0';
+                                               work_int = atoi(&cmd_input[2]);
+                                               cmd_input[3] = tempc;
+                                               if((work_int >=0) && (work_int <=7)) {
+
+                                                  BAND *xvtr=band_get_band(BANDS+work_int);
+                                                  BANDSTACK *bandstack=xvtr->bandstack;
+                                                  BANDSTACK_ENTRY *entry=bandstack->entry;
+                                                  tempc = cmd_input[4]; 
+                                                  cmd_input[4]='\0';
+                                                  xvtr->disablePA = atoi(&cmd_input[3]); 
+                                                  cmd_input[4]=tempc;
+                                                  
+                                                  /* Get the title of the XVTR */
+                                                  tempc = cmd_input[19];
+                                                  cmd_input[19] = '\0';
+                                                  strncpy(xvtr->title,&cmd_input[4],16); 
+                                                  cmd_input[19] = tempc;
+
+                                                  /* Pull out the Min freq */
+                                                  tempc = cmd_input[30];
+                                                  cmd_input[30]='\0';
+                                                  xvtr->frequencyMin = (long long) atoi(&cmd_input[19]); 
+                                                  cmd_input[30] = tempc;
+
+                                                  /* Pull out the Max freq */
+                                                  tempc = cmd_input[41];
+                                                  cmd_input[41]='\0';
+                                                  xvtr->frequencyMax = (long long) atoi(&cmd_input[30]); 
+                                                  cmd_input[41] = tempc;
+                                                  
+
+                                                  /* Pull out the LO freq */
+                                                  xvtr->frequencyLO = (long long) atoi(&cmd_input[41]); 
+                                                } else {
+                                                  fprintf(stderr,"RIGCTL: ERROR ZZUA - incorrect length command received=%d",len);
+                                                  send_resp(client_sock,"?;");
+                                                }
+                                            } 
+                                         }
+        else if((strcmp(cmd_str,"UL")==0) && (zzid_flag == 0)) {  
+                                            // TS-2000 - UL - Detects the PLL unlock status - not supported
                                              if(len <=2) {
                                                //send_resp(client_sock,"UL0;"); 
                                                send_resp(client_sock,"?;"); 
                                              }
                                          }
-        else if(strcmp(cmd_str,"UP")==0) {  // Emulates the mic up key
+        else if((strcmp(cmd_str,"UP")==0) && (zzid_flag == 0))  {
+                                            // TS-2000 - UP - Emulates the mic up key
                                          }
-        else if(strcmp(cmd_str,"VD")==0) {  // Sets/Reads VOX dleay time - 0000-3000ms in steps of 150
-                                            // We want vox_hang variable in PiHPSDR
+        else if(strcmp(cmd_str,"VD")==0) {  
+                                            // TS-2000 - VD - Sets/Reads VOX delay time - 0000-3000ms in steps of 150
+                                            // PiHPSDR - ZZVD - Sets/Reads VOX Hang time
+                                            // We want vox_hang variable in Pi HPSDR
                                             // Max value in variable in ms... so 250 = 250ms
                                              if(len <=2) {
                                                work_int = (int) vox_hang;
-                                               sprintf(msg,"VD%04d;",work_int); 
+                                               if(zzid_flag == 0) {
+                                                  sprintf(msg,"VD%04d;",work_int); 
+                                               } else {
+                                                  sprintf(msg,"ZZVD%04d;",work_int); 
+                                               }
                                                send_resp(client_sock,msg);
                                              } else {
                                                   work_int = atoi(&cmd_input[2]);
-                                                  // Bounds check for legal values for PiHPSDR
+                                                  // Bounds check for legal values for Pi HPSDR
                                                   if(work_int > 1000) { work_int = 1000; }
                                                   if(work_int < 0) { work_int = 0; }
                                                   vox_hang = (double) work_int;
@@ -1509,42 +3459,86 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                                                   #endif
                                              }
                                          }
-        else if(strcmp(cmd_str,"VG")==0) {  // Sets/Reads VOX gain 000-009
-                                            // We want vox_threshold variable in PiHPSDR
+        else if(strcmp(cmd_str,"VG")==0) {  
+                                            // TI-2000 - VG - Sets/Reads VOX gain 000-009
+                                            // PiHPSDR - ZZVG - Set/Read VOX Threshold - 0-1000
+                                            // We want vox_threshold variable in Pi HPSDR
                                             // Max value in variable 0.1 
                                             // 3 char 000-009 valid ranges
-                                             if(len <=2) {
-                                               work_int = (int) ((vox_threshold) * 100.0);
-                                               sprintf(msg,"VG00%1d;",work_int);
+                                            if(len <=2) {
+                                               if(zzid_flag == 0) {
+                                                    work_int = (int) ((vox_threshold) * 100.0);
+                                                    sprintf(msg,"VG00%1d;",work_int);
+                                               } else {
+                                                    work_int = (int) ((vox_threshold) * 1000.0);
+                                                    sprintf(msg,"ZZVG%04d;",work_int);
+                                               }
                                                send_resp(client_sock,msg);
                                              } else {
-                                                  // Set the threshold here
-                                                  work_int = atoi(&cmd_input[2]);
-                                                  vox_threshold = ((double) work_int)/100.0;
-                                                  #ifdef RIGCTL_DEBUG
-                                                  fprintf(stderr,"RIGCTL: Vox thresh=%0.20f\n",vox_threshold);
-                                                  #endif
+                                               work_int = atoi(&cmd_input[2]);
+                                               if((work_int >=0) && (work_int<=9)) {
+                                                  if(zzid_flag == 0) {
+                                                     // Set the threshold here
+                                                     vox_threshold = ((double) work_int)/100.0;
+                                                     #ifdef RIGCTL_DEBUG
+                                                     fprintf(stderr,"RIGCTL: Vox thresh=%0.20f\n",vox_threshold);
+                                                     #endif
+                                                  } else {
+                                                     vox_threshold = ((double) work_int)/1000.0;
+                                                     #ifdef RIGCTL_DEBUG
+                                                     fprintf(stderr,"RIGCTL: Vox thresh=%0.20f\n",vox_threshold);
+                                                     #endif
+                                                  }
+                                                } else {
+                                                     send_resp(client_sock,"?;");
+                                                }
                                              }
                                          }
-        else if(strcmp(cmd_str,"VR")==0) {  // Emulates the voice 1/2 key
+        else if((strcmp(cmd_str,"VR")==0) && (zzid_flag == 0)) {  
+                                            // TS-2000 - VR - Emulates the voice 1/2 key - not supported
                                          }
-        else if(strcmp(cmd_str,"VX")==0) {  // Sets/reads vox f(x) state
+        else if(strcmp(cmd_str,"VX")==0) {  
+                                            // TS-2000 - VX - Sets/reads vox f(x) state
+                                            // PiHPSDR - ZZVX - Set/Read VOX enabled
                                              if(len <=2) {
-                                               sprintf(msg,"VX%1d;",vox_enabled); 
+                                               if(zzid_flag == 0 ) {
+                                                   sprintf(msg,"VX%1d;",vox_enabled); 
+                                               } else {
+                                                   sprintf(msg,"ZZVX%1d;",vox_enabled); 
+                                               } 
                                                send_resp(client_sock,msg);
                                              } else {
                                                work_int = atoi(&cmd_input[2]);
-                                               if(work_int>1) { vox_enabled = 1; vox= 1;}
-                                               if(work_int<1) { vox_enabled = 0; vox=0; }
+                                               if(work_int==1) { vox_enabled = 1; vox= 1;}
+                                               if(work_int!=1) { vox_enabled = 0; vox=0; }
                                              }
                                          }
-        else if(strcmp(cmd_str,"XT")==0) {  // Sets/reads the XIT f(x) state
+        else if((strcmp(cmd_str,"XC")==0) && (zzid_flag == 1)) {  
+                                            // PiHPSDR - ZZXC  - Turn off External MOX- 
+                                            g_idle_add(ext_mox_update,(gpointer)(long)0); // Turn on xmitter (set Mox)
+                                         }
+        else if((strcmp(cmd_str,"XI")==0) && (zzid_flag == 1)) {  
+                                            // PiHPSDR - ZZXI - Initialize the transmitter for external CW
+                                            g_idle_add(ext_cw_setup,NULL);    // Initialize for external transmit
+                                            g_idle_add(ext_mox_update,(gpointer)(long)1); // Turn on External MOX
+                                         }
+       else if((strcmp(cmd_str,"XO")==0) && (zzid_flag == 1)) {  
+                                            // PiHPSDR - ZZXT - Turn CW Note off when in CW mode
+                                            g_idle_add(ext_cw_key, (gpointer)(long)0);
+                                         }
+        else if(strcmp(cmd_str,"XT")==0) {  
+                                           if(zzid_flag == 0 ) {
+                                            // TS-2000 - XT - Sets/reads the XIT f(x) state - not supported
                                              if(len <=2) {
                                                //send_resp(client_sock,"XT0;"); 
                                                send_resp(client_sock,"?;"); 
                                              }
+                                           } else {
+                                            // PiHPSDR - ZZXT - Turn CW Note on when in CW mode
+                                            g_idle_add(ext_cw_key, (gpointer)(long)1);
+                                           }
                                          }
-        else if(strcmp(cmd_str,"XX")==0) {  // 
+        else if((strcmp(cmd_str,"XX")==0) && (zzid_flag == 0)) {  // 
                                             // Format RL01234: First dig 0=neg, 1=pos number
                                             //                 1-4- digital offset in hertz.
                                             if(len > 4) { // It is set instead of a read
@@ -1595,117 +3589,198 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
 // 
 
 
+// Serial Port Launch
+int set_interface_attribs (int fd, int speed, int parity)
+{
+        struct termios tty;
+        memset (&tty, 0, sizeof tty);
+        if (tcgetattr (fd, &tty) != 0)
+        {
+                fprintf (stderr,"RIGCTL: Error %d from tcgetattr", errno);
+                return -1;
+        }
+
+        cfsetospeed (&tty, speed);
+        cfsetispeed (&tty, speed);
+
+        tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
+        // disable IGNBRK for mismatched speed tests; otherwise receive break
+        // as \000 chars
+        tty.c_iflag &= ~IGNBRK;         // disable break processing
+        tty.c_lflag = 0;                // no signaling chars, no echo,
+                                        // no canonical processing
+        tty.c_oflag = 0;                // no remapping, no delays
+        tty.c_cc[VMIN]  = 0;            // read doesn't block
+        tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout
+
+        //tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
+        tty.c_iflag |= (IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
+
+        tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
+                                        // enable reading
+        tty.c_cflag &= ~(PARENB | PARODD);      // shut off parity
+        tty.c_cflag |= parity;
+        tty.c_cflag &= ~CSTOPB;
+        tty.c_cflag &= ~CRTSCTS;
+
+        if (tcsetattr (fd, TCSANOW, &tty) != 0)
+        {
+                fprintf(stderr, "RIGCTL: Error %d from tcsetattr", errno);
+                return -1;
+        }
+        return 0;
+}
+
+void set_blocking (int fd, int should_block)
+{
+        struct termios tty;
+        memset (&tty, 0, sizeof tty);
+        if (tcgetattr (fd, &tty) != 0)
+        {
+                fprintf (stderr,"RIGCTL: Error %d from tggetattr\n", errno);
+                return;
+        }
+        tty.c_cc[VMIN]  = should_block ? 1 : 0;
+        tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout
+
+        if (tcsetattr (fd, TCSANOW, &tty) != 0)
+                fprintf (stderr,"RIGCTL: error %d setting term attributes\n", errno);
+}
+static gpointer serial_server(gpointer data) {
+     // We're going to Read the Serial port and
+     // when we get data we'll send it to parse_cmd
+     int num_chars;
+     char ser_buf[100];
+     char work_buf[100];
+     const char s[2]=";";
+     char *p;
+     char *d;
+     char save_buf[100] = "";
+     int str_len = 0;
+     cat_control++;
+     while(1) {
+        int num_chars = read (fd, ser_buf, sizeof ser_buf);
+        if( num_chars != 0) {
+           //fprintf(stderr,"RIGCTL: RECEVIED=%s<<\n",ser_buf);
+           strcat(work_buf,ser_buf);
+           strcpy(ser_buf,"");  // Clear away serial buffer
+           p = &work_buf[0]; 
+           while((d=strstr(p,";")) != NULL) {
+                 *d = '\0';
+                 g_mutex_lock(&mutex_b->m);
+                 parse_cmd(p,strlen(p),-1);
+                 g_mutex_unlock(&mutex_b->m);
+                 p = ++d;
+                 //fprintf(stderr,"RIGCTL: STRLEFT=%s\n",p);
+           }
+           strcpy(save_buf,p);
+           for(str_len=0; str_len<=99; str_len++) {
+             ser_buf[str_len] = '\0';
+             work_buf[str_len] = '\0';
+           }
+           strcpy(work_buf,save_buf);
+           for(str_len=0; str_len<=99; str_len++) {
+             save_buf[str_len] = '\0';
+           }
+/*
+           if(strstr(ser_buf,";") != NULL) {
+              p = strtok(ser_buf,s);
+              fprintf(stderr,"RIGCTL: Tok=%s\n",p);
+              while(p != NULL) {
+                 strcpy(work_buf,p);
+                 g_mutex_lock(&mutex_b->m);
+                 parse_cmd(work_buf,strlen(work_buf),-1);
+                 g_mutex_unlock(&mutex_b->m);
+                 p = strtok(NULL,s);
+                 fprintf(stderr,"RIGCTL: Tok=%s\n",p);
+              }
+           } else {
+               strcat(work_buf,ser_buf);
+               fprintf(stderr,"RIGCTL: Work_buf=%s\n",work_buf);
+           }
+*/
+        } /*else {
+           usleep(100L);
+        }*/
+     }
+}
+
+int launch_serial () {
+     fprintf(stderr,"RIGCTL: Launch Serial port %s\n",ser_port);
+
+
+     if(mutex_b_exists == 0) {
+        mutex_b = g_new(GT_MUTEX,1);
+        g_mutex_init(&mutex_b->m);
+        mutex_b_exists = 1;
+     }
+     
+     fd = open (ser_port, O_RDWR | O_NOCTTY | O_SYNC);   
+     if (fd < 0)
+     {
+        fprintf (stderr,"RIGCTL: Error %d opening %s: %s\n", errno, ser_port, strerror (errno));
+        return 0 ;
+     }
+     //set_interface_attribs (fd, B38400, 0);  // set speed to 115,200 bps, 8n1 (no parity)
+     set_interface_attribs (fd, serial_baud_rate, 0); 
+     /*
+     if(serial_parity == 1) {
+         set_interface_attribs (fd, PARENB, 0); 
+     }
+     if(serial_parity == 2) {
+         set_interface_attribs (fd, PARODD, 0); 
+     }
+     */
+     set_blocking (fd, 1);                   // set no blocking
+
+     
+     serial_server_thread_id = g_thread_new( "Serial server", serial_server, NULL);
+     if( ! serial_server_thread_id )
+     {
+       fprintf(stderr,"g_thread_new failed on serial_server\n");
+       return 0;
+     }
+     return 1;
+}
+// Serial Port close
+void disable_serial () {
+     fprintf(stderr,"RIGCTL: Disable Serial port %s\n",ser_port);
+     cat_control--;
+}
+
 //
 // 2-25-17 - K5JAE - create each thread with the pointer to the port number  
 //                   (Port numbers now const ints instead of defines..) 
 //
 void launch_rigctl () {
    int err;
+   
    fprintf(stderr, "LAUNCHING RIGCTL!!\n");
 
+   rigctl_busy = 1;
    mutex_a = g_new(GT_MUTEX,1);
    g_mutex_init(&mutex_a->m);
 
-   mutex_b = g_new(GT_MUTEX,1);
-   g_mutex_init(&mutex_b->m);
-   
-   // This routine encapsulates the pthread call
-/*
-   err = pthread_create (&rigctl_a_thread_id,NULL,rigctl_a,NULL);
-   if(err != 0) {
-       fprintf(stderr, "pthread_create failed on rigctl_a launch\n");
-   }  
-*/
-
-   rigctl_a_thread_id = g_thread_new( "rigctl a", rigctl, (gpointer)&TelnetPortA);
-   if( ! rigctl_a_thread_id )
-   {
-     fprintf(stderr,"g_thread_new failed on rigctl_a\n");
-   }
-
-
-/*
-   err = pthread_create (&rigctl_b_thread_id,NULL,rigctl_b,NULL);
-   if(err != 0) {
-       fprintf(stderr, "pthread_create failed on rigctl_b launch\n");
-   }  
-*/
-
-   rigctl_b_thread_id = g_thread_new( "rigctl b", rigctl, (gpointer)&TelnetPortB);
-   if( ! rigctl_b_thread_id )
-   {
-     fprintf(stderr,"g_thread_new failed on rigctl_b\n");
+   if(mutex_b_exists == 0) {
+      mutex_b = g_new(GT_MUTEX,1);
+      g_mutex_init(&mutex_b->m);
+      mutex_b_exists = 1;
    }
+   
+   mutex_c = g_new(GT_MUTEX,1);
+   g_mutex_init(&mutex_c->m);
 
-/*
-   err = pthread_create (&rigctl_c_thread_id,NULL,rigctl_c,NULL);
-   if(err != 0) {
-       fprintf(stderr, "pthread_create failed on rigctl_c launch\n");
-   }  
-*/
-
-   rigctl_c_thread_id = g_thread_new( "rigctl c", rigctl, (gpointer)&TelnetPortC);
-   if( ! rigctl_c_thread_id )
+   // This routine encapsulates the thread call
+   rigctl_server_thread_id = g_thread_new( "rigctl server", rigctl_server, (gpointer)(long)rigctl_port_base);
+   if( ! rigctl_server_thread_id )
    {
-     fprintf(stderr,"g_thread_new failed on rigctl_c\n");
+     fprintf(stderr,"g_thread_new failed on rigctl_server\n");
    }
-
 }
 
 
-// Telnet Server launch code below
-// max number of bytes we can get at once
 #define MAXDATASIZE 300
 
-//
-// 2-25-17 - K5JAE - removed duplicate init servers.
-//
-
-
-int init_server ( int * socket_desc_ptr, struct sockaddr_in * client, struct sockaddr_in * server, int telnet_port) {
-    int client_sock;
-    int c;
-    //Create socket
-    *socket_desc_ptr = socket(AF_INET , SOCK_STREAM , 0);
-
-    if (*socket_desc_ptr == -1)
-    {
-        fprintf(stderr,"RIGCTL: Could not create socket");
-    }
-    fprintf(stderr, "RIGCTL: Socket created\n");
-     
-    //Prepare the sockaddr_in structure
-    server->sin_family = AF_INET;
-    server->sin_addr.s_addr = INADDR_ANY;
-    server->sin_port = htons( telnet_port );
-     
-    //Bind
-    if( bind(*socket_desc_ptr,(struct sockaddr *) server , sizeof(struct sockaddr_in)) < 0)
-    {
-        //print the error message
-        fprintf(stderr,"RIGCTL: bind failed. Error\n");
-        return 1;
-    }
-    fprintf(stderr,"RIGCTL: Bind done on port %d\n",telnet_port);
-     
-    //Listen
-    listen(*socket_desc_ptr, 3);
-     
-    //Accept and incoming connection
-    fprintf(stderr,"RIGCTL: Waiting for incoming connections...\n");
-    c = sizeof(struct sockaddr_in);
-     
-    //accept connection from an incoming client
-    client_sock = accept(*socket_desc_ptr,(struct sockaddr *)client, (socklen_t*)&c);
-    if (client_sock < 0)
-    {
-        fprintf(stderr,"RIGCTL: Accept failed\n");
-    }
-    fprintf(stderr,"RIGCTL: Connection accepted\n");
-
-    return client_sock;
-}
-
 int rigctlGetMode()  {
         switch(vfo[active_receiver->id].mode) {
            case modeLSB: return(1); // LSB
@@ -1720,61 +3795,155 @@ int rigctlGetMode()  {
         }
 }
 
+
 int rigctlSetFilterLow(int val){
 };
 int rigctlSetFilterHigh(int val){
 };
 
-void set_band(long long new_freqA, int ctl) {      
+void set_freqB(long long new_freqB) {      
 
-   fprintf(stderr,"set_band: f=%11lld ctl=%d\n",new_freqA,ctl );
-   BANDSTACK_ENTRY *entry;
-   BAND *band;
-   FILTER* band_filters;
-   FILTER* band_filter;
+   //BANDSTACK_ENTRY *bandstack = bandstack_entry_get_current();
+   //bandstack->frequencyB = new_freqB;
+   //frequencyB = new_freqB;
+   vfo[VFO_B].frequency = new_freqB;   
+   g_idle_add(ext_vfo_update,NULL);
+}
 
-   int b = get_band_from_frequency(new_freqA);
 
-   if(b == -1) { // Out of ham bands...
-      fprintf(stderr,"set_band: out of ham bands\n");
-      setFrequency(new_freqA);
-      g_idle_add(vfo_update,NULL);
-      return;
-   }   
+int set_band (gpointer data) {
+  
+  BANDSTACK *bandstack;
+  long long new_freq = *(long long *) data;
+  free(data);
 
-   band=band_set_current(b);
+  #ifdef RIGCTL_DEBUG
+  fprintf(stderr,"RIGCTL set_band: New freq=%lld\n",new_freq);
+  #endif
 
-   entry=bandstack_entry_next();
-   entry->mode = vfo[VFO_A].mode;
-   set_mode(active_receiver,entry->mode); // From current band setting
-   
+  // If CTUN=1 - can only change frequencies within the sample_rate range!
+  if((vfo[active_receiver->id].ctun == 1) &&
+        ((vfo[active_receiver->id].ctun_frequency + (active_receiver->sample_rate/2) < new_freq) ||
+         (vfo[active_receiver->id].ctun_frequency - (active_receiver->sample_rate/2) > new_freq))) {
+       fprintf(stderr,"RIGCTL: *** set_band: CTUN Bounce ***\n");
+       return 0;
+  }
+
+  int b = get_band_from_frequency (new_freq);
 
-   band_filters=filters[entry->mode];
-   band_filter=&band_filters[entry->filter];
+  if(b == -1) { // Not in the ham bands!
+     // We're not going to update the bandstack - but rather just
+     // change the frequency and move on  
+        vfo[active_receiver->id].frequency=new_freq;
+        receiver_vfo_changed(receiver[active_receiver->id]);
+        g_idle_add(ext_vfo_update,NULL);
+        return 0;
+  }
 
-  set_filter(active_receiver,band_filter->low,band_filter->high);
-  setFrequency(new_freqA);
+  #ifdef RIGCTL_DEBUG
+  fprintf(stderr,"RIGCTL set_band: New Band=%d\n",b);
+  #endif
+  int id=active_receiver->id;
+
+  //if(id==0) {
+  //  fprintf(stderr,"RIGCTL set_band: id=0\n");
+  //  vfo_save_bandstack();
+  //}
+  if(b==vfo[id].band) {
+    //fprintf(stderr,"RIGCTL set_band:b=cur_band \n");
+    // same band selected - step to the next band stack
+    bandstack=bandstack_get_bandstack(b);
+    vfo[id].bandstack++;
+    if(vfo[id].bandstack>=bandstack->entries) {
+      //fprintf(stderr,"VFO_BAND_CHANGED: bandstack set to 0\n");
+      vfo[id].bandstack=0;
+    }
+  } else {
+    // new band - get band stack entry
+    //fprintf(stderr,"VFO_BAND_CHANGED: new_band\n");
+    bandstack=bandstack_get_bandstack(b)      ;
+    vfo[id].bandstack=bandstack->current_entry;
+    //fprintf(stderr,"VFO_BAND_CHANGED: vfo[id].banstack=%d\n",vfo[id].bandstack);
+  }
 
-  // BAND *band=band_get_current_band();
-  band=band_set_current(b);
-  if(active_receiver->id==0) {
-    set_alex_rx_antenna(band->alexRxAntenna);
-    set_alex_tx_antenna(band->alexTxAntenna);
-    set_alex_attenuation(band->alexAttenuation);
+  BAND *band=band_get_band(b);
+  BANDSTACK_ENTRY *entry=&bandstack->entry[vfo[id].bandstack];
+  if(vfo[id].band != b) {
+     vfo[id].mode=entry->mode;
+  }
+  vfo[id].band=b;
+  entry->frequency = new_freq;
+  //vfo[id].frequency=entry->frequency;
+  if(vfo[id].ctun == 1) {
+      fprintf(stderr,"RIGCTL: set_band #### Change frequency");
+      if(new_freq > vfo[id].ctun_frequency) {
+         vfo[id].offset = new_freq - vfo[id].ctun_frequency; 
+      } else {
+         vfo[id].offset = vfo[id].ctun_frequency - new_freq; 
+      }
+      fprintf(stderr,"RIGCTL: set_band OFSET= %011lld\n",vfo[id].offset);
+  } else {
+      entry->frequency = new_freq;
   }
 
-  //setFrequency(new_freqA);
-  g_idle_add(vfo_update,NULL);
+  //vfo[id].mode=entry->mode;
+  vfo[id].filter=entry->filter;
+  vfo[id].lo=band->frequencyLO;
+
+  switch(id) {
+    case 0:
+      bandstack->current_entry=vfo[id].bandstack;
+      receiver_vfo_changed(receiver[id]);
+      BAND *band=band_get_band(vfo[id].band);
+      set_alex_rx_antenna(band->alexRxAntenna);
+      set_alex_tx_antenna(band->alexTxAntenna);
+      set_alex_attenuation(band->alexAttenuation);
+      receiver_vfo_changed(receiver[0]);
+      break;
+   case 1:
+      if(receivers==2) {
+        receiver_vfo_changed(receiver[1]);
+      }
+      break;
+  }
 
+  if(split) {
+    tx_set_mode(transmitter,vfo[VFO_B].mode);
+  } else {
+    tx_set_mode(transmitter,vfo[VFO_A].mode);
+  }
   calcDriveLevel();
-  calcTuneDriveLevel();
-}
+  //calcTuneDriveLevel();
+  g_idle_add(ext_vfo_update,NULL);
 
-void set_freqB(long long new_freqB) {      
+  return 0;
+}
+int set_alc(gpointer data) {
+    int * lcl_ptr = (int *) data;
+    alc = *lcl_ptr;
+    fprintf(stderr,"RIGCTL: set_alc=%d\n",alc);
+    return 0;
+}
 
-   //BANDSTACK_ENTRY *bandstack = bandstack_entry_get_current();
-   //bandstack->frequencyB = new_freqB;
-   //frequencyB = new_freqB;
-   vfo[VFO_B].frequency = new_freqB;   
-   g_idle_add(vfo_update,NULL);
+int lookup_band(int val) {
+    int work_int;
+    switch(val) {
+       case 160: work_int = 0; break;
+       case  80: work_int = 1; break;
+       case  60: work_int = 2; break;
+       case  40: work_int = 3; break;
+       case  30: work_int = 4; break;
+       case  20: work_int = 5; break;
+       case  17: work_int = 6; break;
+       case  15: work_int = 7; break;
+       case  12: work_int = 8; break;
+       case  10: work_int = 9; break;
+       case   6: work_int = 10; break;
+       case 888: work_int = 11; break; // General coverage
+       case 999: work_int = 12; break; // WWV
+       case 136: work_int = 13; break; // WWV
+       case 472: work_int = 14; break; // WWV
+       default: work_int = 0;
+     }
+     return work_int;
 }
index 51e59ed386bac45eca3fb06e130eb29c53a25047..da827ebdde7a8cc36ab119e03cc8e41f0a6711f6 100644 (file)
--- a/rigctl.h
+++ b/rigctl.h
@@ -2,10 +2,21 @@
 #define RIGCTL_H
 
 void launch_rigctl ();
+int launch_serial ();
+void disable_sreial ();
+
+void  close_rigctl_ports ();
 int   rigctlGetMode();
+int   lookup_band(int);
 char * rigctlGetFilter();
 void set_freqB(long long);
-void set_band(long long, int);
+int set_band(void *);
 extern int cat_control;
+int set_alc(gpointer);
+extern int rigctl_busy;
+
+extern int rigctl_port_base;
+extern int rigctl_enable;
+
 
 #endif // RIGCTL_H
diff --git a/rigctl_menu.c b/rigctl_menu.c
new file mode 100644 (file)
index 0000000..b728f80
--- /dev/null
@@ -0,0 +1,233 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#include <gtk/gtk.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "new_menu.h"
+#include "rigctl_menu.h"
+#include "rigctl.h"
+#include "band.h"
+#include "radio.h"
+#include "vfo.h"
+
+int  serial_enable;
+char ser_port[64]="/dev/ttyUSB0";
+int serial_baud_rate = B4800;
+int serial_parity = 0; // 0=none, 1=even, 2=odd
+
+static GtkWidget *parent_window=NULL;
+
+static GtkWidget *menu_b=NULL;
+
+static GtkWidget *dialog=NULL;
+
+static void cleanup() {
+  if(dialog!=NULL) {
+    gtk_widget_destroy(dialog);
+    dialog=NULL;
+    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 rigctl_value_changed_cb(GtkWidget *widget, gpointer data) {
+   rigctl_port_base = gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget)); 
+}
+
+static void serial_value_changed_cb(GtkWidget *widget, gpointer data) {
+     sprintf(ser_port,"/dev/ttyUSB%0d",(int) gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget))); 
+     fprintf(stderr,"RIGCTL_MENU: New Serial port=%s\n",ser_port);
+}
+
+static void rigctl_enable_cb(GtkWidget *widget, gpointer data) {
+  rigctl_enable=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+  if(rigctl_enable) {
+     launch_rigctl();
+  } else {
+     disable_rigctl();
+  }
+}
+
+static void serial_enable_cb(GtkWidget *widget, gpointer data) {
+  serial_enable=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+  if(serial_enable) {
+     if(launch_serial() == 0) {
+        gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget),FALSE)      ;
+     }       
+  } else {
+     disable_serial();
+  }
+}
+
+// Set Baud Rate
+static void baud_rate_cb(GtkWidget *widget, gpointer data) {
+   serial_baud_rate = (uintptr_t) data;
+   fprintf(stderr,"RIGCTL_MENU: Baud rate changed\n");
+}
+
+// Set Parity 0=None, 1=Even, 2=0dd
+static void parity_cb(GtkWidget *widget, gpointer data) {
+   serial_parity = (uintptr_t) data;
+   fprintf(stderr,"RITCTL_MENU: Serial Parity changed=%d\n", serial_parity);
+}
+
+void rigctl_menu(GtkWidget *parent) {
+  int i;
+
+  parent_window=parent;
+
+  dialog=gtk_dialog_new();
+  gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - RIGCTL");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
+
+  GdkRGBA color;
+  color.red = 1.0;
+  color.green = 1.0;
+  color.blue = 1.0;
+  color.alpha = 1.0;
+  gtk_widget_override_background_color(dialog,GTK_STATE_FLAG_NORMAL,&color);
+
+  GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+
+  GtkWidget *grid=gtk_grid_new();
+  gtk_grid_set_column_spacing (GTK_GRID(grid),10);
+  //gtk_grid_set_row_spacing (GTK_GRID(grid),10);
+  //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
+  //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+
+  GtkWidget *close_b=gtk_button_new_with_label("Close");
+  g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
+  gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
+
+
+  GtkWidget *rigctl_enable_b=gtk_check_button_new_with_label("Rigctl Enable");
+  //gtk_widget_override_font(tx_out_of_band_b, pango_font_description_from_string("Arial 18"));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rigctl_enable_b), rigctl_enable);
+  gtk_widget_show(rigctl_enable_b);
+  gtk_grid_attach(GTK_GRID(grid),rigctl_enable_b,0,1,1,1);
+  g_signal_connect(rigctl_enable_b,"toggled",G_CALLBACK(rigctl_enable_cb),NULL);
+  GtkWidget *rigctl_port_label =gtk_label_new("RigCtl Port Number");
+  //gtk_widget_override_font(band_label, pango_font_description_from_string("Arial 18"));
+  gtk_widget_show(rigctl_port_label);
+  gtk_grid_attach(GTK_GRID(grid),rigctl_port_label,0,2,1,1);
+
+  GtkWidget *rigctl_port_spinner =gtk_spin_button_new_with_range(18000,21000,1);
+  //gtk_widget_override_font(rigctl_r, pango_font_description_from_string("Arial 18"));
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON(rigctl_port_spinner),(double)19090);
+  gtk_widget_show(rigctl_port_spinner);
+  gtk_grid_attach(GTK_GRID(grid),rigctl_port_spinner,1,2,1,1);
+  g_signal_connect(rigctl_port_spinner,"value_changed",G_CALLBACK(rigctl_value_changed_cb),NULL);
+
+  /* Put the Serial Port stuff here */
+  GtkWidget *serial_enable_b=gtk_check_button_new_with_label("Serial Port Enable");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (serial_enable_b), serial_enable);
+  gtk_widget_show(serial_enable_b);
+  gtk_grid_attach(GTK_GRID(grid),serial_enable_b,0,3,1,1);
+  g_signal_connect(serial_enable_b,"toggled",G_CALLBACK(serial_enable_cb),NULL);
+
+  GtkWidget *serial_text_label=gtk_label_new("Serial Port: /dev/ttyUSB");
+  gtk_grid_attach(GTK_GRID(grid),serial_text_label,0,4,1,1);
+
+  GtkWidget *serial_port_spinner =gtk_spin_button_new_with_range(0,7,1);
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON(serial_port_spinner),(double)0);
+  gtk_widget_show(serial_port_spinner);
+  gtk_grid_attach(GTK_GRID(grid),serial_port_spinner,1,4,1,1);
+  g_signal_connect(serial_port_spinner,"value_changed",G_CALLBACK(serial_value_changed_cb),NULL);
+
+  // Serial baud rate here
+  GtkWidget *baud_rate_label =gtk_label_new("Baud Rate:");
+  gtk_widget_show(baud_rate_label);
+  gtk_grid_attach(GTK_GRID(grid),baud_rate_label,0,5,1,1);
+  
+  GtkWidget *baud_rate_b4800=gtk_radio_button_new_with_label(NULL,"4800");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (baud_rate_b4800), serial_baud_rate == B4800);
+  gtk_widget_show(baud_rate_b4800);
+  gtk_grid_attach(GTK_GRID(grid),baud_rate_b4800,1,5,1,1);
+  g_signal_connect(baud_rate_b4800,"toggled",G_CALLBACK(baud_rate_cb),(gpointer *) B4800);
+
+  GtkWidget *baud_rate_b9600=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(baud_rate_b4800),"9600");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (baud_rate_b9600), serial_baud_rate == B9600);
+  gtk_widget_show(baud_rate_b9600);
+  gtk_grid_attach(GTK_GRID(grid),baud_rate_b9600,2,5,1,1);
+  g_signal_connect(baud_rate_b9600,"toggled",G_CALLBACK(baud_rate_cb),(gpointer *) B9600);
+
+  GtkWidget *baud_rate_b19200=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(baud_rate_b9600),"19200");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (baud_rate_b19200),serial_baud_rate == B19200);
+  gtk_widget_show(baud_rate_b19200);
+  gtk_grid_attach(GTK_GRID(grid),baud_rate_b19200,3,5,1,1);
+  g_signal_connect(baud_rate_b19200,"toggled",G_CALLBACK(baud_rate_cb),(gpointer *) B19200);
+
+  GtkWidget *baud_rate_b38400=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(baud_rate_b19200),"38400");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (baud_rate_b38400),serial_baud_rate == B38400);
+  gtk_widget_show(baud_rate_b38400);
+  gtk_grid_attach(GTK_GRID(grid),baud_rate_b38400,4,5,1,1);
+  g_signal_connect(baud_rate_b38400,"toggled",G_CALLBACK(baud_rate_cb),(gpointer *) B38400);
+
+  // Serial parity
+/*
+  GtkWidget *parity_label =gtk_label_new("Parity:");
+  gtk_widget_show(parity_label);
+  gtk_grid_attach(GTK_GRID(grid),parity_label,0,6,1,1);
+  
+  GtkWidget *parity_none_b=gtk_radio_button_new_with_label(NULL,"None");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (parity_none_b), serial_parity == 0);
+  gtk_widget_show(parity_none_b);
+  gtk_grid_attach(GTK_GRID(grid),parity_none_b,1,6,1,1);
+  g_signal_connect(parity_none_b,"toggled",G_CALLBACK(parity_cb),(gpointer *) 0);
+
+  GtkWidget *parity_even_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(parity_none_b),"Even");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (parity_even_b), serial_parity == 1);
+  gtk_widget_show(parity_even_b);
+  gtk_grid_attach(GTK_GRID(grid),parity_even_b,2,6,1,1);
+  g_signal_connect(parity_even_b,"toggled",G_CALLBACK(parity_cb),(gpointer *) 1);
+
+  GtkWidget *parity_odd_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(parity_even_b),"Odd");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (parity_odd_b), serial_parity == 2);
+  gtk_widget_show(parity_odd_b);
+  gtk_grid_attach(GTK_GRID(grid),parity_odd_b,3,6,1,1);
+  g_signal_connect(parity_odd_b,"toggled",G_CALLBACK(parity_cb),(gpointer *) 1);
+*/
+
+  // Below stays put
+  gtk_container_add(GTK_CONTAINER(content),grid);
+
+  sub_menu=dialog;
+
+  gtk_widget_show_all(dialog);
+
+}
+
diff --git a/rigctl_menu.h b/rigctl_menu.h
new file mode 100644 (file)
index 0000000..bfb2719
--- /dev/null
@@ -0,0 +1,31 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+#include <gtk/gtk.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <string.h>
+
+extern void rigctl_menu(GtkWidget *parent);
+extern char ser_port[];
+extern void disable_rigctl();
+extern void disable_serial();
+
+extern int serial_baud_rate;
+extern int serial_parity;
diff --git a/rit.c b/rit.c
deleted file mode 100644 (file)
index e9091b6..0000000
--- a/rit.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/* Copyright (C)
-* 2015 - John Melton, G0ORX/N6LYT
-*
-* This program is free software; you can redistribute it and/or
-* modify it under the terms of the GNU General Public License
-* as published by the Free Software Foundation; either version 2
-* of the License, or (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software
-* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-*
-*/
-
-#include <gtk/gtk.h>
-#include <semaphore.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "radio.h"
-#include "rit.h"
-#include "vfo.h"
-
-static GtkWidget *parent_window;
-
-static GtkWidget *h_box;
-static GtkWidget *v_box_1;
-static GtkWidget *v_box_2;
-static GtkWidget *ctun_b;
-static GtkWidget *rit_b;
-static GtkWidget *rit_plus_b;
-static GtkWidget *rit_minus_b;
-static gint rit_timer;
-
-static gboolean rit_enabled=FALSE;
-
-static void set_button_text_color(GtkWidget *widget,char *color) {
-  GtkStyleContext *style_context;
-  GtkCssProvider *provider = gtk_css_provider_new ();
-  gchar tmp[64];
-  style_context = gtk_widget_get_style_context(widget);
-  gtk_style_context_add_provider(style_context, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
-  g_snprintf(tmp, sizeof tmp, "GtkButton, GtkLabel { color: %s; }", color);
-  gtk_css_provider_load_from_data(GTK_CSS_PROVIDER(provider), tmp, -1, NULL);
-  g_object_unref (provider);
-}
-
-static gboolean ctun_pressed_event_cb (GtkWidget *widget, GdkEventButton *event, gpointer        data) {
-  ctun=ctun==1?0:1;
-  
-  if(ctun) {
-    set_button_text_color(ctun_b,"red");
-  } else {
-    set_button_text_color(ctun_b,"black");
-    vfo[active_receiver->id].offset=0;
-    set_offset(active_receiver,0);
-    vfo_update(NULL);
-  }
-  return TRUE;
-}
-
-static gboolean rit_timer_cb(gpointer data) {
-  int v=active_receiver->id;
-  if((GtkWidget*)data==rit_plus_b) {
-    vfo[v].rit+=rit_increment;
-  } else {
-    vfo[v].rit-=rit_increment;
-  }
-  if(vfo[v].rit>1000) vfo[v].rit=1000;
-  if(vfo[v].rit<-1000) vfo[v].rit=-1000;
-  vfo_update(NULL);
-  return TRUE;
-}
-
-static gboolean rit_pressed_event_cb (GtkWidget *widget, GdkEventButton *event, gpointer        data) {
-  if(rit_enabled) {
-    rit_enabled=FALSE;
-    set_button_text_color(rit_b,"black");
-    vfo[active_receiver->id].offset=0;
-    gtk_widget_set_sensitive(rit_plus_b,FALSE);
-    gtk_widget_set_sensitive(rit_minus_b,FALSE);
-  } else {
-    rit_enabled=TRUE;
-    set_button_text_color(rit_b,"red");
-    gtk_widget_set_sensitive(rit_plus_b,TRUE);
-    gtk_widget_set_sensitive(rit_minus_b,TRUE);
-  }
-  vfo_update(NULL);
-}
-
-static gboolean rit_step_pressed_event_cb (GtkWidget *widget, GdkEventButton *event, gpointer        data) {
-  int v=active_receiver->id;
-  if(widget==rit_plus_b) {
-    vfo[v].rit+=rit_increment;
-  } else {
-    vfo[v].rit-=rit_increment;
-  }
-  if(vfo[v].rit>1000) vfo[v].rit=1000;
-  if(vfo[v].rit<-1000) vfo[v].rit=-1000;
-  vfo_update(NULL);
-  rit_timer=g_timeout_add(200,rit_timer_cb,widget);
-  return TRUE;
-}
-
-
-static gboolean rit_step_released_event_cb (GtkWidget *widget, GdkEventButton *event, gpointer        data) {
-  g_source_remove(rit_timer);
-  return TRUE;
-}
-
-
-GtkWidget* rit_init(int width,int height,GtkWidget *parent) {
-
-  GdkRGBA black;
-  black.red=0.0;
-  black.green=0.0;
-  black.blue=0.0;
-  black.alpha=0.0;
-
-  fprintf(stderr,"rit_init: width=%d height=%d\n",width,height);
-
-  parent_window=parent;
-
-  h_box=gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0);
-  gtk_widget_set_size_request (h_box, width, height);
-  gtk_widget_override_background_color(h_box, GTK_STATE_NORMAL, &black);
-
-  v_box_2=gtk_box_new(GTK_ORIENTATION_VERTICAL,0);
-  gtk_widget_override_background_color(v_box_2, GTK_STATE_NORMAL, &black);
-
-  rit_plus_b=gtk_button_new_with_label("RIT+");
-  gtk_widget_override_font(rit_plus_b, pango_font_description_from_string("FreeMono Bold 10"));
-  g_signal_connect (rit_plus_b, "pressed", G_CALLBACK(rit_step_pressed_event_cb), NULL);
-  g_signal_connect (rit_plus_b, "released", G_CALLBACK(rit_step_released_event_cb), NULL);
-  gtk_box_pack_start (GTK_BOX(v_box_2),rit_plus_b,TRUE,TRUE,0);
-
-  rit_minus_b=gtk_button_new_with_label("RIT-");
-  gtk_widget_override_font(rit_minus_b, pango_font_description_from_string("FreeMono Bold 10"));
-  g_signal_connect (rit_minus_b, "pressed", G_CALLBACK(rit_step_pressed_event_cb), NULL);
-  g_signal_connect (rit_minus_b, "released", G_CALLBACK(rit_step_released_event_cb), NULL);
-  gtk_box_pack_start (GTK_BOX(v_box_2),rit_minus_b,TRUE,TRUE,0);
-  
-  gtk_widget_set_sensitive(rit_plus_b,FALSE);
-  gtk_widget_set_sensitive(rit_minus_b,FALSE);
-
-  gtk_box_pack_start (GTK_BOX(h_box),v_box_2,TRUE,TRUE,0);
-  
-  v_box_1=gtk_box_new(GTK_ORIENTATION_VERTICAL,0);
-  gtk_widget_override_background_color(v_box_1, GTK_STATE_NORMAL, &black);
-
-  ctun_b=gtk_button_new_with_label("CTUN");
-  gtk_widget_override_font(ctun_b, pango_font_description_from_string("FreeMono Bold 10"));
-  g_signal_connect (ctun_b, "pressed", G_CALLBACK(ctun_pressed_event_cb), NULL);
-  gtk_box_pack_start (GTK_BOX(v_box_1),ctun_b,TRUE,TRUE,0);
-  
-  rit_b=gtk_button_new_with_label("RIT");
-  gtk_widget_override_font(rit_b, pango_font_description_from_string("FreeMono Bold 10"));
-  g_signal_connect (rit_b, "pressed", G_CALLBACK(rit_pressed_event_cb), NULL);
-  gtk_box_pack_start (GTK_BOX(v_box_1),rit_b,TRUE,TRUE,0);
-  
-  gtk_box_pack_start (GTK_BOX(h_box),v_box_1,TRUE,TRUE,0);
-
-  gtk_widget_show_all(h_box);
-
-  return h_box;
-}
index 02e15372e6e7b5629cb39786d32b34c6536ded35..af86bdf8fc7457e081efae17a09c883a141a3bdf 100644 (file)
--- a/rx_menu.c
+++ b/rx_menu.c
@@ -20,6 +20,7 @@
 #include <gtk/gtk.h>
 #include <semaphore.h>
 #include <stdio.h>
+#include <stdint.h>
 #include <string.h>
 
 #include "audio.h"
@@ -37,15 +38,24 @@ static GtkWidget *menu_b=NULL;
 
 static GtkWidget *dialog=NULL;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 dither_cb(GtkWidget *widget, gpointer data) {
   active_receiver->dither=active_receiver->dither==1?0:1;
 }
@@ -59,18 +69,20 @@ static void preamp_cb(GtkWidget *widget, gpointer data) {
 }
 
 static void sample_rate_cb(GtkWidget *widget, gpointer data) {
-  receiver_change_sample_rate(active_receiver,(int)data);
+  receiver_change_sample_rate(active_receiver,(uintptr_t)data);
 }
 
 static void adc_cb(GtkWidget *widget, gpointer data) {
-  receiver_change_adc(active_receiver,(int)data);
+  receiver_change_adc(active_receiver,(uintptr_t)data);
 }
 
 static void local_audio_cb(GtkWidget *widget, gpointer data) {
+fprintf(stderr,"local_audio_cb: rx=%d\n",active_receiver->id);
   if(gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
     if(audio_open_output(active_receiver)==0) {
       active_receiver->local_audio=1;
     } else {
+fprintf(stderr,"local_audio_cb: audio_open_output failed\n");
       active_receiver->local_audio=0;
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
     }
@@ -80,25 +92,34 @@ static void local_audio_cb(GtkWidget *widget, gpointer data) {
       audio_close_output(active_receiver);
     }
   }
+fprintf(stderr,"local_audio_cb: local_audio=%d\n",active_receiver->local_audio);
 }
 
 static void mute_audio_cb(GtkWidget *widget, gpointer data) {
   active_receiver->mute_when_not_active=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
 }
 
+static void mute_radio_cb(GtkWidget *widget, gpointer data) {
+  active_receiver->mute_radio=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+}
+
 static void local_output_changed_cb(GtkWidget *widget, gpointer data) {
   active_receiver->audio_device=(int)(long)data;
+fprintf(stderr,"local_output_changed rx=%d to %d\n",active_receiver->id,active_receiver->audio_device);
   if(active_receiver->local_audio) {
     audio_close_output(active_receiver);
     if(audio_open_output(active_receiver)==0) {
       active_receiver->local_audio=1;
+    } else {
+      active_receiver->local_audio=0;
     }
+fprintf(stderr,"local_output_changed rx=%d local_audio=%d\n",active_receiver->id,active_receiver->local_audio);
   }
 }
 
 static void audio_channel_cb(GtkWidget *widget, gpointer data) {
   if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
-    active_receiver->audio_channel=(int)data;
+    active_receiver->audio_channel=(uintptr_t)data;
   }
 }
 
@@ -110,7 +131,11 @@ void rx_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  char title[64];
+  sprintf(title,"piHPSDR - Receive (RX %d VFO %s)",active_receiver->id,active_receiver->id==0?"A":"B");
+  gtk_window_set_title(GTK_WINDOW(dialog),title);
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -127,14 +152,10 @@ void rx_menu(GtkWidget *parent) {
   //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
   //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
 
-  GtkWidget *close_b=gtk_button_new_with_label("Close RX");
+  GtkWidget *close_b=gtk_button_new_with_label("Close");
   g_signal_connect (close_b, "button_press_event", G_CALLBACK(close_cb), NULL);
   gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
 
-  sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B");
-  GtkWidget *rx_label=gtk_label_new(label);
-  gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1);
-
   int x=0;
 
   switch(protocol) {
@@ -166,7 +187,7 @@ void rx_menu(GtkWidget *parent) {
       gtk_grid_attach(GTK_GRID(grid),sample_rate_384,x,5,1,1);
       g_signal_connect(sample_rate_384,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)384000);
 
-#ifndef GPIO
+#ifndef raspberrypi
       GtkWidget *sample_rate_768=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_384),"768000");
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_768), active_receiver->sample_rate==768000);
       gtk_grid_attach(GTK_GRID(grid),sample_rate_768,x,6,1,1);
@@ -282,7 +303,7 @@ void rx_menu(GtkWidget *parent) {
       }
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (adc_b), active_receiver->adc==i);
       gtk_grid_attach(GTK_GRID(grid),adc_b,x,2+i,1,1);
-      g_signal_connect(adc_b,"pressed",G_CALLBACK(adc_cb),(gpointer *)i);
+      g_signal_connect(adc_b,"pressed",G_CALLBACK(adc_cb),(gpointer)(long)i);
     }
     x++;
   }
@@ -298,17 +319,13 @@ void rx_menu(GtkWidget *parent) {
 
     if(active_receiver->audio_device==-1) active_receiver->audio_device=0;
 
+    GtkWidget *output=NULL;
     for(i=0;i<n_output_devices;i++) {
-      GtkWidget *output;
-      if(i==0) {
-        output=gtk_radio_button_new_with_label(NULL,output_devices[i]);
-      } else {
-        output=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(output),output_devices[i]);
-      }
+      output=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(output),output_devices[i]);
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (output), active_receiver->audio_device==i);
       gtk_widget_show(output);
       gtk_grid_attach(GTK_GRID(grid),output,x,++row,1,1);
-      g_signal_connect(output,"pressed",G_CALLBACK(local_output_changed_cb),(gpointer *)i);
+      g_signal_connect(output,"pressed",G_CALLBACK(local_output_changed_cb),(gpointer)(long)i);
     }
 
     row=0;
@@ -339,6 +356,14 @@ void rx_menu(GtkWidget *parent) {
   gtk_grid_attach(GTK_GRID(grid),mute_audio_b,x,++row,1,1);
   g_signal_connect(mute_audio_b,"toggled",G_CALLBACK(mute_audio_cb),NULL);
   
+  row++;
+
+  GtkWidget *mute_radio_b=gtk_check_button_new_with_label("Mute audio to radio");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mute_radio_b), active_receiver->mute_radio);
+  gtk_widget_show(mute_radio_b);
+  gtk_grid_attach(GTK_GRID(grid),mute_radio_b,x,++row,1,1);
+  g_signal_connect(mute_radio_b,"toggled",G_CALLBACK(mute_radio_cb),NULL);
+
   gtk_container_add(GTK_CONTAINER(content),grid);
 
   sub_menu=dialog;
index 45f956de51e990e188d2942c294bd185fcee16c6..4e82d193062b25e81ee873fd0788f4bd71a5a545 100644 (file)
@@ -24,6 +24,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include <semaphore.h>
+
+#include <wdsp.h>
+
 #include "agc.h"
 #include "band.h"
 #include "channel.h"
 #ifdef FREEDV
 #include "freedv.h"
 #endif
+#ifdef GPIO
 #include "gpio.h"
+#endif
 
 //static float panadapter_max=-60.0;
 //static float panadapter_min=-160.0;
 
 static gfloat filter_left;
 static gfloat filter_right;
+static gfloat cw_frequency;
 
 /* Create a new surface of the appropriate size to store our scribbles */
 static gboolean
@@ -66,7 +72,7 @@ panadapter_configure_event_cb (GtkWidget         *widget,
                                        display_height);
 
   cairo_t *cr=cairo_create(rx->panadapter_surface);
-  cairo_set_source_rgb(cr, 0, 0, 0);
+  cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
   cairo_paint(cr);
   cairo_destroy(cr);
   return TRUE;
@@ -83,11 +89,11 @@ panadapter_draw_cb (GtkWidget *widget,
 {
   RECEIVER *rx=(RECEIVER *)data;
   if(rx->panadapter_surface) {
-    cairo_set_source_surface (cr, rx->panadapter_surface, 00);
+    cairo_set_source_surface (cr, rx->panadapter_surface, 0.0, 0.0);
     cairo_paint (cr);
   }
 
-  return TRUE;
+  return FALSE;
 }
 
 static gboolean panadapter_button_press_event_cb(GtkWidget *widget, GdkEventButton *event, gpointer data) {
@@ -108,6 +114,7 @@ static gboolean panadapter_scroll_event_cb(GtkWidget *widget, GdkEventScroll *ev
 
 void rx_panadapter_update(RECEIVER *rx) {
   int i;
+  int x1,x2;
   int result;
   float *samples;
   float saved_max;
@@ -119,28 +126,73 @@ void rx_panadapter_update(RECEIVER *rx) {
   int display_width=gtk_widget_get_allocated_width (rx->panadapter);
   int display_height=gtk_widget_get_allocated_height (rx->panadapter);
 
+#ifdef FREEDV
+  if(rx->freedv) {
+    display_height=display_height-20;
+  }
+#endif
   samples=rx->pixel_samples;
 
   //clear_panadater_surface();
   cairo_t *cr;
   cr = cairo_create (rx->panadapter_surface);
-  cairo_set_source_rgb (cr, 0, 0, 0);
+  cairo_set_line_width(cr, 1.0);
+  cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
   cairo_rectangle(cr,0,0,display_width,display_height);
   cairo_fill(cr);
   //cairo_paint (cr);
 
+  long long frequency=vfo[rx->id].frequency;
+  long half=(long)rx->sample_rate/2L;
+  long long min_display=frequency-half;
+  long long max_display=frequency+half;
+  BAND *band=band_get_band(vfo[rx->id].band);
+
+  if(vfo[rx->id].band==band60) {
+    for(i=0;i<channel_entries;i++) {
+      long long low_freq=band_channels_60m[i].frequency-(band_channels_60m[i].width/(long long)2);
+      long long hi_freq=band_channels_60m[i].frequency+(band_channels_60m[i].width/(long long)2);
+      x1=(low_freq-min_display)/(long long)rx->hz_per_pixel;
+      x2=(hi_freq-min_display)/(long long)rx->hz_per_pixel;
+      cairo_set_source_rgb (cr, 0.6, 0.3, 0.3);
+      cairo_rectangle(cr, x1, 0.0, x2-x1, (double)display_height);
+      cairo_fill(cr);
+/*
+      cairo_set_source_rgba (cr, 0.5, 1.0, 0.0, 1.0);
+      cairo_move_to(cr,(double)x1,0.0);
+      cairo_line_to(cr,(double)x1,(double)display_height);
+      cairo_stroke(cr);
+      cairo_move_to(cr,(double)x2,0.0);
+      cairo_line_to(cr,(double)x2,(double)display_height);
+      cairo_stroke(cr);
+*/
+    }
+  }
+
   // filter
-  cairo_set_source_rgb (cr, 0.25, 0.25, 0.25);
+  cairo_set_source_rgba (cr, 0.25, 0.25, 0.25, 0.75);
   filter_left=(double)display_width/2.0+(((double)rx->filter_low+vfo[rx->id].offset)/rx->hz_per_pixel);
   filter_right=(double)display_width/2.0+(((double)rx->filter_high+vfo[rx->id].offset)/rx->hz_per_pixel);
   cairo_rectangle(cr, filter_left, 0.0, filter_right-filter_left, (double)display_height);
   cairo_fill(cr);
 
+  if(vfo[rx->id].mode==modeCWU || vfo[rx->id].mode==modeCWL) {
+    if(active) {
+      cairo_set_source_rgb (cr, 1.0, 1.0, 0.0);
+    } else {
+      cairo_set_source_rgb (cr, 0.25, 0.25, 0.0);
+    }
+    cw_frequency=filter_left+((filter_right-filter_left)/2.0);
+    cairo_move_to(cr,cw_frequency,10.0);
+    cairo_line_to(cr,cw_frequency,(double)display_height);
+    cairo_stroke(cr);
+  }
+
   // plot the levels
   if(active) {
-    cairo_set_source_rgb (cr, 0, 1, 1);
+    cairo_set_source_rgb (cr, 0.0, 1.0, 1.0);
   } else {
-    cairo_set_source_rgb (cr, 0, 0.5, 0.5);
+    cairo_set_source_rgb (cr, 0.0, 0.5, 0.5);
   }
 
   double dbm_per_line=(double)display_height/((double)rx->panadapter_high-(double)rx->panadapter_low);
@@ -166,8 +218,6 @@ void rx_panadapter_update(RECEIVER *rx) {
   // plot frequency markers
   long long f;
   long divisor=20000;
-  long half=(long)rx->sample_rate/2L;
-  long long frequency=vfo[rx->id].frequency;
   switch(rx->sample_rate) {
     case 48000:
       divisor=5000L;
@@ -180,7 +230,7 @@ void rx_panadapter_update(RECEIVER *rx) {
       divisor=20000L;
       break;
     case 384000:
-      divisor=25000L;
+      divisor=50000L;
       break;
     case 768000:
       divisor=50000L;
@@ -215,24 +265,23 @@ void rx_panadapter_update(RECEIVER *rx) {
   }
   cairo_stroke(cr);
 
-  // band edges
-  long long min_display=frequency-half;
-  long long max_display=frequency+half;
-  BAND *band=band_get_band(vfo[rx->id].band);
-  if(band->frequencyMin!=0LL) {
-    cairo_set_source_rgb (cr, 1, 0, 0);
-    cairo_set_line_width(cr, 2.0);
-    if((min_display<band->frequencyMin)&&(max_display>band->frequencyMin)) {
-      i=(band->frequencyMin-min_display)/(long long)rx->hz_per_pixel;
-      cairo_move_to(cr,(double)i,0.0);
-      cairo_line_to(cr,(double)i,(double)display_height);
-      cairo_stroke(cr);
-    }
-    if((min_display<band->frequencyMax)&&(max_display>band->frequencyMax)) {
-      i=(band->frequencyMax-min_display)/(long long)rx->hz_per_pixel;
-      cairo_move_to(cr,(double)i,0.0);
-      cairo_line_to(cr,(double)i,(double)display_height);
-      cairo_stroke(cr);
+  if(vfo[rx->id].band!=band60) {
+    // band edges
+    if(band->frequencyMin!=0LL) {
+      cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
+      cairo_set_line_width(cr, 2.0);
+      if((min_display<band->frequencyMin)&&(max_display>band->frequencyMin)) {
+        i=(band->frequencyMin-min_display)/(long long)rx->hz_per_pixel;
+        cairo_move_to(cr,(double)i,0.0);
+        cairo_line_to(cr,(double)i,(double)display_height);
+        cairo_stroke(cr);
+      }
+      if((min_display<band->frequencyMax)&&(max_display>band->frequencyMax)) {
+        i=(band->frequencyMax-min_display)/(long long)rx->hz_per_pixel;
+        cairo_move_to(cr,(double)i,0.0);
+        cairo_line_to(cr,(double)i,(double)display_height);
+        cairo_stroke(cr);
+      }
     }
   }
             
@@ -289,9 +338,9 @@ void rx_panadapter_update(RECEIVER *rx) {
 
   // cursor
   if(active) {
-    cairo_set_source_rgb (cr, 1, 0, 0);
+    cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
   } else {
-    cairo_set_source_rgb (cr, 0.5, 00);
+    cairo_set_source_rgb (cr, 0.5, 0.0, 0.0);
   }
   cairo_set_line_width(cr, 1.0);
   cairo_move_to(cr,(double)(display_width/2.0)+(vfo[rx->id].offset/rx->hz_per_pixel),0.0);
@@ -319,14 +368,14 @@ void rx_panadapter_update(RECEIVER *rx) {
   if(display_filled) {
     cairo_close_path (cr);
     if(active) {
-      cairo_set_source_rgba(cr, 1, 1, 1,0.5);
+      cairo_set_source_rgba(cr, 1.0, 1.0, 1.0,0.5);
     } else {
       cairo_set_source_rgba(cr, 0.5, 0.5, 0.5,0.5);
     }
     cairo_fill_preserve (cr);
   }
   if(active) {
-    cairo_set_source_rgb(cr, 1, 1, 1);
+    cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
   } else {
     cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
   }
@@ -334,37 +383,40 @@ void rx_panadapter_update(RECEIVER *rx) {
   cairo_stroke(cr);
 
 #ifdef FREEDV
-  int mode=rx->mode;
-  if(mode==modeFREEDV) {
-    cairo_set_source_rgb(cr, 0, 1, 0);
-    cairo_set_font_size(cr, 16);
-    cairo_text_extents(cr, freedv_text_data, &extents);
-    cairo_move_to(cr, (double)display_width/2.0-(extents.width/2.0),(double)display_height-2.0);
-    cairo_show_text(cr, freedv_text_data);
+  if(rx->freedv) {
+    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+    cairo_rectangle(cr,0,display_height,display_width,display_height+20);
+    cairo_fill(cr);
+
+    cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);
+    cairo_set_font_size(cr, 18);
+    cairo_move_to(cr, 0.0, (double)display_height+20.0-2.0);
+    cairo_show_text(cr, rx->freedv_text_data);
   }
 #endif
 
 #ifdef GPIO
   if(active) {
-    cairo_set_source_rgb(cr,1,1,0);
-    cairo_set_font_size(cr,12);
+    cairo_set_source_rgb(cr,1.0,1.0,0.0);
+    cairo_set_font_size(cr,16);
     if(ENABLE_E1_ENCODER) {
-      cairo_move_to(cr, display_width-100,20);
+      cairo_move_to(cr, display_width-150,30);
       cairo_show_text(cr, encoder_string[e1_encoder_action]);
     }
 
     if(ENABLE_E2_ENCODER) {
-      cairo_move_to(cr, display_width-100,40);
+      cairo_move_to(cr, display_width-150,50);
       cairo_show_text(cr, encoder_string[e2_encoder_action]);
     }
 
     if(ENABLE_E3_ENCODER) {
-      cairo_move_to(cr, display_width-100,60);
+      cairo_move_to(cr, display_width-150,70);
       cairo_show_text(cr, encoder_string[e3_encoder_action]);
     }
   }
 #endif
 
+
   cairo_destroy (cr);
   gtk_widget_queue_draw (rx->panadapter);
 
diff --git a/signal.c b/signal.c
deleted file mode 100644 (file)
index 9db7c7e..0000000
--- a/signal.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Copyright (C)
-* 2015 - John Melton, G0ORX/N6LYT
-*
-* This program is free software; you can redistribute it and/or
-* modify it under the terms of the GNU General Public License
-* as published by the Free Software Foundation; either version 2
-* of the License, or (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software
-* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-*
-*/
-
-#include <math.h>
-
-#include "radio.h"
-#include "signal.h"
-
-#define PI 3.1415926535897932
-
-double sineWave(double* buf, int samples, double sinphase, double freq) {
-    double phaseStep = freq / (double)sample_rate * 2.0 * PI;
-    double cosval = cos(sinphase);
-    double sinval = sin(sinphase);
-    double cosdelta = cos(phaseStep);
-    double sindelta = sin(phaseStep);
-    int i;
-
-    for (i = 0; i < samples; i++) {
-        double tmpval = cosval * cosdelta - sinval * sindelta;
-        sinval = cosval * sindelta + sinval * cosdelta;
-        cosval = tmpval;
-        buf[i*2] = sinval;
-        sinphase += phaseStep;
-    }
-    return sinphase;
-}
-
-double cosineWave(double* buf, int samples, double cosphase, double freq) {
-    double phaseStep = freq / (double)sample_rate * 2.0 * PI;
-    double cosval = cos(cosphase);
-    double sinval = sin(cosphase);
-    double cosdelta = cos(phaseStep);
-    double sindelta = sin(phaseStep);
-    int i;
-
-    for (i = 0; i < samples; i++) {
-        double tmpval = cosval * cosdelta - sinval * sindelta;
-        sinval = cosval * sindelta + sinval * cosdelta;
-        cosval = tmpval;
-        buf[(i*2)+1] = cosval;
-        cosphase += phaseStep;
-    }
-    return cosphase;
-}
index 4b0290466bee0b3a383d85ec6dd4d78ff24048f7..b91cb498e77af7882621a5a538c7b39021982660 100644 (file)
--- a/sliders.c
+++ b/sliders.c
@@ -23,6 +23,7 @@
 #include <stdlib.h>
 #include <math.h>
 
+#include "receiver.h"
 #include "sliders.h"
 #include "mode.h"
 #include "filter.h"
 #include "channel.h"
 #include "wdsp.h"
 #include "radio.h"
-#include "receiver.h"
+#include "transmitter.h"
 #include "property.h"
 #include "main.h"
+#include "ext.h"
 
 static int width;
 static int height;
@@ -52,8 +54,9 @@ static GtkWidget *sliders;
 #define LINEIN_GAIN 3
 #define AGC_GAIN 4
 #define DRIVE 5
-#define TUNE_DRIVE 6
-#define ATTENUATION 7
+#define ATTENUATION 6
+#define SQUELCH 7
+#define COMP 8
 
 static gint scale_timer;
 static int scale_status=NONE;
@@ -66,40 +69,41 @@ static GtkWidget *attenuation_label;
 static GtkWidget *attenuation_scale;
 static GtkWidget *mic_gain_label;
 static GtkWidget *mic_gain_scale;
-static GtkWidget *linein_gain_label;
-static GtkWidget *linein_gain_scale;
 static GtkWidget *drive_label;
 static GtkWidget *drive_scale;
-static GtkWidget *tune_label;
-static GtkWidget *tune_scale;
+static GtkWidget *squelch_label;
+static GtkWidget *squelch_scale;
+static GtkWidget *squelch_enable;
+static GtkWidget *comp_label;
+static GtkWidget *comp_scale;
+static GtkWidget *comp_enable;
 static GtkWidget *dummy_label;
 
 static GdkRGBA white;
 static GdkRGBA gray;
 
-int linein_changed(void *data) {
+void sliders_update() {
   if(display_sliders) {
     if(mic_linein) {
-      gtk_widget_hide(mic_gain_label);
-      gtk_widget_hide(mic_gain_scale);
-      gtk_widget_show(linein_gain_label);
-      gtk_widget_show(linein_gain_scale);
+      gtk_label_set_text(GTK_LABEL(mic_gain_label),"Linein:");
+      gtk_range_set_range(GTK_RANGE(mic_gain_scale),0.0,31.0);
+      gtk_range_set_value (GTK_RANGE(mic_gain_scale),linein_gain);
     } else {
-      gtk_widget_hide(linein_gain_label);
-      gtk_widget_hide(linein_gain_scale);
-      gtk_widget_show(mic_gain_label);
-      gtk_widget_show(mic_gain_scale);
+      gtk_label_set_text(GTK_LABEL(mic_gain_label),"Mic (dB):");
+      gtk_range_set_range(GTK_RANGE(mic_gain_scale),-10.0,50.0);
+      gtk_range_set_value (GTK_RANGE(mic_gain_scale),mic_gain);
     }
   }
-  return 0;
 }
 
-int active_receiver_changed(void *data) {
+int sliders_active_receiver_changed(void *data) {
   if(display_sliders) {
     gtk_range_set_value(GTK_RANGE(af_gain_scale),active_receiver->volume*100.0);
     gtk_range_set_value (GTK_RANGE(agc_scale),active_receiver->agc_gain);
     gtk_range_set_value (GTK_RANGE(attenuation_scale),active_receiver->attenuation);
+    sliders_update();
   }
+  return FALSE;
 }
 
 int scale_timeout_cb(gpointer data) {
@@ -184,20 +188,23 @@ void set_agc_gain(double value) {
   }
 }
 
-int update_agc_gain(void *data) {
-  set_agc_gain(*(double*)data);
-  free(data);
-  return 0;
+void update_agc_gain(double gain) {
+  set_agc_gain(gain);
 }
 
 static void afgain_value_changed_cb(GtkWidget *widget, gpointer data) {
     active_receiver->volume=gtk_range_get_value(GTK_RANGE(af_gain_scale))/100.0;
-    SetRXAPanelGain1 (active_receiver->id, active_receiver->volume);
+#ifdef FREEDV
+    if(!active_receiver->freedv) {
+#endif
+      SetRXAPanelGain1 (active_receiver->id, active_receiver->volume);
+#ifdef FREEDV
+    }
+#endif
 }
 
-int update_af_gain(void *data) {
+void update_af_gain() {
   set_af_gain(active_receiver->volume);
-  return 0;
 }
 
 void set_af_gain(double value) {
@@ -234,9 +241,13 @@ void set_af_gain(double value) {
 }
 
 static void micgain_value_changed_cb(GtkWidget *widget, gpointer data) {
-    mic_gain=gtk_range_get_value(GTK_RANGE(widget));
-    double gain=pow(10.0, mic_gain / 20.0);
-    SetTXAPanelGain1(transmitter->id,gain);
+    if(mic_linein) {
+      linein_gain=(int)gtk_range_get_value(GTK_RANGE(widget));
+    } else {
+      mic_gain=gtk_range_get_value(GTK_RANGE(widget));
+      double gain=pow(10.0, mic_gain / 20.0);
+      SetTXAPanelGain1(transmitter->id,gain);
+    }
 }
 
 void set_mic_gain(double value) {
@@ -280,14 +291,10 @@ int update_mic_gain(void *data) {
   return 0;
 }
 
-static void lineingain_value_changed_cb(GtkWidget *widget, gpointer data) {
-    linein_gain=(int)gtk_range_get_value(GTK_RANGE(widget));
-}
-
 void set_linein_gain(int value) {
   linein_gain=value;
   if(display_sliders) {
-    gtk_range_set_value (GTK_RANGE(linein_gain_scale),linein_gain);
+    gtk_range_set_value (GTK_RANGE(mic_gain_scale),linein_gain);
   } else {
     if(scale_status!=LINEIN_GAIN) {
       if(scale_status!=NONE) {
@@ -300,20 +307,19 @@ void set_linein_gain(int value) {
       scale_status=LINEIN_GAIN;
       scale_dialog=gtk_dialog_new_with_buttons("Linein Gain",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
       GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
-      linein_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 31.0, 1.00);
-      gtk_widget_set_size_request (linein_gain_scale, 400, 30);
-      gtk_range_set_value (GTK_RANGE(linein_gain_scale),linein_gain);
-      gtk_widget_show(linein_gain_scale);
-      gtk_container_add(GTK_CONTAINER(content),linein_gain_scale);
+      mic_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 31.0, 1.00);
+      gtk_widget_set_size_request (mic_gain_scale, 400, 30);
+      gtk_range_set_value (GTK_RANGE(mic_gain_scale),linein_gain);
+      gtk_widget_show(mic_gain_scale);
+      gtk_container_add(GTK_CONTAINER(content),mic_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(linein_gain_scale),linein_gain);
+      gtk_range_set_value (GTK_RANGE(mic_gain_scale),linein_gain);
       scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
     }
-
   }
 }
 
@@ -365,12 +371,30 @@ int update_drive(void *data) {
   return 0;
 }
 
-void set_tune(double value) {
-  setTuneDrive(value);
+static void squelch_value_changed_cb(GtkWidget *widget, gpointer data) {
+  active_receiver->squelch=gtk_range_get_value(GTK_RANGE(widget));
+  setSquelch(active_receiver);
+}
+
+static void squelch_enable_cb(GtkWidget *widget, gpointer data) {
+  active_receiver->squelch_enable=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+  setSquelch(active_receiver);
+}
+
+static void compressor_value_changed_cb(GtkWidget *widget, gpointer data) {
+  transmitter_set_compressor_level(transmitter,gtk_range_get_value(GTK_RANGE(widget)));
+}
+
+static void compressor_enable_cb(GtkWidget *widget, gpointer data) {
+  transmitter_set_compressor(transmitter,gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)));
+}
+
+void set_squelch(RECEIVER* rx) {
+  setSquelch(active_receiver);
   if(display_sliders) {
-    gtk_range_set_value (GTK_RANGE(tune_scale),value);
+    gtk_range_set_value (GTK_RANGE(squelch_scale),active_receiver->squelch);
   } else {
-    if(scale_status!=TUNE_DRIVE) {
+    if(scale_status!=SQUELCH) {
       if(scale_status!=NONE) {
         g_source_remove(scale_timer);
         gtk_widget_destroy(scale_dialog);
@@ -378,42 +402,66 @@ void set_tune(double value) {
       }
     }
     if(scale_status==NONE) {
-      scale_status=TUNE_DRIVE;
-      scale_dialog=gtk_dialog_new_with_buttons("Tune Drive",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+      scale_status=SQUELCH;
+      scale_dialog=gtk_dialog_new_with_buttons("Squelch",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
       GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
-      tune_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 100.0, 1.00);
-      gtk_widget_set_size_request (tune_scale, 400, 30);
-      gtk_range_set_value (GTK_RANGE(tune_scale),value);
-      gtk_widget_show(tune_scale);
-      gtk_container_add(GTK_CONTAINER(content),tune_scale);
+      squelch_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 100.0, 1.00);
+      gtk_range_set_value (GTK_RANGE(squelch_scale),active_receiver->squelch);
+      gtk_widget_set_size_request (squelch_scale, 400, 30);
+      gtk_widget_show(squelch_scale);
+      gtk_container_add(GTK_CONTAINER(content),squelch_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(tune_scale),value);
+      gtk_range_set_value (GTK_RANGE(squelch_scale),active_receiver->squelch);
       scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
     }
   }
 }
 
-static void tune_value_changed_cb(GtkWidget *widget, gpointer data) {
-  setTuneDrive(gtk_range_get_value(GTK_RANGE(tune_scale)));
+void set_compression(TRANSMITTER* tx) {
+//  if(display_sliders) {
+//    gtk_range_set_value (GTK_RANGE(comp_scale),tx->compressor_level);
+//  } else {
+    if(scale_status!=COMP) {
+      if(scale_status!=NONE) {
+        g_source_remove(scale_timer);
+        gtk_widget_destroy(scale_dialog);
+        scale_status=NONE;
+      }
+    }
+    if(scale_status==NONE) {
+      scale_status=COMP;
+      scale_dialog=gtk_dialog_new_with_buttons("COMP",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+      GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
+      comp_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 20.0, 1.00);
+      gtk_range_set_value (GTK_RANGE(comp_scale),tx->compressor_level);
+      gtk_widget_set_size_request (comp_scale, 400, 30);
+      gtk_widget_show(comp_scale);
+      gtk_container_add(GTK_CONTAINER(content),comp_scale);
+      scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
+      int result=gtk_dialog_run(GTK_DIALOG(scale_dialog));
+    } else {
+      g_source_remove(scale_timer);
+      gtk_range_set_value (GTK_RANGE(comp_scale),tx->compressor_level);
+      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;
+  width=my_width;
+  height=my_height;
 
-    fprintf(stderr,"sliders_init: width=%d height=%d\n", width,height);
+fprintf(stderr,"sliders_init: width=%d height=%d\n", width,height);
 
-    sliders=gtk_grid_new();
-    gtk_widget_set_size_request (sliders, width, height);
-    gtk_grid_set_row_homogeneous(GTK_GRID(sliders), FALSE);
-    gtk_grid_set_column_homogeneous(GTK_GRID(sliders),TRUE);
+  sliders=gtk_grid_new();
+  gtk_widget_set_size_request (sliders, width, height);
+  gtk_grid_set_row_homogeneous(GTK_GRID(sliders), FALSE);
+  gtk_grid_set_column_homogeneous(GTK_GRID(sliders),TRUE);
 
   af_gain_label=gtk_label_new("AF:");
-  //gtk_widget_override_font(af_gain_label, pango_font_description_from_string("Arial 16"));
   gtk_widget_show(af_gain_label);
   gtk_grid_attach(GTK_GRID(sliders),af_gain_label,0,0,1,1);
 
@@ -424,7 +472,6 @@ GtkWidget *sliders_init(int my_width, int my_height) {
   g_signal_connect(G_OBJECT(af_gain_scale),"value_changed",G_CALLBACK(afgain_value_changed_cb),NULL);
 
   agc_gain_label=gtk_label_new("AGC:");
-  //gtk_widget_override_font(agc_gain_label, pango_font_description_from_string("Arial 16"));
   gtk_widget_show(agc_gain_label);
   gtk_grid_attach(GTK_GRID(sliders),agc_gain_label,3,0,1,1);
 
@@ -435,7 +482,6 @@ GtkWidget *sliders_init(int my_width, int my_height) {
   g_signal_connect(G_OBJECT(agc_scale),"value_changed",G_CALLBACK(agcgain_value_changed_cb),NULL);
 
   attenuation_label=gtk_label_new("ATT (dB):");
-  //gtk_widget_override_font(attenuation_label, pango_font_description_from_string("Arial 16"));
   gtk_widget_show(attenuation_label);
   gtk_grid_attach(GTK_GRID(sliders),attenuation_label,6,0,1,1);
 
@@ -446,28 +492,15 @@ GtkWidget *sliders_init(int my_width, int my_height) {
   g_signal_connect(G_OBJECT(attenuation_scale),"value_changed",G_CALLBACK(attenuation_value_changed_cb),NULL);
 
 
-
-  mic_gain_label=gtk_label_new("Mic (dB):");
-  //gtk_widget_override_font(mic_gain_label, pango_font_description_from_string("Arial 16"));
+  mic_gain_label=gtk_label_new(mic_linein?"Linein:":"Mic (dB):");
   gtk_grid_attach(GTK_GRID(sliders),mic_gain_label,0,1,1,1);
 
-  mic_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,-10.0, 50.0, 1.0);
-  gtk_range_set_value (GTK_RANGE(mic_gain_scale),mic_gain);
+  mic_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,mic_linein?0.0:-10.0,mic_linein?31.0:50.0, 1.0);
+  gtk_range_set_value (GTK_RANGE(mic_gain_scale),mic_linein?linein_gain:mic_gain);
   gtk_grid_attach(GTK_GRID(sliders),mic_gain_scale,1,1,2,1);
   g_signal_connect(G_OBJECT(mic_gain_scale),"value_changed",G_CALLBACK(micgain_value_changed_cb),NULL);
 
-  linein_gain_label=gtk_label_new("Linein:");
-  gtk_grid_attach(GTK_GRID(sliders),linein_gain_label,0,1,1,1);
-
-  linein_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 31.0, 1.0);
-  gtk_range_set_value (GTK_RANGE(linein_gain_scale),linein_gain);
-  gtk_widget_show(linein_gain_scale);
-  gtk_grid_attach(GTK_GRID(sliders),linein_gain_scale,1,1,2,1);
-  g_signal_connect(G_OBJECT(linein_gain_scale),"value_changed",G_CALLBACK(lineingain_value_changed_cb),NULL);
-
   drive_label=gtk_label_new("Drive:");
-  //gtk_widget_override_font(drive_label, pango_font_description_from_string("Arial 16"));
-  gtk_widget_show(drive_label);
   gtk_grid_attach(GTK_GRID(sliders),drive_label,3,1,1,1);
 
   drive_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 100.0, 1.0);
@@ -476,21 +509,21 @@ GtkWidget *sliders_init(int my_width, int my_height) {
   gtk_grid_attach(GTK_GRID(sliders),drive_scale,4,1,2,1);
   g_signal_connect(G_OBJECT(drive_scale),"value_changed",G_CALLBACK(drive_value_changed_cb),NULL);
 
-  tune_label=gtk_label_new("Tune:");
-  //gtk_widget_override_font(tune_label, pango_font_description_from_string("Arial 16"));
-  gtk_widget_show(tune_label);
-  gtk_grid_attach(GTK_GRID(sliders),tune_label,6,1,1,1);
-
-  tune_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 100.0, 1.0);
-  gtk_range_set_value (GTK_RANGE(tune_scale),getTuneDrive());
-  gtk_widget_show(tune_scale);
-  gtk_grid_attach(GTK_GRID(sliders),tune_scale,7,1,2,1);
-  g_signal_connect(G_OBJECT(tune_scale),"value_changed",G_CALLBACK(tune_value_changed_cb),NULL);
-
-  dummy_label=gtk_label_new(" ");
-  //gtk_widget_override_font(dummy_label, pango_font_description_from_string("Arial 16"));
-  gtk_widget_show(dummy_label);
-  gtk_grid_attach(GTK_GRID(sliders),dummy_label,9,1,1,1);
+  squelch_label=gtk_label_new("Squelch:");
+  gtk_widget_show(squelch_label);
+  gtk_grid_attach(GTK_GRID(sliders),squelch_label,6,1,1,1);
+
+  squelch_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 100.0, 1.0);
+  gtk_range_set_value (GTK_RANGE(squelch_scale),active_receiver->squelch);
+  gtk_widget_show(squelch_scale);
+  gtk_grid_attach(GTK_GRID(sliders),squelch_scale,7,1,2,1);
+  g_signal_connect(G_OBJECT(squelch_scale),"value_changed",G_CALLBACK(squelch_value_changed_cb),NULL);
+
+  squelch_enable=gtk_check_button_new();
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(squelch_enable),active_receiver->squelch_enable);
+  gtk_widget_show(squelch_enable);
+  gtk_grid_attach(GTK_GRID(sliders),squelch_enable,9,1,1,1);
+  g_signal_connect(squelch_enable,"toggled",G_CALLBACK(squelch_enable_cb),NULL);
 
   return sliders;
 }
index 17aa927166c8b2520a579639e19a998f7a4dc9cd..14b55f51a45d393853591025121a76115c0a4a2a 100644 (file)
--- a/sliders.h
+++ b/sliders.h
 #ifndef _SLIDERS_H
 #define _SLIDERS_H
 
-extern int linein_changed(void *data);
-extern int active_receiver_changed(void *data);
-extern int update_agc_gain(void *);
-extern int update_af_gain(void *);
+extern int sliders_active_receiver_changed(void *data);
+extern void update_agc_gain(double gain);
+extern void update_af_gain();
 extern int update_mic_gain(void *);
 extern int update_drive(void *);
 
@@ -31,8 +30,12 @@ extern void set_agc_gain(double value);
 extern void set_af_gain(double value);
 extern void set_mic_gain(double value);
 extern void set_drive(double drive);
-extern void set_tune(double tune);
+//extern void set_tune(double tune);
 extern void set_attenuation_value(double attenuation);
 extern GtkWidget *sliders_init(int my_width, int my_height);
 
+extern void sliders_update();
+
+extern void set_squelch(RECEIVER* rx);
+
 #endif
index 8b1f98303ab5dfecc781ab2d844e6dc46c521b96..d711fcf24c9f65b26973854d9d4f3697e209f1af 100644 (file)
--- a/soundio.c
+++ b/soundio.c
@@ -26,7 +26,6 @@
 #include <string.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <pthread.h>
 #include <sched.h>
 #include <semaphore.h>
 
diff --git a/splash.c b/splash.c
deleted file mode 100644 (file)
index 0520d5b..0000000
--- a/splash.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Copyright (C)
-* 2015 - John Melton, G0ORX/N6LYT
-*
-* This program is free software; you can redistribute it and/or
-* modify it under the terms of the GNU General Public License
-* as published by the Free Software Foundation; either version 2
-* of the License, or (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software
-* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-*
-*/
-
-#include <gtk/gtk.h>
-#include "version.h"
-
-GtkWidget *grid;
-GtkWidget *status;
-static cairo_surface_t *splash_surface = NULL;
-
-
-/* Close the splash screen */
-void splash_close()
-{
-  gtk_widget_destroy(grid);
-}
-
-GtkWidget *splash_create(char* image_name,int width,int height)
-{
-  GtkWidget  *image;
-
-  grid = gtk_grid_new();
-  gtk_widget_set_size_request(grid, width, height);
-  gtk_grid_set_row_homogeneous(GTK_GRID(grid),FALSE);
-  gtk_grid_set_column_homogeneous(GTK_GRID(grid),FALSE);
-
-  image=gtk_image_new_from_file(image_name);
-  gtk_grid_attach(GTK_GRID(grid), image, 0, 0, 1, 4);
-
-  char build[64];
-  sprintf(build,"build: %s %s",build_date, version);
-
-  GtkWidget *pi_label=gtk_label_new("pihpsdr by John Melton g0orx/n6lyt");
-  gtk_label_set_justify(GTK_LABEL(pi_label),GTK_JUSTIFY_LEFT);
-  gtk_widget_show(pi_label);
-  gtk_grid_attach(GTK_GRID(grid),pi_label,1,0,1,1);
-  GtkWidget *build_date_label=gtk_label_new(build);
-  gtk_label_set_justify(GTK_LABEL(build_date_label),GTK_JUSTIFY_LEFT);
-  gtk_widget_show(build_date_label);
-  gtk_grid_attach(GTK_GRID(grid),build_date_label,1,1,1,1);
-
-  status=gtk_label_new("");
-  gtk_label_set_justify(GTK_LABEL(status),GTK_JUSTIFY_LEFT);
-  gtk_widget_override_font(status, pango_font_description_from_string("FreeMono 18"));
-  gtk_widget_show(status);
-  gtk_grid_attach(GTK_GRID(grid), status, 1, 3, 1, 1);
-
-  return grid;
-}
-
-void splash_status(char *text) {
-  //fprintf(stderr,"splash_status: %s\n",text);
-  gtk_label_set_text(GTK_LABEL(status),text);
-  usleep(10000);
-  while (gtk_events_pending ())
-    gtk_main_iteration ();
-}
index cf1a9fc53f251171fafb821f1a1ad36706e24649..d1d0a873240e04ddb4432fc7eb158d666426520a 100644 (file)
@@ -19,6 +19,8 @@
 
 #include <gtk/gtk.h>
 #include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "new_menu.h"
@@ -29,18 +31,27 @@ static GtkWidget *parent_window=NULL;
 
 static GtkWidget *dialog=NULL;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 gboolean step_select_cb (GtkWidget *widget, gpointer        data) {
-  step=steps[(int)data];
-  vfo_update(NULL);
+  step=steps[(uintptr_t)data];
+  vfo_update();
 }
 
 void step_menu(GtkWidget *parent) {
@@ -49,7 +60,9 @@ void step_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - VFO Step");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -65,7 +78,7 @@ void step_menu(GtkWidget *parent) {
   gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
   gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
 
-  GtkWidget *close_b=gtk_button_new_with_label("Close Step");
+  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);
 
@@ -81,7 +94,7 @@ void step_menu(GtkWidget *parent) {
     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (step_rb), steps[i]==step);
     gtk_widget_show(step_rb);
     gtk_grid_attach(GTK_GRID(grid),step_rb,i%5,1+(i/5),1,1);
-    g_signal_connect(step_rb,"pressed",G_CALLBACK(step_select_cb),(gpointer *)i);
+    g_signal_connect(step_rb,"pressed",G_CALLBACK(step_select_cb),(gpointer)(long)i);
     i++;
   }
 
index 71e79ae844f78ce65e5f18d5f0ca79e749962bbc..80f38718b1bcab05531721af120b5e142b12686a 100644 (file)
@@ -20,6 +20,8 @@
 
 #include <gtk/gtk.h>
 #include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "new_menu.h"
@@ -34,6 +36,7 @@
 #include "vfo.h"
 #include "button_text.h"
 #include "store.h"
+#include "ext.h"
 
 static GtkWidget *parent_window=NULL;
 
@@ -41,17 +44,26 @@ static GtkWidget *dialog=NULL;
 
 GtkWidget *store_button[NUM_OF_MEMORYS];
 
-static gboolean store_close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 gboolean store_select_cb (GtkWidget *widget, gpointer data) {
-   int index = (int) data;
+   int index = (uintptr_t) data;
    fprintf(stderr,"STORE BUTTON PUSHED=%d\n",index);
    char workstr[40];
      
@@ -74,7 +86,7 @@ static gboolean store_select_cb (GtkWidget *widget, gpointer data) {
 }
 
 static gboolean recall_select_cb (GtkWidget *widget, gpointer data) {
-    int index = (int) data;
+    int index = (uintptr_t) data;
     long long new_freq;
     
     //new_freq = mem[index].frequency;
@@ -93,7 +105,7 @@ static gboolean recall_select_cb (GtkWidget *widget, gpointer data) {
     //vfo_band_changed(vfo[active_receiver->id].band);
     vfo_filter_changed(mem[index].filter);
     vfo_mode_changed(mem[index].mode);
-    g_idle_add(vfo_update,NULL);
+    g_idle_add(ext_vfo_update,NULL);
 
 }
 
@@ -107,7 +119,9 @@ void store_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - Store");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -125,20 +139,20 @@ void store_menu(GtkWidget *parent) {
   gtk_grid_set_column_spacing (GTK_GRID(grid),5);
   gtk_grid_set_row_spacing (GTK_GRID(grid),5);
 
-  GtkWidget *close_b=gtk_button_new_with_label("Close Store");
-  g_signal_connect (close_b, "pressed", G_CALLBACK(store_close_cb), NULL);
+  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);
 
   for(i=0;i<NUM_OF_MEMORYS;i++) {
      sprintf(label_str,"Store M%d",i); 
      b=gtk_button_new_with_label(label_str);
-     g_signal_connect(b,"pressed",G_CALLBACK(store_select_cb),(gpointer *) i);
+     g_signal_connect(b,"pressed",G_CALLBACK(store_select_cb),(gpointer)(long)i);
      gtk_grid_attach(GTK_GRID(grid),b,2,i,1,1);
 
      sprintf(label_str,"M%d=%8.6f MHz",i,((double) mem[i].frequency)/1000000.0);
      b=gtk_button_new_with_label(label_str);
      store_button[i]= b;
-     g_signal_connect(b,"pressed",G_CALLBACK(recall_select_cb),(gpointer *) i);
+     g_signal_connect(b,"pressed",G_CALLBACK(recall_select_cb),(gpointer)(long)i);
      gtk_grid_attach(GTK_GRID(grid),b,3,i,1,1);
   }
 
index 197f28ad4c6bc01497b34f9c02a9ba6840c71afd..cacf756d8a9921f52378c99cc273792b8c02716a 100644 (file)
@@ -28,15 +28,24 @@ static GtkWidget *parent_window=NULL;
 
 static GtkWidget *dialog=NULL;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 gboolean test_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   
   int result=check_update();
@@ -56,7 +65,9 @@ void test_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - Test");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -74,7 +85,7 @@ void test_menu(GtkWidget *parent) {
   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 Test");
+  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);
 
index 078f2fd4cebaa7d3f14b011fdec3c799de70a972..025d5de023c812db3f3ca8c70b55db594561c8f1 100644 (file)
--- a/toolbar.c
+++ b/toolbar.c
@@ -20,6 +20,8 @@
 #include <gtk/gtk.h>
 #include <semaphore.h>
 #include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 #ifdef GPIO
 #include "gpio.h"
@@ -32,6 +34,7 @@
 #include "band.h"
 #include "discovered.h"
 #include "new_protocol.h"
+#include "old_protocol.h"
 #include "vfo.h"
 #include "alex.h"
 #include "agc.h"
@@ -46,6 +49,7 @@
 #ifdef RADIOBERRY
 #include "radioberry.h"        
 #endif
+#include "ext.h"       
 
 #define MAX_FUNCTION 3
 int function=0;
@@ -80,11 +84,14 @@ static gint rit_plus_timer=-1;
 static gint rit_minus_timer=-1;
 
 static gboolean rit_timer_cb(gpointer data) {
-  int i=(int)data;
+  int i=(uintptr_t)data;
   vfo[active_receiver->id].rit+=(i*rit_increment);
   if(vfo[active_receiver->id].rit>1000) vfo[active_receiver->id].rit=1000;
   if(vfo[active_receiver->id].rit<-1000) vfo[active_receiver->id].rit=-1000;
-  vfo_update(NULL);
+  if(protocol==NEW_PROTOCOL) {
+    schedule_high_priority();
+  }
+  vfo_update();
   return TRUE;
 }
 
@@ -116,7 +123,7 @@ void update_toolbar_labels() {
       gtk_button_set_label(GTK_BUTTON(sim_s1),"Freq");
       gtk_button_set_label(GTK_BUTTON(sim_s2),"Mem");
       //gtk_button_set_label(GTK_BUTTON(sim_s3),"Vox");
-      gtk_button_set_label(GTK_BUTTON(sim_s3),vfo[active_receiver->id].rit_enabled==0?"RIT On":"RIT Off");
+      gtk_button_set_label(GTK_BUTTON(sim_s3),"RIT");
 
       gtk_button_set_label(GTK_BUTTON(sim_s4),"RIT+");
       gtk_button_set_label(GTK_BUTTON(sim_s5),"RIT-");
@@ -140,10 +147,10 @@ void update_toolbar_labels() {
       } else {
         gtk_button_set_label(GTK_BUTTON(sim_s2),"");
       }
-      gtk_button_set_label(GTK_BUTTON(sim_s3),"");
-      gtk_button_set_label(GTK_BUTTON(sim_s4),"");
-      gtk_button_set_label(GTK_BUTTON(sim_s5),"");
-      gtk_button_set_label(GTK_BUTTON(sim_s6),"");
+      gtk_button_set_label(GTK_BUTTON(sim_s3),"Band");
+      gtk_button_set_label(GTK_BUTTON(sim_s4),"Mode");
+      gtk_button_set_label(GTK_BUTTON(sim_s5),"Filter");
+      gtk_button_set_label(GTK_BUTTON(sim_s6),"Mox");
       if(full_tune) {
         set_button_text_color(sim_s1,"red");
       }
@@ -191,7 +198,7 @@ void ctun_cb (GtkWidget *widget, gpointer data) {
   }
   vfo[id].ctun_frequency=vfo[id].frequency;
   set_offset(active_receiver,vfo[id].offset);
-  vfo_update(NULL);
+  vfo_update();
 }
 
 static void atob_cb (GtkWidget *widget, gpointer data) {
@@ -213,31 +220,36 @@ static void split_cb (GtkWidget *widget, gpointer data) {
   } else {
     tx_set_mode(transmitter,vfo[VFO_A].mode);
   }
-  vfo_update(NULL);
+  vfo_update();
 }
 
 static void rit_enable_cb(GtkWidget *widget, gpointer data) {
   vfo[active_receiver->id].rit_enabled=vfo[active_receiver->id].rit_enabled==1?0:1;
-  gtk_button_set_label(GTK_BUTTON(widget),vfo[active_receiver->id].rit_enabled==0?"RIT On":"RIT Off");
-  vfo_update(NULL);
+  if(protocol==NEW_PROTOCOL) {
+    schedule_high_priority();
+  }
+  vfo_update();
 }
 
 static void rit_cb(GtkWidget *widget, gpointer data) {
-  int i=(int)data;
+  int i=(uintptr_t)data;
   vfo[active_receiver->id].rit+=i*rit_increment;
   if(vfo[active_receiver->id].rit>1000) vfo[active_receiver->id].rit=1000;
   if(vfo[active_receiver->id].rit<-1000) vfo[active_receiver->id].rit=-1000;
-  vfo_update(NULL);
+  if(protocol==NEW_PROTOCOL) {
+    schedule_high_priority();
+  }
+  vfo_update();
   if(i<0) {
-    rit_minus_timer=g_timeout_add(200,rit_timer_cb,(void *)i);
+    rit_minus_timer=g_timeout_add(200,rit_timer_cb,(gpointer)(long)i);
   } else {
-    rit_plus_timer=g_timeout_add(200,rit_timer_cb,(void *)i);
+    rit_plus_timer=g_timeout_add(200,rit_timer_cb,(gpointer)(long)i);
   }
 }
 
 static void rit_clear_cb(GtkWidget *widget, gpointer data) {
   vfo[active_receiver->id].rit=0;
-  vfo_update(NULL);
+  vfo_update();
 }
 
 static void freq_cb(GtkWidget *widget, gpointer data) {
@@ -250,7 +262,7 @@ static void mem_cb(GtkWidget *widget, gpointer data) {
 
 static void vox_cb(GtkWidget *widget, gpointer data) {
   vox_enabled=vox_enabled==1?0:1;
-  vfo_update(NULL);
+  vfo_update();
 }
 
 static void stop() {
@@ -267,6 +279,9 @@ static void stop() {
 #ifdef GPIO
   gpio_close();
 #endif
+#ifdef WIRIINGPI
+  gpio_close();
+#endif
 }
 
 static void yes_cb(GtkWidget *widget, gpointer data) {
@@ -323,241 +338,13 @@ static void exit_cb(GtkWidget *widget, gpointer data) {
 
 }
 
-static void cw_keyer_internal_cb(GtkWidget *widget, gpointer data) {
-  cw_keyer_internal=cw_keyer_internal==1?0:1;
-  cw_changed();
-}
-
-static void cw_keyer_speed_value_changed_cb(GtkWidget *widget, gpointer data) {
-  cw_keyer_speed=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
-  cw_changed();
-}
-
-static void cw_breakin_cb(GtkWidget *widget, gpointer data) {
-  cw_breakin=cw_breakin==1?0:1;
-  cw_changed();
-}
-
-static void cw_keyer_hang_time_value_changed_cb(GtkWidget *widget, gpointer data) {
-  cw_keyer_hang_time=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
-  cw_changed();
-}
-
-static void cw_keys_reversed_cb(GtkWidget *widget, gpointer data) {
-  cw_keys_reversed=cw_keys_reversed==1?0:1;
-  cw_changed();
-}
-
-static void cw_keyer_mode_cb(GtkWidget *widget, gpointer data) {
-  cw_keyer_mode=(int)data;
-  cw_changed();
-}
-
-static void vfo_divisor_value_changed_cb(GtkWidget *widget, gpointer data) {
-  vfo_encoder_divisor=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
-}
-
-static void panadapter_high_value_changed_cb(GtkWidget *widget, gpointer data) {
-  panadapter_high=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
-}
-
-static void panadapter_low_value_changed_cb(GtkWidget *widget, gpointer data) {
-  panadapter_low=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
-}
-
-static void waterfall_high_value_changed_cb(GtkWidget *widget, gpointer data) {
-  waterfall_high=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
-}
-
-static void waterfall_low_value_changed_cb(GtkWidget *widget, gpointer data) {
-  waterfall_low=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
-}
-
-static void waterfall_automatic_cb(GtkWidget *widget, gpointer data) {
-  waterfall_automatic=waterfall_automatic==1?0:1;
-}
-
-static void config_cb(GtkWidget *widget, gpointer data) {
-  GtkWidget *dialog=gtk_dialog_new_with_buttons("Audio",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
-  GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
-  GtkWidget *grid=gtk_grid_new();
-  gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
-  gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
-
-  GtkWidget *display_label=gtk_label_new("Display: ");
-  //gtk_widget_override_font(display_label, pango_font_description_from_string("Arial 18"));
-  gtk_widget_show(display_label);
-  gtk_grid_attach(GTK_GRID(grid),display_label,0,0,1,1);
-
-  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,1,1,1);
-
-  GtkWidget *panadapter_high_r=gtk_spin_button_new_with_range(-220.0,100.0,1.0);
-  //gtk_widget_override_font(panadapter_high_r, pango_font_description_from_string("Arial 18"));
-  gtk_spin_button_set_value(GTK_SPIN_BUTTON(panadapter_high_r),(double)panadapter_high);
-  gtk_widget_show(panadapter_high_r);
-  gtk_grid_attach(GTK_GRID(grid),panadapter_high_r,1,1,1,1);
-  g_signal_connect(panadapter_high_r,"value_changed",G_CALLBACK(panadapter_high_value_changed_cb),NULL);
-
-  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,2,1,1);
-
-  GtkWidget *panadapter_low_r=gtk_spin_button_new_with_range(-220.0,100.0,1.0);
-  //gtk_widget_override_font(panadapter_low_r, pango_font_description_from_string("Arial 18"));
-  gtk_spin_button_set_value(GTK_SPIN_BUTTON(panadapter_low_r),(double)panadapter_low);
-  gtk_widget_show(panadapter_low_r);
-  gtk_grid_attach(GTK_GRID(grid),panadapter_low_r,1,2,1,1);
-  g_signal_connect(panadapter_low_r,"value_changed",G_CALLBACK(panadapter_low_value_changed_cb),NULL);
-
-  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,3,1,1);
-
-  GtkWidget *waterfall_automatic_b=gtk_check_button_new();
-  ////gtk_widget_override_font(waterfall_automatic_b, pango_font_description_from_string("Arial 18"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (waterfall_automatic_b), waterfall_automatic);
-  gtk_widget_show(waterfall_automatic_b);
-  gtk_grid_attach(GTK_GRID(grid),waterfall_automatic_b,1,3,1,1);
-  g_signal_connect(waterfall_automatic_b,"toggled",G_CALLBACK(waterfall_automatic_cb),NULL);
-
-  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,4,1,1);
-
-  GtkWidget *waterfall_high_r=gtk_spin_button_new_with_range(-220.0,100.0,1.0);
-  //gtk_widget_override_font(waterfall_high_r, pango_font_description_from_string("Arial 18"));
-  gtk_spin_button_set_value(GTK_SPIN_BUTTON(waterfall_high_r),(double)waterfall_high);
-  gtk_widget_show(waterfall_high_r);
-  gtk_grid_attach(GTK_GRID(grid),waterfall_high_r,1,4,1,1);
-  g_signal_connect(waterfall_high_r,"value_changed",G_CALLBACK(waterfall_high_value_changed_cb),NULL);
-
-  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,5,1,1);
-
-  GtkWidget *waterfall_low_r=gtk_spin_button_new_with_range(-220.0,100.0,1.0);
-  //gtk_widget_override_font(waterfall_low_r, pango_font_description_from_string("Arial 18"));
-  gtk_spin_button_set_value(GTK_SPIN_BUTTON(waterfall_low_r),(double)waterfall_low);
-  gtk_widget_show(waterfall_low_r);
-  gtk_grid_attach(GTK_GRID(grid),waterfall_low_r,1,5,1,1);
-  g_signal_connect(waterfall_low_r,"value_changed",G_CALLBACK(waterfall_low_value_changed_cb),NULL);
-
-
-  GtkWidget *vfo_encoder_label=gtk_label_new("VFO Encoder: ");
-  //gtk_widget_override_font(vfo_encoder_label, pango_font_description_from_string("Arial 18"));
-  gtk_widget_show(vfo_encoder_label);
-  gtk_grid_attach(GTK_GRID(grid),vfo_encoder_label,0,6,1,1);
-
-  GtkWidget *vfo_divisor_label=gtk_label_new("Divisor: ");
-  //gtk_widget_override_font(vfo_divisor_label, pango_font_description_from_string("Arial 18"));
-  gtk_widget_show(vfo_divisor_label);
-  gtk_grid_attach(GTK_GRID(grid),vfo_divisor_label,0,7,1,1);
-
-  GtkWidget *vfo_divisor=gtk_spin_button_new_with_range(1.0,60.0,1.0);
-  //gtk_widget_override_font(vfo_divisor, pango_font_description_from_string("Arial 18"));
-  gtk_spin_button_set_value(GTK_SPIN_BUTTON(vfo_divisor),(double)vfo_encoder_divisor);
-  gtk_widget_show(vfo_divisor);
-  gtk_grid_attach(GTK_GRID(grid),vfo_divisor,1,7,1,1);
-  g_signal_connect(vfo_divisor,"value_changed",G_CALLBACK(vfo_divisor_value_changed_cb),NULL);
-
-  gtk_container_add(GTK_CONTAINER(content),grid);
-  GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
-  //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 18"));
-  gtk_widget_show_all(dialog);
-
-  g_signal_connect_swapped (dialog,
-                           "response",
-                           G_CALLBACK (gtk_widget_destroy),
-                           dialog);
-
-  int result=gtk_dialog_run(GTK_DIALOG(dialog));
-}
-
-static void cw_cb(GtkWidget *widget, gpointer data) {
-  GtkWidget *dialog=gtk_dialog_new_with_buttons("CW",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
-  GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
-  GtkWidget *grid=gtk_grid_new();
-  //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
-  gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
-
-
-  GtkWidget *cw_keyer_internal_b=gtk_check_button_new_with_label("CW Internal - Speed (WPM)");
-  //gtk_widget_override_font(cw_keyer_internal_b, pango_font_description_from_string("Arial 18"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cw_keyer_internal_b), cw_keyer_internal);
-  gtk_widget_show(cw_keyer_internal_b);
-  gtk_grid_attach(GTK_GRID(grid),cw_keyer_internal_b,0,0,1,1);
-  g_signal_connect(cw_keyer_internal_b,"toggled",G_CALLBACK(cw_keyer_internal_cb),NULL);
-
-  GtkWidget *cw_keyer_speed_b=gtk_spin_button_new_with_range(1.0,60.0,1.0);
-  //gtk_widget_override_font(cw_keyer_speed_b, pango_font_description_from_string("Arial 18"));
-  gtk_spin_button_set_value(GTK_SPIN_BUTTON(cw_keyer_speed_b),(double)cw_keyer_speed);
-  gtk_widget_show(cw_keyer_speed_b);
-  gtk_grid_attach(GTK_GRID(grid),cw_keyer_speed_b,1,0,1,1);
-  g_signal_connect(cw_keyer_speed_b,"value_changed",G_CALLBACK(cw_keyer_speed_value_changed_cb),NULL);
-
-  GtkWidget *cw_breakin_b=gtk_check_button_new_with_label("CW Break In - Delay (ms)");
-  //gtk_widget_override_font(cw_breakin_b, pango_font_description_from_string("Arial 18"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cw_breakin_b), cw_breakin);
-  gtk_widget_show(cw_breakin_b);
-  gtk_grid_attach(GTK_GRID(grid),cw_breakin_b,0,1,1,1);
-  g_signal_connect(cw_breakin_b,"toggled",G_CALLBACK(cw_breakin_cb),NULL);
-
-  GtkWidget *cw_keyer_hang_time_b=gtk_spin_button_new_with_range(0.0,1000.0,1.0);
-  //gtk_widget_override_font(cw_keyer_hang_time_b, pango_font_description_from_string("Arial 18"));
-  gtk_spin_button_set_value(GTK_SPIN_BUTTON(cw_keyer_hang_time_b),(double)cw_keyer_hang_time);
-  gtk_widget_show(cw_keyer_hang_time_b);
-  gtk_grid_attach(GTK_GRID(grid),cw_keyer_hang_time_b,1,1,1,1);
-  g_signal_connect(cw_keyer_hang_time_b,"value_changed",G_CALLBACK(cw_keyer_hang_time_value_changed_cb),NULL);
-  
-  GtkWidget *cw_keyer_straight=gtk_radio_button_new_with_label(NULL,"CW KEYER STRAIGHT");
-  //gtk_widget_override_font(cw_keyer_straight, pango_font_description_from_string("Arial 18"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cw_keyer_straight), cw_keyer_mode==KEYER_STRAIGHT);
-  gtk_widget_show(cw_keyer_straight);
-  gtk_grid_attach(GTK_GRID(grid),cw_keyer_straight,0,2,1,1);
-  g_signal_connect(cw_keyer_straight,"pressed",G_CALLBACK(cw_keyer_mode_cb),(gpointer *)KEYER_STRAIGHT);
-
-  GtkWidget *cw_keyer_mode_a=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(cw_keyer_straight),"CW KEYER MODE A");
-  //gtk_widget_override_font(cw_keyer_mode_a, pango_font_description_from_string("Arial 18"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cw_keyer_mode_a), cw_keyer_mode==KEYER_MODE_A);
-  gtk_widget_show(cw_keyer_mode_a);
-  gtk_grid_attach(GTK_GRID(grid),cw_keyer_mode_a,0,3,1,1);
-  g_signal_connect(cw_keyer_mode_a,"pressed",G_CALLBACK(cw_keyer_mode_cb),(gpointer *)KEYER_MODE_A);
-
-  GtkWidget *cw_keyer_mode_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(cw_keyer_mode_a),"CW KEYER MODE B");
-  //gtk_widget_override_font(cw_keyer_mode_b, pango_font_description_from_string("Arial 18"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cw_keyer_mode_b), cw_keyer_mode==KEYER_MODE_B);
-  gtk_widget_show(cw_keyer_mode_b);
-  gtk_grid_attach(GTK_GRID(grid),cw_keyer_mode_b,0,4,1,1);
-  g_signal_connect(cw_keyer_mode_b,"pressed",G_CALLBACK(cw_keyer_mode_cb),(gpointer *)KEYER_MODE_B);
-
-  gtk_container_add(GTK_CONTAINER(content),grid);
-  GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
-  //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 18"));
-  gtk_widget_show_all(dialog);
-
-  g_signal_connect_swapped (dialog,
-                           "response",
-                           G_CALLBACK (gtk_widget_destroy),
-                           dialog);
-
-  int result=gtk_dialog_run(GTK_DIALOG(dialog));
-}
-
 void lock_cb(GtkWidget *widget, gpointer data) {
   locked=locked==1?0:1;
-  vfo_update(NULL);
+  vfo_update();
 }
 
 void mox_cb(GtkWidget *widget, gpointer data) {
 
-fprintf(stderr,"mox_cb: mox=%d\n",mox);
   if(getTune()==1) {
     setTune(0);
   }
@@ -571,11 +358,10 @@ fprintf(stderr,"mox_cb: mox=%d\n",mox);
   } else {
     transmitter_set_out_of_band(transmitter);
   }
-  g_idle_add(vfo_update,NULL);
+  g_idle_add(ext_vfo_update,NULL);
 }
 
-int mox_update(void *data) {
-  int state=(int)data;
+void mox_update(int state) {
   if(getTune()==1) {
     setTune(0);
   }
@@ -588,26 +374,11 @@ int mox_update(void *data) {
   } else {
     setMox(state);
   }
-  g_idle_add(vfo_update,NULL);
-  return 0;
+  g_idle_add(ext_vfo_update,NULL);
 }
 
-int ptt_update(void *data) {
-
-  return mox_update(data);
-/*
-  int mode;
-  if(split) {
-    mode=vfo[1].mode;
-  } else {
-    mode=vfo[0].mode;
-  }
-  if(protocol==NEW_PROTOCOL || protocol==ORIGINAL_PROTOCOL || (mode!=modeCWU && mode!=modeCWL)) {
-    mox_cb(NULL,NULL);
-  }
-  g_idle_add(vfo_update,NULL);
-  return 0;
-*/
+void ptt_update(int state) {
+  mox_update(state);
 }
 
 void tune_cb(GtkWidget *widget, gpointer data) {
@@ -621,7 +392,24 @@ void tune_cb(GtkWidget *widget, gpointer data) {
   } else {
     transmitter_set_out_of_band(transmitter);
   }
-  vfo_update(NULL);
+  g_idle_add(ext_vfo_update,NULL);
+}
+
+void tune_update(int state) {
+  if(getMox()==1) {
+    setMox(0);
+  }
+  if(state) {
+    setTune(0);
+    if(canTransmit() || tx_out_of_band) {
+      setTune(1);
+    } else {
+      transmitter_set_out_of_band(transmitter);
+    }
+  } else {
+    setTune(state);
+  }
+  g_idle_add(ext_vfo_update,NULL);
 }
 
 void sim_s1_pressed_cb(GtkWidget *widget, gpointer data) {
@@ -711,6 +499,7 @@ void sim_s3_pressed_cb(GtkWidget *widget, gpointer data) {
       rit_enable_cb(widget,data);
       break;
     case 3:
+      band_cb(widget,data);
       break;
   }
 }
@@ -743,6 +532,7 @@ void sim_s4_pressed_cb(GtkWidget *widget, gpointer data) {
       }
       break;
     case 3:
+      mode_cb(widget,data);
       break;
   }
 }
@@ -779,6 +569,7 @@ void sim_s5_pressed_cb(GtkWidget *widget, gpointer data) {
       }
       break;
     case 3:
+      filter_cb(widget,data);
       break;
   }
 }
@@ -825,6 +616,7 @@ void sim_s6_released_cb(GtkWidget *widget, gpointer data) {
     case 2:
       break;
     case 3:
+      mox_cb((GtkWidget *)NULL, (gpointer)NULL);
       break;
   }
 }
@@ -848,7 +640,7 @@ void sim_function_cb(GtkWidget *widget, gpointer data) {
     function=0;
   }
   update_toolbar_labels();
-  vfo_update(NULL);
+  vfo_update();
 }
 
 GtkWidget *toolbar_init(int my_width, int my_height, GtkWidget* parent) {
index 203b606884a7cf035ab0a5fd7f2201b281473f29..38b2487ad376bb603bdc40a85ccd48ca2537fe8f 100644 (file)
--- a/toolbar.h
+++ b/toolbar.h
@@ -24,8 +24,9 @@ extern int function;
 
 
 void update_toolbar_labels();
-int ptt_update(void *data);
-int mox_update(void *data);
+void ptt_update(int state);
+void mox_update(int state);
+void tune_update(int state);
 void tune_cb(GtkWidget *widget, gpointer data);
 
 void sim_mox_cb(GtkWidget *widget, gpointer data);
index 3a9420a18ab048144787f1d150e801732d7c9664..0e3adced3649456a6c5177d63fa216ece8bb9f7e 100644 (file)
 #include "property.h"
 #include "radio.h"
 #include "vfo.h"
+#include "vox.h"
 #include "meter.h"
+#include "toolbar.h"
 #include "tx_panadapter.h"
 #include "waterfall.h"
+#include "receiver.h"
 #include "transmitter.h"
+#include "new_protocol.h"
+#include "old_protocol.h"
+#ifdef FREEDV
+#include "freedv.h"
+#endif
+#include "audio_waterfall.h"
+#include "ext.h"
 
 #define min(x,y) (x<y?x:y)
 #define max(x,y) (x<y?y:x)
 static int filterLow;
 static int filterHigh;
 
+static int waterfall_samples=0;
+static int waterfall_resample=8;
+
 static gint update_out_of_band(gpointer data) {
   TRANSMITTER *tx=(TRANSMITTER *)data;
   tx->out_of_band=0;
-  vfo_update(NULL);
+  vfo_update();
   return FALSE;
 }
 
@@ -57,6 +70,32 @@ void transmitter_set_out_of_band(TRANSMITTER *tx) {
   tx->out_of_band_timer_id=gdk_threads_add_timeout_full(G_PRIORITY_HIGH_IDLE,1000,update_out_of_band, tx, NULL);
 }
 
+void transmitter_set_deviation(TRANSMITTER *tx) {
+  SetTXAFMDeviation(tx->id, (double)tx->deviation);
+}
+
+void transmitter_set_am_carrier_level(TRANSMITTER *tx) {
+  SetTXAAMCarrierLevel(tx->id, tx->am_carrier_level);
+}
+
+void transmitter_set_ctcss(TRANSMITTER *tx,int run,double frequency) {
+  tx->ctcss=run;
+  tx->ctcss_frequency=frequency;
+fprintf(stderr,"transmitter_set_ctcss: ctcss_frequency=%f run=%d\n",tx->ctcss_frequency,tx->ctcss);
+  SetTXACTCSSFreq(tx->id, tx->ctcss_frequency);
+  SetTXACTCSSRun(tx->id, tx->ctcss);
+}
+
+void transmitter_set_compressor_level(TRANSMITTER *tx,double level) {
+  tx->compressor_level=level;
+  SetTXACompressorGain(tx->id, tx->compressor_level);
+}
+
+void transmitter_set_compressor(TRANSMITTER *tx,int state) {
+  tx->compressor=state;
+  SetTXACompressorRun(tx->id, tx->compressor);
+}
+
 void reconfigure_transmitter(TRANSMITTER *tx,int height) {
   gtk_widget_set_size_request(tx->panadapter, tx->width, height);
 }
@@ -78,6 +117,13 @@ void transmitter_save_state(TRANSMITTER *tx) {
   sprintf(value,"%d",tx->alex_antenna);
   setProperty(name,value);
 
+  sprintf(name,"transmitter.%d.panadapter_low",tx->id);
+  sprintf(value,"%d",tx->panadapter_low);
+  setProperty(name,value);
+  sprintf(name,"transmitter.%d.panadapter_high",tx->id);
+  sprintf(value,"%d",tx->panadapter_high);
+  setProperty(name,value);
+
   sprintf(name,"transmitter.%d.local_microphone",tx->id);
   sprintf(value,"%d",tx->local_microphone);
   setProperty(name,value);
@@ -88,6 +134,54 @@ void transmitter_save_state(TRANSMITTER *tx) {
   sprintf(name,"transmitter.%d.low_latency",tx->id);
   sprintf(value,"%d",tx->low_latency);
   setProperty(name,value);
+#ifdef PURESIGNAL
+  sprintf(name,"transmitter.%d.puresignal",tx->id);
+  sprintf(value,"%d",tx->puresignal);
+  setProperty(name,value);
+  sprintf(name,"transmitter.%d.auto_on",tx->id);
+  sprintf(value,"%d",tx->auto_on);
+  setProperty(name,value);
+  sprintf(name,"transmitter.%d.single_on",tx->id);
+  sprintf(value,"%d",tx->single_on);
+  setProperty(name,value);
+#endif
+  sprintf(name,"transmitter.%d.ctcss",tx->id);
+  sprintf(value,"%d",tx->ctcss);
+  setProperty(name,value);
+  sprintf(name,"transmitter.%d.ctcss_frequency",tx->id);
+  sprintf(value,"%f",tx->ctcss_frequency);
+  setProperty(name,value);
+  sprintf(name,"transmitter.%d.deviation",tx->id);
+  sprintf(value,"%d",tx->deviation);
+  setProperty(name,value);
+  sprintf(name,"transmitter.%d.am_carrier_level",tx->id);
+  sprintf(value,"%f",tx->am_carrier_level);
+  setProperty(name,value);
+#ifdef FREEDV
+  if(strlen(tx->freedv_text_data)>0) {
+    sprintf(name,"transmitter.%d.freedv_text_data",tx->id);
+    sprintf(value,"%s",tx->freedv_text_data);
+    setProperty(name,value);
+  }
+#endif
+  sprintf(name,"transmitter.%d.drive",tx->id);
+  sprintf(value,"%d",tx->drive);
+  setProperty(name,value);
+  sprintf(name,"transmitter.%d.tune_percent",tx->id);
+  sprintf(value,"%d",tx->tune_percent);
+  setProperty(name,value);
+  sprintf(name,"transmitter.%d.tune_use_drive",tx->id);
+  sprintf(value,"%d",tx->tune_use_drive);
+  setProperty(name,value);
+  sprintf(name,"transmitter.%d.drive_level",tx->id);
+  sprintf(value,"%d",tx->drive_level);
+  setProperty(name,value);
+  sprintf(name,"transmitter.%d.compressor",tx->id);
+  sprintf(value,"%d",tx->compressor);
+  setProperty(name,value);
+  sprintf(name,"transmitter.%d.compressor_level",tx->id);
+  sprintf(value,"%f",tx->compressor_level);
+  setProperty(name,value);
 }
 
 void transmitter_restore_state(TRANSMITTER *tx) {
@@ -107,6 +201,13 @@ void transmitter_restore_state(TRANSMITTER *tx) {
   value=getProperty(name);
   if(value) tx->alex_antenna=atoi(value);
 
+  sprintf(name,"transmitter.%d.panadapter_low",tx->id);
+  value=getProperty(name);
+  if(value) tx->panadapter_low=atoi(value);
+  sprintf(name,"transmitter.%d.panadapter_high",tx->id);
+  value=getProperty(name);
+  if(value) tx->panadapter_high=atoi(value);
+
   sprintf(name,"transmitter.%d.local_microphone",tx->id);
   value=getProperty(name);
   if(value) tx->local_microphone=atoi(value);
@@ -116,24 +217,86 @@ void transmitter_restore_state(TRANSMITTER *tx) {
   sprintf(name,"transmitter.%d.low_latency",tx->id);
   value=getProperty(name);
   if(value) tx->low_latency=atoi(value);
+#ifdef PURESIGNAL
+  sprintf(name,"transmitter.%d.puresignal",tx->id);
+  value=getProperty(name);
+  if(value) tx->puresignal=atoi(value);
+  sprintf(name,"transmitter.%d.auto_on",tx->id);
+  value=getProperty(name);
+  if(value) tx->auto_on=atoi(value);
+  sprintf(name,"transmitter.%d.single_on",tx->id);
+  value=getProperty(name);
+  if(value) tx->single_on=atoi(value);
+#endif
+  sprintf(name,"transmitter.%d.ctcss",tx->id);
+  value=getProperty(name);
+  if(value) tx->ctcss=atoi(value);
+  sprintf(name,"transmitter.%d.ctcss_frequency",tx->id);
+  value=getProperty(name);
+  if(value) tx->ctcss_frequency=atof(value);
+  sprintf(name,"transmitter.%d.deviation",tx->id);
+  value=getProperty(name);
+  if(value) tx->deviation=atoi(value);
+  sprintf(name,"transmitter.%d.am_carrier_level",tx->id);
+  value=getProperty(name);
+  if(value) tx->am_carrier_level=atof(value);
+#ifdef FREEDV
+  sprintf(name,"transmitter.%d.freedv_text_data",tx->id);
+  value=getProperty(name);
+  if(value) strcpy(tx->freedv_text_data,value);
+#endif
+  sprintf(name,"transmitter.%d.drive",tx->id);
+  value=getProperty(name);
+  if(value) tx->drive=atoi(value);
+  sprintf(name,"transmitter.%d.tune_percent",tx->id);
+  value=getProperty(name);
+  if(value) tx->tune_percent=atoi(value);
+  sprintf(name,"transmitter.%d.tune_use_drive",tx->id);
+  value=getProperty(name);
+  if(value) tx->tune_use_drive=atoi(value);
+  sprintf(name,"transmitter.%d.drive_level",tx->id);
+  value=getProperty(name);
+  if(value) tx->drive_level=atoi(value);
+  sprintf(name,"transmitter.%d.compressor",tx->id);
+  value=getProperty(name);
+  if(value) tx->compressor=atoi(value);
+  sprintf(name,"transmitter.%d.compressor_level",tx->id);
+  value=getProperty(name);
+  if(value) tx->compressor_level=atof(value);
 }
 
-static gint update_display(gpointer data) {
+static gboolean update_display(gpointer data) {
   TRANSMITTER *tx=(TRANSMITTER *)data;
   int rc;
-  double fwd;
-  double rev;
-  double exciter;
 
+  int i;
+
+//fprintf(stderr,"update_display: tx id=%d\n",tx->id);
   if(tx->displaying) {
-    GetPixels(tx->id,0,tx->pixel_samples,&rc);
+#ifdef AUDIO_SAMPLES
+    if(audio_samples!=NULL) {
+      GetPixels(CHANNEL_AUDIO,0,audio_samples,&rc);
+      if(rc) {
+        audio_waterfall_update();
+      }
+    }
+#endif
+#ifdef PURESIGNAL
+    if(tx->puresignal && tx->feedback) {
+      RECEIVER *tx_feedback=receiver[PS_TX_FEEDBACK];
+      GetPixels(tx_feedback->id,0,tx_feedback->pixel_samples,&rc);
+      memcpy(tx->pixel_samples,tx_feedback->pixel_samples,sizeof(float)*tx->pixels);
+    } else {
+#endif
+      GetPixels(tx->id,0,tx->pixel_samples,&rc);
+#ifdef PURESIGNAL
+    }
+#endif
     if(rc) {
       tx_panadapter_update(tx);
-    } else {
-//fprintf(stderr,"tx: update_display: GetPixels: id=%d returned %d\n",tx->id,rc);
     }
 
-    double alc=GetTXAMeter(tx->id, alc);
+    transmitter->alc=GetTXAMeter(tx->id, alc);
     double constant1=3.3;
     double constant2=0.095;
 
@@ -177,17 +340,17 @@ static gint update_display(gpointer data) {
       }
       double v1;
       v1=((double)power/4095.0)*constant1;
-      fwd=(v1*v1)/constant2;
+      transmitter->fwd=(v1*v1)/constant2;
 
       power=exciter_power;
       v1=((double)power/4095.0)*constant1;
-      exciter=(v1*v1)/constant2;
+      transmitter->exciter=(v1*v1)/constant2;
 
-      rev=0.0;
+      transmitter->rev=0.0;
       if(alex_forward_power!=0) {
         power=alex_reverse_power;
         v1=((double)power/4095.0)*constant1;
-        rev=(v1*v1)/constant2;
+        transmitter->rev=(v1*v1)/constant2;
       }
     } else {
       switch(device) {
@@ -233,21 +396,21 @@ static gint update_display(gpointer data) {
       }
       double v1;
       v1=((double)power/4095.0)*constant1;
-      fwd=(v1*v1)/constant2;
+      transmitter->fwd=(v1*v1)/constant2;
 
       power=exciter_power;
       v1=((double)power/4095.0)*constant1;
-      exciter=(v1*v1)/constant2;
+      transmitter->exciter=(v1*v1)/constant2;
 
-      rev=0.0;
+      transmitter->rev=0.0;
       if(alex_forward_power!=0) {
         power=alex_reverse_power;
         v1=((double)power/4095.0)*constant1;
-        rev=(v1*v1)/constant2;
+        transmitter->rev=(v1*v1)/constant2;
       }
     } 
 
-    meter_update(POWER,fwd,rev,exciter,alc);
+    meter_update(POWER,transmitter->fwd,transmitter->rev,transmitter->exciter,transmitter->alc);
 
     return TRUE; // keep going
   }
@@ -306,19 +469,6 @@ static void init_analyzer(TRANSMITTER *tx) {
 
 }
 
-#ifdef INCLUDED
-void transmitter_change_sample_rate(TRANSMITTER *tx,int sample_rate) {
-  SetChannelState(tx->id,0,1);
-  tx->mic_sample_rate=sample_rate;
-  tx->output_samples=tx->buffer_size/(tx->mic_sample_rate/48000);
-  free(tx->mic_input_buffer);
-  tx->mic_input_buffer=malloc(sizeof(double)*2*tx->buffer_size);
-  init_analyzer(tx);
-fprintf(stderr,"transmitter_change_sample_rate: id=%d rate=%d output_samples=%d\n",tx->id, tx->mic_sample_rate, tx->output_samples);
-  SetChannelState(tx->id,1,0);
-}
-#endif
-
 static void create_visual(TRANSMITTER *tx) {
  
   fprintf(stderr,"transmitter: create_visual: id=%d\n",tx->id);
@@ -331,6 +481,8 @@ static void create_visual(TRANSMITTER *tx) {
     gtk_fixed_put(GTK_FIXED(tx->panel),tx->panadapter,0,0);
   }
 
+  gtk_widget_show_all(tx->panel);
+
 }
 
 TRANSMITTER *create_transmitter(int id, int buffer_size, int fft_size, int fps, int width, int height) {
@@ -348,18 +500,16 @@ TRANSMITTER *create_transmitter(int id, int buffer_size, int fft_size, int fps,
        if(protocol==ORIGINAL_PROTOCOL) {
 #endif
     tx->mic_sample_rate=48000;
-//    tx->mic_sample_rate=receiver[0]->sample_rate;
     tx->mic_dsp_rate=48000;
     tx->iq_output_rate=48000;
-//    tx->output_samples=tx->buffer_size/(tx->mic_sample_rate/48000);
     tx->output_samples=tx->buffer_size;
-    tx->pixels=width;
+    tx->pixels=width; // to allow 48k to 24k conversion
   } else {
     tx->mic_sample_rate=48000;
-    tx->mic_dsp_rate=48000;
+    tx->mic_dsp_rate=96000;
     tx->iq_output_rate=192000;
     tx->output_samples=tx->buffer_size*4;
-    tx->pixels=width*4; // to allow 192k to 48k conversion
+    tx->pixels=width*4; // to allow 192k to 24k conversion
   }
 
   tx->width=width;
@@ -367,8 +517,8 @@ TRANSMITTER *create_transmitter(int id, int buffer_size, int fft_size, int fps,
   tx->display_panadapter=1;
   tx->display_waterfall=0;
 
-  tx->panadapter_high=20;
-  tx->panadapter_low=-80;
+  tx->panadapter_high=0;
+  tx->panadapter_low=-60;
 
   tx->displaying=0;
   
@@ -383,13 +533,36 @@ fprintf(stderr,"create_transmitter: id=%d buffer_size=%d mic_sample_rate=%d mic_
 
   tx->low_latency=0;
 
+#ifdef PURESIGNAL
+  tx->puresignal=0;
+  tx->feedback=0;
+  tx->twotone=0;
+  tx->auto_on=0;
+  tx->single_on=0;
+#endif
+
+  tx->ctcss=0;
+  tx->ctcss_frequency=100.0;
+
+  tx->deviation=2500;
+  tx->am_carrier_level=0.5;
+
+#ifdef FREEDV
+  strcpy(tx->freedv_text_data,"Call, Name and Location");
+  tx->freedv_samples=0;
+#endif
+
+  tx->drive=50;
+  tx->tune_percent=10;
+  tx->tune_use_drive=0;
+
+  tx->compressor=0;
+  tx->compressor_level=0.0;
+
+  tx->local_microphone=0;
+
   transmitter_restore_state(tx);
 
-  if(split) {
-    tx->mode=vfo[VFO_B].mode;
-  } else {
-    tx->mode=vfo[VFO_A].mode;
-  }
 
   // allocate buffers
 fprintf(stderr,"transmitter: allocate buffers: mic_input_buffer=%d iq_output_buffer=%d pixels=%d\n",tx->buffer_size,tx->output_samples,tx->pixels);
@@ -397,6 +570,7 @@ fprintf(stderr,"transmitter: allocate buffers: mic_input_buffer=%d iq_output_buf
   tx->iq_output_buffer=malloc(sizeof(double)*2*tx->output_samples);
   tx->samples=0;
   tx->pixel_samples=malloc(sizeof(float)*tx->pixels);
+fprintf(stderr,"transmitter: allocate buffers: mic_input_buffer=%p iq_output_buffer=%p pixels=%p\n",tx->mic_input_buffer,tx->iq_output_buffer,tx->pixel_samples);
 
   fprintf(stderr,"create_transmitter: OpenChannel id=%d buffer_size=%d fft_size=%d sample_rate=%d dspRate=%d outputRate=%d\n",
               tx->id,
@@ -416,17 +590,18 @@ fprintf(stderr,"transmitter: allocate buffers: mic_input_buffer=%d iq_output_buf
               0, // run
               0.010, 0.025, 0.0, 0.010, 0);
 
-fprintf(stderr,"TXASetNC: %d\n",tx->fft_size);
   TXASetNC(tx->id, tx->fft_size);
-fprintf(stderr,"TXASetMP: %d\n",tx->low_latency);
   TXASetMP(tx->id, tx->low_latency);
 
-  SetTXAMode(tx->id, tx->mode);
-  tx_set_filter(tx,tx_filter_low,tx_filter_high);
+
+  int mode=vfo[VFO_A].mode;
+  if(split) {
+    mode=vfo[VFO_B].mode;
+  }
+
   SetTXABandpassWindow(tx->id, 1);
   SetTXABandpassRun(tx->id, 1);
 
-  SetTXAFMDeviation(tx->id,(double)deviation);
   SetTXAFMEmphPosition(tx->id,pre_emphasize);
 
   SetTXACFIRRun(tx->id, protocol==NEW_PROTOCOL?1:0); // turned on if new protocol
@@ -436,14 +611,14 @@ fprintf(stderr,"TXASetMP: %d\n",tx->low_latency);
   } else {
     SetTXAEQRun(tx->id, 0);
   }
-  SetTXACTCSSRun(tx->id, 0);
+
+  transmitter_set_ctcss(tx,tx->ctcss,tx->ctcss_frequency);
   SetTXAAMSQRun(tx->id, 0);
-  SetTXACompressorRun(tx->id, 0);
   SetTXAosctrlRun(tx->id, 0);
 
   SetTXAALCAttack(tx->id, 1);
   SetTXAALCDecay(tx->id, 10);
-  SetTXAALCSt(tx->id, tx_alc);
+  SetTXAALCSt(tx->id, 1); // turn it on (always on)
 
   SetTXALevelerAttack(tx->id, 1);
   SetTXALevelerDecay(tx->id, 500);
@@ -457,6 +632,7 @@ fprintf(stderr,"TXASetMP: %d\n",tx->low_latency);
 
   SetTXAPostGenMode(tx->id, 0);
   SetTXAPostGenToneMag(tx->id, tone_level);
+  SetTXAPostGenTTMag(tx->id, tone_level,tone_level);
   SetTXAPostGenToneFreq(tx->id, 0.0);
   SetTXAPostGenRun(tx->id, 0);
 
@@ -464,6 +640,13 @@ fprintf(stderr,"TXASetMP: %d\n",tx->low_latency);
   SetTXAPanelGain1(tx->id,gain);
   SetTXAPanelRun(tx->id, 1);
 
+  SetTXAFMDeviation(tx->id, (double)tx->deviation);
+  SetTXAAMCarrierLevel(tx->id, tx->am_carrier_level);
+
+  SetTXACompressorGain(tx->id, tx->compressor_level);
+  SetTXACompressorRun(tx->id, tx->compressor);
+
+  tx_set_mode(tx,mode);
 
   XCreateAnalyzer(tx->id, &rc, 262144, 1, 1, "");
   if (rc != 0) {
@@ -492,6 +675,7 @@ void tx_set_filter(TRANSMITTER *tx,int low,int high) {
   } else {
     mode=vfo[0].mode;
   }
+//fprintf(stderr,"tx_set_filter: tx=%p mode=%d low=%d high=%d\n",tx,mode,low,high);
   switch(mode) {
     case modeLSB:
     case modeCWL:
@@ -512,7 +696,7 @@ void tx_set_filter(TRANSMITTER *tx,int low,int high) {
       tx->filter_high=high;
       break;
     case modeFMN:
-      if(deviation==2500) {
+      if(tx->deviation==2500) {
         tx->filter_low=-4000;
         tx->filter_high=4000;
       } else {
@@ -553,7 +737,7 @@ static void full_tx_buffer(TRANSMITTER *tx) {
 
   switch(protocol) {
 #ifdef RADIOBERRY
-       case RADIOBERRY_PROTOCOL:
+    case RADIOBERRY_PROTOCOL:
 #endif
     case ORIGINAL_PROTOCOL:
       gain=32767.0;  // 16 bit
@@ -563,83 +747,59 @@ static void full_tx_buffer(TRANSMITTER *tx) {
       break;
   }
 
-  if(vox_enabled || vox_setting) {
-    if(split) {
-      mode=vfo[1].mode;
-    } else {
-      mode=vfo[0].mode;
-    }
-    switch(mode) {
-      case modeLSB:
-      case modeUSB:
-      case modeDSB:
-      case modeFMN:
-      case modeAM:
-      case modeSAM:
-#ifdef FREEDV
-      case modeFREEDV:
-#endif
-        update_vox(tx);
-        break;
-    }
-  }
+  update_vox(tx);
 
   fexchange0(tx->id, tx->mic_input_buffer, tx->iq_output_buffer, &error);
   if(error!=0) {
     fprintf(stderr,"full_tx_buffer: id=%d fexchange0: error=%d\n",tx->id,error);
   }
 
+#ifdef PURESIGNAL
+  if(tx->displaying && !(tx->puresignal && tx->feedback)) {
+#else
   if(tx->displaying) {
+#endif
     Spectrum0(1, tx->id, 0, 0, tx->iq_output_buffer);
   }
 
-if(isTransmitting()) {
-#ifdef FREEDV
-  int mode;
-  if(split) {
-    mode=vfo[VFO_B].mode;
-  } else {
-    mode=vfo[VFO_A].mode;
-  }
-
-  if(mode==modeFREEDV) {
-    gain=8388607.0;
-  }
-#endif
+  if(isTransmitting()) {
 
-  if(radio->device==NEW_DEVICE_ATLAS && atlas_penelope) {
-    if(tune) {
-      gain=gain*tune_drive;
-    } else {
-      gain=gain*(double)drive;
+    if(radio->device==NEW_DEVICE_ATLAS && atlas_penelope) {
+      if(tune && !transmitter->tune_use_drive) {
+        gain=gain*((double)transmitter->drive_level*100.0/(double)transmitter->tune_percent);
+      } else {
+        gain=gain*(double)transmitter->drive_level;
+      }
     }
-  }
 
-  for(j=0;j<tx->output_samples;j++) {
-    isample=(long)(tx->iq_output_buffer[j*2]*gain);
-    qsample=(long)(tx->iq_output_buffer[(j*2)+1]*gain);
-    switch(protocol) {
-      case ORIGINAL_PROTOCOL:
-        old_protocol_iq_samples(isample,qsample);
-        break;
-      case NEW_PROTOCOL:
-        new_protocol_iq_samples(isample,qsample);
-        break;
+    for(j=0;j<tx->output_samples;j++) {
+      double is=tx->iq_output_buffer[j*2];
+      double qs=tx->iq_output_buffer[(j*2)+1];
+      isample=is>=0.0?(long)floor(is*gain+0.5):(long)ceil(is*gain-0.5);
+      qsample=qs>=0.0?(long)floor(qs*gain+0.5):(long)ceil(qs*gain-0.5);
+      switch(protocol) {
+        case ORIGINAL_PROTOCOL:
+          old_protocol_iq_samples(isample,qsample);
+          break;
+        case NEW_PROTOCOL:
+          new_protocol_iq_samples(isample,qsample);
+          break;
 #ifdef RADIOBERRY
-     case RADIOBERRY_PROTOCOL:
-        radioberry_protocol_iq_samples(isample,qsample);
-        break;
+        case RADIOBERRY_PROTOCOL:
+          radioberry_protocol_iq_samples(isample,qsample);
+          break;
 #endif
+      }
     }
   }
-  }
 
 }
 
 void add_mic_sample(TRANSMITTER *tx,short mic_sample) {
-  double mic_sample_double;
   int mode;
-  long sample;
+  double sample;
+  double mic_sample_double;
+  int i,s;
 
   if(split) {
     mode=vfo[1].mode;
@@ -647,35 +807,128 @@ void add_mic_sample(TRANSMITTER *tx,short mic_sample) {
     mode=vfo[0].mode;
   }
 
-  switch(mode) {
-#ifdef FREEDV
-    case modeFREEDV:
-      break;
+  if(mode==modeCWL || mode==modeCWU || tune) {
+    mic_sample_double=0.0;
+  } else {
+    //long sam=mic_sample<<16;
+    //sample=(double)sam;
+    //mic_sample_double=(1.0 / 2147483648.0) * sample;
+    mic_sample_double=(double)mic_sample/32768.0;
+  }
+  tx->mic_input_buffer[tx->samples*2]=mic_sample_double;
+  tx->mic_input_buffer[(tx->samples*2)+1]=0.0; //mic_sample_double;
+  tx->samples++;
+  if(tx->samples==tx->buffer_size) {
+    full_tx_buffer(tx);
+    tx->samples=0;
+  }
+  
+#ifdef AUDIO_WATERFALL
+  if(audio_samples!=NULL && isTransmitting()) {
+    if(waterfall_samples==0) {
+       audio_samples[audio_samples_index]=(float)mic_sample;
+       audio_samples_index++;
+       if(audio_samples_index>=AUDIO_WATERFALL_SAMPLES) {
+         //Spectrum(CHANNEL_AUDIO,0,0,audio_samples,audio_samples);
+         audio_samples_index=0;
+     }
+     }
+     waterfall_samples++;
+     if(waterfall_samples==waterfall_resample) {
+       waterfall_samples=0;
+     }
+   }
 #endif
-    default:
-      if(mode==modeCWL || mode==modeCWU || tune) {
-        mic_sample_double=0.0;
-      } else {
-        sample=mic_sample<<16;
-        mic_sample_double=(1.0 / 2147483648.0) * (double)(sample);
+}
+
+#ifdef PURESIGNAL
+void add_ps_iq_samples(TRANSMITTER *tx, double i_sample_tx,double q_sample_tx, double i_sample_rx, double q_sample_rx) {
+  RECEIVER *tx_feedback=receiver[PS_TX_FEEDBACK];
+  RECEIVER *rx_feedback=receiver[PS_RX_FEEDBACK];
+
+//fprintf(stderr,"add_ps_iq_samples: samples=%d i_rx=%f q_rx=%f i_tx=%f q_tx=%f\n",rx_feedback->samples, i_sample_rx,q_sample_rx,i_sample_tx,q_sample_tx);
+
+  tx_feedback->iq_input_buffer[tx_feedback->samples*2]=i_sample_tx;
+  tx_feedback->iq_input_buffer[(tx_feedback->samples*2)+1]=q_sample_tx;
+  rx_feedback->iq_input_buffer[rx_feedback->samples*2]=i_sample_rx;
+  rx_feedback->iq_input_buffer[(rx_feedback->samples*2)+1]=q_sample_rx;
+
+  tx_feedback->samples=tx_feedback->samples+1;
+  rx_feedback->samples=rx_feedback->samples+1;
+
+  if(rx_feedback->samples>=rx_feedback->buffer_size) {
+    if(isTransmitting()) {
+      pscc(transmitter->id, rx_feedback->buffer_size, tx_feedback->iq_input_buffer, rx_feedback->iq_input_buffer);
+      if(transmitter->displaying) {
+        if(transmitter->feedback) {
+          Spectrum0(1, tx_feedback->id, 0, 0, tx_feedback->iq_input_buffer);
+        //} else {
+        //  Spectrum0(1, rx_feedback->id, 0, 0, rx_feedback->iq_input_buffer);
+        }
       }
-//fprintf(stderr,"add_mic_sample: id=%d sample=%f (%d,%ld)\n",tx->id,mic_sample_double,mic_sample,sample);
-      tx->mic_input_buffer[tx->samples*2]=mic_sample_double;
-      tx->mic_input_buffer[(tx->samples*2)+1]=mic_sample_double;
-      tx->samples++;
-      if(tx->samples==tx->buffer_size) {
-        full_tx_buffer(tx);
-        tx->samples=0;
+    }
+    rx_feedback->samples=0;
+    tx_feedback->samples=0;
+  }
+}
+#endif
+
+#ifdef FREEDV
+void add_freedv_mic_sample(TRANSMITTER *tx, short mic_sample) {
+  int i,s;
+
+  //if(active_receiver->freedv && isTransmitting() && !tune) {
+  if(!tune) {
+    if(tx->freedv_samples==0) {
+      //int modem_samples=mod_sample_freedv(mic_sample);
+      short vs=(short)((double)mic_sample*pow(10.0, mic_gain / 20.0));
+      int modem_samples=mod_sample_freedv(vs);
+      if(modem_samples!=0) {
+        for(s=0;s<modem_samples;s++) {
+          for(i=0;i<freedv_resample;i++) { // 8K to 48K
+            add_mic_sample(tx,mod_out[s]);
+          }
+        }
       }
-      break;
+    }
+    tx->freedv_samples++;
+    if(tx->freedv_samples>=freedv_resample) {
+      tx->freedv_samples=0;
+    }
   }
 }
+#endif
 
 void tx_set_displaying(TRANSMITTER *tx,int state) {
   tx->displaying=state;
   if(state) {
-fprintf(stderr,"start tx display update timer: %d\n", 1000/tx->fps);
-    tx->update_timer_id=gdk_threads_add_timeout_full(G_PRIORITY_HIGH_IDLE,1000/tx->fps, update_display, tx, NULL);
+    tx->update_timer_id=gdk_threads_add_timeout_full(G_PRIORITY_HIGH_IDLE,1000/tx->fps, update_display, (gpointer)tx, NULL);
+  }
+}
+
+#ifdef PURESIGNAL
+void tx_set_ps(TRANSMITTER *tx,int state) {
+  tx->puresignal=state;
+  if(state) {
+    SetPSControl(tx->id, 0, 0, 1, 0);
+  } else {
+    SetPSControl(tx->id, 1, 0, 0, 0);
   }
+  vfo_update();
 }
 
+void tx_set_twotone(TRANSMITTER *tx,int state) {
+  transmitter->twotone=state;
+  if(state) {
+    SetTXAPostGenMode(transmitter->id, 1);
+    SetTXAPostGenRun(transmitter->id, 1);
+  } else {
+    SetTXAPostGenRun(transmitter->id, 0);
+  }
+  g_idle_add(ext_mox_update,(gpointer)(long)state);
+}
+
+void tx_set_ps_sample_rate(TRANSMITTER *tx,int rate) {
+  SetPSFeedbackRate (tx->id,rate);
+}
+#endif
index 20aaf990661f50f4a5000bf57d1bbea821941e3e..6d670a3c2aeaf9888c05f9b5852d9503b9f3a419 100644 (file)
@@ -75,18 +75,73 @@ typedef struct _transmitter {
 
   int low_latency;
 
+#ifdef PURESIGNAL
+  int puresignal;
+  int twotone;
+  int feedback;
+  int auto_on;
+  int single_on;
+#endif
+
+  double ctcss_frequency;
+  int ctcss;
+
+  int deviation;
+
+  double am_carrier_level;
+
+  int attenuation;
+
+  int drive;
+  int tune_use_drive;
+  int tune_percent;
+
+  int drive_level;
+#ifdef FREEDV
+  char freedv_text_data[64];
+  int freedv_text_index;
+  int freedv_samples;
+#endif
+
+  int compressor;
+  double compressor_level;
+
+  double fwd;
+  double exciter;
+  double rev;
+  double alc;
+
+  int x;
+  int y;
+
 } TRANSMITTER;
 
 extern TRANSMITTER *create_transmitter(int id, int buffer_size, int fft_size, int fps, int width, int height);
 
 void reconfigure_transmitter(TRANSMITTER *tx,int height);
 
+
 extern void tx_set_mode(TRANSMITTER* tx,int m);
 extern void tx_set_filter(TRANSMITTER *tx,int low,int high);
+extern void transmitter_set_deviation(TRANSMITTER *tx);
+extern void transmitter_set_am_carrier_level(TRANSMITTER *tx);
 extern void tx_set_pre_emphasize(TRANSMITTER *tx,int state);
+extern void transmitter_set_ctcss(TRANSMITTER *tx,int run,double frequency);
 
 extern void add_mic_sample(TRANSMITTER *tx,short mic_sample);
+extern void add_freedv_mic_sample(TRANSMITTER *tx,short mic_sample);
 
 extern void transmitter_save_state(TRANSMITTER *tx);
 extern void transmitter_set_out_of_band(TRANSMITTER *tx);
+extern void tx_set_displaying(TRANSMITTER *tx,int state);
+
+extern void tx_set_ps(TRANSMITTER *tx,int state);
+extern void tx_set_twotone(TRANSMITTER *tx,int state);
+
+extern void transmitter_set_compressor_level(TRANSMITTER *tx,double level);
+extern void transmitter_set_compressor(TRANSMITTER *tx,int state);
+
+extern void tx_set_ps_sample_rate(TRANSMITTER *tx,int rate);
+extern void add_ps_iq_samples(TRANSMITTER *tx, double i_sample_0,double q_sample_0, double i_sample_1, double q_sample_1);
 #endif
index 0ba3f00840e12928f49b078c05b88633fec9cc82..ffad2a29cac59e947091c9f5fdbe47d484d23346 100644 (file)
--- a/tx_menu.c
+++ b/tx_menu.c
@@ -24,6 +24,7 @@
 #include "radio.h"
 #include "sliders.h"
 #include "transmitter.h"
+#include "ext.h"
 
 static GtkWidget *parent_window=NULL;
 
@@ -31,18 +32,39 @@ static GtkWidget *dialog=NULL;
 
 static GtkWidget *last_filter;
 
+static GtkWidget *micin_b;
 static GtkWidget *linein_b;
 static GtkWidget *micboost_b;
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static GtkWidget *tune_label;
+static GtkWidget *tune_scale;
+
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 comp_enable_cb(GtkWidget *widget, gpointer data) {
+  transmitter->compressor=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+}
+
+static void comp_cb(GtkWidget *widget, gpointer data) {
+  transmitter_set_compressor_level(transmitter,gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)));
+}
+
 static void tx_spin_low_cb (GtkWidget *widget, gpointer data) {
   tx_filter_low=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
   tx_set_filter(transmitter,tx_filter_low,tx_filter_high);
@@ -57,20 +79,48 @@ static void micboost_cb(GtkWidget *widget, gpointer data) {
   mic_boost=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
 }
 
-static void linein_cb(GtkWidget *widget, gpointer data) {
-  mic_linein=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
-  g_idle_add(linein_changed,NULL);
+static void panadapter_high_value_changed_cb(GtkWidget *widget, gpointer data) {
+  transmitter->panadapter_high=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
+}
+
+static void panadapter_low_value_changed_cb(GtkWidget *widget, gpointer data) {
+  transmitter->panadapter_low=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
+}
+
+static void am_carrier_level_value_changed_cb(GtkWidget *widget, gpointer data) {
+  transmitter->am_carrier_level=gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget));
+  transmitter_set_am_carrier_level(transmitter);
+}
+
+static void ctcss_cb (GtkWidget *widget, gpointer data) {
+  int state=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+  transmitter_set_ctcss(transmitter,state,transmitter->ctcss_frequency);
+}
+
+static void ctcss_spin_cb (GtkWidget *widget, gpointer data) {
+  double frequency=gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget));
+  transmitter_set_ctcss(transmitter,transmitter->ctcss,frequency);
+}
+
+static void tune_use_drive_cb (GtkWidget *widget, gpointer data) {
+  transmitter->tune_use_drive=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+}
+
+static void tune_percent_cb (GtkWidget *widget, gpointer data) {
+  transmitter->tune_percent=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
 }
 
 static void local_microphone_cb(GtkWidget *widget, gpointer data) {
   if(gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
     if(audio_open_input()==0) {
       transmitter->local_microphone=1;
+      gtk_widget_hide(micin_b);
       gtk_widget_hide(linein_b);
       gtk_widget_hide(micboost_b);
     } else {
       transmitter->local_microphone=0;
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
+      gtk_widget_show(micin_b);
       gtk_widget_show(linein_b);
       gtk_widget_show(micboost_b);
     }
@@ -78,12 +128,23 @@ static void local_microphone_cb(GtkWidget *widget, gpointer data) {
     if(transmitter->local_microphone) {
       transmitter->local_microphone=0;
       audio_close_input();
+      gtk_widget_show(micin_b);
       gtk_widget_show(linein_b);
       gtk_widget_show(micboost_b);
     }
   }
 }
 
+static void micin_changed(GtkWidget *widget, gpointer data) {
+  mic_linein=0;
+  g_idle_add(ext_sliders_update,NULL);
+}
+
+static void linein_changed(GtkWidget *widget, gpointer data) {
+  mic_linein=1;
+  g_idle_add(ext_sliders_update,NULL);
+}
+
 static void local_input_changed_cb(GtkWidget *widget, gpointer data) {
   transmitter->input_device=(int)(long)data;
   if(transmitter->local_microphone) {
@@ -101,6 +162,10 @@ static gboolean emp_cb (GtkWidget *widget, gpointer data) {
   tx_set_pre_emphasize(transmitter,pre_emphasize);
 }
 
+static void tune_value_changed_cb(GtkWidget *widget, gpointer data) {
+  setTuneDrive(gtk_range_get_value(GTK_RANGE(tune_scale)));
+}
+
 void tx_menu(GtkWidget *parent) {
   GtkWidget *b;
   int i;
@@ -109,7 +174,9 @@ void tx_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - Transmit");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -122,8 +189,8 @@ void tx_menu(GtkWidget *parent) {
 
   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_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);
 
@@ -134,16 +201,85 @@ void tx_menu(GtkWidget *parent) {
   g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
   gtk_grid_attach(GTK_GRID(grid),close_b,col,row,1,1);
 
-  col++;
-
-  GtkWidget *label=gtk_label_new("Transmit");
-  gtk_grid_attach(GTK_GRID(grid),label,col,row,1,1);
-
   row++;
   col=0;
 
+#ifdef RADIOBERRY
+  if(protocol==ORIGINAL_PROTOCOL || protocol==NEW_PROTOCOL || protocol==RADIOBERRY_PROTOCOL) {
+#else
+  if(protocol==ORIGINAL_PROTOCOL || protocol==NEW_PROTOCOL) {
+#endif
+
+    micin_b=gtk_radio_button_new_with_label_from_widget(NULL,"Mic In");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (micin_b), mic_linein==0);
+    gtk_widget_show(micin_b);
+    gtk_grid_attach(GTK_GRID(grid),micin_b,col,row,1,1);
+    g_signal_connect(micin_b,"pressed",G_CALLBACK(micin_changed),NULL);
+
+    col++;
+
+    linein_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(micin_b),"Line In");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (linein_b), mic_linein==1);
+    gtk_widget_show(linein_b);
+    gtk_grid_attach(GTK_GRID(grid),linein_b,col,row,1,1);
+    g_signal_connect(linein_b,"pressed",G_CALLBACK(linein_changed),NULL);
+
+    row++;
+    col=0;
+
+    micboost_b=gtk_check_button_new_with_label("Mic Boost (radio only)");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (micboost_b), mic_boost);
+    gtk_grid_attach(GTK_GRID(grid),micboost_b,col,row,2,1);
+    g_signal_connect(micboost_b,"toggled",G_CALLBACK(micboost_cb),NULL);
+
+    row++;
+    col=0;
+
+    GtkWidget *comp_enable=gtk_check_button_new_with_label("Compression (dB):");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (comp_enable), transmitter->compressor);
+    gtk_grid_attach(GTK_GRID(grid),comp_enable,col,row,1,1);
+    g_signal_connect(comp_enable,"toggled",G_CALLBACK(comp_enable_cb),NULL);
+
+    col++;
+
+    GtkWidget *comp=gtk_spin_button_new_with_range(0.0,20.0,1.0);
+    gtk_spin_button_set_value(GTK_SPIN_BUTTON(comp),(double)transmitter->compressor_level);
+    gtk_grid_attach(GTK_GRID(grid),comp,col,row,1,1);
+    g_signal_connect(comp,"value-changed",G_CALLBACK(comp_cb),NULL);
+
+    row++;
+    col=0;
 
-  label=gtk_label_new("Filter: ");
+  }
+
+  if(n_input_devices>0) {
+    GtkWidget *local_microphone_b=gtk_check_button_new_with_label("Local Microphone Input");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (local_microphone_b), transmitter->local_microphone);
+    gtk_widget_show(local_microphone_b);
+    gtk_grid_attach(GTK_GRID(grid),local_microphone_b,col,row++,2,1);
+    g_signal_connect(local_microphone_b,"toggled",G_CALLBACK(local_microphone_cb),NULL);
+
+    if(transmitter->input_device==-1) {
+      transmitter->input_device=0;
+    }
+
+    GtkWidget *input=NULL;
+    for(i=0;i<n_input_devices;i++) {
+      input=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(input),input_devices[i]);
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (input), transmitter->input_device==i);
+      gtk_widget_show(input);
+      gtk_grid_attach(GTK_GRID(grid),input,col,row++,2,1);
+      g_signal_connect(input,"pressed",G_CALLBACK(local_input_changed_cb),(gpointer)(long)i);
+    }
+  }
+
+  row=1;
+  col=3;
+
+  GtkWidget *label=gtk_label_new("TX Filter: ");
+#ifdef GTK316
+  gtk_label_set_xalign(GTK_LABEL(label),0);
+#endif
   gtk_grid_attach(GTK_GRID(grid),label,col,row,1,1);
 
   col++;
@@ -160,58 +296,111 @@ void tx_menu(GtkWidget *parent) {
   gtk_grid_attach(GTK_GRID(grid),tx_spin_high,col,row,1,1);
   g_signal_connect(tx_spin_high,"value-changed",G_CALLBACK(tx_spin_high_cb),NULL);
 
+
   row++;
-  col=0;
+  col=3;
 
-#ifdef RADIOBERRY
-       if(protocol==ORIGINAL_PROTOCOL || protocol==NEW_PROTOCOL || protocol==RADIOBERRY_PROTOCOL) {
-#else
-       if(protocol==ORIGINAL_PROTOCOL || protocol==NEW_PROTOCOL) {
+  GtkWidget *panadapter_high_label=gtk_label_new("Panadapter High: ");
+#ifdef GTK316
+  gtk_label_set_xalign(GTK_LABEL(panadapter_high_label),0);
 #endif
-    linein_b=gtk_check_button_new_with_label("Mic Line In (ACC connector)");
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (linein_b), mic_linein);
-    gtk_grid_attach(GTK_GRID(grid),linein_b,col,++row,3,1);
-    g_signal_connect(linein_b,"toggled",G_CALLBACK(linein_cb),NULL);
+  gtk_widget_show(panadapter_high_label);
+  gtk_grid_attach(GTK_GRID(grid),panadapter_high_label,col,row,1,1);
 
-    micboost_b=gtk_check_button_new_with_label("Mic Boost (radio only)");
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (micboost_b), mic_boost);
-    gtk_grid_attach(GTK_GRID(grid),micboost_b,col,++row,3,1);
-    g_signal_connect(micboost_b,"toggled",G_CALLBACK(micboost_cb),NULL);
+  col++;
 
-  }
+  GtkWidget *panadapter_high_r=gtk_spin_button_new_with_range(-220.0,100.0,1.0);
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON(panadapter_high_r),(double)transmitter->panadapter_high);
+  gtk_widget_show(panadapter_high_r);
+  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);
 
-  if(n_input_devices>0) {
-    GtkWidget *local_microphone_b=gtk_check_button_new_with_label("Local Microphone Input");
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (local_microphone_b), transmitter->local_microphone);
-    gtk_widget_show(local_microphone_b);
-    gtk_grid_attach(GTK_GRID(grid),local_microphone_b,col,++row,3,1);
-    g_signal_connect(local_microphone_b,"toggled",G_CALLBACK(local_microphone_cb),NULL);
+  row++;
+  col=3;
 
-    if(transmitter->input_device==-1) transmitter->input_device=0;
+  GtkWidget *panadapter_low_label=gtk_label_new("Panadapter Low: ");
+#ifdef GTK316
+  gtk_label_set_xalign(GTK_LABEL(panadapter_low_label),0);
+#endif
+  gtk_widget_show(panadapter_low_label);
+  gtk_grid_attach(GTK_GRID(grid),panadapter_low_label,col,row,1,1);
 
-    for(i=0;i<n_input_devices;i++) {
-      GtkWidget *input;
-      if(i==0) {
-        input=gtk_radio_button_new_with_label(NULL,input_devices[i]);
-      } else {
-        input=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(input),input_devices[i]);
-      }
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (input), transmitter->input_device==i);
-      gtk_widget_show(input);
-      gtk_grid_attach(GTK_GRID(grid),input,col,++row,3,1);
-      g_signal_connect(input,"pressed",G_CALLBACK(local_input_changed_cb),(gpointer *)i);
-    }
-  }
+  col++;
+
+  GtkWidget *panadapter_low_r=gtk_spin_button_new_with_range(-220.0,100.0,1.0);
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON(panadapter_low_r),(double)transmitter->panadapter_low);
+  gtk_widget_show(panadapter_low_r);
+  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;
+  col=3;
+
+  GtkWidget *am_carrier_level_label=gtk_label_new("AM Carrier Level: ");
+#ifdef GTK316
+  gtk_label_set_xalign(GTK_LABEL(am_carrier_level_label),0);
+#endif
+  gtk_widget_show(am_carrier_level_label);
+  gtk_grid_attach(GTK_GRID(grid),am_carrier_level_label,col,row,1,1);
+
+  col++;
+
+  GtkWidget *am_carrier_level=gtk_spin_button_new_with_range(0.0,1.0,0.1);
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON(am_carrier_level),(double)transmitter->am_carrier_level);
+  gtk_widget_show(am_carrier_level);
+  gtk_grid_attach(GTK_GRID(grid),am_carrier_level,col,row,1,1);
+  g_signal_connect(am_carrier_level,"value_changed",G_CALLBACK(am_carrier_level_value_changed_cb),NULL);
+
+  row++;
+  col=3;
 
   GtkWidget *emp_b=gtk_check_button_new_with_label("FM TX Pre-emphasize before limiting");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (emp_b), pre_emphasize);
   gtk_widget_show(emp_b);
-  gtk_grid_attach(GTK_GRID(grid),emp_b,col,row,3,1);
+  gtk_grid_attach(GTK_GRID(grid),emp_b,col,row,2,1);
   g_signal_connect(emp_b,"toggled",G_CALLBACK(emp_cb),NULL);
 
+  row++;
+  col=3;
+
+  GtkWidget *ctcss_b=gtk_check_button_new_with_label("CTCSS Enable");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ctcss_b), transmitter->ctcss);
+  gtk_widget_show(ctcss_b);
+  gtk_grid_attach(GTK_GRID(grid),ctcss_b,col,row,1,1);
+  g_signal_connect(ctcss_b,"toggled",G_CALLBACK(ctcss_cb),NULL);
+
+  col++;
+  GtkWidget *ctcss_spin=gtk_spin_button_new_with_range(67.0,250.3,0.1);
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON(ctcss_spin),(double)transmitter->ctcss_frequency);
+  gtk_grid_attach(GTK_GRID(grid),ctcss_spin,col,row,1,1);
+  g_signal_connect(ctcss_spin,"value-changed",G_CALLBACK(ctcss_spin_cb),NULL);
+  
+  row++;
+  col=3;
+
+  GtkWidget *tune_use_drive_b=gtk_check_button_new_with_label("Tune use drive");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tune_use_drive_b), transmitter->tune_use_drive);
+  gtk_widget_show(tune_use_drive_b);
+  gtk_grid_attach(GTK_GRID(grid),tune_use_drive_b,col,row,1,1);
+  g_signal_connect(tune_use_drive_b,"toggled",G_CALLBACK(tune_use_drive_cb),NULL);
+
+  row++;
+  col=3;
+  
+  GtkWidget *tune_percent_label=gtk_label_new("Tune Percent: ");
+#ifdef GTK316
+  gtk_label_set_xalign(GTK_LABEL(tune_percent_label),0);
+#endif
+  gtk_widget_show(tune_percent_label);
+  gtk_grid_attach(GTK_GRID(grid),tune_percent_label,col,row,1,1);
+
+  col++;
+  GtkWidget *tune_percent=gtk_spin_button_new_with_range(1.0,100.0,1.0);
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON(tune_percent),(double)transmitter->tune_percent);
+  gtk_grid_attach(GTK_GRID(grid),tune_percent,col,row,1,1);
+  g_signal_connect(tune_percent,"value-changed",G_CALLBACK(tune_percent_cb),NULL);
+
+
   gtk_container_add(GTK_CONTAINER(content),grid);
 
   sub_menu=dialog;
index 40408c6c251fcfdc760e8e4a36c7601d7c857a3d..7920fe3b73f9df2ced3b7dfe15935cd6fcd00758 100644 (file)
--- a/tx_menu.h
+++ b/tx_menu.h
@@ -15,4 +15,5 @@
 *
 */
 
-void tx_menu(GtkWidget *parent);
+extern void tx_menu(GtkWidget *parent);
+extern void set_tune(double value);
index 10c09f13ccf7516a8324b784e119f9f2dce9731d..28eb3fc86c563b5640ef33f4fdef98ed84e62f03 100644 (file)
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <semaphore.h>
+#include <wdsp.h>
 #include "agc.h"
 #include "band.h"
 #include "channel.h"
@@ -51,7 +52,7 @@ static gfloat filter_right;
 
 /* Create a new surface of the appropriate size to store our scribbles */
 static gboolean
-panadapter_configure_event_cb (GtkWidget         *widget,
+tx_panadapter_configure_event_cb (GtkWidget         *widget,
             GdkEventConfigure *event,
             gpointer           data)
 {
@@ -68,7 +69,7 @@ panadapter_configure_event_cb (GtkWidget         *widget,
                                        display_height);
 
   cairo_t *cr=cairo_create(tx->panadapter_surface);
-  cairo_set_source_rgb(cr, 0, 0, 0);
+  cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
   cairo_paint(cr);
   cairo_destroy(cr);
   return TRUE;
@@ -79,20 +80,20 @@ panadapter_configure_event_cb (GtkWidget         *widget,
  * clipped to only draw the exposed areas of the widget
  */
 static gboolean
-panadapter_draw_cb (GtkWidget *widget,
+tx_panadapter_draw_cb (GtkWidget *widget,
  cairo_t   *cr,
  gpointer   data)
 {
   TRANSMITTER *tx=(TRANSMITTER *)data;
   if(tx->panadapter_surface) {
-    cairo_set_source_surface (cr, tx->panadapter_surface, 00);
+    cairo_set_source_surface (cr, tx->panadapter_surface, 0.0, 0.0);
     cairo_paint (cr);
   }
-  return TRUE;
+  return FALSE;
 }
 
 static gboolean
-panadapter_button_press_event_cb (GtkWidget      *widget,
+tx_panadapter_button_press_event_cb (GtkWidget      *widget,
                GdkEventButton *event,
                gpointer        data)
 {
@@ -106,7 +107,7 @@ panadapter_button_press_event_cb (GtkWidget      *widget,
 }
 
 static gboolean
-panadapter_button_release_event_cb (GtkWidget      *widget,
+tx_panadapter_button_release_event_cb (GtkWidget      *widget,
                GdkEventButton *event,
                gpointer        data)
 {
@@ -132,7 +133,7 @@ panadapter_button_release_event_cb (GtkWidget      *widget,
 }
 
 static gboolean
-panadapter_motion_notify_event_cb (GtkWidget      *widget,
+tx_panadapter_motion_notify_event_cb (GtkWidget      *widget,
                 GdkEventMotion *event,
                 gpointer        data)
 {
@@ -154,7 +155,7 @@ panadapter_motion_notify_event_cb (GtkWidget      *widget,
 }
 
 static gboolean
-panadapter_scroll_event_cb (GtkWidget      *widget,
+tx_panadapter_scroll_event_cb (GtkWidget      *widget,
                GdkEventScroll *event,
                gpointer        data)
 {
@@ -174,6 +175,8 @@ void tx_panadapter_update(TRANSMITTER *tx) {
   gfloat saved_hz_per_pixel;
   cairo_text_extents_t extents;
 
+  if(tx->panadapter_surface) {
+
   int display_width=gtk_widget_get_allocated_width (tx->panadapter);
   int display_height=gtk_widget_get_allocated_height (tx->panadapter);
 
@@ -182,13 +185,15 @@ void tx_panadapter_update(TRANSMITTER *tx) {
     id=1;
   }
   samples=tx->pixel_samples;
+
   //hz_per_pixel=(double)tx->output_rate/(double)display_width;
+  //hz_per_pixel=24000.0/(double)display_width;
   hz_per_pixel=48000.0/(double)display_width;
 
   //clear_panadater_surface();
   cairo_t *cr;
   cr = cairo_create (tx->panadapter_surface);
-  cairo_set_source_rgb (cr, 0, 0, 0);
+  cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
   cairo_paint (cr);
 
   // filter
@@ -204,12 +209,12 @@ void tx_panadapter_update(TRANSMITTER *tx) {
   for (i = 1; i < numSteps; i++) {
     int num = tx->panadapter_high - i * 20;
     int y = (int)floor((tx->panadapter_high - num) * display_height / V);
-    cairo_set_source_rgb (cr, 0, 1, 1);
+    cairo_set_source_rgb (cr, 0.0, 1.0, 1.0);
     cairo_set_line_width(cr, 1.0);
     cairo_move_to(cr,0.0,(double)y);
     cairo_line_to(cr,(double)display_width,(double)y);
 
-    cairo_set_source_rgb (cr, 0, 1, 1);
+    cairo_set_source_rgb (cr, 0.0, 1.0, 1.0);
     cairo_select_font_face(cr, "FreeMono", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
     cairo_set_font_size(cr, 12);
     char v[32];
@@ -222,6 +227,7 @@ void tx_panadapter_update(TRANSMITTER *tx) {
   // plot frequency markers
   long long f;
   long long divisor=20000;
+  //long long half=12000LL; //(long long)(tx->output_rate/2);
   long long half=24000LL; //(long long)(tx->output_rate/2);
   long long frequency;
   frequency=vfo[id].frequency+vfo[VFO_B].offset;
@@ -230,12 +236,12 @@ void tx_panadapter_update(TRANSMITTER *tx) {
     f = frequency - half + (long) (hz_per_pixel * i);
     if (f > 0) {
       if ((f % divisor) < (long) hz_per_pixel) {
-        cairo_set_source_rgb (cr, 0, 1, 1);
+        cairo_set_source_rgb (cr, 0.0, 1.0, 1.0);
         cairo_set_line_width(cr, 1.0);
         cairo_move_to(cr,(double)i,10.0);
         cairo_line_to(cr,(double)i,(double)display_height);
 
-        cairo_set_source_rgb (cr, 0, 1, 1);
+        cairo_set_source_rgb (cr, 0.0, 1.0, 1.0);
         cairo_select_font_face(cr, "FreeMono",
                             CAIRO_FONT_SLANT_NORMAL,
                             CAIRO_FONT_WEIGHT_BOLD);
@@ -262,7 +268,7 @@ void tx_panadapter_update(TRANSMITTER *tx) {
   }
   BAND *band=band_get_band(b);
   if(band->frequencyMin!=0LL) {
-    cairo_set_source_rgb (cr, 1, 0, 0);
+    cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
     cairo_set_line_width(cr, 2.0);
     if((min_display<band->frequencyMin)&&(max_display>band->frequencyMin)) {
       i=(band->frequencyMin-min_display)/(long long)hz_per_pixel;
@@ -279,7 +285,7 @@ void tx_panadapter_update(TRANSMITTER *tx) {
   }
             
   // cursor
-  cairo_set_source_rgb (cr, 1, 0, 0);
+  cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
   cairo_set_line_width(cr, 1.0);
 //fprintf(stderr,"cursor: x=%f\n",(double)(display_width/2.0)+(vfo[tx->id].offset/hz_per_pixel));
   cairo_move_to(cr,(double)(display_width/2.0)+(vfo[id].offset/hz_per_pixel),0.0);
@@ -293,16 +299,24 @@ void tx_panadapter_update(TRANSMITTER *tx) {
 
   int offset=0;
 
-  if(protocol==NEW_PROTOCOL) {
-    offset=1200;
+  switch(protocol) {
+    case ORIGINAL_PROTOCOL:
+      //offset=(tx->pixels/4)*1;
+      offset=0;
+      break;
+    case NEW_PROTOCOL:
+      //offset=(tx->pixels/16)*7;
+      offset=(tx->pixels/8)*3;
+      break;
   }
-  s1=(double)samples[0+offset]+(double)get_attenuation();
+
+  s1=(double)samples[0+offset]/*+(double)get_attenuation()*/;
   s1 = floor((tx->panadapter_high - s1)
                         * (double) display_height
                         / (tx->panadapter_high - tx->panadapter_low));
   cairo_move_to(cr, 0.0, s1);
   for(i=1;i<display_width;i++) {
-    s2=(double)samples[i+offset]+(double)get_attenuation();
+    s2=(double)samples[i+offset]/*+(double)get_attenuation()*/;
     s2 = floor((tx->panadapter_high - s2)
                             * (double) display_height
                             / (tx->panadapter_high - tx->panadapter_low));
@@ -311,47 +325,64 @@ void tx_panadapter_update(TRANSMITTER *tx) {
 
   if(display_filled) {
     cairo_close_path (cr);
-    cairo_set_source_rgba(cr, 1, 1, 1,0.5);
+    cairo_set_source_rgba(cr, 1.0, 1.0, 1.0,0.5);
     cairo_fill_preserve (cr);
   }
-  cairo_set_source_rgb(cr, 1, 1, 1);
+  cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
   cairo_set_line_width(cr, 1.0);
   cairo_stroke(cr);
 
 #ifdef FREEDV
-  int mode;
-  mode=tx->mode;
-  if(mode==modeFREEDV) {
-    cairo_set_source_rgb(cr, 1, 0, 0);
+  if(active_receiver->freedv) {
+    cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
     cairo_set_font_size(cr, 16);
-    cairo_text_extents(cr, freedv_text_data, &extents);
+    cairo_text_extents(cr, transmitter->freedv_text_data, &extents);
     cairo_move_to(cr, (double)display_width/2.0-(extents.width/2.0),(double)display_height-2.0);
-    cairo_show_text(cr, freedv_text_data);
+    cairo_show_text(cr, transmitter->freedv_text_data);
   }
 #endif
 
 #ifdef GPIO
-  cairo_set_source_rgb(cr,1,1,0);
-  cairo_set_font_size(cr,12);
+  cairo_set_source_rgb(cr,1.0,1.0,0.0);
+  cairo_set_font_size(cr,16);
   if(ENABLE_E1_ENCODER) {
-    cairo_move_to(cr, display_width-100,30);
+    cairo_move_to(cr, display_width-150,30);
     cairo_show_text(cr, encoder_string[e1_encoder_action]);
   }
 
   if(ENABLE_E2_ENCODER) {
-    cairo_move_to(cr, display_width-100,50);
+    cairo_move_to(cr, display_width-150,50);
     cairo_show_text(cr, encoder_string[e2_encoder_action]);
   }
 
   if(ENABLE_E3_ENCODER) {
-    cairo_move_to(cr, display_width-100,70);
+    cairo_move_to(cr, display_width-150,70);
     cairo_show_text(cr, encoder_string[e3_encoder_action]);
   }
 #endif
 
+#ifdef PURESIGNAL
+  if(tx->puresignal) {
+    cairo_set_source_rgb(cr,0.0,1.0,0.0);
+    cairo_move_to(cr,display_width/2,display_height-10);
+    cairo_show_text(cr, "PureSignal");
+
+    int info[16];
+    GetPSInfo(tx->id,&info[0]);
+    if(info[14]==0) {
+      cairo_set_source_rgb(cr,1.0,0.0,0.0);
+    } else {
+      cairo_set_source_rgb(cr,0.0,1.0,0.0);
+    }
+    cairo_move_to(cr,(display_width/2)+100,display_height-10);
+    cairo_show_text(cr, "Correcting");
+  }
+#endif
+
   cairo_destroy (cr);
   gtk_widget_queue_draw (tx->panadapter);
 
+  }
 }
 
 void tx_panadapter_init(TRANSMITTER *tx, int width,int height) {
@@ -359,25 +390,27 @@ void tx_panadapter_init(TRANSMITTER *tx, int width,int height) {
   int display_width=width;
   int display_height=height;
 
+fprintf(stderr,"tx_panadapter_init: %d x %d\n",display_width,display_height);
+
   tx->panadapter_surface=NULL;
   tx->panadapter=gtk_drawing_area_new ();
   gtk_widget_set_size_request (tx->panadapter, width, height);
 
   /* Signals used to handle the backing surface */
   g_signal_connect (tx->panadapter, "draw",
-            G_CALLBACK (panadapter_draw_cb), tx);
+            G_CALLBACK (tx_panadapter_draw_cb), tx);
   g_signal_connect (tx->panadapter,"configure-event",
-            G_CALLBACK (panadapter_configure_event_cb), tx);
+            G_CALLBACK (tx_panadapter_configure_event_cb), tx);
 
   /* Event signals */
   g_signal_connect (tx->panadapter, "motion-notify-event",
-            G_CALLBACK (panadapter_motion_notify_event_cb), tx);
+            G_CALLBACK (tx_panadapter_motion_notify_event_cb), tx);
   g_signal_connect (tx->panadapter, "button-press-event",
-            G_CALLBACK (panadapter_button_press_event_cb), tx);
+            G_CALLBACK (tx_panadapter_button_press_event_cb), tx);
   g_signal_connect (tx->panadapter, "button-release-event",
-            G_CALLBACK (panadapter_button_release_event_cb), tx);
+            G_CALLBACK (tx_panadapter_button_release_event_cb), tx);
   g_signal_connect(tx->panadapter,"scroll_event",
-            G_CALLBACK(panadapter_scroll_event_cb),tx);
+            G_CALLBACK(tx_panadapter_scroll_event_cb),tx);
 
   /* Ask to receive events the drawing area doesn't normally
    * subscribe to. In particular, we need to ask for the
index b4f7d49d238331e720ad17d568724194e8db2c43..5f2756af7e7fa5b66c6c94cff90b429e567f60ed 100644 (file)
--- a/update.c
+++ b/update.c
@@ -23,7 +23,7 @@ int check_update() {
 
   FILE* f=fopen("latest","r");
   if(f) {
-    fgets(new_version,sizeof(new_version),f);
+    char *s=fgets(new_version,sizeof(new_version),f);
     fclose(f);
   } else {
     fprintf(stderr,"check_update: could not read latest version\n");
@@ -42,7 +42,7 @@ int check_update() {
 
   fprintf(stderr,"check_version: latest version is %s\n",new_version);
 
-  fprintf(stderr,"check_version: length of version=%d length of new_version=%d\n", strlen(version), strlen(new_version));
+  fprintf(stderr,"check_version: length of version=%ld length of new_version=%ld\n", strlen(version), strlen(new_version));
   rc=strcmp(version,new_version);
 
   return rc;
diff --git a/vfo.c b/vfo.c
index b73484a1d622f8258cc58a74134650d9e75af09f..4666596f786e4571309e3d1af20f0ab124732c87 100644 (file)
--- a/vfo.c
+++ b/vfo.c
@@ -20,7 +20,6 @@
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
 #include <math.h>
-#include <pthread.h>
 #include <semaphore.h>
 #include <string.h>
 #include <stdlib.h>
 #ifdef RADIOBERRY
 #include "radioberry.h"
 #endif
+#include "ext.h"
+#ifdef FREEDV
+#include "freedv.h"
+#endif
 
 static GtkWidget *parent_window;
 static int my_width;
@@ -169,6 +172,17 @@ void vfo_restore_state() {
   }
 }
 
+void vfo_xvtr_changed() {
+  if(vfo[0].band>=BANDS) {
+    BAND *band=band_get_band(vfo[0].band);
+    vfo[0].lo=band->frequencyLO+band->errorLO;
+  }
+  if(vfo[1].band>=BANDS) {
+    BAND *band=band_get_band(vfo[1].band);
+    vfo[1].lo=band->frequencyLO+band->errorLO;
+  }
+}
+
 void vfo_band_changed(int b) {
   BANDSTACK *bandstack;
 
@@ -196,7 +210,7 @@ void vfo_band_changed(int b) {
   vfo[id].frequency=entry->frequency;
   vfo[id].mode=entry->mode;
   vfo[id].filter=entry->filter;
-  vfo[id].lo=band->frequencyLO;
+  vfo[id].lo=band->frequencyLO+band->errorLO;
 
   switch(id) {
     case 0:
@@ -221,8 +235,7 @@ void vfo_band_changed(int b) {
     tx_set_mode(transmitter,vfo[VFO_A].mode);
   }
   calcDriveLevel();
-  calcTuneDriveLevel();
-  vfo_update(NULL);
+  vfo_update();
 }
 
 void vfo_bandstack_changed(int b) {
@@ -261,8 +274,7 @@ void vfo_bandstack_changed(int b) {
     tx_set_mode(transmitter,vfo[VFO_A].mode);
   }
   calcDriveLevel();
-  calcTuneDriveLevel();
-  vfo_update(NULL);
+  vfo_update();
 
 }
 
@@ -287,7 +299,7 @@ void vfo_mode_changed(int m) {
     tx_set_mode(transmitter,vfo[VFO_A].mode);
   }
 
-  vfo_update(NULL);
+  vfo_update();
 }
 
 void vfo_filter_changed(int f) {
@@ -304,7 +316,7 @@ void vfo_filter_changed(int f) {
       break;
   }
 
-  vfo_update(NULL);
+  vfo_update();
 }
 
 void vfo_a_to_b() {
@@ -313,7 +325,6 @@ void vfo_a_to_b() {
   vfo[VFO_B].frequency=vfo[VFO_A].frequency;
   vfo[VFO_B].mode=vfo[VFO_A].mode;
   vfo[VFO_B].filter=vfo[VFO_A].filter;
-  vfo[VFO_B].filter=vfo[VFO_A].filter;
   vfo[VFO_B].lo=vfo[VFO_A].lo;
   vfo[VFO_B].offset=vfo[VFO_A].offset;
   vfo[VFO_B].rit_enabled=vfo[VFO_A].rit_enabled;
@@ -325,7 +336,7 @@ void vfo_a_to_b() {
   if(split) {
     tx_set_mode(transmitter,vfo[VFO_B].mode);
   }
-  vfo_update(NULL);
+  vfo_update();
 }
 
 void vfo_b_to_a() {
@@ -342,7 +353,7 @@ void vfo_b_to_a() {
   if(!split) {
     tx_set_mode(transmitter,vfo[VFO_B].mode);
   }
-  vfo_update(NULL);
+  vfo_update();
 }
 
 void vfo_a_swap_b() {
@@ -395,7 +406,7 @@ void vfo_a_swap_b() {
   } else {
     tx_set_mode(transmitter,vfo[VFO_A].mode);
   }
-  vfo_update(NULL);
+  vfo_update();
 }
 
 void vfo_step(int steps) {
@@ -411,7 +422,7 @@ void vfo_step(int steps) {
     BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
     setFrequency(active_receiver->frequency+(steps*step));
 #endif
-    vfo_update(NULL);
+    vfo_update();
   }
 }
 
@@ -433,7 +444,7 @@ void vfo_move(long long hz) {
         break;
     }
     receiver_frequency_changed(active_receiver);
-    vfo_update(NULL);
+    vfo_update();
   }
 }
 
@@ -490,7 +501,7 @@ void vfo_move_to(long long hz) {
     }
 #endif
 #endif
-    vfo_update(NULL);
+    vfo_update();
   }
 }
 
@@ -523,10 +534,10 @@ static gboolean vfo_configure_event_cb (GtkWidget         *widget,
   /* Initialize the surface to black */
   cairo_t *cr;
   cr = cairo_create (vfo_surface);
-  cairo_set_source_rgb (cr, 0, 0, 0);
+  cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
   cairo_paint (cr);
   cairo_destroy(cr);
-  g_idle_add(vfo_update,NULL);
+  g_idle_add(ext_vfo_update,NULL);
   return TRUE;
 }
 
@@ -534,12 +545,12 @@ static gboolean vfo_draw_cb (GtkWidget *widget,
  cairo_t   *cr,
  gpointer   data)
 {
-  cairo_set_source_surface (cr, vfo_surface, 00);
+  cairo_set_source_surface (cr, vfo_surface, 0.0, 0.0);
   cairo_paint (cr);
-  return TRUE;
+  return FALSE;
 }
 
-int vfo_update(void *data) {
+void vfo_update() {
     
     int id=active_receiver->id;
     FILTER* band_filters=filters[vfo[id].mode];
@@ -548,89 +559,62 @@ int vfo_update(void *data) {
         char temp_text[32];
         cairo_t *cr;
         cr = cairo_create (vfo_surface);
-        cairo_set_source_rgb (cr, 0, 0, 0);
+        cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
         cairo_paint (cr);
 
         cairo_select_font_face(cr, "FreeMono",
             CAIRO_FONT_SLANT_NORMAL,
             CAIRO_FONT_WEIGHT_BOLD);
 
-        char version[16];
-        char text[128];
-#ifdef RADIOBERRY
-        if(radio->protocol==ORIGINAL_PROTOCOL || radio->protocol==RADIOBERRY_PROTOCOL ) {
-#else
-               if(radio->protocol==ORIGINAL_PROTOCOL) {
-#endif
-          switch(radio->device) {
-#ifdef USBOZY
-            case DEVICE_OZY:
-              strcpy(version,"");
-              break;
-#endif
-            default:
-              sprintf(version,"%d.%d",
-                  radio->software_version/10,
-                  radio->software_version%10);
-              break;
-          }
-        } else {
-            sprintf(version,"%d.%d",
-                radio->software_version/10,
-                radio->software_version%10);
+        char dv[32];
+        strcpy(dv,"");
+#ifdef FREEDV
+        if(active_receiver->freedv) {
+          sprintf(dv,"FreeDV %s", freedv_get_mode_string());
         }
-
-        switch(radio->protocol) {
-            case ORIGINAL_PROTOCOL:
-              switch(radio->device) {
-#ifdef USBOZY
-                case DEVICE_OZY:
-                  sprintf(text,"%s", radio->name);
-                  break;
-#endif
-                default:
-                  sprintf(text,"%s %s %s",
-                    radio->name,
-                    version,
-                    inet_ntoa(radio->info.network.address.sin_addr));
-                  break;
-              }
-              break;
-            case NEW_PROTOCOL:
-              sprintf(text,"%s %s %s",
-                    radio->name,
-                    version,
-                    inet_ntoa(radio->info.network.address.sin_addr));
-              break;
-#ifdef LIMESDR
-            case LIMESDR_PROTOCOL:
-              sprintf(text,"%s", radio->name);
-              break;
-#endif
-#ifdef RADIOBERRY
-                       case RADIOBERRY_PROTOCOL:
-                               sprintf(text,"%s", radio->name);
-                               break;
 #endif
-        }
-        cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
         cairo_set_font_size(cr, 12);
-        cairo_move_to(cr, 5, 15);  
-        cairo_show_text(cr, text);
+        cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
+        cairo_move_to(cr, 5, 15);
+        
+        switch(vfo[id].mode) {
+          case modeFMN:
+            if(active_receiver->deviation==2500) {
+              sprintf(temp_text,"%s 8k %s",mode_string[vfo[id].mode],dv);
+            } else {
+              sprintf(temp_text,"%s 16k %s",mode_string[vfo[id].mode],dv);
+            }
+            break;
+          case modeCWL:
+          case modeCWU:
+            sprintf(temp_text,"%s %s %d wpm %d Hz",mode_string[vfo[id].mode],band_filter->title,cw_keyer_speed,cw_keyer_sidetone_frequency);
+            break;
+          case modeLSB:
+          case modeUSB:
+          case modeDSB:
+          case modeAM:
+            sprintf(temp_text,"%s %s %s",mode_string[vfo[id].mode],band_filter->title,dv);
+            break;
+          default:
+            sprintf(temp_text,"%s %s",mode_string[vfo[id].mode],band_filter->title);
+            break;
+        }
+        cairo_show_text(cr, temp_text);
+
 
         long long af=vfo[0].frequency+vfo[0].offset;
         if(transmitter->out_of_band && !split) {
-          cairo_set_source_rgb(cr, 1, 0, 0);
+          cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
           sprintf(temp_text,"VFO A: Out of band");
         } else {
           sprintf(temp_text,"VFO A: %0lld.%06lld",af/(long long)1000000,af%(long long)1000000);
           if(isTransmitting() && !split) {
-              cairo_set_source_rgb(cr, 1, 0, 0);
+              cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
           } else {
               if(active_receiver->id==0) {
-                cairo_set_source_rgb(cr, 0, 1, 0);
+                cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);
               } else {
-                cairo_set_source_rgb(cr, 0, 0.65, 0);
+                cairo_set_source_rgb(cr, 0.0, 0.65, 0.0);
               }
           }
         }
@@ -641,65 +625,50 @@ int vfo_update(void *data) {
 
         long long bf=vfo[1].frequency+vfo[1].offset;
         if(transmitter->out_of_band && split) {
-          cairo_set_source_rgb(cr, 1, 0, 0);
+          cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
           sprintf(temp_text,"VFO B: Out of band");
         } else {
           sprintf(temp_text,"VFO B: %0lld.%06lld",bf/(long long)1000000,bf%(long long)1000000);
           if(isTransmitting() && split) {
-              cairo_set_source_rgb(cr, 1, 0, 0);
+              cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
           } else {
               if(active_receiver->id==1) {
-                cairo_set_source_rgb(cr, 0, 1, 0);
+                cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);
               } else {
-                cairo_set_source_rgb(cr, 0, 0.65, 0);
+                cairo_set_source_rgb(cr, 0.0, 0.65, 0.0);
               }
           }
         }
         cairo_move_to(cr, 260, 38);  
         cairo_show_text(cr, temp_text);
 
-        cairo_set_font_size(cr, 12);
-
         if(vfo[id].rit_enabled==0) {
             cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
         } else {
-            cairo_set_source_rgb(cr, 1, 1, 0);
+            cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
         }
         sprintf(temp_text,"RIT: %lld Hz",vfo[id].rit);
-        cairo_move_to(cr, 5, 50);  
+        cairo_move_to(cr, 210, 15);
         cairo_set_font_size(cr, 12);
         cairo_show_text(cr, temp_text);
 
-        cairo_move_to(cr, 190, 15);  
-        if(vox_enabled) {
-          cairo_set_source_rgb(cr, 1, 0, 0);
+        cairo_move_to(cr, 150, 50);
+        if(active_receiver->nb) {
+          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, "VOX");
-        
-        cairo_move_to(cr, 220, 15);  
-        if(locked) {
-          cairo_set_source_rgb(cr, 1, 0, 0);
+        cairo_show_text(cr, "NB");
+
+        cairo_move_to(cr, 175, 50);
+        if(active_receiver->nb2) {
+          cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
         } else {
           cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
         }
-        cairo_show_text(cr, "Locked");
-        
-        cairo_set_source_rgb(cr, 1, 1, 0);
-        cairo_move_to(cr, 100, 50);  
-        if(vfo[id].mode==modeFMN) {
-          if(deviation==2500) {
-            sprintf(temp_text,"%s 8k",mode_string[vfo[id].mode]); 
-          } else {
-            sprintf(temp_text,"%s 16k",mode_string[vfo[id].mode]); 
-          }
-        } else {
-          sprintf(temp_text,"%s %s",mode_string[vfo[id].mode],band_filter->title); 
-        }
-        cairo_show_text(cr, temp_text);
+        cairo_show_text(cr, "NB2");
 
-        cairo_move_to(cr, 170, 50);  
+        cairo_move_to(cr, 200, 50);  
         if(active_receiver->nr) {
           cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
         } else {
@@ -707,7 +676,7 @@ int vfo_update(void *data) {
         }
         cairo_show_text(cr, "NR");
 
-        cairo_move_to(cr, 200, 50);  
+        cairo_move_to(cr, 225, 50);  
         if(active_receiver->nr2) {
           cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
         } else {
@@ -715,7 +684,7 @@ int vfo_update(void *data) {
         }
         cairo_show_text(cr, "NR2");
 
-        cairo_move_to(cr, 230, 50);  
+        cairo_move_to(cr, 250, 50);  
         if(active_receiver->anf) {
           cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
         } else {
@@ -723,7 +692,7 @@ int vfo_update(void *data) {
         }
         cairo_show_text(cr, "ANF");
 
-        cairo_move_to(cr, 260, 50);  
+        cairo_move_to(cr, 275, 50);  
         if(active_receiver->snb) {
           cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
         } else {
@@ -731,26 +700,26 @@ int vfo_update(void *data) {
         }
         cairo_show_text(cr, "SNB");
 
-        cairo_move_to(cr, 290, 50);  
+        cairo_move_to(cr, 350, 50);  
         switch(active_receiver->agc) {
           case AGC_OFF:
             cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
             cairo_show_text(cr, "AGC OFF");
             break;
           case AGC_LONG:
-            cairo_set_source_rgb(cr, 1, 1, 0);
+            cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
             cairo_show_text(cr, "AGC LONG");
             break;
           case AGC_SLOW:
-            cairo_set_source_rgb(cr, 1, 1, 0);
+            cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
             cairo_show_text(cr, "AGC SLOW");
             break;
           case AGC_MEDIUM:
-            cairo_set_source_rgb(cr, 1, 1, 0);
+            cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
             cairo_show_text(cr, "AGC MEDIUM");
             break;
           case AGC_FAST:
-            cairo_set_source_rgb(cr, 1, 1, 0);
+            cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
             cairo_show_text(cr, "AGC FAST");
             break;
         }
@@ -760,55 +729,73 @@ int vfo_update(void *data) {
           s++;
         }
         sprintf(temp_text,"Step %s",step_labels[s]);
-        cairo_move_to(cr, 375, 50);
-        cairo_set_source_rgb(cr, 1, 1, 0);
+        cairo_move_to(cr, 300, 15);
+        cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
         cairo_show_text(cr, temp_text);
 
-        char *info=getFrequencyInfo(af);
+        char *info=getFrequencyInfo(af,active_receiver->filter_low,active_receiver->filter_high);
 /*
         cairo_move_to(cr, (my_width/4)*3, 50);
         cairo_show_text(cr, getFrequencyInfo(af));
 */
          
-        cairo_move_to(cr, 460, 50);  
+        cairo_move_to(cr, 400, 15);  
         if(vfo[id].ctun) {
-          cairo_set_source_rgb(cr, 1, 1, 0);
+          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, "CTUN");
 
-        cairo_move_to(cr, 500, 50);  
+        cairo_move_to(cr, 450, 15);  
         if(cat_control>0) {
-          cairo_set_source_rgb(cr, 1, 1, 0);
+          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, "CAT");
 
-        cairo_move_to(cr, 270, 15);
+        cairo_move_to(cr, 500, 15);  
+        if(vox_enabled) {
+          cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
+        } else {
+          cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
+        }
+        cairo_show_text(cr, "VOX");
+
+        cairo_move_to(cr, 5, 50);
+        if(locked) {
+          cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
+        } else {
+          cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
+        }
+        cairo_show_text(cr, "Locked");
+
+        cairo_move_to(cr, 55, 50);
         if(split) {
-          cairo_set_source_rgb(cr, 1, 0, 0);
+          cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
         } else {
           cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
         }
         cairo_show_text(cr, "Split");
-       
-        cairo_move_to(cr, 310, 15);
-        if(vfo[id].mode==modeCWL || vfo[id].mode==modeCWU) {
-          cairo_set_source_rgb(cr, 1, 1, 0);
+
+#ifdef PURESIGNAL
+        cairo_move_to(cr, 105, 50);
+        if(transmitter->puresignal) {
+          cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
         } else {
           cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
         }
-        sprintf(temp_text,"CW %d wpm, sidetone %d Hz",cw_keyer_speed,cw_keyer_sidetone_frequency);
-        cairo_show_text(cr, temp_text);
+        cairo_show_text(cr, "PS");
+#endif
+
+
 
         cairo_destroy (cr);
         gtk_widget_queue_draw (vfo_panel);
     } else {
 fprintf(stderr,"vfo_update: no surface!\n");
     }
-    return 0;
 }
 
 /*
@@ -817,7 +804,7 @@ vfo_step_select_cb (GtkWidget *widget,
                gpointer        data)
 {
   step=steps[(int)data];
-  vfo_update(NULL);
+  vfo_update();
 }
 */
 
@@ -826,15 +813,6 @@ vfo_press_event_cb (GtkWidget *widget,
                GdkEventButton *event,
                gpointer        data)
 {
-/*
-  if((int)event->x < (my_width/4)) {
-    //lock_cb(NULL,NULL);
-  } else if((int)event->x < (my_width/2) && (int)event->x > (my_width/4)) {
-    start_freqent();
-  } else {
-    start_step();
-  }
-*/
   start_vfo();
   return TRUE;
 }
diff --git a/vfo.h b/vfo.h
index 186297927918b1338b90af95757158378deefa49..5b812d1129d501d9d4eb26401446c2cf7893b1e3 100644 (file)
--- a/vfo.h
+++ b/vfo.h
@@ -52,7 +52,7 @@ extern GtkWidget* vfo_init(int width,int height,GtkWidget *parent);
 extern void vfo_step(int steps);
 extern void vfo_move(long long hz);
 extern void vfo_move_to(long long hz);
-extern int vfo_update(void*);
+extern void vfo_update();
 extern void set_frequency();
 
 extern void vfo_save_state();
@@ -65,4 +65,6 @@ extern void vfo_filter_changed(int f);
 extern void vfo_a_to_b();
 extern void vfo_b_to_a();
 extern void vfo_a_swap_b();
+
+extern void vfo_xvtr_changed();
 #endif
index a9dfc359cceae4cd4d0814611da167056155d128..5afcdc57bbe054761684b22a5579f61bcc468681 100644 (file)
 */
 
 #include <gtk/gtk.h>
+#include <ctype.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#include <wdsp.h>
 
 #include "new_menu.h"
 #include "band.h"
 #include "mode.h"
 #include "radio.h"
 #include "receiver.h"
+#include "transmitter.h"
 #include "vfo.h"
+#include "button_text.h"
+#include "ext.h"
+#ifdef FREEDV
+#include "freedv.h"
+#endif
 
 static GtkWidget *parent_window=NULL;
 static GtkWidget *dialog=NULL;
@@ -44,15 +52,31 @@ static char *btn_labels[] = {"1","2","3",
                ,"CL"
               };
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static GtkWidget *btn[16];
+
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 squelch_enable_cb(GtkWidget *widget, gpointer data) {
+  active_receiver->squelch_enable=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+  setSquelch(active_receiver);
+}
+
 static gboolean freqent_select_cb (GtkWidget *widget, gpointer data) {
   char *str = (char *) data;
   const char *labelText;
@@ -133,12 +157,12 @@ static gboolean freqent_select_cb (GtkWidget *widget, gpointer data) {
         }
       }
       setFrequency(f);
-      vfo_update(NULL);
+      vfo_update();
     
       set = 1;
     }
   }
-  vfo_update(NULL);
+  vfo_update();
 }
 
 static void rit_cb(GtkComboBox *widget,gpointer data) {
@@ -153,12 +177,38 @@ static void rit_cb(GtkComboBox *widget,gpointer data) {
       rit_increment=100;
       break;
   }
-  vfo_update(NULL);
+  vfo_update();
 }
 
 static void vfo_cb(GtkComboBox *widget,gpointer data) {
   step=steps[gtk_combo_box_get_active(widget)];
-  vfo_update(NULL);
+  vfo_update();
+}
+
+#ifdef FREEDV
+static void enable_freedv_cb(GtkWidget *widget, gpointer data) {
+  set_freedv(gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)));
+}
+#endif
+
+#ifdef FREEDV
+static void enable_ps_cb(GtkWidget *widget, gpointer data) {
+  tx_set_ps(transmitter,gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)));
+}
+#endif
+
+static void set_btn_state() {
+  int i;
+
+  for(i=0;i<16;i++) {
+    gtk_widget_set_sensitive(btn[i], locked==0);
+  }
+}
+
+static void lock_cb(GtkWidget *widget, gpointer data) {
+  locked=locked==1?0:1;
+  set_btn_state();
+  vfo_update();
 }
 
 static GtkWidget *last_mode;
@@ -170,7 +220,11 @@ void vfo_menu(GtkWidget *parent) {
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  char title[64];
+  sprintf(title,"piHPSDR - VFO (RX %d VFO %s)",active_receiver->id,active_receiver->id==0?"A":"B");
+  gtk_window_set_title(GTK_WINDOW(dialog),title);
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -192,10 +246,10 @@ void vfo_menu(GtkWidget *parent) {
   g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
   gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
 
-  char rx_id[32];
-  sprintf(rx_id,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B");
-  GtkWidget *rx_label=gtk_label_new(rx_id);
-  gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1);
+  GtkWidget *lock_b=gtk_check_button_new_with_label("Lock VFO");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lock_b), locked);
+  gtk_grid_attach(GTK_GRID(grid),lock_b,1,0,1,1);
+  g_signal_connect(lock_b,"toggled",G_CALLBACK(lock_cb),NULL);
 
   label = gtk_label_new (NULL);
   gtk_label_set_markup (GTK_LABEL (label), "<big>0</big>");
@@ -204,15 +258,16 @@ void vfo_menu(GtkWidget *parent) {
 
   GtkWidget *step_rb=NULL;
   for (i=0; i<16; i++) {
-    GtkWidget *b=gtk_button_new_with_label(btn_labels[i]);
-    set_button_text_color(b,"black");
-    gtk_widget_show(b);
-    gtk_grid_attach(GTK_GRID(grid),b,i%3,2+(i/3),1,1);
-    g_signal_connect(b,"pressed",G_CALLBACK(freqent_select_cb),(gpointer *)btn_labels[i]);
+    btn[i]=gtk_button_new_with_label(btn_labels[i]);
+    set_button_text_color(btn[i],"black");
+    gtk_widget_show(btn[i]);
+    gtk_grid_attach(GTK_GRID(grid),btn[i],i%3,2+(i/3),1,1);
+    g_signal_connect(btn[i],"pressed",G_CALLBACK(freqent_select_cb),(gpointer *)btn_labels[i]);
   }
+  set_btn_state();
 
   GtkWidget *rit_label=gtk_label_new("RIT step: ");
-  gtk_grid_attach(GTK_GRID(grid),rit_label,3,1,1,1);
+  gtk_grid_attach(GTK_GRID(grid),rit_label,3,2,1,1);
 
   GtkWidget *rit_b=gtk_combo_box_text_new();
   gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(rit_b),NULL,"1 Hz");
@@ -230,7 +285,7 @@ void vfo_menu(GtkWidget *parent) {
       break;
   }
   g_signal_connect(rit_b,"changed",G_CALLBACK(rit_cb),NULL);
-  gtk_grid_attach(GTK_GRID(grid),rit_b,3,2,1,1);
+  gtk_grid_attach(GTK_GRID(grid),rit_b,4,2,1,1);
 
   GtkWidget *vfo_label=gtk_label_new("VFO step: ");
   gtk_grid_attach(GTK_GRID(grid),vfo_label,3,3,1,1);
@@ -245,7 +300,27 @@ void vfo_menu(GtkWidget *parent) {
     i++;
   }
   g_signal_connect(vfo_b,"changed",G_CALLBACK(vfo_cb),NULL);
-  gtk_grid_attach(GTK_GRID(grid),vfo_b,3,4,1,1);
+  gtk_grid_attach(GTK_GRID(grid),vfo_b,4,3,1,1);
+
+
+  GtkWidget *enable_squelch=gtk_check_button_new_with_label("Enable Squelch");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (enable_squelch), active_receiver->squelch_enable);
+  gtk_grid_attach(GTK_GRID(grid),enable_squelch,3,5,1,1);
+  g_signal_connect(enable_squelch,"toggled",G_CALLBACK(squelch_enable_cb),NULL);
+
+#ifdef FREEDV
+  GtkWidget *enable_freedv=gtk_check_button_new_with_label("Enable FreeDV");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (enable_freedv), active_receiver->freedv);
+  gtk_grid_attach(GTK_GRID(grid),enable_freedv,3,6,1,1);
+  g_signal_connect(enable_freedv,"toggled",G_CALLBACK(enable_freedv_cb),NULL);
+#endif
+
+#ifdef PURESIGNAL
+  GtkWidget *enable_ps=gtk_check_button_new_with_label("Enable Pure Signal");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (enable_ps), transmitter->puresignal);
+  gtk_grid_attach(GTK_GRID(grid),enable_ps,3,7,1,1);
+  g_signal_connect(enable_ps,"toggled",G_CALLBACK(enable_ps_cb),NULL);
+#endif
 
   gtk_container_add(GTK_CONTAINER(content),grid);
 
diff --git a/vox.c b/vox.c
index 7b99e558101fba2b2ad99c187c04e9cca2fc1fc8..5b9cbb2292c623f2b743b00ae89109a3d33ff553 100644 (file)
--- a/vox.c
+++ b/vox.c
@@ -23,6 +23,7 @@
 #include "transmitter.h"
 #include "vox.h"
 #include "vfo.h"
+#include "ext.h"
 
 static guint vox_timeout;
 
@@ -30,8 +31,8 @@ static double peak=0.0;
 
 static int vox_timeout_cb(gpointer data) {
   //setVox(0);
-  g_idle_add(vox_changed,(gpointer)0);
-  g_idle_add(vfo_update,NULL);
+  g_idle_add(ext_vox_changed,(gpointer)0);
+  g_idle_add(ext_vfo_update,NULL);
   return FALSE;
 }
 
@@ -42,7 +43,8 @@ double vox_get_peak() {
 }
 
 void update_vox(TRANSMITTER *tx) {
-  // assumes in is interleaved left and right channel with length samples
+  // calculate peak microphone input
+  // assumes it is interleaved left and right channel with length samples
   int previous_vox=vox;
   int i;
   double sample;
@@ -57,19 +59,17 @@ void update_vox(TRANSMITTER *tx) {
     }
   }
 
-
   if(vox_enabled) {
     if(peak>vox_threshold) {
       if(previous_vox) {
         g_source_remove(vox_timeout);
       } else {
-        //setVox(1);
-        g_idle_add(vox_changed,(gpointer)1);
+        g_idle_add(ext_vox_changed,(gpointer)1);
       }
       vox_timeout=g_timeout_add((int)vox_hang,vox_timeout_cb,NULL);
     }
     if(vox!=previous_vox) {
-      g_idle_add(vfo_update,NULL);
+      g_idle_add(ext_vfo_update,NULL);
     }
   }
 }
@@ -78,7 +78,7 @@ void vox_cancel() {
   if(vox) {
     g_source_remove(vox_timeout);
     //setVox(0);
-    g_idle_add(vox_changed,(gpointer)0);
-    g_idle_add(vfo_update,NULL);
+    g_idle_add(ext_vox_changed,(gpointer)0);
+    g_idle_add(ext_vfo_update,NULL);
   }
 }
index 8b710f7fe215281b9ff98047dc10e89d3151b83b..460ac435c51ee9c7b6f6d5932fef1679aa53caee 100644 (file)
 #include <gtk/gtk.h>
 #include <semaphore.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
-#include <pthread.h>
 
 #include "led.h"
 #include "new_menu.h"
 #include "radio.h"
 #include "transmitter.h"
+#include "vfo.h"
 #include "vox_menu.h"
 #include "vox.h"
 
@@ -37,6 +38,7 @@ static GtkWidget *dialog=NULL;
 static GtkWidget *level;
 
 static GtkWidget *led;
+static GdkRGBA led_color={0.0,0.0,0.0,1.0};
 
 static GdkRGBA white={1.0,1.0,1.0,1.0};
 static GdkRGBA red={1.0,0.0,0.0,1.0};
@@ -60,7 +62,10 @@ static int level_update(void *data) {
 
     if(peak>vox_threshold) {
       // red indicator
-      led_set_color(1.0,0.0,0.0); // red
+      led_color.red=1.0;
+      led_color.green=0.0;
+      led_color.blue=0.0;
+      led_set_color(led); // red
       if(hold==0) {
         hold=1;
       } else {
@@ -70,14 +75,17 @@ static int level_update(void *data) {
     } else {
       // green indicator
       if(hold==0) {
-        led_set_color(0.0,1.0,0.0); // green
+        led_color.red=0.0;
+        led_color.green=1.0;
+        led_color.blue=0.0;
+        led_set_color(led); // green
       }
     }
   }
   return 0;
 }
 
-static void *level_thread(void* arg) {
+static gpointer level_thread(gpointer arg) {
   while(run_level) {
     peak=vox_get_peak();
     g_idle_add(level_update,NULL);
@@ -85,19 +93,28 @@ static void *level_thread(void* arg) {
   }
 }
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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 gboolean enable_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   vox_enabled=vox_enabled==1?0:1;
   gtk_button_set_label(GTK_BUTTON(widget),vox_enabled==0?"VOX Enable":"VOX Disable");
-  vfo_update(NULL);
+  vfo_update();
   return TRUE;
 }
 
@@ -136,7 +153,9 @@ void vox_menu(GtkWidget *parent) {
   dialog=gtk_dialog_new();
   g_signal_connect (dialog, "destroy", G_CALLBACK(destroy_cb), NULL);
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - VOX");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   gtk_widget_override_background_color(dialog,GTK_STATE_FLAG_NORMAL,&white);
 
@@ -148,11 +167,11 @@ void vox_menu(GtkWidget *parent) {
   //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
   gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
 
-  GtkWidget *close_b=gtk_button_new_with_label("Close VOX");
+  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);
 
-  led=create_led(10,10);
+  led=create_led(10,10,&led_color);
   gtk_grid_attach(GTK_GRID(grid),led,2,0,1,1);
  
   GtkWidget *enable_b=gtk_button_new_with_label(vox_enabled==0?"VOX Enable":"VOX Disable");
index 3af56d428caed617c45df31f9a740cdd0d4ecc1c..4f750274a09aff542295f7cfc78d00fd287a647e 100644 (file)
@@ -49,14 +49,6 @@ static gboolean pressed=FALSE;
 
 static gfloat hz_per_pixel;
 
-/*
-#define BANDS 7
-
-static long long frequency[BANDS];
-static gint mode[BANDS];
-static gint band=4;
-*/
-
 static int display_width;
 static int display_height;
 
@@ -90,7 +82,7 @@ waterfall_draw_cb (GtkWidget *widget,
   RECEIVER *rx=(RECEIVER *)data;
   gdk_cairo_set_source_pixbuf (cr, rx->pixbuf, 0, 0);
   cairo_paint (cr);
-  return TRUE;
+  return FALSE;
 }
 
 static gboolean
@@ -137,6 +129,42 @@ void waterfall_update(RECEIVER *rx) {
     int rowstride=gdk_pixbuf_get_rowstride(rx->pixbuf);
     int channels=gdk_pixbuf_get_n_channels(rx->pixbuf);
 
+    hz_per_pixel=(double)rx->sample_rate/(double)display_width;
+
+    if(rx->waterfall_frequency!=0 && (rx->sample_rate==rx->waterfall_sample_rate)) {
+      if(rx->waterfall_frequency!=vfo[rx->id].frequency) {
+        // scrolled or band change
+        long long half=(long long)(rx->sample_rate/2);
+        if(rx->waterfall_frequency<(vfo[rx->id].frequency-half) || rx->waterfall_frequency>(vfo[rx->id].frequency+half)) {
+          // outside of the range - blank waterfall
+//fprintf(stderr,"waterfall_update: clear waterfall from %lld to %lld\n",rx->waterfall_frequency,vfo[rx->id].frequency);
+          memset(pixels, 0, display_width*display_height*3);
+        } else {
+          // rotate waterfall
+          int rotate_pixels=(int)((double)(rx->waterfall_frequency-vfo[rx->id].frequency)/hz_per_pixel);
+//fprintf(stderr,"waterfall_update: rotate waterfall from %lld to %lld pixels=%d\n",rx->waterfall_frequency,vfo[rx->id].frequency,rotate_pixels);
+          if(rotate_pixels<0) {
+            memmove(pixels,&pixels[-rotate_pixels*3],((display_width*display_height)+rotate_pixels)*3);
+            //now clear the right hand side
+            for(i=0;i<display_height;i++) {
+              memset(&pixels[((i*display_width)+(width+rotate_pixels))*3], 0, -rotate_pixels*3);
+            }
+          } else {
+            memmove(&pixels[rotate_pixels*3],pixels,((display_width*display_height)-rotate_pixels)*3);
+            //now clear the left hand side
+            for(i=0;i<display_height;i++) {
+              memset(&pixels[(i*display_width)*3], 0, rotate_pixels*3);
+            }
+          }
+        }
+      }
+    } else {
+      memset(pixels, 0, display_width*display_height*3);
+    }
+
+    rx->waterfall_frequency=vfo[rx->id].frequency;
+    rx->waterfall_sample_rate=rx->sample_rate;
+
     memmove(&pixels[rowstride],pixels,(height-1)*rowstride);
 
     float sample;
@@ -214,11 +242,8 @@ void waterfall_init(RECEIVER *rx,int width,int height) {
   display_height=height;
 
   rx->pixbuf=NULL;
-  rx->waterfall_low=waterfall_low;
-  rx->waterfall_high=waterfall_high;
-  rx->waterfall_automatic=waterfall_automatic;
-
-  hz_per_pixel=(double)rx->sample_rate/(double)display_width;
+  rx->waterfall_frequency=0;
+  rx->waterfall_sample_rate=0;
 
   //waterfall_frame = gtk_frame_new (NULL);
   rx->waterfall = gtk_drawing_area_new ();
index 2736864707cfd97fda4f8d62d0718e8e85e44f1d..962d583c2504f4629fa466a91e561370e424ee65 100644 (file)
@@ -29,6 +29,7 @@
 #include "mode.h"
 #include "xvtr_menu.h"
 #include "radio.h"
+#include "vfo.h"
 
 static GtkWidget *parent_window=NULL;
 static GtkWidget *menu_b=NULL;
@@ -37,47 +38,71 @@ static GtkWidget *title[BANDS+XVTRS];
 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 *disable_pa[BANDS+XVTRS];
 
-static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+static void save_xvtr () {
   int i;
+  int b;
   if(dialog!=NULL) {
     const char *t;
     const char *minf;
     const char *maxf;
     const char *lof;
+    const char *loerr;
     for(i=BANDS;i<BANDS+XVTRS;i++) {
       BAND *xvtr=band_get_band(i);
       BANDSTACK *bandstack=xvtr->bandstack;
-      BANDSTACK_ENTRY *entry=bandstack->entry;
       t=gtk_entry_get_text(GTK_ENTRY(title[i]));
       strcpy(xvtr->title,t);
       if(strlen(t)!=0) {
         minf=gtk_entry_get_text(GTK_ENTRY(min_frequency[i]));
-        xvtr->frequencyMin=atoll(minf);
+        xvtr->frequencyMin=atoll(minf)*1000000;
         maxf=gtk_entry_get_text(GTK_ENTRY(max_frequency[i]));
-        xvtr->frequencyMax=atoll(maxf);
+        xvtr->frequencyMax=atoll(maxf)*1000000;
         lof=gtk_entry_get_text(GTK_ENTRY(lo_frequency[i]));
-        xvtr->frequencyLO=atoll(lof);
+        xvtr->frequencyLO=atoll(lof)*1000000;
+        loerr=gtk_entry_get_text(GTK_ENTRY(lo_error[i]));
+        xvtr->errorLO=atoll(loerr);
         xvtr->disablePA=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(disable_pa[i]));
-        entry->frequency=xvtr->frequencyMin;
-        entry->mode=modeUSB;
-        entry->filter=filterF6;
+        for(b=0;b<bandstack->entries;b++) {
+          BANDSTACK_ENTRY *entry=&bandstack->entry[b];
+          entry->frequency=xvtr->frequencyMin;
+          entry->mode=modeUSB;
+          entry->filter=filterF6;
+        }
 fprintf(stderr,"min=%s:%lld max=%s:%lld lo=%s:%lld\n",minf,xvtr->frequencyMin,maxf,xvtr->frequencyMax,lof,xvtr->frequencyLO);
       } else {
         xvtr->frequencyMin=0;
         xvtr->frequencyMax=0;
         xvtr->frequencyLO=0;
+        xvtr->errorLO=0;
         xvtr->disablePA=0;
       }
     }
+    vfo_xvtr_changed();
+  }
+}
+
+static void cleanup() {
+  save_xvtr();
+  if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
     dialog=NULL;
     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;
+}
+
 void xvtr_menu(GtkWidget *parent) {
   int i,j;
   char f[16];
@@ -87,7 +112,9 @@ fprintf(stderr,"xvtr_menu\n");
 
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
+  gtk_window_set_title(GTK_WINDOW(dialog),"piHPSDR - XVTR");
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
 
   GdkRGBA color;
   color.red = 1.0;
@@ -100,55 +127,63 @@ fprintf(stderr,"xvtr_menu\n");
   GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
 
   GtkWidget *grid=gtk_grid_new();
-  //gtk_grid_set_column_spacing (GTK_GRID(grid),10);
-  //gtk_grid_set_row_spacing (GTK_GRID(grid),10);
-  //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
-  //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+  gtk_grid_set_column_spacing (GTK_GRID(grid),10);
+  gtk_grid_set_row_homogeneous(GTK_GRID(grid),FALSE);
+  gtk_grid_set_column_homogeneous(GTK_GRID(grid),FALSE);
 
-  GtkWidget *close_b=gtk_button_new_with_label("Close XVTR");
+  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);
 
   GtkWidget *label=gtk_label_new("Title");
   gtk_grid_attach(GTK_GRID(grid),label,0,1,1,1);
-  label=gtk_label_new("Min Freq (Hz)");
+  label=gtk_label_new("Min Frequency(MHz)");
   gtk_grid_attach(GTK_GRID(grid),label,1,1,1,1);
-  label=gtk_label_new("Max Freq (Hz)");
+  label=gtk_label_new("Max Frequency(MHz)");
   gtk_grid_attach(GTK_GRID(grid),label,2,1,1,1);
-  label=gtk_label_new("LO Freq (Hz)");
+  label=gtk_label_new("LO Frequency(MHz)");
   gtk_grid_attach(GTK_GRID(grid),label,3,1,1,1);
-  label=gtk_label_new("Disable PA");
+  label=gtk_label_new("LO Error(Hz)");
   gtk_grid_attach(GTK_GRID(grid),label,4,1,1,1);
-
+  label=gtk_label_new("Disable PA");
+  gtk_grid_attach(GTK_GRID(grid),label,5,1,1,1);
 
 
   for(i=BANDS;i<BANDS+XVTRS;i++) {
-fprintf(stderr,"xvtr_menu: band: %d\n",i);
     BAND *xvtr=band_get_band(i);
-fprintf(stderr,"xvtr_menu: band: %s\n",xvtr->title);
 
     title[i]=gtk_entry_new();
+    gtk_entry_set_width_chars(GTK_ENTRY(title[i]),7);
     gtk_entry_set_text(GTK_ENTRY(title[i]),xvtr->title);
     gtk_grid_attach(GTK_GRID(grid),title[i],0,i+2,1,1);
 
     min_frequency[i]=gtk_entry_new();
-    sprintf(f,"%lld",xvtr->frequencyMin);
+    gtk_entry_set_width_chars(GTK_ENTRY(min_frequency[i]),7);
+    sprintf(f,"%lld",xvtr->frequencyMin/1000000LL);
     gtk_entry_set_text(GTK_ENTRY(min_frequency[i]),f);
     gtk_grid_attach(GTK_GRID(grid),min_frequency[i],1,i+2,1,1);
     
     max_frequency[i]=gtk_entry_new();
-    sprintf(f,"%lld",xvtr->frequencyMax);
+    gtk_entry_set_width_chars(GTK_ENTRY(max_frequency[i]),7);
+    sprintf(f,"%lld",xvtr->frequencyMax/1000000LL);
     gtk_entry_set_text(GTK_ENTRY(max_frequency[i]),f);
     gtk_grid_attach(GTK_GRID(grid),max_frequency[i],2,i+2,1,1);
     
     lo_frequency[i]=gtk_entry_new();
-    sprintf(f,"%lld",xvtr->frequencyLO);
+    gtk_entry_set_width_chars(GTK_ENTRY(lo_frequency[i]),7);
+    sprintf(f,"%lld",xvtr->frequencyLO/1000000LL);
     gtk_entry_set_text(GTK_ENTRY(lo_frequency[i]),f);
     gtk_grid_attach(GTK_GRID(grid),lo_frequency[i],3,i+2,1,1);
 
+    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);
+
     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],4,i+2,1,1);
+    gtk_grid_attach(GTK_GRID(grid),disable_pa[i],5,i+2,1,1);
     
   }