From 9c00fa04c46eb59d986ecab6022fce27b4837d9b Mon Sep 17 00:00:00 2001
From: DL1YCF <dl1ycf@darc.de>
Date: Sat, 28 Dec 2019 15:32:27 +0100
Subject: [PATCH] store "HermesLite" calibration in a variable (no hard-wiring)

---
 hpsdrsim.c      | 16 +++++++++++-----
 old_discovery.c | 18 ++++++++++++++----
 old_protocol.c  | 38 ++++++++++++++++++--------------------
 radio.c         |  3 +++
 radio.h         |  2 ++
 sliders.c       |  6 +++---
 6 files changed, 51 insertions(+), 32 deletions(-)

diff --git a/hpsdrsim.c b/hpsdrsim.c
index 005b8c1..ad26a3e 100644
--- a/hpsdrsim.c
+++ b/hpsdrsim.c
@@ -178,7 +178,7 @@ int main(int argc, char *argv[])
 	pthread_attr_t attr;
 	pthread_t thread;
 
-	uint8_t reply[11] = { 0xef, 0xfe, 2, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 32, 1 };
+	uint8_t reply[11] = { 0xef, 0xfe, 2, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0, 1 };
 
 	uint8_t id[4] = { 0xef, 0xfe, 1, 6 };
 	uint32_t code;
@@ -587,7 +587,13 @@ int main(int argc, char *argv[])
 				if (active_thread || new_protocol_running()) {
 				    reply[2] = 3;
 				}
+				reply[9]=31; // software version
 				reply[10] = OLDDEVICE;
+				if (OLDDEVICE == DEVICE_HERMES_LITE2) {
+				    // use HL1 device ID and new software version
+				    reply[9]=41;
+				    reply[10]=DEVICE_HERMES_LITE;
+				}
 				memset(buffer, 0, 60);
 				memcpy(buffer, reply, 11);
 
@@ -1049,14 +1055,14 @@ void process_ep2(uint8_t *frame)
 	     // to an RX gain of -12 to +48 dB. However the front-end hardware
 	     // determines which is the correct "zero level", that is, the gain
 	     // which corresponds to full-amplitude IQ samples for a 0 dBm input.
-	     // Experimentally, we set this "zero level" to +16 dB that (that is,
-	     // a RxGain value of 28). So the "attenuation" is (28 -G) where G
+	     // Experimentally, we set this "zero level" to +13 dB that (that is,
+	     // a RxGain value of 25). So the "attenuation" is (25 -G) where G
 	     // is the RXgain value.
 	     // NOTE: according to the AD9866 data sheet, this "calibration value"
-	     //       should be 22 instead of 28, while a value of 31 is used
+	     //       should be 22 instead of 25, while a value of 31 is used
 	     //       by the HermesLite firmware  when bit6 is not set.
 	     //
