]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
Changed button debounce for original controller. Changed band menu display to only...
authorJohn Melton G0ORX <john.d.melton@googlemail.com>
Fri, 25 Oct 2019 16:43:07 +0000 (17:43 +0100)
committerJohn Melton G0ORX <john.d.melton@googlemail.com>
Fri, 25 Oct 2019 16:43:07 +0000 (17:43 +0100)
28 files changed:
Makefile
band.c
band_menu.c
configure.c
encoder_menu.c
ext.c
gpio.c
gpio.h
i2c.c
new_discovery.c
new_menu.c
old_discovery.c
radio.c
release/pihpsdr-controller1.v2.0.0-beta.tar [new file with mode: 0644]
release/pihpsdr-controller2-v1.v2.0.0-beta.tar [new file with mode: 0644]
release/pihpsdr-controller2-v2.v2.0.0-beta.tar [new file with mode: 0644]
release/pihpsdr-nocontroller.v2.0.0-beta.tar [new file with mode: 0644]
release/pihpsdr-v2.0.0-beta.tar
release/pihpsdr.tar
release/pihpsdr/64-limesuite.rules [new file with mode: 0644]
release/pihpsdr/README.MIDI [new file with mode: 0644]
release/pihpsdr/install.sh
release/pihpsdr/midi.inp [new file with mode: 0644]
release/pihpsdr/pihpsdr
rx_panadapter.c
switch_menu.c
tx_panadapter.c
version.c

index f7f7a3992ebac60dfd6f0650bb965a0bdeeb6ebb..1d17bb3836787c044b2c0696bca2c2c01538c6e5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,35 +1,40 @@
 # Get git commit version and date
-#GIT_VERSION := $(shell git --no-pager describe --tags --always --dirty)
 GIT_DATE := $(firstword $(shell git --no-pager show --date=short --format="%ai" --name-only))
 GIT_VERSION := $(shell git describe --abbrev=0 --tags)
 
-# uncomment the line below to include CONTROLLER2 (Also include GPIO and I2C)
-#CONTROLLER2_INCLUDE=CONTROLLER2
-
-# uncomment the line below to include GPIO
+# uncomment the line below to include GPIO (For original piHPSDR Controller and Controller2)
 GPIO_INCLUDE=GPIO
 
-# uncomment the line below to include MCP23017 I2C
+# uncomment the line below to include MCP23017 I2C (required for Controller2)
 #I2C_INCLUDE=I2C
 
+# uncomment the line below to include CONTROLLER2_V1 (single encoders) (Also uncomment GPIO and I2C)
+#CONTROLLER2_V1_INCLUDE=CONTROLLER2_V1
+
+# uncomment the line below to include CONTROLLER2_V2 (dual encoders) (Also uncomment GPIO and I2C)
+#CONTROLLER2_V2_INCLUDE=CONTROLLER2_V2
+
 # uncomment the line below to include USB Ozy support
 # USBOZY_INCLUDE=USBOZY
 
+# uncomment the line below to include Pure Signal support
+PURESIGNAL_INCLUDE=PURESIGNAL
+
+# uncomment the line to below include support local CW keyer
+#LOCALCW_INCLUDE=LOCALCW
+
+# uncomment the line below for SoapySDR
+SOAPYSDR_INCLUDE=SOAPYSDR
+
 # uncomment the line below to include support for psk31
 #PSK_INCLUDE=PSK
 
 # uncomment the line to below include support for FreeDV codec2
 #FREEDV_INCLUDE=FREEDV
 
-# uncomment the line below to include Pure Signal support
-PURESIGNAL_INCLUDE=PURESIGNAL
-
 # uncomment the line to below include support for sx1509 i2c expander
 #SX1509_INCLUDE=sx1509
 
-# uncomment the line to below include support local CW keyer
-#LOCALCW_INCLUDE=LOCALCW
-
 # uncomment the line below to include support for STEMlab discovery (WITH AVAHI)
 #STEMLAB_DISCOVERY=STEMLAB_DISCOVERY
 
@@ -42,21 +47,20 @@ PURESIGNAL_INCLUDE=PURESIGNAL
 # uncomment the line below to include MIDI support
 MIDI_INCLUDE=MIDI
 
-#uncomment the line below for the platform being compiled on (actually not used)
-UNAME_N=raspberrypi
-#UNAME_N=odroid
-#UNAME_N=up
-#UNAME_N=pine64
-#UNAME_N=jetsen
-
-CC=gcc
-LINK=gcc
+# uncomment the line below when Radioberry radio cape is plugged in (for now use emulator and old protocol)
+#RADIOBERRY_INCLUDE=RADIOBERRY
 
 # uncomment the line below for various debug facilities
 #DEBUG_OPTION=-D DEBUG
 
-ifeq ($(CONTROLLER2_INCLUDE),CONTROLLER2)
-CONTROLLER2_OPTIONS=-D CONTROLLER2
+CC=gcc
+LINK=gcc
+
+ifeq ($(CONTROLLER2_V2_INCLUDE),CONTROLLER2_V2)
+CONTROLLER2_OPTIONS=-D CONTROLLER2_V2
+endif
+ifeq ($(CONTROLLER2_V1_INCLUDE),CONTROLLER2_V1)
+CONTROLLER2_OPTIONS=-D CONTROLLER2_V1
 endif
 
 ifeq ($(MIDI_INCLUDE),MIDI)
@@ -102,15 +106,10 @@ ozyio.o
 endif
 
 
-# uncomment the line below when Radioberry radio cape is plugged in (for now use emulator and old protocol)
-#RADIOBERRY_INCLUDE=RADIOBERRY
 ifeq ($(RADIOBERRY_INCLUDE),RADIOBERRY)
 RADIOBERRY_OPTIONS=-D RADIOBERRY
 endif
 
-# uncomment the line below for SoapySDR
-#SOAPYSDR_INCLUDE=SOAPYSDR
-
 ifeq ($(SOAPYSDR_INCLUDE),SOAPYSDR)
 SOAPYSDR_OPTIONS=-D SOAPYSDR
 SOAPYSDRLIBS=-lSoapySDR
@@ -471,6 +470,23 @@ release: $(PROGRAM)
        cd release; tar cvf pihpsdr.tar pihpsdr
        cd release; tar cvf pihpsdr-$(GIT_VERSION).tar pihpsdr
 
+nocontroller: clean controller1 $(PROGRAM)
+       cp $(PROGRAM) release/pihpsdr
+       cd release; tar cvf pihpsdr-nocontroller.$(GIT_VERSION).tar pihpsdr
+
+controller1: clean $(PROGRAM)
+       cp $(PROGRAM) release/pihpsdr
+       cd release; tar cvf pihpsdr-controller1.$(GIT_VERSION).tar pihpsdr
+
+controller2v1: clean $(PROGRAM)
+       cp $(PROGRAM) release/pihpsdr
+       cd release; tar cvf pihpsdr-controller2-v1.$(GIT_VERSION).tar pihpsdr
+
+controller2v2: clean $(PROGRAM)
+       cp $(PROGRAM) release/pihpsdr
+       cd release; tar cvf pihpsdr-controller2-v2.$(GIT_VERSION).tar pihpsdr
+
+
 #############################################################################
 #
 # hpsdrsim is a cool program that emulates an SDR board with UDP and TCP
diff --git a/band.c b/band.c
index 3c0eeef79a53a2cd7b74e1c8d126846ea6abf320..2d6eb8eaad72cb3ea4805d304f0b49811d022381 100644 (file)
--- a/band.c
+++ b/band.c
@@ -277,7 +277,7 @@ BAND bands[BANDS+XVTRS] =
      {"10",&bandstack10,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,28000000LL,29700000LL,0LL,0LL,0},
      {"6",&bandstack6,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,50000000LL,54000000LL,0LL,0LL,0},
 #ifdef SOAPYSDR
-     {"70",&bandstack70,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0LL,0},
+     {"4",&bandstack144,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,70000000LL,70500000LL,0LL,0LL,0},
      {"144",&bandstack144,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,144000000LL,148000000LL,0LL,0LL,0},
      {"220",&bandstack144,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,222000000LL,224980000LL,0LL,0LL,0},
      {"430",&bandstack430,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,420000000LL,450000000LL,0LL,0LL,0},
@@ -285,7 +285,7 @@ BAND bands[BANDS+XVTRS] =
      {"1240",&bandstack1240,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,1240000000LL,1300000000LL,0LL,0LL,0},
      {"2300",&bandstack2300,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,2300000000LL,2450000000LL,0LL,0LL,0},
      {"3400",&bandstack3400,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,3400000000LL,3410000000LL,0LL,0LL,0},
-     {"AIR",&bandstackAIR,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0LL,0},
+     {"AIR",&bandstack3400,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,108000000LL,137000000LL,0LL,0LL,0},
 #endif
      {"GEN",&bandstackGEN,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0LL,0},
      {"WWV",&bandstackWWV,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0LL,0},
index bde4957d86f6ddb502e12f90b29644900646dc82..0b61a8bcc3b9e994a4e9d17ccfaf783b7865a5d0 100644 (file)
@@ -69,7 +69,7 @@ gboolean band_select_cb (GtkWidget *widget, gpointer        data) {
 
 void band_menu(GtkWidget *parent) {
   GtkWidget *b;
-  int i;
+  int i,j;
   BAND *band;
 
   parent_window=parent;
@@ -102,27 +102,30 @@ void band_menu(GtkWidget *parent) {
   g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
   gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
 
-  for(i=0;i<BANDS+XVTRS;i++) {
-#ifdef SOAPYSDR
-    if(protocol!=SOAPYSDR_PROTOCOL) {
-      if(i>=band70 && i<=band3400) {
-        continue;
-      }
-    }
-#endif
+  long long frequency_min=radio->frequency_min;
+  long long frequency_max=radio->frequency_max;
 
+  j=0;
+  for(i=0;i<BANDS+XVTRS;i++) {
     band=(BAND*)band_get_band(i);
     if(strlen(band->title)>0) {
+      if(i<BANDS) {
+        if(!(band->frequencyMin==0.0 && band->frequencyMax==0.0)) {
+          if(band->frequencyMin<frequency_min || band->frequencyMax>frequency_max) {
+            continue;
+          }
+        }
+      }
       GtkWidget *b=gtk_button_new_with_label(band->title);
       set_button_text_color(b,"black");
-      //if(i==band_get_current()) {
       if(i==vfo[active_receiver->id].band) {
         set_button_text_color(b,"orange");
         last_band=b;
       }
       gtk_widget_show(b);
-      gtk_grid_attach(GTK_GRID(grid),b,i%5,1+(i/5),1,1);
+      gtk_grid_attach(GTK_GRID(grid),b,j%5,1+(j/5),1,1);
       g_signal_connect(b,"clicked",G_CALLBACK(band_select_cb),(gpointer)(long)i);
+      j++;
     }
   }
 
index 9ac48f1cd1544960eefc0255ac592cc5f51ba2bb..e0d04629b1d2fbe1d8b61926f7feee321f8a602c 100644 (file)
@@ -62,7 +62,7 @@ static   GtkWidget *E4_a;
 static   GtkWidget *E4_b_label;
 static   GtkWidget *E4_b;
 static   GtkWidget *b_enable_E4_pullup;
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
 static GtkWidget *b_enable_E5_encoder;
 static   GtkWidget *E5_a_label;
 static   GtkWidget *E5_a;
@@ -316,7 +316,7 @@ void configure_gpio(GtkWidget *parent) {
   gtk_widget_show(b_enable_E4_pullup);
   gtk_grid_attach(GTK_GRID(grid),b_enable_E4_pullup,5,y,1,1);
 
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
   y++;
   b_enable_E5_encoder=gtk_check_button_new_with_label("Enable E5");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_E5_encoder), ENABLE_E5_ENCODER);
@@ -348,7 +348,7 @@ void configure_gpio(GtkWidget *parent) {
 
 #endif
 
-#ifndef CONTROLLER2
+#if !defined (CONTROLLER2_V2) && !defined(CONTROLLER2_V1)
   y++;
   b_enable_mox=gtk_check_button_new_with_label("Enable MOX/TUN");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_mox), ENABLE_MOX_BUTTON);
@@ -403,7 +403,7 @@ void configure_gpio(GtkWidget *parent) {
 
   y++;
 
-#ifndef CONTROLLER2
+#if !defined (CONTROLLER2_V2) && !defined (CONTROLLER2_V1)
   b_enable_S2=gtk_check_button_new_with_label("Enable S2");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_S2), ENABLE_S2_BUTTON);
   gtk_widget_show(b_enable_S2);
@@ -437,7 +437,7 @@ void configure_gpio(GtkWidget *parent) {
 
   y++;
 
-#ifndef CONTROLLER2
+#if !defined (CONTROLLER2_V2) && !defined (CONTROLLER2_V1)
   b_enable_S3=gtk_check_button_new_with_label("Enable S3");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_S3), ENABLE_S3_BUTTON);
   gtk_widget_show(b_enable_S3);
