]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
changes for updated wdsp and some cleanup
authorJohn Melton g0orx/n6lyt <john.d.melton@googlemail.com>
Wed, 6 Apr 2016 07:10:52 +0000 (07:10 +0000)
committerJohn Melton g0orx/n6lyt <john.d.melton@googlemail.com>
Wed, 6 Apr 2016 07:10:52 +0000 (07:10 +0000)
53 files changed:
Makefile
agc.h
alex.h
band.c
band.h
bandstack.h
channel.h
discovered.c [new file with mode: 0644]
discovered.h
filter.c
filter.h
gpio.c [new file with mode: 0644]
gpio.h [new file with mode: 0644]
main.c
main.h
menu.c [new file with mode: 0644]
menu.h [new file with mode: 0644]
meter.c
meter.h
mode.c
mode.h
new_discovery.c
new_discovery.h
new_protocol.c
new_protocol.h
new_protocol_programmer.c
old_discovery.c [new file with mode: 0644]
old_discovery.h [new file with mode: 0644]
old_protocol.c [new file with mode: 0644]
old_protocol.h [new file with mode: 0644]
panadapter.c
panadapter.h
pihpsdr [deleted file]
property.c
property.h
radio.c
radio.h
rotary_encoder.c [deleted file]
rotary_encoder.h [deleted file]
splash.c
splash.h
splash.png [deleted file]
toolbar.c
toolbar.h
version.c [new file with mode: 0644]
version.h [new file with mode: 0644]
vfo.c
vfo.h
waterfall.c
waterfall.h
wdsp_init.c [new file with mode: 0644]
wdsp_init.h [new file with mode: 0644]
xvtr.h

index c5bae3b6503938b872f3ce4a8de97ade07ec5d6e..7b468b090018c58a88a1506d41c006f1c35e72d9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,10 +2,14 @@ UNAME_N := $(shell uname -n)
 
 CC=gcc
 LINK=gcc
-OPTIONS=-g -D $(UNAME_N)
+OPTIONS=-g -D $(UNAME_N) -O3
 GTKINCLUDES=`pkg-config --cflags gtk+-3.0`
 GTKLIBS=`pkg-config --libs gtk+-3.0`
+ifeq ($(UNAME_N),raspberrypi)
 LIBS=-lwiringPi -lpigpio -lrt -lm -lwdsp -lpthread $(GTKLIBS)
+else
+LIBS=-lwiringPi -lrt -lm -lwdsp -lpthread $(GTKLIBS)
+endif
 INCLUDES=$(GTKINCLUDES)
 
 COMPILE=$(CC) $(OPTIONS) $(INCLUDES)
@@ -15,72 +19,97 @@ PROGRAM=pihpsdr
 
 SOURCES= \
 band.c \
+frequency.c \
+discovered.c \
 filter.c \
 main.c \
+menu.c \
 meter.c \
 mode.c \
+old_discovery.c \
 new_discovery.c \
+old_protocol.c \
 new_protocol.c \
 new_protocol_programmer.c \
 panadapter.c \
 property.c \
 radio.c \
-rotary_encoder.c \
+gpio.c \
 splash.c \
 toolbar.c \
+version.c \
 vfo.c \
-waterfall.c
+waterfall.c \
+wdsp_init.c
 
 HEADERS= \
 agc.h \
 alex.h \
 band.h \
+frequency.h \
 bandstack.h \
 channel.h \
 discovered.h \
 filter.h \
+menu.h \
 meter.h \
 mode.h \
+old_discovery.h \
 new_discovery.h \
+old_protocol.h \
 new_protocol.h \
 panadapter.h \
 property.h \
 radio.h \
-rotary_encoder.h \
+gpio.h \
 splash.h \
 toolbar.h \
+version.h \
 vfo.h \
 waterfall.h \
+wdsp_init.h \
 xvtr.h
 
 OBJS= \
 band.o \
+frequency.o \
+discovered.o \
 filter.o \
+version.o \
 main.o \
+menu.o \
 meter.o \
 mode.o \
+old_discovery.o \
 new_discovery.o \
+old_protocol.o \
 new_protocol.o \
 new_protocol_programmer.o \
 panadapter.o \
 property.o \
 radio.o \
-rotary_encoder.o \
+gpio.o \
 splash.o \
 toolbar.o \
 vfo.o \
-waterfall.o
+waterfall.o \
+wdsp_init.o
 
-all: $(PROGRAM) $(HEADERS) $(SOURCES)
+all: prebuild $(PROGRAM) $(HEADERS) $(SOURCES)
+
+prebuild:
+       rm -f version.o
 
 $(PROGRAM): $(OBJS)
        $(LINK) -o $(PROGRAM) $(OBJS) $(LIBS)
 
 .c.o:
-       $(COMPILE) $(OPTIONS) -c -o $@ $<
+       $(COMPILE) -c -o $@ $<
 
 
 clean:
        -rm -f *.o
        -rm -f $(PROGRAM)
 
+install:
+       cp pihpsdr ../pihpsdr
diff --git a/agc.h b/agc.h
index c6e3affa2b0075e5d35e57d3663f8b2d95acb330..c64de97765f03541bfca3e119d5366fbc050af1c 100644 (file)
--- a/agc.h
+++ b/agc.h
@@ -1,3 +1,22 @@
+/* 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.
+*
+*/
+
 #define AGC_OFF 0
 #define AGC_LONG 1
 #define AGC_SLOW 2
diff --git a/alex.h b/alex.h
index 7ead806525450a3b3f3aa96862198e80e40f6ab3..a9178cb68b5f8de4d5a70a9645711e4f96cb9af4 100644 (file)
--- a/alex.h
+++ b/alex.h
@@ -1,3 +1,22 @@
+/* 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.
+*
+*/
+
 #define ALEX_RX_ANTENNA_NONE   0x00000000
 #define ALEX_RX_ANTENNA_XVTR   0x00000900
 #define ALEX_RX_ANTENNA_EXT1   0x00000A00
diff --git a/band.c b/band.c
index 53ec3284274e64c1b29eddf425be562cdeebe758..d023d04678acd3be62ae54a2bb02519d71441af0 100644 (file)
--- a/band.c
+++ b/band.c
@@ -1,3 +1,22 @@
+/* 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 <stdio.h>
 
 #include "bandstack.h"
@@ -100,19 +119,19 @@ BANDSTACK bandstackGEN={3,1,bandstack_entriesGEN};
 BANDSTACK bandstackWWV={5,1,bandstack_entriesWWV};
 
 BAND bands[BANDS] = 
-    {{"160",&bandstack160,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
-     {"80",&bandstack80,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
-     {"60",&bandstack60,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
-     {"40",&bandstack40,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
-     {"30",&bandstack30,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
-     {"20",&bandstack20,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
-     {"18",&bandstack18,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
-     {"15",&bandstack15,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
-     {"12",&bandstack12,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
-     {"10",&bandstack10,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
-     {"50",&bandstack50,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
-     {"GEN",&bandstackGEN,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB},
-     {"WWV",&bandstackWWV,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB}};
+    {{"160",&bandstack160,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB,30},
+     {"80",&bandstack80,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB,30},
+     {"60",&bandstack60,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB,30},
+     {"40",&bandstack40,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB,30},
+     {"30",&bandstack30,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB,30},
+     {"20",&bandstack20,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB,30},
+     {"18",&bandstack18,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB,30},
+     {"15",&bandstack15,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB,30},
+     {"12",&bandstack12,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB,30},
+     {"10",&bandstack10,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB,30},
+     {"50",&bandstack50,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB,30},
+     {"GEN",&bandstackGEN,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB,0},
+     {"WWV",&bandstackWWV,0,0,0,ALEX_RX_ANTENNA_NONE,ALEX_TX_ANTENNA_1,ALEX_ATTENUATION_0dB,0}};
 
 #define NUM_BAND_LIMITS 22
 
@@ -170,13 +189,24 @@ BANDSTACK_ENTRY *bandstack_entry_get_current() {
 BANDSTACK_ENTRY *bandstack_entry_next() {
     BANDSTACK *bandstack=bands[band].bandstack;
     bandstack->current_entry++;
-    if(bandstack->current_entry==bandstack->entries) {
+    if(bandstack->current_entry>=bandstack->entries) {
         bandstack->current_entry=0;
     }
     BANDSTACK_ENTRY *entry=&bandstack->entry[bandstack->current_entry];
     return entry;
 }
 
+BANDSTACK_ENTRY *bandstack_entry_previous() {
+    BANDSTACK *bandstack=bands[band].bandstack;
+    bandstack->current_entry--;
+    if(bandstack->current_entry<0) {
+        bandstack->current_entry=bandstack->entries-1;
+    }
+    BANDSTACK_ENTRY *entry=&bandstack->entry[bandstack->current_entry];
+    return entry;
+}
+
+
 int band_get_current() {
     return band;
 }
@@ -230,6 +260,10 @@ void bandSaveState() {
         sprintf(name,"band.%d.alexAttenuation",b);
         setProperty(name,value);
 
+        sprintf(value,"%d",bands[b].pa_calibration);
+        sprintf(name,"band.%d.pa_calibration",b);
+        setProperty(name,value);
+
         for(stack=0;stack<bands[b].bandstack->entries;stack++) {
             entry=bands[b].bandstack->entry;
             entry+=stack;
@@ -303,6 +337,11 @@ void bandRestoreState() {
         sprintf(name,"band.%d.alexAttenuation",b);
         value=getProperty(name);
         if(value) bands[b].alexAttenuation=atoi(value);
+
+        sprintf(name,"band.%d.pa_calibration",b);
+        value=getProperty(name);
+        if(value) bands[b].pa_calibration=atoi(value);
+
         for(stack=0;stack<bands[b].bandstack->entries;stack++) {
             entry=bands[b].bandstack->entry;
             entry+=stack;
@@ -341,4 +380,18 @@ void bandRestoreState() {
     if(value) band=atoi(value);
 }
 
+BAND_LIMITS* getBandLimits(long long minDisplay,long long maxDisplay) {
+    BAND_LIMITS* limits;
+    int i;
+
+    for(i=0;i<NUM_BAND_LIMITS;i++) {
+        limits=&bandLimits[i];
+        if((minDisplay<=limits->minFrequency&&maxDisplay>=limits->minFrequency) ||
+           (minDisplay<=limits->maxFrequency&&maxDisplay>=limits->maxFrequency)) {
+            return limits;
+        }
+    }
+
+    return NULL;
+}
 
diff --git a/band.h b/band.h
index 24d15c10c4a42337b1369ab0f0c1287a1365753d..add9288b1e956f1e01ebd53bddbdab01565423a9 100644 (file)
--- a/band.h
+++ b/band.h
@@ -1,14 +1,6 @@
-/**
-* @file band.h
-* @brief Header files for the Amateur Radio band stack.
-* @author John Melton, G0ORX/N6LYT, Doxygen Comments Dave Larsen, KV0S
-* @version 0.1
-* @date 2009-04-11
-*/
-// band.h
-
 /* Copyright (C)
-* 2009 - John Melton, G0ORX/N6LYT, Doxygen Comments Dave Larsen, KV0S
+* 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
@@ -43,6 +35,7 @@
 #define bandWWV 12
 
 #define BANDS 13
+#define HAM_BANDS 11
 
 /* --------------------------------------------------------------------------*/
 /**
@@ -68,6 +61,7 @@ struct _BAND {
     unsigned long alexRxAntenna;
     unsigned long alexTxAntenna;
     unsigned long alexAttenuation;
+    int pa_calibration;
 };
 
 typedef struct _BAND BAND;
@@ -82,19 +76,12 @@ BAND *band_get_band(int b);
 BAND *band_set_current(int b);
 
 BANDSTACK_ENTRY *bandstack_entry_next();
+BANDSTACK_ENTRY *bandstack_entry_previous();
 BANDSTACK_ENTRY *bandstack_entry_get_current();
 
-/*
-void bandSaveState();
-void bandRestoreState();
-void forceBand(int band,int setup);
-void configureXVTRButton(int setup);
-GtkWidget* buildBandUI();
-
-int remoteSetBand(gpointer *data);
-
 BAND_LIMITS* getBandLimits(long long minDisplay,long long maxDisplay);
-XVTR_ENTRY* getXvtrEntry(int i);
 
+/*
+XVTR_ENTRY* getXvtrEntry(int i);
 */
 
index 2fb8e9adf6f3df8066797d3a889a6cfcae92ae8e..c40a09edf765efa484450ec3fd56e9fdda309dad 100644 (file)
@@ -1,14 +1,7 @@
-/**
-* @file bandstack.h
-* @brief Bandstack definition files
-* @author John Melton, G0ORX/N6LYT, Doxygen Comments Dave Larsen, KV0S
-* @version 0.1
-* @date 2009-04-11
-*/
-// bandstack.h
-
 /* Copyright (C)
-* This program is free software; you can redistribute it and/or2009 - John Melton, G0ORX/N6LYT, Doxygen Comments Dave Larsen, KV0S
+* 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.
index ae1e178f9bb5998ed6ae36a2237f1c6e65fbc84e..877f7a0ee47cf7a420c58228b997d9745ab2665f 100644 (file)
--- a/channel.h
+++ b/channel.h
@@ -1,3 +1,22 @@
+/* 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.
+*
+*/
+
 #define CHANNEL_RX0 0
 #define CHANNEL_RX1 1
 #define CHANNEL_RX2 2
diff --git a/discovered.c b/discovered.c
new file mode 100644 (file)
index 0000000..513f255
--- /dev/null
@@ -0,0 +1,25 @@
+/* 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 "discovered.h"
+
+int selected_device=0;
+int devices=0;
+DISCOVERED discovered[MAX_DEVICES];
+
index e644e69f51d7344faa20878955a54cf072adee6e..6eea2623c54fc9bfb6bb257304ca338781adacf0 100644 (file)
@@ -1,3 +1,22 @@
+/* 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 <netinet/in.h>
 
 #define MAX_DEVICES 16
index e6b0fe50838850099bed605fe46ffa21fee0f57f..c6a4ff8f7e96e24695d577539a9f121aa3678cad 100644 (file)
--- a/filter.c
+++ b/filter.c
@@ -1,3 +1,22 @@
+/* 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 "filter.h"
 
 FILTER filterLSB[FILTERS]={
index ad72c9f3ec98d6fb09a1bbd07fdc7849fadf55d1..c6e05036f9e505ea5d30fae89acb0c2bee7b6079 100644 (file)
--- a/filter.h
+++ b/filter.h
@@ -1,13 +1,6 @@
-/**
-* @file filter.h
-* @brief Header files to define the filters.
-* @author John Melton, G0ORX/N6LYT, Doxygen Comments Dave Larsen, KV0S
-* @version 0.1
-* @date 2009-04-11
-*/
-// filter.h
 /* Copyright (C)
-* 2009 - John Melton, G0ORX/N6LYT, Doxygen Comments Dave Larsen, KV0S
+* 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
diff --git a/gpio.c b/gpio.c
new file mode 100644 (file)
index 0000000..ccc35ba
--- /dev/null
+++ b/gpio.c
@@ -0,0 +1,1147 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <sched.h>
+#include <pthread.h>
+#include <wiringPi.h>
+#ifdef raspberrypi
+#include <pigpio.h>
+#endif
+
+#include "band.h"
+#include "channel.h"
+#include "mode.h"
+#include "filter.h"
+#include "bandstack.h"
+#include "toolbar.h"
+#include "gpio.h"
+#include "radio.h"
+#include "toolbar.h"
+#include "main.h"
+#include "property.h"
+
+#define SYSFS_GPIO_DIR  "/sys/class/gpio"
+
+int ENABLE_VFO_ENCODER=1;
+int ENABLE_VFO_PULLUP=1;
+#ifdef raspberrypi
+int VFO_ENCODER_A=17;
+int VFO_ENCODER_B=18;
+#endif
+#ifdef odroid
+int VFO_ENCODER_A=88;
+int VFO_ENCODER_B=87;
+int VFO_ENCODER_A_PIN=0;
+int VFO_ENCODER_B_PIN=1;
+#endif
+int ENABLE_AF_ENCODER=88;
+int ENABLE_AF_PULLUP=87;
+int AF_ENCODER_A=20;
+int AF_ENCODER_B=26;
+int AF_FUNCTION=25;
+int ENABLE_RF_ENCODER=1;
+int ENABLE_RF_PULLUP=0;
+int RF_ENCODER_A=16;
+int RF_ENCODER_B=19;
+int RF_FUNCTION=8;
+int ENABLE_AGC_ENCODER=1;
+int ENABLE_AGC_PULLUP=0;
+int AGC_ENCODER_A=4;
+int AGC_ENCODER_B=21;
+int AGC_FUNCTION=7;
+int ENABLE_BAND_BUTTON=1;
+int BAND_BUTTON=13;
+int ENABLE_BANDSTACK_BUTTON=1;
+int BANDSTACK_BUTTON=12;
+int ENABLE_MODE_BUTTON=1;
+int MODE_BUTTON=6;
+int ENABLE_FILTER_BUTTON=1;
+int FILTER_BUTTON=5;
+int ENABLE_NOISE_BUTTON=1;
+int NOISE_BUTTON=24;
+int ENABLE_AGC_BUTTON=1;
+int AGC_BUTTON=23;
+int ENABLE_MOX_BUTTON=1;
+int MOX_BUTTON=27;
+int ENABLE_FUNCTION_BUTTON=1;
+int FUNCTION_BUTTON=22;
+int ENABLE_LOCK_BUTTON=1;
+int LOCK_BUTTON=25;
+
+
+
+/*
+#define PI_VFO_ENCODER_A 17
+#define PI_VFO_ENCODER_B 18
+
+#define ODROID_VFO_ENCODER_A 88
+#define ODROID_VFO_ENCODER_B 87
+#define ODROID_VFO_ENCODER_A_PIN 0
+#define ODROID_VFO_ENCODER_B_PIN 1
+
+#define AF_ENCODER_A 20
+#define AF_ENCODER_B 26
+#define AF_FUNCTION 21
+
+#define RF_ENCODER_A 16
+#define RF_ENCODER_B 19
+#define RF_FUNCTION 13
+
+#define FUNCTION_BUTTON 22
+#define BAND_BUTTON 13
+#define BANDSTACK_BUTTON 12
+#define MODE_BUTTON 6
+#define FILTER_BUTTON 5
+#define NOISE_BUTTON 24
+#define AGC_BUTTON 23
+#define MOX_BUTTON 27
+
+static int VFO_ENCODER_A=17;
+static int VFO_ENCODER_B=18;
+
+static int VFO_ENCODER_A_PIN=0;
+static int VFO_ENCODER_B_PIN=0;
+*/
+
+static volatile int vfoEncoderPos;
+static volatile int afEncoderPos;
+static volatile int afFunction;
+static volatile int rfEncoderPos;
+static volatile int rfFunction;
+static volatile int agcEncoderPos;
+static volatile int function_state;
+static volatile int band_state;
+static volatile int bandstack_state;
+static volatile int mode_state;
+static volatile int filter_state;
+static volatile int noise_state;
+static volatile int agc_state;
+static volatile int mox_state;
+static volatile int lock_state;
+
+static void* rotary_encoder_thread(void *arg);
+static pthread_t rotary_encoder_thread_id;
+int function=0;
+static int previous_function_button=0;
+static int af_function=0;
+static int previous_af_function=0;
+static int rf_function=0;
+static int previous_rf_function=0;
+static int band_button=0;
+static int previous_band_button=0;
+static int bandstack_button=0;
+static int previous_bandstack_button=0;
+static int mode_button=0;
+static int previous_mode_button=0;
+static int filter_button=0;
+static int previous_filter_button=0;
+static int noise_button=0;
+static int previous_noise_button=0;
+static int agc_button=0;
+static int previous_agc_button=0;
+static int mox_button=0;
+static int previous_mox_button=0;
+static int lock_button=0;
+static int previous_lock_button=0;
+
+static void afFunctionAlert(int gpio, int level, uint32_t tick) {
+    afFunction=(level==0);
+}
+
+static void rfFunctionAlert(int gpio, int level, uint32_t tick) {
+    rfFunction=(level==0);
+}
+
+static void functionAlert(int gpio, int level, uint32_t tick) {
+    function_state=(level==0);
+}
+
+static void bandAlert(int gpio, int level, uint32_t tick) {
+    band_state=(level==0);
+}
+
+static void bandstackAlert(int gpio, int level, uint32_t tick) {
+    bandstack_state=(level==0);
+}
+
+static void modeAlert(int gpio, int level, uint32_t tick) {
+    mode_state=(level==0);
+}
+
+static void filterAlert(int gpio, int level, uint32_t tick) {
+    filter_state=(level==0);
+}
+
+static void noiseAlert(int gpio, int level, uint32_t tick) {
+    noise_state=(level==0);
+}
+
+static void agcAlert(int gpio, int level, uint32_t tick) {
+    agc_state=(level==0);
+}
+
+static void moxAlert(int gpio, int level, uint32_t tick) {
+    mox_state=(level==0);
+}
+
+static void lockAlert(int gpio, int level, uint32_t tick) {
+    lock_state=(level==0);
+}
+
+static void vfoEncoderPulse(int gpio, int level, unsigned int tick) {
+   static int levA=0, levB=0, lastGpio = -1;
+
+   if (gpio == VFO_ENCODER_A) levA = level; else levB = level;
+
+   if (gpio != lastGpio) /* debounce */
+   {
+      lastGpio = gpio;
+
+      if ((gpio == VFO_ENCODER_A) && (level == 0))
+      {
+         if (!levB) ++vfoEncoderPos;
+      }
+      else if ((gpio == VFO_ENCODER_B) && (level == 1))
+      {
+         if (levA) --vfoEncoderPos;
+      }
+   }
+}
+
+static void afEncoderPulse(int gpio, int level, uint32_t tick)
+{
+   static int levA=0, levB=0, lastGpio = -1;
+
+   if (gpio == AF_ENCODER_A) levA = level; else levB = level;
+
+   if (gpio != lastGpio) /* debounce */
+   {
+      lastGpio = gpio;
+
+      if ((gpio == AF_ENCODER_A) && (level == 0))
+      {
+         if (!levB) ++afEncoderPos;
+      }
+      else if ((gpio == AF_ENCODER_B) && (level == 1))
+      {
+         if (levA) --afEncoderPos;
+      }
+   }
+}
+
+static void rfEncoderPulse(int gpio, int level, uint32_t tick)
+{
+   static int levA=0, levB=0, lastGpio = -1;
+
+   if (gpio == RF_ENCODER_A) levA = level; else levB = level;
+
+   if (gpio != lastGpio) /* debounce */
+   {
+      lastGpio = gpio;
+
+      if ((gpio == RF_ENCODER_A) && (level == 0))
+      {
+         if (!levB) ++rfEncoderPos;
+      }
+      else if ((gpio == RF_ENCODER_B) && (level == 1))
+      {
+         if (levA) --rfEncoderPos;
+      }
+   }
+}
+
+static void agcEncoderPulse(int gpio, int level, uint32_t tick)
+{
+   static int levA=0, levB=0, lastGpio = -1;
+
+   if (gpio == AGC_ENCODER_A) levA = level; else levB = level;
+
+   if (gpio != lastGpio) /* debounce */
+   {
+      lastGpio = gpio;
+
+      if ((gpio == AGC_ENCODER_A) && (level == 0))
+      {
+         if (!levB) ++agcEncoderPos;
+      }
+      else if ((gpio == AGC_ENCODER_B) && (level == 1))
+      {
+         if (levA) --agcEncoderPos;
+      }
+   }
+}
+
+#ifdef odroid
+void interruptB(void) {
+   vfoEncoderPulse(VFO_ENCODER_B,digitalRead(VFO_ENCODER_B_PIN),0);
+}
+
+void interruptA(void) {
+   vfoEncoderPulse(VFO_ENCODER_A,digitalRead(VFO_ENCODER_A_PIN),0);
+}
+#endif
+
+void gpio_restore_state() {
+  char* value;
+  loadProperties("gpio.props");
+  value=getProperty("ENABLE_VFO_ENCODER");
+  if(value) ENABLE_VFO_ENCODER=atoi(value);
+  value=getProperty("ENABLE_VFO_PULLUP");
+  if(value) ENABLE_VFO_PULLUP=atoi(value);
+  value=getProperty("VFO_ENCODER_A");
+  if(value) VFO_ENCODER_A=atoi(value);
+  value=getProperty("VFO_ENCODER_B");
+  if(value) VFO_ENCODER_B=atoi(value);
+#ifdef odroid
+  value=getProperty("VFO_ENCODER_A_PIN");
+  if(value) VFO_ENCODER_A_PIN=atoi(value);
+  value=getProperty("VFO_ENCODER_B_PIN");
+  if(value) VFO_ENCODER_B_PIN=atoi(value);
+#endif
+  value=getProperty("ENABLE_AF_ENCODER");
+  if(value) ENABLE_AF_ENCODER=atoi(value);
+  value=getProperty("ENABLE_AF_PULLUP");
+  if(value) ENABLE_AF_PULLUP=atoi(value);
+  value=getProperty("AF_ENCODER_A");
+  if(value) AF_ENCODER_A=atoi(value);
+  value=getProperty("AF_ENCODER_B");
+  if(value) AF_ENCODER_B=atoi(value);
+  value=getProperty("ENABLE_RF_ENCODER");
+  if(value) ENABLE_RF_ENCODER=atoi(value);
+  value=getProperty("ENABLE_RF_PULLUP");
+  if(value) ENABLE_RF_PULLUP=atoi(value);
+  value=getProperty("RF_ENCODER_A");
+  if(value) RF_ENCODER_A=atoi(value);
+  value=getProperty("RF_ENCODER_B");
+  if(value) RF_ENCODER_B=atoi(value);
+  value=getProperty("ENABLE_AGC_ENCODER");
+  if(value) ENABLE_AGC_ENCODER=atoi(value);
+  value=getProperty("ENABLE_AGC_PULLUP");
+  if(value) ENABLE_AGC_PULLUP=atoi(value);
+  value=getProperty("AGC_ENCODER_A");
+  if(value) AGC_ENCODER_A=atoi(value);
+  value=getProperty("AGC_ENCODER_B");
+  if(value) AGC_ENCODER_B=atoi(value);
+  value=getProperty("ENABLE_BAND_BUTTON");
+  if(value) ENABLE_BAND_BUTTON=atoi(value);
+  value=getProperty("BAND_BUTTON");
+  if(value) BAND_BUTTON=atoi(value);
+  value=getProperty("ENABLE_BANDSTACK_BUTTON");
+  if(value) ENABLE_BANDSTACK_BUTTON=atoi(value);
+  value=getProperty("BANDSTACK_BUTTON");
+  if(value) BANDSTACK_BUTTON=atoi(value);
+  value=getProperty("ENABLE_MODE_BUTTON");
+  if(value) ENABLE_MODE_BUTTON=atoi(value);
+  value=getProperty("MODE_BUTTON");
+  if(value) MODE_BUTTON=atoi(value);
+  value=getProperty("ENABLE_FILTER_BUTTON");
+  if(value) ENABLE_FILTER_BUTTON=atoi(value);
+  value=getProperty("FILTER_BUTTON");
+  if(value) FILTER_BUTTON=atoi(value);
+  value=getProperty("ENABLE_NOISE_BUTTON");
+  if(value) ENABLE_NOISE_BUTTON=atoi(value);
+  value=getProperty("NOISE_BUTTON");
+  if(value) NOISE_BUTTON=atoi(value);
+  value=getProperty("ENABLE_AGC_BUTTON");
+  if(value) ENABLE_AGC_BUTTON=atoi(value);
+  value=getProperty("AGC_BUTTON");
+  if(value) AGC_BUTTON=atoi(value);
+  value=getProperty("ENABLE_FUNCTION_BUTTON");
+  if(value) ENABLE_FUNCTION_BUTTON=atoi(value);
+  value=getProperty("FUNCTION_BUTTON");
+  if(value) FUNCTION_BUTTON=atoi(value);
+  value=getProperty("ENABLE_MOX_BUTTON");
+  if(value) ENABLE_MOX_BUTTON=atoi(value);
+  value=getProperty("MOX_BUTTON");
+  if(value) MOX_BUTTON=atoi(value);
+  value=getProperty("ENABLE_LOCK_BUTTON");
+  if(value) ENABLE_LOCK_BUTTON=atoi(value);
+  value=getProperty("LOCK_BUTTON");
+  if(value) LOCK_BUTTON=atoi(value);
+}
+
+void gpio_save_state() {
+   char value[80];
+
+  sprintf(value,"%d",ENABLE_VFO_ENCODER);
+  setProperty("ENABLE_VFO_ENCODER",value);
+  sprintf(value,"%d",ENABLE_VFO_PULLUP);
+  setProperty("ENABLE_VFO_PULLUP",value);
+  sprintf(value,"%d",VFO_ENCODER_A);
+  setProperty("VFO_ENCODER_A",value);
+  sprintf(value,"%d",VFO_ENCODER_B);
+  setProperty("VFO_ENCODER_B",value);
+#ifdef odroid
+  sprintf(value,"%d",VFO_ENCODER_A_PIN);
+  setProperty("VFO_ENCODER_A_PIN",value);
+  sprintf(value,"%d",VFO_ENCODER_B_PIN);
+  setProperty("VFO_ENCODER_B_PIN",value);
+#endif
+  sprintf(value,"%d",ENABLE_AF_ENCODER);
+  setProperty("ENABLE_AF_ENCODER",value);
+  sprintf(value,"%d",ENABLE_AF_PULLUP);
+  setProperty("ENABLE_AF_PULLUP",value);
+  sprintf(value,"%d",AF_ENCODER_A);
+  setProperty("AF_ENCODER_A",value);
+  sprintf(value,"%d",AF_ENCODER_B);
+  setProperty("AF_ENCODER_B",value);
+  sprintf(value,"%d",ENABLE_RF_ENCODER);
+  setProperty("ENABLE_RF_ENCODER",value);
+  sprintf(value,"%d",ENABLE_RF_PULLUP);
+  setProperty("ENABLE_RF_PULLUP",value);
+  sprintf(value,"%d",RF_ENCODER_A);
+  setProperty("RF_ENCODER_A",value);
+  sprintf(value,"%d",RF_ENCODER_B);
+  setProperty("RF_ENCODER_B",value);
+  sprintf(value,"%d",ENABLE_AGC_ENCODER);
+  setProperty("ENABLE_AGC_ENCODER",value);
+  sprintf(value,"%d",ENABLE_AGC_PULLUP);
+  setProperty("ENABLE_AGC_PULLUP",value);
+  sprintf(value,"%d",AGC_ENCODER_A);
+  setProperty("AGC_ENCODER_A",value);
+  sprintf(value,"%d",AGC_ENCODER_B);
+  setProperty("AGC_ENCODER_B",value);
+  sprintf(value,"%d",ENABLE_BAND_BUTTON);
+  setProperty("ENABLE_BAND_BUTTON",value);
+  sprintf(value,"%d",BAND_BUTTON);
+  setProperty("BAND_BUTTON",value);
+  sprintf(value,"%d",ENABLE_BANDSTACK_BUTTON);
+  setProperty("ENABLE_BANDSTACK_BUTTON",value);
+  sprintf(value,"%d",BANDSTACK_BUTTON);
+  setProperty("BANDSTACK_BUTTON",value);
+  sprintf(value,"%d",ENABLE_MODE_BUTTON);
+  setProperty("ENABLE_MODE_BUTTON",value);
+  sprintf(value,"%d",MODE_BUTTON);
+  setProperty("MODE_BUTTON",value);
+  sprintf(value,"%d",ENABLE_FILTER_BUTTON);
+  setProperty("ENABLE_FILTER_BUTTON",value);
+  sprintf(value,"%d",FILTER_BUTTON);
+  setProperty("FILTER_BUTTON",value);
+  sprintf(value,"%d",ENABLE_NOISE_BUTTON);
+  setProperty("ENABLE_NOISE_BUTTON",value);
+  sprintf(value,"%d",NOISE_BUTTON);
+  setProperty("NOISE_BUTTON",value);
+  sprintf(value,"%d",ENABLE_AGC_BUTTON);
+  setProperty("ENABLE_AGC_BUTTON",value);
+  sprintf(value,"%d",AGC_BUTTON);
+  setProperty("AGC_BUTTON",value);
+  sprintf(value,"%d",ENABLE_FUNCTION_BUTTON);
+  setProperty("ENABLE_FUNCTION_BUTTON",value);
+  sprintf(value,"%d",FUNCTION_BUTTON);
+  setProperty("FUNCTION_BUTTON",value);
+  sprintf(value,"%d",ENABLE_MOX_BUTTON);
+  setProperty("ENABLE_MOX_BUTTON",value);
+  sprintf(value,"%d",MOX_BUTTON);
+  setProperty("MOX_BUTTON",value);
+  sprintf(value,"%d",ENABLE_LOCK_BUTTON);
+  setProperty("ENABLE_LOCK_BUTTON",value);
+  sprintf(value,"%d",LOCK_BUTTON);
+  setProperty("LOCK_BUTTON",value);
+
+  saveProperties("gpio.props");
+}
+
+
+int gpio_init() {
+fprintf(stderr,"encoder_init\n");
+  gpio_restore_state();
+  //if(strcmp(unameData.nodename,"raspberrypi")==0) {
+#ifdef raspberrypi
+
+    fprintf(stderr,"encoder_init: VFO_ENCODER_A=%d VFO_ENCODER_B=%d\n",VFO_ENCODER_A,VFO_ENCODER_B);
+
+    fprintf(stderr,"gpioInitialize\n");
+    if(gpioInitialise()<0) {
+        fprintf(stderr,"Cannot initialize GPIO\n");
+        return -1;
+    }
+
+  if(ENABLE_FUNCTION_BUTTON) {
+    gpioSetMode(FUNCTION_BUTTON, PI_INPUT);
+    gpioSetPullUpDown(FUNCTION_BUTTON,PI_PUD_UP);
+    gpioSetAlertFunc(FUNCTION_BUTTON, functionAlert);
+  }
+
+  if(ENABLE_VFO_ENCODER) {
+    gpioSetMode(VFO_ENCODER_A, PI_INPUT);
+    gpioSetMode(VFO_ENCODER_B, PI_INPUT);
+    if(ENABLE_VFO_PULLUP) {
+      gpioSetPullUpDown(VFO_ENCODER_A, PI_PUD_UP);
+      gpioSetPullUpDown(VFO_ENCODER_B, PI_PUD_UP);
+    } else {
+      gpioSetPullUpDown(VFO_ENCODER_A, PI_PUD_OFF);
+      gpioSetPullUpDown(VFO_ENCODER_B, PI_PUD_OFF);
+    }
+    gpioSetAlertFunc(VFO_ENCODER_A, vfoEncoderPulse);
+    gpioSetAlertFunc(VFO_ENCODER_B, vfoEncoderPulse);
+    vfoEncoderPos=0;
+  }
+
+
+    gpioSetMode(AF_FUNCTION, PI_INPUT);
+    gpioSetPullUpDown(AF_FUNCTION,PI_PUD_UP);
+    gpioSetAlertFunc(AF_FUNCTION, afFunctionAlert);
+    afFunction=0;
+
+  if(ENABLE_AF_ENCODER) {
+    gpioSetMode(AF_ENCODER_A, PI_INPUT);
+    gpioSetMode(AF_ENCODER_B, PI_INPUT);
+    if(ENABLE_AF_PULLUP) {
+      gpioSetPullUpDown(AF_ENCODER_A, PI_PUD_UP);
+      gpioSetPullUpDown(AF_ENCODER_B, PI_PUD_UP);
+    } else {
+      gpioSetPullUpDown(AF_ENCODER_A, PI_PUD_OFF);
+      gpioSetPullUpDown(AF_ENCODER_B, PI_PUD_OFF);
+    }
+    gpioSetAlertFunc(AF_ENCODER_A, afEncoderPulse);
+    gpioSetAlertFunc(AF_ENCODER_B, afEncoderPulse);
+    afEncoderPos=0;
+  }
+
+    gpioSetMode(RF_FUNCTION, PI_INPUT);
+    gpioSetPullUpDown(RF_FUNCTION,PI_PUD_UP);
+    gpioSetAlertFunc(RF_FUNCTION, rfFunctionAlert);
+    rfFunction=0;
+
+  if(ENABLE_RF_ENCODER) {
+    gpioSetMode(RF_ENCODER_A, PI_INPUT);
+    gpioSetMode(RF_ENCODER_B, PI_INPUT);
+    if(ENABLE_AF_PULLUP) {
+      gpioSetPullUpDown(RF_ENCODER_A, PI_PUD_UP);
+      gpioSetPullUpDown(RF_ENCODER_B, PI_PUD_UP);
+    } else {
+      gpioSetPullUpDown(RF_ENCODER_A, PI_PUD_OFF);
+      gpioSetPullUpDown(RF_ENCODER_B, PI_PUD_OFF);
+    }
+    gpioSetAlertFunc(RF_ENCODER_A, rfEncoderPulse);
+    gpioSetAlertFunc(RF_ENCODER_B, rfEncoderPulse);
+    rfEncoderPos=0;
+  }
+
+  if(ENABLE_AGC_ENCODER) {
+    gpioSetMode(AGC_ENCODER_A, PI_INPUT);
+    gpioSetMode(AGC_ENCODER_B, PI_INPUT);
+    if(ENABLE_AF_PULLUP) {
+      gpioSetPullUpDown(AGC_ENCODER_A, PI_PUD_UP);
+      gpioSetPullUpDown(AGC_ENCODER_B, PI_PUD_UP);
+    } else {
+      gpioSetPullUpDown(AGC_ENCODER_A, PI_PUD_OFF);
+      gpioSetPullUpDown(AGC_ENCODER_B, PI_PUD_OFF);
+    }
+    gpioSetAlertFunc(AGC_ENCODER_A, agcEncoderPulse);
+    gpioSetAlertFunc(AGC_ENCODER_B, agcEncoderPulse);
+    rfEncoderPos=0;
+  }
+
+
+  if(ENABLE_BAND_BUTTON) {
+    gpioSetMode(BAND_BUTTON, PI_INPUT);
+    gpioSetPullUpDown(BAND_BUTTON,PI_PUD_UP);
+    gpioSetAlertFunc(BAND_BUTTON, bandAlert);
+  }
+  if(ENABLE_BANDSTACK_BUTTON) {
+    gpioSetMode(BANDSTACK_BUTTON, PI_INPUT);
+    gpioSetPullUpDown(BANDSTACK_BUTTON,PI_PUD_UP);
+    gpioSetAlertFunc(BANDSTACK_BUTTON, bandstackAlert);
+  }
+  if(ENABLE_MODE_BUTTON) {
+    gpioSetMode(MODE_BUTTON, PI_INPUT);
+    gpioSetPullUpDown(MODE_BUTTON,PI_PUD_UP);
+    gpioSetAlertFunc(MODE_BUTTON, modeAlert);
+  }
+  if(ENABLE_FILTER_BUTTON) {
+    gpioSetMode(FILTER_BUTTON, PI_INPUT);
+    gpioSetPullUpDown(FILTER_BUTTON,PI_PUD_UP);
+    gpioSetAlertFunc(FILTER_BUTTON, filterAlert);
+  }
+  if(ENABLE_NOISE_BUTTON) {
+    gpioSetMode(NOISE_BUTTON, PI_INPUT);
+    gpioSetPullUpDown(NOISE_BUTTON,PI_PUD_UP);
+    gpioSetAlertFunc(NOISE_BUTTON, noiseAlert);
+  }
+  if(ENABLE_AGC_BUTTON) {
+    gpioSetMode(AGC_BUTTON, PI_INPUT);
+    gpioSetPullUpDown(AGC_BUTTON,PI_PUD_UP);
+    gpioSetAlertFunc(AGC_BUTTON, agcAlert);
+  }
+  if(ENABLE_MOX_BUTTON) {
+    gpioSetMode(MOX_BUTTON, PI_INPUT);
+    gpioSetPullUpDown(MOX_BUTTON,PI_PUD_UP);
+    gpioSetAlertFunc(MOX_BUTTON, moxAlert);
+  }
+
+  if(ENABLE_LOCK_BUTTON) {
+    gpioSetMode(LOCK_BUTTON, PI_INPUT);
+    gpioSetPullUpDown(LOCK_BUTTON,PI_PUD_UP);
+    gpioSetAlertFunc(LOCK_BUTTON, lockAlert);
+  }
+#endif
+//  } else if(strcmp(unameData.nodename,"odroid")==0) {
+#ifdef odroid
+
+    //VFO_ENCODER_A=ODROID_VFO_ENCODER_A;
+    //VFO_ENCODER_B=ODROID_VFO_ENCODER_B;
+    //VFO_ENCODER_A_PIN=ODROID_VFO_ENCODER_A_PIN;
+    //VFO_ENCODER_B_PIN=ODROID_VFO_ENCODER_B_PIN;
+    fprintf(stderr,"encoder_init: VFO_ENCODER_A=%d VFO_ENCODER_B=%d\n",VFO_ENCODER_A,VFO_ENCODER_B);
+
+    fprintf(stderr,"wiringPiSetup\n");
+    if (wiringPiSetup () < 0) {
+      printf ("Unable to setup wiringPi: %s\n", strerror (errno));
+      return 1;
+    }
+
+    FILE *fp;
+
+    fp = popen("echo 88 > /sys/class/gpio/export\n", "r");
+    pclose(fp);
+    fp = popen("echo \"in\" > /sys/class/gpio/gpio88/direction\n", "r");
+    pclose(fp);
+    fp = popen("chmod 0666 /sys/class/gpio/gpio88/value\n", "r");
+    pclose(fp);
+
+    fp = popen("echo 87 > /sys/class/gpio/export\n", "r");
+    pclose(fp);
+    fp = popen("echo \"in\" > /sys/class/gpio/gpio87/direction\n", "r");
+    pclose(fp);
+    fp = popen("chmod 0666 /sys/class/gpio/gpio87/value\n", "r");
+    pclose(fp);
+
+    if ( wiringPiISR (0, INT_EDGE_BOTH, &interruptB) < 0 ) {
+      printf ("Unable to setup ISR: %s\n", strerror (errno));
+      return 1;
+    }
+
+    if ( wiringPiISR (1, INT_EDGE_BOTH, &interruptA) < 0 ) {
+      printf ("Unable to setup ISR: %s\n", strerror (errno));
+      return 1;
+    }
+#endif
+//  } else {
+//    fprintf(stderr,"Unknown nodename: %s. Rotary Encoder not enabled.\n",unameData.nodename);
+//    return 1;
+//  }
+
+  int rc=pthread_create(&rotary_encoder_thread_id, NULL, rotary_encoder_thread, NULL);
+  if(rc<0) {
+    fprintf(stderr,"pthread_create for rotary_encoder_thread failed %d\n",rc);
+  }
+
+
+  return 0;
+}
+
+void gpio_close() {
+//  if(strcmp(unameData.nodename,"raspberrypi")==0) {
+#ifdef raspberrypi
+    gpioTerminate();
+#endif
+//  }
+//  if(strcmp(unameData.nodename,"odroid")==0) {
+#ifdef odroid
+    FILE *fp;
+    fp = popen("echo 97 > /sys/class/gpio/unexport\n", "r");
+    pclose(fp);
+    fp = popen("echo 108 > /sys/class/gpio/unexport\n", "r");
+    pclose(fp);
+#endif
+//  }
+}
+
+int vfo_encoder_get_pos() {
+  int pos=vfoEncoderPos;
+
+  if(vfo_encoder_divisor>1) {
+    if(pos<0 && pos>-vfo_encoder_divisor) {
+        pos=0;
+    } else if(pos>0 && pos<vfo_encoder_divisor) {
+        pos=0;
+    }
+    pos=pos/vfo_encoder_divisor;
+    vfoEncoderPos=vfoEncoderPos-(pos*vfo_encoder_divisor);
+  } else {
+    vfoEncoderPos=0;
+  }
+  return pos;
+}
+
+int af_encoder_get_pos() {
+    int pos=afEncoderPos;
+    afEncoderPos=0;
+    return pos;
+}
+
+int af_function_get_state() {
+    return afFunction;
+}
+
+int rf_encoder_get_pos() {
+    int pos=rfEncoderPos;
+    rfEncoderPos=0;
+    return pos;
+}
+
+int agc_encoder_get_pos() {
+    int pos=agcEncoderPos;
+    agcEncoderPos=0;
+    return pos;
+}
+
+int rf_function_get_state() {
+    return rfFunction;
+}
+
+int function_get_state() {
+    return function_state;
+}
+
+int band_get_state() {
+    return band_state;
+}
+
+int bandstack_get_state() {
+    return bandstack_state;
+}
+
+int mode_get_state() {
+    return mode_state;
+}
+
+int filter_get_state() {
+    return filter_state;
+}
+
+int noise_get_state() {
+    return noise_state;
+}
+
+int agc_get_state() {
+    return agc_state;
+}
+
+int mox_get_state() {
+    return mox_state;
+}
+
+int lock_get_state() {
+    return lock_state;
+}
+
+
+static int vfo_encoder_changed(void *data) {
+  if(!locked) {
+    int pos=*(int*)data;
+    BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
+    entry->frequencyA=entry->frequencyA+(pos*step);
+    setFrequency(entry->frequencyA);
+    vfo_update(NULL);
+  }
+  free(data);
+  return 0;
+}
+
+static int af_encoder_changed(void *data) {
+  int pos=*(int*)data;
+  if(pos!=0) {
+    if(function) {
+      // mic gain
+      double gain=mic_gain;
+      gain+=(double)pos/100.0;
+      if(gain<0.0) {
+        gain=0.0;
+      } else if(gain>4.0) {
+        gain=4.0;
+      }
+      set_mic_gain(gain);
+    } else {
+      // af gain
+      double gain=volume;
+      gain+=(double)pos/100.0;
+      if(gain<0.0) {
+        gain=0.0;
+      } else if(gain>1.0) {
+        gain=1.0;
+      }
+      set_af_gain(gain);
+    }
+  }
+  free(data);
+  return 0;
+}
+
+static int rf_encoder_changed(void *data) {
+  int pos=*(int*)data;
+  if(pos!=0) {
+    if(function || tune) {
+      // tune drive
+      double d=getTuneDrive();
+      d+=(double)pos/100.0;
+      if(d<0.0) {
+        d=0.0;
+      } else if(d>1.0) {
+        d=1.0;
+      }
+      set_tune(d);
+    } else {
+      // drive
+      double d=getDrive();
+      d+=(double)pos/100.0;
+      if(d<0.0) {
+        d=0.0;
+      } else if(d>1.0) {
+        d=1.0;
+      }
+      set_drive(d);
+    }
+  }
+  free(data);
+  return 0;
+}
+
+static int agc_encoder_changed(void *data) {
+  int pos=*(int*)data;
+  if(pos!=0) {
+    double gain=agc_gain;
+    gain+=(double)pos;
+    if(gain<0.0) {
+      gain=0.0;
+    } else if(gain>120.0) {
+      gain=120.0;
+    }
+    set_agc_gain(gain);
+  }
+  return 0;
+}
+
+static int band_pressed(void *data) {
+  BAND* band;
+  BANDSTACK_ENTRY *entry;
+fprintf(stderr,"band_pressed\n");
+  int b=band_get_current();
+  if(function) {
+    b--;
+    if(b<0) {
+      b=BANDS-1;
+    }
+  } else {
+    b++;
+    if(b>=BANDS) {
+      b=0;
+    }
+  }
+  band=band_set_current(b);
+  entry=bandstack_entry_get_current();
+
+  setFrequency(entry->frequencyA);
+  setMode(entry->mode);
+  FILTER* band_filters=filters[entry->mode];
+  FILTER* band_filter=&band_filters[entry->filter];
+  setFilter(band_filter->low,band_filter->high);
+
+  band=band_get_current_band();
+  set_alex_rx_antenna(band->alexRxAntenna);
+  set_alex_tx_antenna(band->alexTxAntenna);
+  set_alex_attenuation(band->alexAttenuation);
+  vfo_update(NULL);
+
+  return 0;
+}
+
+static int bandstack_pressed(void *data) {
+  BANDSTACK_ENTRY *entry;
+  fprintf(stderr,"bandstack_pressed\n");
+  if(function) {
+    entry=bandstack_entry_previous();
+  } else {
+    entry=bandstack_entry_next();
+  }
+  setFrequency(entry->frequencyA);
+  setMode(entry->mode);
+  FILTER* band_filters=filters[entry->mode];
+  FILTER* band_filter=&band_filters[entry->filter];
+  setFilter(band_filter->low,band_filter->high);
+  vfo_update(NULL);
+  return 0;
+}
+
+static int function_pressed(void *data) {
+fprintf(stderr,"function_pressed\n");
+  function=function==1?0:1;
+  vfo_update(NULL);
+  return 0;
+}
+
+static int mox_pressed(void *data) {
+fprintf(stderr,"mox_pressed\n");
+  if(function) {
+    tune_cb((GtkWidget *)NULL, (gpointer)NULL);
+  } else {
+    mox_cb((GtkWidget *)NULL, (gpointer)NULL);
+  }
+  return 0;
+}
+
+static int lock_pressed(void *data) {
+fprintf(stderr,"lock_pressed\n");
+  lock_cb((GtkWidget *)NULL, (gpointer)NULL);
+  return 0;
+}
+
+static int mode_pressed(void *data) {
+  BAND* band;
+  BANDSTACK_ENTRY *entry;
+
+fprintf(stderr,"mode_pressed\n");
+  band=band_get_current_band();
+  entry=bandstack_entry_get_current();
+  if(function) {
+    entry->mode--;
+    if(entry->mode<0) {
+      entry->mode=MODES-1;
+    }
+  } else {
+    entry->mode++;
+    if(entry->mode>=MODES) {
+      entry->mode=0;
+    }
+  }
+  setMode(entry->mode);
+
+  FILTER* band_filters=filters[entry->mode];
+  FILTER* band_filter=&band_filters[entry->filter];
+  setFilter(band_filter->low,band_filter->high);
+  
+  vfo_update(NULL);
+
+  return 0;
+}
+
+static int filter_pressed(void *data) {
+  BAND* band;
+  BANDSTACK_ENTRY *entry;
+
+fprintf(stderr,"filter_pressed\n");
+  band=band_get_current_band();
+  entry=bandstack_entry_get_current();
+  // note order of filter reversed (largest first)
+  if(function) {
+    entry->filter++;
+    if(entry->filter>=FILTERS) {
+      entry->filter=0;
+    }
+  } else {
+    entry->filter--;
+    if(entry->filter<0) {
+      entry->filter=FILTERS-1;
+    }
+  }
+
+  FILTER* band_filters=filters[entry->mode];
+  FILTER* band_filter=&band_filters[entry->filter];
+  setFilter(band_filter->low,band_filter->high);
+  vfo_update(NULL);
+
+  return 0;
+}
+
+static int noise_pressed(void *data) {
+fprintf(stderr,"noise_pressed\n");
+  if(function) {
+    if(nr) {
+      nr=0;
+    } else if(nb) {
+      nr=1;
+      nb=0;
+    } else if(anf) {
+      nb=1;
+      anf=0;
+    } else if(snb) {
+      snb=0;
+      anf=1;
+    } else {
+      snb=1;
+    }
+  } else {
+    if(nr) {
+      nr=0;
+      nb=1;
+    } else if(nb) {
+      nb=0;
+      anf=1;
+    } else if(anf) {
+      anf=0;
+      snb=1;
+    } else if(snb) {
+      snb=0;
+    } else {
+      nr=1;
+    }
+  }
+  SetRXAANRRun(CHANNEL_RX0, nr);
+  SetRXAEMNRRun(CHANNEL_RX0, nb);
+  SetRXAANFRun(CHANNEL_RX0, anf);
+  SetRXASNBARun(CHANNEL_RX0, snb);
+  vfo_update(NULL);
+  return 0;
+}
+
+static int agc_pressed(void *data) {
+fprintf(stderr,"agc_pressed\n");
+  if(function) {
+    agc--;
+    if(agc<0) {
+      agc=3;
+    }
+  } else {
+    agc++;
+    if(agc>=4) {
+      agc=0;
+    }
+  }
+  SetRXAAGCMode(CHANNEL_RX0, agc);
+  vfo_update(NULL);
+  return 0;
+}
+
+static void* rotary_encoder_thread(void *arg) {
+    int pos;
+    while(1) {
+
+        int function_button=function_get_state();
+        if(function_button!=previous_function_button) {
+            previous_function_button=function_button;
+            if(function_button) {
+                g_idle_add(function_pressed,(gpointer)NULL);
+            }
+        }
+
+        pos=vfo_encoder_get_pos();
+        if(pos!=0) {
+            int *p=malloc(sizeof(int));
+            *p=pos;
+            g_idle_add(vfo_encoder_changed,(gpointer)p);
+        }
+
+/*
+        af_function=af_function_get_state();
+        if(af_function!=previous_af_function) {
+            previous_af_function=af_function;
+        }
+*/
+        pos=af_encoder_get_pos();
+        if(pos!=0) {
+            int *p=malloc(sizeof(int));
+            *p=pos;
+            g_idle_add(af_encoder_changed,(gpointer)p);
+        }
+
+/*
+        rf_function=rf_function_get_state();
+        if(rf_function!=previous_rf_function) {
+            previous_rf_function=rf_function;
+        }
+*/
+        pos=rf_encoder_get_pos();
+        if(pos!=0) {
+            int *p=malloc(sizeof(int));
+            *p=pos;
+            g_idle_add(rf_encoder_changed,(gpointer)p);
+        }
+
+        pos=agc_encoder_get_pos();
+        if(pos!=0) {
+            int *p=malloc(sizeof(int));
+            *p=pos;
+            g_idle_add(agc_encoder_changed,(gpointer)p);
+        }
+
+
+        int band_button=band_get_state();
+        if(band_button!=previous_band_button) {
+            previous_band_button=band_button;
+            if(band_button) {
+                g_idle_add(band_pressed,(gpointer)NULL);
+            }
+        }
+
+        int bandstack_button=bandstack_get_state();
+        if(bandstack_button!=previous_bandstack_button) {
+            previous_bandstack_button=bandstack_button;
+            if(bandstack_button) {
+                g_idle_add(bandstack_pressed,(gpointer)NULL);
+            }
+        }
+
+        int mode_button=mode_get_state();
+        if(mode_button!=previous_mode_button) {
+            previous_mode_button=mode_button;
+            if(mode_button) {
+                g_idle_add(mode_pressed,(gpointer)NULL);
+            }
+        }
+
+        int filter_button=filter_get_state();
+        if(filter_button!=previous_filter_button) {
+            previous_filter_button=filter_button;
+            if(filter_button) {
+                g_idle_add(filter_pressed,(gpointer)NULL);
+            }
+        }
+
+        int noise_button=noise_get_state();
+        if(noise_button!=previous_noise_button) {
+            previous_noise_button=noise_button;
+            if(noise_button) {
+                g_idle_add(noise_pressed,(gpointer)NULL);
+            }
+        }
+
+        int agc_button=agc_get_state();
+        if(agc_button!=previous_agc_button) {
+            previous_agc_button=agc_button;
+            if(agc_button) {
+                g_idle_add(agc_pressed,(gpointer)NULL);
+            }
+        }
+
+        int mox_button=mox_get_state();
+        if(mox_button!=previous_mox_button) {
+            previous_mox_button=mox_button;
+            if(mox_button) {
+                g_idle_add(mox_pressed,(gpointer)NULL);
+            }
+        }
+
+        int lock_button=lock_get_state();
+        if(lock_button!=previous_lock_button) {
+            previous_lock_button=lock_button;
+            if(lock_button) {
+                g_idle_add(lock_pressed,(gpointer)NULL);
+            }
+        }
+
+//        if(strcmp(unameData.nodename,"raspberrypi")==0) {
+#ifdef raspberrypi
+          gpioDelay(100000); // 10 per second
+#endif
+//        } else if(strcmp(unameData.nodename,"odroid")==0) {
+#ifdef odroid
+          usleep(100000);
+#endif
+//        }
+    }
+}
diff --git a/gpio.h b/gpio.h
new file mode 100644 (file)
index 0000000..569b616
--- /dev/null
+++ b/gpio.h
@@ -0,0 +1,71 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+extern int ENABLE_VFO_ENCODER;
+extern int ENABLE_VFO_PULLUP;
+extern int VFO_ENCODER_A;
+extern int VFO_ENCODER_B;
+extern int VFO_ENCODER_A_PIN;
+extern int VFO_ENCODER_B_PIN;
+extern int ENABLE_AF_ENCODER;
+extern int ENABLE_AF_PULLUP;
+extern int AF_ENCODER_A;
+extern int AF_ENCODER_B;
+extern int ENABLE_RF_ENCODER;
+extern int ENABLE_RF_PULLUP;
+extern int RF_ENCODER_A;
+extern int RF_ENCODER_B;
+extern int ENABLE_AGC_ENCODER;
+extern int ENABLE_AGC_PULLUP;
+extern int AGC_ENCODER_A;
+extern int AGC_ENCODER_B;
+extern int ENABLE_BAND_BUTTON;
+extern int BAND_BUTTON;
+extern int ENABLE_BANDSTACK_BUTTON;
+extern int BANDSTACK_BUTTON;
+extern int ENABLE_MODE_BUTTON;
+extern int MODE_BUTTON;
+extern int ENABLE_FILTER_BUTTON;
+extern int FILTER_BUTTON;
+extern int ENABLE_NOISE_BUTTON;
+extern int NOISE_BUTTON;
+extern int ENABLE_AGC_BUTTON;
+extern int AGC_BUTTON;
+extern int ENABLE_MOX_BUTTON;
+extern int MOX_BUTTON;
+extern int ENABLE_FUNCTION_BUTTON;
+extern int FUNCTION_BUTTON;
+
+extern int function;
+void gpio_restore_state();
+void gpio_save_state();
+int gpio_init();
+void gpio_close();
+int vfo_encoder_get_pos();
+int af_encoder_get_pos();
+int af_function_get_state();
+int rf_encoder_get_pos();
+int rf_function_get_state();
+int function_get_state();
+int band_get_state();
+int mode_get_state();
+int filter_get_state();
+int noise_get_state();
+int mox_get_state();
+
diff --git a/main.c b/main.c
index 814e9f50ea1c640b7af5b13aec2ac712770211aa..ab7183b63e561395423326438c785e2b083ded4c 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,3 +1,22 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
 #include <math.h>
 #include "main.h"
 #include "channel.h"
 #include "discovered.h"