-	     chk_data(28 -(frame[4] & 0x3F) , rx_att[0], "RX1 HL ATT/GAIN");
+	     chk_data(25 -(frame[4] & 0x3F) , rx_att[0], "RX1 HL ATT/GAIN");
            } else {
              chk_data((frame[4] & 0x1F) >> 0, rx_att[0], "RX1 ATT");
              chk_data((frame[4] & 0x20) >> 5, rx1_attE, "RX1 ATT enable");
diff --git a/old_discovery.c b/old_discovery.c
index d63409c..70f458e 100644
--- a/old_discovery.c
+++ b/old_discovery.c
@@ -406,6 +406,7 @@ fprintf(stderr,"discover_receive_thread\n");
                 if(devices<MAX_DEVICES) {
                     discovered[devices].protocol=ORIGINAL_PROTOCOL;
                     discovered[devices].device=buffer[10]&0xFF;
+                    discovered[devices].software_version=buffer[9]&0xFF;
                     switch(discovered[devices].device) {
                         case DEVICE_METIS:
                             strcpy(discovered[devices].name,"Metis");
@@ -433,13 +434,23 @@ fprintf(stderr,"discover_receive_thread\n");
                             discovered[devices].frequency_max=61440000.0;
                             break;
                         case DEVICE_HERMES_LITE:
-			    // could also be a RadioBerry disguising itself as HermesLite
-                            strcpy(discovered[devices].name,"Hermes Lite");		
+			    //
+			    // It seems that some HermesLite V2 boards use
+			    // DEVICE_HERMES_LITE as the ID and a software version
+			    // that is larger or equal to 40, while the original
+			    // (V1) HermesLite boards have software versions up to 31.
+			    // Therefore this is possibly a HL2 board!
+			    if (discovered[devices].software_version < 40) {
+                              strcpy(discovered[devices].name,"HermesLite V1");		
+			    } else {
+                              strcpy(discovered[devices].name,"HermesLite V2");		
+			      discovered[devices].device = DEVICE_HERMES_LITE2;
+			    }
                             discovered[devices].frequency_min=0.0;
                             discovered[devices].frequency_max=30720000.0;
                             break;
                         case DEVICE_HERMES_LITE2:
-                            strcpy(discovered[devices].name,"Hermes Lite 2");		
+                            strcpy(discovered[devices].name,"HermesLite V2");		
                             discovered[devices].frequency_min=0.0;
                             discovered[devices].frequency_max=30720000.0;
                             break;
@@ -462,7 +473,6 @@ fprintf(stderr,"discover_receive_thread\n");
                             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];
                     }
diff --git a/old_protocol.c b/old_protocol.c
index b9df299..b0514a3 100644
--- a/old_protocol.c
+++ b/old_protocol.c
@@ -1169,23 +1169,24 @@ void ozy_send_buffer() {
     if(active_receiver->random) {
       output_buffer[C3]|=LT2208_RANDOM_ON;
     }
+    if(active_receiver->dither) {
+	output_buffer[C3]|=LT2208_DITHER_ON;
+    }
+#ifdef RADIOBERRY
     //
     // RadioBerry seems to encode the RXgain different from HERMES_LITE:
     // the dither bit is hi-jacked for bit5 of RXgain
+    //
     if (have_rx_gain) {
-#ifdef RADIOBERRY
-        // adc_attenuation is in the range 28 ... -32 and maps to 0 ... 60
-	if (adc_attenuation[active_receiver->adc] > 3)  { // RxGain > 31
-		output_buffer[C3]|=LT2208_DITHER_OFF;
-	} else {
-		output_buffer[C3]|=LT2208_DITHER_ON;
-	}
-#endif
-    } else {
-	if(active_receiver->dither) {
+        output_buffer[C3] &= ~LT2208_DITHER_ON;  // clear dither bit if if was set
+        int rxgain = rx_gain_calibration - adc_attenuation[active_receiver->adc];
+        if (rxgain <  0) rxgain=0;
+        if (rxgain > 60) rxgain=60;
+	if (rxgain > 31)  {
 		output_buffer[C3]|=LT2208_DITHER_ON;
 	}
     }
+#endif
     if (filter_board == CHARLY25 && active_receiver->preamp) {
       output_buffer[C3]|=LT2208_GAIN_ON;
     }
@@ -1469,25 +1470,22 @@ void ozy_send_buffer() {
 	  // to behave differently and stores bit5 of the gain in the
 	  // dither bit (see above) and a 5-bit attenuation value here.
 	  //
+          int rxgain = rx_gain_calibration - adc_attenuation[active_receiver->adc];
+          if (rxgain <  0) rxgain=0;
+          if (rxgain > 60) rxgain=60;
 #ifdef RADIOBERRY
-	  // adc_attenuation is in the range 28 ... -32
-	  int att = 28 + adc_attenuationctive_receiver->adc];  // RxGain: 0 ... 60
-          if (att <  0) att=0;
-          if (att > 60) att=60;
-          if (att > 31) att -= 32;  // high bit set above in dither
+	  // encode lower 5 bits of RXgain
           if (isTransmitting()) {
             output_buffer[C4]=0x20 | (transmitter->attenuation & 0x1F);
           } else {
-            output_buffer[C4]=0x20|att;
+            output_buffer[C4]=0x20 | (rxgain & 0x1F);
           }
 #else
-	  int att = 28 - adc_attenuation[active_receiver->adc];
-          if (att <  0) att=0;
-          if (att > 60) att=60;
+	  // encode all 6 bits of RXgain in ATT value and set bit6
           if (isTransmitting()) {
 	    output_buffer[C4] = 0x40 | (31 - (transmitter->attenuation & 0x1F));
           } else { 
-	    output_buffer[C4] = 0x40 | att;
+	    output_buffer[C4] = 0x40 | (rxgain & 0x3F);
           }
 #endif
         } else {
diff --git a/radio.c b/radio.c
index 193ae59..f73b43e 100644
--- a/radio.c
+++ b/radio.c
@@ -259,6 +259,7 @@ int tune=0;
 int memory_tune=0;
 int full_tune=0;
 int have_rx_gain=0;
+int rx_gain_calibration=25;
 
 //long long displayFrequency=14250000;
 //long long ddsFrequency=14250000;
@@ -434,9 +435,11 @@ void start_radio() {
 	    case DEVICE_HERMES_LITE:
 	    case DEVICE_HERMES_LITE2:
 		have_rx_gain=1;
+		rx_gain_calibration=25;
 		break;
 	    default:
 		have_rx_gain=0;
+		rx_gain_calibration=0;
 		break;
 	}
 	break;
diff --git a/radio.h b/radio.h
index 937ee29..b91dd5e 100644
--- a/radio.h
+++ b/radio.h
@@ -278,6 +278,8 @@ extern double display_calibration;
 extern int can_transmit;
 
 extern int have_rx_gain;   // TRUE on HermesLite/RadioBerry
+extern int rx_gain_calibration;  // position of the RX gain slider that
+				 // corresponds to zero amplification/attenuation
 
 extern void radio_stop();
 extern void reconfigure_radio();
diff --git a/sliders.c b/sliders.c
index 280222e..963a517 100644
--- a/sliders.c
+++ b/sliders.c
@@ -160,7 +160,7 @@ static void attenuation_value_changed_cb(GtkWidget *widget, gpointer data) {
     //from 0 - 48 db; the rx-gain slider functions as a gain slider with att = 0;
     //att set to 20 for good power measurement.
     int rx_gain_slider_value = (int)gtk_range_get_value(GTK_RANGE(attenuation_scale));
-    adc_attenuation[active_receiver->adc]= 28 - rx_gain_slider_value;
+    adc_attenuation[active_receiver->adc]= rx_gain_calibration - rx_gain_slider_value;
     set_attenuation(adc_attenuation[active_receiver->adc]);
   } else {
     adc_attenuation[active_receiver->adc]=(int)gtk_range_get_value(GTK_RANGE(attenuation_scale));
@@ -172,7 +172,7 @@ void set_attenuation_value(double value) {
   adc_attenuation[active_receiver->adc]=(int)value;
   if(display_sliders) {
     if (have_rx_gain) {
-	gtk_range_set_value (GTK_RANGE(attenuation_scale),(double)(28-adc_attenuation[active_receiver->adc]));
+	gtk_range_set_value (GTK_RANGE(attenuation_scale),(double)(rx_gain_calibration-adc_attenuation[active_receiver->adc]));
     } else {
         gtk_range_set_value (GTK_RANGE(attenuation_scale),(double)adc_attenuation[active_receiver->adc]);
     }
@@ -786,7 +786,7 @@ fprintf(stderr,"sliders_init: width=%d height=%d\n", width,height);
 
   if (have_rx_gain) {
 	attenuation_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 60.0, 1.0);
-	gtk_range_set_value (GTK_RANGE(attenuation_scale),28-adc_attenuation[active_receiver->adc]);
+	gtk_range_set_value (GTK_RANGE(attenuation_scale),rx_gain_calibration-adc_attenuation[active_receiver->adc]);
   } else {
 	attenuation_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 31.0, 1.0);
 	gtk_range_set_value (GTK_RANGE(attenuation_scale),adc_attenuation[active_receiver->adc]);
-- 
2.45.2