@@ -470,7 +470,7 @@ void configure_gpio(GtkWidget *parent) {
 #endif
   y++;
 
-#ifndef CONTROLLER2
+#if !defined (CONTROLLER2_V2) && !defined (CONTROLLER2_V1)
   b_enable_S4=gtk_check_button_new_with_label("Enable S4");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_S4), ENABLE_S4_BUTTON);
   gtk_widget_show(b_enable_S4);
index 83d89baae483412315889e9dfa6601e02ed2fdbd..acf99a7d7d2d2884b660804222cfa3e5d2500ca4 100644 (file)
@@ -32,7 +32,7 @@
 #include "vfo.h"
 #include "button_text.h"
 #include "gpio.h"
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER_V1)
 #include "i2c.h"
 #endif
 
@@ -58,7 +58,7 @@ static GtkWidget *b_panadapter_low;
 static GtkWidget *b_squelch;
 static GtkWidget *b_compression;
 
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
 static GtkWidget *b_top_af_gain_rx1;
 static GtkWidget *b_top_af_gain_rx2;
 static GtkWidget *b_top_agc_gain_rx1;
@@ -80,23 +80,25 @@ static GtkWidget *b_top_compression;
 
 enum {
   ENC2,
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
   ENC2_TOP,
 #endif
   ENC2_SW,
   ENC3,
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
   ENC3_TOP,
 #endif
   ENC3_SW,
   ENC4,
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
   ENC4_TOP,
 #endif
   ENC4_SW,
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
   ENC5,
+#if defined (CONTROLLER2_V2)
   ENC5_TOP,
+#endif
   ENC5_SW,
 #endif
 };
