From 038d98f426d68efbab9c6bfa0ad2920539d66293 Mon Sep 17 00:00:00 2001
From: c vw <dl1ycf@darc.de>
Date: Fri, 26 Jul 2019 18:05:53 +0200
Subject: [PATCH] Finalized things.

---
 Makefile        |   5 +-
 Makefile.mac    |   5 +-
 README.MacOS    |   1 -
 alex.h          |  18 +-
 new_protocol.c  |  78 +++++++--
 old_discovery.c |   4 +-
 old_protocol.c  | 429 ++++++++++++++++++++++++++----------------------
 ps_menu.c       |  38 +++--
 radio.c         |   4 +-
 rx_menu.c       |  13 +-
 transmitter.c   |   1 +
 11 files changed, 351 insertions(+), 245 deletions(-)

diff --git a/Makefile b/Makefile
index f3a8cf4..8bf0d14 100644
--- a/Makefile
+++ b/Makefile
@@ -33,9 +33,6 @@ GIT_VERSION := $(shell git describe --abbrev=0 --tags)
 # uncomment the line below to include support for STEMlab discovery (WITHOUT AVAHI)
 #STEMLAB_DISCOVERY=STEMLAB_DISCOVERY_NOAVAHI
 
-# uncommment this line for circumventing problems with RedPitya HPSDR apps.
-#STEMLAB_FIX_OPTION=-DSTEMLAB_FIX
-
 # uncomment the line below to include support for Pi SDR
 #PI_SDR_INCLUDE=PI_SDR
 
@@ -214,7 +211,7 @@ AUDIO_LIBS=-lasound
 
 OPTIONS=-g -Wno-deprecated-declarations $(MIDI_OPTIONS) $(PURESIGNAL_OPTIONS) $(REMOTE_OPTIONS) $(USBOZY_OPTIONS) \
 	$(I2C_OPTIONS) $(GPIO_OPTIONS) $(LIMESDR_OPTIONS) $(FREEDV_OPTIONS) $(LOCALCW_OPTIONS) $(RADIOBERRY_OPTIONS) \
-	$(PI_SDR_OPTIONS) $(PSK_OPTIONS) $(STEMLAB_OPTIONS) $(STEMLAB_FIX_OPTION) \
+	$(PI_SDR_OPTIONS) $(PSK_OPTIONS) $(STEMLAB_OPTIONS) \
 	-D GIT_DATE='"$(GIT_DATE)"' -D GIT_VERSION='"$(GIT_VERSION)"' $(DEBUG_OPTION) -O3
 
 LIBS=-lrt -lm -lwdsp -lpthread $(AUDIO_LIBS) $(USBOZY_LIBS) $(PSKLIBS) $(GTKLIBS) $(GPIO_LIBS) $(SOAPYSDRLIBS) $(FREEDVLIBS) $(STEMLAB_LIBS) $(MIDI_LIBS)
diff --git a/Makefile.mac b/Makefile.mac
index e3fc050..0095644 100644
--- a/Makefile.mac
+++ b/Makefile.mac
@@ -30,9 +30,6 @@ PURESIGNAL_INCLUDE=PURESIGNAL
 # uncomment the line below to include support for STEMlab discovery (WITHOUT AVAHI)
 STEMLAB_DISCOVERY=STEMLAB_DISCOVERY_NOAVAHI
 
-# uncommment this line for circumventing problems with RedPitya HPSDR apps.
-STEMLAB_FIX_OPTION=-DSTEMLAB_FIX
-
 # uncomment the line below to include support for Pi SDR
 #PI_SDR_INCLUDE=PI_SDR
 
@@ -199,7 +196,7 @@ PORTAUDIO_OPTIONS=-DPORTAUDIO
 AUDIO_LIBS=-lportaudio
 
 OPTIONS=-g -Wno-deprecated-declarations $(MIDI_OPTIONS) $(PURESIGNAL_OPTIONS) $(REMOTE_OPTIONS) $(USBOZY_OPTIONS) $(I2C_OPTIONS) $(GPIO_OPTIONS) $(LIMESDR_OPTIONS) \
-                $(FREEDV_OPTIONS) $(LOCALCW_OPTIONS) $(RADIOBERRY_OPTIONS) $(PI_SDR_OPTIONS) $(PSK_OPTIONS) $(STEMLAB_OPTIONS) $(STEMLAB_FIX_OPTION) \
+                $(FREEDV_OPTIONS) $(LOCALCW_OPTIONS) $(RADIOBERRY_OPTIONS) $(PI_SDR_OPTIONS) $(PSK_OPTIONS) $(STEMLAB_OPTIONS) \
                 -D GIT_DATE='"$(GIT_DATE)"' -D GIT_VERSION='"$(GIT_VERSION)"' $(PORTAUDIO_OPTIONS) $(DEBUG_OPTION) -O3
 
 LIBS=-lm -lwdsp -lpthread $(AUDIO_LIBS) $(USBOZY_LIBS) $(PSKLIBS) $(GTKLIBS) $(GPIO_LIBS) $(SOAPYSDRLIBS) $(FREEDVLIBS) $(STEMLAB_LIBS) $(MIDI_LIBS)
diff --git a/README.MacOS b/README.MacOS
index b2a88d2..02253d7 100644
--- a/README.MacOS
+++ b/README.MacOS
@@ -107,7 +107,6 @@ That's easy. Just adjust the Makefile according to the instructions found there
 and type "make". In my case (I have a HAMLAB RedPitaya-based SDR box), I need
 the following options in the Makefile (and have all others commented out):
 