+#include "gpio.h"
+#include "old_discovery.h"
 #include "new_discovery.h"
 #include "new_protocol.h"
 #include "wdsp.h"
 #include "vfo.h"
+#include "menu.h"
 #include "meter.h"
 #include "panadapter.h"
 #include "splash.h"
 #include "waterfall.h"
 #include "toolbar.h"
 #include "radio.h"
-
-#define VFO_HEIGHT (display_height/8)
-#define VFO_WIDTH ((display_width/4)*3)
-#define METER_HEIGHT (display_height/8)
-#define METER_WIDTH (display_width/4)
-#define PANADAPTER_HEIGHT (display_height/4)
-#define TOOLBAR_HEIGHT (display_height/4)
-#define WATERFALL_HEIGHT (display_height-(VFO_HEIGHT+PANADAPTER_HEIGHT+TOOLBAR_HEIGHT))
+#include "wdsp_init.h"
+#include "version.h"
+
+#define VFO_HEIGHT ((display_height/32)*4)
+#define VFO_WIDTH ((display_width/32)*16)
+#define MENU_HEIGHT VFO_HEIGHT
+#define MENU_WIDTH ((display_width/32)*3)
+#define METER_HEIGHT VFO_HEIGHT
+#define METER_WIDTH ((display_width/32)*13)
+#define PANADAPTER_HEIGHT ((display_height/32)*8)
+#define SLIDERS_HEIGHT ((display_height/32)*6)
+#define TOOLBAR_HEIGHT ((display_height/32)*2)
+#define WATERFALL_HEIGHT (display_height-(VFO_HEIGHT+PANADAPTER_HEIGHT+SLIDERS_HEIGHT+TOOLBAR_HEIGHT))
 
 struct utsname unameData;
 
@@ -46,74 +73,130 @@ static int start=0;
 
 static GtkWidget *discovery_dialog;
 
+static sem_t wisdom_sem;
+
+static GdkCursor *cursor_arrow;
+static GdkCursor *cursor_watch;
+
 gint update(gpointer data) {
     int result;
-    GetPixels(isTransmitting()==0?CHANNEL_RX0:CHANNEL_TX,samples,&result);
+    double fwd;
+    double rev;
+    double exciter;
+
+    GetPixels(isTransmitting()==0?CHANNEL_RX0:CHANNEL_TX,0,samples,&result);
     if(result==1) {
-        panadapter_update(samples,isTransmitting());
+        if(display_panadapter) {
+          panadapter_update(samples,isTransmitting());
+        }
         if(!isTransmitting()) {
-            waterfall_update(samples);
+            if(display_waterfall) {
+              waterfall_update(samples);
+            }
         }
     }
 
     if(!isTransmitting()) {
         float m=GetRXAMeter(CHANNEL_RX0, 1/*WDSP.S_AV*/);
-        meter_update(SMETER,(double)m,0.0);
+        meter_update(SMETER,(double)m,0.0,0.0);
     } else {
 
         DISCOVERED *d=&discovered[selected_device];
 
-        double constant1=5.0;
-        double constant2=0.108;
-
-        switch(d->device) {
-            case NEW_DEVICE_ATLAS:
-                constant1=3.3;
-                constant2=0.09;
-                break;
-            case NEW_DEVICE_HERMES:
-                constant1=3.3;
-                constant2=0.09;
-                break;
-            case NEW_DEVICE_HERMES2:
-                constant1=3.3;
-                constant2=0.095;
-                break;
-            case NEW_DEVICE_ANGELIA:
-                constant1=3.3;
-                constant2=0.095;
-                break;
-            case NEW_DEVICE_ORION:
-                constant1=5.0;
-                constant2=0.108;
-                break;
-            case NEW_DEVICE_ANAN_10E:
-                constant1=3.3;
-                constant2=0.09;
-                break;
-            case NEW_DEVICE_HERMES_LITE:
-                constant1=3.3;
-                constant2=0.09;
-                break;
-        }
+        double constant1=3.3;
+        double constant2=0.09;
+
+        if(d->protocol==ORIGINAL_PROTOCOL) {
+            switch(d->device) {
+                case DEVICE_METIS:
+                    break;
+                case DEVICE_HERMES:
+                    //constant2=0.095; HERMES 2
+                    break;
+                case DEVICE_ANGELIA:
+                    break;
+                case DEVICE_ORION:
+                    constant1=5.0;
+                    constant2=0.108;
+                    break;
+                case DEVICE_HERMES_LITE:
+                    break;
+            }
+
+            int power=alex_forward_power;
+            if(power==0) {
+                power=exciter_power;
+            }
+            double v1;
+            v1=((double)power/4095.0)*constant1;
+            fwd=(v1*v1)/constant2;
+
+            power=exciter_power;
+            v1=((double)power/4095.0)*constant1;
+            exciter=(v1*v1)/constant2;
+
+            rev=0.0;
+            if(alex_forward_power!=0) {
+                power=alex_reverse_power;
+                v1=((double)power/4095.0)*constant1;
+                rev=(v1*v1)/constant2;
+            }
+         
+        } else {
+            switch(d->device) {
+                case NEW_DEVICE_ATLAS:
+                    constant1=3.3;
+                    constant2=0.09;
+                    break;
+                case NEW_DEVICE_HERMES:
+                    constant1=3.3;
+                    constant2=0.09;
+                    break;
+                case NEW_DEVICE_HERMES2:
+                    constant1=3.3;
+                    constant2=0.095;
+                    break;
+                case NEW_DEVICE_ANGELIA:
+                    constant1=3.3;
+                    constant2=0.095;
+                    break;
+                case NEW_DEVICE_ORION:
+                    constant1=5.0;
+                    constant2=0.108;
+                    break;
+                case NEW_DEVICE_ANAN_10E:
+                    constant1=3.3;
+                    constant2=0.09;
+                    break;
+                case NEW_DEVICE_HERMES_LITE:
+                    constant1=3.3;
+                    constant2=0.09;
+                    break;
+            }
         
-        int power=alex_forward_power;
-        if(power==0) {
+            int power=alex_forward_power;
+            if(power==0) {
+                power=exciter_power;
+            }
+            double v1;
+            v1=((double)power/4095.0)*constant1;
+            fwd=(v1*v1)/constant2;
+
             power=exciter_power;
-        }
-        double v1;
-        double fwd;
-        double rev;
-        v1=((double)power/4095.0)*constant1;
-        fwd=(v1*v1)/constant2;
-
-        rev=0.0;
-        if(alex_forward_power!=0) {
-            power=alex_reverse_power;
             v1=((double)power/4095.0)*constant1;
-            rev=(v1*v1)/constant2;
+            exciter=(v1*v1)/constant2;
+
+            rev=0.0;
+            if(alex_forward_power!=0) {
+                power=alex_reverse_power;
+                v1=((double)power/4095.0)*constant1;
+                rev=(v1*v1)/constant2;
+            }
         }
-        meter_update(POWER,fwd,rev);
+
+//fprintf(stderr,"drive=%d tune_drive=%d alex_forward_power=%d alex_reverse_power=%d exciter_power=%d fwd=%f rev=%f exciter=%f\n",
+//               drive, tune_drive, alex_forward_power, alex_reverse_power, exciter_power, fwd, rev, exciter);
+        meter_update(POWER,fwd,rev,exciter);
     }
 
     return TRUE;
@@ -121,7 +204,6 @@ gint update(gpointer data) {
 
 static gint save_cb(gpointer data) {
     radioSaveState();
-    saveProperties(property_path);
     return TRUE;
 }
 
@@ -132,39 +214,480 @@ fprintf(stderr,"start_cb\n");
     gtk_widget_destroy(discovery_dialog);
 }
 
+static void sample_rate_cb(GtkWidget *widget, gpointer data) {
+  sample_rate=(int)data;
+}
+
+static void display_panadapter_cb(GtkWidget *widget, gpointer data) {
+  display_panadapter=display_panadapter==1?0:1;
+}
+
+static void display_waterfall_cb(GtkWidget *widget, gpointer data) {
+  display_waterfall=display_waterfall==1?0:1;
+}
+
+static void display_sliders_cb(GtkWidget *widget, gpointer data) {
+  display_sliders=display_sliders==1?0:1;
+}
+
+static void display_toolbar_cb(GtkWidget *widget, gpointer data) {
+  display_toolbar=display_toolbar==1?0:1;
+}
+
+static void configure_gpio() {
+  gpio_restore_state();
+
+  GtkWidget *dialog=gtk_dialog_new_with_buttons("Configure GPIO",GTK_WINDOW(splash_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+  GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+  GtkWidget *grid=gtk_grid_new();
+  gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+  gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
+
+
+  GtkWidget *b_enable_vfo_encoder=gtk_check_button_new_with_label("Enable VFO");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_vfo_encoder), ENABLE_VFO_ENCODER);
+  gtk_widget_show(b_enable_vfo_encoder);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_vfo_encoder,0,0,1,1);
+
+  GtkWidget *vfo_a_label=gtk_label_new("GPIO A:");
+  gtk_widget_show(vfo_a_label);
+  gtk_grid_attach(GTK_GRID(grid),vfo_a_label,1,0,1,1);
+
+  GtkWidget *vfo_a=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(vfo_a),VFO_ENCODER_A);
+  gtk_widget_show(vfo_a);
+  gtk_grid_attach(GTK_GRID(grid),vfo_a,2,0,1,1);
+
+  GtkWidget *vfo_b_label=gtk_label_new("GPIO B:");
+  gtk_widget_show(vfo_b_label);
+  gtk_grid_attach(GTK_GRID(grid),vfo_b_label,3,0,1,1);
+
+  GtkWidget *vfo_b=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(vfo_b),VFO_ENCODER_B);
+  gtk_widget_show(vfo_b);
+  gtk_grid_attach(GTK_GRID(grid),vfo_b,4,0,1,1);
+
+  GtkWidget *b_enable_vfo_pullup=gtk_check_button_new_with_label("Enable Pull-up");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_vfo_pullup), ENABLE_VFO_PULLUP);
+  gtk_widget_show(b_enable_vfo_pullup);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_vfo_pullup,5,0,1,1);
+
+
+
+  GtkWidget *b_enable_af_encoder=gtk_check_button_new_with_label("Enable AF");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_af_encoder), ENABLE_AF_ENCODER);
+  gtk_widget_show(b_enable_af_encoder);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_af_encoder,0,1,1,1);
+
+  GtkWidget *af_a_label=gtk_label_new("GPIO A:");
+  gtk_widget_show(af_a_label);
+  gtk_grid_attach(GTK_GRID(grid),af_a_label,1,1,1,1);
+
+  GtkWidget *af_a=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(af_a),AF_ENCODER_A);
+  gtk_widget_show(af_a);
+  gtk_grid_attach(GTK_GRID(grid),af_a,2,1,1,1);
+
+  GtkWidget *af_b_label=gtk_label_new("GPIO B:");
+  gtk_widget_show(af_b_label);
+  gtk_grid_attach(GTK_GRID(grid),af_b_label,3,1,1,1);
+
+  GtkWidget *af_b=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(af_b),AF_ENCODER_B);
+  gtk_widget_show(af_b);
+  gtk_grid_attach(GTK_GRID(grid),af_b,4,1,1,1);
+
+  GtkWidget *b_enable_af_pullup=gtk_check_button_new_with_label("Enable Pull-up");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_af_pullup), ENABLE_AF_PULLUP);
+  gtk_widget_show(b_enable_af_pullup);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_af_pullup,5,1,1,1);
+
+
+
+  GtkWidget *b_enable_rf_encoder=gtk_check_button_new_with_label("Enable RF");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_rf_encoder), ENABLE_RF_ENCODER);
+  gtk_widget_show(b_enable_rf_encoder);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_rf_encoder,0,2,1,1);
+
+  GtkWidget *rf_a_label=gtk_label_new("GPIO A:");
+  gtk_widget_show(rf_a_label);
+  gtk_grid_attach(GTK_GRID(grid),rf_a_label,1,2,1,1);
+
+  GtkWidget *rf_a=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(rf_a),RF_ENCODER_A);
+  gtk_widget_show(rf_a);
+  gtk_grid_attach(GTK_GRID(grid),rf_a,2,2,1,1);
+
+  GtkWidget *rf_b_label=gtk_label_new("GPIO B:");
+  gtk_widget_show(rf_b_label);
+  gtk_grid_attach(GTK_GRID(grid),rf_b_label,3,2,1,1);
+
+  GtkWidget *rf_b=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(rf_b),RF_ENCODER_B);
+  gtk_widget_show(rf_b);
+  gtk_grid_attach(GTK_GRID(grid),rf_b,4,2,1,1);
+
+  GtkWidget *b_enable_rf_pullup=gtk_check_button_new_with_label("Enable Pull-up");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_rf_pullup), ENABLE_RF_PULLUP);
+  gtk_widget_show(b_enable_rf_pullup);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_rf_pullup,5,2,1,1);
+
+
+
+  GtkWidget *b_enable_agc_encoder=gtk_check_button_new_with_label("Enable AGC");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_agc_encoder), ENABLE_AGC_ENCODER);
+  gtk_widget_show(b_enable_agc_encoder);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_agc_encoder,0,3,1,1);
+
+  GtkWidget *agc_a_label=gtk_label_new("GPIO A:");
+  gtk_widget_show(agc_a_label);
+  gtk_grid_attach(GTK_GRID(grid),agc_a_label,1,3,1,1);
+
+  GtkWidget *agc_a=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(agc_a),AGC_ENCODER_A);
+  gtk_widget_show(agc_a);
+  gtk_grid_attach(GTK_GRID(grid),agc_a,2,3,1,1);
+
+  GtkWidget *agc_b_label=gtk_label_new("GPIO B:");
+  gtk_widget_show(agc_b_label);
+  gtk_grid_attach(GTK_GRID(grid),agc_b_label,3,3,1,1);
+
+  GtkWidget *agc_b=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(agc_b),AGC_ENCODER_B);
+  gtk_widget_show(agc_b);
+  gtk_grid_attach(GTK_GRID(grid),agc_b,4,3,1,1);
+
+  GtkWidget *b_enable_agc_pullup=gtk_check_button_new_with_label("Enable Pull-up");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_agc_pullup), ENABLE_AGC_PULLUP);
+  gtk_widget_show(b_enable_agc_pullup);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_agc_pullup,5,3,1,1);
+
+
+
+  GtkWidget *b_enable_band=gtk_check_button_new_with_label("Enable Band");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_band), ENABLE_BAND_BUTTON);
+  gtk_widget_show(b_enable_band);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_band,0,4,1,1);
+
+  GtkWidget *band_label=gtk_label_new("GPIO:");
+  gtk_widget_show(band_label);
+  gtk_grid_attach(GTK_GRID(grid),band_label,1,4,1,1);
+
+  GtkWidget *band=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(band),BAND_BUTTON);
+  gtk_widget_show(band);
+  gtk_grid_attach(GTK_GRID(grid),band,2,4,1,1);
+
+
+  GtkWidget *b_enable_mode=gtk_check_button_new_with_label("Enable Mode");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_mode), ENABLE_MODE_BUTTON);
+  gtk_widget_show(b_enable_mode);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_mode,0,5,1,1);
+
+  GtkWidget *mode_label=gtk_label_new("GPIO:");
+  gtk_widget_show(mode_label);
+  gtk_grid_attach(GTK_GRID(grid),mode_label,1,5,1,1);
+
+  GtkWidget *mode=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(mode),MODE_BUTTON);
+  gtk_widget_show(mode);
+  gtk_grid_attach(GTK_GRID(grid),mode,2,5,1,1);
+
+
+  GtkWidget *b_enable_filter=gtk_check_button_new_with_label("Enable Filter");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_filter), ENABLE_FILTER_BUTTON);
+  gtk_widget_show(b_enable_filter);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_filter,0,6,1,1);
+
+  GtkWidget *filter_label=gtk_label_new("GPIO:");
+  gtk_widget_show(filter_label);
+  gtk_grid_attach(GTK_GRID(grid),filter_label,1,6,1,1);
+
+  GtkWidget *filter=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(filter),FILTER_BUTTON);
+  gtk_widget_show(filter);
+  gtk_grid_attach(GTK_GRID(grid),filter,2,6,1,1);
+
+
+  GtkWidget *b_enable_noise=gtk_check_button_new_with_label("Enable Noise");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_noise), ENABLE_NOISE_BUTTON);
+  gtk_widget_show(b_enable_noise);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_noise,0,7,1,1);
+
+  GtkWidget *noise_label=gtk_label_new("GPIO:");
+  gtk_widget_show(noise_label);
+  gtk_grid_attach(GTK_GRID(grid),noise_label,1,7,1,1);
+
+  GtkWidget *noise=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(noise),NOISE_BUTTON);
+  gtk_widget_show(noise);
+  gtk_grid_attach(GTK_GRID(grid),noise,2,7,1,1);
+
+
+  GtkWidget *b_enable_agc=gtk_check_button_new_with_label("Enable AGC");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_agc), ENABLE_AGC_BUTTON);
+  gtk_widget_show(b_enable_agc);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_agc,0,8,1,1);
+
+  GtkWidget *agc_label=gtk_label_new("GPIO:");
+  gtk_widget_show(agc_label);
+  gtk_grid_attach(GTK_GRID(grid),agc_label,1,8,1,1);
+
+  GtkWidget *agc=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(agc),AGC_BUTTON);
+  gtk_widget_show(agc);
+  gtk_grid_attach(GTK_GRID(grid),agc,2,8,1,1);
+
+
+  GtkWidget *b_enable_mox=gtk_check_button_new_with_label("Enable MOX");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_mox), ENABLE_MOX_BUTTON);
+  gtk_widget_show(b_enable_mox);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_mox,0,9,1,1);
+
+  GtkWidget *mox_label=gtk_label_new("GPIO:");
+  gtk_widget_show(mox_label);
+  gtk_grid_attach(GTK_GRID(grid),mox_label,1,9,1,1);
+
+  GtkWidget *mox=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(mox),MOX_BUTTON);
+  gtk_widget_show(mox);
+  gtk_grid_attach(GTK_GRID(grid),mox,2,9,1,1);
+
+
+  GtkWidget *b_enable_function=gtk_check_button_new_with_label("Enable Function");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_function), ENABLE_FUNCTION_BUTTON);
+  gtk_widget_show(b_enable_function);
+  gtk_grid_attach(GTK_GRID(grid),b_enable_function,0,10,1,1);
+
+  GtkWidget *function_label=gtk_label_new("GPIO:");
+  gtk_widget_show(function_label);
+  gtk_grid_attach(GTK_GRID(grid),function_label,1,10,1,1);
+
+  GtkWidget *function=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(function),FUNCTION_BUTTON);
+  gtk_widget_show(function);
+  gtk_grid_attach(GTK_GRID(grid),function,2,10,1,1);
+
+
+
+  gtk_container_add(GTK_CONTAINER(content),grid);
+
+  gtk_container_add(GTK_CONTAINER(content),grid);
+
+  GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
+  //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 20"));
+  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));
+
+  ENABLE_VFO_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_vfo_encoder))?1:0;
+  VFO_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(vfo_a));
+  VFO_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(vfo_b));
+  ENABLE_AF_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_af_encoder))?1:0;
+  AF_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(af_a));
+  AF_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(af_b));
+  ENABLE_RF_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_rf_encoder))?1:0;
+  RF_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(rf_a));
+  RF_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(rf_b));
+  ENABLE_AGC_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_agc_encoder))?1:0;
+  AGC_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(agc_a));
+  AGC_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(agc_b));
+  ENABLE_BAND_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_band))?1:0;
+  BAND_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(band));
+  ENABLE_MODE_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_mode))?1:0;
+  MODE_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(mode));
+  ENABLE_FILTER_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_filter))?1:0;
+  FILTER_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(filter));
+  ENABLE_NOISE_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_noise))?1:0;
+  NOISE_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(noise));
+  ENABLE_AGC_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_agc))?1:0;
+  AGC_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(agc));
+  ENABLE_MOX_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_mox))?1:0;
+  MOX_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(mox));
+  ENABLE_FUNCTION_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_function))?1:0;
+  FUNCTION_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(function));
+
+  gtk_widget_destroy(dialog);
+
+  gpio_save_state();
+}
+
 static void configure_cb(GtkWidget *widget, gpointer data) {
+  DISCOVERED* d;
+  d=&discovered[(int)data];
+  sprintf(property_path,"%02X-%02X-%02X-%02X-%02X-%02X.props",
+                        d->mac_address[0],
+                        d->mac_address[1],
+                        d->mac_address[2],
+                        d->mac_address[3],
+                        d->mac_address[4],
+                        d->mac_address[5]);
+  radioRestoreState();
+  
+  GtkWidget *dialog=gtk_dialog_new_with_buttons("Configure",GTK_WINDOW(splash_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),FALSE);
+  gtk_grid_set_row_homogeneous(GTK_GRID(grid),FALSE);
+
+  GtkWidget *sample_rate_label=gtk_label_new("Sample Rate:");
+  //gtk_widget_override_font(sample_rate_label, pango_font_description_from_string("Arial 18"));
+  gtk_widget_show(sample_rate_label);
+  gtk_grid_attach(GTK_GRID(grid),sample_rate_label,0,0,1,1);
+
+  GtkWidget *sample_rate_48=gtk_radio_button_new_with_label(NULL,"48000");
+  //gtk_widget_override_font(sample_rate_48, pango_font_description_from_string("Arial 18"));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_48), sample_rate==48000);
+  gtk_widget_show(sample_rate_48);
+  gtk_grid_attach(GTK_GRID(grid),sample_rate_48,0,1,1,1);
+  g_signal_connect(sample_rate_48,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)48000);
+
+  GtkWidget *sample_rate_96=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_48),"96000");
+  //gtk_widget_override_font(sample_rate_96, pango_font_description_from_string("Arial 18"));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_96), sample_rate==96000);
+  gtk_widget_show(sample_rate_96);
+  gtk_grid_attach(GTK_GRID(grid),sample_rate_96,0,2,1,1);
+  g_signal_connect(sample_rate_96,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)96000);
+
+  GtkWidget *sample_rate_192=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_96),"192000");
+  //gtk_widget_override_font(sample_rate_192, pango_font_description_from_string("Arial 18"));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_192), sample_rate==192000);
+  gtk_widget_show(sample_rate_192);
+  gtk_grid_attach(GTK_GRID(grid),sample_rate_192,0,3,1,1);
+  g_signal_connect(sample_rate_192,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)192000);
+
+  GtkWidget *sample_rate_384=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_192),"384000");
+  //gtk_widget_override_font(sample_rate_384, pango_font_description_from_string("Arial 18"));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_384), sample_rate==384000);
+  gtk_widget_show(sample_rate_384);
+  gtk_grid_attach(GTK_GRID(grid),sample_rate_384,0,4,1,1);
+  g_signal_connect(sample_rate_384,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)384000);
+
+
+  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,5,1,1);
+
+  GtkWidget *b_display_panadapter=gtk_check_button_new_with_label("Display Panadapter");
+  //gtk_widget_override_font(b_display_panadapter, pango_font_description_from_string("Arial 18"));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_display_panadapter), display_panadapter);
+  gtk_widget_show(b_display_panadapter);
+  gtk_grid_attach(GTK_GRID(grid),b_display_panadapter,0,6,1,1);
+  g_signal_connect(b_display_panadapter,"toggled",G_CALLBACK(display_panadapter_cb),(gpointer *)NULL);
+
+  GtkWidget *b_display_waterfall=gtk_check_button_new_with_label("Display Waterfall");
+  //gtk_widget_override_font(b_display_waterfall, pango_font_description_from_string("Arial 18"));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_display_waterfall), display_waterfall);
+  gtk_widget_show(b_display_waterfall);
+  gtk_grid_attach(GTK_GRID(grid),b_display_waterfall,0,7,1,1);
+  g_signal_connect(b_display_waterfall,"toggled",G_CALLBACK(display_waterfall_cb),(gpointer *)NULL);
+
+  GtkWidget *b_display_sliders=gtk_check_button_new_with_label("Display Sliders");
+  //gtk_widget_override_font(b_display_sliders, pango_font_description_from_string("Arial 18"));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_display_sliders), display_sliders);
+  gtk_widget_show(b_display_sliders);
+  gtk_grid_attach(GTK_GRID(grid),b_display_sliders,0,8,1,1);
+  g_signal_connect(b_display_sliders,"toggled",G_CALLBACK(display_sliders_cb),(gpointer *)NULL);
+
+  GtkWidget *b_display_toolbar=gtk_check_button_new_with_label("Display Toolbar");
+  //gtk_widget_override_font(b_display_toolbar, pango_font_description_from_string("Arial 18"));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_display_toolbar), display_toolbar);
+  gtk_widget_show(b_display_toolbar);
+  gtk_grid_attach(GTK_GRID(grid),b_display_toolbar,0,9,1,1);
+  g_signal_connect(b_display_toolbar,"toggled",G_CALLBACK(display_toolbar_cb),(gpointer *)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 20"));
+  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));
+
+  radioSaveState();
+
 }
 