@@ -134,7 +136,7 @@ static void enc_select_cb(GtkWidget *widget,gpointer data) {
     case ENC2:
       e2_encoder_action=choice->action;
       break;
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
     case ENC2_TOP:
       e2_top_encoder_action=choice->action;
       break;
@@ -142,7 +144,7 @@ static void enc_select_cb(GtkWidget *widget,gpointer data) {
     case ENC3:
       e3_encoder_action=choice->action;
       break;
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
     case ENC3_TOP:
       e3_top_encoder_action=choice->action;
       break;
@@ -150,15 +152,17 @@ static void enc_select_cb(GtkWidget *widget,gpointer data) {
     case ENC4:
       e4_encoder_action=choice->action;
       break;
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
     case ENC4_TOP:
       e4_top_encoder_action=choice->action;
       break;
 #endif
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
     case ENC5:
       e5_encoder_action=choice->action;
       break;
+#endif
+#if defined (CONTROLLER2_V2)
     case ENC5_TOP:
       e5_top_encoder_action=choice->action;
       break;
@@ -205,7 +209,7 @@ static void sw_select_cb(GtkWidget *widget,gpointer data) {
     case ENC4_SW:
       e4_sw_action=choice->action;
       break;
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
     case ENC5_SW:
       e5_sw_action=choice->action;
       break;
@@ -297,7 +301,7 @@ GtkWidget* getRadioButton(int action) {
   return button;
 }
 
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
 GtkWidget* getTopRadioButton(int action) {
   GtkWidget* button;
   switch(action) {
@@ -379,7 +383,7 @@ static gboolean select_cb (GtkWidget *widget, gpointer data) {
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
 }
 
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
 static gboolean top_select_cb (GtkWidget *widget, gpointer data) {
   GtkWidget *button;
   int action;
@@ -456,7 +460,7 @@ void encoder_select(int pos) {
 
 }
 
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
 void top_encoder_select(int pos) {
   int action;
   GtkWidget *button;
@@ -543,7 +547,7 @@ void top_encoder_select(int pos) {
     }
   }
 
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
   static gboolean top_action_select_cb (GtkWidget *widget, gpointer data) {
     int action=(int)data;
     switch(encoder) {
@@ -599,7 +603,7 @@ void top_encoder_select(int pos) {
     return TRUE;
   }
 
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
   static gboolean enc2_top_cb(GtkWidget *widget, gpointer data) {
     int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget));
     e2_top_encoder_action=i;
@@ -665,13 +669,19 @@ void encoder_menu(GtkWidget *parent) {
 
   row++;
   col=1;
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
+#ifdef CONTROLLER2_V1
+  GtkWidget *label_encoder=gtk_label_new("Encoder");
+  gtk_grid_attach(GTK_GRID(grid),label_encoder,col,row,1,1);
+  col++;
+#else
   GtkWidget *label_bottom=gtk_label_new("Bottom");
   gtk_grid_attach(GTK_GRID(grid),label_bottom,col,row,1,1);
   col++;
   GtkWidget *label_top=gtk_label_new("Top");
   gtk_grid_attach(GTK_GRID(grid),label_top,col,row,1,1);
   col++;
+#endif
 #else
   GtkWidget *label_encoder=gtk_label_new("Encoder");
   gtk_grid_attach(GTK_GRID(grid),label_encoder,col,row,1,1);
@@ -693,7 +703,7 @@ void encoder_menu(GtkWidget *parent) {
   g_signal_connect(enc2,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC2));
   col++;
   
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
   GtkWidget *enc2_top=gtk_button_new_with_label(encoder_string[e2_top_encoder_action]);
   gtk_grid_attach(GTK_GRID(grid),enc2_top,col,row,1,1);
   g_signal_connect(enc2_top,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC2_TOP));
@@ -716,7 +726,7 @@ void encoder_menu(GtkWidget *parent) {
   g_signal_connect(enc3,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC3));
   col++;
   
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
   GtkWidget *enc3_top=gtk_button_new_with_label(encoder_string[e3_top_encoder_action]);
   gtk_grid_attach(GTK_GRID(grid),enc3_top,col,row,1,1);
   g_signal_connect(enc3_top,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC3_TOP));
@@ -739,7 +749,7 @@ void encoder_menu(GtkWidget *parent) {
   g_signal_connect(enc4,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC4));
   col++;
   
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
   GtkWidget *enc4_top=gtk_button_new_with_label(encoder_string[e4_top_encoder_action]);
   gtk_grid_attach(GTK_GRID(grid),enc4_top,col,row,1,1);
   g_signal_connect(enc4_top,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC4_TOP));
@@ -753,7 +763,7 @@ void encoder_menu(GtkWidget *parent) {
   row++;
   col=0;
 
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
   GtkWidget *enc5_title=gtk_label_new("ENC5: ");
   gtk_grid_attach(GTK_GRID(grid),enc5_title,col,row,1,1);
   col++;
@@ -763,10 +773,12 @@ void encoder_menu(GtkWidget *parent) {
   g_signal_connect(enc5,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC5));
   col++;
   
+#ifdef CONTROLLER2
   GtkWidget *enc5_top=gtk_button_new_with_label(encoder_string[e5_top_encoder_action]);
   gtk_grid_attach(GTK_GRID(grid),enc5_top,col,row,1,1);
   g_signal_connect(enc5_top,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC5_TOP));
   col++;
+#endif
 
   GtkWidget *enc5_sw=gtk_button_new_with_label(sw_string[e5_sw_action]);
   gtk_grid_attach(GTK_GRID(grid),enc5_sw,col,row,1,1);
@@ -779,229 +791,3 @@ void encoder_menu(GtkWidget *parent) {
 
   gtk_widget_show_all(dialog);
 }
-
-/*
-void encoder_menu(GtkWidget *parent,int e) {
-  GtkWidget *b;
-  int i;
-  BAND *band;
-
-  encoder=e;
-
-  int encoder_action;
-#ifdef CONTROLLER2
-  int top_encoder_action;
-#endif
-  switch(encoder) {
-    case 2:
-      encoder_action=e2_encoder_action;
-      break;
-    case 3:
-      encoder_action=e3_encoder_action;
-      break;
-    case 4:
-      encoder_action=e4_encoder_action;
-      break;
-#ifdef CONTROLLER2
-    case 5:
-      encoder_action=e5_encoder_action;
-      break;
-#endif
-  }
-#ifdef CONTROLLER2
-  switch(encoder) {
-    case 2:
-      top_encoder_action=e2_top_encoder_action;
-      break;
-    case 3:
-      top_encoder_action=e3_top_encoder_action;
-      break;
-    case 4:
-      top_encoder_action=e4_top_encoder_action;
-      break;
-    case 5:
-      top_encoder_action=e5_top_encoder_action;
-      break;
-  }
-#endif
-
-  parent_window=parent;
-
-  dialog=gtk_dialog_new();
-  gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
-  //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE);
-  char title[32];
-  sprintf(title,"piHPSDR - Encoder E%d Action:",encoder);
-  gtk_window_set_title(GTK_WINDOW(dialog),title);
-  g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL);
-
-  GdkRGBA color;
-  color.red = 1.0;
-  color.green = 1.0;
-  color.blue = 1.0;
-  color.alpha = 1.0;
-  gtk_widget_override_background_color(dialog,GTK_STATE_FLAG_NORMAL,&color);
-
-  GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
-
-  GtkWidget *grid=gtk_grid_new();
-
-  gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
-  gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
-  gtk_grid_set_column_spacing (GTK_GRID(grid),5);
-  gtk_grid_set_row_spacing (GTK_GRID(grid),5);
-
-  int row=0;
-  int col=0;
-
-  GtkWidget *close_b=gtk_button_new_with_label("Close");
-  g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
-  gtk_grid_attach(GTK_GRID(grid),close_b,col,row,1,1);
-
-  row++;
-  col=0;
-
-#ifdef CONTROLLER2
-  GtkWidget *bottom_title=gtk_label_new("Bottom");
-  gtk_grid_attach(GTK_GRID(grid),bottom_title,col,row,4,1);
-
-  row++;
-  col=0;
-#endif
-
-  b_af_gain_rx1=gtk_radio_button_new_with_label(NULL,"AF Gain RX1");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_af_gain_rx1), encoder_action==ENCODER_AF_GAIN_RX1);
-  gtk_widget_show(b_af_gain_rx1);
-  gtk_grid_attach(GTK_GRID(grid),b_af_gain_rx1,col,row,2,1);
-  g_signal_connect(b_af_gain_rx1,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_AF_GAIN_RX1);
-
-  row++;
-
-  b_af_gain_rx2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_af_gain_rx1),"AF Gain RX2");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_af_gain_rx2), encoder_action==ENCODER_AF_GAIN_RX2);
-  gtk_widget_show(b_af_gain_rx2);
-  gtk_grid_attach(GTK_GRID(grid),b_af_gain_rx2,col,row,2,1);
-  g_signal_connect(b_af_gain_rx2,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_AF_GAIN_RX2);
-
-  row++;
-
-  b_agc_gain_rx1=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_af_gain_rx2),"AGC Gain RX1");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_agc_gain_rx1), encoder_action==ENCODER_AGC_GAIN_RX1);
-  gtk_widget_show(b_agc_gain_rx1);
-  gtk_grid_attach(GTK_GRID(grid),b_agc_gain_rx1,col,row,2,1);
-  g_signal_connect(b_agc_gain_rx1,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_AGC_GAIN_RX1);
-
-  row++;
-
-  b_agc_gain_rx2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_agc_gain_rx1),"AGC Gain RX2");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_agc_gain_rx2), encoder_action==ENCODER_AGC_GAIN_RX2);
-  gtk_widget_show(b_agc_gain_rx2);
-  gtk_grid_attach(GTK_GRID(grid),b_agc_gain_rx2,col,row,2,1);
-  g_signal_connect(b_agc_gain_rx2,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_AGC_GAIN_RX2);
-
-  row++;
-#ifdef RADIOBERRY
-       b_attenuation=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_agc_gain_rx2),"RX GAIN");
-#else
-       b_attenuation=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_agc_gain_rx2),"Attenuation");
-#endif
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_attenuation), encoder_action==ENCODER_ATTENUATION);
-  gtk_widget_show(b_attenuation);
-  gtk_grid_attach(GTK_GRID(grid),b_attenuation,col,row,2,1);
-  g_signal_connect(b_attenuation,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_ATTENUATION);
-
-  row++;
-
-  b_mic_gain=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_attenuation),"Mic Gain");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_mic_gain), encoder_action==ENCODER_MIC_GAIN);
-  gtk_widget_show(b_mic_gain);
-  gtk_grid_attach(GTK_GRID(grid),b_mic_gain,col,row,2,1);
-  g_signal_connect(b_mic_gain,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_MIC_GAIN);
-
-  row++;
-
-  b_drive=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_mic_gain),"Drive");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_drive), encoder_action==ENCODER_DRIVE);
-  gtk_widget_show(b_drive);
-  gtk_grid_attach(GTK_GRID(grid),b_drive,col,row,2,1);
-  g_signal_connect(b_drive,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_DRIVE);
-
-  b_xit=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_drive),"XIT");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_xit), encoder_action==ENCODER_XIT);
-  gtk_widget_show(b_xit);
-  gtk_grid_attach(GTK_GRID(grid),b_xit,col,row,2,1);
-  g_signal_connect(b_xit,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_XIT);
-
-  col++;
-  row=1;
-
-  b_rit_rx1=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_drive),"RIT RX1");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_rit_rx1), encoder_action==ENCODER_RIT_RX1);
-  gtk_widget_show(b_rit_rx1);
-  gtk_grid_attach(GTK_GRID(grid),b_rit_rx1,col,row,2,1);
-  g_signal_connect(b_rit_rx1,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_RIT_RX1);
-
-  row++;
-
-  b_rit_rx2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_rit_rx1),"RIT RX2");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_rit_rx2), encoder_action==ENCODER_RIT_RX2);
-  gtk_widget_show(b_rit_rx2);
-  gtk_grid_attach(GTK_GRID(grid),b_rit_rx2,col,row,2,1);
-  g_signal_connect(b_rit_rx2,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_RIT_RX2);
-
-  row++;
-
-  b_cw_speed=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_rit_rx2),"CW Speed");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_cw_speed), encoder_action==ENCODER_CW_SPEED);
-  gtk_widget_show(b_cw_speed);
-  gtk_grid_attach(GTK_GRID(grid),b_cw_speed,col,row,2,1);
-  g_signal_connect(b_cw_speed,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_CW_SPEED);
-
-  row++;
-
-  b_cw_frequency=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_cw_speed),"CW Freq");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_cw_frequency), encoder_action==ENCODER_CW_FREQUENCY);
-  gtk_widget_show(b_cw_frequency);
-  gtk_grid_attach(GTK_GRID(grid),b_cw_frequency,col,row,2,1);
-  g_signal_connect(b_cw_frequency,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_CW_FREQUENCY);
-
-  row++;
-
-  b_panadapter_high=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_cw_frequency),"Panadapter High");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_panadapter_high), encoder_action==ENCODER_PANADAPTER_HIGH);
-  gtk_widget_show(b_panadapter_high);
-  gtk_grid_attach(GTK_GRID(grid),b_panadapter_high,col,row,2,1);
-  g_signal_connect(b_panadapter_high,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_PANADAPTER_HIGH);
-
-  row++;
-
-  b_panadapter_low=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_panadapter_high),"Panadapter Low");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_panadapter_low), encoder_action==ENCODER_PANADAPTER_LOW);
-  gtk_widget_show(b_panadapter_low);
-  gtk_grid_attach(GTK_GRID(grid),b_panadapter_low,col,row,2,1);
-  g_signal_connect(b_panadapter_low,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_PANADAPTER_LOW);
-
-  row++;
-
-  b_squelch=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_panadapter_low),"Squelch");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_squelch), encoder_action==ENCODER_SQUELCH);
-  gtk_widget_show(b_squelch);
-  gtk_grid_attach(GTK_GRID(grid),b_squelch,col,row,2,1);
-  g_signal_connect(b_squelch,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_SQUELCH);
-
-  row++;
-
-  b_compression=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_squelch),"COMP");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_compression), encoder_action==ENCODER_COMP);
-  gtk_widget_show(b_compression);
-  gtk_grid_attach(GTK_GRID(grid),b_compression,col,row,2,1);
-  g_signal_connect(b_compression,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_COMP);
-
-  gtk_container_add(GTK_CONTAINER(content),grid);
-
-  sub_menu=dialog;
-
-  gtk_widget_show_all(dialog);
-
-}
-*/
diff --git a/ext.c b/ext.c
index 0d68f255f8625a99e03c15cd1f62b6c125f92363..972e8daa2bac5d77d092e1fa1da9592f20a6b53d 100644 (file)
--- a/ext.c
+++ b/ext.c
@@ -343,21 +343,53 @@ int ext_snb_update(void *data) {
 }
 
 int ext_band_plus(void *data) {
+  long long frequency_min=radio->frequency_min;
+  long long frequency_max=radio->frequency_max;
   int id=active_receiver->id;
   int b=vfo[id].band;
-  b++;
-  if(b>=BANDS) b=0;
-  vfo_band_changed(b);
+  BAND *band;
+  int found=0;
+  while(!found) {
+    b++;
+    if(b>=BANDS+XVTRS) b=0;
+    band=(BAND*)band_get_band(b);
+    if(strlen(band->title)>0) {
+      if(b<BANDS) {
+        if(!(band->frequencyMin==0.0 && band->frequencyMax==0.0)) {
+          if(band->frequencyMin<frequency_min || band->frequencyMax>frequency_max) {
+            continue;
+          }
+        }
+      }
+      vfo_band_changed(b);
+      found=1;
+    }
+  }
   return 0;
 }
 
 
 int ext_band_minus(void *data) {
+  long long frequency_min=radio->frequency_min;
+  long long frequency_max=radio->frequency_max;
   int id=active_receiver->id;
   int b=vfo[id].band;
-  b--;
-  if(b<0) b=BANDS-1;
-  vfo_band_changed(b);
+  BAND *band;
+  int found=0;
+  while(!found) {
+    b--;
+    if(b<0) b=BANDS+XVTRS-1;
+    band=(BAND*)band_get_band(b);
+    if(strlen(band->title)>0) {
+      if(b<BANDS) {
+        if(band->frequencyMin<frequency_min || band->frequencyMax>frequency_max) {
+          continue;
+        }
+      }
+      vfo_band_changed(b);
+      found=1;
+    }
+  }
   return 0;
 }
 
diff --git a/gpio.c b/gpio.c
index 040a1c49d91dcb4c91032c7e30730c815eb47e43..2f17b94c7d3ef1c28f422819ad4b729a5882d577 100644 (file)
--- a/gpio.c
+++ b/gpio.c
@@ -52,7 +52,7 @@
 #include "encoder_menu.h"
 #include "diversity_menu.h"
 #include "gpio.h"
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined(CONTROLLER2_V1)
 #include "i2c.h"
 #endif
 #include "ext.h"
 #endif
 
 // debounce settle time in ms
-#define DEFAULT_SETTLE_TIME 150
+#define DEFAULT_SETTLE_TIME 50
 
 int settle_time=DEFAULT_SETTLE_TIME;
 static gint release_timer=-1;
 
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V1)
+// uses wiringpi pin numbers
+int ENABLE_VFO_ENCODER=1;
+int ENABLE_VFO_PULLUP=1;
+int VFO_ENCODER_A=1;
+int VFO_ENCODER_B=0;
+int ENABLE_E2_ENCODER=1;
+int ENABLE_E2_PULLUP=1;
+int E2_ENCODER_A=28;
+int E2_ENCODER_B=25;
+int E2_FUNCTION=3;
+int ENABLE_E3_ENCODER=1;
+int ENABLE_E3_PULLUP=1;
+int E3_ENCODER_A=7;
+int E3_ENCODER_B=29;
+int E3_FUNCTION=2;
+int ENABLE_E4_ENCODER=1;
+int ENABLE_E4_PULLUP=1;
+int E4_ENCODER_A=27;
+int E4_ENCODER_B=24;
+int E4_FUNCTION=4;
+int ENABLE_E5_ENCODER=1;
+int ENABLE_E5_PULLUP=1;
+int E5_ENCODER_A=6;
+int E5_ENCODER_B=10;
+int E5_FUNCTION=5;
+
+int ENABLE_E2_BUTTON=1;
+int ENABLE_E3_BUTTON=1;
+int ENABLE_E4_BUTTON=1;
+int ENABLE_E5_BUTTON=1;
 
+int I2C_INTERRUPT=16;
+#endif
+#if defined (CONTROLLER2_V2)
+// uses wiringpi pin numbers
 int ENABLE_VFO_ENCODER=1;
 int ENABLE_VFO_PULLUP=0;
 int VFO_ENCODER_A=1;
 int VFO_ENCODER_B=0;
-#ifdef VFO_HAS_FUNCTION
-int VFO_FUNCTION=12;
-#endif
 int ENABLE_E2_ENCODER=1;
 int ENABLE_E2_PULLUP=1;
 int E2_ENCODER_A=21;
@@ -112,8 +143,9 @@ int ENABLE_E4_BUTTON=1;
 int ENABLE_E5_BUTTON=1;
 
 int I2C_INTERRUPT=16;
+#endif
 
-#else
+#if !defined (CONTROLLER2_V2) && !defined (CONTROLLER2_V1)
 // uses wiringpi pin numbers
 int ENABLE_VFO_ENCODER=1;
 int ENABLE_VFO_PULLUP=1;
@@ -167,7 +199,22 @@ int CW_ACTIVE_LOW=1;
 int vfoEncoderPos;
 int vfoFunction;
 
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V1)
+int e2EncoderPos;
+int e2_sw_action=MENU_BAND;
+int e2_encoder_action=ENCODER_AF_GAIN_RX1;
+int e3EncoderPos;
+int e3_sw_action=MENU_MODE;
+int e3_encoder_action=ENCODER_AGC_GAIN_RX1;
+int e4EncoderPos;
+int e4_sw_action=MENU_FILTER;
+int e4_encoder_action=ENCODER_IF_WIDTH_RX1;
+int e5EncoderPos;
+int e5_sw_action=MENU_FREQUENCY;
+int e5_encoder_action=ENCODER_DRIVE;
+#endif
+
+#if defined (CONTROLLER2_V2)
 int e2EncoderPos;
 int e2_sw_action=MENU_BAND;
 int e2_encoder_action=ENCODER_AF_GAIN_RX2;
@@ -177,19 +224,23 @@ int e3_encoder_action=ENCODER_AGC_GAIN_RX2;
 int e4EncoderPos;
 int e4_sw_action=MENU_FILTER;
 int e4_encoder_action=ENCODER_IF_WIDTH_RX2;
+int e5EncoderPos;
+int e5_sw_action=MENU_FREQUENCY;
+int e5_encoder_action=ENCODER_DRIVE;
+#endif
+
+#if defined (CONTROLLER2_V2)
 int e2_top_encoder_action=ENCODER_AF_GAIN_RX1;
 int e3_top_encoder_action=ENCODER_AGC_GAIN_RX1;
 int e4_top_encoder_action=ENCODER_IF_WIDTH_RX1;
+int e5_top_encoder_action=ENCODER_TUNE_DRIVE;
 int e2TopEncoderPos;
 int e3TopEncoderPos;
 int e4TopEncoderPos;
-
-int e5_encoder_action=ENCODER_DRIVE;
-int e5_top_encoder_action=ENCODER_TUNE_DRIVE;
-int e5EncoderPos;
 int e5TopEncoderPos;
-int e5_sw_action=MENU_FREQUENCY;
-#else
+#endif
+
+#if !defined (CONTROLLER2_V2) && !defined (CONTROLLER2_V1)
 int e2EncoderPos;
 int e2_sw_action=RIT;
 int e2_encoder_action=ENCODER_AF_GAIN_RX1;
@@ -293,12 +344,12 @@ char *sw_string[SWITCH_ACTIONS] = {
   "FREQUENCY MENU",
   "MEMORY MENU",
   "DIVERSITY MENU",
-#ifndef CONTROLLER2
+#if !defined (CONTROLLER2_V2) && !defined (CONTROLLER2_V1)
   "FUNCTION",
 #endif
 };
 
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
 int sw_action[SWITCHES] = {TUNE,MOX,PS,TWO_TONE,NR,A_TO_B,B_TO_A,MODE_MINUS,BAND_MINUS,MODE_PLUS,BAND_PLUS,XIT,NB,SNB,LOCK,CTUN};
 #endif
 
@@ -500,7 +551,7 @@ fprintf(stderr,"e_function_pressed: %d\n",action);
     case MENU_DIVERSITY:
       g_idle_add(ext_diversity_update,GINT_TO_POINTER(1));
       break;
-#ifndef CONTROLLER2
+#if !defined (CONTROLLER2_V1) && !defined (CONTROLLER2_V2)
     case FUNCTION:
       g_idle_add(ext_function_update,NULL);
       break;
@@ -536,7 +587,7 @@ static void e4FunctionAlert() {
     }
 }
 
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
 static unsigned long e5debounce=0;
 
 static void e5FunctionAlert() {
@@ -547,216 +598,160 @@ static void e5FunctionAlert() {
 }
 #endif
 
-#ifndef CONTROLLER2
+#if !defined (CONTROLLER2_V2) && !defined (CONTROLLER2_V1)
+static int function_level=1;
 static unsigned long function_debounce=0;
 
 static void functionAlert() {
     int t=millis();
-    if(t-function_debounce > settle_time) {
-      int level=digitalRead(FUNCTION_BUTTON);
+    if(millis()<function_debounce) {
+      return;
+    }
+    int level=digitalRead(FUNCTION_BUTTON);
+    if(level!=function_level) {
       if(level==0) {
         if(running) g_idle_add(function_pressed,NULL);
       }
-      function_debounce=t;
+      function_level=level;
+      function_debounce=t+settle_time;
     }
 }
 
+static int s1_level=1;
 static unsigned long s1_debounce=0;
-static gint s1_timer=-1;
-
-static gboolean s1_timer_cb(gpointer data) {
-    int level=digitalRead(S1_BUTTON);
-    if(level==1) {
-      s1_timer=-1;
-      g_idle_add(s1_released,NULL);
-      return FALSE;
-    }
-    return TRUE;
-}
 
 static void s1Alert() {
     int t=millis();
-    if(t-s1_debounce > settle_time) {
-      int level=digitalRead(S1_BUTTON);
+    if(millis()<s1_debounce) {
+      return;
+    }
+    int level=digitalRead(S1_BUTTON);
+    if(level!=s1_level) {
       if(level==0) {
-        g_idle_add(s1_pressed,NULL);
-        s1_timer=g_timeout_add(settle_time,s1_timer_cb,NULL);
+        if(running) g_idle_add(s1_pressed,NULL);
       } else {
-        if(s1_timer!=-1) {
-          g_source_remove(s1_timer);
-          s1_timer==-1;
-        }
-        g_idle_add(s1_released,NULL);
+        if(running) g_idle_add(s1_released,NULL);
       }
-      s1_debounce=t;
+      s1_level=level;
+      s1_debounce=t+settle_time;
     }
 }
 
+static int s2_level=1;
 static unsigned long s2_debounce=0;
-static gint s2_timer=-1;
-
-static gboolean s2_timer_cb(gpointer data) {
-    int level=digitalRead(S2_BUTTON);
-    if(level==1) {
-      s2_timer=-1;
-      g_idle_add(s2_released,NULL);
-      return FALSE;
-    }
-    return TRUE;
-}
 
 static void s2Alert() {
     int t=millis();
-    if(t-s2_debounce > settle_time) {
-      int level=digitalRead(S2_BUTTON);
+    if(millis()<s2_debounce) {
+      return;
+    }
+    int level=digitalRead(S2_BUTTON);
+    if(level!=s2_level) {
       if(level==0) {
-        g_idle_add(s2_pressed,NULL);
-        s2_timer=g_timeout_add(settle_time,s2_timer_cb,NULL);
+        if(running) g_idle_add(s2_pressed,NULL);
       } else {
-        if(s2_timer!=-1) {
-          g_source_remove(s2_timer);
-          s2_timer==-1;
-        }
-        g_idle_add(s2_released,NULL);
+        if(running) g_idle_add(s2_released,NULL);
       }
-      s2_debounce=t;
+      s2_level=level;
+      s2_debounce=t+settle_time;
     }
 }
 
+static int s3_level=1;
 static unsigned long s3_debounce=0;
-static gint s3_timer=-1;
-
-static gboolean s3_timer_cb(gpointer data) {
-    int level=digitalRead(S3_BUTTON);
-    if(level==1) {
-      s3_timer=-1;
-      g_idle_add(s3_released,NULL);
-      return FALSE;
-    }
-    return TRUE;
-}
 
 static void s3Alert() {
     int t=millis();
-    if(t-s3_debounce > settle_time) {
-      int level=digitalRead(S3_BUTTON);
+    if(millis()<s3_debounce) {
+      return;
+    }
+    int level=digitalRead(S3_BUTTON);
+    if(level!=s3_level) {
       if(level==0) {
-        g_idle_add(s3_pressed,NULL);
-        s3_timer=g_timeout_add(settle_time,s3_timer_cb,NULL);
+        if(running) g_idle_add(s3_pressed,NULL);
       } else {
-        if(s3_timer!=-1) {
-          g_source_remove(s3_timer);
-          s3_timer==-1;
-        }
-        g_idle_add(s3_released,NULL);
+        if(running) g_idle_add(s3_released,NULL);
       }
-      s3_debounce=t;
+      s3_level=level;
+      s3_debounce=t+settle_time;
     }
 }
 
+static int s4_level=1;
 static unsigned long s4_debounce=0;
-static gint s4_timer=-1;
-
-static gboolean s4_timer_cb(gpointer data) {
-    int level=digitalRead(S4_BUTTON);
-    if(level==1) {
-      s4_timer=-1;
-      g_idle_add(s4_released,NULL);
-      return FALSE;
-    }
-    return TRUE;
-}
 
 static void s4Alert() {
     int t=millis();
-    if(t-s4_debounce > settle_time) {
-      int level=digitalRead(S4_BUTTON);
+    if(millis()<s4_debounce) {
+      return;
+    }
+    int level=digitalRead(S4_BUTTON);
+    if(level!=s4_level) {
       if(level==0) {
-        g_idle_add(s4_pressed,NULL);
-        s4_timer=g_timeout_add(settle_time,s4_timer_cb,NULL);
+        if(running) g_idle_add(s4_pressed,NULL);
       } else {
-        if(s4_timer!=-1) {
-          g_source_remove(s4_timer);
-          s4_timer==-1;
-        }
-        g_idle_add(s4_released,NULL);
+        if(running) g_idle_add(s4_released,NULL);
       }
-      s4_debounce=t;
+      s4_level=level;
+      s4_debounce=t+settle_time;
     }
 }
 
+static int s5_level=1;
 static unsigned long s5_debounce=0;
-static gint s5_timer=-1;
-
-static gboolean s5_timer_cb(gpointer data) {
-    int level=digitalRead(S5_BUTTON);
-    if(level==1) {
-      s5_timer=-1;
-      g_idle_add(s5_released,NULL);
-      return FALSE;
-    }
-    return TRUE;
-}
 
 static void s5Alert() {
     int t=millis();
-    if(t-s5_debounce > settle_time) {
-      int level=digitalRead(S5_BUTTON);
+    if(millis()<s5_debounce) {
+      return;
+    }
+    int level=digitalRead(S5_BUTTON);
+    if(level!=s5_level) {
       if(level==0) {
-        g_idle_add(s5_pressed,NULL);
-        s5_timer=g_timeout_add(settle_time,s5_timer_cb,NULL);
+        if(running) g_idle_add(s5_pressed,NULL);
       } else {
-        if(s5_timer!=-1) {
-          g_source_remove(s5_timer);
-          s5_timer==-1;
-        }
-        g_idle_add(s5_released,NULL);
+        if(running) g_idle_add(s5_released,NULL);
       }
-      s5_debounce=t;
+      s5_level=level;
+      s5_debounce=t+settle_time;
     }
 }
 
+static int s6_level=1;
 static unsigned long s6_debounce=0;
-static gint s6_timer=-1;
-
-static gboolean s6_timer_cb(gpointer data) {
-    int level=digitalRead(S6_BUTTON);
-    if(level==1) {
-      s6_timer=-1;
-      g_idle_add(s6_released,NULL);
-      return FALSE;
-    }
-    return TRUE;
-}
 
 static void s6Alert() {
     int t=millis();
-    if(t-s6_debounce > settle_time) {
-      int level=digitalRead(S6_BUTTON);
+    if(millis()<s6_debounce) {
+      return;
+    }
+    int level=digitalRead(S6_BUTTON);
+    if(level!=s6_level) {
       if(level==0) {
-        g_idle_add(s6_pressed,NULL);
-        s6_timer=g_timeout_add(settle_time,s6_timer_cb,NULL);
+        if(running) g_idle_add(s6_pressed,NULL);
       } else {
-        if(s6_timer!=-1) {
-          g_source_remove(s6_timer);
-          s6_timer==-1;
-        }
-        g_idle_add(s6_released,NULL);
+        if(running) g_idle_add(s6_released,NULL);
       }
-      s6_debounce=t;
+      s6_level=level;
+      s6_debounce=t+settle_time;
     }
 }
 
+static int mox_level=1;
 static unsigned long mox_debounce=0;
 
 static void moxAlert() {
     int t=millis();
-    if(t-mox_debounce > settle_time) {
-      int level=digitalRead(MOX_BUTTON);
+    if(millis()<mox_debounce) {
+      return;
+    }
+    int level=digitalRead(MOX_BUTTON);
+    if(level!=mox_level) {
       if(level==0) {
-        g_idle_add(mox_pressed,(gpointer)NULL);
+        if(running) g_idle_add(mox_pressed,NULL);
       }
-      mox_debounce=t;
+      mox_level=level;
+      mox_debounce=t+settle_time;
     }
 }
 #endif
@@ -840,7 +835,7 @@ static void e2EncoderB() {
   e2EncoderInterrupt(E2_ENCODER_B);
 }
 
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2)
 static void e2TopEncoderInterrupt(int gpio) {
   static int e2TopCurrentA=1, e2TopCurrentB=1;
 
@@ -884,7 +879,7 @@ static void e3EncoderB() {
   e3EncoderInterrupt(E3_ENCODER_B);
 }
 
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2)
 static void e3TopEncoderInterrupt(int gpio) {
   static int e3TopCurrentA=1, e3TopCurrentB=1;
 
@@ -929,7 +924,7 @@ static void e4EncoderB() {
   e4EncoderInterrupt(E4_ENCODER_B);
 }
 
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2)
 static void e4TopEncoderInterrupt(int gpio) {
   static int e4TopCurrentA=1, e4TopCurrentB=1;
 
@@ -953,7 +948,7 @@ static void e4TopEncoderB() {
 #endif
 
 
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2)  || defined (CONTROLLER2_V1)
 static void e5EncoderInterrupt(int gpio) {
   static int e5CurrentA=1, e5CurrentB=1;
 
@@ -975,7 +970,9 @@ static void e5EncoderA() {
 static void e5EncoderB() {
   e5EncoderInterrupt(E5_ENCODER_B);
 }
+#endif
 
+#if defined (CONTROLLER2_V2)
 static void e5TopEncoderInterrupt(int gpio) {
   static int e5TopCurrentA=1, e5TopCurrentB=1;
 
@@ -996,10 +993,10 @@ static void e5TopEncoderA() {
 static void e5TopEncoderB() {
   e5TopEncoderInterrupt(E5_TOP_ENCODER_B);
 }
-
 #endif
 
-#ifdef CONTROLLER2
+
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
 static void pI2CInterrupt() {
     int level=digitalRead(I2C_INTERRUPT);
     if(level==0) {
@@ -1013,6 +1010,8 @@ void gpio_restore_actions() {
   char name[80];
   int i;
 
+  value=getProperty("settle_time");
+  if(value) settle_time=atoi(value);
   value=getProperty("e2_encoder_action");
   if(value) e2_encoder_action=atoi(value);
   value=getProperty("e2_sw_action");
@@ -1025,17 +1024,23 @@ void gpio_restore_actions() {
   if(value) e4_encoder_action=atoi(value);
   value=getProperty("e4_sw_action");
   if(value) e4_sw_action=atoi(value);
-#ifdef CONTROLLER2
+
+#if defined (CONTROLLER2_V2)
   value=getProperty("e2_top_encoder_action");
   if(value) e2_top_encoder_action=atoi(value);
   value=getProperty("e3_top_encoder_action");
   if(value) e3_top_encoder_action=atoi(value);
   value=getProperty("e4_top_encoder_action");
   if(value) e4_top_encoder_action=atoi(value);
+#endif
+
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
   value=getProperty("e5_encoder_action");
   if(value) e5_encoder_action=atoi(value);
+#if defined (CONTROLLER2_V2)
   value=getProperty("e5_top_encoder_action");
   if(value) e5_top_encoder_action=atoi(value);
+#endif
   value=getProperty("e5_sw_action");
   if(value) e5_sw_action=atoi(value);
   for(i=0;i<SWITCHES;i++) {
@@ -1085,7 +1090,7 @@ void gpio_restore_state() {
   if(value) E4_ENCODER_A=atoi(value);
   value=getProperty("E4_ENCODER_B");
   if(value) E4_ENCODER_B=atoi(value);
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
   value=getProperty("ENABLE_E5_ENCODER");
   if(value) ENABLE_E5_ENCODER=atoi(value);
   value=getProperty("ENABLE_E5_PULLUP");
@@ -1095,7 +1100,7 @@ void gpio_restore_state() {
   value=getProperty("E5_ENCODER_B");
   if(value) E5_ENCODER_B=atoi(value);
 #endif
-#ifndef CONTROLLER2
+#if !defined (CONTROLLER2_V2) && !defined(CONTROLLER2_V1)
   value=getProperty("ENABLE_S1_BUTTON");
   if(value) ENABLE_S1_BUTTON=atoi(value);
   value=getProperty("S1_BUTTON");
@@ -1136,7 +1141,7 @@ void gpio_restore_state() {
   if(value) ENABLE_E3_BUTTON=atoi(value);
   value=getProperty("ENABLE_E4_BUTTON");
   if(value) ENABLE_E4_BUTTON=atoi(value);
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
   value=getProperty("ENABLE_E5_BUTTON");
   if(value) ENABLE_E5_BUTTON=atoi(value);
 #endif
@@ -1161,6 +1166,9 @@ void gpio_save_actions() {
   int i;
   char name[80];
   char value[80];
+
+  sprintf(value,"%d",settle_time);
+  setProperty("settle_time",value);
   sprintf(value,"%d",e2_sw_action);
   setProperty("e2_sw_action",value);
   sprintf(value,"%d",e2_encoder_action);
@@ -1173,19 +1181,23 @@ void gpio_save_actions() {
   setProperty("e4_sw_action",value);
   sprintf(value,"%d",e4_encoder_action);
   setProperty("e4_encoder_action",value);
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
+  sprintf(value,"%d",e5_sw_action);
+  setProperty("e5_sw_action",value);
+  sprintf(value,"%d",e5_encoder_action);
+  setProperty("e5_encoder_action",value);
+#endif
+#if defined (CONTROLLER2_V2)
   sprintf(value,"%d",e2_top_encoder_action);
   setProperty("e2_top_encoder_action",value);
   sprintf(value,"%d",e3_top_encoder_action);
   setProperty("e3_top_encoder_action",value);
   sprintf(value,"%d",e4_top_encoder_action);
   setProperty("e4_top_encoder_action",value);
-  sprintf(value,"%d",e5_sw_action);
-  setProperty("e5_sw_action",value);
-  sprintf(value,"%d",e5_encoder_action);
-  setProperty("e5_encoder_action",value);
   sprintf(value,"%d",e5_top_encoder_action);
   setProperty("e5_top_encoder_action",value);
+#endif
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
   for(i=0;i<SWITCHES;i++) {
     sprintf(name,"sw_action[%d]",i);
     sprintf(value,"%d",sw_action[i]);
@@ -1232,7 +1244,7 @@ void gpio_save_state() {
   setProperty("E4_ENCODER_A",value);
   sprintf(value,"%d",E4_ENCODER_B);
   setProperty("E4_ENCODER_B",value);
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
   sprintf(value,"%d",ENABLE_E5_ENCODER);
   setProperty("ENABLE_E5_ENCODER",value);
   sprintf(value,"%d",ENABLE_E5_PULLUP);
@@ -1242,7 +1254,7 @@ void gpio_save_state() {
   sprintf(value,"%d",E5_ENCODER_B);
   setProperty("E5_ENCODER_B",value);
 #endif
-#ifndef CONTROLLER2
+#if !defined(CONTROLLER2_V2) && !defined(CONTROLLER2_V1)
   sprintf(value,"%d",ENABLE_S1_BUTTON);
   setProperty("ENABLE_S1_BUTTON",value);
   sprintf(value,"%d",S1_BUTTON);
@@ -1283,7 +1295,7 @@ void gpio_save_state() {
   setProperty("ENABLE_E3_BUTTON",value);
   sprintf(value,"%d",ENABLE_E4_BUTTON);
   setProperty("ENABLE_E4_BUTTON",value);
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
   sprintf(value,"%d",ENABLE_E5_BUTTON);
   setProperty("ENABLE_E5_BUTTON",value);
 #endif
@@ -1311,7 +1323,7 @@ static void setup_pin(int pin, int up_down, void(*pAlert)(void)) {
   pinMode(pin,INPUT);
   pullUpDnControl(pin,up_down);
   usleep(10000);
-  rc=wiringPiISR(pin,INT_EDGE_FALLING,pAlert);
+  rc=wiringPiISR(pin,INT_EDGE_BOTH,pAlert);
   if(rc<0) {
     fprintf(stderr,"wirngPiISR returned %d\n",rc);
   }
@@ -1401,7 +1413,7 @@ int gpio_init() {
   wiringPiSetup(); // use WiringPi pin numbers
 
   if(ENABLE_VFO_ENCODER) {
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
 #ifdef VFO_HAS_FUNCTION
     setup_pin(VFO_FUNCTION, PUD_UP, &vfoFunctionAlert);
     vfoFunction=0;
@@ -1422,14 +1434,12 @@ int gpio_init() {
          
     setup_encoder_pin(E2_ENCODER_A,ENABLE_E2_PULLUP?PUD_UP:PUD_OFF,&e2EncoderA);
     setup_encoder_pin(E2_ENCODER_B,ENABLE_E2_PULLUP?PUD_UP:PUD_OFF,NULL);
-    //setup_encoder_pin(E2_ENCODER_B,ENABLE_E2_PULLUP?PUD_UP:PUD_OFF,&e2EncoderB);
     e2EncoderPos=0;
 
 
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
     setup_encoder_pin(E2_TOP_ENCODER_A,ENABLE_E2_PULLUP?PUD_UP:PUD_OFF,&e2TopEncoderA);
     setup_encoder_pin(E2_TOP_ENCODER_B,ENABLE_E2_PULLUP?PUD_UP:PUD_OFF,NULL);
-    //setup_encoder_pin(E2_TOP_ENCODER_B,ENABLE_E2_PULLUP?PUD_UP:PUD_OFF,&e2TopEncoderB);
     e2TopEncoderPos=0;
 #endif
   }
@@ -1439,13 +1449,11 @@ int gpio_init() {
        
     setup_encoder_pin(E3_ENCODER_A,ENABLE_E3_PULLUP?PUD_UP:PUD_OFF,&e3EncoderA);
     setup_encoder_pin(E3_ENCODER_B,ENABLE_E3_PULLUP?PUD_UP:PUD_OFF,NULL);
-    //setup_encoder_pin(E3_ENCODER_B,ENABLE_E3_PULLUP?PUD_UP:PUD_OFF,&e3EncoderB);
     e3EncoderPos=0;
 
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
     setup_encoder_pin(E3_TOP_ENCODER_A,ENABLE_E3_PULLUP?PUD_UP:PUD_OFF,&e3TopEncoderA);
     setup_encoder_pin(E3_TOP_ENCODER_B,ENABLE_E3_PULLUP?PUD_UP:PUD_OFF,NULL);
-    //setup_encoder_pin(E3_TOP_ENCODER_B,ENABLE_E3_PULLUP?PUD_UP:PUD_OFF,&e3TopEncoderB);
     e3TopEncoderPos=0;
 #endif
   }
@@ -1455,36 +1463,34 @@ int gpio_init() {
          
     setup_encoder_pin(E4_ENCODER_A,ENABLE_E4_PULLUP?PUD_UP:PUD_OFF,&e4EncoderA);
     setup_encoder_pin(E4_ENCODER_B,ENABLE_E4_PULLUP?PUD_UP:PUD_OFF,NULL);
-    //setup_encoder_pin(E4_ENCODER_B,ENABLE_E4_PULLUP?PUD_UP:PUD_OFF,&e4EncoderB);
     e4EncoderPos=0;
          
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
     setup_encoder_pin(E4_TOP_ENCODER_A,ENABLE_E4_PULLUP?PUD_UP:PUD_OFF,&e4TopEncoderA);
     setup_encoder_pin(E4_TOP_ENCODER_B,ENABLE_E4_PULLUP?PUD_UP:PUD_OFF,NULL);
-    //setup_encoder_pin(E4_TOP_ENCODER_B,ENABLE_E4_PULLUP?PUD_UP:PUD_OFF,&e4TopEncoderB);
     e4TopEncoderPos=0;
 #endif
   }
 
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
   if(ENABLE_E5_ENCODER) {
     setup_pin(E5_FUNCTION, PUD_UP, &e5FunctionAlert);
 
     setup_encoder_pin(E5_ENCODER_A,ENABLE_E5_PULLUP?PUD_UP:PUD_OFF,&e5EncoderA);
     setup_encoder_pin(E5_ENCODER_B,ENABLE_E5_PULLUP?PUD_UP:PUD_OFF,NULL);
-    //setup_encoder_pin(E5_ENCODER_B,ENABLE_E5_PULLUP?PUD_UP:PUD_OFF,&e5EncoderB);
     e5EncoderPos=0;
 
+#if defined (CONTROLLER2_V2)
     setup_encoder_pin(E5_TOP_ENCODER_A,ENABLE_E5_PULLUP?PUD_UP:PUD_OFF,&e5TopEncoderA);
     setup_encoder_pin(E5_TOP_ENCODER_B,ENABLE_E5_PULLUP?PUD_UP:PUD_OFF,NULL);
-    //setup_encoder_pin(E5_TOP_ENCODER_B,ENABLE_E5_PULLUP?PUD_UP:PUD_OFF,&e5TopEncoderB);
     e5TopEncoderPos=0;
+#endif
   }
 #endif
 
-#ifndef CONTROLLER2
+#if !defined (CONTROLLER2_V2) && !defined(CONTROLLER2_V1)
   if(ENABLE_FUNCTION_BUTTON) {
-    //setup_pin(FUNCTION_BUTTON, PUD_UP, &functionAlert);
+    setup_pin(FUNCTION_BUTTON, PUD_UP, &functionAlert);
   }
 
   if(ENABLE_MOX_BUTTON) {
@@ -1524,7 +1530,7 @@ int gpio_init() {
   }
   fprintf(stderr, "rotary_encoder_thread: id=%p\n",rotary_encoder_thread_id);
 
-#ifdef CONTROLLER2
+#if defined(CONTROLLER2_V2) || defined (CONTROLLER2_V1)
   // setup i2c
   i2c_init();
 
@@ -1596,11 +1602,19 @@ int e4_encoder_get_pos() {
     return pos;
 }
 
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
+int e5_encoder_get_pos() {
+    int pos=e5EncoderPos;
+    e5EncoderPos=0;
+    return pos;
+}
+#endif
+
 int e4_function_get_state() {
     return e4_sw_action;
 }
 
-#ifdef CONTROLLER2
+#ifdef CONTROLLER2_V2
 int e2_top_encoder_get_pos() {
     int pos=e2TopEncoderPos;
     e2TopEncoderPos=0;
@@ -1619,12 +1633,6 @@ int e4_top_encoder_get_pos() {
     return pos;
 }
 
-int e5_encoder_get_pos() {
-    int pos=e5EncoderPos;
-    e5EncoderPos=0;
-    return pos;
-}
-
 int e5_top_encoder_get_pos() {
     int pos=e5TopEncoderPos;
     e5TopEncoderPos=0;
@@ -1868,7 +1876,6 @@ static int e2_encoder_changed(void *data) {
   } else {
     encoder_changed(e2_encoder_action,pos);
   }
-  //free(data);
   return 0;
 }
 
@@ -1879,7 +1886,6 @@ static int e3_encoder_changed(void *data) {
   } else {
     encoder_changed(e3_encoder_action,pos);
   }
-  //free(data);
   return 0;
 }
 
@@ -1890,11 +1896,23 @@ static int e4_encoder_changed(void *data) {
   } else {
     encoder_changed(e4_encoder_action,pos);
   }
-  //free(data);
   return 0;
 }
 
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
+static int e5_encoder_changed(void *data) {
+  int pos=(int)data;
+  if(active_menu==E5_MENU) {
+    encoder_select(pos);
+  } else {
+    encoder_changed(e5_encoder_action,pos);
+  }
+  return 0;
+}
+#endif
+
+
+#ifdef CONTROLLER2_V2
 static int e2_top_encoder_changed(void *data) {
   int pos=(int)data;
   if(active_menu==E2_MENU) {
@@ -1902,7 +1920,6 @@ static int e2_top_encoder_changed(void *data) {
   } else {
     encoder_changed(e2_top_encoder_action,pos);
   }
-  //free(data);
   return 0;
 }
 
@@ -1913,7 +1930,6 @@ static int e3_top_encoder_changed(void *data) {
   } else {
     encoder_changed(e3_top_encoder_action,pos);
   }
-  //free(data);
   return 0;
 }
 
@@ -1924,18 +1940,6 @@ static int e4_top_encoder_changed(void *data) {
   } else {
     encoder_changed(e4_top_encoder_action,pos);
   }
-  //free(data);
-  return 0;
-}
-
-static int e5_encoder_changed(void *data) {
-  int pos=(int)data;
-  if(active_menu==E5_MENU) {
-    encoder_select(pos);
-  } else {
-    encoder_changed(e5_encoder_action,pos);
-  }
-  //free(data);
   return 0;
 }
 
@@ -1946,7 +1950,6 @@ static int e5_top_encoder_changed(void *data) {
   } else {
     encoder_changed(e5_top_encoder_action,pos);
   }
-  //free(data);
   return 0;
 }
 #endif
@@ -1979,7 +1982,14 @@ static gpointer rotary_encoder_thread(gpointer data) {
             g_idle_add(e4_encoder_changed,(gpointer)pos);
         }
 
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
+        pos=e5_encoder_get_pos();
+        if(pos!=0) {
+            g_idle_add(e5_encoder_changed,(gpointer)pos);
+        }
+#endif
+
+#if defined (CONTROLLER2_V2)
         pos=e2_top_encoder_get_pos();
         if(pos!=0) {
             g_idle_add(e2_top_encoder_changed,(gpointer)pos);
@@ -1995,11 +2005,6 @@ static gpointer rotary_encoder_thread(gpointer data) {
             g_idle_add(e4_top_encoder_changed,(gpointer)pos);
         }
 
-        pos=e5_encoder_get_pos();
-        if(pos!=0) {
-            g_idle_add(e5_encoder_changed,(gpointer)pos);
-        }
-
         pos=e5_top_encoder_get_pos();
         if(pos!=0) {
             g_idle_add(e5_top_encoder_changed,(gpointer)pos);
diff --git a/gpio.h b/gpio.h
index 67575451179ae701f706a6e7d72faec46f66b5e4..2d825367b6d740b2a8158bd1b3c537a49827064c 100644 (file)
--- a/gpio.h
+++ b/gpio.h
@@ -92,7 +92,7 @@ enum {
 extern char *sw_string[SWITCH_ACTIONS];
 
 
-#ifndef CONTROLLER2
+#if !defined (CONTROLLER2_V2) && !defined (CONTROLLER2_V1)
 #define SWITCHES 8
 enum {
   SW1=0,
@@ -104,7 +104,9 @@ enum {
   SW7,
   SW8
 };
-#else
+#endif
+
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
 #define SWITCHES 16
 enum {
   SW2=0,
@@ -165,7 +167,7 @@ extern int ENABLE_E4_ENCODER;
 extern int ENABLE_E4_PULLUP;
 extern int E4_ENCODER_A;
 extern int E4_ENCODER_B;
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
 extern int ENABLE_E5_ENCODER;
 extern int ENABLE_E5_PULLUP;
 extern int E5_ENCODER_A;
diff --git a/i2c.c b/i2c.c
index 9b297c832afe35bde09dcdf214afef29a404a491..d299a612b477ccd25857a92ba21a31377268beb9 100644 (file)
--- a/i2c.c
+++ b/i2c.c
@@ -152,6 +152,7 @@ void i2c_interrupt() {
           case SW_8:
             i=SW8;
             break;
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
           case SW_9:
             i=SW9;
             break;
@@ -179,6 +180,7 @@ void i2c_interrupt() {
           case SW_17:
             i=SW17;
             break;
+#endif
         }
 //g_print("i1c_interrupt: sw=%d action=%d\n",i,sw_action[i]);
         switch(sw_action[i]) {
index 67b95ce542a29d176d98b9b378bcc6b9c13f0372..41ad20fe3568dcb0494ad7cc4fd2eba8f3c3c76e 100644 (file)
@@ -190,6 +190,7 @@ gpointer new_discover_receive_thread(gpointer data) {
     int bytes_read;
     struct timeval tv;
     int i;
+    double frequency_min, frequency_max;
 
     tv.tv_sec = 2;
     tv.tv_usec = 0;
@@ -219,27 +220,43 @@ gpointer new_discover_receive_thread(gpointer data) {
                     switch(discovered[devices].device) {
                        case NEW_DEVICE_ATLAS:
                             strcpy(discovered[devices].name,"Atlas");
+                            frequency_min=0.0;
+                            frequency_max=61440000.0;
                             break;
                        case NEW_DEVICE_HERMES:
                             strcpy(discovered[devices].name,"Hermes");
+                            frequency_min=0.0;
+                            frequency_max=61440000.0;
                             break;
                        case NEW_DEVICE_HERMES2:
                             strcpy(discovered[devices].name,"Hermes2");
+                            frequency_min=0.0;
+                            frequency_max=61440000.0;
                             break;
                        case NEW_DEVICE_ANGELIA:
                             strcpy(discovered[devices].name,"Angelia");
+                            frequency_min=0.0;
+                            frequency_max=61440000.0;
                             break;
                        case NEW_DEVICE_ORION:
                             strcpy(discovered[devices].name,"Orion");
+                            frequency_min=0.0;
+                            frequency_max=61440000.0;
                             break;
                        case NEW_DEVICE_ORION2:
                             strcpy(discovered[devices].name,"Orion2");
+                            frequency_min=0.0;
+                            frequency_max=61440000.0;
                             break;
                        case NEW_DEVICE_HERMES_LITE:
                             strcpy(discovered[devices].name,"Hermes Lite");
+                            frequency_min=0.0;
+                            frequency_max=30720000.0;
                             break;
                         default:
                             strcpy(discovered[devices].name,"Unknown");
+                            frequency_min=0.0;
+                            frequency_max=30720000.0;
                             break;
                     }
                     discovered[devices].software_version=buffer[13]&0xFF;
@@ -267,6 +284,8 @@ gpointer new_discover_receive_thread(gpointer data) {
                             discovered[devices].info.network.mac_address[4],
                             discovered[devices].info.network.mac_address[5],
                             discovered[devices].info.network.interface_name);
+                            discovered[devices].frequency_min=frequency_min;
+                            discovered[devices].frequency_max=frequency_max;
                     devices++;
                 }
             }
index 2d31ca83a752802efa4416f0b2fadbe9b37bf1a5..3a922399f9b08ccf0eaf27076f3e4e4749b95c5a 100644 (file)
@@ -56,7 +56,7 @@
 #include "tx_menu.h"
 #include "ps_menu.h"
 #include "encoder_menu.h"
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
 #include "switch_menu.h"
 #endif
 #include "vfo_menu.h"
@@ -165,7 +165,7 @@ static gboolean encoder_cb (GtkWidget *widget, GdkEventButton *event, gpointer d
   return TRUE;
 }
 
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
 static gboolean switch_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   cleanup();
   fprintf(stderr, "new_menu: calling switch_menu\n");
@@ -582,7 +582,7 @@ void new_menu()
     gtk_grid_attach(GTK_GRID(grid),encoders_b,(i%5),i/5,1,1);
     i++;
 
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
     GtkWidget *switches_b=gtk_button_new_with_label("Switches");
     g_signal_connect (switches_b, "button-press-event", G_CALLBACK(switch_cb), NULL);
     gtk_grid_attach(GTK_GRID(grid),switches_b,(i%5),i/5,1,1);
index 48c48e59c0ab4d421ec7cfa9016a1d7fdfde117b..4c2bacac1cfb4f4d5822a1f97b2c5f788637ada2 100644 (file)
@@ -389,11 +389,11 @@ fprintf(stderr,"discover_receive_thread\n");
         bytes_read=recvfrom(discovery_socket,buffer,sizeof(buffer),1032,(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");
+            perror("old_discovery: recvfrom socket failed for discover_receive_thread");
             break;
         }
         if (bytes_read == 0) break;
-        fprintf(stderr,"Old Protocol discovered: received %d bytes\n",bytes_read);
+        fprintf(stderr,"old_discovery: 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) {
@@ -403,39 +403,57 @@ fprintf(stderr,"discover_receive_thread\n");
                     switch(discovered[devices].device) {
                         case DEVICE_METIS:
                             strcpy(discovered[devices].name,"Metis");
+                            discovered[devices].frequency_min=0.0;
+                            discovered[devices].frequency_max=61440000.0;
                             break;
                         case DEVICE_HERMES:
                             strcpy(discovered[devices].name,"Hermes");
+                            discovered[devices].frequency_min=0.0;
+                            discovered[devices].frequency_max=61440000.0;
                             break;
                         case DEVICE_GRIFFIN:
                             strcpy(discovered[devices].name,"Griffin");
+                            discovered[devices].frequency_min=0.0;
+                            discovered[devices].frequency_max=61440000.0;
                             break;
                         case DEVICE_ANGELIA:
                             strcpy(discovered[devices].name,"Angelia");
+                            discovered[devices].frequency_min=0.0;
+                            discovered[devices].frequency_max=61440000.0;
                             break;
                         case DEVICE_ORION:
                             strcpy(discovered[devices].name,"Orion");
+                            discovered[devices].frequency_min=0.0;
+                            discovered[devices].frequency_max=61440000.0;
                             break;
                         case DEVICE_HERMES_LITE:
-                                                       #ifdef RADIOBERRY
-                                                               strcpy(discovered[devices].name,"Radioberry");
-                                                       #else
-                                                               strcpy(discovered[devices].name,"Hermes Lite");         
-                                                       #endif
-
+#ifdef RADIOBERRY
+                            strcpy(discovered[devices].name,"Radioberry");
+#else
+                            strcpy(discovered[devices].name,"Hermes Lite");            
+#endif
+                            discovered[devices].frequency_min=0.0;
+                            discovered[devices].frequency_max=30720000.0;
                             break;
                         case DEVICE_ORION2:
                             strcpy(discovered[devices].name,"Orion2");
+                            discovered[devices].frequency_min=0.0;
+                            discovered[devices].frequency_max=61440000.0;
                             break;
                        case DEVICE_STEMLAB:
                            // This is in principle the same as HERMES but has two ADCs
                            // (and therefore, can do DIVERSITY).
                             strcpy(discovered[devices].name,"STEMlab");
+                            discovered[devices].frequency_min=0.0;
+                            discovered[devices].frequency_max=30720000.0;
                             break;
                         default:
                             strcpy(discovered[devices].name,"Unknown");
+                            discovered[devices].frequency_min=0.0;
+                            discovered[devices].frequency_max=61440000.0;
                             break;
                     }
+g_print("old_discovery: name=%s min=%f max=%f\n",discovered[devices].name, discovered[devices].frequency_min, discovered[devices].frequency_max);
                     discovered[devices].software_version=buffer[9]&0xFF;
                     for(i=0;i<6;i++) {
                         discovered[devices].info.network.mac_address[i]=buffer[i+3];
@@ -448,7 +466,7 @@ fprintf(stderr,"discover_receive_thread\n");
                     discovered[devices].info.network.interface_length=sizeof(interface_addr);
                     strcpy(discovered[devices].info.network.interface_name,interface_name);
                    discovered[devices].use_tcp=0;
-                   fprintf(stderr,"discovery: found device=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n",
+                   fprintf(stderr,"old_discovery: found device=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s min=%f max=%f\n",
                             discovered[devices].device,
                             discovered[devices].software_version,
                             discovered[devices].status,
@@ -459,7 +477,9 @@ fprintf(stderr,"discover_receive_thread\n");
                             discovered[devices].info.network.mac_address[3],
                             discovered[devices].info.network.mac_address[4],
                             discovered[devices].info.network.mac_address[5],
-                            discovered[devices].info.network.interface_name);
+                            discovered[devices].info.network.interface_name,
+                            discovered[devices].frequency_min,
+                            discovered[devices].frequency_max);
                     devices++;
                 }
             }
diff --git a/radio.c b/radio.c
index 20f4e7918afec2d9ceede3b6b4ca12e35b490dea..faa0ee793a7e5fd42837630623e68f6bb455307d 100644 (file)
--- a/radio.c
+++ b/radio.c
@@ -142,7 +142,7 @@ RECEIVER *receiver[MAX_RECEIVERS];
 RECEIVER *active_receiver;
 TRANSMITTER *transmitter;
 
-int buffer_size=1024; // 64, 128, 256, 512, 1024
+int buffer_size=2048; // 64, 128, 256, 512, 1024, 2048
 int fft_size=2048; // 1024, 2048, 4096, 8192, 16384
 
 int atlas_penelope=0;
@@ -179,8 +179,8 @@ double display_average_time=120.0;
 int waterfall_high=-100;
 int waterfall_low=-150;
 
-int display_sliders=1;
-int display_toolbar=1;
+int display_sliders=0;
+int display_toolbar=0;
 
 //double volume=0.2;
 double mic_gain=0.0;
@@ -321,11 +321,14 @@ void reconfigure_radio() {
   int i;
   int y;
 //fprintf(stderr,"reconfigure_radio: receivers=%d\n",receivers);
-  int rx_height=display_height-VFO_HEIGHT-TOOLBAR_HEIGHT;
+  int rx_height=display_height-VFO_HEIGHT;
   if(display_sliders) {
     rx_height-=SLIDERS_HEIGHT;
   }
+  if(display_toolbar) {
+    rx_height-=TOOLBAR_HEIGHT;
+  }
+
   y=VFO_HEIGHT;
   for(i=0;i<receivers;i++) {
     reconfigure_receiver(receiver[i],rx_height/receivers);
@@ -344,6 +347,7 @@ void reconfigure_radio() {
     }
     gtk_widget_show_all(sliders);  // ... this shows both C25 and Alex ATT/Preamp sliders
     att_type_changed();            // ... and this hides the â€žwrong“ ones.
+    y+=SLIDERS_HEIGHT;
   } else {
     if(sliders!=NULL) {
       gtk_container_remove(GTK_CONTAINER(fixed),sliders); 
@@ -351,6 +355,21 @@ void reconfigure_radio() {
     }
   }
 
+  if(display_toolbar) {
+    if(toolbar==NULL) {
+      toolbar = toolbar_init(display_width,TOOLBAR_HEIGHT,top_window);
+      gtk_fixed_put(GTK_FIXED(fixed),toolbar,0,y);
+    } else {
+      gtk_fixed_move(GTK_FIXED(fixed),toolbar,0,y);
+    }
+    gtk_widget_show_all(toolbar);
+  } else {
+    if(toolbar!=NULL) {
+      gtk_container_remove(GTK_CONTAINER(fixed),toolbar);
+      toolbar=NULL;
+    }
+  }
+
   if(can_transmit) {
     reconfigure_transmitter(transmitter,rx_height);
   }
@@ -649,7 +668,7 @@ void start_radio() {
   adc[0].preamp=FALSE;
   adc[0].attenuation=0;
 #ifdef SOAPYSDR
-  adc[0].antenna=1; // LNAH
+  adc[0].antenna=2; // LNAL
   if(radio->device==SOAPYSDR_USB_DEVICE) {
     adc[0].rx_gain=malloc(radio->info.soapy.rx_gains*sizeof(gint));
     for (size_t i = 0; i < radio->info.soapy.rx_gains; i++) {
@@ -692,9 +711,9 @@ void start_radio() {
 
 //fprintf(stderr,"meter_calibration=%f display_calibration=%f\n", meter_calibration, display_calibration);
 
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
   display_sliders=0;
-  display_toolbar=1;
+  display_toolbar=0;
 #else
   display_sliders=1;
   display_toolbar=1;
@@ -836,12 +855,6 @@ void start_radio() {
 #endif
   }
 
-
-
-//#ifdef I2C
-//  i2c_init();
-//#endif
-
   if(display_sliders) {
 //fprintf(stderr,"create sliders\n");
     sliders = sliders_init(display_width,SLIDERS_HEIGHT);
diff --git a/release/pihpsdr-controller1.v2.0.0-beta.tar b/release/pihpsdr-controller1.v2.0.0-beta.tar
new file mode 100644 (file)
index 0000000..0ce5acb
Binary files /dev/null and b/release/pihpsdr-controller1.v2.0.0-beta.tar differ
diff --git a/release/pihpsdr-controller2-v1.v2.0.0-beta.tar b/release/pihpsdr-controller2-v1.v2.0.0-beta.tar
new file mode 100644 (file)
index 0000000..77b4d10
Binary files /dev/null and b/release/pihpsdr-controller2-v1.v2.0.0-beta.tar differ
diff --git a/release/pihpsdr-controller2-v2.v2.0.0-beta.tar b/release/pihpsdr-controller2-v2.v2.0.0-beta.tar
new file mode 100644 (file)
index 0000000..98c0b40
Binary files /dev/null and b/release/pihpsdr-controller2-v2.v2.0.0-beta.tar differ
diff --git a/release/pihpsdr-nocontroller.v2.0.0-beta.tar b/release/pihpsdr-nocontroller.v2.0.0-beta.tar
new file mode 100644 (file)
index 0000000..e4bfd19
Binary files /dev/null and b/release/pihpsdr-nocontroller.v2.0.0-beta.tar differ
index b622ef8cb91465aaeb06070d0127e5383c170791..0ce5acbb9e20f229ba7fe4adfb643bb6d24a2cf2 100644 (file)
Binary files a/release/pihpsdr-v2.0.0-beta.tar and b/release/pihpsdr-v2.0.0-beta.tar differ
index b622ef8cb91465aaeb06070d0127e5383c170791..0ce5acbb9e20f229ba7fe4adfb643bb6d24a2cf2 100644 (file)
Binary files a/release/pihpsdr.tar and b/release/pihpsdr.tar differ
diff --git a/release/pihpsdr/64-limesuite.rules b/release/pihpsdr/64-limesuite.rules
new file mode 100644 (file)
index 0000000..9093aa6
--- /dev/null
@@ -0,0 +1,5 @@
+SUBSYSTEM=="usb", ATTR{idVendor}=="04b4", ATTR{idProduct}=="8613", SYMLINK+="stream-%k", MODE="666"
+SUBSYSTEM=="usb", ATTR{idVendor}=="04b4", ATTR{idProduct}=="00f1", SYMLINK+="stream-%k", MODE="666"
+SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="601f", SYMLINK+="stream-%k", MODE="666"
+SUBSYSTEM=="usb", ATTR{idVendor}=="1d50", ATTR{idProduct}=="6108", SYMLINK+="stream-%k", MODE="666"
+SUBSYSTEM=="xillybus", MODE="666", OPTIONS="last_rule"
diff --git a/release/pihpsdr/README.MIDI b/release/pihpsdr/README.MIDI
new file mode 100644 (file)
index 0000000..05d3e6a
--- /dev/null
@@ -0,0 +1,188 @@
+MIDI support in piHPSDR - Manual for Users
+==========================================
+
+
+To use MIDI devices in piHPSDR, you must provide a file "midi.inp" that resides
+in the current working dir of piHPSDR (that is, where the "*.props" file and
+the WDSP wisdom files also reside).
+
+A sample midi.inp file for the popular Behringer "CMD PL-1" MIDI console is
+provided as an example. The basic rules for the file are
+
+- the file is line-oriented. Each line contains a directive
+
+- in each line, a "#" sign denotes a comment, that is:
+  a line beginning with a "#" is skipped
+  in all other lines, the "#" and all following characters are skipped.
+
+- the first non-comment line specifies the MIDI device (just in case, when
+  several MIDI controllers are connected to the computer). This line MUST
+  contain the string "DEVICE=", and everything following is treated as the
+  device name (without trailing blanks). Only MIDI devices are accepted whose
+  name starts with the given device name. for example, the line
+
+  DEVICE=CMD PL
+
+  will accept the "CMD PL-1" MIDI controller.
+
+- The following lines all must contain one of the strings
+  "KEY=", "CTRL=", or "PITCH=". The syntax is as follows:
+
+  KEY: buttons which generate Note-On/Note-Off MIDI events
+  ========================================================
+
+  The syntay is 
+
+  KEY=<nr> CHAN=<chan> ACTION=<action> <modifier>
+
+  where <nr> is the Number of the Midi Note, <chan> is the MIDI
+  channel where the event is expected.
+
+  The key words with the line can be given in any order. If
+  CHAN=  is omitted, MIDI events from any channel are accepted.
+
+   <action> is the key-word for a SDR "action" (see below)
+  and <modifier> can be omitted, or can be the string "ONOFF".
+  If the "ONOFF" modifier is there, an action is taken both upon
+  Note-On and Note-Off events (usually: when pressing and releasing
+  the button), while otherwise actions are only take upon "Note-on"
+  events.
+  Example without "ONOFF":
+  When using a button for the "TUNE" function, the
+  radio will go "tune" state when hitting the button, and return
+  to normal operation when hitting the button a second time.
+  Example with "ONOFF":
+  When using the same button for the "TUNE" function with the "ONOFF"
+  modifier, the radion will go to "tune" state when pressing the
+  button and return to normal operation when releasing it.
+
+  For example, in the sample file midi.inp you find the line
+
+  KEY=34 ACTION=MOX
+
+  and this means that the "Cue" button of the Behringer controller,
+  whiche generates Note on/off message for Note 34, is used to
+  switch MOX.
+
+  CTRL: MIDI controllers
+  ======================
+
+  Here we must distinguish between controllers that give a value in a 
+  fixed range (0-127), and controller that only encode the direction and
+  speed of turning a knob. We will name the first kind of controllers
+  (usually expression pedals, etc.) "knobs" and the second kind "wheels".
+
+  For example, the line
+
+  CTRL=20 ACTION=RFPOWER
+
+  will set the TX drive power, with value 0 for the minimum controller
+  position and the maximum value (100) for the maximum controller
+  position. Note that the Behringer controller has no "knobs", only
+  "wheels".
+
+  Wheels generate values which indicate the direction (left/right) and
+  speed of the rotation. A typical use would be to control the VFO
+  frequency. The description of wheel must contain the key-word "WHEEL"
+  and the critical values for normal/fast/very-fast left/right turns.
+  For example, the line
+
+  CTRL=31 WHEEL THR=59 61 63 65 67 69 ACTION=VFO
+
+  in the sample midi.inp file indicates that the VFO is controlled
+  by a MIDI controller with "note" 31 (this is the big knob for the
+  Behringer controller). The controller values sent by the MIDI
+  hardware are <64 for left turns and >64 for right turns, and the
+  larger the speed of rotation the larger the deviation from 64.
+  The sample line means that the frequency is reduced by 100 VFO-steps
+  if the controller value sent is <= 59, the frequency is reduced by
+  10 VFO-steps for controller values 59 and 60, and the VFO frequency
+  is reduced by one VFO-step is the controller sends the values 62
+  and 63. Likewise, the thresholds for an increase of the VFO frequency
+  by 1/10/100 VFO-steps are 65, 67, 69.
+  This allows to move from one band edge to the other easily.
+
+  If fast or very-fast motions are not wanted, set the threshold
+  accordingly. For example,
+
+  CTRL=4 WHEEL THR=-1 -1 63 65 128 128 ACTION=AGC
+
+  changes the AGC value by a constant amount for each MIDI message
+  generated, since the controller values are always in the range
+  0-127 and the threshold for fast and very-fast are never reached.
+
+  For wheels, there can be an additional directive DELAY=<delay>,
+  if this is given, it specifies a delay time (in msec) in which no
+  further WHEEL event is processed. If a wheel is used, for example,
+  to cycle through the filter settings, a delay takes care that this
+  does not go too fast.
+
+  PITCH: MIDI PITCH sliders
+  =========================
+
+  Sometimes a MIDI controller features a "pitch" controller. This
+  controller sends values between 0 and 16385. It can be used to
+  control all sorts of "sliders", e.g. TX drive level, AF level,
+  etc. Since there can only be a single pitch controller, the
+  line in file midi.inp is simply
+
+  PITCH ACTION=AFGAIN
+
+  and this means that with the pitch controller, the AF volume
+  is controlled. MIDI pitch controllers are treated as "KNOBS",
+  that is, the same way as MIDI controllers that generate values
+  in a fixed range.
+
+
+LIST OF ACTIONS
+===============
+
+Here is a list of actions implemented. Note that not all actions
+can be used with all sorts of MIDI events. For example, activating
+MOX makes only sense with a button (KEY), while setting the TX
+drive could be used with a knob (CTRL but no WHEEL), with a wheel
+(CTRL with WHEEL), or even with a pitch controller.
+
+Here is a list of actions currently implemented, in alphabetical
+order. We also give for which types of MIDI events (KEY, KNOB,
+WHEEL) this action is defined. We further have a "dummy" action
+NONE which means that there is nothing to do.
+
+
+Action         Event                Explanation
+----------------------------------------------------------------------------------------------
+AFGAIN         KNOB,WHEEL           AF audio volume
+AGC            KNOB,WHEEL           AGC level
+AGCATTACK      KEY                  cycle through AGC settings (fast/slow, etc.)
+ATT            KEY                  cycle  through "ALEX attenuator" settings
+ATT            KNOB,WHEEL           set RX attenuation (0-31dB)
+BANDUP         KEY,WHEEL            cycle through the bands (upwards)
+BANDDOWN       KEY,WHEEL            cycle through the bands (downwards)
+COMPRESS       KNOB,WHEEL           set TX compression level
+CTUN           KEY                  toggle CTUN mode
+FILTERUP       KEY,WHEEL            cycle through the filters (upwards)
+FILTERDOWN     KEY,WHEEL            cycle through the filster (downwards)
+LOCK           KEY                  lock VFO(s)
+MICGAIN        KNOB,WHEEL           MIC gain
+MODEUP         KEY,WHEEL            cycle through the modes (upwards)
+MODEDOWN       KEY,WHEEL            cycle through the modes (downwards)
+MOX            KEY                  MOX on/off
+NB             KEY                  cycle through NoiseBlanker settings
+NR             KEY                  cycle through NoiseReduction settings
+PANHIGH        WHEEL                change "high" level of current pan-adapter
+PANLOW         WHEEL                change "bottom" level of current pan-adapter
+PREAMP         KEY                  cycle through preamp settings (only available for CHARLY25 filter boards)
+PURESIGNAL     KEY                  toggle PURESIGNAL (on/off)
+RITCLEAR       KEY                  clear RIT frequency
+RITVAL         WHEEL                change RIT frequency offset
+RFPOWER        KNOB,WHEEL           TX power
+SPLIT          KEY                  toggle Split mode
+SWAPVFO        KEY                  Swap VFO-A/VFO-B
+TUNE           KEY                  Tune on/off
+VFO            WHEEL                change VFO frequency
+VFOA2B         KEY                  frequency VFO A -> VFO B
+VFOB2A         KEY                  frequency VFO B -> VFO A
+VOX            KEY                  toggle VOX (on/off)
+
+If you need more or different type of actions, the implementation should be straightforward.
index 757fd4ba661a23032054a670e544075742620e1a..77cb1e1c019482fe3e9d3a9420994f8a2bd1fc3d 100755 (executable)
@@ -1,11 +1,13 @@
 echo "installing fftw"
 sudo apt-get -y install libfftw3-3
+echo "installing librtlsdr0"
+sudo apt-get -y install librtlsdr0
 echo "removing old versions of pihpsdr"
 sudo rm -rf /usr/local/bin/pihpsdr
 echo "creating start script"
 cat <<EOT > start_pihpsdr.sh
 cd `pwd`
-sudo /usr/local/bin/pihpsdr
+/usr/local/bin/pihpsdr >log 2>&1
 EOT
 chmod +x start_pihpsdr.sh
 echo "creating desktop shortcut"
@@ -33,6 +35,14 @@ fi
 cp pihpsdr.desktop ~/.local/share/applications
 echo "removing old versions of shared libraries"
 sudo rm -rf /usr/local/lib/libwdsp.so
+sudo rm -rf /usr/local/lib/libLimeSuite*
+sudo rm -rf /usr/local/lib/libSoapySDR*
+sudo rm -rf /usr/local/lib/SoapySDR
+echo "copying udev rules"
+sudo cp 64-limesuite.rules /etc/udev/rules.d/
+sudo cp 90-ozy.rules /etc/udev/rules.d/
+sudo udevadm control --reload-rules
+sudo udevadm trigger
 echo "installing pihpsdr"
 sudo cp pihpsdr /usr/local/bin
 echo "installing shared libraries"
@@ -44,6 +54,6 @@ cd /usr/local/lib
 sudo ln -s libLimeSuite.so.19.04.1 libLimeSuite.so.19.04-1
 sudo ln -s libLimeSuite.so.19.04-1 libLimeSuite.so
 sudo ln -s libSoapySDR.so.0.8.0 libSoapySDR.so.0.8
-sudo ln -s libSoapySDR.so.0.8 libLimeSuite.so
-sudo apt-get install librtlsdr-dev
+sudo ln -s libSoapySDR.so.0.8 libSoapySDR.so
 sudo ldconfig
+
diff --git a/release/pihpsdr/midi.inp b/release/pihpsdr/midi.inp
new file mode 100644 (file)
index 0000000..cb0ddce
--- /dev/null
@@ -0,0 +1,74 @@
+#
+# Sample midi.inp file, suitable for a Behringer CMD PL-1 MIDI controller
+#
+# Note that the Attenuator is implemented twice, as a key and as a wheel
+# The key is suitable for radios with a step (ALEX) attenuator, the wheel
+# fits best for radios with a programmable attenuator (0-31 dB).
+# The button (Key 2) also works for STEMlab and CHARLY25
+#
+# The preamp button (Key 1) only has function with STEMlab and CHARLY25
+#
+# Do not assign the "Key" with number 31. You will unintentionally
+# "push" it most of the times you change the VFO frequency.
+#
+# NOTE: we could just leave out all lines with ACTION=NONE. In this case
+#       a diagnostic message ("unknown MIDI event") is printed to stderr.
+#
+DEVICE=CMD PL-1
+#
+# Big Wheel and Big Slider
+#
+CTRL=31 WHEEL THR=59 61 63 65 67 69 ACTION=VFO           # Big wheel:    : main VFO knob
+KEY=31 ACTION=NONE                                       # Button integrated in the big wheel (do not assign)
+PITCH ACTION=AFGAIN                                      # Big slider    : AF gain
+#
+# 8 Knobs (top left).
+# Note that you can push each knob and this generates
+# Note On/Off messages for KEY=0...8 which we do not
+# assign: we want to glue labels on the Controller and therefore
+# we do not have two labels per knob.
+#
+CTRL=0 WHEEL THR=-1 -1 63 65 128 128 ACTION=ATT          # Knob 1        : RX att
+KEY=0                                ACTION=NONE         # Push Knob 1   : (unassigned)
+CTRL=1 WHEEL THR=-1 -1 63 65 128 128 ACTION=COMPRESS     # Knob 2        : TX compression
+KEY=1                                ACTION=NONE         # Push Knob 1   : (unassigned)
+CTRL=2 WHEEL THR=-1 -1 63 65 128 128 ACTION=RITVAL       # Knob 3        : RIT value
+KEY=2                                ACTION=NONE         # Push Knob 1   : (unassigned)
+CTRL=3 WHEEL THR=-1 -1 63 65 128 128 ACTION=PANLOW       # Knob 4        : Panadapter low
+KEY=4                                ACTION=NONE         # Push Knob 1   : (unassigned)
+CTRL=4 WHEEL THR=-1 -1 63 65 128 128 ACTION=AGC          # Knob 5        : AGC
+KEY=4                                ACTION=NONE         # Push Knob 1   : (unassigned)
+CTRL=5 WHEEL THR=-1 -1 63 65 128 128 ACTION=MICGAIN      # Knob 6        : MIC gain
+KEY=5                                ACTION=NONE         # Push Knob 1   : (unassigned)
+CTRL=6 WHEEL THR=-1 -1 63 65 128 128 ACTION=RFPOWER      # Knob 7        : TX drive
+KEY=6                                ACTION=NONE         # Push Knob 1   : (unassigned)
+CTRL=7 WHEEL THR=-1 -1 63 65 128 128 ACTION=FILTERUP     # Knob 8        : cycle through the filters
+KEY=7                                ACTION=NONE         # Push Knob 1   : (unassigned)
+#
+# 8 Keys (below the 8 Knobs)
+#
+KEY=16 ACTION=PREAMP                                    # Key 1         : Cycle through Preamp settings
+KEY=17 ACTION=ATT                                       # Key 2         : Cycle through ATT (Alex ATT) settings
+KEY=18 ACTION=RITCLEAR                                          # Key 3         : Clear RIT value and disable RIT
+KEY=19 ACTION=CTUN                                      # Key 4         : toggle CTUN
+KEY=20 ACTION=NOISEBLANKER                              # Key 5         : cycle through NB settings
+KEY=21 ACTION=NOISEREDUCTION                            # Key 6         : cycle through NR settings
+KEY=22 ACTION=VOX                                       # Key 7         : toggle VOX
+KEY=23 ACTION=AGCATTACK                                         # Key 8         : cycle AGC fast/medium/slow
+#
+# "other" keys
+# Note that the "DECK" key switches the MIDI channel of the device.
+#
+KEY=24 ACTION=TUNE                                       # LOAD    button: TUNE on/off
+KEY=25 ACTION=LOCK                                       # LOCK    button: Lock VFO(s)
+KEY=26 ACTION=PURESIGNAL                                 # DECK    button: toggle PURESIGNAL
+KEY=27 ACTION=SWAPVFO                                   # SCRATCH button: Swap VFOs A and B
+KEY=31 ACTION=NONE                                       # Button integrated in the big wheel (do not assign)
+KEY=32 ACTION=VFOA2B                                     # SYNC    button: Frequency VFO A -> VFO B
+KEY=33 ACTION=VFOB2A                                     # TAP     button: Frequency VFO B -> VFO A
+KEY=34 ACTION=MOX                                        # CUE     button: MOX on/off
+KEY=35 ACTION=SPLIT                                      # >||     button: toggle Split
+KEY=36 ACTION=MODEDOWN                                  # <<      button: Mode down
+KEY=37 ACTION=MODEUP                                    # >>      button: Mode up
+KEY=38 ACTION=BANDDOWN                                  # -       button: Band down
+KEY=39 ACTION=BANDUP                                    # +       button: Band up
index d9877df63ba968af869ae333923022277aef7803..7cfe052b175e4f655f41294854bdf97ee55446d9 100755 (executable)
Binary files a/release/pihpsdr/pihpsdr and b/release/pihpsdr/pihpsdr differ
index 076024d3819372f73aac1c491cab5b6eb4207692..7ba22ac71a50eb425dc6fc1d88c2f98cdb091b53 100644 (file)
@@ -431,8 +431,7 @@ void rx_panadapter_update(RECEIVER *rx) {
   }
 #endif
 
-#ifdef GPIO 
-#ifndef CONTROLLER2 
+#if !defined (CONTROLLER2_V2) && !defined (CONTROLLER2_V1) && defined (GPIO)
   if(active) {
     cairo_set_source_rgb(cr,1.0,1.0,0.0);
     cairo_set_font_size(cr,16);
@@ -452,7 +451,6 @@ void rx_panadapter_update(RECEIVER *rx) {
     }
   }
 #endif
-#endif
 
 
   cairo_destroy (cr);
index fd5a40c20bd9c3cdc989ca344d54260448a875c5..f15cd72ac0ce191f8d77d0e32a30ffb1469cfcca 100644 (file)
@@ -17,7 +17,7 @@
 *
 */
 
-#ifdef CONTROLLER2
+#if defined (CONTROLLER2_V2) || defined (CONTROLLER2_V1)
 #include <gtk/gtk.h>
 #include <stdio.h>
 #include <string.h>
@@ -33,9 +33,7 @@
 #include "vfo.h"
 #include "button_text.h"
 #include "gpio.h"
-#ifdef CONTROLLER2
 #include "i2c.h"
-#endif
 
 typedef struct _choice {
   int sw;
@@ -136,7 +134,7 @@ void switch_menu(GtkWidget *parent) {
   row++;
   col=0;
 
-#ifndef CONTROLLER2
+#if !defined (CONTROLLER2_V2) && !defined (CONTROLLER2_V1)
 
   GtkWidget *sw7_title=gtk_label_new("SW7: ");
   gtk_grid_attach(GTK_GRID(grid),sw7_title,col,row,1,1);
index 1bc63b9da289ac58b11ec62f23caafff7d445b9f..efa8a84e6c0655b6263553fafa8a10d7300d323d 100644 (file)
@@ -38,7 +38,9 @@
 #ifdef FREEDV
 #include "freedv.h"
 #endif
+#ifdef GPIO
 #include "gpio.h"
+#endif
 
 
 static gint last_x;
@@ -367,8 +369,7 @@ void tx_panadapter_update(TRANSMITTER *tx) {
   }
 #endif
 
-#ifdef GPIO
-#ifndef CONTROLLER2
+#if !defined (CONTROLLER2_V2) && !defined (CONTROLLER2_V1) && defined (GPIO)
   cairo_set_source_rgb(cr,1.0,1.0,0.0);
   cairo_set_font_size(cr,16);
   if(ENABLE_E2_ENCODER) {
@@ -386,7 +387,6 @@ void tx_panadapter_update(TRANSMITTER *tx) {
     cairo_show_text(cr, encoder_string[e4_encoder_action]);
   }
 #endif
-#endif
 
 #ifdef PURESIGNAL
   if(tx->puresignal) {
index 2b9e70646c3bfa6484c123ea26dfb0dd089109e7..06ccee09efd4349cd595a9920ea706b0474f8ec6 100644 (file)
--- a/version.c
+++ b/version.c
 char build_date[]=GIT_DATE;
 char build_version[]=GIT_VERSION;
 
-#ifdef CONTROLLER2
-char version[]="2.0.0 (Controller2)";
+#if defined (CONTROLLER2_V1)
+char version[]="2.0.0 (Controller2 V1)";
+#elif defined (CONTROLLER2_V2)
+char version[]="2.0.0 (Controller2 V2)";
+#elif defined (GPIO)
+char version[]="2.0.0 (Controller1)";
 #else
 char version[]="2.0.0";
 #endif