-STEMLAB_FIX_OPTION=-DSTEMLAB_FIX
 STEMLAB_DISCOVERY=STEMLAB_DISCOVERY_MAC
 
 
diff --git a/alex.h b/alex.h
index ca9c38b..6341cac 100644
--- a/alex.h
+++ b/alex.h
@@ -28,11 +28,21 @@
 // For ANAN-7000/8000, there are furthermore ALEX1 bits for the filter
 // board of the second RX.
 //
+// One note about bit 11 (controlling relay K36)
+//
+// On older (Rev 15/16) filter boards, K36 switches an output (ByPass)
+// On newer (Rev 24)    filter boards, K36 switches an input  (ByPass)
+//
+// That is, we use bit 11 ONLY when "RX BYPASS" is selected as the *input*
+// for the PS feedback signal. If you select "RX BYPASS" for the old
+// ANAN-100 boards PS will not work, you have to use EXT1.
+//
+//
 #define ALEX_RX_ANTENNA_NONE   0x00000000		// route Ant1,2,2 to RX1
-#define ALEX_RX_ANTENNA_XVTR   0x00000900		// route XVTR-in  to RX1
-#define ALEX_RX_ANTENNA_EXT1   0x00000A00		// route EXT1     to RX1
-#define ALEX_RX_ANTENNA_EXT2   0x00000C00		// jOUTE EXT2     to RX1
-#define ALEX_RX_ANTENNA_BYPASS 0x00000800		// disconnect RX1 from Ant1,2,3
+#define ALEX_RX_ANTENNA_XVTR   0x00000100		// route XVTR-in  to RX1 (bit 8)
+#define ALEX_RX_ANTENNA_EXT1   0x00000200		// route EXT1     to RX1 (bit 9)
+#define ALEX_RX_ANTENNA_EXT2   0x00000400		// route EXT2     to RX1 (bit 10)
+#define ALEX_RX_ANTENNA_BYPASS 0x00000800		// connect BYPASS to RX1 (bit 11)
 
 #define ALEX_TX_ANTENNA_1      0x01000000		// route TX to ANT1
 #define ALEX_TX_ANTENNA_2      0x02000000		// route TX to ANT2
