From 7f9830590e0c62d8fd852e85392ea9fcbb95e128 Mon Sep 17 00:00:00 2001
From: c vw <dl1ycf@darc.de>
Date: Fri, 6 Mar 2020 10:48:36 +0100
Subject: [PATCH] Merging and polishing John's "MUTE" changes, make PS
 switching "bullet-proof"

---
 iambic.c       |  1 -
 mac_midi.c     |  2 +-
 midi.h         |  2 +-
 midi2.c        |  2 +-
 midi3.c        |  8 ++++----
 new_menu.c     | 11 +++++-----
 new_protocol.c | 29 +++++++-------------------
 new_protocol.h |  1 -
 transmitter.c  | 56 ++++++++++++++++++++++++++++++++++++--------------
 9 files changed, 60 insertions(+), 52 deletions(-)

diff --git a/iambic.c b/iambic.c
index b8d3c2d..58a20cb 100644
--- a/iambic.c
+++ b/iambic.c
@@ -337,7 +337,6 @@ void set_keyer_out(int state) {
 }
 
 static void* keyer_thread(void *arg) {
-    int pos;
     struct timespec loop_delay;
     int interval = 1000000; // 1 ms
     int i;
diff --git a/mac_midi.c b/mac_midi.c
index 429a67d..d52603d 100644
--- a/mac_midi.c
+++ b/mac_midi.c
@@ -70,7 +70,7 @@ static enum {
 } command;
 
 static void ReadMIDIdevice(const MIDIPacketList *pktlist, void *refCon, void *connRefCon) {
-    int i,j,k,byte,chan,arg1,arg2;
+    int i,j,byte,chan,arg1,arg2;
     MIDIPacket *packet = (MIDIPacket *)pktlist->packet;
 	
 	
diff --git a/midi.h b/midi.h
index 278caa8..4c50766 100644
--- a/midi.h
+++ b/midi.h
@@ -77,6 +77,7 @@ enum MIDIaction {
   MODE_DOWN,		// MODEDOWN:		cycle through modes downwards
   MODE_UP,		// MODEUP:		cycle through modes upwards
   MIDI_MOX,		// MOX:			toggle "mox" state
+  MIDI_MUTE,		// MUTE:		toggle mute on/off
   MIDI_NB,		// NOISEBLANKER:	cycle through NoiseBlanker states (none, NB, NB2)
   MIDI_NR,		// NOISEREDUCTION:	cycle through NoiseReduction states (none, NR, NR2)
   PAN_HIGH,		// PANHIGH:		"high" value of current panadapter
@@ -102,7 +103,6 @@ enum MIDIaction {
   VOXLEVEL, 		// VOXLEVEL:		adjust VOX threshold
   MIDI_XIT_CLEAR,	// XITCLEAR:		clear XIT value
   XIT_VAL,		// XITVAL:		change XIT value
-  MIDI_MUTE,		// MUTE:		toggle mute on/off
 };
 
 //
diff --git a/midi2.c b/midi2.c
index 671a044..b152b3a 100644
--- a/midi2.c
+++ b/midi2.c
@@ -130,6 +130,7 @@ static struct {
 	{ MODE_DOWN,		"MODEDOWN"},
 	{ MODE_UP,		"MODEUP"},
         { MIDI_MOX,     	"MOX"},
+	{ MIDI_MUTE,		"MUTE"},
 	{ MIDI_NB,    		"NOISEBLANKER"},
 	{ MIDI_NR,    		"NOISEREDUCTION"},
         { PAN_HIGH,     	"PANHIGH"},
@@ -155,7 +156,6 @@ static struct {
 	{ VOXLEVEL,   		"VOXLEVEL"},
 	{ MIDI_XIT_CLEAR,  	"XITCLEAR"},
 	{ XIT_VAL,  		"XITVAL"},
-	{ MIDI_MUTE,		"MUTE"},
         { ACTION_NONE,  	"NONE"}
 };
 
diff --git a/midi3.c b/midi3.c
index 634c9d5..8d930bd 100644
--- a/midi3.c
+++ b/midi3.c
@@ -429,6 +429,10 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 		g_idle_add(ext_mox_update, GINT_TO_POINTER(new));
 	    }
 	    break;    
+        /////////////////////////////////////////////////////////// "MUTE"
+        case MIDI_MUTE:
+            g_idle_add(ext_mute_update,NULL);
+            break;
 	/////////////////////////////////////////////////////////// "NOISEBLANKER"
 	case MIDI_NB: // only key supported
 	    // cycle through NoiseBlanker settings: OFF, NB, NB2
@@ -800,10 +804,6 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
               g_idle_add(ext_vfo_update, NULL);
 	    }
             break;
-	/////////////////////////////////////////////////////////// "MUTE"
-        case MIDI_MUTE:
-            g_idle_add(ext_mute_update,NULL);
-            break;
 
 	case ACTION_NONE:
 	    // No error message, this is the "official" action for un-used controller buttons.
diff --git a/new_menu.c b/new_menu.c
index 90b92df..0e6fa58 100644
--- a/new_menu.c
+++ b/new_menu.c
@@ -58,10 +58,8 @@
 #include "fft_menu.h"
 #include "main.h"
 #include "gpio.h"
-#ifdef RESTART_BUTTON
 #include "old_protocol.h"
 #include "new_protocol.h"
-#endif
 
 
 static GtkWidget *menu_b=NULL;
@@ -104,8 +102,9 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat
 
 #ifdef RESTART_BUTTON
 //
-// To recover from certain error conditions, this function
-// restart the protocol.
+// The "Restart" button restarts the protocol
+// This may help to recover from certain error conditions
+// Hitting this button automatically closes the menu window via cleanup()
 //
 static gboolean restart_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
   cleanup();
@@ -496,8 +495,8 @@ void new_menu()
 
 #ifdef RESTART_BUTTON
     //
-    // The new "Restart" button activates a function that restarts
-    // the protocol and closes the menu window
+    // The "Restart" restarts the protocol
+    // This may help to recover from certain error conditions
     //
     GtkWidget *restart_b=gtk_button_new_with_label("Restart");
     g_signal_connect (restart_b, "button-press-event", G_CALLBACK(restart_cb), NULL);
diff --git a/new_protocol.c b/new_protocol.c
index a7ac56d..979ff06 100644
--- a/new_protocol.c
+++ b/new_protocol.c
@@ -1359,7 +1359,7 @@ void new_protocol_restart() {
   char *buffer;
   //
   // halt the protocol, wait 200 msec, and re-start it
-  // the data socket is kept open
+  // the data socket is drained but kept open 
   //
   running=0;
   // wait until the thread that receives from the radio has terminated
@@ -1370,9 +1370,8 @@ void new_protocol_restart() {
   // let the FPGA rest a while
   usleep(200000); // 200 ms
   //
-  // at this point, we should drain all UDP packets that are still
-  // there in the data_socket. So we use select() and read until
-  // nothing is left
+  // drain all data that might still wait in the data_socket.
+  // (use select() and read until nothing is left)
   //
   FD_ZERO(&fds);
   FD_SET(data_socket, &fds);
@@ -1383,7 +1382,9 @@ void new_protocol_restart() {
     recvfrom(data_socket,buffer,NET_BUFFER_SIZE,0,(struct sockaddr*)&addr,&length);
   }
   free(buffer);
-  // reset sequence numbers
+  //
+  // reset sequence numbers, action table, etc.
+  //
   high_priority_sequence=0;
   rx_specific_sequence=0;
   tx_specific_sequence=0;
@@ -1403,28 +1404,12 @@ void new_protocol_restart() {
   running=1;
   new_protocol_thread_id = g_thread_new( "new protocol", new_protocol_thread, NULL);
 
-  // send the general packet
+  // start the protocol
   new_protocol_general();
-
-  // set TX and RX specific, start timer thread
   new_protocol_start();
-
-  // send HP packet, this actually starts the radio in the FPGA
   new_protocol_high_priority();
 }
 
-void new_protocol_run() {
-    new_protocol_high_priority();
-}
-
-double calibrate(int v) {
-    // Angelia
-    double v1;
-    v1=(double)v/4095.0*3.3;
-
-    return (v1*v1)/0.095;
-}
-
 static gpointer new_protocol_thread(gpointer data) {
 
     int ddc;
diff --git a/new_protocol.h b/new_protocol.h
index bbde387..bdc6ba2 100644
--- a/new_protocol.h
+++ b/new_protocol.h
@@ -78,7 +78,6 @@ extern void schedule_transmit_specific();
 
 extern void new_protocol_init(int pixels);
 extern void new_protocol_stop();
-extern void new_protocol_run();
 
 extern void filter_board_changed();
 extern void pa_changed();
diff --git a/transmitter.c b/transmitter.c
index f092401..0c27b37 100644
--- a/transmitter.c
+++ b/transmitter.c
@@ -1320,26 +1320,52 @@ void tx_set_displaying(TRANSMITTER *tx,int state) {
 
 void tx_set_ps(TRANSMITTER *tx,int state) {
 #ifdef PURESIGNAL
-  if (protocol == ORIGINAL_PROTOCOL) {
-    old_protocol_stop();
-    usleep(100000);
-  }
-  if(state) {
-    tx->puresignal=1;
-    SetPSControl(tx->id, 0, 0, 1, 0);
-  } else {
+  //
+  // Switch PURESIGNAL on (state !=0) or off (state==0)
+  //
+  // The following rules must be obeyed:
+  //
+  // a.) do not call SetPSControl unless you know the feedback
+  //     data streams are flowing. Otherwise, these calls may
+  //     be have no effect (experimental observation)
+  //
+  // b.  in the old protocol, do not change the value of
+  //     tx->puresignal unless the protocol is stopped.
+  //     (to have a safe re-configuration of the number of
+  //     RX streams)
+  //
+  if (!state) {
+    // if switching off, stop PS engine first, keep feedback
+    // streams flowing for a while to be sure SetPSControl works.
     SetPSControl(tx->id, 1, 0, 0, 0);
-    // wait a moment for PS to shut down
     usleep(100000);
-    tx->puresignal=0;
   }
-  if (protocol == NEW_PROTOCOL) {
-    schedule_high_priority();
-    schedule_receive_specific();
+  switch (protocol) {
+    case ORIGINAL_PROTOCOL:
+      // stop protocol, change PS state, restart protocol
+      old_protocol_stop();
+      usleep(100000);
+      tx->puresignal = state ? 1 : 0;
+      old_protocol_run();
+      break;
+    case NEW_PROTOCOL:
+      // change PS state and tell radio about it
+      tx->puresignal = state ? 1 : 0;
+      schedule_high_priority();
+      schedule_receive_specific();
+#ifdef SOAPY_SDR
+    case SOAPY_PROTOCOL:
+      // are there feedback channels in SOAPY?
+      break;
+#endif
   }
-  if (protocol == ORIGINAL_PROTOCOL) {
-    old_protocol_run();
+  if(state) {
+    // if switching on: wait a while to get the feedback
+    // streams flowing, then start PS engine
+    usleep(100000);
+    SetPSControl(tx->id, 0, 0, 1, 0);
   }
+  // update screen
   g_idle_add(ext_vfo_update,NULL);
 #endif
 }
-- 
2.45.2