]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
Finalized the "silence residual TX signal after TX/RX" option.
authorc vw <dl1ycf@darc.de>
Wed, 5 Jan 2022 09:10:10 +0000 (10:10 +0100)
committerc vw <dl1ycf@darc.de>
Wed, 5 Jan 2022 09:10:10 +0000 (10:10 +0100)
radio.c
receiver.c
receiver.h

diff --git a/radio.c b/radio.c
index c2fab287d6346cda036819df7b1cf7004390a870..92c2430fb18465816430e2f226a4ab15dd3d2a0b 100644 (file)
--- a/radio.c
+++ b/radio.c
@@ -1542,14 +1542,50 @@ static void rxtx(int state) {
       gtk_container_remove(GTK_CONTAINER(fixed), transmitter->panel);
     }
     if(!duplex) {
+      //
+      // Set parameters for the "silence first RXIQ samples after TX/RX transition" feature
+      // the default is "no silence", that is, fastest turnaround
+      //
+      int do_silence=0;
+      if (protocol == ORIGINAL_PROTOCOL && (device == DEVICE_HERMES_LITE2 || device == DEVICE_STEMLAB)) {
+        //
+        // These systems get a significant "tail" of the RX feedback signal into the RX after TX/RX,
+        // leading to AGC pumping. The problem is most severe if there is a carrier until the end of
+        // the TX phase (TUNE, AM, FM), the problem is virtually non-existent for CW, and of medium
+        // importance in SSB. On the other hand, one want a very fast turnaround in CW.
+        // So there is no "muting" for CW, 31 msec off "muting" for TUNE/AM/FM, and 16 msec for other modes.
+        //
+        switch(get_tx_mode()) {
+          case modeCWU:
+         case modeCWL:
+           do_silence=0;  // no "silence"
+            break;
+          case modeAM:
+         case modeFMN:
+           do_silence=5;  // leads to 31 ms "silence"
+            break;
+          default:
+           do_silence=6;  // leads to 16 ms "silence"
+            break;
+        }
+        if (tune) do_silence=5; // 31 ms "silence" for TUNEing in any mode
+      }
+
       for(i=0;i<receivers;i++) {
         gtk_fixed_put(GTK_FIXED(fixed),receiver[i]->panel,receiver[i]->x,receiver[i]->y);
         SetChannelState(receiver[i]->id,1,0);
         set_displaying(receiver[i],1);
-        receiver[i]->rxcount=0;
-        receiver[i]->maxcount=-1;
-       // if not duplex, clear RX iq buffer
+        //
+        // There might be some left-over samples in the RX buffer that were filled in
+        // *before* going TX, delete them
+        //
         receiver[i]->samples=0;
+        if (do_silence) {
+          receiver[i]->txrxmax = receiver[i]->sample_rate >> do_silence;
+        } else {
+          receiver[i]->txrxmax = 0;
+        }
+        receiver[i]->txrxcount = 0;
       }
     }
   }
index 933cc5f20332447758a06111341181b18413c39a..f3a8e3814b57eeb00aac6ca68194dce2adbf3958 100644 (file)
@@ -1239,7 +1239,8 @@ g_print("%s: rx=%p id=%d local_audio=%d\n",__FUNCTION__,rx,rx->id,rx->local_audi
   // defer set_agc until here, otherwise the AGC threshold is not computed correctly
   set_agc(rx, rx->agc);
 
-  rx->rxcount=99999;
+  rx->txrxcount=0;
+  rx->txrxmax=0;
   return rx;
 }
 
@@ -1252,7 +1253,6 @@ void receiver_change_sample_rate(RECEIVER *rx,int sample_rate) {
   g_mutex_lock(&rx->mutex);
 
   rx->sample_rate=sample_rate;
-  rx->samples=0;  // clear RX iq buffer
   int scale=rx->sample_rate/48000;
   rx->output_samples=rx->buffer_size/scale;
   rx->hz_per_pixel=(double)rx->sample_rate/(double)rx->width;
@@ -1500,17 +1500,21 @@ static int tx_buffer_seen=0;
 
 void add_iq_samples(RECEIVER *rx, double i_sample,double q_sample) {
 
-  if (rx->rxcount <= 20000) {
-    if (i_sample*i_sample + q_sample*q_sample > 0.01) rx->maxcount=rx->rxcount;
-    if (rx->rxcount < (int)(rx->sample_rate >> 5)) {
-      i_sample=0.0;
-      q_sample=0.0;
-    }
-    if (rx->rxcount == 20000) {
-      fprintf(stderr,"ID=%d MAXCOUNT=%d\n", rx->id, rx->maxcount);
-      rx->rxcount = 99999;
-    }
-    rx->rxcount++;
+  //
+  // At the end of a TX/RX transition, txrxcount is set to zero,
+  // and txrxmax to some suitable value.
+  // Then, the first txrxmax RXIQ samples are "silenced"
+  // This is necessary on systems where RX feedback samples
+  // from cross-talk at the TRX relay arrive with some delay.
+  //
+  // If txrxmax is zero, no "silencing" takes place here,
+  // this is the case for radios not showing this problem,
+  // and generally if in CW mode or using duplex.
+  //
+  if (rx->txrxcount < rx->txrxmax) {
+    i_sample=0.0;
+    q_sample=0.0;
+    rx->txrxcount++;
   }
 
   rx->iq_input_buffer[rx->samples*2]=i_sample;
@@ -1526,8 +1530,19 @@ void add_iq_samples(RECEIVER *rx, double i_sample,double q_sample) {
 // Note that we sum the second channel onto the first one.
 //
 void add_div_iq_samples(RECEIVER *rx, double i0, double q0, double i1, double q1) {
-  rx->iq_input_buffer[rx->samples*2]    = i0 + (div_cos*i1 - div_sin*q1);
-  rx->iq_input_buffer[(rx->samples*2)+1]= q0 + (div_sin*i1 + div_cos*q1);
+  double i_sample=i0 + (div_cos*i1 - div_sin*q1);
+  double q_sample=q0 + (div_sin*i1 + div_cos*q1);
+  //
+  // The rest of the code is copied from add_iq_samples()
+  //
+  if (rx->txrxcount < rx->txrxmax) {
+    i_sample=0.0;
+    q_sample=0.0;
+    rx->txrxcount++;
+  }
+
+  rx->iq_input_buffer[rx->samples*2]=i_sample;
+  rx->iq_input_buffer[(rx->samples*2)+1]=q_sample;
   rx->samples=rx->samples+1;
   if(rx->samples>=rx->buffer_size) {
     full_rx_buffer(rx);
index d72b0c61110b32b937ddf321729c6a9b550f0a33..41d580cc9d66732719191af9b3d314368ee3572c 100644 (file)
@@ -167,7 +167,13 @@ typedef struct _receiver {
   gint x;
   gint y;
 
-  int rxcount; int maxcount;
+  // two variables that implement the new
+  // "mute first RX IQ samples after TX/RX transition"
+  // feature that is relevant for HermesLite-II and STEMlab
+  // (and possibly some other radios)
+  //
+  guint txrxcount;
+  guint txrxmax;
 } RECEIVER;
 
 extern RECEIVER *create_pure_signal_receiver(int id, int buffer_size,int sample_rate,int pixels);