diff --git a/new_protocol.c b/new_protocol.c
index 5d83fa3..dc784c3 100644
--- a/new_protocol.c
+++ b/new_protocol.c
@@ -816,6 +816,31 @@ static void new_protocol_high_priority() {
     long alex0=0x00000000;
     long alex1=0x00000000;
 
+    if (device != NEW_DEVICE_ORION2) {
+      //
+      // ANAN7000 and 8000 do not have ALEX attenuators.
+      // Even worse, ALEX0(14) bit used to control these attenuators
+      // on ANAN-10/100/200 is now used differently.
+      //
+      // Note: ALEX attenuators are not much used anyway since we
+      //       have step attenuators on most boards.
+      //
+      switch (receiver[0]->alex_attenuation) {
+	case 0:
+	  alex0 |= ALEX_ATTENUATION_0dB;
+	  break;
+	case 1:
+	  alex0 |= ALEX_ATTENUATION_10dB;
+	  break;
+	case 2:
+	  alex0 |= ALEX_ATTENUATION_20dB;
+	  break;
+	case 3:
+	  alex0 |= ALEX_ATTENUATION_30dB;
+	  break;
+      }
+    }
+
     if(isTransmitting()) {
       alex0 |= ALEX_TX_RELAY;
       if(transmitter->puresignal) {
@@ -856,8 +881,14 @@ static void new_protocol_high_priority() {
       default:
 //
 //	Old (ANAN-100/200) high-pass filters
+//      Bypass HPFs while using EXT1 for PURESIGNAL feedback!
 //
-        if(rxFrequency<1800000L) {
+	i=0;  // flag used here for "filter bypass"
+	if (rxFrequency<1800000L) i=1;
+#ifdef PURESIGNAL
+	if (isTransmitting() && transmitter->puresignal && receiver[PS_RX_FEEDBACK]->alex_antenna == 6) i=1;
+#endif
+        if (i) {
           alex0|=ALEX_BYPASS_HPF;
         } else if(rxFrequency<6500000L) {
           alex0|=ALEX_1_5MHZ_HPF;
@@ -929,12 +960,15 @@ static void new_protocol_high_priority() {
 //  ANAN-7000 routes signals differently (these bits have no function on ANAN-80000)
 //            and uses ALEX0(14) to connnect Ext/XvrtIn to the RX.
 //
-    i=receiver[0]->alex_antenna;
+    i=receiver[0]->alex_antenna;			// 0,1,2  or 3,4,5
+#ifdef PURESIGNAL
     if (isTransmitting() && transmitter->puresignal) {
-	i=receiver[PS_RX_FEEDBACK]->alex_antenna;   // 0, 3, or 4
+	i=receiver[PS_RX_FEEDBACK]->alex_antenna;   	// 0, 6, or 7
     }
+#endif
     if (device == NEW_DEVICE_ORION2) i +=100;
     switch(i) {
+	case 6:  // EXT 1 for PS feedback
         case 3:  // EXT 1
           alex0|=ALEX_RX_ANTENNA_EXT1;
           break;
@@ -944,32 +978,33 @@ static void new_protocol_high_priority() {
         case 5:  // XVTR
             alex0|=ALEX_RX_ANTENNA_XVTR;
           break;
+	case 7: // RX_Bypass_In for PS feedback
+          alex0|=ALEX_RX_ANTENNA_BYPASS;
+          break;
 	case 103:	// EXT1 on ANAN-7000
+	case 106:	// EXT1 on ANAN-7000 for PS feedback
 	  alex0|=ALEX_ANAN7000_RX_ANT_EXT1;
 	  break;
-	case 104:	// EXT2 means RxBypass on ANAN-7000
-	  alex0|=ALEX_ANAN7000_RX_ANT_BYPASS;
+	case 104:
+	  // no EXT2 jacket on ANAN7000!
 	  break;
 	case 105:
 	  alex0|=ALEX_ANAN7000_RX_ANT_XVTR;
 	  break;
+	case 107:	// RxBypassIn on ANAN-7000
+	  alex0|=ALEX_ANAN7000_RX_ANT_BYPASS;
+	  break;
     }
 
 //
 //  Now we set the bits for Ant1/2/3 (RX and TX may be different)
-//  If RX is from none of Ant1/2/3, do not switch (leave these relays
-//  in TX state)
 //
-    if(isTransmitting() || (receiver[0]->alex_antenna > 2)) {
+    if(isTransmitting()) {
       i=transmitter->alex_antenna;
     } else {
       i=receiver[0]->alex_antenna;
     }
-    // i has value 0, 1, or 2.
     switch(i) {
-      default:
-	// should not happen, ignore silently and connect to ANT1
-	/* FALLTHROUGH */
       case 0:  // ANT 1
         alex0|=ALEX_TX_ANTENNA_1;
         break;
@@ -979,6 +1014,15 @@ static void new_protocol_high_priority() {
       case 2:  // ANT 3
         alex0|=ALEX_TX_ANTENNA_3;
         break;
+      default:
+	// this should not happen in TX case. Out of paranoia,
+        // connect ANT1 in this case
+	if (isTransmitting()) {
+	  fprintf(stderr,"WARNING: illegal TX antenna chosen, using ANT1\n");
+	  transmitter->alex_antenna=0;
+          alex0|=ALEX_TX_ANTENNA_1;
+	}
+	break;
     }
 
     high_priority_buffer_to_radio[1432]=(alex0>>24)&0xFF;
@@ -992,7 +1036,15 @@ static void new_protocol_high_priority() {
 //  Orion2 boards: set RX2 filters according ro VFOB frequency
 //
     if (device == NEW_DEVICE_ORION2) {
-        rxFrequency=vfo[VFO_B].frequency-vfo[VFO_B].lo;
+	//
+	// Note that while using DIVERSITY, the second RX filter settings must match
+	// those of the first RX
+	//
+	if (diversity_enabled) {
+          rxFrequency=vfo[VFO_A].frequency-vfo[VFO_A].lo;
+	} else {
+          rxFrequency=vfo[VFO_B].frequency-vfo[VFO_B].lo;
+	}
 //
 //      new ANAN-7000/8000 band-pass RX filters
 //      This info comes from file bpf2_select.v in the
diff --git a/old_discovery.c b/old_discovery.c
index 086a3b9..48c48e5 100644
--- a/old_discovery.c
+++ b/old_discovery.c
@@ -428,8 +428,8 @@ fprintf(stderr,"discover_receive_thread\n");
                             strcpy(discovered[devices].name,"Orion2");
                             break;
 			case DEVICE_STEMLAB:
-			    // This is in principle the same as HERMES so pretend a HERMES
-			    discovered[devices].device = DEVICE_HERMES;
+			    // This is in principle the same as HERMES but has two ADCs
+			    // (and therefore, can do DIVERSITY).
                             strcpy(discovered[devices].name,"STEMlab");
                             break;
                         default:
diff --git a/old_protocol.c b/old_protocol.c
index 38b16c6..42f0b6b 100644
--- a/old_protocol.c
+++ b/old_protocol.c
@@ -535,29 +535,189 @@ static gpointer receive_thread(gpointer arg) {
   return NULL;
 }
 
+//
+// To avoid overloading code with handling all the different cases
+// at various places,
+// we define here the channel number of the receivers, as well as the
+// number of HPSDR receivers to use (up to 5)
+// These are FIXED numbers and depend on the device and whether the code
+// is compiled with or without PURESIGNAL
+// Furthermore, we provide a function that determines the frequency for
+// a given (HPSDR) receiver. This makes the code below much more transparent.
+//
+
+static int rx_feedback_receiver() {
+  //
+  // Depending on the device, return channel number of RX feedback receiver
+  //
+  int ret;
+  switch (device) {
+    case DEVICE_METIS:
+      ret=0;
+      break;
+    case DEVICE_HERMES:
+    case DEVICE_STEMLAB:
+      ret=2;
+      break;
+    case DEVICE_ANGELIA:
+    case DEVICE_ORION:
+    case DEVICE_ORION2:
+      ret=3;
+    default:
+      ret=0;
+      break;
+  }
+  return ret;
+}
+
+static int tx_feedback_receiver() {
+  //
+  // Depending on the device, return channel number of RX feedback receiver
+  //
+  int ret;
+  switch (device) {
+    case DEVICE_METIS:
+      ret=1;
+      break;
+    case DEVICE_HERMES:
+    case DEVICE_STEMLAB:
+      ret=3;
+      break;
+    case DEVICE_ANGELIA:
+    case DEVICE_ORION:
+    case DEVICE_ORION2:
+      ret=4;
+    default:
+      ret=1;
+      break;
+  }
+  return ret;
+}
+
+static int first_receiver() {
+  //
+  // Depending on the device and whether we compiled for PURESIGNAL,
+  // return the number of the first receiver
+  //
+  return 0;
+}
+
+static int second_receiver() {
+  //
+  // Depending on the device and whether we compiled for PURESIGNAL,
+  // return the number of the second receiver
+  //
+#ifdef PURESIGNAL
+  return 2;
+#else
+  return 1;
+#endif
+}
+
+static long long channel_freq(int chan) {
+  //
+  // Depending on PURESIGNAL and DIVERSITY, return
+  // the frequency associated with the current HPSDR
+  // RX channel (0 <= chan <= 4).
+  // Note that for the RX channels which the firmware
+  // associates with the TX DAC the frequency need not
+  // be set.
+  //
+  // This function returns the TX frequency if chan is
+  // outside the allowed range, and thus can be used
+  // to determine the TX frequency.
+  //
+  int v;
+  long long freq;
+
+  switch (chan) {
+#ifdef PURESIGNAL
+    case 0:
+    case 1:
+      v=receiver[0]->id;
+      break;
+    case 2:
+    case 3:
+      if (diversity_enabled) {
+	v=receiver[0]->id;
+      } else {
+	v=receiver[1]->id;
+      }
+      break;
+#else
+    case 0:
+      v=receiver[0]->id;
+      break;
+    case 1:
+      if (diversity_enabled) {
+	v=receiver[0]->id;
+      } else {
+	v=receiver[1]->id;
+      }
+      break;
+#endif
+  }
+  if (v < 0) {
+    //
+    // v=-1 indicates that there is no VFO associated,
+    // in this case we take the TX frequency. So we can use this
+    // function also to determine the TX frequency
+    //
+    if(active_receiver->id==VFO_A) {
+      if(split) {
+	freq=vfo[VFO_B].frequency-vfo[VFO_B].lo+vfo[VFO_B].offset;
+      } else {
+	freq=vfo[VFO_A].frequency-vfo[VFO_A].lo+vfo[VFO_A].offset;
+      }
+    } else {
+      if(split) {
+	freq=vfo[VFO_A].frequency-vfo[VFO_A].lo+vfo[VFO_A].offset;
+      } else {
+	freq=vfo[VFO_B].frequency-vfo[VFO_B].lo+vfo[VFO_B].offset;
+      }
+    }
+  } else {
+    //
+    // determine frequency associated with VFO v
+    //
+    freq=vfo[v].frequency-vfo[v].lo;
+    if(vfo[v].rit_enabled) {
+      freq+=vfo[v].rit;
+    }
+    if(vfo[v].mode==modeCWU) {
+      freq-=(long long)cw_keyer_sidetone_frequency;
+    } else if(vfo[v].mode==modeCWL) {
+      freq+=(long long)cw_keyer_sidetone_frequency;
+    }
+  }
+  return freq;
+}
+
 static int how_many_receivers() {
   //
   // Depending on how the program is compiled and which board we have,
   // we use a FIXED number of receivers except for RADIOBERRY and PI_SDR,
   // where the number may be dynamically changed
   //
-  int num;
+  int ret;
 #if defined(RADIOBERRY) || defined(PI_SDR)
-        num = receivers;   // 1 or 2
+        ret = receivers;     // 1 or 2
 #else
-        num = RECEIVERS;     // 2
+        ret = RECEIVERS;     // 2
 #endif
 
 #ifdef PURESIGNAL
     // for PureSignal, the number of receivers needed is hard-coded below.
-    // we need at least 3 (for RX), and up to 5 for Orion2 boards, since
-    // the TX DAC channel is hard-wired to RX5.
-    num = 3;
-    if (device == DEVICE_HERMES) num = 4;
-    if (device == DEVICE_ANGELIA || device == DEVICE_ORION || device == DEVICE_ORION2) num = 5;
+    // we need at least 2, and up to 5 for Orion2 boards. This is so because
+    // the TX DAC is hard-wired to RX4 for HERMES,STEMLAB and to RX5 for ANGELIA
+    // and beyond.
+    ret = 2;  // METIS?
+    if (device == DEVICE_HERMES  || device == DEVICE_STEMLAB) ret = 4;
+    if (device == DEVICE_ANGELIA || device == DEVICE_ORION || device == DEVICE_ORION2) ret = 5;
 #endif
-    return num;
+    return ret;
 }
+
 static void process_ozy_input_buffer(unsigned char  *buffer) {
   int i,j;
   int r;
@@ -586,6 +746,10 @@ static void process_ozy_input_buffer(unsigned char  *buffer) {
   int tx_vfo=split?VFO_B:VFO_A;
 
   int num_hpsdr_receivers=how_many_receivers();
+  int rxfdbk = rx_feedback_receiver();
+  int txfdbk = tx_feedback_receiver();
+  int rx1channel = first_receiver();
+  int rx2channel = second_receiver();
 
   if(buffer[b++]==SYNC && buffer[b++]==SYNC && buffer[b++]==SYNC) {
     // extract control bytes
@@ -661,114 +825,55 @@ static void process_ozy_input_buffer(unsigned char  *buffer) {
         left_sample_double=(double)left_sample/8388607.0; // 24 bit sample 2^23-1
         right_sample_double=(double)right_sample/8388607.0; // 24 bit sample 2^23-1
 
-#ifdef PURESIGNAL
 	if (isTransmitting() && transmitter->puresignal) {
 	  //
-	  // case: transmitting with PURESIGNAL. Get sample pairs and feed to pscc
+	  // transmitting with PURESIGNAL. Get sample pairs and feed to pscc
 	  //
-          switch(r) {
-            case 0:
-              if(device==DEVICE_METIS)  {
-                left_sample_double_rx=left_sample_double;
-                right_sample_double_rx=right_sample_double;
-              }
-              break;
-            case 1:
-              if(device==DEVICE_METIS)  {
-                left_sample_double_tx=left_sample_double;
-                right_sample_double_tx=right_sample_double;
-                add_ps_iq_samples(transmitter, left_sample_double_tx,right_sample_double_tx,left_sample_double_rx,right_sample_double_rx);
-              }
-              break;
-            case 2:
-              if(device==DEVICE_HERMES)  {
-                left_sample_double_rx=left_sample_double;
-                right_sample_double_rx=right_sample_double;
-              }
-              break;
-            case 3:
-              if(device==DEVICE_HERMES)  {
-                left_sample_double_tx=left_sample_double;
-                right_sample_double_tx=right_sample_double;
-                add_ps_iq_samples(transmitter, left_sample_double_tx,right_sample_double_tx,left_sample_double_rx,right_sample_double_rx);
-              } else if(device==DEVICE_ANGELIA || device==DEVICE_ORION || device==DEVICE_ORION2) {
-                left_sample_double_rx=left_sample_double;
-                right_sample_double_rx=right_sample_double;
-              }
-              break;
-            case 4:
-              if(device==DEVICE_ANGELIA || device==DEVICE_ORION || device==DEVICE_ORION2) {
-                left_sample_double_tx=left_sample_double;
-                right_sample_double_tx=right_sample_double;
-                add_ps_iq_samples(transmitter, left_sample_double_tx,right_sample_double_tx,left_sample_double_rx,right_sample_double_rx);
-              }
-              break;
+	  if (r == rxfdbk) {
+            left_sample_double_rx=left_sample_double;
+            right_sample_double_rx=right_sample_double;
+          } else if (r == txfdbk) {
+            left_sample_double_tx=left_sample_double;
+            right_sample_double_tx=right_sample_double;
           }
-        }
-        if (!isTransmitting() && diversity_enabled) {
-	  //
-	  // case: compiled for PURESIGNAL and RX with DIVERSITY. Feed sample pair to diversity mixer for RX1 and original RX2 sample to RX2
-	  //
-          switch(r) {
-            case 0:
-              left_sample_double_rx=left_sample_double;
-              right_sample_double_rx=right_sample_double;
-              break;
-            case 2:
-              left_sample_double_tx=left_sample_double;
-              right_sample_double_tx=right_sample_double;
-              add_div_iq_samples(receiver[0], left_sample_double_rx,right_sample_double_rx,left_sample_double_tx,right_sample_double_tx);
-              if (receivers >1) add_iq_samples(receiver[1], left_sample_double,right_sample_double);
-              break;
+	  // this is pure paranoia, it allows for txfdbk < rxfdbk
+          if (r+1 == num_hpsdr_receivers) {
+            add_ps_iq_samples(transmitter, left_sample_double_tx,right_sample_double_tx,left_sample_double_rx,right_sample_double_rx);
           }
         }
-        if (!isTransmitting() && !diversity_enabled) {
+
+	if (!isTransmitting() && diversity_enabled) {
 	  //
-	  // case: compiled for PURESIGNAL and RX without DIVERSITY. Feed samples to RX1 and RX2
+	  // receiving with DIVERSITY. Get sample pairs and feed to diversity mixer
 	  //
-          switch(r) {
-            case 0:
-              add_iq_samples(receiver[0], left_sample_double,right_sample_double);
-              break;
-            case 2:
-              if (receivers >1) add_iq_samples(receiver[1], left_sample_double,right_sample_double);
-              break;
+          if (r == rx1channel) {
+            left_sample_double_rx=left_sample_double;
+            right_sample_double_rx=right_sample_double;
+          } else if (r == rx2channel) {
+            left_sample_double_tx=left_sample_double;
+            right_sample_double_tx=right_sample_double;
           }
-        }
-#else
-        // no PURESIGNAL
-        if (diversity_enabled) {
-	  //
-	  // case: compiled without PURESIGNAL and using DIVERSITY: Feed sample pair to diversity mixer for RX1 and original RX2 sample to RX2
-	  //
-          switch(r) {
-            case 0:
-              left_sample_double_rx=left_sample_double;
-              right_sample_double_rx=right_sample_double;
-              break;
-            case 1:
-              left_sample_double_tx=left_sample_double;
-              right_sample_double_tx=right_sample_double;
-              add_div_iq_samples(receiver[0], left_sample_double_rx,right_sample_double_rx,left_sample_double_tx,right_sample_double_tx);
-              if (receivers >1) add_iq_samples(receiver[1], left_sample_double,right_sample_double);
-              break;
+	  // this is pure paranoia, it allows for div_main < div_aux
+          if (r+1 == num_hpsdr_receivers) {
+            add_div_iq_samples(receiver[0], left_sample_double_rx,right_sample_double_rx,left_sample_double_tx,right_sample_double_tx);
+	    // if we have a second receiver, display "auxiliary" receiver as well
+            if (receivers >1) add_iq_samples(receiver[1], left_sample_double_tx,right_sample_double_tx);
           }
-        }
-        if (!diversity_enabled) {
+	}
+
+        if (!isTransmitting() && !diversity_enabled) {
 	  //
-	  // case: compiled without PURESIGNAL and not using DIVERSITY: Feed samples to RX1 and RX2
+	  // RX without DIVERSITY. Feed samples to RX1 and RX2
 	  //
-          switch(r) {
-            case 0:
-              add_iq_samples(receiver[0], left_sample_double,right_sample_double);
-              break;
-            case 1:
-              if (receivers >1) add_iq_samples(receiver[1], left_sample_double,right_sample_double);
-              break;
+          if (r == rx1channel) {
+             add_iq_samples(receiver[0], left_sample_double,right_sample_double);
+          } else if (r == rx2channel ]] receivers > 1) {
+             add_iq_samples(receiver[1], left_sample_double,right_sample_double);
           }
-	}
-#endif
-      }
+        }
+      } // end of loop over the receiver channels
+
+      // TX without PURESIGNAL: receivers are shut down -- do nothing
 
       mic_sample  = (short)(buffer[b++]<<8);
       mic_sample |= (short)(buffer[b++]&0xFF);
@@ -1002,17 +1107,21 @@ void ozy_send_buffer() {
     //
     if (isTransmitting() && transmitter->puresignal) i=receiver[PS_RX_FEEDBACK]->alex_antenna;
     switch(i) {
-      case 3:  // Alex: RX2 IN, ANAN: EXT1, ANAN7000: still uses internal feedback 
-        output_buffer[C3]|=0x80;
+      case 6:  // EXT1 used for PS feedback
+      case 3:  // EXT1 (RX2_IN)
+        output_buffer[C3]|=0x40;
         break;
-      case 4:  // Alex: RX1 IN, ANAN: EXT2, ANAN7000: RX BYPASS
-        output_buffer[C3]|=0xA0;
+      case 4:  // EXT2 (RX1_IN)
+        output_buffer[C3]|=0x20;
         break;
       case 5:  // XVTR
-        output_buffer[C3]|=0xE0;
+        output_buffer[C3]|=0x60;
         break;
+      case 7:  // RX Bypass In
+        output_buffer[C3]|=0x80;
+	break;
       default:
-	// RX1_OUT and RX1_ANT bits remain zero
+	// RX1_ANT bits remain zero
         break;
     }
 
@@ -1072,20 +1181,7 @@ void ozy_send_buffer() {
     switch(command) {
       case 1: // tx frequency
         output_buffer[C0]=0x02;
-        long long txFrequency;
-        if(active_receiver->id==VFO_A) {
-          if(split) {
-            txFrequency=vfo[VFO_B].frequency-vfo[VFO_B].lo+vfo[VFO_B].offset;
-          } else {
-            txFrequency=vfo[VFO_A].frequency-vfo[VFO_A].lo+vfo[VFO_A].offset;
-          }
-        } else {
-          if(split) {
-            txFrequency=vfo[VFO_A].frequency-vfo[VFO_A].lo+vfo[VFO_A].offset;
-          } else {
-            txFrequency=vfo[VFO_B].frequency-vfo[VFO_B].lo+vfo[VFO_B].offset;
-          }
-        }
+        long long txFrequency=channel_freq(-1);
         output_buffer[C1]=txFrequency>>24;
         output_buffer[C2]=txFrequency>>16;
         output_buffer[C3]=txFrequency>>8;
@@ -1094,51 +1190,14 @@ void ozy_send_buffer() {
       case 2: // rx frequency
         if(current_rx<num_hpsdr_receivers) {
           output_buffer[C0]=0x04+(current_rx*2);
-#ifdef PURESIGNAL
-          int v=receiver[current_rx/2]->id;
-	  // for the "last" receiver, v is out of range. In this case,
-	  // use TX frequency also while receiving
-          if((isTransmitting() && transmitter->puresignal) || (v >= MAX_VFOS)) {
-            long long txFrequency;
-            if(active_receiver->id==VFO_A) {
-              if(split) {
-                txFrequency=vfo[VFO_B].frequency-vfo[VFO_B].lo+vfo[VFO_B].offset;
-              } else {
-                txFrequency=vfo[VFO_A].frequency-vfo[VFO_A].lo+vfo[VFO_A].offset;
-              }
-            } else {
-              if(split) {
-                txFrequency=vfo[VFO_A].frequency-vfo[VFO_A].lo+vfo[VFO_A].offset;
-              } else {
-                txFrequency=vfo[VFO_B].frequency-vfo[VFO_B].lo+vfo[VFO_B].offset;
-              }
-            }
-            output_buffer[C1]=txFrequency>>24;
-            output_buffer[C2]=txFrequency>>16;
-            output_buffer[C3]=txFrequency>>8;
-            output_buffer[C4]=txFrequency;
-          } else {
-#else
-          int v=receiver[current_rx]->id;
-#endif
-            long long rxFrequency=vfo[v].frequency-vfo[v].lo;
-            if(vfo[v].rit_enabled) {
-              rxFrequency+=vfo[v].rit;
-            }
-            if(vfo[v].mode==modeCWU) {
-              rxFrequency-=(long long)cw_keyer_sidetone_frequency;
-            } else if(vfo[v].mode==modeCWL) {
-              rxFrequency+=(long long)cw_keyer_sidetone_frequency;
-            }
-            output_buffer[C1]=rxFrequency>>24;
-            output_buffer[C2]=rxFrequency>>16;
-            output_buffer[C3]=rxFrequency>>8;
-            output_buffer[C4]=rxFrequency;
-#ifdef PURESIGNAL
-          }
-#endif
+	  long long rxFrequency=channel_freq(current_rx);
+          output_buffer[C1]=rxFrequency>>24;
+          output_buffer[C2]=rxFrequency>>16;
+          output_buffer[C3]=rxFrequency>>8;
+          output_buffer[C4]=rxFrequency;
           current_rx++;
         }
+	// if we have reached the last RX channel, wrap around
         if(current_rx>=num_hpsdr_receivers) {
           current_rx=0;
         }
@@ -1147,7 +1206,6 @@ void ozy_send_buffer() {
         {
         BAND *band=band_get_current_band();
         int power=0;
-#ifdef STEMLAB_FIX
 	//
 	// Some HPSDR apps for the RedPitaya generate CW inside the FPGA, but while
 	// doing this, DriveLevel changes are processed by the server, but do not become effective.
@@ -1162,9 +1220,6 @@ void ozy_send_buffer() {
           mode=vfo[0].mode;
         }
         if(isTransmitting() || (mode == modeCWU) || (mode == modeCWL)) {
-#else
-        if(isTransmitting()) {
-#endif
           if(tune && !transmitter->tune_use_drive) {
             power=(int)((double)transmitter->drive_level/100.0*(double)transmitter->tune_percent);
           } else {
@@ -1220,7 +1275,8 @@ void ozy_send_buffer() {
         output_buffer[C3]=0x00;
         output_buffer[C4]=0x00;
   
-        if(radio->device==DEVICE_HERMES || radio->device==DEVICE_ANGELIA || radio->device==DEVICE_ORION || radio->device==DEVICE_ORION2) {
+        if(device==DEVICE_HERMES || device==DEVICE_ANGELIA || device==DEVICE_ORION
+                                 || device==DEVICE_ORION2  || device == DEVICE_STEMLAB) {
 	  // if attenuation is zero, then disable attenuator
 	  i = adc_attenuation[receiver[0]->adc] & 0x1F;
           if (i >0) output_buffer[C4]=0x20| i;
@@ -1235,7 +1291,8 @@ void ozy_send_buffer() {
         output_buffer[C0]=0x16;
         output_buffer[C1]=0x00;
         if(receivers==2) {
-          if(radio->device==DEVICE_HERMES || radio->device==DEVICE_ANGELIA || radio->device==DEVICE_ORION || radio->device==DEVICE_ORION2) {
+          if(device==DEVICE_HERMES || device==DEVICE_ANGELIA || device==DEVICE_ORION
+                                   || device==DEVICE_ORION2  || device==DEVICE_STEMLAB) {
 	    // if attenuation is zero, then disable attenuator
 	    i = adc_attenuation[receiver[1]->adc] & 0x1F;
             if (i > 0) output_buffer[C1]=0x20|i;
@@ -1449,6 +1506,7 @@ static int metis_write(unsigned char ep,unsigned char* buffer,int length) {
 }
 
 static void metis_restart() {
+  int i;
   //
   // In TCP-ONLY mode, we possibly need to re-connect
   // since if we come from a METIS-stop, the server
@@ -1463,34 +1521,17 @@ static void metis_restart() {
   // reset current rx
   current_rx=0;
 
-#ifdef STEMLAB_FIX
   // 
   // Some (older) HPSDR apps on the RedPitaya have very small
   // buffers that over-run if too much data is sent
   // to the RedPitaya *before* sending a METIS start packet.
-  // Therefore we send only four OZY buffers here.
+  // We fill the DUC FIFO here with about 500 samples before
+  // starting.
   //
-  command=1;   // ship out a "C0=0" and a "set tx" command
-  ozy_send_buffer();
-  ozy_send_buffer();
-  command=2;  // ship out a "C0=0" and a "set rx" command for RX1
-  ozy_send_buffer();
-  ozy_send_buffer();
-
-  current_rx=0;
-  command=1;
-#else
-  // DL1YCF: this is the original code, which does not do what it pretends ....
-  // send commands twice
   command=1;
-  do {
+  for (i=1; i<8; i++) {
     ozy_send_buffer();
-  } while (command!=1);
-
-  do {
-    ozy_send_buffer();
-  } while (command!=1);
-#endif
+  }
 
   sleep(1);
 
diff --git a/ps_menu.c b/ps_menu.c
index acadd84..fb80d26 100644
--- a/ps_menu.c
+++ b/ps_menu.c
@@ -261,15 +261,21 @@ static int info_thread(gpointer arg) {
 }
 
 //
-// Set "RX1 ANT", "RX1 OUT", and ADC settings for the PS feedback signal
+// select route for PS feedback signal.
+// note: we need new code numbers such that we can
+//       distinguish "normal RX" and "feedback" use
+//       of EXT1. In the latter case, any RX filters have
+//       to by bypassed, which is of particular importance
+//       on the 6m band.
+//       
 //
 static void ps_ant_cb(GtkWidget *widget, gpointer data) {
   int val = (int) (uintptr_t) data;
   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
     switch (val) {
-      case 0:	// AUTO (Internal), feedback goes to first ADC
-      case 3:	// EXT1,            feedback goes to first ADC
-      case 4:	// EXT2,            feedback goes to first ADC
+      case 0:	// Internal
+      case 6:	// EXT1; RX filters switched to "BYPASS"
+      case 7:	// Bypass
 	receiver[PS_RX_FEEDBACK]->alex_antenna = val;
 	if (protocol == NEW_PROTOCOL) {
 	  schedule_high_priority();
@@ -330,7 +336,6 @@ static void twotone_cb(GtkWidget *widget, gpointer data) {
 void ps_menu(GtkWidget *parent) {
   GtkWidget *b;
   int i;
-  const char *cp;
 
   parent_window=parent;
 
@@ -420,15 +425,17 @@ void ps_menu(GtkWidget *parent) {
   //
   // AUTO		Using internal feedback (to ADC0)
   // EXT1		Using EXT1 jacket (to ADC0), ANAN-7000: still uses AUTO
-  // EXT2		Using EXT2 jacket (to ADC0), ANAN-7000: "EXT2 is called RX Bypass"
-  // RX2		Using RX2  jacket (to ADC1)
+  // BYPASS		Using BYPASS. Not available with ANAN-100/200 up to Rev. 16 filter boards
+  //
+  // In fact, we provide the possibility of using EXT1 only to support these older
+  // (before February, 2015) ANAN-100/200 devices.
   //
   GtkWidget *ps_ant_label=gtk_label_new("PS FeedBk ANT:");
   gtk_widget_show(ps_ant_label);
   gtk_grid_attach(GTK_GRID(grid), ps_ant_label, col, row, 1, 1);
   col++;
 
-  GtkWidget *ps_ant_auto=gtk_radio_button_new_with_label(NULL,"AUTO");
+  GtkWidget *ps_ant_auto=gtk_radio_button_new_with_label(NULL,"Internal");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ps_ant_auto), 
     (receiver[PS_RX_FEEDBACK]->alex_antenna == 0) );
   gtk_widget_show(ps_ant_auto);
@@ -438,23 +445,18 @@ void ps_menu(GtkWidget *parent) {
 
   GtkWidget *ps_ant_ext1=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ps_ant_auto),"EXT1");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ps_ant_ext1),
-    (receiver[PS_RX_FEEDBACK]->alex_antenna==3) );
+    (receiver[PS_RX_FEEDBACK]->alex_antenna==6) );
   gtk_widget_show(ps_ant_ext1);
   gtk_grid_attach(GTK_GRID(grid), ps_ant_ext1, col, row, 1, 1);
-  g_signal_connect(ps_ant_ext1,"toggled", G_CALLBACK(ps_ant_cb), (gpointer) (long) 3);
+  g_signal_connect(ps_ant_ext1,"toggled", G_CALLBACK(ps_ant_cb), (gpointer) (long) 6);
   col++;
 
-  cp="EXT2";
-  // On ANAN-7000 there is no EXT2 jacket. This function is now called "RX ByPass"
-  // On ANAN-8000 this must be done by physical re-wiring
-  if ((protocol == ORIGINAL_PROTOCOL && device == DEVICE_ORION2) || 
-      (protocol == NEW_PROTOCOL      && device == NEW_DEVICE_ORION2))  cp="RxByPass";
-  GtkWidget *ps_ant_ext2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ps_ant_auto),cp);
+  GtkWidget *ps_ant_ext2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ps_ant_auto),"ByPass IN");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ps_ant_ext2),
-    (receiver[PS_RX_FEEDBACK]->alex_antenna==4) );
+    (receiver[PS_RX_FEEDBACK]->alex_antenna==7) );
   gtk_widget_show(ps_ant_ext2);
   gtk_grid_attach(GTK_GRID(grid), ps_ant_ext2, col, row, 1, 1);
-  g_signal_connect(ps_ant_ext2,"toggled", G_CALLBACK(ps_ant_cb), (gpointer) (long) 4);
+  g_signal_connect(ps_ant_ext2,"toggled", G_CALLBACK(ps_ant_cb), (gpointer) (long) 7);
   col++;
 
   row++;
diff --git a/radio.c b/radio.c
index c719191..3abb01d 100644
--- a/radio.c
+++ b/radio.c
@@ -492,9 +492,7 @@ void start_radio() {
   switch(protocol) {
     case ORIGINAL_PROTOCOL:
       switch(device) {
-        case DEVICE_METIS:
-          n_adc=1;  // No support for multiple MERCURY cards on a single ATLAS bus.
-          break;
+        case DEVICE_METIS: // No support for multiple MERCURY cards on a single ATLAS bus.
         case DEVICE_HERMES:
         case DEVICE_HERMES_LITE:
           n_adc=1;
diff --git a/rx_menu.c b/rx_menu.c
index 4cff08f..6ac0d1f 100644
--- a/rx_menu.c
+++ b/rx_menu.c
@@ -32,6 +32,7 @@
 #include "radio.h"
 #include "receiver.h"
 #include "sliders.h"
+#include "new_protocol.h"
 
 static GtkWidget *parent_window=NULL;
 
@@ -59,14 +60,23 @@ static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_d
 
 static void dither_cb(GtkWidget *widget, gpointer data) {
   active_receiver->dither=active_receiver->dither==1?0:1;
+  if (protocol == NEW_PROTOCOL) {
+    schedule_high_priority();
+  }
 }
 
 static void random_cb(GtkWidget *widget, gpointer data) {
   active_receiver->random=active_receiver->random==1?0:1;
+  if (protocol == NEW_PROTOCOL) {
+    schedule_high_priority();
+  }
 }
 
 static void preamp_cb(GtkWidget *widget, gpointer data) {
   active_receiver->preamp=active_receiver->preamp==1?0:1;
+  if (protocol == NEW_PROTOCOL) {
+    schedule_high_priority();
+  }
 }
 
 static void alex_att_cb(GtkWidget *widget, gpointer data) {
@@ -243,8 +253,7 @@ void rx_menu(GtkWidget *parent) {
   // On SDRs other than CHARLY25, preamps or Alex attenuators may be present or not, and we
   // do not try to find out whether they are. This would overload the code, and we then
   // also must have a menu to check e.g. which ANAN model is actually present.
-  // Instead, we offer these checkboxes in either case and must rely on the user
-  // not playing around with features that are not there.
+  // Instead, we offer these checkboxes in either case.
   //
   // NOTE: Preamps are not present on most current HPSDR models, and ALEX attenuators
   //       are not present e.g. in ANAN-7000.
diff --git a/transmitter.c b/transmitter.c
index bc4cf61..68b7082 100644
--- a/transmitter.c
+++ b/transmitter.c
@@ -369,6 +369,7 @@ static gboolean update_display(gpointer data) {
           constant2=0.09;
           break;
         case DEVICE_HERMES:
+        case DEVICE_STEMLAB:
           constant1=3.3;
           constant2=0.095;
           break;
-- 
2.45.2