+static pthread_t wisdom_thread_id;
+
+static void* wisdom_thread(void *arg) {
+  splash_status("Creating FFTW Wisdom file ...");
+  WDSPwisdom ((char *)arg);
+  sem_post(&wisdom_sem);
+}
 
 gint init(void* arg) {
 
   GtkWidget *window;
   GtkWidget *grid;
+  GtkWidget *fixed;
+  gint x;
+  gint y;
   GtkWidget *vfo;
+  GtkWidget *menu;
   GtkWidget *meter;
   GtkWidget *panadapter;
   GtkWidget *waterfall;
+  GtkWidget *sliders;
   GtkWidget *toolbar;
 
   DISCOVERED* d;
 
+  char *res;
   char wisdom_directory[1024];
   char wisdom_file[1024];
 
   fprintf(stderr,"init\n");
 
+  cursor_arrow=gdk_cursor_new(GDK_ARROW);
+  cursor_watch=gdk_cursor_new(GDK_WATCH);
+
+  GdkWindow *gdk_splash_window = gtk_widget_get_window(splash_window);
+  gdk_window_set_cursor(gdk_splash_window,cursor_watch);
+
+  init_radio();
+
   // check if wisdom file exists
-  getcwd(wisdom_directory, sizeof(wisdom_directory));
+  res=getcwd(wisdom_directory, sizeof(wisdom_directory));
   strcpy(&wisdom_directory[strlen(wisdom_directory)],"/");
   strcpy(wisdom_file,wisdom_directory);
   strcpy(&wisdom_file[strlen(wisdom_file)],"wdspWisdom");
+  splash_status("Checking FFTW Wisdom file ...");
   if(access(wisdom_file,F_OK)<0) {
-      WDSPwisdom (wisdom_directory);
+      int rc=sem_init(&wisdom_sem, 0, 0);
+      rc=pthread_create(&wisdom_thread_id, NULL, wisdom_thread, (void *)wisdom_directory);
+      while(sem_trywait(&wisdom_sem)<0) {
+        splash_status(wisdom_get_status());
+        while (gtk_events_pending ())
+          gtk_main_iteration ();
+        usleep(100000); // 100ms
+      }
   }
 
   while(!start) {
+      gdk_window_set_cursor(gdk_splash_window,cursor_watch);
+      selected_device=0;
+      devices=0;
+      splash_status("Old Protocol ... Discovering Devices");
+      old_discovery();
+      splash_status("New Protocol ... Discovering Devices");
       new_discovery();
+      splash_status("Discovery");
       if(devices==0) {
+          gdk_window_set_cursor(gdk_splash_window,cursor_arrow);
           fprintf(stderr,"No devices found!\n");
           GtkDialogFlags flags = GTK_DIALOG_DESTROY_WITH_PARENT;
           discovery_dialog = gtk_message_dialog_new (GTK_WINDOW(splash_window),
@@ -172,27 +695,30 @@ gint init(void* arg) {
                                  GTK_MESSAGE_ERROR,
                                  GTK_BUTTONS_OK_CANCEL,
                                  "No devices found! Retry Discovery?");
+          gtk_widget_override_font(discovery_dialog, pango_font_description_from_string("Arial 18"));
           gint result=gtk_dialog_run (GTK_DIALOG (discovery_dialog));
+          gtk_widget_destroy(discovery_dialog);
           if(result==GTK_RESPONSE_CANCEL) {
                _exit(0);
           }
-      } else if(devices==1) {
-          selected_device=0;
-          start=1;
       } else {
           fprintf(stderr,"%s: found %d devices.\n", (char *)arg, devices);
+          gdk_window_set_cursor(gdk_splash_window,cursor_arrow);
           GtkDialogFlags flags=GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT;
           discovery_dialog = gtk_dialog_new_with_buttons ("Discovered",
                                       GTK_WINDOW(splash_window),
                                       flags,
+                                      "Configure GPIO",
+                                      GTK_RESPONSE_YES,
                                       "Discover",
                                       GTK_RESPONSE_REJECT,
+                                      "Exit",
+                                      GTK_RESPONSE_CLOSE,
                                       NULL);
 
+          gtk_widget_override_font(discovery_dialog, pango_font_description_from_string("Arial 18"));
           GtkWidget *content;
 
-//          g_signal_connect_swapped(discovery_dialog,"response",G_CALLBACK(gtk_widget_destroy),discovery_dialog);
-
           content=gtk_dialog_get_content_area(GTK_DIALOG(discovery_dialog));
 
           GtkWidget *grid=gtk_grid_new();
@@ -203,8 +729,11 @@ gint init(void* arg) {
           char text[128];
           for(i=0;i<devices;i++) {
               d=&discovered[i];
-              sprintf(text,"%s %s (%02X:%02X:%02X:%02X:%02X:%02X) on interface %s\n",
+              sprintf(text,"%s (%s %d.%d) %s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n",
                         d->name,
+                        d->protocol==ORIGINAL_PROTOCOL?"old":"new",
+                        d->protocol==ORIGINAL_PROTOCOL?d->software_version/10:d->software_version/100,
+                        d->protocol==ORIGINAL_PROTOCOL?d->software_version%10:d->software_version%100,
                         inet_ntoa(d->address.sin_addr),
                         d->mac_address[0],
                         d->mac_address[1],
@@ -215,27 +744,46 @@ gint init(void* arg) {
                         d->interface_name);
 
               GtkWidget *label=gtk_label_new(text);
+              gtk_widget_override_font(label, pango_font_description_from_string("Arial 12"));
               gtk_widget_show(label);
-              gtk_grid_attach(GTK_GRID(grid),label,0,i,3,1);
+              gtk_grid_attach(GTK_GRID(grid),label,0,i,4,1);
 
               GtkWidget *start_button=gtk_button_new_with_label("Start");
+              gtk_widget_override_font(start_button, pango_font_description_from_string("Arial 18"));
               gtk_widget_show(start_button);
-              gtk_grid_attach(GTK_GRID(grid),start_button,3,i,1,1);
+              gtk_grid_attach(GTK_GRID(grid),start_button,4,i,1,1);
               g_signal_connect(start_button,"pressed",G_CALLBACK(start_cb),(gpointer *)i);
 
               GtkWidget *configure_button=gtk_button_new_with_label("Configure");
+              gtk_widget_override_font(configure_button, pango_font_description_from_string("Arial 18"));
               gtk_widget_show(configure_button);
-              gtk_grid_attach(GTK_GRID(grid),configure_button,4,i,1,1);
+              gtk_grid_attach(GTK_GRID(grid),configure_button,5,i,1,1);
               g_signal_connect(configure_button,"pressed",G_CALLBACK(configure_cb),(gpointer *)i);
           }
 
           gtk_container_add (GTK_CONTAINER (content), grid);
           gtk_widget_show_all(discovery_dialog);
           gint result=gtk_dialog_run(GTK_DIALOG(discovery_dialog));
+
+          if(result==GTK_RESPONSE_CLOSE) {
+              _exit(0);
+          }
+         
+          if(result==GTK_RESPONSE_YES) {
+              gtk_widget_destroy(discovery_dialog);
+              configure_gpio();
+          }
       }
   }
 
+  gdk_window_set_cursor(gdk_splash_window,cursor_watch);
+
+  splash_status("Initializing wdsp ...");
+
   d=&discovered[selected_device];
+  protocol=d->protocol;
+  device=d->device;
+
   sprintf(property_path,"%02X-%02X-%02X-%02X-%02X-%02X.props",
                         d->mac_address[0],
                         d->mac_address[1],
@@ -244,39 +792,128 @@ gint init(void* arg) {
                         d->mac_address[4],
                         d->mac_address[5]);
 
-  loadProperties(property_path);
   radioRestoreState();
 
   samples=malloc(display_width*sizeof(float));
 
-  //selected_device=0;
-  setSampleRate(48000);
-  new_protocol_init(0,display_width);
+  //splash_status("Initializing wdsp ...");
+  wdsp_init(0,display_width,d->protocol);
 
-  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-  gtk_window_set_title (GTK_WINDOW (window), "pihpsdr");
+  if(d->protocol==ORIGINAL_PROTOCOL) {
+      splash_status("Initializing old protocol ...");
+      old_protocol_init(0,display_width);
+  } else {
+      splash_status("Initializing new protocol ...");
+      new_protocol_init(0,display_width);
+  }
 
-  //g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
+  splash_status("Initializing GPIO ...");
+  gpio_init();
 
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_title (GTK_WINDOW (window), "pihpsdr");
   gtk_container_set_border_width (GTK_CONTAINER (window), 0);
 
+#ifdef GRID_LAYOUT
   grid = gtk_grid_new();
+  gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
+  gtk_grid_set_row_homogeneous(GTK_GRID(grid),FALSE);
   gtk_container_add(GTK_CONTAINER(window), grid);
+#else
+  fixed=gtk_fixed_new();
+  gtk_container_add(GTK_CONTAINER(window), fixed);
+  y=0;
+#endif
 
+fprintf(stderr,"vfo_height=%d\n",VFO_HEIGHT);
   vfo = vfo_init(VFO_WIDTH,VFO_HEIGHT,window);
-  gtk_grid_attach(GTK_GRID(grid), vfo, 0, 0, 3, 1);
-
+#ifdef GRID_LAYOUT
+  gtk_grid_attach(GTK_GRID(grid), vfo, 0, y, 16, 1);
+#else
+  gtk_fixed_put(GTK_FIXED(fixed),vfo,0,0);
+#endif
+
+
+fprintf(stderr,"menu_height=%d\n",MENU_HEIGHT);
+  menu = menu_init(MENU_WIDTH,MENU_HEIGHT,window);
+#ifdef GRID_LAYOUT
+  gtk_grid_attach(GTK_GRID(grid), menu, 16, 0, 1, 1);
+#else
+  gtk_fixed_put(GTK_FIXED(fixed),menu,VFO_WIDTH,y);
+#endif
+
+fprintf(stderr,"meter_height=%d\n",METER_HEIGHT);
   meter = meter_init(METER_WIDTH,METER_HEIGHT);
-  gtk_grid_attach(GTK_GRID(grid), meter, 3, 0, 1, 1);
+#ifdef GRID_LAYOUT
+  gtk_grid_attach(GTK_GRID(grid), meter, 17, 0, 15, 1);
+#else
+  gtk_fixed_put(GTK_FIXED(fixed),meter,VFO_WIDTH+MENU_WIDTH,y);
+  y+=VFO_HEIGHT;
+#endif
+
+  if(display_panadapter) {
+    int height=PANADAPTER_HEIGHT;
+    if(!display_waterfall) {
+      height+=WATERFALL_HEIGHT;
+      if(!display_sliders) {
+        height+=SLIDERS_HEIGHT;
+      }
+      if(!display_toolbar) {
+        height+=TOOLBAR_HEIGHT;
+      }
+    }
+fprintf(stderr,"panadapter_height=%d\n",height);
+    panadapter = panadapter_init(display_width,height);
+#ifdef GRID_LAYOUT
+    gtk_grid_attach(GTK_GRID(grid), panadapter, 0, 1, 32, 1);
+#else
+    gtk_fixed_put(GTK_FIXED(fixed),panadapter,0,VFO_HEIGHT);
+    y+=height;
+#endif
+  }
 
-  panadapter = panadapter_init(display_width,PANADAPTER_HEIGHT);
-  gtk_grid_attach(GTK_GRID(grid), panadapter, 0, 1, 4, 1);
+  if(display_waterfall) {
+    int height=WATERFALL_HEIGHT;
+    if(!display_panadapter) {
+      height+=PANADAPTER_HEIGHT;
+    }
+    if(!display_sliders) {
+      height+=SLIDERS_HEIGHT;
+    }
+    if(!display_toolbar) {
+      height+=TOOLBAR_HEIGHT;
+    }
+fprintf(stderr,"waterfall_height=%d\n",height);
+    waterfall = waterfall_init(display_width,height);
+#ifdef GRID_LAYOUT
+    gtk_grid_attach(GTK_GRID(grid), waterfall, 0, 2, 32, 1);
+#else
+    gtk_fixed_put(GTK_FIXED(fixed),waterfall,0,y);
+    y+=height;
+#endif
+  }
 
-  waterfall = waterfall_init(display_width,WATERFALL_HEIGHT);
-  gtk_grid_attach(GTK_GRID(grid), waterfall, 0, 2, 4, 1);
+  if(display_sliders) {
+fprintf(stderr,"sliders_height=%d\n",SLIDERS_HEIGHT);
+    sliders = sliders_init(display_width,SLIDERS_HEIGHT,window);
+#ifdef GRID_LAYOUT
+    gtk_grid_attach(GTK_GRID(grid), sliders, 0, 3, 32, 1);
+#else
+    gtk_fixed_put(GTK_FIXED(fixed),sliders,0,y);
+    y+=SLIDERS_HEIGHT;
+#endif
+  }
 
-  toolbar = toolbar_init(display_width,TOOLBAR_HEIGHT,window);
-  gtk_grid_attach(GTK_GRID(grid), toolbar, 0, 3, 4, 1);
+  if(display_toolbar) {
+fprintf(stderr,"toolbar_height=%d\n",TOOLBAR_HEIGHT);
+    toolbar = toolbar_init(display_width,TOOLBAR_HEIGHT,window);
+#ifdef GRID_LAYOUT
+    gtk_grid_attach(GTK_GRID(grid), toolbar, 0, 4, 32, 1);
+#else
+    gtk_fixed_put(GTK_FIXED(fixed),toolbar,0,y);
+    y+=TOOLBAR_HEIGHT;
+#endif
+  }
 
   splash_close();
 
@@ -285,19 +922,8 @@ gint init(void* arg) {
 
   gtk_window_fullscreen(GTK_WINDOW(window));
 
-  GdkCursor *cursor=gdk_cursor_new(GDK_ARROW);
   GdkWindow *gdk_window = gtk_widget_get_window(window);
-  gdk_window_set_cursor(gdk_window,cursor);
-
-/*
-  GdkDisplay *display=gdk_display_get_default();
-  if(display==NULL) {
-    fprintf(stderr,"no default display!\n");
-    _exit(0);
-  }
-
-  GdkCursor *cursor=gdk_cursor_new_for_display(display,GDK_ARROW);
-*/
+  gdk_window_set_cursor(gdk_window,cursor_arrow);
 
   update_timer_id=gdk_threads_add_timeout(1000/updates_per_second, update, NULL);
 
@@ -306,6 +932,10 @@ gint init(void* arg) {
 
   vfo_update(NULL);
 
+  if(protocol==ORIGINAL_PROTOCOL) {
+    setFrequency(getFrequency());
+  }
+
   return 0;
 }
 
@@ -316,6 +946,8 @@ main (int   argc,
 {
   gtk_init (&argc, &argv);
 
+  fprintf(stderr,"Build: %s %s\n",build_date,build_time);
+
   uname(&unameData);
   fprintf(stderr,"sysname: %s\n",unameData.sysname);
   fprintf(stderr,"nodename: %s\n",unameData.nodename);
@@ -330,12 +962,12 @@ main (int   argc,
   }
 
 
-  //display_width=gdk_screen_get_width(screen);
-  //display_height=gdk_screen_get_height(screen);
-  display_width=800;
-  display_height=480;
+  display_width=gdk_screen_get_width(screen);
+  display_height=gdk_screen_get_height(screen);
+
+  fprintf(stderr,"display_width=%d display_height=%d\n", display_width, display_height);
 
-  splash_show("splash.png", 0, display_width, display_height);
+  splash_show("hpsdr.png", 0, display_width, display_height);
 
   g_idle_add(init,(void *)argv[0]);
 
diff --git a/main.h b/main.h
index 1e1d95556165bba6a338a1a9590d5a2fa1d6e697..dff008921bf44a9e44622c15546b0724183f4e7e 100644 (file)
--- a/main.h
+++ b/main.h
@@ -1,2 +1,21 @@
+/* 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 <sys/utsname.h>
 extern struct utsname unameData;
diff --git a/menu.c b/menu.c
new file mode 100644 (file)
index 0000000..317d867
--- /dev/null
+++ b/menu.c
@@ -0,0 +1,532 @@
+/* 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 "band.h"
+#include "discovered.h"
+#include "new_protocol.h"
+#include "radio.h"
+#include "version.h"
+
+static GtkWidget *parent_window;
+
+static GtkWidget *box;
+static GtkWidget *menu;
+
+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 linein_cb(GtkWidget *widget, gpointer data) {
+  mic_linein=mic_linein==1?0:1;
+}
+
+static void micboost_cb(GtkWidget *widget, gpointer data) {
+  mic_boost=mic_boost==1?0:1;
+}
+
+static void ptt_cb(GtkWidget *widget, gpointer data) {
+  mic_ptt_enabled=mic_ptt_enabled==1?0:1;
+}
+
+static void ptt_ring_cb(GtkWidget *widget, gpointer data) {
+  mic_ptt_tip_bias_ring=0;
+}
+
+static void ptt_tip_cb(GtkWidget *widget, gpointer data) {
+  mic_ptt_tip_bias_ring=1;
+}
+
+static void bias_cb(GtkWidget *widget, gpointer data) {
+  mic_bias_enabled=mic_bias_enabled==1?0:1;
+}
+
+static void apollo_cb(GtkWidget *widget, gpointer data);
+
+static void alex_cb(GtkWidget *widget, gpointer data) {
+  if(filter_board==ALEX) {
+    filter_board=NONE;
+  } else if(filter_board==NONE) {
+    filter_board=ALEX;
+  } else if(filter_board==APOLLO) {
+    GtkWidget *w=(GtkWidget *)data;
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), FALSE);
+    filter_board=ALEX;
+  }
+
+  if(protocol==NEW_PROTOCOL) {
+    filter_board_changed();
+  }
+}
+
+static void apollo_cb(GtkWidget *widget, gpointer data) {
+  if(filter_board==APOLLO) {
+    filter_board=NONE;
+  } else if(filter_board==NONE) {
+    filter_board=APOLLO;
+  } else if(filter_board==ALEX) {
+    GtkWidget *w=(GtkWidget *)data;
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), FALSE);
+    filter_board=APOLLO;
+  }
+  if(protocol==NEW_PROTOCOL) {
+    filter_board_changed();
+  }
+}
+
+static void apollo_tuner_cb(GtkWidget *widget, gpointer data) {
+  apollo_tuner=apollo_tuner==1?0:1;
+  if(protocol==NEW_PROTOCOL) {
+    tuner_changed();
+  }
+}
+
+static void pa_cb(GtkWidget *widget, gpointer data) {
+  pa=pa==1?0:1;
+  if(protocol==NEW_PROTOCOL) {
+    pa_changed();
+  }
+}
+
+
+static void tx_out_of_band_cb(GtkWidget *widget, gpointer data) {
+  tx_out_of_band=tx_out_of_band==1?0:1;
+}
+
+static void pa_value_changed_cb(GtkWidget *widget, gpointer data) {
+  BAND *band=(BAND *)data;
+  band->pa_calibration=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
+}
+
+static gboolean exit_pressed_event_cb (GtkWidget *widget,
+               GdkEventButton *event,
+               gpointer        data)
+{
+  gpio_close();
+  if(protocol==ORIGINAL_PROTOCOL) {
+    old_protocol_stop();
+  } else {
+    new_protocol_stop();
+  }
+  _exit(0);
+}
+
+static gboolean menu_pressed_event_cb (GtkWidget *widget,
+               GdkEventButton *event,
+               gpointer        data)
+{
+  int i;
+  int id;
+
+  GtkWidget *dialog=gtk_dialog_new_with_buttons("Menu",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+
+  GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+
+
+
+  GtkWidget *notebook=gtk_notebook_new();
+
+
+  GtkWidget *display_label=gtk_label_new("Display");
+  GtkWidget *display_grid=gtk_grid_new();
+  gtk_grid_set_row_homogeneous(GTK_GRID(display_grid),TRUE);
+
+  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(display_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(display_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(display_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(display_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(display_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(display_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(display_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(display_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(display_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(display_grid),waterfall_low_r,1,5,1,1);
+  g_signal_connect(waterfall_low_r,"value_changed",G_CALLBACK(waterfall_low_value_changed_cb),NULL);
+
+  id=gtk_notebook_append_page(GTK_NOTEBOOK(notebook),display_grid,display_label);
+
+
+
+  GtkWidget *tx_label=gtk_label_new("TX");
+  GtkWidget *tx_grid=gtk_grid_new();
+  gtk_grid_set_row_homogeneous(GTK_GRID(tx_grid),TRUE);
+  gtk_grid_set_column_spacing (GTK_GRID(tx_grid),10);
+
+  for(i=0;i<HAM_BANDS;i++) {
+    BAND *band=band_get_band(i);
+
+    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(tx_grid),band_label,(i/6)*2,i%6,1,1);
+
+    GtkWidget *pa_r=gtk_spin_button_new_with_range(0.0,100.0,1.0);
+    //gtk_widget_override_font(pa_r, pango_font_description_from_string("Arial 18"));
+    gtk_spin_button_set_value(GTK_SPIN_BUTTON(pa_r),(double)band->pa_calibration);
+    gtk_widget_show(pa_r);
+    gtk_grid_attach(GTK_GRID(tx_grid),pa_r,((i/6)*2)+1,i%6,1,1);
+    g_signal_connect(pa_r,"value_changed",G_CALLBACK(pa_value_changed_cb),band);
+  }
+
+  GtkWidget *tx_out_of_band_b=gtk_check_button_new_with_label("Transmit out of band");
+  //gtk_widget_override_font(tx_out_of_band_b, pango_font_description_from_string("Arial 18"));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tx_out_of_band_b), tx_out_of_band);
+  gtk_widget_show(tx_out_of_band_b);
+  gtk_grid_attach(GTK_GRID(tx_grid),tx_out_of_band_b,0,7,4,1);
+  g_signal_connect(tx_out_of_band_b,"toggled",G_CALLBACK(tx_out_of_band_cb),NULL);
+
+  id=gtk_notebook_append_page(GTK_NOTEBOOK(notebook),tx_grid,tx_label);
+
+  GtkWidget *cw_label=gtk_label_new("CW");
+  GtkWidget *cw_grid=gtk_grid_new();
+  gtk_grid_set_row_homogeneous(GTK_GRID(cw_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(cw_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(cw_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(cw_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(cw_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(cw_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(cw_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(cw_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);
+
+  id=gtk_notebook_append_page(GTK_NOTEBOOK(notebook),cw_grid,cw_label);
+
+
+  GtkWidget *encoder_label=gtk_label_new("VFO Encoder");
+  GtkWidget *encoder_grid=gtk_grid_new();
+  gtk_grid_set_row_homogeneous(GTK_GRID(encoder_grid),TRUE);
+
+  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(encoder_grid),vfo_divisor_label,0,0,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(encoder_grid),vfo_divisor,1,0,1,1);
+  g_signal_connect(vfo_divisor,"value_changed",G_CALLBACK(vfo_divisor_value_changed_cb),NULL);
+
+  id=gtk_notebook_append_page(GTK_NOTEBOOK(notebook),encoder_grid,encoder_label);
+
+  GtkWidget *microphone_label=gtk_label_new("Microphone");
+  GtkWidget *microphone_grid=gtk_grid_new();
+  gtk_grid_set_row_homogeneous(GTK_GRID(microphone_grid),TRUE);
+
+  GtkWidget *linein_b=gtk_check_button_new_with_label("Line In");
+  //gtk_widget_override_font(linein_b, pango_font_description_from_string("Arial 18"));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (linein_b), mic_linein);
+  gtk_widget_show(linein_b);
+  gtk_grid_attach(GTK_GRID(microphone_grid),linein_b,1,1,1,1);
+  g_signal_connect(linein_b,"toggled",G_CALLBACK(linein_cb),NULL);
+
+  GtkWidget *micboost_b=gtk_check_button_new_with_label("Boost");
+  //gtk_widget_override_font(micboost_b, pango_font_description_from_string("Arial 18"));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (micboost_b), mic_boost);
+  gtk_widget_show(micboost_b);
+  gtk_grid_attach(GTK_GRID(microphone_grid),micboost_b,1,2,1,1);
+  g_signal_connect(micboost_b,"toggled",G_CALLBACK(micboost_cb),NULL);
+
+
+  if((protocol==NEW_PROTOCOL && device==NEW_DEVICE_ORION) || (protocol==ORIGINAL_PROTOCOL && device==DEVICE_ORION)) {
+
+    GtkWidget *ptt_ring_b=gtk_radio_button_new_with_label(NULL,"PTT On Ring, Mic and Bias on Tip");
+    //gtk_widget_override_font(ptt_ring_b, pango_font_description_from_string("Arial 18"));
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptt_ring_b), mic_ptt_tip_bias_ring==0);
+    gtk_widget_show(ptt_ring_b);
+    gtk_grid_attach(GTK_GRID(microphone_grid),ptt_ring_b,1,3,1,1);
+    g_signal_connect(ptt_ring_b,"pressed",G_CALLBACK(ptt_ring_cb),NULL);
+
+    GtkWidget *ptt_tip_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ptt_ring_b),"PTT On Tip, Mic and Bias on Ring");
+    //gtk_widget_override_font(ptt_tip_b, pango_font_description_from_string("Arial 18"));
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptt_tip_b), mic_ptt_tip_bias_ring==1);
+    gtk_widget_show(ptt_tip_b);
+    gtk_grid_attach(GTK_GRID(microphone_grid),ptt_tip_b,1,4,1,1);
+    g_signal_connect(ptt_tip_b,"pressed",G_CALLBACK(ptt_tip_cb),NULL);
+
+    GtkWidget *ptt_b=gtk_check_button_new_with_label("PTT Enabled");
+    //gtk_widget_override_font(ptt_b, pango_font_description_from_string("Arial 18"));
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptt_b), mic_ptt_enabled);
+    gtk_widget_show(ptt_b);
+    gtk_grid_attach(GTK_GRID(microphone_grid),ptt_b,1,5,1,1);
+    g_signal_connect(ptt_b,"toggled",G_CALLBACK(ptt_cb),NULL);
+
+    GtkWidget *bias_b=gtk_check_button_new_with_label("BIAS Enabled");
+    //gtk_widget_override_font(bias_b, pango_font_description_from_string("Arial 18"));
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bias_b), mic_bias_enabled);
+    gtk_widget_show(bias_b);
+    gtk_grid_attach(GTK_GRID(microphone_grid),bias_b,1,6,1,1);
+    g_signal_connect(bias_b,"toggled",G_CALLBACK(bias_cb),NULL);
+  }
+
+  id=gtk_notebook_append_page(GTK_NOTEBOOK(notebook),microphone_grid,microphone_label);
+
+  GtkWidget *filters_label=gtk_label_new("Filters/PA");
+  GtkWidget *filters_grid=gtk_grid_new();
+  gtk_grid_set_row_homogeneous(GTK_GRID(filters_grid),TRUE);
+
+  GtkWidget *alex_b=gtk_check_button_new_with_label("ALEX");
+  //gtk_widget_override_font(alex_b, pango_font_description_from_string("Arial 18"));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (alex_b), filter_board==ALEX);
+  gtk_widget_show(alex_b);
+  gtk_grid_attach(GTK_GRID(filters_grid),alex_b,2,1,1,1);
+
+  GtkWidget *apollo_b=gtk_check_button_new_with_label("APOLLO");
+  //gtk_widget_override_font(apollo_b, pango_font_description_from_string("Arial 18"));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (apollo_b), filter_board==APOLLO);
+  gtk_widget_show(apollo_b);
+  gtk_grid_attach(GTK_GRID(filters_grid),apollo_b,2,2,1,1);
+
+  g_signal_connect(alex_b,"toggled",G_CALLBACK(alex_cb),apollo_b);
+  g_signal_connect(apollo_b,"toggled",G_CALLBACK(apollo_cb),alex_b);
+
+  GtkWidget *apollo_tuner_b=gtk_check_button_new_with_label("Auto Tuner");
+  //gtk_widget_override_font(apollo_tuner_b, pango_font_description_from_string("Arial 18"));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (apollo_tuner_b), apollo_tuner);
+  gtk_widget_show(apollo_tuner_b);
+  gtk_grid_attach(GTK_GRID(filters_grid),apollo_tuner_b,2,3,1,1);
+  g_signal_connect(apollo_tuner_b,"toggled",G_CALLBACK(apollo_tuner_cb),NULL);
+
+  GtkWidget *pa_b=gtk_check_button_new_with_label("PA");
+  //gtk_widget_override_font(pa_b, pango_font_description_from_string("Arial 18"));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pa_b), pa);
+  gtk_widget_show(pa_b);
+  gtk_grid_attach(GTK_GRID(filters_grid),pa_b,2,4,1,1);
+  g_signal_connect(pa_b,"toggled",G_CALLBACK(pa_cb),NULL);
+
+  id=gtk_notebook_append_page(GTK_NOTEBOOK(notebook),filters_grid,filters_label);
+
+
+  GtkWidget *exit_label=gtk_label_new("Exit");
+  GtkWidget *exit_grid=gtk_grid_new();
+  //gtk_grid_set_row_homogeneous(GTK_GRID(exit_grid),TRUE);
+
+  GtkWidget *exit_button=gtk_button_new_with_label("Exit PiHPSDR");
+  g_signal_connect (exit_button, "pressed", G_CALLBACK(exit_pressed_event_cb), NULL);
+  gtk_grid_attach(GTK_GRID(exit_grid),exit_button,0,0,1,1);
+
+  id=gtk_notebook_append_page(GTK_NOTEBOOK(notebook),exit_grid,exit_label);
+
+
+
+/*
+  GtkWidget *about_label=gtk_label_new("About");
+  GtkWidget *about_grid=gtk_grid_new();
+  gtk_grid_set_column_homogeneous(GTK_GRID(about_grid),TRUE);
+
+  char build[64];
+
+  sprintf(build,"build: %s %s",build_date, build_time);
+  GtkWidget *pi_label=gtk_label_new("pihpsdr by John Melton g0orx/n6lyt");
+  gtk_widget_show(pi_label);
+  gtk_grid_attach(GTK_GRID(about_grid),pi_label,0,0,1,1);
+  GtkWidget *filler_label=gtk_label_new("");
+  gtk_widget_show(filler_label);
+  gtk_grid_attach(GTK_GRID(about_grid),filler_label,0,1,1,1);
+  GtkWidget *build_date_label=gtk_label_new(build);
+  gtk_widget_show(build_date_label);
+  gtk_grid_attach(GTK_GRID(about_grid),build_date_label,0,2,1,1);
+   
+  id=gtk_notebook_append_page(GTK_NOTEBOOK(notebook),about_grid,about_label);
+*/
+  gtk_container_add(GTK_CONTAINER(content),notebook);
+
+  GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close Dialog",GTK_RESPONSE_OK);
+ // gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 18"));
+
+  gtk_widget_show_all(dialog);
+
+  int result=gtk_dialog_run(GTK_DIALOG(dialog));
+
+  radioSaveState();
+
+  gtk_widget_destroy (dialog);
+
+  return TRUE;
+
+}
+
+GtkWidget* menu_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,"menu_init: width=%d height=%d\n",width,height);
+
+  parent_window=parent;
+
+  box=gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0);
+  gtk_widget_set_size_request (box, width, height);
+  gtk_widget_override_background_color(box, GTK_STATE_NORMAL, &black);
+
+  menu=gtk_button_new_with_label("Menu");
+ // gtk_widget_set_size_request (menu, width, height);
+  g_signal_connect (menu, "pressed", G_CALLBACK(menu_pressed_event_cb), NULL);
+  gtk_box_pack_start (GTK_BOX(box),menu,TRUE,TRUE,0);
+
+  gtk_widget_show_all(box);
+
+  return box;
+}
diff --git a/menu.h b/menu.h
new file mode 100644 (file)
index 0000000..90f6b2d
--- /dev/null
+++ b/menu.h
@@ -0,0 +1,21 @@
+/* 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.
+*
+*/
+
+
+GtkWidget* menu_init(int width,int height,GtkWidget *parent);
diff --git a/meter.c b/meter.c
index 2d77107d4603381a38db721372cff50c8bd886ad..5c774bd0b22b2942169e1e94fde45c776fa4ff2c 100644 (file)
--- a/meter.c
+++ b/meter.c
@@ -1,3 +1,22 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
 #include <string.h>
@@ -11,6 +30,9 @@ static cairo_surface_t *meter_surface = NULL;
 
 static int meter_width;
 static int meter_height;
+static int last_meter_type=SMETER;
+static int max_level=-200;
+static int max_count=0;
 
 static void
 meter_clear_surface (void)
@@ -28,6 +50,9 @@ meter_configure_event_cb (GtkWidget         *widget,
             GdkEventConfigure *event,
             gpointer           data)
 {
+fprintf(stderr,"meter_configure_event_cb: width=%d height=%d\n",
+                                       gtk_widget_get_allocated_width (widget),
+                                       gtk_widget_get_allocated_height (widget));
   if (meter_surface)
     cairo_surface_destroy (meter_surface);
 
@@ -56,6 +81,7 @@ meter_draw_cb (GtkWidget *widget, cairo_t   *cr, gpointer   data) {
 
 GtkWidget* meter_init(int width,int height) {
 
+fprintf(stderr,"meter_init: width=%d height=%d\n",width,height);
   meter_width=width;
   meter_height=height;
 
@@ -73,10 +99,11 @@ GtkWidget* meter_init(int width,int height) {
 }
 
 
-void meter_update(int meter_type,double value,double reverse) {
+void meter_update(int meter_type,double value,double reverse,double exciter) {
   
   char sf[32];
   int text_location;
+  double offset;
   cairo_t *cr;
   cr = cairo_create (meter_surface);
 
@@ -84,62 +111,90 @@ void meter_update(int meter_type,double value,double reverse) {
   cairo_set_source_rgb (cr, 0, 0, 0);
   cairo_paint (cr);
 
+  if(last_meter_type!=meter_type) {
+    last_meter_type=meter_type;
+    max_count=0;
+    if(meter_type==SMETER) {
+      max_level=-200;
+    } else {
+      max_level=0;
+    }
+  }
+
   cairo_set_source_rgb(cr, 1, 1, 1);
   switch(meter_type) {
     case SMETER:
       // value is dBm
       text_location=10;
+      offset=5.0;
       cairo_select_font_face(cr, "Arial",
                     CAIRO_FONT_SLANT_NORMAL,
                     CAIRO_FONT_WEIGHT_BOLD);
       double level=value+(double)get_attenuation();
       if(meter_width>=114) {
         int db=meter_width/114; // S9+60 (9*6)+60
+        if(db>2) db=2;
         int i;
         cairo_set_line_width(cr, 1.0);
         cairo_set_source_rgb(cr, 1, 1, 1);
         for(i=0;i<54;i++) {
-          cairo_move_to(cr,(double)(i*db),(double)meter_height-20);
+          cairo_move_to(cr,offset+(double)(i*db),(double)meter_height-20);
           if(i%18==0) {
-            cairo_line_to(cr,(double)(i*db),(double)(meter_height-30));
+            cairo_line_to(cr,offset+(double)(i*db),(double)(meter_height-30));
           } else if(i%6==0) {
-            cairo_line_to(cr,(double)(i*db),(double)(meter_height-25));
+            cairo_line_to(cr,offset+(double)(i*db),(double)(meter_height-25));
           }
         }
         cairo_stroke(cr);
 
         cairo_set_font_size(cr, 12);
-        cairo_move_to(cr, (double)(18*db)-3.0, (double)meter_height);
+        cairo_move_to(cr, offset+(double)(18*db)-3.0, (double)meter_height);
         cairo_show_text(cr, "3");
-        cairo_move_to(cr, (double)(36*db)-3.0, (double)meter_height);
+        cairo_move_to(cr, offset+(double)(36*db)-3.0, (double)meter_height);
         cairo_show_text(cr, "6");
 
         cairo_set_source_rgb(cr, 1, 0, 0);
-        cairo_move_to(cr,(double)(54*db),(double)meter_height-20);
-        cairo_line_to(cr,(double)(54*db),(double)(meter_height-30));
-        cairo_move_to(cr,(double)(74*db),(double)meter_height-20);
-        cairo_line_to(cr,(double)(74*db),(double)(meter_height-30));
-        cairo_move_to(cr,(double)(94*db),(double)meter_height-20);
-        cairo_line_to(cr,(double)(94*db),(double)(meter_height-30));
-        cairo_move_to(cr,(double)(114*db),(double)meter_height-20);
-        cairo_line_to(cr,(double)(114*db),(double)(meter_height-30));
+        cairo_move_to(cr,offset+(double)(54*db),(double)meter_height-20);
+        cairo_line_to(cr,offset+(double)(54*db),(double)(meter_height-30));
+        cairo_move_to(cr,offset+(double)(74*db),(double)meter_height-20);
+        cairo_line_to(cr,offset+(double)(74*db),(double)(meter_height-30));
+        cairo_move_to(cr,offset+(double)(94*db),(double)meter_height-20);
+        cairo_line_to(cr,offset+(double)(94*db),(double)(meter_height-30));
+        cairo_move_to(cr,offset+(double)(114*db),(double)meter_height-20);
+        cairo_line_to(cr,offset+(double)(114*db),(double)(meter_height-30));
         cairo_stroke(cr);
 
-        cairo_move_to(cr, (double)(54*db)-3.0, (double)meter_height);
+        cairo_move_to(cr, offset+(double)(54*db)-3.0, (double)meter_height);
         cairo_show_text(cr, "9");
-        cairo_move_to(cr, (double)(74*db)-12.0, (double)meter_height);
+        cairo_move_to(cr, offset+(double)(74*db)-12.0, (double)meter_height);
         cairo_show_text(cr, "+20");
-        cairo_move_to(cr, (double)(94*db)-9.0, (double)meter_height);
+        cairo_move_to(cr, offset+(double)(94*db)-9.0, (double)meter_height);
         cairo_show_text(cr, "+40");
-        cairo_move_to(cr, (double)(114*db)-6.0, (double)meter_height);
+        cairo_move_to(cr, offset+(double)(114*db)-6.0, (double)meter_height);
         cairo_show_text(cr, "+60");
 
         cairo_set_source_rgb(cr, 0, 1, 0);
-        cairo_move_to(cr,(double)((level+127.0)*db),(double)meter_height-30);
-        cairo_line_to(cr,(double)((level+127.0)*db),(double)(meter_height-50));
+        cairo_rectangle(cr, offset+0.0, (double)(meter_height-50), (double)((level+127.0)*db), 20.0);
+        cairo_fill(cr);
+
+        if(level>max_level || max_count==10) {
+          max_level=level;
+          max_count=0;
+        }
+
+        if(max_level!=0) {
+          cairo_set_source_rgb(cr, 1, 1, 0);
+          cairo_move_to(cr,offset+(double)((max_level+127.0)*db),(double)meter_height-30);
+          cairo_line_to(cr,offset+(double)((max_level+127.0)*db),(double)(meter_height-50));
+        }
+
+
         cairo_stroke(cr);
 
-        text_location=(db*114)+5;
+        max_count++;
+
+
+        text_location=offset+(db*114)+5;
       }
 
       cairo_set_font_size(cr, 16);
@@ -154,18 +209,23 @@ void meter_update(int meter_type,double value,double reverse) {
             CAIRO_FONT_WEIGHT_BOLD);
       cairo_set_font_size(cr, 18);
 
-      sprintf(sf,"FWD: %3.2f W",value);
+      if((int)value>max_level || max_count==10) {
+          max_level=(int)value;
+          max_count=0;
+      }
+      max_count++;
+
+      sprintf(sf,"FWD: %d W",(int)max_level);
       cairo_move_to(cr, 10, 25);
       cairo_show_text(cr, sf);
 
-      // value is Watts
       double swr=(value+reverse)/(value-reverse);
       cairo_select_font_face(cr, "Arial",
             CAIRO_FONT_SLANT_NORMAL,
             CAIRO_FONT_WEIGHT_BOLD);
       cairo_set_font_size(cr, 18);
 
-      sprintf(sf,"SWR: %1.2f:1",swr);
+      sprintf(sf,"SWR: %1.1f:1",swr);
       cairo_move_to(cr, 10, 45);
       cairo_show_text(cr, sf);
       
diff --git a/meter.h b/meter.h
index ad197d33a01749c2ebc39c6869aa758bdf5c5d50..eb6c57bdc159c6ff4bb820e22e3ed28b93860dae 100644 (file)
--- a/meter.h
+++ b/meter.h
@@ -1,6 +1,25 @@
+/* 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.
+*
+*/
+
 #define SMETER 0
 #define POWER 1
 
 
 GtkWidget* meter_init(int width,int height);
-void meter_update(int meter_type,double value,double reverse);
+void meter_update(int meter_type,double value,double reverse,double exciter);
diff --git a/mode.c b/mode.c
index 98fdfa52226314463973c93535bd47835a99c229..9b6048f66962df46412f857805e8c530227b0f04 100644 (file)
--- a/mode.c
+++ b/mode.c
@@ -1,2 +1,21 @@
+/* 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.
+*
+*/
+
 char *mode_string[]={"LSB","USB","DSB","CWL","CWU","FMN","AM","DIGU","SPEC","DIGL","SAM","DRM"};
 
diff --git a/mode.h b/mode.h
index a4766a0254b681808cea220334d1bfee5e990651..154bab644a0e0ed09389dcd1cadf4502e5fe50a6 100644 (file)
--- a/mode.h
+++ b/mode.h
@@ -1,14 +1,6 @@
-/**
-* @file mode.h
-* @brief Header files for the mode functions
-* @author John Melton, G0ORX/N6LYT, Doxygen Comments Dave Larsen, KV0S
-* @version 0.1
-* @date 2009-04-12
-*/
-// mode.h
-
 /* Copyright (C)
-* 2009 - John Melton, G0ORX/N6LYT, Doxygen Comments Dave Larsen, KV0S
+* 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
index fe4a05a8862c0aae09c5f92064eca4c690113ec6..c69a10a46cc1cf7373d2feb174cfc8a11d7d269a 100644 (file)
@@ -1,3 +1,22 @@
+/* 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 <stdlib.h>
 #include <stdio.h>
 #include <sys/types.h>
@@ -17,9 +36,6 @@
 #include "discovered.h"
 //#include "discovery.h"
 
-int selected_device=0;
-int devices=0;
-DISCOVERED discovered[MAX_DEVICES];
 
 static char interface_name[64];
 static struct sockaddr_in interface_addr={0};
@@ -51,12 +67,11 @@ void print_device(int i) {
 }
 
 void new_discovery() {
-    devices=0;
-    selected_device=0;
     struct ifaddrs *addrs,*ifa;
     getifaddrs(&addrs);
     ifa = addrs;
     while (ifa) {
+        g_main_context_iteration(NULL, 0);
         if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET) {
             if((ifa->ifa_flags&IFF_UP)==IFF_UP
                 && (ifa->ifa_flags&IFF_RUNNING)==IFF_RUNNING
@@ -165,7 +180,7 @@ void* new_discover_receive_thread(void* arg) {
     struct timeval tv;
     int i;
 
-    tv.tv_sec = 1;
+    tv.tv_sec = 2;
     tv.tv_usec = 0;
 
     setsockopt(discovery_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval));
index fefa81a13403a4f655236148ad7e3aaafb074f4c..84b98dca50e63d2e1080cd95766035b10150a39a 100644 (file)
@@ -1,2 +1,21 @@
+/* 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.
+*
+*/
+
 
 void new_discovery(void);
index a3b968730ac26e8243a123fe0e3a37818d2930ee..dab050616b55a93bea85877999ed60c6955a70fd 100644 (file)
@@ -1,3 +1,22 @@
+/* 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.
+*
+*/
+
 
 //#define ECHO_MIC
 
 #include "channel.h"
 #include "discovered.h"
 #include "wdsp.h"
+#include "mode.h"
+#include "filter.h"
 #include "radio.h"
 #include "vfo.h"
 #include "toolbar.h"
+#include "wdsp_init.h"
 
 #define PI 3.1415926535897932F
 
-static int receiver;
-static int running=0;
-
 int data_socket;
 
+static int receiver;
+static int running;
+
 static struct sockaddr_in base_addr;
 static int base_addr_length;
 
@@ -69,21 +91,8 @@ static long general_sequence = 0;
 static long rx_specific_sequence = 0;
 static long tx_specific_sequence = 0;
 
-static int lt2208Dither = 0;
-static int lt2208Random = 0;
-static int attenuation = 20; // 20dB
-
-static long long ddsAFrequency = 14250000;
-static int filterLow=150;
-static int filterHigh=2550;
-static int mode=modeUSB;
-static unsigned long alex_rx_antenna=0;
-static unsigned long alex_tx_antenna=0;
-static unsigned long alex_attenuation=0;
-
 static int buffer_size=BUFFER_SIZE;
 static int fft_size=4096;
-static int sampleRate=48000;
 static int dspRate=48000;
 static int outputRate=48000;
 
@@ -94,165 +103,46 @@ static int micOutputRate=192000;
 static int spectrumWIDTH=800;
 static int SPECTRUM_UPDATES_PER_SECOND=10;
 
-static int mox=0;
-static int tune=0;
 static float phase = 0.0F;
 
-static int ptt;
-static int dot;
-static int dash;
-static int pll_locked;
-static int adc_overload;
-unsigned int exciter_power;
-unsigned int alex_forward_power;
-unsigned int alex_reverse_power;
-static int supply_volts;
-
 long response_sequence;
 int response;
 
+sem_t send_high_priority_sem;
 int send_high_priority=0;
+sem_t send_general_sem;
 int send_general=0;
 
-static void initAnalyzer(int channel,int buffer_size);
 static void* new_protocol_thread(void* arg);
 static void* new_protocol_timer_thread(void* arg);
 
-void filter_board_changed() {
-    send_general=1;
-}
-
-void pa_changed() {
-    send_general=1;
-}
-
-void tuner_changed() {
-    send_general=1;
-}
-
-void cw_changed() {
-}
-
-void set_attenuation(int value) {
-    attenuation=value;
-}
-
-int get_attenuation() {
-    return attenuation;
-}
-
-void set_alex_rx_antenna(unsigned long v) {
-    alex_rx_antenna=v;
-    send_high_priority=1;
-}
-
-void set_alex_tx_antenna(unsigned long v) {
-    alex_tx_antenna=v;
-    send_high_priority=1;
-}
-
-void set_alex_attenuation(unsigned long v) {
-    alex_attenuation=v;
+void schedule_high_priority(int source) {
+fprintf(stderr,"new_protocol: schedule_high_priority: source=%d\n",source);
+    sem_wait(&send_high_priority_sem);
     send_high_priority=1;
+    sem_post(&send_high_priority_sem);
 }
 
-void setSampleRate(int rate) {
-    sampleRate=rate;
-}
-
-int getSampleRate() {
-    return sampleRate;
-}
-
-void setFrequency(long long f) {
-    ddsAFrequency=f;
-    send_high_priority=1;
-}
-
-long long getFrequency() {
-    return ddsAFrequency;
-}
-
-void setMode(int m) {
-    mode=m;
-    SetRXAMode(receiver, mode);
-    SetTXAMode(CHANNEL_TX, mode);
-}
-
-int getMode() {
-    return mode;
-}
-
-void setFilter(int low,int high) {
-    if(mode==modeCWL) {
-        filterLow=-cwPitch-low;
-        filterHigh=-cwPitch+high;
-    } else if(mode==modeCWU) {
-        filterLow=cwPitch-low;
-        filterHigh=cwPitch+high;
-    } else {
-        filterLow=low;
-        filterHigh=high;
-    }
-
-    RXANBPSetFreqs(receiver,(double)filterLow,(double)filterHigh);
-    SetRXABandpassFreqs(receiver, (double)filterLow, (double)filterHigh);
-    SetRXASNBAOutputBandwidth(receiver, (double)filterLow, (double)filterHigh);
-
-    SetTXABandpassFreqs(CHANNEL_TX, (double)filterLow, (double)filterHigh);
-}
-
-int getFilterLow() {
-    return filterLow;
-}
-
-int getFilterHigh() {
-    return filterHigh;
-}
-
-void setMox(int state) {
-    if(mox!=state) {
-        mox=state;
-        send_high_priority=1;
-    }
-}
-
-int getMox() {
-    return mox;
-}
-
-void setTune(int state) {
-    if(tune!=state) {
-        tune=state;
-        send_high_priority=1;
-        send_general=1;
-    }
-}
-
-int getTune() {
-    return tune;
-}
-
-int isTransmitting() {
-    return ptt!=0 || mox!=0 || tune!=0;
+void schedule_general() {
+fprintf(stderr,"new_protocol: schedule_general\n");
+    sem_wait(&send_general_sem);
+    send_general=1;
+    sem_post(&send_general_sem);
 }
 
-double getDrive() {
-    return (double)drive/255.0;
+void filter_board_changed() {
+    schedule_general();
 }
 
-void setDrive(double value) {
-    drive=(int)(value*255.0);
-    send_high_priority=1;
+void pa_changed() {
+    schedule_general();
 }
 
-double getTuneDrive() {
-    return (double)tune_drive/255.0;
+void tuner_changed() {
+    schedule_general();
 }
 
-void setTuneDrive(double value) {
-    tune_drive=(int)(value*255.0);
-    send_high_priority=1;
+void cw_changed() {
 }
 
 void new_protocol_init(int rx,int pixels) {
@@ -263,56 +153,8 @@ void new_protocol_init(int rx,int pixels) {
     fprintf(stderr,"new_protocol_init: %d\n",rx);
 
     rc=sem_init(&response_sem, 0, 0);
-
-    fprintf(stderr,"OpenChannel %d buffer_size=%d fft_size=%d sampleRate=%d dspRate=%d outputRate=%d\n",
-                rx,
-                buffer_size,
-                fft_size,
-                sampleRate,
-                dspRate,
-                outputRate);
-
-    OpenChannel(rx,
-                buffer_size,
-                fft_size,
-                sampleRate,
-                dspRate,
-                outputRate,
-                0, // receive
-                1, // run
-                0.010, 0.025, 0.0, 0.010, 0);
-
-    fprintf(stderr,"OpenChannel %d buffer_size=%d fft_size=%d sampleRate=%d dspRate=%d outputRate=%d\n",
-                CHANNEL_TX,
-                buffer_size,
-                fft_size,
-                micSampleRate,
-                micDspRate,
-                micOutputRate);
-
-    OpenChannel(CHANNEL_TX,
-                buffer_size,
-                fft_size,
-                micSampleRate,
-                micDspRate,
-                micOutputRate,
-                1, // transmit
-                1, // run
-                0.010, 0.025, 0.0, 0.010, 0);
-
-    fprintf(stderr,"XCreateAnalyzer %d\n",rx);
-    int success;
-    XCreateAnalyzer(rx, &success, 262144, 1, 1, "");
-        if (success != 0) {
-            fprintf(stderr, "XCreateAnalyzer %d failed: %d\n" ,rx,success);
-        }
-    initAnalyzer(rx,buffer_size);
-
-    XCreateAnalyzer(CHANNEL_TX, &success, 262144, 1, 1, "");
-        if (success != 0) {
-            fprintf(stderr, "XCreateAnalyzer CHANNEL_TX failed: %d\n" ,success);
-        }
-    initAnalyzer(CHANNEL_TX,BUFFER_SIZE);
+    rc=sem_init(&send_high_priority_sem, 0, 1);
+    rc=sem_init(&send_general_sem, 0, 1);
 
     rc=pthread_create(&new_protocol_thread_id,NULL,new_protocol_thread,NULL);
     if(rc != 0) {
@@ -320,88 +162,8 @@ void new_protocol_init(int rx,int pixels) {
         exit(-1);
     }
 
-    SetRXAMode(rx, mode);
-    SetRXABandpassFreqs(rx, (double)filterLow, (double)filterHigh);
-    SetRXAAGCMode(rx, agc);
-    SetRXAAGCTop(rx,agc_gain);
-
-    SetRXAAMDSBMode(CHANNEL_RX0, 0);
-    SetRXAShiftRun(CHANNEL_RX0, 0);
-    SetRXAEMNRgainMethod(CHANNEL_RX0, 1);
-    SetRXAEMNRnpeMethod(CHANNEL_RX0, 0);
-    SetRXAEMNRaeRun(CHANNEL_RX0, 1);
-    SetRXAEMNRPosition(CHANNEL_RX0, 0);
-    SetRXAEMNRRun(CHANNEL_RX0, 0);
-    SetRXAANRRun(CHANNEL_RX0, 0);
-    SetRXAANFRun(CHANNEL_RX0, 0);
-
-    SetTXAMode(CHANNEL_TX, mode);
-    SetTXABandpassFreqs(CHANNEL_TX, (double)filterLow, (double)filterHigh);
-    SetTXABandpassWindow(CHANNEL_TX, 1);
-    SetTXABandpassRun(CHANNEL_TX, 1);
-
-    SetTXACFIRRun(CHANNEL_TX, 1);
-    SetTXAEQRun(CHANNEL_TX, 0);
-    SetTXACTCSSRun(CHANNEL_TX, 0);
-    SetTXAAMSQRun(CHANNEL_TX, 0);
-    SetTXACompressorRun(CHANNEL_TX, 0);
-    SetTXAosctrlRun(CHANNEL_TX, 0);
-    SetTXAPreGenRun(CHANNEL_TX, 0);
-    SetTXAPostGenRun(CHANNEL_TX, 0);
-
 }
 
-static void initAnalyzer(int channel,int buffer_size) {
-    int flp[] = {0};
-    double KEEP_TIME = 0.1;
-    int spur_elimination_ffts = 1;
-    int data_type = 1;
-    int fft_size = 8192;
-    int window_type = 4;
-    double kaiser_pi = 14.0;
-    int overlap = 2048;
-    int clip = 0;
-    int span_clip_l = 0;
-    int span_clip_h = 0;
-    int pixels=spectrumWIDTH;
-    int stitches = 1;
-    int avm = 0;
-    double tau = 0.001 * 120.0;
-    int MAX_AV_FRAMES = 60;
-    int display_average = MAX(2, (int) MIN((double) MAX_AV_FRAMES, (double) SPECTRUM_UPDATES_PER_SECOND * tau));
-    double avb = exp(-1.0 / (SPECTRUM_UPDATES_PER_SECOND * tau));
-    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) SPECTRUM_UPDATES_PER_SECOND, KEEP_TIME * (double) fft_size * (double) SPECTRUM_UPDATES_PER_SECOND);
-
-    fprintf(stderr,"SetAnalyzer channel=%d\n",channel);
-    SetAnalyzer(channel,
-            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
-            avm, //averaging mode
-            display_average, //number of spans to (moving) average for pixel result
-            avb, //back multiplier for weighted averaging
-            calibration_data_set, //identifier of which set of calibration data to use
-            span_min_freq, //frequency at first pixel value8192
-            span_max_freq, //frequency at last pixel value
-            max_w //max samples to hold in input ring buffers
-    );
-}
-
-
 static void new_protocol_general() {
     unsigned char buffer[60];
 
@@ -446,9 +208,7 @@ static void new_protocol_high_priority(int run,int tx,int drive) {
 
     buffer[4]=run|(tx<<1);
 
-    extern long long ddsAFrequency;
-
-    long phase=(long)((4294967296.0*(double)ddsAFrequency)/122880000.0);
+    long phase=(long)((4294967296.0*(double)ddsFrequency)/122880000.0);
 
 // rx
     buffer[9]=phase>>24;
@@ -456,7 +216,7 @@ static void new_protocol_high_priority(int run,int tx,int drive) {
     buffer[11]=phase>>8;
     buffer[12]=phase;
 
-// tx
+// tx (no split yet)
     buffer[329]=phase>>24;
     buffer[330]=phase>>16;
     buffer[331]=phase>>8;
@@ -477,15 +237,15 @@ else                                               HPF <= 6'b000010;    // 20MHz
 
     long filters=0x00000000;
 // set HPF
-    if(ddsAFrequency<1800000L) {
+    if(ddsFrequency<1800000L) {
         filters|=ALEX_BYPASS_HPF;
-    } else if(ddsAFrequency<6500000L) {
+    } else if(ddsFrequency<6500000L) {
         filters|=ALEX_1_5MHZ_HPF;
-    } else if(ddsAFrequency<9500000L) {
+    } else if(ddsFrequency<9500000L) {
         filters|=ALEX_6_5MHZ_HPF;
-    } else if(ddsAFrequency<13000000L) {
+    } else if(ddsFrequency<13000000L) {
         filters|=ALEX_9_5MHZ_HPF;
-    } else if(ddsAFrequency<20000000L) {
+    } else if(ddsFrequency<20000000L) {
         filters|=ALEX_13MHZ_HPF;
     } else {
         filters|=ALEX_20MHZ_HPF;
@@ -501,17 +261,17 @@ else if (frequency > 2400000)  LPF <= 7'b0000100;       // > 160m so use 80m LPF
 else LPF <= 7'b0001000;             // < 2.4MHz so use 160m LPF^M
 */
 
-    if(ddsAFrequency>32000000) {
+    if(ddsFrequency>32000000) {
         filters|=ALEX_6_BYPASS_LPF;
-    } else if(ddsAFrequency>22000000) {
+    } else if(ddsFrequency>22000000) {
         filters|=ALEX_12_10_LPF;
-    } else if(ddsAFrequency>15000000) {
+    } else if(ddsFrequency>15000000) {
         filters|=ALEX_17_15_LPF;
-    } else if(ddsAFrequency>8000000) {
+    } else if(ddsFrequency>8000000) {
         filters|=ALEX_30_20_LPF;
-    } else if(ddsAFrequency>4500000) {
+    } else if(ddsFrequency>4500000) {
         filters|=ALEX_60_40_LPF;
-    } else if(ddsAFrequency>2400000) {
+    } else if(ddsFrequency>2400000) {
         filters|=ALEX_80_LPF;
     } else {
         filters|=ALEX_160_LPF;
@@ -588,7 +348,22 @@ static void new_protocol_transmit_specific() {
     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]=orion_mic;
+    buffer[50]=0;
+    if(mic_linein) {
+      buffer[50]|=0x01;
+    }
+    if(mic_boost) {
+      buffer[50]|=0x02;
+    }
+    if(mic_ptt_enabled==0) {
+      buffer[50]|=0x04;
+    }
+    if(mic_bias_enabled) {
+      buffer[50]|=0x10;
+    }
+    if(mic_ptt_tip_bias_ring) {
+      buffer[50]|=0x08;
+    }
     buffer[51]=0x7F; // Line in gain
 
     if(sendto(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&transmitter_addr,transmitter_addr_length)<0) {
@@ -629,12 +404,12 @@ static void new_protocol_receive_specific() {
       buffer[17+(i*6)]=adc[i];
     }
 
-    buffer[18]=((sampleRate/1000)>>8)&0xFF;
-    buffer[19]=(sampleRate/1000)&0xFF;
+    buffer[18]=((sample_rate/1000)>>8)&0xFF;
+    buffer[19]=(sample_rate/1000)&0xFF;
     buffer[22]=24;
 
-    buffer[24]=((sampleRate/1000)>>8)&0xFF;
-    buffer[25]=(sampleRate/1000)&0xFF;
+    buffer[24]=((sample_rate/1000)>>8)&0xFF;
+    buffer[25]=(sample_rate/1000)&0xFF;
     buffer[28]=24;
 
     if(sendto(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&receiver_addr,receiver_addr_length)<0) {
@@ -761,7 +536,7 @@ fprintf(stderr,"new_protocol_thread: receiver=%d\n", receiver);
     micsamples=0;
     iqindex=4;
 
-    switch(sampleRate) {
+    switch(sample_rate) {
         case 48000:
             outputsamples=BUFFER_SIZE;
             break;
@@ -851,7 +626,7 @@ fprintf(stderr,"outputsamples=%d\n", outputsamples);
 
 //fprintf(stderr,"samples per frame %d\n",samplesperframe);
 
-          //if(!isTransmitting()) {
+          if(!isTransmitting()) {
               b=16;
               for(i=0;i<samplesperframe;i++) {
                   leftsample   = (int)((signed char) buffer[b++]) << 16;
@@ -906,7 +681,7 @@ fprintf(stderr,"outputsamples=%d\n", outputsamples);
                       samples=0;
                   }
               }
-          //}
+          }
 
        } else if(sourceport==COMMAND_RESPONCE_TO_HOST_PORT) {
           // command/response
@@ -1033,14 +808,19 @@ fprintf(stderr,"outputsamples=%d\n", outputsamples);
        }
 
        if(running) {
+           sem_wait(&send_general_sem);
            if(send_general==1) {
                new_protocol_general();
                send_general=0;
            }
+           sem_post(&send_general_sem);
+
+           sem_wait(&send_high_priority_sem);
            if(send_high_priority==1) {
                new_protocol_high_priority(1,isTransmitting(),tune==0?drive:tune_drive);
                send_high_priority=0;
            }
+           sem_post(&send_high_priority_sem);
        }
         
     }
index 1252f659017cf94f6ada877ff56640f32e523ea7..40ceee3d77a0393d3d5a54efa0648be830947c2c 100644 (file)
@@ -1,3 +1,22 @@
+/* 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.
+*
+*/
+
 
 // port definitions from host
 #define GENERAL_REGISTERS_FROM_HOST_PORT 1024
 
 #define BUFFER_SIZE 1024
 
-#define modeLSB 0
-#define modeUSB 1
-#define modeDSB 2
-#define modeCWL 3
-#define modeCWU 4
-#define modeFMN 5
-#define modeAM 6
-#define modeDIGU 7
-#define modeSPEC 8
-#define modeDIGL 9
-#define modeSAM 10
-#define modeDRM 11
-
 extern int data_socket;
 extern sem_t response_sem;
 
@@ -40,6 +46,12 @@ extern unsigned int exciter_power;
 extern unsigned int alex_forward_power;
 extern unsigned int alex_reverse_power;
 
+extern int send_high_priority;
+extern int send_general;
+
+void schedule_high_priority(int source);
+void schedule_general();
+
 void new_protocol_init(int rx,int pixels);
 void new_protocol_stop();
 
@@ -48,31 +60,9 @@ void pa_changed();
 void tuner_changed();
 void cw_changed();
 
-void set_attenuation(int value);
-int get_attenuation();
-
-void set_alex_rx_antenna(unsigned long v);
-void set_alex_tx_antenna(unsigned long v);
-void set_alex_attenuation(unsigned long v);
-
 void setMox(int state);
 int getMox();
 void setTune(int state);
 int getTune();
 int isTransmitting();
 
-double getDrive();
-void setDrive(double d);
-double getTuneDrive();
-void setTuneDrive(double d);
-
-void setSampleRate(int rate);
-int getSampleRate();
-void setFrequency(long long f);
-long long getFrequency();
-void setMode(int m);
-int getMode();
-void setFilter(int low,int high);
-int getFilterLow();
-int getFilterHigh();
-
index 8d0dea02a3871d77d7d5d76e7db2465d5c8c7e57..728970c1af224dd15f832bf638d08e3848de6861 100644 (file)
@@ -1,3 +1,22 @@
+/* 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 <stdio.h>
 #include <stdlib.h>
 #include <string.h>
diff --git a/old_discovery.c b/old_discovery.c
new file mode 100644 (file)
index 0000000..5b9835b
--- /dev/null
@@ -0,0 +1,251 @@
+/* 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 <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <net/if_arp.h>
+#include <net/if.h>
+#include <ifaddrs.h>
+#include <pthread.h>
+#include <string.h>
+#include <errno.h>
+
+#include "discovered.h"
+#include "old_discovery.h"
+
+static char interface_name[64];
+static struct sockaddr_in interface_addr={0};
+static int interface_length;
+
+#define DISCOVERY_PORT 1024
+static int discovery_socket;
+static struct sockaddr_in discovery_addr;
+
+static pthread_t discover_thread_id;
+static void* discover_receive_thread(void* arg);
+
+static void discover(struct ifaddrs* iface) {
+    int rc;
+    struct sockaddr_in *sa;
+    //char *addr;
+
+    strcpy(interface_name,iface->ifa_name);
+    fprintf(stderr,"discover: looking for HPSDR devices on %s\n",interface_name);
+
+    // send a broadcast to locate hpsdr boards on the network
+    discovery_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
+    if(discovery_socket<0) {
+        perror("discover: create socket failed for discovery_socket\n");
+        exit(-1);
+    }
+
+    int optval = 1;
+    setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+
+    sa = (struct sockaddr_in *) iface->ifa_addr;
+    //addr = inet_ntoa(sa->sin_addr);
+
+    // bind to this interface and the discovery port
+    interface_addr.sin_family = AF_INET;
+    interface_addr.sin_addr.s_addr = sa->sin_addr.s_addr;
+    interface_addr.sin_port = htons(DISCOVERY_PORT*2);
+    if(bind(discovery_socket,(struct sockaddr*)&interface_addr,sizeof(interface_addr))<0) {
+        perror("discover: bind socket failed for discovery_socket\n");
+        exit(-1);
+    }
+
+    fprintf(stderr,"discover: bound to %s\n",interface_name);
+
+    // allow broadcast on the socket
+    int on=1;
+    rc=setsockopt(discovery_socket, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
+    if(rc != 0) {
+        fprintf(stderr,"discover: cannot set SO_BROADCAST: rc=%d\n", rc);
+        exit(-1);
+    }
+
+    // setup to address
+    struct sockaddr_in to_addr={0};
+    to_addr.sin_family=AF_INET;
+    to_addr.sin_port=htons(DISCOVERY_PORT);
+    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);
+    }
+
+
+    // send discovery packet
+    unsigned char buffer[63];
+    buffer[0]=0xEF;
+    buffer[1]=0xFE;
+    buffer[2]=0x02;
+    int i;
+    for(i=3;i<63;i++) {
+        buffer[i]=0x00;
+    }
+
+    if(sendto(discovery_socket,buffer,63,0,(struct sockaddr*)&to_addr,sizeof(to_addr))<0) {
+        perror("discover: sendto socket failed for discovery_socket\n");
+        exit(-1);
+    }
+
+    // wait for receive thread to complete
+    void* status;
+    pthread_join(discover_thread_id,&status);
+
+    close(discovery_socket);
+
+    fprintf(stderr,"discover: exiting discover for %s\n",iface->ifa_name);
+
+}
+
+static void* discover_receive_thread(void* arg) {
+    struct sockaddr_in addr;
+    int len;
+    unsigned char buffer[2048];
+    int bytes_read;
+    struct timeval tv;
+    int i;
+
+fprintf(stderr,"discover_receive_thread\n");
+
+    tv.tv_sec = 2;
+    tv.tv_usec = 0;
+
+    setsockopt(discovery_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval));
+
+    len=sizeof(addr);
+    while(1) {
+        bytes_read=recvfrom(discovery_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&addr,&len);
+        if(bytes_read<0) {
+            fprintf(stderr,"discovery: bytes read %d\n", bytes_read);
+            perror("discovery: recvfrom socket failed for discover_receive_thread");
+            break;
+        }
+        fprintf(stderr,"discovered: received %d bytes\n",bytes_read);
+        if ((buffer[0] & 0xFF) == 0xEF && (buffer[1] & 0xFF) == 0xFE) {
+            int status = buffer[2] & 0xFF;
+            if (status == 2 || status == 3) {
+                if(devices<MAX_DEVICES) {
+                    discovered[devices].protocol=ORIGINAL_PROTOCOL;
+                    discovered[devices].device=buffer[10]&0xFF;
+                    switch(discovered[devices].device) {
+                        case DEVICE_METIS:
+                            strcpy(discovered[devices].name,"Metis");
+                            break;
+                        case DEVICE_HERMES:
+                            strcpy(discovered[devices].name,"Hermes");
+                            break;
+                        case DEVICE_GRIFFIN:
+                            strcpy(discovered[devices].name,"Griffin");
+                            break;
+                        case DEVICE_ANGELIA:
+                            strcpy(discovered[devices].name,"Angelia");
+                            break;
+                        case DEVICE_ORION:
+                            strcpy(discovered[devices].name,"Orion");
+                            break;
+                        case DEVICE_HERMES_LITE:
+                            strcpy(discovered[devices].name,"Hermes Lite");
+                            break;
+                        default:
+                            strcpy(discovered[devices].name,"Unknown");
+                            break;
+                    }
+                    discovered[devices].software_version=buffer[9]&0xFF;
+                    for(i=0;i<6;i++) {
+                        discovered[devices].mac_address[i]=buffer[i+3];
+                    }
+                    discovered[devices].status=status;
+                    memcpy((void*)&discovered[devices].address,(void*)&addr,sizeof(addr));
+                    discovered[devices].address_length=sizeof(addr);
+                    memcpy((void*)&discovered[devices].interface_address,(void*)&interface_addr,sizeof(interface_addr));
+                    discovered[devices].interface_length=sizeof(interface_addr);
+                    strcpy(discovered[devices].interface_name,interface_name);
+                    fprintf(stderr,"discovery: found device=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n",
+                            discovered[devices].device,
+                            discovered[devices].software_version,
+                            discovered[devices].status,
+                            inet_ntoa(discovered[devices].address.sin_addr),
+                            discovered[devices].mac_address[0],
+                            discovered[devices].mac_address[1],
+                            discovered[devices].mac_address[2],
+                            discovered[devices].mac_address[3],
+                            discovered[devices].mac_address[4],
+                            discovered[devices].mac_address[5],
+                            discovered[devices].interface_name);
+                    devices++;
+                }
+            }
+        }
+
+    }
+    fprintf(stderr,"discovery: exiting discover_receive_thread\n");
+    pthread_exit(NULL);
+}
+
+void old_discovery() {
+    struct ifaddrs *addrs,*ifa;
+
+fprintf(stderr,"old_discovery\n");
+    getifaddrs(&addrs);
+    ifa = addrs;
+    while (ifa) {
+        g_main_context_iteration(NULL, 0);
+        if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET) {
+            if((ifa->ifa_flags&IFF_UP)==IFF_UP
+                && (ifa->ifa_flags&IFF_RUNNING)==IFF_RUNNING
+                && (ifa->ifa_flags&IFF_LOOPBACK)!=IFF_LOOPBACK) {
+                discover(ifa);
+            }
+        }
+        ifa = ifa->ifa_next;
+    }
+    freeifaddrs(addrs);
+
+    fprintf(stderr, "discovery found %d devices\n",devices);
+
+    int i;
+    for(i=0;i<devices;i++) {
+                    fprintf(stderr,"discovery: found device=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n",
+                            discovered[i].device,
+                            discovered[i].software_version,
+                            discovered[i].status,
+                            inet_ntoa(discovered[i].address.sin_addr),
+                            discovered[i].mac_address[0],
+                            discovered[i].mac_address[1],
+                            discovered[i].mac_address[2],
+                            discovered[i].mac_address[3],
+                            discovered[i].mac_address[4],
+                            discovered[i].mac_address[5],
+                            discovered[i].interface_name);
+    }
+
+}
+
diff --git a/old_discovery.h b/old_discovery.h
new file mode 100644 (file)
index 0000000..89fddbe
--- /dev/null
@@ -0,0 +1,20 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+void old_discovery(void);
diff --git a/old_protocol.c b/old_protocol.c
new file mode 100644 (file)
index 0000000..9be6c60
--- /dev/null
@@ -0,0 +1,803 @@
+/* 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 <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <net/if_arp.h>
+#include <net/if.h>
+#include <ifaddrs.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+
+#include "band.h"
+#include "channel.h"
+#include "discovered.h"
+#include "mode.h"
+#include "filter.h"
+#include "old_protocol.h"
+#include "radio.h"
+#include "toolbar.h"
+
+#define PI 3.1415926535897932F
+
+#define DATA_PORT 1024
+
+#define SYNC 0x7F
+#define OZY_BUFFER_SIZE 512
+#define OUTPUT_BUFFER_SIZE 1024
+
+// ozy command and control
+#define MOX_DISABLED    0x00
+#define MOX_ENABLED     0x01
+
+#define MIC_SOURCE_JANUS 0x00
+#define MIC_SOURCE_PENELOPE 0x80
+#define CONFIG_NONE     0x00
+#define CONFIG_PENELOPE 0x20
+#define CONFIG_MERCURY  0x40
+#define CONFIG_BOTH     0x60
+#define PENELOPE_122_88MHZ_SOURCE 0x00
+#define MERCURY_122_88MHZ_SOURCE  0x10
+#define ATLAS_10MHZ_SOURCE        0x00
+#define PENELOPE_10MHZ_SOURCE     0x04
+#define MERCURY_10MHZ_SOURCE      0x08
+#define SPEED_48K                 0x00
+#define SPEED_96K                 0x01
+#define SPEED_192K                0x02
+#define SPEED_384K                0x03
+#define MODE_CLASS_E              0x01
+#define MODE_OTHERS               0x00
+#define ALEX_ATTENUATION_0DB      0x00
+#define ALEX_ATTENUATION_10DB     0x01
+#define ALEX_ATTENUATION_20DB     0x02
+#define ALEX_ATTENUATION_30DB     0x03
+#define LT2208_GAIN_OFF           0x00
+#define LT2208_GAIN_ON            0x04
+#define LT2208_DITHER_OFF         0x00
+#define LT2208_DITHER_ON          0x08
+#define LT2208_RANDOM_OFF         0x00
+#define LT2208_RANDOM_ON          0x10
+
+static int buffer_size=BUFFER_SIZE;
+
+static int receiver;
+static int display_width;
+
+static int speed;
+
+static int dsp_rate=48000;
+static int output_rate=48000;
+
+static int data_socket;
+static struct sockaddr_in data_addr;
+static int data_addr_length;
+
+static int output_buffer_size;
+
+static unsigned char control_in[5]={0x00,0x00,0x00,0x00,0x00};
+static unsigned char control_out[5]={0x00,0x00,0x00,0x00,0x00};
+
+static double tuning_phase;
+static float phase=0.0f;
+
+static int running;
+static long ep4_sequence;
+
+static int samples=0;
+
+//static float left_input_buffer[BUFFER_SIZE];
+//static float right_input_buffer[BUFFER_SIZE];
+static double iqinputbuffer[BUFFER_SIZE*2];
+
+//static float mic_left_buffer[BUFFER_SIZE];
+//static float mic_right_buffer[BUFFER_SIZE];
+static double micinputbuffer[BUFFER_SIZE*2];
+
+//static float left_output_buffer[OUTPUT_BUFFER_SIZE];
+//static float right_output_buffer[OUTPUT_BUFFER_SIZE];
+static double audiooutputbuffer[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 micoutputbuffer[BUFFER_SIZE*2];
+
+static short left_rx_sample;
+static short right_rx_sample;
+static short left_tx_sample;
+static short right_tx_sample;
+
+static unsigned char output_buffer[OZY_BUFFER_SIZE];
+static int output_buffer_index=0;
+
+static int command=0;
+
+static pthread_t receive_thread_id;
+static void start_receive_thread();
+static void *receive_thread(void* arg);
+static void process_ozy_input_buffer(char  *buffer);
+static void process_bandscope_buffer(char  *buffer);
+void ozy_send_buffer();
+
+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);
+
+void schedule_frequency_changed() {
+//fprintf(stderr,"old_protocol: schedule_frequency_changed\n");
+    //sem_wait(&frequency_changed_sem);
+    frequencyChanged=1;
+    //sem_post(&frequency_changed_sem);
+}
+
+static float sineWave(double* buf, int samples, float phase, float freq) {
+    float phase_step = 2 * PI * freq / 192000.0F;
+    int i;
+    for (i = 0; i < samples; i++) {
+        buf[i*2] = (double) sin(phase);
+        phase += phase_step;
+    }
+    return phase;
+}
+
+static void setSpeed(int s) {
+  int speed=SPEED_48K;
+  output_buffer_size=OUTPUT_BUFFER_SIZE;
+  switch(s) {
+    case 48000:
+        speed=SPEED_48K;
+        output_buffer_size=OUTPUT_BUFFER_SIZE;
+        break;
+    case 96000:
+        speed=SPEED_96K;
+        output_buffer_size=OUTPUT_BUFFER_SIZE/2;
+        break;
+    case 192000:
+        speed=SPEED_192K;
+        output_buffer_size=OUTPUT_BUFFER_SIZE/4;
+        break;
+    case 384000:
+        speed=SPEED_384K;
+        output_buffer_size=OUTPUT_BUFFER_SIZE/8;
+        break;
+    default:
+        fprintf(stderr,"Invalid sample rate: %d. Defaulting to 48K.\n",s);
+        break;
+  }
+
+  //fprintf(stderr,"setSpeed sample_rate=%d speed=%d\n",s,speed);
+
+  control_out[1]=control_out[1]&0xFC;
+  control_out[1]=control_out[1]|speed;
+
+}
+
+
+void old_protocol_stop() {
+  metis_start_stop(0);
+  running=FALSE;
+}
+
+void old_protocol_init(int rx,int pixels) {
+  int i;
+
+  fprintf(stderr,"old_protocol_init\n");
+
+  //int result=sem_init(&frequency_changed_sem, 0, 1);
+
+  receiver=rx;
+  display_width=pixels;
+
+   // setup defaults
+  control_out[0] = MOX_DISABLED;
+  control_out[1] = CONFIG_BOTH
+            | MERCURY_122_88MHZ_SOURCE
+            | MERCURY_10MHZ_SOURCE
+            | speed
+            | MIC_SOURCE_PENELOPE;
+  control_out[2] = MODE_OTHERS;
+  control_out[3] = ALEX_ATTENUATION_0DB
+            | LT2208_GAIN_OFF
+            | LT2208_DITHER_ON
+            | LT2208_RANDOM_ON;
+  control_out[4] = 0;
+
+  setSpeed(sample_rate);
+
+  start_receive_thread();
+
+  fprintf(stderr,"old_protocol_init: prime radio\n");
+  for(i=8;i<OZY_BUFFER_SIZE;i++) {
+    output_buffer[i]=0;
+  }
+  do {
+    ozy_send_buffer();
+  } while (command!=0);
+
+  metis_start_stop(1);
+
+}
+
+static void start_receive_thread() {
+  int i;
+  int rc;
+  struct hostent *h;
+
+  fprintf(stderr,"old_protocol starting receive thread\n");
+
+  DISCOVERED* d=&discovered[selected_device];
+
+  data_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
+  if(data_socket<0) {
+    perror("old_protocol: create socket failed for data_socket\n");
+    exit(-1);
+  }
+
+  int optval = 1;
+  setsockopt(data_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+
+  // bind to the interface
+  if(bind(data_socket,(struct sockaddr*)&d->interface_address,d->interface_length)<0) {
+    perror("old_protocol: bind socket failed for data_socket\n");
+    exit(-1);
+  }
+
+  memcpy(&data_addr,&d->address,d->address_length);
+  data_addr_length=d->address_length;
+  data_addr.sin_port=htons(DATA_PORT);
+
+  rc=pthread_create(&receive_thread_id,NULL,receive_thread,NULL);
+  if(rc != 0) {
+    fprintf(stderr,"old_protocol: pthread_create failed on receive_thread: rc=%d\n", rc);
+    exit(-1);
+  }
+
+}
+
+static void *receive_thread(void* arg) {
+  struct sockaddr_in addr;
+  int length;
+  unsigned char buffer[2048];
+  int bytes_read;
+  int ep;
+  long sequence;
+
+  fprintf(stderr, "old_protocol: receive_thread\n");
+  running=1;
+
+  length=sizeof(addr);
+  while(running) {
+    bytes_read=recvfrom(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&addr,&length);
+    if(bytes_read<0) {
+      perror("recvfrom socket failed for old_protocol: receive_thread");
+      exit(1);
+    }
+
+    if(buffer[0]==0xEF && buffer[1]==0xFE) {
+      switch(buffer[2]) {
+        case 1:
+          // get the end point
+          ep=buffer[3]&0xFF;
+
+          // get the sequence number
+          sequence=((buffer[4]&0xFF)<<24)+((buffer[5]&0xFF)<<16)+((buffer[6]&0xFF)<<8)+(buffer[7]&0xFF);
+
+          switch(ep) {
+            case 6: // EP6
+              // process the data
+              process_ozy_input_buffer(&buffer[8]);
+              process_ozy_input_buffer(&buffer[520]);
+              break;
+            case 4: // EP4
+/*
+              ep4_sequence++;
+              if(sequence!=ep4_sequence) {
+                ep4_sequence=sequence;
+              } else {
+                int seq=(int)(sequence%32L);
+                if((sequence%32L)==0L) {
+                  reset_bandscope_buffer_index();
+                }
+                process_bandscope_buffer(&buffer[8]);
+                process_bandscope_buffer(&buffer[520]);
+              }
+*/
+              break;
+            default:
+              fprintf(stderr,"unexpected EP %d length=%d\n",ep,bytes_read);
+              break;
+          }
+          break;
+        case 2:  // response to a discovery packet
+          fprintf(stderr,"unexepected discovery response when not in discovery mode\n");
+          break;
+        default:
+          fprintf(stderr,"unexpected packet type: 0x%02X\n",buffer[2]);
+          break;
+      }
+    } else {
+      fprintf(stderr,"received bad header bytes on data port %02X,%02X\n",buffer[0],buffer[1]);
+    }
+  }
+}
+
+static void process_ozy_input_buffer(char  *buffer) {
+  int i,j;
+  int b=0;
+  unsigned char ozy_samples[8*8];
+  int bytes;
+  int last_ptt;
+  int last_dot;
+  int last_dash;
+  double gain;
+  int left_sample;
+  int right_sample;
+  int mic_sample;
+  float left_sample_float;
+  float right_sample_float;
+  float mic_sample_float;
+
+  if(buffer[b++]==SYNC && buffer[b++]==SYNC && buffer[b++]==SYNC) {
+    // extract control bytes
+    control_in[0]=buffer[b++];
+    control_in[1]=buffer[b++];
+    control_in[2]=buffer[b++];
+    control_in[3]=buffer[b++];
+    control_in[4]=buffer[b++];
+
+    last_ptt=ptt;
+    last_dot=dot;
+    last_dash=dash;
+    ptt=(control_in[0]&0x01)==0x01;
+    dash=(control_in[0]&0x02)==0x02;
+    dot=(control_in[0]&0x04)==0x04;
+
+    if(last_ptt!=ptt) {
+      g_idle_add(ptt_update,(gpointer)ptt);
+    }
+
+    switch((control_in[0]>>3)&0x1F) {
+      case 0:
+        adc_overload=control_in[1]&0x01;
+        IO1=(control_in[1]&0x02)?0:1;
+        IO2=(control_in[1]&0x04)?0:1;
+        IO3=(control_in[1]&0x08)?0:1;
+        if(mercury_software_version!=control_in[2]) {
+          mercury_software_version=control_in[2];
+          fprintf(stderr,"  Mercury Software version: %d (0x%0X)\n",mercury_software_version,mercury_software_version);
+        }
+        if(penelope_software_version!=control_in[3]) {
+          penelope_software_version=control_in[3];
+          fprintf(stderr,"  Penelope Software version: %d (0x%0X)\n",penelope_software_version,penelope_software_version);
+        }
+        if(ozy_software_version!=control_in[4]) {
+          ozy_software_version=control_in[4];
+          fprintf(stderr,"FPGA firmware version: %d.%d\n",ozy_software_version/10,ozy_software_version%10);
+        }
+        break;
+      case 1:
+        exciter_power=((control_in[1]&0xFF)<<8)|(control_in[2]&0xFF); // from Penelope or Hermes
+        alex_forward_power=((control_in[3]&0xFF)<<8)|(control_in[4]&0xFF); // from Alex or Apollo
+        break;
+      case 2:
+        alex_reverse_power=((control_in[1]&0xFF)<<8)|(control_in[2]&0xFF); // from Alex or Apollo
+        AIN3=(control_in[3]<<8)+control_in[4]; // from Pennelope or Hermes
+        break;
+      case 3:
+        AIN4=(control_in[1]<<8)+control_in[2]; // from Pennelope or Hermes
+        AIN6=(control_in[3]<<8)+control_in[4]; // from Pennelope or Hermes
+        break;
+    }
+
+
+    // extract the 63 samples
+    for(i=0;i<63;i++) {
+
+      left_sample   = (int)((signed char) buffer[b++]) << 16;
+      left_sample  += (int)((unsigned char)buffer[b++]) << 8;
+      left_sample  += (int)((unsigned char)buffer[b++]);
+      right_sample  = (int)((signed char) buffer[b++]) << 16;
+      right_sample += (int)((unsigned char)buffer[b++]) << 8;
+      right_sample += (int)((unsigned char)buffer[b++]);
+      mic_sample    = (int)((signed char) buffer[b++]) << 8;
+      mic_sample   += (int)((unsigned char)buffer[b++]);
+/*
+      left_sample  = ((int)buffer[b++]) << 16;
+      left_sample  = (((unsigned char)buffer[b++]) << 8) | left_sample;
+      left_sample  = ((unsigned char)buffer[b++]) | left_sample;
+      right_sample = ((int)buffer[b++]) << 16;
+      right_sample = (((unsigned char)buffer[b++]) << 8) | right_sample;
+      right_sample = ((unsigned char)buffer[b++]) | right_sample;
+      mic_sample   = ((int)buffer[b++]) << 8;
+      mic_sample   = ((unsigned char)buffer[b++]) | mic_sample;
+*/
+      left_sample_float=(float)left_sample/8388607.0; // 24 bit sample 2^23-1
+      right_sample_float=(float)right_sample/8388607.0; // 24 bit sample 2^23-1
+      mic_sample_float=(float)mic_sample/32767.0f; // 16 bit sample 2^16-1
+
+      // add to buffer
+      if(isTransmitting()) {
+        micinputbuffer[samples*2]=(double)mic_sample_float*mic_gain;
+        micinputbuffer[(samples*2)+1]=(double)mic_sample_float*mic_gain;
+        samples++;
+      } else {
+        iqinputbuffer[samples*2]=(double)left_sample_float;
+        iqinputbuffer[(samples*2)+1]=(double)right_sample_float;
+        samples++;
+      }
+
+      // when we have enough samples give them to WDSP and get the results
+      if(samples==buffer_size) {
+        int error;
+        if(isTransmitting()) {
+          if(tune) {
+            double tunefrequency = (double)((filterHigh - filterLow) / 2);
+            phase=sineWave(micinputbuffer, BUFFER_SIZE, phase, (float)tunefrequency);
+          } else if(mode==modeCWU || mode==modeCWL) {
+          }
+          // process the output
+          fexchange0(CHANNEL_TX, micinputbuffer, micoutputbuffer, &error);
+          if(error!=0) {
+            fprintf(stderr,"fexchange0 (CHANNEL_TX) returned error: %d\n", error);
+          }
+          Spectrum0(1, CHANNEL_TX, 0, 0, micoutputbuffer);
+          if(penelope) {
+            if(tune) {
+              gain=65535.0*255.0/(double)tune_drive;
+            } else {
+              gain=65535.0*255.0/(double)drive;
+            }
+          } else {
+            gain=65535.0;
+          }
+          for(j=0;j<output_buffer_size;j++) {
+            left_rx_sample=0;
+            right_rx_sample=0;
+            left_tx_sample=(short)(micoutputbuffer[j*2]*gain*2);
+            right_tx_sample=(short)(micoutputbuffer[(j*2)+1]*gain*2);
+            output_buffer[output_buffer_index++]=left_rx_sample>>8;
+            output_buffer[output_buffer_index++]=left_rx_sample;
+            output_buffer[output_buffer_index++]=right_rx_sample>>8;
+            output_buffer[output_buffer_index++]=right_rx_sample;
+            output_buffer[output_buffer_index++]=left_tx_sample>>8;
+            output_buffer[output_buffer_index++]=left_tx_sample;
+            output_buffer[output_buffer_index++]=right_tx_sample>>8;
+            output_buffer[output_buffer_index++]=right_tx_sample;
+            if(output_buffer_index>=OZY_BUFFER_SIZE) {
+              ozy_send_buffer();
+              output_buffer_index=8;
+            }
+          }
+        } else {
+          // process the input
+          fexchange0(CHANNEL_RX0, iqinputbuffer, audiooutputbuffer, &error);
+          if(error!=0) {
+            fprintf(stderr,"fexchange2 (CHANNEL_RX0) returned error: %d\n", error);
+          }
+          Spectrum0(1, CHANNEL_RX0, 0, 0, iqinputbuffer);
+          for(j=0;j<output_buffer_size;j++) {
+            left_rx_sample=(short)(audiooutputbuffer[j*2]*32767.0*volume);
+            right_rx_sample=(short)(audiooutputbuffer[(j*2)+1]*32767.0*volume);
+            left_tx_sample=0;
+            right_tx_sample=0;
+            output_buffer[output_buffer_index++]=left_rx_sample>>8;
+            output_buffer[output_buffer_index++]=left_rx_sample;
+            output_buffer[output_buffer_index++]=right_rx_sample>>8;
+            output_buffer[output_buffer_index++]=right_rx_sample;
+            output_buffer[output_buffer_index++]=left_tx_sample>>8;
+            output_buffer[output_buffer_index++]=left_tx_sample;
+            output_buffer[output_buffer_index++]=right_tx_sample>>8;
+            output_buffer[output_buffer_index++]=right_tx_sample;
+            if(output_buffer_index>=OZY_BUFFER_SIZE) {
+              ozy_send_buffer();
+              output_buffer_index=8;
+            }
+          }
+        }
+        samples=0;
+      }
+    }
+  } else {
+    time_t t;
+    struct tm* gmt;
+    time(&t);
+    gmt=gmtime(&t);
+
+    fprintf(stderr,"%s: process_ozy_input_buffer: did not find sync\n",
+            asctime(gmt));
+    exit(1);
+  }
+}
+
+/*
+static void process_bandscope_buffer(char  *buffer) {
+}
+*/
+
+
+void ozy_send_buffer() {
+  output_buffer[0]=SYNC;
+  output_buffer[1]=SYNC;
+  output_buffer[2]=SYNC;
+
+  switch(command) {
+#ifdef EXCLUDE
+    case 0:
+      //sem_wait(&frequency_changed_sem);
+      if(frequencyChanged) {
+        // send rx frequency
+        output_buffer[3]=control_out[0]|0x04;
+        output_buffer[4]=ddsFrequency>>24;
+        output_buffer[5]=ddsFrequency>>16;
+        output_buffer[6]=ddsFrequency>>8;
+        output_buffer[7]=ddsFrequency;
+        //freqcommand++;
+      } else {
+        output_buffer[3]=control_out[0];
+        output_buffer[4]=control_out[1];
+        output_buffer[5]=control_out[2];
+        output_buffer[6]=control_out[3];
+        output_buffer[7]=control_out[4];
+      }
+      //sem_post(&frequency_changed_sem);
+      break;
+    case 1:
+      // send tx frequency
+      output_buffer[3]=control_out[0]|0x02;
+/*
+      if(bSplit) {
+        if(frequencyBChanged) {
+          output_buffer[3]=control_out[0]|0x02; // Penelope
+          output_buffer[4]=ddsBFrequency>>24;
+          output_buffer[5]=ddsBFrequency>>16;
+          output_buffer[6]=ddsBFrequency>>8;
+          output_buffer[7]=ddsBFrequency;
+        } else {
+          output_buffer[3]=control_out[0];
+          output_buffer[4]=control_out[1];
+          output_buffer[5]=control_out[2];
+          output_buffer[6]=control_out[3];
+          output_buffer[7]=control_out[4];
+        }
+      } else {
+*/
+        //sem_wait(&frequency_changed_sem);
+        if(frequencyChanged) {
+          output_buffer[4]=ddsFrequency>>24;
+          output_buffer[5]=ddsFrequency>>16;
+          output_buffer[6]=ddsFrequency>>8;
+          output_buffer[7]=ddsFrequency;
+        } else {
+          output_buffer[3]=control_out[0];
+          output_buffer[4]=control_out[1];
+          output_buffer[5]=control_out[2];
+          output_buffer[6]=control_out[3];
+          output_buffer[7]=control_out[4];
+        }
+        frequencyChanged=0;
+        //sem_post(&frequency_changed_sem);
+/*
+      }
+*/
+/*
+      frequencyBChanged=0;
+*/
+      break;
+    case 2:
+      output_buffer[3]=control_out[0];
+      output_buffer[4]=control_out[1];
+      output_buffer[5]=control_out[2];
+      output_buffer[6]=control_out[3];
+      output_buffer[7]=control_out[4];
+      break;
+#endif
+
+    case 0:
+      output_buffer[3]=control_out[0];
+      output_buffer[4]=control_out[1];
+      output_buffer[5]=control_out[2];
+      output_buffer[6]=control_out[3];
+      output_buffer[7]=control_out[4];
+      break;
+    case 1:
+      output_buffer[3]=control_out[0]|0x04;
+      output_buffer[4]=ddsFrequency>>24;
+      output_buffer[5]=ddsFrequency>>16;
+      output_buffer[6]=ddsFrequency>>8;
+      output_buffer[7]=ddsFrequency;
+      break;
+    case 2:
+      output_buffer[3]=control_out[0]|0x02;
+      output_buffer[4]=ddsFrequency>>24;
+      output_buffer[5]=ddsFrequency>>16;
+      output_buffer[6]=ddsFrequency>>8;
+      output_buffer[7]=ddsFrequency;
+      break;
+    case 3:
+      {
+      float d=(float)drive;
+      if(tune) {
+        d=(float)tune_drive;
+      }
+      BAND *band=band_get_current_band();
+      d=(d/100.0F)*(float)band->pa_calibration;
+
+      output_buffer[3]=0x12;
+      output_buffer[4]=(int)d;
+      output_buffer[5]=control_out[2];
+      if(mic_boost) {
+        output_buffer[5]|=0x01;
+      }
+      if(mic_linein) {
+        output_buffer[5]|=0x02;
+      }
+      if(filter_board==APOLLO) {
+        output_buffer[5]|=0x2C; // board, filter ,tuner
+      }
+      if((filter_board==APOLLO) && tune && apollo_tuner) {
+        output_buffer[5]|=0x10;
+      }
+      output_buffer[6]=control_out[3];
+      output_buffer[7]=control_out[4];
+      }
+      break;
+    case 4:
+      // need to add orion tip/ring and bias configuration
+      output_buffer[3]=0x14;
+      output_buffer[4]=0x00;
+      if(mic_ptt_enabled==0) {
+        output_buffer[4]|=0x40;
+      }
+      if(mic_bias_enabled) {
+        output_buffer[4]|=0x20;
+      }
+      if(mic_ptt_tip_bias_ring) {
+        output_buffer[4]|=0x10;
+      }
+      output_buffer[5]=0x00;
+      output_buffer[6]=0x00;
+      output_buffer[7]=0x00;
+      break;
+    case 5:
+      // need to add rx attenuation and cw configuration
+      output_buffer[3]=0x16;
+      output_buffer[4]=0x00;
+      output_buffer[5]=0x00;
+      if(cw_keys_reversed!=0) {
+        output_buffer[5]|=0x40;
+      }
+      output_buffer[6]=cw_keyer_speed | (cw_keyer_mode<<6);
+      output_buffer[7]=cw_keyer_weight | (cw_keyer_spacing<<7);
+      break;
+    case 6:
+      // need to add tx attenuation and rx ADC selection
+      output_buffer[3]=0x1C;
+      output_buffer[4]=0x00;
+      output_buffer[5]=0x00;
+      output_buffer[6]=0x00;
+      output_buffer[7]=0x00;
+      break;
+    case 7:
+      // need to add cw configuration
+      output_buffer[3]=0x1E;
+      if(cw_keyer_internal==1) {
+        if(isTransmitting() || (mode!=modeCWU && mode!=modeCWL)) {
+          output_buffer[4]=0x00;
+        } else {
+          output_buffer[4]=0x01;
+        }
+      } else {
+        output_buffer[4]=0x00;
+      }
+      output_buffer[5]=cw_keyer_sidetone_volume;
+      output_buffer[6]=cw_keyer_ptt_delay;
+      output_buffer[7]=0x00;
+      break;
+    case 8:
+      // need to add cw configuration
+      output_buffer[3]=0x20;
+      output_buffer[4]=cw_keyer_hang_time;
+      output_buffer[5]=cw_keyer_hang_time>>8;
+      output_buffer[6]=cw_keyer_sidetone_frequency;
+      output_buffer[7]=cw_keyer_sidetone_frequency>>8;
+      break;
+  }
+  command++;
+  //if(command>=14) {
+    if(command>=8) {
+      command=0;
+    }
+  // set mox
+  output_buffer[3]|=isTransmitting();
+
+  metis_write(0x02,output_buffer,OZY_BUFFER_SIZE);
+}
+
+static int metis_write(unsigned char ep,char* buffer,int length) {
+  int i;
+
+  // copy the buffer over
+  for(i=0;i<512;i++) {
+    metis_buffer[i+metis_offset]=buffer[i];
+  }
+
+  if(metis_offset==8) {
+    metis_offset=520;
+  } else {
+    send_sequence++;
+    metis_buffer[0]=0xEF;
+    metis_buffer[1]=0xFE;
+    metis_buffer[2]=0x01;
+    metis_buffer[3]=ep;
+    metis_buffer[4]=(send_sequence>>24)&0xFF;
+    metis_buffer[5]=(send_sequence>>16)&0xFF;
+    metis_buffer[6]=(send_sequence>>8)&0xFF;
+    metis_buffer[7]=(send_sequence)&0xFF;
+
+    // send the buffer
+    metis_send_buffer(&metis_buffer[0],1032);
+    metis_offset=8;
+
+  }
+
+  return length;
+}
+
+static void metis_start_stop(int command) {
+  int i;
+  unsigned char buffer[64];
+    
+  buffer[0]=0xEF;
+  buffer[1]=0xFE;
+  buffer[2]=0x04;    // start/stop command
+  buffer[3]=command;    // send EP6 and EP4 data (0x00=stop)
+
+  for(i=0;i<60;i++) {
+    buffer[i+4]=0x00;
+  }
+
+  metis_send_buffer(buffer,sizeof(buffer));
+}
+
+static void metis_send_buffer(char* buffer,int length) {
+  if(sendto(data_socket,buffer,length,0,(struct sockaddr*)&data_addr,data_addr_length)!=length) {
+    perror("sendto socket failed for metis_send_data\n");
+  }
+}
+
+
diff --git a/old_protocol.h b/old_protocol.h
new file mode 100644 (file)
index 0000000..633006b
--- /dev/null
@@ -0,0 +1,23 @@
+/* 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.
+*
+*/
+
+#define BUFFER_SIZE 1024
+void old_protocol_stop();
+void old_protocol_init(int rx,int pixels);
+void schedule_frequency_changed();
index 96284efc37ada384fdbfb9043ed492eafb56406b..4d50c379954499f61cb7cfda84c6f6de2eecbfc1 100644 (file)
@@ -1,3 +1,22 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
 #include <math.h>
@@ -5,7 +24,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include <semaphore.h>
-#include "new_protocol.h"
+#include "band.h"
+#include "discovered.h"
+#include "radio.h"
 #include "panadapter.h"
 #include "vfo.h"
 
@@ -18,8 +39,8 @@ static gint last_x;
 static gboolean has_moved=FALSE;
 static gboolean pressed=FALSE;
 
-static float panadapter_max=-60.0;
-static float panadapter_min=-160.0;
+//static float panadapter_max=-60.0;
+//static float panadapter_min=-160.0;
 
 static gfloat hz_per_pixel;
 static gfloat filter_left;
@@ -155,13 +176,17 @@ void panadapter_update(float *data,int tx) {
         if(panadapter_surface) {
 
             if(tx) {
-                saved_max=panadapter_max;
-                saved_min=panadapter_min;
+                saved_max=panadapter_high;
+                saved_min=panadapter_low;
                 saved_hz_per_pixel=hz_per_pixel;
 
-                panadapter_max=30;
-                panadapter_min=-100;
-                hz_per_pixel=192000.0/(double)display_width;
+                panadapter_high=20;
+                panadapter_low=-100;
+                if(protocol==ORIGINAL_PROTOCOL) {
+                    hz_per_pixel=48000.0/(double)display_width;
+                } else {
+                    hz_per_pixel=192000.0/(double)display_width;
+                }
             }
 
             //clear_panadater_surface();
@@ -178,11 +203,11 @@ void panadapter_update(float *data,int tx) {
             cairo_fill(cr);
 
             // plot the levels
-            int V = (int)(panadapter_max - panadapter_min);
+            int V = (int)(panadapter_high - panadapter_low);
             int numSteps = V / 20;
             for (i = 1; i < numSteps; i++) {
-                int num = panadapter_max - i * 20;
-                int y = (int)floor((panadapter_max - num) * panadapter_height / V);
+                int num = panadapter_high - i * 20;
+                int y = (int)floor((panadapter_high - num) * panadapter_height / V);
 
                 cairo_set_source_rgb (cr, 0, 1, 1);
                 cairo_set_line_width(cr, 1.0);
@@ -203,8 +228,9 @@ void panadapter_update(float *data,int tx) {
 
             // plot frequency markers
             long f;
+            long half=(long)getSampleRate()/2L;
             for(i=0;i<display_width;i++) {
-                f = getFrequency() - ((long) getSampleRate() / 2) + (long) (hz_per_pixel * i);
+                f = getFrequency() - half + (long) (hz_per_pixel * i);
                 if (f > 0) {
                     if ((f % 20000) < (long) hz_per_pixel) {
                         cairo_set_source_rgb (cr, 0, 1, 1);
@@ -226,6 +252,25 @@ void panadapter_update(float *data,int tx) {
             }
             cairo_stroke(cr);
 
+            // band edges
+            long min_display=getFrequency()-half;
+            long max_display=getFrequency()+half;
+            BAND_LIMITS* bandLimits=getBandLimits(min_display,max_display);
+            if(bandLimits!=NULL) {
+                cairo_set_source_rgb (cr, 1, 0, 0);
+                cairo_set_line_width(cr, 2.0);
+                if((min_display<bandLimits->minFrequency)&&(max_display>bandLimits->minFrequency)) {
+                    i=(bandLimits->minFrequency-min_display)/(long long)hz_per_pixel;
+                    cairo_move_to(cr,(double)i,0.0);
+                    cairo_line_to(cr,(double)i,(double)panadapter_height);
+                }
+                if((min_display<bandLimits->maxFrequency)&&(max_display>bandLimits->maxFrequency)) {
+                    i=(bandLimits->maxFrequency-min_display)/(long long)hz_per_pixel;
+                    cairo_move_to(cr,(double)i,0.0);
+                    cairo_line_to(cr,(double)i,(double)panadapter_height);
+                }
+            }
+            
             // cursor
             cairo_set_source_rgb (cr, 1, 0, 0);
             cairo_set_line_width(cr, 1.0);
@@ -238,17 +283,17 @@ void panadapter_update(float *data,int tx) {
             cairo_set_line_width(cr, 1.0);
 
             double s1,s2;
-            samples[0]=panadapter_min-20;
-            samples[display_width-1]=panadapter_min-20;
+            samples[0]=panadapter_low-20;
+            samples[display_width-1]=panadapter_low-20;
             for(i=1;i<display_width;i++) {
                 s1=samples[i-1]+get_attenuation();
-                s1 = floor((panadapter_max - s1)
+                s1 = floor((panadapter_high - s1)
                             * (double) panadapter_height
-                            / (panadapter_max - panadapter_min));
+                            / (panadapter_high - panadapter_low));
                 s2=samples[i]+get_attenuation();
-                s2 = floor((panadapter_max - s2)
+                s2 = floor((panadapter_high - s2)
                             * (double) panadapter_height
-                            / (panadapter_max - panadapter_min));
+                            / (panadapter_high - panadapter_low));
                 cairo_move_to(cr, (double)i-1, s1);
                 cairo_line_to(cr, (double)i, s2);
             }
@@ -260,8 +305,8 @@ void panadapter_update(float *data,int tx) {
             gtk_widget_queue_draw (panadapter);
 
             if(tx) {
-                panadapter_max=saved_max;
-                panadapter_min=saved_min;
+                panadapter_high=saved_max;
+                panadapter_low=saved_min;
                 hz_per_pixel=saved_hz_per_pixel;
             }
 
index 142ff312ed3cdab2f6fb30995d35fa8e6ee8540f..278f5049664b6dcaa002e8b414222eeca1369095 100644 (file)
@@ -1,3 +1,22 @@
+/* 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.
+*
+*/
+
 void panadapter_update(float* data,int tx);
 
 GtkWidget* panadapter_init(int width,int height);
diff --git a/pihpsdr b/pihpsdr
deleted file mode 100755 (executable)
index f647db0..0000000
Binary files a/pihpsdr and /dev/null differ
index 22bf486aad6816668b875883dcc5173b94c6b105..32a7f07c0d2178c42841f92a93a7045682696e11 100644 (file)
@@ -1,3 +1,22 @@
+/* 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 <stdlib.h>
 #include <stdio.h>
 #include <string.h>
index 55cd608fe82297bb9ada5b5ce1de89e9f8ee28d0..5056c6e582a6f9452899822059f6b6f6f7cde536 100644 (file)
@@ -1,3 +1,22 @@
+/* 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.
+*
+*/
+
 typedef struct _PROPERTY PROPERTY;
 
 /* --------------------------------------------------------------------------*/
diff --git a/radio.c b/radio.c
index 1188605074481115b56532e1d9e29749f48eccbe..3dcff68c5852ff2728090e236301d7c5c77c3f8d 100644 (file)
--- a/radio.c
+++ b/radio.c
@@ -1,31 +1,66 @@
+/* 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 <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <semaphore.h>
 
 #include "radio.h"
 #include "agc.h"
 #include "band.h"
 #include "discovered.h"
 #include "property.h"
+#include "new_protocol.h"
 
 char property_path[128];
+sem_t property_sem;
+
+
+int penelope=0;
+int tx_out_of_band=0;
 
 int sample_rate=48000;
 int filter_board=ALEX;
 int pa=PA_ENABLED;
 int apollo_tuner=0;
 
-int panadapter_high=-80;
-int panadapter_low=-160;
+int display_panadapter=1;
+int panadapter_high=-60;
+int panadapter_low=-140;
 
+int display_waterfall=1;
 int waterfall_high=-100;
 int waterfall_low=-150;
 int waterfall_automatic=1;
 
+int display_sliders=1;
+int display_toolbar=1;
+
 double volume=0.2;
 double mic_gain=1.5;
 
-int orion_mic=MIC_BOOST|ORION_MIC_PTT_ENABLED|ORION_MIC_PTT_TIP_BIAS_RING|ORION_MIC_BIAS_ENABLED;
+int mic_linein=0;
+int mic_boost=0;
+int mic_bias_enabled=0;
+int mic_ptt_enabled=0;
+int mic_ptt_tip_bias_ring=0;
 
 int agc=AGC_MEDIUM;
 double agc_gain=60.0;
@@ -49,6 +84,13 @@ int step=100;
 
 int byte_swap=0;
 
+int lt2208Dither = 0;
+int lt2208Random = 0;
+int attenuation = 20; // 20dB
+unsigned long alex_rx_antenna=0;
+unsigned long alex_tx_antenna=0;
+unsigned long alex_attenuation=0;
+
 int cw_keys_reversed=0; // 0=disabled 1=enabled
 int cw_keyer_speed=12; // 1-60 WPM
 int cw_keyer_mode=KEYER_STRAIGHT;
@@ -61,8 +103,161 @@ int cw_keyer_hang_time=300; // ms
 int cw_keyer_sidetone_frequency=400; // Hz
 int cw_breakin=1; // 0=disabled 1=enabled
 
+int vfo_encoder_divisor=25;
+
+int protocol;
+int device;
+int ozy_software_version;
+int mercury_software_version;
+int penelope_software_version;
+int ptt;
+int dot;
+int dash;
+int adc_overload;
+int pll_locked;
+unsigned int exciter_power;
+unsigned int alex_forward_power;
+unsigned int alex_reverse_power;
+unsigned int AIN3;
+unsigned int AIN4;
+unsigned int AIN6;
+unsigned int IO1;
+unsigned int IO2;
+unsigned int IO3;
+int supply_volts;
+int mox;
+int tune;
+
+long long ddsFrequency=14250000;
+
+void init_radio() {
+  int rc;
+  rc=sem_init(&property_sem, 0, 0);
+  if(rc!=0) {
+    fprintf(stderr,"init_radio: sem_init failed for property_sem: %d\n", rc);
+    exit(-1);
+  }
+  sem_post(&property_sem);
+}
+
+void setSampleRate(int rate) {
+    sample_rate=rate;
+}
+
+int getSampleRate() {
+    return sample_rate;
+}
+
+void setMox(int state) {
+fprintf(stderr,"setMox: protocol=%d\n", protocol);
+  if(mox!=state) {
+    mox=state;
+    if(protocol==NEW_PROTOCOL) {
+      schedule_high_priority(3);
+    }
+  }
+}
+
+int getMox() {
+    return mox;
+}
+
+void setTune(int state) {
+fprintf(stderr,"setTune: protocol=%d\n", protocol);
+  if(tune!=state) {
+    tune=state;
+    if(protocol==NEW_PROTOCOL) {
+      schedule_high_priority(4);
+      schedule_general();
+    }
+  }
+}
+
+int getTune() {
+  return tune;
+}
+
+int isTransmitting() {
+  return ptt!=0 || mox!=0 || tune!=0;
+}
+
+void setFrequency(long long f) {
+//fprintf(stderr,"setFrequency: protocol=%d f=%lld\n", protocol, f);
+  ddsFrequency=f;
+  if(protocol==NEW_PROTOCOL) {
+    schedule_high_priority(5);
+  } else {
+    schedule_frequency_changed();
+  }
+}
+
+long long getFrequency() {
+    return ddsFrequency;
+}
+
+double getDrive() {
+    return (double)drive/255.0;
+}
+
+void setDrive(double value) {
+//fprintf(stderr,"setDrive: protocol=%d\n", protocol);
+    drive=(int)(value*255.0);
+    if(protocol==NEW_PROTOCOL) {
+      schedule_high_priority(6);
+    }
+}
+
+double getTuneDrive() {
+    return (double)tune_drive/255.0;
+}
+
+void setTuneDrive(double value) {
+fprintf(stderr,"setTuneDrive: protocol=%d\n", protocol);
+    tune_drive=(int)(value*255.0);
+    if(protocol==NEW_PROTOCOL) {
+      schedule_high_priority(7);
+    }
+}
+
+void set_attenuation(int value) {
+    attenuation=value;
+}
+
+int get_attenuation() {
+    return attenuation;
+}
+
+void set_alex_rx_antenna(unsigned long v) {
+    alex_rx_antenna=v;
+    if(protocol==NEW_PROTOCOL) {
+        schedule_high_priority(1);
+    }
+}
+
+void set_alex_tx_antenna(unsigned long v) {
+    alex_tx_antenna=v;
+    if(protocol==NEW_PROTOCOL) {
+        schedule_high_priority(2);
+    }
+}
+
+void set_alex_attenuation(unsigned long v) {
+    alex_attenuation=v;
+    if(protocol==NEW_PROTOCOL) {
+        schedule_high_priority(0);
+    }
+}
+
 void radioRestoreState() {
     char *value;
+
+    sem_wait(&property_sem);
+    loadProperties(property_path);
+
+    value=getProperty("penelope");
+    if(value) penelope=atoi(value);
+    value=getProperty("tx_out_of_band");
+    if(value) tx_out_of_band=atoi(value);
     value=getProperty("sample_rate");
     if(value) sample_rate=atoi(value);
     value=getProperty("filter_board");
@@ -71,10 +266,18 @@ void radioRestoreState() {
     if(value) apollo_tuner=atoi(value);
     value=getProperty("pa");
     if(value) pa=atoi(value);
+    value=getProperty("display_panadapter");
+    if(value) display_panadapter=atoi(value);
     value=getProperty("panadapter_high");
     if(value) panadapter_high=atoi(value);
     value=getProperty("panadapter_low");
     if(value) panadapter_low=atoi(value);
+    value=getProperty("display_waterfall");
+    if(value) display_waterfall=atoi(value);
+    value=getProperty("display_sliders");
+    if(value) display_sliders=atoi(value);
+    value=getProperty("display_toolbar");
+    if(value) display_toolbar=atoi(value);
     value=getProperty("waterfall_high");
     if(value) waterfall_high=atoi(value);
     value=getProperty("waterfall_low");
@@ -83,10 +286,22 @@ void radioRestoreState() {
     if(value) waterfall_automatic=atoi(value);
     value=getProperty("volume");
     if(value) volume=atof(value);
+    value=getProperty("drive");
+    if(value) drive=atoi(value);
+    value=getProperty("tune_drive");
+    if(value) tune_drive=atoi(value);
     value=getProperty("mic_gain");
     if(value) mic_gain=atof(value);
-    value=getProperty("orion_mic");
-    if(value) orion_mic=atof(value);
+    value=getProperty("mic_boost");
+    if(value) mic_boost=atof(value);
+    value=getProperty("mic_linein");
+    if(value) mic_linein=atof(value);
+    value=getProperty("mic_ptt_enabled");
+    if(value) mic_ptt_enabled=atof(value);
+    value=getProperty("mic_bias_enabled");
+    if(value) mic_bias_enabled=atof(value);
+    value=getProperty("mic_ptt_tip_bias_ring");
+    if(value) mic_ptt_tip_bias_ring=atof(value);
     value=getProperty("nr");
     if(value) nr=atoi(value);
     value=getProperty("nb");
@@ -125,13 +340,17 @@ void radioRestoreState() {
     if(value) cw_keyer_sidetone_frequency=atoi(value);
     value=getProperty("cw_breakin");
     if(value) cw_breakin=atoi(value);
-
+    value=getProperty("vfo_encoder_divisor");
+    if(value) vfo_encoder_divisor=atoi(value);
 
     bandRestoreState();
+    sem_post(&property_sem);
 }
 
 void radioSaveState() {
     char value[80];
+
+    sem_wait(&property_sem);
     sprintf(value,"%d",sample_rate);
     setProperty("sample_rate",value);
     sprintf(value,"%d",filter_board);
@@ -140,10 +359,18 @@ void radioSaveState() {
     setProperty("apollo_tuner",value);
     sprintf(value,"%d",pa);
     setProperty("pa",value);
+    sprintf(value,"%d",display_panadapter);
+    setProperty("display_panadapter",value);
     sprintf(value,"%d",panadapter_high);
     setProperty("panadapter_high",value);
     sprintf(value,"%d",panadapter_low);
     setProperty("panadapter_low",value);
+    sprintf(value,"%d",display_waterfall);
+    setProperty("display_waterfall",value);
+    sprintf(value,"%d",display_sliders);
+    setProperty("display_sliders",value);
+    sprintf(value,"%d",display_toolbar);
+    setProperty("display_toolbar",value);
     sprintf(value,"%d",waterfall_high);
     setProperty("waterfall_high",value);
     sprintf(value,"%d",waterfall_low);
@@ -154,8 +381,20 @@ void radioSaveState() {
     setProperty("volume",value);
     sprintf(value,"%f",mic_gain);
     setProperty("mic_gain",value);
-    sprintf(value,"%d",orion_mic);
-    setProperty("orion_mic",value);
+    sprintf(value,"%d",drive);
+    setProperty("drive",value);
+    sprintf(value,"%d",tune_drive);
+    setProperty("tune_drive",value);
+    sprintf(value,"%d",mic_boost);
+    setProperty("mic_boost",value);
+    sprintf(value,"%d",mic_linein);
+    setProperty("mic_linein",value);
+    sprintf(value,"%d",mic_ptt_enabled);
+    setProperty("mic_ptt_enabled",value);
+    sprintf(value,"%d",mic_bias_enabled);
+    setProperty("mic_bias_enabled",value);
+    sprintf(value,"%d",mic_ptt_tip_bias_ring);
+    setProperty("mic_ptt_tip_bias_ring",value);
     sprintf(value,"%d",nr);
     setProperty("nr",value);
     sprintf(value,"%d",nb);
@@ -194,6 +433,11 @@ void radioSaveState() {
     setProperty("cw_keyer_sidetone_frequency",value);
     sprintf(value,"%d",cw_breakin);
     setProperty("cw_breakin",value);
+    sprintf(value,"%d",vfo_encoder_divisor);
+    setProperty("vfo_encoder_divisor",value);
 
     bandSaveState();
+
+    saveProperties(property_path);
+    sem_post(&property_sem);
 }
diff --git a/radio.h b/radio.h
index 28ef822db1f1424e6eface17eb41defdb6463b99..87d1b696d46db14220b2abb0f336c7224eb4f6f7 100644 (file)
--- a/radio.h
+++ b/radio.h
@@ -1,13 +1,43 @@
+/* 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.
+*
+*/
+
+
+#define NEW_MIC_IN 0x00
+#define NEW_LINE_IN 0x01
+#define NEW_MIC_BOOST 0x02
+#define NEW_ORION_MIC_PTT_ENABLED 0x00
+#define NEW_ORION_MIC_PTT_DISABLED 0x04
+#define NEW_ORION_MIC_PTT_RING_BIAS_TIP 0x00
+#define NEW_ORION_MIC_PTT_TIP_BIAS_RING 0x08
+#define NEW_ORION_MIC_BIAS_DISABLED 0x00
+#define NEW_ORION_MIC_BIAS_ENABLED 0x10
+
+#define OLD_MIC_IN 0x00
+#define OLD_LINE_IN 0x02
+#define OLD_MIC_BOOST 0x01
+#define OLD_ORION_MIC_PTT_ENABLED 0x40
+#define OLD_ORION_MIC_PTT_DISABLED 0x00
+#define OLD_ORION_MIC_PTT_RING_BIAS_TIP 0x00
+#define OLD_ORION_MIC_PTT_TIP_BIAS_RING 0x08
+#define OLD_ORION_MIC_BIAS_DISABLED 0x00
+#define OLD_ORION_MIC_BIAS_ENABLED 0x20
 
-#define MIC_IN 0x00
-#define LINE_IN 0x01
-#define MIC_BOOST 0x02
-#define ORION_MIC_PTT_ENABLED 0x00
-#define ORION_MIC_PTT_DISABLED 0x04
-#define ORION_MIC_PTT_RING_BIAS_TIP 0x00
-#define ORION_MIC_PTT_TIP_BIAS_RING 0x08
-#define ORION_MIC_BIAS_DISABLED 0x00
-#define ORION_MIC_BIAS_ENABLED 0x10
 
 extern char property_path[];
 
@@ -25,18 +55,26 @@ extern char property_path[];
 #define KEYER_MODE_A 1
 #define KEYER_MODE_B 2
 
+extern int penelope;
+extern int tx_out_of_band;
+
 extern int sample_rate;
 extern int filter_board;
 extern int pa;
 extern int apollo_tuner;
 
+extern int display_panadapter;
 extern int panadapter_high;
 extern int panadapter_low;
 
+extern int display_waterfall;
 extern int waterfall_high;
 extern int waterfall_low;
 extern int waterfall_automatic;
 
+extern int display_sliders;
+extern int display_toolbar;
+
 extern double volume;
 extern double mic_gain;
 extern int agc;
@@ -49,7 +87,11 @@ extern int snb;
 
 extern int cwPitch;
 
-extern int orion_mic;
+extern int mic_linein;
+extern int mic_boost;
+extern int mic_bias_enabled;
+extern int mic_ptt_enabled;
+extern int mic_ptt_tip_bias_ring;
 
 extern int tune_drive;
 extern int drive;
@@ -63,6 +105,13 @@ extern int step;
 
 extern int byte_swap;
 
+extern int lt2208Dither;
+extern int lt2208Random;
+extern int attenuation;
+extern unsigned long alex_rx_antenna;
+extern unsigned long alex_tx_antenna;
+extern unsigned long alex_attenuation;
+
 extern int cw_keys_reversed;
 extern int cw_keyer_speed;
 extern int cw_keyer_mode;
@@ -75,6 +124,56 @@ extern int cw_keyer_hang_time;
 extern int cw_keyer_sidetone_frequency;
 extern int cw_breakin;
 
+extern int vfo_encoder_divisor;
+
+extern int protocol;
+extern int device;
+extern int ozy_software_version;
+extern int mercury_software_version;
+extern int penelope_software_version;
+extern int mox;
+extern int tune;
+extern int ptt;
+extern int dot;
+extern int dash;
+extern int adc_overload;
+extern int pll_locked;
+extern unsigned int exciter_power;
+extern unsigned int alex_forward_power;
+extern unsigned int alex_reverse_power;
+extern unsigned int IO1;
+extern unsigned int IO2;
+extern unsigned int IO3;
+extern unsigned int AIN3;
+extern unsigned int AIN4;
+extern unsigned int AIN6;
+extern int supply_volts;
+
+extern long long ddsFrequency;
+
+extern void init_radio();
+extern void setSampleRate(int rate);
+extern int getSampleRate();
+extern void setMox(int state);
+extern int getMox();
+extern void setTune(int state);
+extern int getTune();
+double getDrive();
+void setDrive(double d);
+double getTuneDrive();
+void setTuneDrive(double d);
+
+void set_attenuation(int value);
+int get_attenuation();
+void set_alex_rx_antenna(unsigned long v);
+void set_alex_tx_antenna(unsigned long v);
+void set_alex_attenuation(unsigned long v);
+
+extern int isTransmitting();
+
+extern void setFrequency(long long f);
+extern long long getFrequency();
+
 extern void radioRestoreState();
 extern void radioSaveState();
 
diff --git a/rotary_encoder.c b/rotary_encoder.c
deleted file mode 100644 (file)
index 9e70db4..0000000
+++ /dev/null
@@ -1,298 +0,0 @@
-#include <stdio.h>
-#include <pigpio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <poll.h>
-#include <sched.h>
-#include <pthread.h>
-#include <wiringPi.h>
-
-#include "rotary_encoder.h"
-#include "main.h"
-
-#define SYSFS_GPIO_DIR  "/sys/class/gpio"
-
-#define RASPBERRYPI_VFO_ENCODER_A 14
-#define RASPBERRYPI_VFO_ENCODER_B 15
-
-#define ODROID_VFO_ENCODER_A 108
-#define ODROID_VFO_ENCODER_B 97
-#define ODROID_VFO_ENCODER_A_PIN 23
-#define ODROID_VFO_ENCODER_B_PIN 24
-
-#define AF_ENCODER_A 20
-#define AF_ENCODER_B 26
-#define AF_FUNCTION 21
-
-#define RF_ENCODER_A 16
-#define RF_ENCODER_B 19
-#define RF_FUNCTION 13
-
-#define FUNCTION 12
-#define BAND 6
-
-static int VFO_ENCODER_A=14;
-static int VFO_ENCODER_B=15;
-
-static int VFO_ENCODER_A_PIN=0;
-static int VFO_ENCODER_B_PIN=0;
-
-static volatile int vfoEncoderPos;
-static volatile int afEncoderPos;
-static volatile int afFunction;
-static volatile int rfEncoderPos;
-static volatile int rfFunction;
-static volatile int function;
-static volatile int band;
-
-static void afFunctionAlert(int gpio, int level, uint32_t tick) {
-    afFunction=(level==0);
-}
-
-static void rfFunctionAlert(int gpio, int level, uint32_t tick) {
-    rfFunction=(level==0);
-}
-
-static void functionAlert(int gpio, int level, uint32_t tick) {
-    function=(level==0);
-}
-
-static void bandAlert(int gpio, int level, uint32_t tick) {
-    band=(level==0);
-}
-
-static void vfoEncoderPulse(int gpio, int level, unsigned int tick) {
-   static int levA=0, levB=0, lastGpio = -1;
-
-//fprintf(stderr,"vfoEncoderPulse:%d=%d\n",gpio,level);
-   if (gpio == VFO_ENCODER_A) levA = level; else levB = level;
-
-   if (gpio != lastGpio) /* debounce */
-   {
-      lastGpio = gpio;
-
-      if ((gpio == VFO_ENCODER_A) && (level == 0))
-      {
-         if (!levB) ++vfoEncoderPos;
-      }
-      else if ((gpio == VFO_ENCODER_B) && (level == 1))
-      {
-         if (levA) --vfoEncoderPos;
-      }
-   }
-}
-
-static void afEncoderPulse(int gpio, int level, uint32_t tick)
-{
-   static int levA=0, levB=0, lastGpio = -1;
-
-   if (gpio == AF_ENCODER_A) levA = level; else levB = level;
-
-   if (gpio != lastGpio) /* debounce */
-   {
-      lastGpio = gpio;
-
-      if ((gpio == AF_ENCODER_A) && (level == 0))
-      {
-         if (!levB) ++afEncoderPos;
-      }
-      else if ((gpio == AF_ENCODER_B) && (level == 1))
-      {
-         if (levA) --afEncoderPos;
-      }
-   }
-}
-
-static void rfEncoderPulse(int gpio, int level, uint32_t tick)
-{
-   static int levA=0, levB=0, lastGpio = -1;
-
-   if (gpio == RF_ENCODER_A) levA = level; else levB = level;
-
-   if (gpio != lastGpio) /* debounce */
-   {
-      lastGpio = gpio;
-
-      if ((gpio == RF_ENCODER_A) && (level == 0))
-      {
-         if (!levB) ++rfEncoderPos;
-      }
-      else if ((gpio == RF_ENCODER_B) && (level == 1))
-      {
-         if (levA) --rfEncoderPos;
-      }
-   }
-}
-
-void interruptB(void) {
-   vfoEncoderPulse(VFO_ENCODER_B,digitalRead(VFO_ENCODER_B_PIN),0);
-}
-
-void interruptA(void) {
-   vfoEncoderPulse(VFO_ENCODER_A,digitalRead(VFO_ENCODER_A_PIN),0);
-}
-
-int encoder_init() {
-
-    if(strcmp(unameData.nodename,"raspberrypi")==0) {
-
-    VFO_ENCODER_A=RASPBERRYPI_VFO_ENCODER_A;
-    VFO_ENCODER_B=RASPBERRYPI_VFO_ENCODER_B;
-    VFO_ENCODER_A_PIN=0;
-    VFO_ENCODER_B_PIN=0;
-
-    fprintf(stderr,"encoder_init: VFO_ENCODER_A=%d VFO_ENCODER_B=%d\n",VFO_ENCODER_A,VFO_ENCODER_B);
-
-    if(gpioInitialise()<0) {
-        fprintf(stderr,"Cannot initialize GPIO\n");
-        return -1;
-    }
-
-   gpioSetMode(VFO_ENCODER_A, PI_INPUT);
-   gpioSetMode(VFO_ENCODER_B, PI_INPUT);
-   gpioSetPullUpDown(VFO_ENCODER_A, PI_PUD_UP);
-   gpioSetPullUpDown(VFO_ENCODER_B, PI_PUD_UP);
-   gpioSetAlertFunc(VFO_ENCODER_A, vfoEncoderPulse);
-   gpioSetAlertFunc(VFO_ENCODER_B, vfoEncoderPulse);
-   vfoEncoderPos=0;
-
-
-   gpioSetMode(AF_FUNCTION, PI_INPUT);
-   gpioSetPullUpDown(AF_FUNCTION,PI_PUD_UP);
-   gpioSetAlertFunc(AF_FUNCTION, afFunctionAlert);
-   afFunction=0;
-
-   gpioSetMode(AF_ENCODER_A, PI_INPUT);
-   gpioSetMode(AF_ENCODER_B, PI_INPUT);
-   gpioSetPullUpDown(AF_ENCODER_A, PI_PUD_OFF);
-   gpioSetPullUpDown(AF_ENCODER_B, PI_PUD_OFF);
-   gpioSetAlertFunc(AF_ENCODER_A, afEncoderPulse);
-   gpioSetAlertFunc(AF_ENCODER_B, afEncoderPulse);
-   afEncoderPos=0;
-
-   gpioSetMode(RF_FUNCTION, PI_INPUT);
-   gpioSetPullUpDown(RF_FUNCTION,PI_PUD_UP);
-   gpioSetAlertFunc(RF_FUNCTION, rfFunctionAlert);
-   rfFunction=0;
-
-   gpioSetMode(RF_ENCODER_A, PI_INPUT);
-   gpioSetMode(RF_ENCODER_B, PI_INPUT);
-   gpioSetPullUpDown(RF_ENCODER_A, PI_PUD_OFF);
-   gpioSetPullUpDown(RF_ENCODER_B, PI_PUD_OFF);
-   gpioSetAlertFunc(RF_ENCODER_A, rfEncoderPulse);
-   gpioSetAlertFunc(RF_ENCODER_B, rfEncoderPulse);
-   rfEncoderPos=0;
-
-   gpioSetMode(FUNCTION, PI_INPUT);
-   gpioSetPullUpDown(FUNCTION,PI_PUD_UP);
-   gpioSetAlertFunc(FUNCTION, functionAlert);
-
-   gpioSetMode(BAND, PI_INPUT);
-   gpioSetPullUpDown(BAND,PI_PUD_UP);
-   gpioSetAlertFunc(BAND, bandAlert);
-
-   } else if(strcmp(unameData.nodename,"odroid")==0) {
-
-    VFO_ENCODER_A=ODROID_VFO_ENCODER_A;
-    VFO_ENCODER_B=ODROID_VFO_ENCODER_B;
-    VFO_ENCODER_A_PIN=ODROID_VFO_ENCODER_A_PIN;
-    VFO_ENCODER_B_PIN=ODROID_VFO_ENCODER_B_PIN;
-
-    fprintf(stderr,"encoder_init: VFO_ENCODER_A=%d VFO_ENCODER_B=%d\n",VFO_ENCODER_A,VFO_ENCODER_B);
-
-  if (wiringPiSetup () < 0) {
-      printf ("Unable to setup wiringPi: %s\n", strerror (errno));
-      return 1;
-  }
-
-  FILE *fp;
-
-  fp = popen("echo 97 > /sys/class/gpio/export\n", "r");
-  pclose(fp);
-  fp = popen("echo \"in\" > /sys/class/gpio/gpio97/direction\n", "r");
-  pclose(fp);
-  fp = popen("chmod 0666 /sys/class/gpio/gpio97/value\n", "r");
-  pclose(fp);
-
-  fp = popen("echo 108 > /sys/class/gpio/export\n", "r");
-  pclose(fp);
-  fp = popen("echo \"in\" > /sys/class/gpio/gpio108/direction\n", "r");
-  pclose(fp);
-  fp = popen("chmod 0666 /sys/class/gpio/gpio108/value\n", "r");
-  pclose(fp);
-
-  if ( wiringPiISR (24, INT_EDGE_BOTH, &interruptB) < 0 ) {
-      printf ("Unable to setup ISR: %s\n", strerror (errno));
-      return 1;
-  }
-
-  if ( wiringPiISR (23, INT_EDGE_BOTH, &interruptA) < 0 ) {
-      printf ("Unable to setup ISR: %s\n", strerror (errno));
-      return 1;
-  }
-  } else {
-     fprintf(stderr,"Unknown nodename: %s. Rotary Encoder not enabled.\n",unameData.nodename);
-     return 1;
-  }
-
-
-   return 0;
-}
-
-void encoder_close() {
-  if(strcmp(unameData.nodename,"odroid")==0) {
-    FILE *fp;
-    fp = popen("echo 97 > /sys/class/gpio/unexport\n", "r");
-    pclose(fp);
-    fp = popen("echo 108 > /sys/class/gpio/unexport\n", "r");
-    pclose(fp);
-  }
-}
-
-int vfo_encoder_get_pos() {
-    int pos=vfoEncoderPos;
-
-  if(strcmp(unameData.nodename,"raspberrypi")==0) {
-    if(pos<0 && pos>-12) {
-        pos=0;
-    } else if(pos>0 && pos<12) {
-        pos=0;
-    }
-    pos=pos/12;
-    vfoEncoderPos=vfoEncoderPos-(pos*12);
-  } else if(strcmp(unameData.nodename,"odroid")==0) {
-    vfoEncoderPos=0;
-  }
-  return pos;
-}
-
-int af_encoder_get_pos() {
-    int pos=afEncoderPos;
-    afEncoderPos=0;
-    return pos;
-}
-
-int af_function_get_state() {
-    return afFunction;
-}
-
-int rf_encoder_get_pos() {
-    int pos=rfEncoderPos;
-    rfEncoderPos=0;
-    return pos;
-}
-
-int rf_function_get_state() {
-    return rfFunction;
-}
-
-int function_get_state() {
-    return function;
-}
-
-int band_get_state() {
-    return band;
-}
diff --git a/rotary_encoder.h b/rotary_encoder.h
deleted file mode 100644 (file)
index 604feb1..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-int encoder_init();
-void encoder_close();
-int vfo_encoder_get_pos();
-int af_encoder_get_pos();
-int af_function_get_state();
-
index 53c7909fcdf83347fe49a7b10ef4025644b5c2f2..a231547577a7143b607242b7101aaf71769fc736 100644 (file)
--- a/splash.c
+++ b/splash.c
@@ -1,6 +1,28 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
 #include <gtk/gtk.h>
+#include "version.h"
 
 GtkWidget *splash_window;
+GtkWidget *status;
+static cairo_surface_t *splash_surface = NULL;
 
 /* Close the splash screen */
 void splash_close()
@@ -8,16 +30,70 @@ void splash_close()
   gtk_widget_destroy(splash_window);
 }
 
+static gboolean splash_configure_event_cb (GtkWidget         *widget,
+            GdkEventConfigure *event,
+            gpointer           data)
+{
+  if (splash_surface)
+    cairo_surface_destroy (splash_surface);
+
+  splash_surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget),
+                                       CAIRO_CONTENT_COLOR,
+                                       gtk_widget_get_allocated_width (widget),
+                                       gtk_widget_get_allocated_height (widget));
+
+  return TRUE;
+}
+
 
 void splash_show(char* image_name,int time,int width,int height)
 {
   GtkWidget  *image;
   splash_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_fullscreen(GTK_WINDOW(splash_window));
   gtk_widget_set_size_request(splash_window, width, height);
   gtk_window_set_decorated(GTK_WINDOW(splash_window), FALSE);
   gtk_window_set_position(GTK_WINDOW(splash_window),GTK_WIN_POS_CENTER_ALWAYS);
   gtk_window_set_resizable(GTK_WINDOW(splash_window), FALSE);
+
+
+  GtkWidget *grid = gtk_grid_new();
+  gtk_grid_set_row_homogeneous(GTK_GRID(grid),FALSE);
+  gtk_grid_set_column_homogeneous(GTK_GRID(grid),FALSE);
+
   image=gtk_image_new_from_file(image_name);
-  gtk_container_add(GTK_CONTAINER(splash_window), image);
+  //gtk_container_add(GTK_CONTAINER(splash_window), image);
+  gtk_grid_attach(GTK_GRID(grid), image, 0, 0, 1, 4);
+  g_signal_connect (splash_window,"configure-event",
+            G_CALLBACK (splash_configure_event_cb), NULL);
+
+  char build[64];
+  sprintf(build,"build: %s %s",build_date, build_time);
+
+  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("Arial 18"));
+  gtk_widget_show(status);
+  //gtk_container_add(GTK_CONTAINER(splash_window), status);
+  gtk_grid_attach(GTK_GRID(grid), status, 1, 3, 1, 1);
+
+  gtk_container_add(GTK_CONTAINER(splash_window), grid);
   gtk_widget_show_all (splash_window);
 }
+
+void splash_status(char *text) {
+  fprintf(stderr,"splash_status: %s\n",text);
+  gtk_label_set_text(GTK_LABEL(status),text);
+  usleep(50000);
+  while (gtk_events_pending ())
+    gtk_main_iteration ();
+}
index 5adb9efc696e0b413658aab0ce9ece3b5738fe0e..b3663057d78bbd7f12665e267d024fae13a7889b 100644 (file)
--- a/splash.h
+++ b/splash.h
@@ -1,5 +1,25 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
 
 extern GtkWidget* splash_window;
 
 void splash_close(void);
-void splash_show(char* image_name,int time,int width,int height);
+void splash_show(char *image_name,int time,int width,int height);
+void splash_status(char *text);
diff --git a/splash.png b/splash.png
deleted file mode 100644 (file)
index 4b249eb..0000000
Binary files a/splash.png and /dev/null differ
index 048ad04dd0e5894bb9277c965cfaff3353212938..95688c3925cc9110e38bad52c206e49885537548 100644 (file)
--- a/toolbar.c
+++ b/toolbar.c
@@ -1,3 +1,22 @@
+/* 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 "toolbar.h"
 #include "mode.h"
 #include "filter.h"
+#include "frequency.h"
 #include "bandstack.h"
 #include "band.h"
 #include "discovered.h"
 #include "new_protocol.h"
-#include "rotary_encoder.h"
 #include "vfo.h"
 #include "alex.h"
 #include "agc.h"
 static int width;
 static int height;
 
-static int column=0;
-
 static GtkWidget *parent_window;
+static GtkWidget *sliders;
 static GtkWidget *toolbar;
-static GtkWidget *toolbar_bottom;
-static GtkWidget *toolbar_top;
 
 static GtkWidget *last_band;
 static GtkWidget *last_mode;
 static GtkWidget *last_filter;
 
+#define NONE 0
+#define AF_GAIN 1
+#define MIC_GAIN 2
+#define AGC_GAIN 3
+#define DRIVE 4
+#define TUNE_DRIVE 5
+
+#define MIC_GAIN_FUDGE 25.0
+
+static gint scale_timer;
+static int scale_status=NONE;
+static GtkWidget *scale_dialog;
 static GtkWidget *af_gain_label;
-static GtkWidget *audio_scale;
+static GtkWidget *af_gain_scale;
 static GtkWidget *agc_gain_label;
 static GtkWidget *agc_scale;
 static GtkWidget *mic_gain_label;
-static GtkWidget *mic_scale;
+static GtkWidget *mic_gain_scale;
+static GtkWidget *drive_label;
 static GtkWidget *drive_scale;
+static GtkWidget *tune_label;
 static GtkWidget *tune_scale;
+static GtkWidget *dummy_label;
 
 static GdkRGBA white;
 static GdkRGBA gray;
@@ -57,17 +88,20 @@ static void band_select_cb(GtkWidget *widget, gpointer data) {
     last_band=widget;
     gtk_widget_override_background_color(last_band, GTK_STATE_NORMAL, &gray);
   }
-  setFrequency(entry->frequencyA);
   setMode(entry->mode);
   FILTER* band_filters=filters[entry->mode];
   FILTER* band_filter=&band_filters[entry->filter];
   setFilter(band_filter->low,band_filter->high);
+  setFrequency(entry->frequencyA);
 
   BAND *band=band_get_current_band();
   set_alex_rx_antenna(band->alexRxAntenna);
   set_alex_tx_antenna(band->alexTxAntenna);
   set_alex_attenuation(band->alexAttenuation);
+
   vfo_update(NULL);
+
+  setFrequency(entry->frequencyA);
 }
 
 static void band_cb(GtkWidget *widget, gpointer data) {
@@ -82,7 +116,7 @@ static void band_cb(GtkWidget *widget, gpointer data) {
     BAND* band=band_get_band(i);
     GtkWidget *b=gtk_button_new_with_label(band->title);
     gtk_widget_override_background_color(b, GTK_STATE_NORMAL, &white);
-    gtk_widget_override_font(b, pango_font_description_from_string("Arial 20"));
+    //gtk_widget_override_font(b, pango_font_description_from_string("Arial 20"));
     if(i==band_get_current()) {
       gtk_widget_override_background_color(b, GTK_STATE_NORMAL, &gray);
       last_band=b;
@@ -95,7 +129,7 @@ static void band_cb(GtkWidget *widget, gpointer data) {
   gtk_container_add(GTK_CONTAINER(content),grid);
 
   GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
-  gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 20"));
+  //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 20"));
   gtk_widget_show_all(dialog);
 
   g_signal_connect_swapped (dialog,
@@ -140,14 +174,14 @@ static void mode_cb(GtkWidget *widget, gpointer data) {
     } else {
       gtk_widget_override_background_color(b, GTK_STATE_NORMAL, &white);
     }
-    gtk_widget_override_font(b, pango_font_description_from_string("Arial 20"));
+    //gtk_widget_override_font(b, pango_font_description_from_string("Arial 20"));
     gtk_widget_show(b);
     gtk_grid_attach(GTK_GRID(grid),b,i%5,i/5,1,1);
     g_signal_connect(b,"pressed",G_CALLBACK(mode_select_cb),(gpointer *)i);
   }
   gtk_container_add(GTK_CONTAINER(content),grid);
   GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
-  gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 20"));
+  //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 20"));
   gtk_widget_show_all(dialog);
 
   g_signal_connect_swapped (dialog,
@@ -187,7 +221,7 @@ static void filter_cb(GtkWidget *widget, gpointer data) {
   for(i=0;i<FILTERS;i++) {
     FILTER* band_filter=&band_filters[i];
     GtkWidget *b=gtk_button_new_with_label(band_filters[i].title);
-    gtk_widget_override_font(b, pango_font_description_from_string("Arial 20"));
+    //gtk_widget_override_font(b, pango_font_description_from_string("Arial 20"));
     if(i==entry->filter) {
       gtk_widget_override_background_color(b, GTK_STATE_NORMAL, &gray);
       last_filter=b;
@@ -200,7 +234,7 @@ static void filter_cb(GtkWidget *widget, gpointer data) {
   }
   gtk_container_add(GTK_CONTAINER(content),grid);
   GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
-  gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 20"));
+  //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 20"));
   gtk_widget_show_all(dialog);
 
   g_signal_connect_swapped (dialog,
@@ -212,33 +246,129 @@ static void filter_cb(GtkWidget *widget, gpointer data) {
 
 }
 
+int scale_timeout_cb(gpointer data) {
+fprintf(stderr,"scale_timeout_cb\n");
+  gtk_widget_destroy(scale_dialog);
+  scale_status=NONE;
+  return FALSE;
+}
+
 static void agc_select_cb(GtkWidget *widget, gpointer data) {
   agc=(int)data;
   SetRXAAGCMode(CHANNEL_RX0, agc);
 }
 
 static void agcgain_value_changed_cb(GtkWidget *widget, gpointer data) {
-  agc_gain=gtk_range_get_value(GTK_RANGE(widget));
+  agc_gain=gtk_range_get_value(GTK_RANGE(agc_scale));
   SetRXAAGCTop(CHANNEL_RX0, agc_gain);
 }
 
 void set_agc_gain(double value) {
-    agc_gain=value;
+  agc_gain=value;
+  SetRXAAGCTop(CHANNEL_RX0, agc_gain);
+  if(display_sliders) {
     gtk_range_set_value (GTK_RANGE(agc_scale),agc_gain);
-    SetRXAAGCTop(CHANNEL_RX0, agc_gain);
+  } else {
+    if(scale_status!=AGC_GAIN) {
+      if(scale_status!=NONE) {
+        g_source_remove(scale_timer);
+        gtk_widget_destroy(scale_dialog);
+        scale_status=NONE;
+      }
+    }
+    if(scale_status==NONE) {
+      scale_status=AGC_GAIN;
+      scale_dialog=gtk_dialog_new_with_buttons("AGC Gain",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+      GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
+      agc_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 120.0, 1.00);
+      gtk_widget_set_size_request (agc_scale, 400, 30);
+      gtk_range_set_value (GTK_RANGE(agc_scale),agc_gain);
+      gtk_widget_show(agc_scale);
+      gtk_container_add(GTK_CONTAINER(content),agc_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(agc_scale),agc_gain);
+      scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
+    }
+  }
 }
 
 static void afgain_value_changed_cb(GtkWidget *widget, gpointer data) {
-    volume=gtk_range_get_value(GTK_RANGE(widget));
+    volume=gtk_range_get_value(GTK_RANGE(af_gain_scale))/100.0;
 }
 
 void set_af_gain(double value) {
-    volume=value;
-    gtk_range_set_value (GTK_RANGE(audio_scale),volume);
+  volume=value;
+  if(display_sliders) {
+    gtk_range_set_value (GTK_RANGE(af_gain_scale),volume*100.0);
+  } else {
+    if(scale_status!=AF_GAIN) {
+      if(scale_status!=NONE) {
+        g_source_remove(scale_timer);
+        gtk_widget_destroy(scale_dialog);
+        scale_status=NONE;
+      }
+    }
+    if(scale_status==NONE) {
+      scale_status=AF_GAIN;
+      scale_dialog=gtk_dialog_new_with_buttons("AF Gain",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+      GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
+      af_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 100.0, 1.00);
+      gtk_widget_set_size_request (af_gain_scale, 400, 30);
+      gtk_range_set_value (GTK_RANGE(af_gain_scale),volume*100.0);
+      gtk_widget_show(af_gain_scale);
+      gtk_container_add(GTK_CONTAINER(content),af_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(af_gain_scale),volume*100.0);
+      scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
+    }
+  }
 }
 
 static void micgain_value_changed_cb(GtkWidget *widget, gpointer data) {
-    mic_gain=gtk_range_get_value(GTK_RANGE(widget));
+    mic_gain=gtk_range_get_value(GTK_RANGE(widget))/MIC_GAIN_FUDGE;
+fprintf(stderr,"micgain_value_changed: %f\n",mic_gain);
+}
+
+void set_mic_gain(double value) {
+  mic_gain=value;
+fprintf(stderr,"set_mic_gain: %f\n",mic_gain);
+  if(display_sliders) {
+    gtk_range_set_value (GTK_RANGE(mic_gain_scale),mic_gain*MIC_GAIN_FUDGE);
+  } else {
+    if(scale_status!=MIC_GAIN) {
+      if(scale_status!=NONE) {
+        g_source_remove(scale_timer);
+        gtk_widget_destroy(scale_dialog);
+        scale_status=NONE;
+      }
+    }
+    if(scale_status==NONE) {
+      scale_status=MIC_GAIN;
+      scale_dialog=gtk_dialog_new_with_buttons("Mic Gain",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+      GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
+      mic_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 100.0, 1.00);
+      gtk_widget_set_size_request (mic_gain_scale, 400, 30);
+      gtk_range_set_value (GTK_RANGE(mic_gain_scale),mic_gain*MIC_GAIN_FUDGE);
+      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(mic_gain_scale),mic_gain*MIC_GAIN_FUDGE);
+      scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
+    }
+
+  }
 }
 
 static void nr_cb(GtkWidget *widget, gpointer data) {
@@ -261,50 +391,6 @@ static void snb_cb(GtkWidget *widget, gpointer data) {
   SetRXASNBARun(CHANNEL_RX0, snb);
 }
 
-static void linein_cb(GtkWidget *widget, gpointer data) {
-  if((orion_mic&0x01)==LINE_IN) {
-      orion_mic=orion_mic&0xFE;
-  } else {
-      orion_mic=orion_mic|LINE_IN;
-  }
-}
-
-static void micboost_cb(GtkWidget *widget, gpointer data) {
-  if((orion_mic&0x02)==MIC_BOOST) {
-      orion_mic=orion_mic&0xFD;
-  } else {
-      orion_mic=orion_mic|MIC_BOOST;
-  }
-}
-
-static void byteswap_cb(GtkWidget *widget, gpointer data) {
-  byte_swap=byte_swap?0:1;
-}
-
-static void ptt_cb(GtkWidget *widget, gpointer data) {
-  if((orion_mic&0x04)==ORION_MIC_PTT_ENABLED) {
-      orion_mic=orion_mic|ORION_MIC_PTT_DISABLED;
-  } else {
-      orion_mic=orion_mic&0xFB;
-  }
-}
-
-static void ptt_ring_cb(GtkWidget *widget, gpointer data) {
-  if((orion_mic&0x08)==ORION_MIC_PTT_RING_BIAS_TIP) {
-      orion_mic=orion_mic|ORION_MIC_PTT_TIP_BIAS_RING;
-  } else {
-      orion_mic=orion_mic&0xF7;
-  }
-}
-
-static void bias_cb(GtkWidget *widget, gpointer data) {
-  if((orion_mic&0x10)==ORION_MIC_BIAS_DISABLED) {
-      orion_mic=orion_mic|ORION_MIC_BIAS_ENABLED;
-  } else {
-      orion_mic=orion_mic&0xEF;
-  }
-}
-
 static void audio_cb(GtkWidget *widget, gpointer data) {
   GtkWidget *dialog=gtk_dialog_new_with_buttons("Audio",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
 
@@ -315,35 +401,35 @@ static void audio_cb(GtkWidget *widget, gpointer data) {
   gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
 
   GtkWidget *b_off=gtk_radio_button_new_with_label(NULL,"Off"); 
-  gtk_widget_override_font(b_off, pango_font_description_from_string("Arial 18"));
+  //gtk_widget_override_font(b_off, pango_font_description_from_string("Arial 16"));
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_off), agc==AGC_OFF);
   gtk_widget_show(b_off);
   gtk_grid_attach(GTK_GRID(grid),b_off,0,0,2,1);
   g_signal_connect(b_off,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_OFF);
 
   GtkWidget *b_long=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_off),"Long"); 
-  gtk_widget_override_font(b_long, pango_font_description_from_string("Arial 18"));
+  //gtk_widget_override_font(b_long, pango_font_description_from_string("Arial 16"));
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_long), agc==AGC_LONG);
   gtk_widget_show(b_long);
   gtk_grid_attach(GTK_GRID(grid),b_long,0,1,2,1);
   g_signal_connect(b_long,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_LONG);
 
   GtkWidget *b_slow=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_long),"Slow"); 
-  gtk_widget_override_font(b_slow, pango_font_description_from_string("Arial 18"));
+  //gtk_widget_override_font(b_slow, pango_font_description_from_string("Arial 16"));
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_slow), agc==AGC_SLOW);
   gtk_widget_show(b_slow);
   gtk_grid_attach(GTK_GRID(grid),b_slow,0,2,2,1);
   g_signal_connect(b_slow,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_SLOW);
 
   GtkWidget *b_medium=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_slow),"Medium"); 
-  gtk_widget_override_font(b_medium, pango_font_description_from_string("Arial 18"));
+  //gtk_widget_override_font(b_medium, pango_font_description_from_string("Arial 16"));
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_medium), agc==AGC_MEDIUM);
   gtk_widget_show(b_medium);
   gtk_grid_attach(GTK_GRID(grid),b_medium,0,3,2,1);
   g_signal_connect(b_medium,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_MEDIUM);
 
   GtkWidget *b_fast=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_medium),"Fast"); 
-  gtk_widget_override_font(b_fast, pango_font_description_from_string("Arial 18"));
+  //gtk_widget_override_font(b_fast, pango_font_description_from_string("Arial 16"));
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_fast), agc==AGC_FAST);
   gtk_widget_show(b_fast);
   gtk_grid_attach(GTK_GRID(grid),b_fast,0,4,2,1);
@@ -351,28 +437,28 @@ static void audio_cb(GtkWidget *widget, gpointer data) {
 
 
   GtkWidget *b_nr=gtk_check_button_new_with_label("NR");
-  gtk_widget_override_font(b_nr, pango_font_description_from_string("Arial 18"));
+  //gtk_widget_override_font(b_nr, pango_font_description_from_string("Arial 16"));
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr), nr==1);
   gtk_widget_show(b_nr);
   gtk_grid_attach(GTK_GRID(grid),b_nr,2,0,2,1);
   g_signal_connect(b_nr,"toggled",G_CALLBACK(nr_cb),NULL);
 
   GtkWidget *b_nb=gtk_check_button_new_with_label("NB");
-  gtk_widget_override_font(b_nb, pango_font_description_from_string("Arial 18"));
+  //gtk_widget_override_font(b_nb, pango_font_description_from_string("Arial 16"));
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nb), nb==1);
   gtk_widget_show(b_nb);
   gtk_grid_attach(GTK_GRID(grid),b_nb,2,1,2,1);
   g_signal_connect(b_nb,"toggled",G_CALLBACK(nb_cb),NULL);
 
   GtkWidget *b_anf=gtk_check_button_new_with_label("ANF");
-  gtk_widget_override_font(b_anf, pango_font_description_from_string("Arial 18"));
+  //gtk_widget_override_font(b_anf, pango_font_description_from_string("Arial 16"));
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_anf), anf==1);
   gtk_widget_show(b_anf);
   gtk_grid_attach(GTK_GRID(grid),b_anf,2,2,2,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 18"));
+  GtkWidget *b_snb=gtk_check_button_new_with_label("NR2");
+  //gtk_widget_override_font(b_snb, pango_font_description_from_string("Arial 16"));
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_snb), snb==1);
   gtk_widget_show(b_snb);
   gtk_grid_attach(GTK_GRID(grid),b_snb,2,3,2,1);
@@ -380,7 +466,7 @@ static void audio_cb(GtkWidget *widget, gpointer data) {
 
   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_override_font(close_button, pango_font_description_from_string("Arial 16"));
   gtk_widget_show_all(dialog);
 
   g_signal_connect_swapped (dialog,
@@ -394,29 +480,92 @@ static void audio_cb(GtkWidget *widget, gpointer data) {
 
 void set_drive(double value) {
   setDrive(value);
-  gtk_range_set_value (GTK_RANGE(drive_scale),value);
+  if(display_sliders) {
+    gtk_range_set_value (GTK_RANGE(drive_scale),value*100.0);
+  } else {
+    if(scale_status!=DRIVE) {
+      if(scale_status!=NONE) {
+        g_source_remove(scale_timer);
+        gtk_widget_destroy(scale_dialog);
+        scale_status=NONE;
+      }
+    }
+    if(scale_status==NONE) {
+      scale_status=DRIVE;
+      scale_dialog=gtk_dialog_new_with_buttons("Drive",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+      GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
+      drive_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 100.0, 1.00);
+      gtk_widget_set_size_request (drive_scale, 400, 30);
+      gtk_range_set_value (GTK_RANGE(drive_scale),value*100.0);
+      gtk_widget_show(drive_scale);
+      gtk_container_add(GTK_CONTAINER(content),drive_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(drive_scale),value*100.0);
+      scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
+    }
+  }
 }
 
 static void drive_value_changed_cb(GtkWidget *widget, gpointer data) {
-  setDrive(gtk_range_get_value(GTK_RANGE(widget)));
+  setDrive(gtk_range_get_value(GTK_RANGE(drive_scale))/100.0);
 }
 
 void set_tune(double value) {
   setTuneDrive(value);
-  gtk_range_set_value (GTK_RANGE(tune_scale),value);
+  if(display_sliders) {
+    gtk_range_set_value (GTK_RANGE(tune_scale),value*100.0);
+  } else {
+    if(scale_status!=TUNE_DRIVE) {
+      if(scale_status!=NONE) {
+        g_source_remove(scale_timer);
+        gtk_widget_destroy(scale_dialog);
+        scale_status=NONE;
+      }
+    }
+    if(scale_status==NONE) {
+      scale_status=TUNE_DRIVE;
+      scale_dialog=gtk_dialog_new_with_buttons("Tune Drive",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+      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*100.0);
+      gtk_widget_show(tune_scale);
+      gtk_container_add(GTK_CONTAINER(content),tune_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*100.0);
+      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(widget)));
+  setTuneDrive(gtk_range_get_value(GTK_RANGE(tune_scale))/100.0);
+}
+
+static void stop() {
+  if(protocol==ORIGINAL_PROTOCOL) {
+    old_protocol_stop();
+  } else {
+    new_protocol_stop();
+  }
+  gpio_close();
 }
 
 static void yes_cb(GtkWidget *widget, gpointer data) {
-  encoder_close();
+  stop();
   _exit(0);
 }
 
 static void halt_cb(GtkWidget *widget, gpointer data) {
-  encoder_close();
+  stop();
   system("shutdown -h -P now");
   _exit(0);
 }
@@ -424,9 +573,8 @@ static void halt_cb(GtkWidget *widget, gpointer data) {
 static void exit_cb(GtkWidget *widget, gpointer data) {
 
   radioSaveState();
-  saveProperties(property_path);
 
-  GtkWidget *dialog=gtk_dialog_new_with_buttons("Audio",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+  GtkWidget *dialog=gtk_dialog_new_with_buttons("Exit",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();
@@ -435,25 +583,25 @@ static void exit_cb(GtkWidget *widget, gpointer data) {
   gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
 
   GtkWidget *label=gtk_label_new("Exit?");
-  gtk_widget_override_font(label, pango_font_description_from_string("Arial 18"));
+  //gtk_widget_override_font(label, pango_font_description_from_string("Arial 18"));
   gtk_widget_show(label);
   gtk_grid_attach(GTK_GRID(grid),label,1,0,1,1);
 
-  GtkWidget *b_yes=gtk_button_new_with_label("Yes (to CLI)");
-  gtk_widget_override_font(b_yes, pango_font_description_from_string("Arial 18"));
+  GtkWidget *b_yes=gtk_button_new_with_label("Yes");
+  //gtk_widget_override_font(b_yes, pango_font_description_from_string("Arial 18"));
   gtk_widget_show(b_yes);
   gtk_grid_attach(GTK_GRID(grid),b_yes,0,1,1,1);
   g_signal_connect(b_yes,"pressed",G_CALLBACK(yes_cb),NULL);
 
   GtkWidget *b_halt=gtk_button_new_with_label("Halt System");
-  gtk_widget_override_font(b_halt, pango_font_description_from_string("Arial 18"));
+  //gtk_widget_override_font(b_halt, pango_font_description_from_string("Arial 18"));
   gtk_widget_show(b_halt);
   gtk_grid_attach(GTK_GRID(grid),b_halt,2,1,1,1);
   g_signal_connect(b_halt,"pressed",G_CALLBACK(halt_cb),NULL);
 
   gtk_container_add(GTK_CONTAINER(content),grid);
   GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Cancel",GTK_RESPONSE_OK);
-  gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 18"));
+  //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 18"));
   gtk_widget_show_all(dialog);
 
   g_signal_connect_swapped (dialog,
@@ -465,52 +613,6 @@ static void exit_cb(GtkWidget *widget, gpointer data) {
 
 }
 
-static void apollo_cb(GtkWidget *widget, gpointer data);
-
-static void alex_cb(GtkWidget *widget, gpointer data) {
-fprintf(stderr,"alex_cb\n");
-  if(filter_board==ALEX) {
-fprintf(stderr,"alex_cb: was ALEX setting NONE\n");
-    filter_board=NONE;
-  } else if(filter_board==NONE) {
-fprintf(stderr,"alex_cb: was NONE setting ALEX\n");
-    filter_board=ALEX;
-  } else if(filter_board==APOLLO) {
-fprintf(stderr,"alex_cb: was APOLLO setting ALEX\n");
-    GtkWidget *w=(GtkWidget *)data;
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), FALSE);
-    filter_board=ALEX;
-  }
-  filter_board_changed();
-}
-
-static void apollo_cb(GtkWidget *widget, gpointer data) {
-fprintf(stderr,"apollo_cb\n");
-  if(filter_board==APOLLO) {
-fprintf(stderr,"apollo_cb: was APOLLO setting NONE\n");
-    filter_board=NONE;
-  } else if(filter_board==NONE) {
-fprintf(stderr,"apollo_cb: was NONE setting APOLLO\n");
-    filter_board=APOLLO;
-  } else if(filter_board==ALEX) {
-fprintf(stderr,"apollo_cb: was ALEX setting APOLLO\n");
-    GtkWidget *w=(GtkWidget *)data;
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), FALSE);
-    filter_board=APOLLO;
-  }
-  filter_board_changed();
-}
-
-static void apollo_tuner_cb(GtkWidget *widget, gpointer data) {
-  apollo_tuner=apollo_tuner==1?0:1;
-  tuner_changed();
-}
-
-static void pa_cb(GtkWidget *widget, gpointer data) {
-  pa=pa==1?0:1;
-  pa_changed();
-}
-
 static void cw_keyer_internal_cb(GtkWidget *widget, gpointer data) {
   cw_keyer_internal=cw_keyer_internal==1?0:1;
   cw_changed();
@@ -541,6 +643,30 @@ static void cw_keyer_mode_cb(GtkWidget *widget, gpointer 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));
@@ -548,83 +674,92 @@ static void config_cb(GtkWidget *widget, gpointer data) {
   gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
   gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
 
-  GtkWidget *linein_b=gtk_check_button_new_with_label("Line In");
-  gtk_widget_override_font(linein_b, pango_font_description_from_string("Arial 18"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (linein_b), (orion_mic&0x01)==LINE_IN);
-  gtk_widget_show(linein_b);
-  gtk_grid_attach(GTK_GRID(grid),linein_b,0,0,1,1);
-  g_signal_connect(linein_b,"toggled",G_CALLBACK(linein_cb),NULL);
-
-  GtkWidget *micboost_b=gtk_check_button_new_with_label("Boost");
-  gtk_widget_override_font(micboost_b, pango_font_description_from_string("Arial 18"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (micboost_b), (orion_mic&0x02)==MIC_BOOST);
-  gtk_widget_show(micboost_b);
-  gtk_grid_attach(GTK_GRID(grid),micboost_b,0,1,1,1);
-  g_signal_connect(micboost_b,"toggled",G_CALLBACK(micboost_cb),NULL);
-
-  GtkWidget *byteswap_b=gtk_check_button_new_with_label("Byte swap");
-  gtk_widget_override_font(byteswap_b, pango_font_description_from_string("Arial 18"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (byteswap_b), byte_swap);
-  gtk_widget_show(byteswap_b);
-  gtk_grid_attach(GTK_GRID(grid),byteswap_b,0,2,1,1);
-  g_signal_connect(byteswap_b,"toggled",G_CALLBACK(byteswap_cb),NULL);
-
-  DISCOVERED* d=&discovered[selected_device];
-  if(d->device==NEW_DEVICE_ORION) {
-    GtkWidget *ptt_b=gtk_check_button_new_with_label("PTT Enabled");
-    gtk_widget_override_font(ptt_b, pango_font_description_from_string("Arial 18"));
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptt_b), (orion_mic&0x04)==ORION_MIC_PTT_ENABLED);
-    gtk_widget_show(ptt_b);
-    gtk_grid_attach(GTK_GRID(grid),ptt_b,0,3,1,1);
-    g_signal_connect(ptt_b,"toggled",G_CALLBACK(ptt_cb),NULL);
-
-    GtkWidget *ptt_ring_b=gtk_check_button_new_with_label("PTT On Ring");
-    gtk_widget_override_font(ptt_ring_b, pango_font_description_from_string("Arial 18"));
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptt_ring_b), (orion_mic&0x08)==ORION_MIC_PTT_RING_BIAS_TIP);
-    gtk_widget_show(ptt_ring_b);
-    gtk_grid_attach(GTK_GRID(grid),ptt_ring_b,0,4,1,1);
-    g_signal_connect(ptt_ring_b,"toggled",G_CALLBACK(ptt_ring_cb),NULL);
-
-    GtkWidget *bias_b=gtk_check_button_new_with_label("BIAS Enabled");
-    gtk_widget_override_font(bias_b, pango_font_description_from_string("Arial 18"));
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bias_b), (orion_mic&0x10)==ORION_MIC_BIAS_ENABLED);
-    gtk_widget_show(bias_b);
-    gtk_grid_attach(GTK_GRID(grid),bias_b,0,5,1,1);
-    g_signal_connect(bias_b,"toggled",G_CALLBACK(bias_cb),NULL);
-  }
-
-  GtkWidget *alex_b=gtk_check_button_new_with_label("ALEX");
-  gtk_widget_override_font(alex_b, pango_font_description_from_string("Arial 18"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (alex_b), filter_board==ALEX);
-  gtk_widget_show(alex_b);
-  gtk_grid_attach(GTK_GRID(grid),alex_b,1,0,1,1);
-
-  GtkWidget *apollo_b=gtk_check_button_new_with_label("APOLLO");
-  gtk_widget_override_font(apollo_b, pango_font_description_from_string("Arial 18"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (apollo_b), filter_board==APOLLO);
-  gtk_widget_show(apollo_b);
-  gtk_grid_attach(GTK_GRID(grid),apollo_b,1,1,1,1);
-
-  g_signal_connect(alex_b,"toggled",G_CALLBACK(alex_cb),apollo_b);
-  g_signal_connect(apollo_b,"toggled",G_CALLBACK(apollo_cb),alex_b);
-
-  GtkWidget *apollo_tuner_b=gtk_check_button_new_with_label("Auto Tuner");
-  gtk_widget_override_font(apollo_tuner_b, pango_font_description_from_string("Arial 18"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (apollo_tuner_b), apollo_tuner);
-  gtk_widget_show(apollo_tuner_b);
-  gtk_grid_attach(GTK_GRID(grid),apollo_tuner_b,1,2,1,1);
-  g_signal_connect(apollo_tuner_b,"toggled",G_CALLBACK(apollo_tuner_cb),NULL);
-
-  GtkWidget *pa_b=gtk_check_button_new_with_label("PA");
-  gtk_widget_override_font(pa_b, pango_font_description_from_string("Arial 18"));
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pa_b), pa);
-  gtk_widget_show(pa_b);
-  gtk_grid_attach(GTK_GRID(grid),pa_b,1,3,1,1);
-  g_signal_connect(pa_b,"toggled",G_CALLBACK(pa_cb),NULL);
+  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_override_font(close_button, pango_font_description_from_string("Arial 18"));
   gtk_widget_show_all(dialog);
 
   g_signal_connect_swapped (dialog,
@@ -644,67 +779,57 @@ static void cw_cb(GtkWidget *widget, gpointer data) {
 
 
   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_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_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_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_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_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_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_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);
 
-/*
-int cw_keyer_speed=12; // 1-60 WPM
-int cw_keyer_weight=30; // 0-100
-int cw_keyer_spacing=0; // 0=on 1=off
-int cw_keyer_sidetone_volume=127; // 0-127
-int cw_keyer_ptt_delay=20; // 0-255ms
-int cw_keyer_hang_time=10; // ms
-int cw_keyer_sidetone_frequency=400; // Hz
-*/
-
   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_override_font(close_button, pango_font_description_from_string("Arial 18"));
   gtk_widget_show_all(dialog);
 
   g_signal_connect_swapped (dialog,
@@ -715,86 +840,42 @@ int cw_keyer_sidetone_frequency=400; // Hz
   int result=gtk_dialog_run(GTK_DIALOG(dialog));
 }
 
+/*
 static void adc_cb(GtkWidget *widget, gpointer data) {
   int adc0=adc[0];
   adc[0]=adc[1];
   adc[1]=adc0;
 
   char label[16];
-  gtk_grid_remove_row(GTK_GRID(toolbar_top),0);
+  gtk_grid_remove_row(GTK_GRID(toolbar_top_1),0);
   
   sprintf(label,"RX0=%d",adc[0]);
   GtkWidget *rx0=gtk_label_new(label);
-  gtk_widget_override_font(rx0, pango_font_description_from_string("Arial 16"));
+  //gtk_widget_override_font(rx0, pango_font_description_from_string("Arial 16"));
   gtk_widget_show(rx0);
-  gtk_grid_attach(GTK_GRID(toolbar_top),rx0,0,0,1,1);
+  gtk_grid_attach(GTK_GRID(toolbar_top_1),rx0,0,0,1,1);
   
   sprintf(label,"RX1=%d",adc[1]);
   GtkWidget *rx1=gtk_label_new(label);
-  gtk_widget_override_font(rx1, pango_font_description_from_string("Arial 16"));
+  //gtk_widget_override_font(rx1, pango_font_description_from_string("Arial 16"));
   gtk_widget_show(rx1);
-  gtk_grid_attach(GTK_GRID(toolbar_top),rx1,1,0,1,1);
+  gtk_grid_attach(GTK_GRID(toolbar_top_1),rx1,1,0,1,1);
 }
+*/
 
-static void lock_cb(GtkWidget *widget, gpointer data) {
+void lock_cb(GtkWidget *widget, gpointer data) {
   locked=locked==1?0:1;
   vfo_update(NULL);
 }
 
-static void mox_cb(GtkWidget *widget, gpointer data) {
-  gtk_grid_remove_row (GTK_GRID(toolbar_top),0);
+void mox_cb(GtkWidget *widget, gpointer data) {
   if(getTune()==1) {
     setTune(0);
   }
-  setMox(getMox()==0?1:0);
-  vfo_update(NULL);
-  if(getMox()) {
-    mic_gain_label=gtk_label_new("Mic Gain:");
-    gtk_widget_override_font(mic_gain_label, pango_font_description_from_string("Arial 18"));
-    gtk_widget_show(mic_gain_label);
-    gtk_grid_attach(GTK_GRID(toolbar_top),mic_gain_label,0,0,1,1);
-
-    mic_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 1.0, 0.01);
-    gtk_range_set_value (GTK_RANGE(mic_scale),mic_gain);
-    gtk_widget_show(mic_scale);
-    gtk_grid_attach(GTK_GRID(toolbar_top),mic_scale,1,0,2,1);
-    g_signal_connect(G_OBJECT(mic_scale),"value_changed",G_CALLBACK(micgain_value_changed_cb),NULL);
-
-    GtkWidget *drive_label=gtk_label_new("Drive:");
-    gtk_widget_override_font(drive_label, pango_font_description_from_string("Arial 18"));
-    gtk_widget_show(drive_label);
-    gtk_grid_attach(GTK_GRID(toolbar_top),drive_label,3,0,1,1);
-
-    drive_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 1.0, 0.01);
-    gtk_range_set_value (GTK_RANGE(drive_scale),getDrive());
-    gtk_widget_show(drive_scale);
-    gtk_grid_attach(GTK_GRID(toolbar_top),drive_scale,4,0,2,1);
-    g_signal_connect(G_OBJECT(drive_scale),"value_changed",G_CALLBACK(drive_value_changed_cb),NULL);
-  } else {
-    af_gain_label=gtk_label_new("AF:");
-    gtk_widget_override_font(af_gain_label, pango_font_description_from_string("Arial 18"));
-    gtk_widget_show(af_gain_label);
-    gtk_grid_attach(GTK_GRID(toolbar_top),af_gain_label,0,0,1,1);
-  
-    audio_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 1.0, 0.01);
-    gtk_range_set_value (GTK_RANGE(audio_scale),volume);
-    gtk_widget_show(audio_scale);
-    gtk_grid_attach(GTK_GRID(toolbar_top),audio_scale,1,0,2,1);
-    g_signal_connect(G_OBJECT(audio_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 18"));
-    gtk_widget_show(agc_gain_label);
-    gtk_grid_attach(GTK_GRID(toolbar_top),agc_gain_label,3,0,1,1);
-
-    agc_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 120.0, 1.0);
-    gtk_range_set_value (GTK_RANGE(agc_scale),agc_gain);
-    gtk_widget_show(agc_scale);
-    gtk_grid_attach(GTK_GRID(toolbar_top),agc_scale,4,0,2,1);
-    g_signal_connect(G_OBJECT(agc_scale),"value_changed",G_CALLBACK(agcgain_value_changed_cb),NULL);
-
+  if(canTransmit() || tx_out_of_band) {
+    setMox(getMox()==0?1:0);
+    vfo_update(NULL);
   }
-  //gtk_widget_queue_draw(toolbar_top);
 }
 
 int ptt_update(void *data) {
@@ -811,54 +892,101 @@ int ptt_update(void *data) {
   return 0;
 }
 
-static void tune_cb(GtkWidget *widget, gpointer data) {
-  gtk_grid_remove_row (GTK_GRID(toolbar_top),0);
+void tune_cb(GtkWidget *widget, gpointer data) {
   if(getMox()==1) {
     setMox(0);
   }
-  setTune(getTune()==0?1:0);
-  vfo_update(NULL);
-  if(getTune()) {
-    GtkWidget *tune_label=gtk_label_new("Tune Drive:");
-    gtk_widget_override_font(tune_label, pango_font_description_from_string("Arial 18"));
-    gtk_widget_show(tune_label);
-    gtk_grid_attach(GTK_GRID(toolbar_top),tune_label,0,0,1,1);
-
-    tune_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 1.0, 0.01);
-    gtk_range_set_value (GTK_RANGE(tune_scale),getTuneDrive());
-    gtk_widget_show(tune_scale);
-    gtk_grid_attach(GTK_GRID(toolbar_top),tune_scale,1,0,2,1);
-    g_signal_connect(G_OBJECT(tune_scale),"value_changed",G_CALLBACK(tune_value_changed_cb),NULL);
-  } else {
-    af_gain_label=gtk_label_new("AF:");
-    gtk_widget_override_font(af_gain_label, pango_font_description_from_string("Arial 18"));
-    gtk_widget_show(af_gain_label);
-    gtk_grid_attach(GTK_GRID(toolbar_top),af_gain_label,0,0,1,1);
-
-    audio_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 1.0, 0.01);
-    gtk_range_set_value (GTK_RANGE(audio_scale),volume);
-    gtk_widget_show(audio_scale);
-    gtk_grid_attach(GTK_GRID(toolbar_top),audio_scale,1,0,2,1);
-    g_signal_connect(G_OBJECT(audio_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 18"));
-    gtk_widget_show(agc_gain_label);
-    gtk_grid_attach(GTK_GRID(toolbar_top),agc_gain_label,3,0,1,1);
-
-    agc_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 120.0, 1.0);
-    gtk_range_set_value (GTK_RANGE(agc_scale),agc_gain);
-    gtk_widget_show(agc_scale);
-    gtk_grid_attach(GTK_GRID(toolbar_top),agc_scale,4,0,2,1);
-    g_signal_connect(G_OBJECT(agc_scale),"value_changed",G_CALLBACK(agcgain_value_changed_cb),NULL);
+  if(canTransmit() || tx_out_of_band) {
+    setTune(getTune()==0?1:0);
+    vfo_update(NULL);
   }
 }
 
+GtkWidget *sliders_init(int my_width, int my_height, GtkWidget* parent) {
+    width=my_width;
+    height=my_height;
+    parent_window=parent;
+
+    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);
+
+  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);
+
+  af_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 100.0, 1.00);
+  gtk_range_set_value (GTK_RANGE(af_gain_scale),volume*100.0);
+  gtk_widget_show(af_gain_scale);
+  gtk_grid_attach(GTK_GRID(sliders),af_gain_scale,1,0,2,1);
+  g_signal_connect(G_OBJECT(af_gain_scale),"value_changed",G_CALLBACK(afgain_value_changed_cb),NULL);
+
+  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);
+
+  agc_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 120.0, 1.0);
+  gtk_range_set_value (GTK_RANGE(agc_scale),agc_gain);
+  gtk_widget_show(agc_scale);
+  gtk_grid_attach(GTK_GRID(sliders),agc_scale,4,0,2,1);
+  g_signal_connect(G_OBJECT(agc_scale),"value_changed",G_CALLBACK(agcgain_value_changed_cb),NULL);
+
+
+  mic_gain_label=gtk_label_new("Mic:");
+  //gtk_widget_override_font(mic_gain_label, pango_font_description_from_string("Arial 16"));
+  gtk_widget_show(mic_gain_label);
+  gtk_grid_attach(GTK_GRID(sliders),mic_gain_label,0,1,1,1);
+
+  mic_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 100.0, 1.0);
+  gtk_range_set_value (GTK_RANGE(mic_gain_scale),mic_gain*MIC_GAIN_FUDGE);
+  gtk_widget_show(mic_gain_scale);
+  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);
+
+  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);
+  gtk_range_set_value (GTK_RANGE(drive_scale),getDrive()*100.0);
+  gtk_widget_show(drive_scale);
+  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()*100.0);
+  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);
+
+  return sliders;
+}
+
 GtkWidget *toolbar_init(int my_width, int my_height, GtkWidget* parent) {
     width=my_width;
     height=my_height;
     parent_window=parent;
 
+    int button_width=width/8;
+
+    fprintf(stderr,"toolbar_init: width=%d height=%d button_width=%d\n", width,height,button_width);
+
     white.red=1.0;
     white.green=1.0;
     white.blue=1.0;
@@ -871,137 +999,40 @@ GtkWidget *toolbar_init(int my_width, int my_height, GtkWidget* parent) {
 
     toolbar=gtk_grid_new();
     gtk_widget_set_size_request (toolbar, width, height);
-    gtk_grid_set_row_homogeneous(GTK_GRID(toolbar), TRUE);
+    gtk_grid_set_column_homogeneous(GTK_GRID(toolbar),TRUE);
 
-    toolbar_top=gtk_grid_new();
-    gtk_grid_set_column_homogeneous(GTK_GRID(toolbar_top),TRUE);
-
-    toolbar_bottom=gtk_grid_new();
-    gtk_grid_set_column_homogeneous(GTK_GRID(toolbar_bottom),FALSE);
-    
     GtkWidget *band=gtk_button_new_with_label("Band");
-    gtk_widget_override_font(band, pango_font_description_from_string("Arial 20"));
+    gtk_widget_set_size_request (band, button_width, 0);
+    //gtk_widget_override_font(band, pango_font_description_from_string("Arial 16"));
     g_signal_connect(G_OBJECT(band),"clicked",G_CALLBACK(band_cb),NULL);
-    gtk_widget_show(band);
-    gtk_grid_attach(GTK_GRID(toolbar_bottom),band,column,0,1,1);
-    column++;
+    gtk_grid_attach(GTK_GRID(toolbar),band,0,0,4,1);
 
     GtkWidget *mode=gtk_button_new_with_label("Mode");
-    gtk_widget_override_font(mode, pango_font_description_from_string("Arial 20"));
+    //gtk_widget_override_font(mode, pango_font_description_from_string("Arial 16"));
     g_signal_connect(G_OBJECT(mode),"clicked",G_CALLBACK(mode_cb),NULL);
-    gtk_widget_show(mode);
-    gtk_grid_attach(GTK_GRID(toolbar_bottom),mode,column,0,1,1);
-    column++;
+    gtk_grid_attach(GTK_GRID(toolbar),mode,4,0,4,1);
 
     GtkWidget *filter=gtk_button_new_with_label("Filter");
-    gtk_widget_override_font(filter, pango_font_description_from_string("Arial 20"));
+    //gtk_widget_override_font(filter, pango_font_description_from_string("Arial 16"));
     g_signal_connect(G_OBJECT(filter),"clicked",G_CALLBACK(filter_cb),NULL);
-    gtk_widget_show(filter);
-    gtk_grid_attach(GTK_GRID(toolbar_bottom),filter,column,0,1,1);
-    column++;
-
-    GtkWidget *audio=gtk_button_new_with_label("Audio");
-    gtk_widget_override_font(audio, pango_font_description_from_string("Arial 20"));
-    g_signal_connect(G_OBJECT(audio),"clicked",G_CALLBACK(audio_cb),NULL);
-    gtk_widget_show(audio);
-    gtk_grid_attach(GTK_GRID(toolbar_bottom),audio,column,0,1,1);
-    column++;
-
-    GtkWidget *config=gtk_button_new_with_label("Config");
-    gtk_widget_override_font(config, pango_font_description_from_string("Arial 20"));
-    g_signal_connect(G_OBJECT(config),"clicked",G_CALLBACK(config_cb),NULL);
-    gtk_widget_show(config);
-    gtk_grid_attach(GTK_GRID(toolbar_bottom),config,column,0,1,1);
-    column++;
-
-    GtkWidget *cw=gtk_button_new_with_label("CW");
-    gtk_widget_override_font(cw, pango_font_description_from_string("Arial 20"));
-    g_signal_connect(G_OBJECT(cw),"clicked",G_CALLBACK(cw_cb),NULL);
-    gtk_widget_show(cw);
-    gtk_grid_attach(GTK_GRID(toolbar_bottom),cw,column,0,1,1);
-    column++;
-
-    GtkWidget *exit=gtk_button_new_with_label("Exit");
-    gtk_widget_override_font(exit, pango_font_description_from_string("Arial 20"));
-    g_signal_connect(G_OBJECT(exit),"clicked",G_CALLBACK(exit_cb),NULL);
-    gtk_widget_show(exit);
-    gtk_grid_attach(GTK_GRID(toolbar_bottom),exit,column,0,1,1);
-    column++;
+    gtk_grid_attach(GTK_GRID(toolbar),filter,8,0,4,1);
 
     GtkWidget *lock=gtk_button_new_with_label("Lock");
-    gtk_widget_override_font(lock, pango_font_description_from_string("Arial 20"));
+    //gtk_widget_override_font(lock, pango_font_description_from_string("Arial 16"));
     g_signal_connect(G_OBJECT(lock),"clicked",G_CALLBACK(lock_cb),NULL);
-    gtk_widget_show(lock);
-    gtk_grid_attach(GTK_GRID(toolbar_bottom),lock,column,0,1,1);
-    column++;
+    gtk_grid_attach(GTK_GRID(toolbar),lock,16,0,4,1);
 
     GtkWidget *tune=gtk_button_new_with_label("Tune");
-    gtk_widget_override_font(tune, pango_font_description_from_string("Arial 20"));
+    //gtk_widget_override_font(tune, pango_font_description_from_string("Arial 16"));
     g_signal_connect(G_OBJECT(tune),"clicked",G_CALLBACK(tune_cb),NULL);
-    gtk_widget_show(tune);
-    gtk_grid_attach(GTK_GRID(toolbar_bottom),tune,column,0,1,1);
-    column++;
+    gtk_grid_attach(GTK_GRID(toolbar),tune,24,0,4,1);
 
     GtkWidget *tx=gtk_button_new_with_label("Mox");
-    gtk_widget_override_font(tx, pango_font_description_from_string("Arial 20"));
+    //gtk_widget_override_font(tx, pango_font_description_from_string("Arial 16"));
     g_signal_connect(G_OBJECT(tx),"clicked",G_CALLBACK(mox_cb),NULL);
-    gtk_widget_show(tx);
-    gtk_grid_attach(GTK_GRID(toolbar_bottom),tx,column,0,1,1);
-    column++;
-
-
-  // default to receive controls on top bar
-  af_gain_label=gtk_label_new("AF:");
-  gtk_widget_override_font(af_gain_label, pango_font_description_from_string("Arial 18"));
-  gtk_widget_show(af_gain_label);
-  gtk_grid_attach(GTK_GRID(toolbar_top),af_gain_label,0,0,1,1);
-
-  audio_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 1.0, 0.01);
-  gtk_range_set_value (GTK_RANGE(audio_scale),volume);
-  gtk_widget_show(audio_scale);
-  gtk_grid_attach(GTK_GRID(toolbar_top),audio_scale,1,0,2,1);
-  g_signal_connect(G_OBJECT(audio_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 18"));
-  gtk_widget_show(agc_gain_label);
-  gtk_grid_attach(GTK_GRID(toolbar_top),agc_gain_label,3,0,1,1);
-
-  agc_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 120.0, 1.0);
-  gtk_range_set_value (GTK_RANGE(agc_scale),agc_gain);
-  gtk_widget_show(agc_scale);
-  gtk_grid_attach(GTK_GRID(toolbar_top),agc_scale,4,0,2,1);
-  g_signal_connect(G_OBJECT(agc_scale),"value_changed",G_CALLBACK(agcgain_value_changed_cb),NULL);
-
-/*
-
-  GtkWidget *drive_label=gtk_label_new("Drive:");
-  gtk_widget_override_font(drive_label, pango_font_description_from_string("Arial 18"));
-  gtk_widget_show(drive_label);
-  gtk_grid_attach(toolbar_top,drive_label,6,0,1,1);
-
-  drive_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 1.0, 0.01);
-  gtk_range_set_value (drive_scale,getTuneDrive());
-  gtk_widget_show(drive_scale);
-  gtk_grid_attach(toolbar_top,drive_scale,7,0,2,1);
-  g_signal_connect(G_OBJECT(drive_scale),"value_changed",G_CALLBACK(drive_value_changed_cb),NULL);
-
-  GtkWidget *tune_label=gtk_label_new("Tune:");
-  gtk_widget_override_font(tune_label, pango_font_description_from_string("Arial 18"));
-  gtk_widget_show(tune_label);
-  gtk_grid_attach(toolbar_top,tune_label,9,0,1,1);
-
-  tune_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 1.0, 0.01);
-  gtk_range_set_value (tune_scale,getTuneDrive());
-  gtk_widget_show(tune_scale);
-  gtk_grid_attach(toolbar_top,tune_scale,10,0,2,1);
-  g_signal_connect(G_OBJECT(tune_scale),"value_changed",G_CALLBACK(tune_value_changed_cb),NULL);
-*/
+    gtk_grid_attach(GTK_GRID(toolbar),tx,28,0,4,1);
 
-  gtk_grid_attach(GTK_GRID(toolbar),toolbar_top,0,0,1,1);
-  gtk_widget_show(toolbar_top);
-  gtk_grid_attach(GTK_GRID(toolbar),toolbar_bottom,0,1,1,1);
-  gtk_widget_show(toolbar_bottom);
+    gtk_widget_show_all(toolbar);
 
   return toolbar;
 }
index 53c25f315bee99eb787f0604dfef906cc11acc08..99940ea1a81a441ab37d92f107fc880ece753bea 100644 (file)
--- a/toolbar.h
+++ b/toolbar.h
@@ -1,6 +1,30 @@
+/* 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.
+*
+*/
+
 void set_agc_gain(double value);
 void set_af_gain(double value);
+void set_mic_gain(double value);
 void set_drive(double drive);
 void set_tune(double tune);
 int ptt_update(void *data);
+void lock_cb(GtkWidget *widget, gpointer data);
+void mox_cb(GtkWidget *widget, gpointer data);
+void tune_cb(GtkWidget *widget, gpointer data);
 GtkWidget *toolbar_init(int my_width, int my_height, GtkWidget* parent);
+GtkWidget *sliders_init(int my_width, int my_height, GtkWidget* parent);
diff --git a/version.c b/version.c
new file mode 100644 (file)
index 0000000..c3bd1b1
--- /dev/null
+++ b/version.c
@@ -0,0 +1,22 @@
+/* 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.
+*
+*/
+
+char build_date[]=__DATE__;
+char build_time[]=__TIME__;
+
diff --git a/version.h b/version.h
new file mode 100644 (file)
index 0000000..a250627
--- /dev/null
+++ b/version.h
@@ -0,0 +1,22 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+extern char build_date[];
+extern char build_time[];
+
diff --git a/vfo.c b/vfo.c
index 648f31d390713aafd71c71c0aaf68a300fd1d438..b0ba2616e28c5a86c6060c722286f98073f146a5 100644 (file)
--- a/vfo.c
+++ b/vfo.c
@@ -1,3 +1,22 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
 #include <math.h>
 #include <stdlib.h>
 #include <unistd.h>
 
+#include "main.h"
+#include "agc.h"
 #include "mode.h"
 #include "filter.h"
 #include "bandstack.h"
 #include "band.h"
+#include "frequency.h"
 #include "new_protocol.h"
-#include "rotary_encoder.h"
 #include "radio.h"
 #include "vfo.h"
 #include "channel.h"
+#include "gpio.h"
 #include "wdsp.h"
 
 static GtkWidget *parent_window;
+static int my_width;
+static int my_height;
 
 static GtkWidget *vfo;
 static cairo_surface_t *vfo_surface = NULL;
 
-static pthread_t rotary_encoder_thread_id;
-
 static int steps[]={1,10,25,50,100,250,500,1000,2500,5000,6250,9000,10000,12500,15000,20000,25000,30000,50000,100000,0};
 static char *step_labels[]={"1Hz","10Hz","25Hz","50Hz","100Hz","250Hz","500Hz","1kHz","2.5kHz","5kHz","6.25kHz","9kHz","10kHz","12.5kHz","15kHz","20kHz","25kHz","30kHz","50kHz","100kHz",0};
-static int af_function=0;
-static int previous_af_function=0;
-static int rf_function=0;
-static int previous_rf_function=0;
-static int band_button=0;
-static int previous_band_button=0;
 
 static GtkWidget* menu=NULL;
 static GtkWidget* band_menu=NULL;
@@ -55,167 +71,13 @@ void vfo_move(int hz) {
   }
 }
 
-static int rotary_encoder_changed(void *data) {
-  if(!locked) {
-    int pos=*(int*)data;
-    BANDSTACK_ENTRY* entry=bandstack_entry_get_current();
-    entry->frequencyA=entry->frequencyA+(pos*step);
-    setFrequency(entry->frequencyA);
-    vfo_update(NULL);
-  }
-  free(data);
-  return 0;
-}
-
-static int af_encoder_changed(void *data) {
-  int pos=*(int*)data;
-  if(pos!=0) {
-    if(af_function) {
-      // agc gain
-      double gain=agc_gain;
-      gain+=(double)pos;
-      if(gain<0.0) {
-        gain=0.0;
-      } else if(gain>120.0) {
-        gain=120.0;
-      }
-      set_agc_gain(gain);
-    } else {
-      // af gain
-      double gain=volume;
-      gain+=(double)pos/20.0;
-      if(gain<0.0) {
-        gain=0.0;
-      } else if(gain>1.0) {
-        gain=1.0;
-      }
-      set_af_gain(gain);
-    }
-  }
-  free(data);
-  return 0;
-}
-
-static int rf_encoder_changed(void *data) {
-  int pos=*(int*)data;
-  if(pos!=0) {
-    if(rf_function) {
-      // tune drive
-      double d=getTuneDrive();
-      d+=(double)pos/10.0;
-      if(d<0.0) {
-        d=0.0;
-      } else if(d>1.0) {
-        d=1.0;
-      }
-      set_tune(d);
-    } else {
-      // drive
-      double d=getDrive();
-      d+=(double)pos/10.0;
-      if(d<0.0) {
-        d=0.0;
-      } else if(d>1.0) {
-        d=1.0;
-      }
-      set_drive(d);
-    }
-  }
-  free(data);
-  return 0;
-}
-
-static int band_pressed(void *data) {
-  int function=*(int*)data;
-
-  BANDSTACK_ENTRY *entry;
-  if(function) {
-    entry=bandstack_entry_next();
-  } else {
-    int b=band_get_current();
-    b++;
-    if(b>=BANDS) {
-      b=0;
-    }
-    BAND* band=band_set_current(b);
-    entry=bandstack_entry_get_current();
-  }
-
-  setFrequency(entry->frequencyA);
-  setMode(entry->mode);
-  FILTER* band_filters=filters[entry->mode];
-  FILTER* band_filter=&band_filters[entry->filter];
-  setFilter(band_filter->low,band_filter->high);
-
-  BAND *band=band_get_current_band();
-  set_alex_rx_antenna(band->alexRxAntenna);
-  set_alex_tx_antenna(band->alexTxAntenna);
-  set_alex_attenuation(band->alexAttenuation);
-  vfo_update(NULL);
-
-
-  free(data);
-  return 0;
-}
-
-static void* rotary_encoder_thread(void *arg) {
-    int pos;
-    while(1) {
-
-        pos=vfo_encoder_get_pos();
-        if(pos!=0) {
-            int *p=malloc(sizeof(int));
-            *p=pos;
-            g_idle_add(rotary_encoder_changed,(gpointer)p);
-        }
-
-        af_function=af_function_get_state();
-        if(af_function!=previous_af_function) {
-            fprintf(stderr,"af_function: %d\n",af_function);
-            previous_af_function=af_function;
-        }
-        pos=af_encoder_get_pos();
-        if(pos!=0) {
-            int *p=malloc(sizeof(int));
-            *p=pos;
-            g_idle_add(af_encoder_changed,(gpointer)p);
-        }
-
-        rf_function=rf_function_get_state();
-        if(rf_function!=previous_rf_function) {
-            fprintf(stderr,"rf_function: %d\n",rf_function);
-            previous_rf_function=rf_function;
-        }
-        pos=rf_encoder_get_pos();
-        if(pos!=0) {
-            int *p=malloc(sizeof(int));
-            *p=pos;
-            g_idle_add(rf_encoder_changed,(gpointer)p);
-        }
-
-        int band_button=band_get_state();
-        if(band_button!=previous_band_button) {
-            fprintf(stderr,"band_button: %d\n",band_button);
-            previous_band_button=band_button;
-            if(band_button) {
-                int function=function_get_state();
-                g_idle_add(band_pressed,(gpointer)function);
-            }
-        }
-
-#ifdef raspberrypi
-        gpioDelay(100000); // 10 per second
-#endif
-#ifdef odroid
-        usleep(100000);
-#endif
-    }
-}
-
 static gboolean vfo_configure_event_cb (GtkWidget         *widget,
             GdkEventConfigure *event,
             gpointer           data)
 {
+fprintf(stderr,"vfo_configure_event_cb: width=%d height=%d\n",
+                                       gtk_widget_get_allocated_width (widget),
+                                       gtk_widget_get_allocated_height (widget));
   if (vfo_surface)
     cairo_surface_destroy (vfo_surface);
 
@@ -257,7 +119,8 @@ int vfo_update(void *data) {
         cairo_select_font_face(cr, "Arial",
             CAIRO_FONT_SLANT_NORMAL,
             CAIRO_FONT_WEIGHT_BOLD);
-        cairo_set_font_size(cr, 36);
+        //cairo_set_font_size(cr, 36);
+        cairo_set_font_size(cr, 28);
 
         if(isTransmitting()) {
             cairo_set_source_rgb(cr, 1, 0, 0);
@@ -266,14 +129,18 @@ int vfo_update(void *data) {
         }
 
         char sf[32];
-        sprintf(sf,"%0lld.%06lld MHz %s %s",entry->frequencyA/(long long)1000000,entry->frequencyA%(long long)1000000,mode_string[entry->mode],band_filter->title);
-        cairo_move_to(cr, 130, 45);  
+        sprintf(sf,"%0lld.%06lld MHz",entry->frequencyA/(long long)1000000,entry->frequencyA%(long long)1000000);
+        cairo_move_to(cr, 5, 30);  
         cairo_show_text(cr, sf);
 
-        cairo_set_font_size(cr, 18);
-        sprintf(sf,"Step %dHz",step);
-        cairo_move_to(cr, 10, 25);  
-        cairo_show_text(cr, sf);
+        cairo_set_font_size(cr, 12);
+
+        cairo_move_to(cr, (my_width/2)+20, 30);  
+        cairo_show_text(cr, getFrequencyInfo(entry->frequencyA));
+
+//        sprintf(sf,"Step %dHz",step);
+//        cairo_move_to(cr, 10, 25);  
+//        cairo_show_text(cr, sf);
 
         if(locked) {
             cairo_set_source_rgb(cr, 1, 0, 0);
@@ -281,6 +148,52 @@ int vfo_update(void *data) {
             cairo_show_text(cr, "Locked");
         }
 
+        if(function) {
+            cairo_set_source_rgb(cr, 1, 0.5, 0);
+            cairo_move_to(cr, 70, 50);  
+            cairo_show_text(cr, "Function");
+        }
+
+        cairo_set_source_rgb(cr, 1, 1, 0);
+        cairo_move_to(cr, 130, 50);  
+        cairo_show_text(cr, mode_string[entry->mode]);
+
+        cairo_move_to(cr, 190, 50);  
+        cairo_show_text(cr, band_filter->title);
+
+        cairo_move_to(cr, 250, 50);  
+        if(nr) {
+          cairo_show_text(cr, "NR");
+        }
+        if(nb) {
+          cairo_show_text(cr, "NB");
+        }
+        if(anf) {
+          cairo_show_text(cr, "ANF");
+        }
+        if(snb) {
+          cairo_show_text(cr, "NR2");
+        }
+
+        cairo_move_to(cr, 310, 50);  
+        switch(agc) {
+          case AGC_OFF:
+            cairo_show_text(cr, "AGC OFF");
+            break;
+          case AGC_LONG:
+            cairo_show_text(cr, "AGC LONG");
+            break;
+          case AGC_SLOW:
+            cairo_show_text(cr, "AGC SLOW");
+            break;
+          case AGC_MEDIUM:
+            cairo_show_text(cr, "AGC MEDIUM");
+            break;
+          case AGC_FAST:
+            cairo_show_text(cr, "AGC FAST");
+            break;
+        }
+
         cairo_destroy (cr);
         gtk_widget_queue_draw (vfo);
     }
@@ -300,7 +213,7 @@ vfo_press_event_cb (GtkWidget *widget,
                GdkEventButton *event,
                gpointer        data)
 {
-  GtkWidget *dialog=gtk_dialog_new_with_buttons("VFO",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+  GtkWidget *dialog=gtk_dialog_new_with_buttons("Step",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
 
   GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
   GtkWidget *grid=gtk_grid_new();
@@ -319,12 +232,13 @@ vfo_press_event_cb (GtkWidget *widget,
     gtk_widget_override_font(step_rb, pango_font_description_from_string("Arial 18"));
     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (step_rb), steps[i]==step);
     gtk_widget_show(step_rb);
-    gtk_grid_attach(GTK_GRID(grid),step_rb,i/5,i%5,1,1);
+    gtk_grid_attach(GTK_GRID(grid),step_rb,i%5,i/5,1,1);
     g_signal_connect(step_rb,"pressed",G_CALLBACK(vfo_step_select_cb),(gpointer *)i);
     i++;
   }
 
   gtk_container_add(GTK_CONTAINER(content),grid);
+
   GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK);
   gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 18"));
   gtk_widget_show_all(dialog);
@@ -341,10 +255,12 @@ vfo_press_event_cb (GtkWidget *widget,
 
 GtkWidget* vfo_init(int width,int height,GtkWidget *parent) {
 
+fprintf(stderr,"vfo_init: width=%d height=%d\n", width, height);
   parent_window=parent;
+  my_width=width;
+  my_height=height;
 
   vfo = gtk_drawing_area_new ();
-  /* set a minimum size */
   gtk_widget_set_size_request (vfo, width, height);
 
   /* Signals used to handle the backing surface */
@@ -353,15 +269,6 @@ GtkWidget* vfo_init(int width,int height,GtkWidget *parent) {
   g_signal_connect (vfo,"configure-event",
             G_CALLBACK (vfo_configure_event_cb), NULL);
 
-  if(encoder_init() == 0) {
-    int rc=pthread_create(&rotary_encoder_thread_id, NULL, rotary_encoder_thread, NULL);
-    if(rc<0) {
-      fprintf(stderr,"pthread_create for rotary_encoder_thread failed %d\n",rc);
-    }
-  } else {
-    fprintf(stderr,"encoder_init failed\n");
-  }
-
   /* Event signals */
   g_signal_connect (vfo, "button-press-event",
             G_CALLBACK (vfo_press_event_cb), NULL);
diff --git a/vfo.h b/vfo.h
index 22d2da102096e9f29d6e21c314156192eedb06aa..008e8e056177aa397fa567d8dd8ba96e8beb18d3 100644 (file)
--- a/vfo.h
+++ b/vfo.h
@@ -1,3 +1,22 @@
+/* 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.
+*
+*/
+
 
 GtkWidget* vfo_init(int width,int height,GtkWidget *parent);
 void vfo_step(int steps);
index 176e868bc7eefb18924e7c38efc19b86edbb7148..e3dd2188a749ed77056e567c4c174cf59a4e7f3a 100644 (file)
@@ -1,3 +1,22 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
 
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
 #include <unistd.h>
 #include <semaphore.h>
 #include <string.h>
+#include "radio.h"
 #include "vfo.h"
-#include "new_protocol.h"
 #include "waterfall.h"
 
 static GtkWidget *waterfall;
 static GdkPixbuf *pixbuf = NULL;
 
-static float highThreshold = -100.0f;
-static float lowThreshold = -150.0f;
-
 static int colorLowR=0; // black
 static int colorLowG=0;
 static int colorLowB=0;
@@ -144,17 +160,17 @@ void waterfall_update(float *data) {
     for(i=0;i<width;i++) {
             sample=data[i]+get_attenuation();
             average+=(int)sample;
-            if(sample<lowThreshold) {
+            if(sample<(float)waterfall_low) {
                 *p++=colorLowR;
                 *p++=colorLowG;
                 *p++=colorLowB;
-            } else if(sample>highThreshold) {
+            } else if(sample>(float)waterfall_high) {
                 *p++=colorHighR;
                 *p++=colorHighG;
                 *p++=colorHighB;
             } else {
-                float range=highThreshold-lowThreshold;
-                float offset=sample-lowThreshold;
+                float range=(float)waterfall_high-(float)waterfall_low;
+                float offset=sample-(float)waterfall_low;
                 float percent=offset/range;
                 if(percent<(2.0f/9.0f)) {
                     float local_percent = percent / (2.0f/9.0f);
@@ -197,8 +213,10 @@ void waterfall_update(float *data) {
     }
 
     
-    lowThreshold=(float)((average/display_width));
-    highThreshold=lowThreshold+50.0;
+    if(waterfall_automatic) {
+      waterfall_low=average/display_width;
+      waterfall_high=waterfall_low+50;
+    }
 
     gtk_widget_queue_draw (waterfall);
 
index 7b5e3790d3e391cedc721c4243a6199fbcfe9875..c656298d04f99f311320d5b0d131fac3792c2198 100644 (file)
@@ -1,3 +1,22 @@
+/* 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.
+*
+*/
+
 
 void waterfall_update(float *data);
 GtkWidget* waterfall_init(int width,int height);
diff --git a/wdsp_init.c b/wdsp_init.c
new file mode 100644 (file)
index 0000000..da15bda
--- /dev/null
@@ -0,0 +1,280 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <net/if_arp.h>
+#include <net/if.h>
+#include <ifaddrs.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <math.h>
+
+#include "alex.h"
+#include "new_protocol.h"
+#include "channel.h"
+#include "discovered.h"
+#include "mode.h"
+#include "filter.h"
+#include "wdsp.h"
+#include "radio.h"
+#include "vfo.h"
+#include "toolbar.h"
+#include "wdsp_init.h"
+
+#define PI 3.1415926535897932F
+
+static int receiver;
+static int running=0;
+
+static int buffer_size=BUFFER_SIZE;
+static int tx_buffer_size=BUFFER_SIZE;
+static int fft_size=4096;
+static int dspRate=48000;
+static int outputRate=48000;
+
+static int micSampleRate=48000;
+static int micDspRate=48000;
+static int micOutputRate=192000;
+
+static int spectrumWIDTH=800;
+static int SPECTRUM_UPDATES_PER_SECOND=10;
+
+static void initAnalyzer(int channel,int buffer_size);
+
+void setMode(int m) {
+    mode=m;
+    SetRXAMode(receiver, mode);
+    SetTXAMode(CHANNEL_TX, mode);
+}
+
+int getMode() {
+    return mode;
+}
+
+void setFilter(int low,int high) {
+    if(mode==modeCWL) {
+        filterLow=-cwPitch-low;
+        filterHigh=-cwPitch+high;
+    } else if(mode==modeCWU) {
+        filterLow=cwPitch-low;
+        filterHigh=cwPitch+high;
+    } else {
+        filterLow=low;
+        filterHigh=high;
+    }
+
+    RXANBPSetFreqs(receiver,(double)filterLow,(double)filterHigh);
+    SetRXABandpassFreqs(receiver, (double)filterLow, (double)filterHigh);
+    SetRXASNBAOutputBandwidth(receiver, (double)filterLow, (double)filterHigh);
+
+    SetTXABandpassFreqs(CHANNEL_TX, (double)filterLow, (double)filterHigh);
+}
+
+int getFilterLow() {
+    return filterLow;
+}
+
+int getFilterHigh() {
+    return filterHigh;
+}
+
+void wdsp_init(int rx,int pixels,int protocol) {
+    int rc;
+    receiver=rx;
+    spectrumWIDTH=pixels;
+
+    fprintf(stderr,"wdsp_init: %d\n",rx);
+   
+    if(protocol==ORIGINAL_PROTOCOL) {
+        micOutputRate=48000;
+    } else {
+        micOutputRate=192000;
+    }
+
+    while (gtk_events_pending ())
+      gtk_main_iteration ();
+
+    fprintf(stderr,"OpenChannel %d buffer_size=%d fft_size=%d sample_rate=%d dspRate=%d outputRate=%d\n",
+                rx,
+                buffer_size,
+                fft_size,
+                sample_rate,
+                dspRate,
+                outputRate);
+
+    OpenChannel(rx,
+                buffer_size,
+                fft_size,
+                sample_rate,
+                dspRate,
+                outputRate,
+                0, // receive
+                1, // run
+                0.010, 0.025, 0.0, 0.010, 0);
+
+    while (gtk_events_pending ())
+      gtk_main_iteration ();
+
+    switch(sample_rate) {
+      case 48000:
+        tx_buffer_size=BUFFER_SIZE;
+        break;
+      case 96000:
+        tx_buffer_size=BUFFER_SIZE/2;
+        break;
+      case 192000:
+        tx_buffer_size=BUFFER_SIZE/4;
+        break;
+      case 384000:
+        tx_buffer_size=BUFFER_SIZE/8;
+        break;
+    }
+    fprintf(stderr,"OpenChannel %d buffer_size=%d fft_size=%d sample_rate=%d dspRate=%d outputRate=%d\n",
+                CHANNEL_TX,
+                tx_buffer_size,
+                fft_size,
+                sample_rate, //micSampleRate,
+                micDspRate,
+                micOutputRate);
+
+    OpenChannel(CHANNEL_TX,
+                buffer_size,
+                fft_size,
+                sample_rate, //micSampleRate,
+                micDspRate,
+                micOutputRate,
+                1, // transmit
+                1, // run
+                0.010, 0.025, 0.0, 0.010, 0);
+
+    while (gtk_events_pending ())
+      gtk_main_iteration ();
+
+    fprintf(stderr,"XCreateAnalyzer %d\n",rx);
+    int success;
+    XCreateAnalyzer(rx, &success, 262144, 1, 1, "");
+        if (success != 0) {
+            fprintf(stderr, "XCreateAnalyzer %d failed: %d\n" ,rx,success);
+        }
+    initAnalyzer(rx,buffer_size);
+
+    while (gtk_events_pending ())
+      gtk_main_iteration ();
+
+    XCreateAnalyzer(CHANNEL_TX, &success, 262144, 1, 1, "");
+        if (success != 0) {
+            fprintf(stderr, "XCreateAnalyzer CHANNEL_TX failed: %d\n" ,success);
+        }
+    initAnalyzer(CHANNEL_TX,tx_buffer_size);
+
+    SetRXAMode(rx, mode);
+    SetRXABandpassFreqs(rx, (double)filterLow, (double)filterHigh);
+    SetRXAAGCMode(rx, agc);
+    SetRXAAGCTop(rx,agc_gain);
+
+    SetRXAAMDSBMode(CHANNEL_RX0, 0);
+    SetRXAShiftRun(CHANNEL_RX0, 0);
+    SetRXAEMNRgainMethod(CHANNEL_RX0, 1);
+    SetRXAEMNRnpeMethod(CHANNEL_RX0, 0);
+    SetRXAEMNRaeRun(CHANNEL_RX0, 1);
+    SetRXAEMNRPosition(CHANNEL_RX0, 0);
+    SetRXAEMNRRun(CHANNEL_RX0, 0);
+    SetRXAANRRun(CHANNEL_RX0, 0);
+    SetRXAANFRun(CHANNEL_RX0, 0);
+
+    SetTXAMode(CHANNEL_TX, mode);
+    SetTXABandpassFreqs(CHANNEL_TX, (double)filterLow, (double)filterHigh);
+    SetTXABandpassWindow(CHANNEL_TX, 1);
+    SetTXABandpassRun(CHANNEL_TX, 1);
+
+    SetTXACFIRRun(CHANNEL_TX, 1);
+    SetTXAEQRun(CHANNEL_TX, 0);
+    SetTXACTCSSRun(CHANNEL_TX, 0);
+    SetTXAAMSQRun(CHANNEL_TX, 0);
+    SetTXACompressorRun(CHANNEL_TX, 0);
+    SetTXAosctrlRun(CHANNEL_TX, 0);
+    SetTXAPreGenRun(CHANNEL_TX, 0);
+    SetTXAPostGenRun(CHANNEL_TX, 0);
+
+}
+
+static void initAnalyzer(int channel,int buffer_size) {
+    int flp[] = {0};
+    double KEEP_TIME = 0.1;
+    int n_pixout=1;
+    int spur_elimination_ffts = 1;
+    int data_type = 1;
+    int fft_size = 8192;
+    int window_type = 4;
+    double kaiser_pi = 14.0;
+    int overlap = 2048;
+    int clip = 0;
+    int span_clip_l = 0;
+    int span_clip_h = 0;
+    int pixels=spectrumWIDTH;
+    int stitches = 1;
+    int avm = 0;
+    double tau = 0.001 * 120.0;
+    int MAX_AV_FRAMES = 60;
+    int display_average = MAX(2, (int) MIN((double) MAX_AV_FRAMES, (double) SPECTRUM_UPDATES_PER_SECOND * tau));
+    double avb = exp(-1.0 / (SPECTRUM_UPDATES_PER_SECOND * tau));
+    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) SPECTRUM_UPDATES_PER_SECOND, KEEP_TIME * (double) fft_size * (double) SPECTRUM_UPDATES_PER_SECOND);
+
+    fprintf(stderr,"SetAnalyzer channel=%d\n",channel);
+    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
+/*
+            avm, //averaging mode
+            display_average, //number of spans to (moving) average for pixel result
+            avb, //back multiplier for weighted averaging
+*/
+            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
+    );
+}
diff --git a/wdsp_init.h b/wdsp_init.h
new file mode 100644 (file)
index 0000000..041737d
--- /dev/null
@@ -0,0 +1,25 @@
+/* Copyright (C)
+* 2015 - John Melton, G0ORX/N6LYT
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+*/
+
+extern void setMode(int m);
+extern int getMode();
+extern void setFilter(int low,int high);
+extern int getFilterLow();
+extern int getFilterHigh();
+extern void wdsp_init(int rx,int pixels,int protocol);
diff --git a/xvtr.h b/xvtr.h
index bc948d6b0a39c8c76fccb985235f4ab805ce2215..4c8f4482c1b75ed1428078070b969f585b949cf6 100644 (file)
--- a/xvtr.h
+++ b/xvtr.h
@@ -1,14 +1,7 @@
-/**
-* @file xvtr.h
-* @brief XVTR definition files
-* @author John Melton, G0ORX/N6LYT, Doxygen Comments Dave Larsen, KV0S
-* @version 0.1
-* @date 2009-04-11
-*/
-// xvtr.h
-
 /* Copyright (C)
-* This program is free software; you can redistribute it and/or2009 - John Melton, G0ORX/N6LYT, Doxygen Comments Dave Larsen, KV0S
+* 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.