From c784c7218fac031973377cd3391c0dacda3dff58 Mon Sep 17 00:00:00 2001
From: c vw <dl1ycf@darc.de>
Date: Thu, 18 Jul 2019 19:02:19 +0200
Subject: [PATCH] OldProtocol: making feedback spectrum high resolution for all
 sample rates

---
 hpsdrsim.c    | 76 ++++++++++++++++++++++++++++++---------------------
 radio.c       |  3 ++
 receiver.c    | 56 +++++++++++++++++++++++++++++--------
 transmitter.c | 62 +++++++++--------------------------------
 4 files changed, 106 insertions(+), 91 deletions(-)

diff --git a/hpsdrsim.c b/hpsdrsim.c
index 881ea13..59d5e6f 100644
--- a/hpsdrsim.c
+++ b/hpsdrsim.c
@@ -205,16 +205,30 @@ static double  last_q_sample=0.0;
 static int  txptr=0;
 static int  rxptr=0;
 
+//
+// Unfortunately, the code number of the gear
+// differes in old and new protocol
+//
 
-#define DEVICE_ATLAS      0
-#define DEVICE_HERMES     1
-#define DEVICE_HERMES2    2
-#define DEVICE_ANGELIA    3
-#define DEVICE_ORION      4
-#define DEVICE_ORION2     5
-#define DEVICE_HERMESLITE 6
-#define DEVICE_C25        100
-static int DEVICE=DEVICE_HERMES;
+#define DEVICE_ATLAS           0
+#define DEVICE_HERMES          1
+#define DEVICE_HERMES2         2
+#define DEVICE_ANGELIA         4
+#define DEVICE_ORION           5
+#define DEVICE_HERMES_LITE     6
+#define DEVICE_ORION2         10
+#define DEVICE_C25           100
+
+#define NEW_DEVICE_ATLAS       0
+#define NEW_DEVICE_HERMES      1
+#define NEW_DEVICE_HERMES2     2
+#define NEW_DEVICE_ANGELIA     3
+#define NEW_DEVICE_ORION       4
+#define NEW_DEVICE_ORION2      5
+#define NEW_DEVICE_HERMES_LITE 6
+
+static int OLDDEVICE=DEVICE_HERMES;
+static int NEWDEVICE=NEW_DEVICE_HERMES;
 
 int main(int argc, char *argv[])
 {
@@ -268,16 +282,16 @@ int main(int argc, char *argv[])
  */
 
         if (argc > 1) {
-	    if (!strncmp(argv[1],"-atlas"  ,      6))  DEVICE=DEVICE_ATLAS;
-	    if (!strncmp(argv[1],"-hermes" ,      7))  DEVICE=DEVICE_HERMES;
-	    if (!strncmp(argv[1],"-hermes2" ,     8))  DEVICE=DEVICE_HERMES2;
-	    if (!strncmp(argv[1],"-angelia" ,     8))  DEVICE=DEVICE_ANGELIA;
-	    if (!strncmp(argv[1],"-orion" ,       6))  DEVICE=DEVICE_ORION;
-	    if (!strncmp(argv[1],"-orion2" ,      7))  DEVICE=DEVICE_ORION2;
-	    if (!strncmp(argv[1],"-hermeslite" , 11))  DEVICE=DEVICE_ORION2;
-	    if (!strncmp(argv[1],"-c25"    ,      4))  DEVICE=DEVICE_C25;
+	    if (!strncmp(argv[1],"-atlas"  ,      6))  {OLDDEVICE=DEVICE_ATLAS;       NEWDEVICE=NEW_DEVICE_ATLAS;}
+	    if (!strncmp(argv[1],"-hermes" ,      7))  {OLDDEVICE=DEVICE_HERMES;      NEWDEVICE=NEW_DEVICE_HERMES;}
+	    if (!strncmp(argv[1],"-hermes2" ,     8))  {OLDDEVICE=DEVICE_HERMES2;     NEWDEVICE=NEW_DEVICE_HERMES2;}
+	    if (!strncmp(argv[1],"-angelia" ,     8))  {OLDDEVICE=DEVICE_ANGELIA;     NEWDEVICE=NEW_DEVICE_ANGELIA;}
+	    if (!strncmp(argv[1],"-orion" ,       6))  {OLDDEVICE=DEVICE_ORION;       NEWDEVICE=NEW_DEVICE_ORION;}
+	    if (!strncmp(argv[1],"-orion2" ,      7))  {OLDDEVICE=DEVICE_ORION2;      NEWDEVICE=NEW_DEVICE_ORION2;}
+	    if (!strncmp(argv[1],"-hermeslite" , 11))  {OLDDEVICE=DEVICE_HERMES_LITE; NEWDEVICE=NEW_DEVICE_HERMES_LITE;}
+	    if (!strncmp(argv[1],"-c25"    ,      4))  {OLDDEVICE=DEVICE_C25;         NEWDEVICE=NEW_DEVICE_HERMES;}
         }
-	switch (DEVICE) {
+	switch (OLDDEVICE) {
 	    case   DEVICE_ATLAS:   fprintf(stderr,"DEVICE is ATLASS\n");      break;
 	    case   DEVICE_HERMES:  fprintf(stderr,"DEVICE is HERMES\n");      break;
 	    case   DEVICE_HERMES2: fprintf(stderr,"DEVICE is HERMES (2)\n");  break;
@@ -286,7 +300,7 @@ int main(int argc, char *argv[])
 	    case   DEVICE_ORION2:  fprintf(stderr,"DEVICE is ORION-II\n");    break;
 	    case   DEVICE_C25:     fprintf(stderr,"DEVICE is STEMlab/C25\n"); break;
 	}
-	reply[10]=DEVICE;
+	reply[10]=OLDDEVICE;
 
 	if ((sock_udp = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
 	{
@@ -719,7 +733,7 @@ int main(int argc, char *argv[])
 				  buffer[ 8]=0xDD;
 				  buffer[ 9]=0xEE;
 				  buffer[10]=0xFF;
-				  buffer[11]=DEVICE;
+				  buffer[11]=NEWDEVICE;
 				  buffer[12]=38;
 				  buffer[13]=103;
 				  buffer[20]=2;
@@ -738,7 +752,7 @@ int main(int argc, char *argv[])
                                   buffer[ 8]=0xDD;
                                   buffer[ 9]=0xEE;
                                   buffer[10]=0xFF;
-                                  buffer[11]=DEVICE;
+                                  buffer[11]=NEWDEVICE;
                                   buffer[12]=38;
                                   buffer[13]=103;
                                   buffer[20]=2;
@@ -765,7 +779,7 @@ int main(int argc, char *argv[])
                                   buffer[ 9]=0xEE;
                                   buffer[10]=0xFF;
 				  buffer[11]=103;
-				  buffer[12]=DEVICE;
+				  buffer[12]=NEWDEVICE;
 				  buffer[13]=(checksum >> 8) & 0xFF;
 				  buffer[14]=(checksum     ) & 0xFF;
 				  sendto(sock_udp, buffer, 60, 0, (struct sockaddr *)&addr_from, sizeof(addr_from));
@@ -791,7 +805,7 @@ int main(int argc, char *argv[])
                                   buffer[ 8]=0xDD;
                                   buffer[ 9]=0xEE;
                                   buffer[10]=0xFF;
-                                  buffer[11]=DEVICE;
+                                  buffer[11]=NEWDEVICE;
                                   buffer[12]=38;
                                   buffer[13]=103;
                                   buffer[20]=2;
@@ -868,7 +882,7 @@ void process_ep2(uint8_t *frame)
           chk_data(((frame[4] >> 6) & 1), MicTS, "TimeStampMic");
           chk_data(((frame[4] >> 7) & 1), CommonMercuryFreq,"Common Mercury Freq");
 
-	  if (DEVICE == DEVICE_C25) {
+	  if (OLDDEVICE == DEVICE_C25) {
               // Charly25: has two 18-dB preamps that are switched with "preamp" and "dither"
               //           and two attenuators encoded in Alex-ATT
 	      //           Both only applies to RX1!
@@ -957,7 +971,7 @@ void process_ep2(uint8_t *frame)
    	   chk_data((frame[4] & 0x1F) >> 0, rx_att[0], "RX1 ATT");
    	   chk_data((frame[4] & 0x20) >> 5, rx1_attE, "RX1 ATT enable");
 
-	   if (DEVICE != DEVICE_C25) {
+	   if (OLDDEVICE != DEVICE_C25) {
 	     // Set RX amplification factors. No switchable preamps available normally.
              rxatt_dbl[0]=pow(10.0, -0.05*(10*AlexAtt+rx_att[0]));
              rxatt_dbl[1]=pow(10.0, -0.05*(rx_att[1]));
@@ -997,7 +1011,7 @@ void process_ep2(uint8_t *frame)
             chk_data((frame[2] & 0x30) >> 4, rx_adc[6], "RX7 ADC");
 	    chk_data((frame[3] & 0x1f), txatt, "TX ATT");
 	    txatt_dbl=pow(10.0, -0.05*(double) txatt);
-	    if (DEVICE == DEVICE_C25) {
+	    if (OLDDEVICE == DEVICE_C25) {
 		// RedPitaya: Hard-wired ADC settings.
 		rx_adc[0]=0;
 		rx_adc[1]=1;
@@ -1128,7 +1142,7 @@ void *handler_ep6(void *arg)
 		    memset(pointer, 0, 504);
 		    for (j=0; j<n; j++) {
 			// ADC1: noise + weak tone on RX, feedback sig. on TX (except STEMlab)
-		        if (ptt && (DEVICE != DEVICE_C25)) {
+		        if (ptt && (OLDDEVICE != DEVICE_C25)) {
 			  i1=isample[rxptr]*txdrv_dbl;
 			  q1=qsample[rxptr]*txdrv_dbl;
 			  fac=IM3a+IM3b*(i1*i1+q1*q1);
@@ -1141,7 +1155,7 @@ void *handler_ep6(void *arg)
 			  adc1qsample += T0800Qtab[pt0800] * 83.886070 *rxatt_dbl[0];
 			}
 			// ADC2: noise + stronger tone on RX, feedback sig. on TX (only STEMlab)
-			if (ptt && (DEVICE == DEVICE_C25)) {
+			if (ptt && (OLDDEVICE == DEVICE_C25)) {
 			  i1=isample[rxptr]*txdrv_dbl;
 			  q1=qsample[rxptr]*txdrv_dbl;
 			  fac=IM3a+IM3b*(i1*i1+q1*q1);
@@ -1176,17 +1190,17 @@ void *handler_ep6(void *arg)
 				myqsample=0;
 				break;
 			    }
-			    if (DEVICE == DEVICE_ATLAS && ptt && (k==1)) {
+			    if (OLDDEVICE == DEVICE_ATLAS && ptt && (k==1)) {
 				// METIS: TX DAC signal goes to RX2 when TXing
 				myisample=dacisample;
 				myqsample=dacqsample;
 			    }
-			    if ((DEVICE==DEVICE_HERMES || DEVICE==DEVICE_HERMES2 || DEVICE==DEVICE_C25) && ptt && (k==3)) {
+			    if ((OLDDEVICE==DEVICE_HERMES || OLDDEVICE==DEVICE_HERMES2 || OLDDEVICE==DEVICE_C25) && ptt && (k==3)) {
 				// HERMES: TX DAC signal goes to RX4 when TXing
 				myisample=dacisample;
 				myqsample=dacqsample;
 			    }
-			    if ((DEVICE==DEVICE_ANGELIA || DEVICE == DEVICE_ORION || DEVICE== DEVICE_ORION2) && ptt && (k==4)) {
+			    if ((OLDDEVICE==DEVICE_ANGELIA || OLDDEVICE == DEVICE_ORION || OLDDEVICE== DEVICE_ORION2) && ptt && (k==4)) {
 				// ANGELIA and beyond: TX DAC signal goes to RX5 when TXing
 				myisample=dacisample;
 				myqsample=dacqsample;
diff --git a/radio.c b/radio.c
index 9017f1e..ce5caad 100644
--- a/radio.c
+++ b/radio.c
@@ -748,6 +748,9 @@ void radio_change_sample_rate(int rate) {
         for(i=0;i<receivers;i++) {
           receiver_change_sample_rate(receiver[i],rate);
         }
+#ifdef PURESIGNAL
+        receiver_change_sample_rate(receiver[PS_RX_FEEDBACK],rate);
+#endif
         old_protocol_set_mic_sample_rate(rate);
         old_protocol_run();
 #ifdef PURESIGNAL
diff --git a/receiver.c b/receiver.c
index a888ba4..f96cbe3 100644
--- a/receiver.c
+++ b/receiver.c
@@ -751,7 +751,7 @@ fprintf(stderr,"receiver: waterfall_init: height=%d y=%d %p\n",height,y,rx->wate
 }
 
 #ifdef PURESIGNAL
-RECEIVER *create_pure_signal_receiver(int id, int buffer_size,int sample_rate,int pixels) {
+RECEIVER *create_pure_signal_receiver(int id, int buffer_size,int sample_rate,int width) {
 fprintf(stderr,"create_pure_signal_receiver: id=%d buffer_size=%d\n",id,buffer_size);
   RECEIVER *rx=malloc(sizeof(RECEIVER));
   rx->id=id;
@@ -766,7 +766,7 @@ fprintf(stderr,"create_pure_signal_receiver: id=%d buffer_size=%d\n",id,buffer_s
   rx->pixels=0;
   rx->fps=0;
 
-  rx->width=0;
+  rx->width=width;  // save for later use, e.g. when changing the sample rate
   rx->height=0;
   rx->display_panadapter=0;
   rx->display_waterfall=0;
@@ -779,7 +779,11 @@ fprintf(stderr,"create_pure_signal_receiver: id=%d buffer_size=%d\n",id,buffer_s
     // 192 kHz, we make a spectrum with four times the pixels and then
     // display only the central part.
     // 
-    rx->pixels = (protocol == ORIGINAL_PROTOCOL) ? pixels : 4*pixels;
+    if (protocol == ORIGINAL_PROTOCOL) {
+	rx->pixels=(sample_rate/48000) * width;
+    } else {
+      rx->pixels = 4*width;
+    }
   }
   // allocate buffers
   rx->iq_sequence=0;
@@ -1102,21 +1106,51 @@ void receiver_change_adc(RECEIVER *rx,int adc) {
 
 void receiver_change_sample_rate(RECEIVER *rx,int sample_rate) {
 
-  SetChannelState(rx->id,0,1);
+//
+// This must be done also for PS_RX_FEEDBACK to change
+// the number of pixels in the display (needed for
+// conversion from higher sample rates to 48K
+//
+// However, some of these operations must only be done
+// if this is a "normal" receiver
+//
+  int normal=(rx->id != PS_RX_FEEDBACK);
+  float *fp, *ofp;
 
   rx->sample_rate=sample_rate;
   int scale=rx->sample_rate/48000;
   rx->output_samples=rx->buffer_size/scale;
-  free(rx->audio_output_buffer);
-  rx->audio_output_buffer=malloc(sizeof(double)*2*rx->output_samples);
-  rx->audio_buffer=malloc(AUDIO_BUFFER_SIZE);
   rx->hz_per_pixel=(double)rx->sample_rate/(double)rx->width;
-  SetInputSamplerate(rx->id, sample_rate);
+
+  if (!normal) {
+    if (protocol == ORIGINAL_PROTOCOL) {
+      rx->pixels = scale * rx->width;
+    } else {
+      // We should never arrive here, since the sample rate of the
+      // PS feedback receiver is fixed.
+      rx->pixels = 4 * rx->width;
+    }
+    // make sure the pixel samples are always valid
+    // ... probably pure DL1YCF's paranoia
+    fp=malloc(sizeof(float)*rx->pixels);
+    ofp=rx->pixel_samples;
+    rx->pixel_samples=fp;
+    free(ofp);
+  }
   init_analyzer(rx);
-  SetEXTANBSamplerate (rx->id, sample_rate);
-  SetEXTNOBSamplerate (rx->id, sample_rate);
+
+  if (normal) {
+    SetChannelState(rx->id,0,1);
+    free(rx->audio_output_buffer);
+    rx->audio_output_buffer=malloc(sizeof(double)*2*rx->output_samples);
+    rx->audio_buffer=malloc(AUDIO_BUFFER_SIZE);
+    SetInputSamplerate(rx->id, sample_rate);
+    SetEXTANBSamplerate (rx->id, sample_rate);
+    SetEXTNOBSamplerate (rx->id, sample_rate);
+    SetChannelState(rx->id,1,0);
+  }
+
 fprintf(stderr,"receiver_change_sample_rate: id=%d rate=%d buffer_size=%d output_samples=%d\n",rx->id, rx->sample_rate, rx->buffer_size, rx->output_samples);
-  SetChannelState(rx->id,1,0);
 }
 
 void receiver_frequency_changed(RECEIVER *rx) {
diff --git a/transmitter.c b/transmitter.c
index 890be41..3f2a745 100644
--- a/transmitter.c
+++ b/transmitter.c
@@ -324,60 +324,24 @@ static gboolean update_display(gpointer data) {
     // then obtain spectrum pixels from PS_RX_FEEDBACK,
     // that is, display the (attenuated) TX signal from the "antenna"
     //
-    // POSSIBLE MISMATCH OF SAMPLE RATES:
+    // POSSIBLE MISMATCH OF SAMPLE RATES IN ORIGINAL PROTOCOL:
     // TX sample rate is fixed 48 kHz, but RX sample rate can be
-    // 2*, 4*, or even 8* larger. In this case, the spectrum shown
-    // here is squeezed, so we have to extend the pixels.
-    // So the feedback spectrum is not nice to look at with 192000 Hz
-    // sample rate (low-res), but at least it is correct.
-    // For the sake of saving CPU cycles, we do not interpolate.
-    //
-    // This correction is applied her for the V1 protocol only, because
-    // there might be non-integer ratios using the new protocol.
+    // 2*, 4*, or even 8* larger. The analyzer has been set up to use
+    // more pixels in this case, so we just need to copy the
+    // inner part of the spectrum.
+    // If both spectra have the same number of pixels, this code
+    // just copies all of them
     //
     if(tx->puresignal && tx->feedback) {
       RECEIVER *rx_feedback=receiver[PS_RX_FEEDBACK];
       GetPixels(rx_feedback->id,0,rx_feedback->pixel_samples,&rc);
-      if (protocol == ORIGINAL_PROTOCOL && (active_receiver->sample_rate != 48000)) {
-        int ratio = active_receiver->sample_rate / 48000;
-        int width = tx->pixels / ratio;         // number of pixels to copy from the feedback spectrum
-        int start = (tx->pixels - width) >> 1;  // Copy from start ... (end-1) 
-        int end   = start + width;
-        int i;
-        float *tfp=tx->pixel_samples;
-	float *rfp=rx_feedback->pixel_samples+start;
-        switch (ratio) {
-          case 8:
-            for (i=start; i < end; i++) {
-		*tfp++ = *rfp;
-		*tfp++ = *rfp;
-		*tfp++ = *rfp;
-		*tfp++ = *rfp;
-		*tfp++ = *rfp;
-		*tfp++ = *rfp;
-		*tfp++ = *rfp;
-		*tfp++ = *rfp++;
-            }
-	    break;
-          case 4:
-            for (i=start; i < end; i++) {
-		*tfp++ = *rfp;
-		*tfp++ = *rfp;
-		*tfp++ = *rfp;
-		*tfp++ = *rfp++;
-            }
-	    break;
-          case 2:
-            for (i=start; i < end; i++) {
-		*tfp++ = *rfp;
-		*tfp++ = *rfp++;
-            }
-	    break;
-	}
-      } else {
-	// TX and feedback sample rates are equal -- just copy
-        memcpy(tx->pixel_samples,rx_feedback->pixel_samples,sizeof(float)*tx->pixels);
-      }
+      int full  = rx_feedback->pixels;  // number of pixels in the feedback spectrum
+      int width = tx->pixels;           // number of pixels to copy from the feedback spectrum
+      int start = (full-width) /2;      // Copy from start ... (end-1) 
+      float *tfp=tx->pixel_samples;
+      float *rfp=rx_feedback->pixel_samples+start;
+      // if full == width, then we just copy all samples
+      memcpy(tfp, rfp, width*sizeof(float));
     } else {
 #endif
       GetPixels(tx->id,0,tx->pixel_samples,&rc);
-- 
2.45.2