]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
VOX corrected, RX/TX switching reworked, streamlining
authorc vw <dl1ycf@darc.de>
Tue, 21 May 2019 08:38:33 +0000 (10:38 +0200)
committerc vw <dl1ycf@darc.de>
Tue, 21 May 2019 08:38:33 +0000 (10:38 +0200)
30 files changed:
Makefile
Makefile.mac
agc_menu.c
audio_waterfall.c
band_menu.c
bandstack_menu.c
dsp_menu.c
equalizer_menu.c
error_handler.c
filter_menu.c
freqent_menu.c
hpsdrsim.c
iambic.c
main.c
new_discovery.c
new_protocol.c
new_protocol_programmer.c
old_discovery.c
old_protocol.c
ps_menu.c
radio.c
radio.h
rigctl.c
rx_menu.c
step_menu.c
transmitter.c
vfo.c
vfo_menu.c
vox.c
waterfall.c

index a6a0f1d02bb1671ac3972e3dcc1944bd962e1c5f..ef76aeddd2990eb9cc1c4a8e0d7667b2ac3ed221 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -435,7 +435,7 @@ prebuild:
 
 clean:
        -rm -f *.o
-       -rm -f $(PROGRAM)
+       -rm -f $(PROGRAM) hpsdrsim
 
 install: $(PROGRAM)
        cp $(PROGRAM) /usr/local/bin
index 26491ea216d6c499844c21ce96ce9f2633e427e2..e3e7f5e9f9afbc9152b16b42d47a718dbb565ed8 100644 (file)
@@ -436,6 +436,7 @@ clean:
        -rm -f *.o
        -rm -f $(PROGRAM)
        -rm -rf $(PROGRAM).app
+       -rm -f hpsdrsim
 
 install: $(PROGRAM)
        cp $(PROGRAM) /usr/local/bin
@@ -459,7 +460,7 @@ hpsdrsim.o:     hpsdrsim.c
        $(CC) -c -O $(PORTAUDIO_OPTIONS) hpsdrsim.c
         
 hpsdrsim:       hpsdrsim.o
-       $(LINK) -o hpsdrsim hpsdrsim.o -lm -lpthread $(AUDIO_LIBS)
+       $(LINK) -o hpsdrsim hpsdrsim.o $(AUDIO_LIBS) -lm -lpthread
 
 #############################################################################
 #
index 3c9262d77d6dbc6060fa34614da5d7b5df26fd32..116ce241d2408ce15d3b1e829dd1ceea2412be39 100644 (file)
@@ -60,9 +60,6 @@ static gboolean agc_select_cb (GtkWidget *widget, gpointer        data) {
   //wdsp_set_agc(CHANNEL_RX0, agc);
   set_agc(active_receiver, active_receiver->agc);
   vfo_update();
-  // DL1YCF added return statement to make the compiler happy.
-  // however I am unsure about the correct return value.
-  // I would have coded this as a void function.
   return FALSE;
 }
 
index cbf606f7d220790ebfa91e90e597d7fa79ac056b..ae89d7cc3453688895ebe05bbf689f19e101b15b 100644 (file)
@@ -78,7 +78,6 @@ waterfall_configure_event_cb (GtkWidget         *widget,
   int height=gtk_widget_get_allocated_height (widget);
 fprintf(stderr,"audio: waterfall_configure_event: width=%d height=%d\n",width,height);
   pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height);
-  // DL1YCF changed to uchar *
   unsigned char *pixels = gdk_pixbuf_get_pixels (pixbuf);
 
   memset(pixels, 0, width*height*3);
@@ -136,7 +135,6 @@ void audio_waterfall_update() {
   int i;
 
   if(pixbuf) {
-    // DL1YCF changed to uchar *
     unsigned char *pixels = gdk_pixbuf_get_pixels (pixbuf);
 
     int width=gdk_pixbuf_get_width(pixbuf);
@@ -149,7 +147,6 @@ void audio_waterfall_update() {
     memmove(&pixels[rowstride*(header+1)],&pixels[rowstride*header],(height-(header+1))*rowstride);
 
     float sample;
-   // DL1YCF changed to uchar *
     unsigned char *p;
     int average=0;
     p=&pixels[rowstride*header];
index c82a3e8faae3b7b8491161cc134346ab1bfb7f24..f1433d126b7d767d14c68e3f68629a072d0dc161 100644 (file)
@@ -64,9 +64,6 @@ gboolean band_select_cb (GtkWidget *widget, gpointer        data) {
   last_band=widget;
   set_button_text_color(last_band,"orange");
   vfo_band_changed(b);
-  // DL1YCF added return statement to make the compiler happy.
-  // however I am unsure about the correct return value.
-  // I would have coded this as a void function.
   return FALSE;
 }
 
index aa05ff04d08347049b18575fc652873b61d9c420..4f8dc575f37f6bed5db4066d6932bf3a3c9ec8eb 100644 (file)
@@ -63,9 +63,6 @@ static gboolean bandstack_select_cb (GtkWidget *widget, gpointer        data) {
   last_bandstack=widget;
   set_button_text_color(last_bandstack,"orange");
   vfo_bandstack_changed(b);
-  // DL1YCF added return statement to make the compiler happy.
-  // however I am unsure about the correct return value.
-  // I would have coded this as a void function.
   return FALSE;
 }
 
index 73ea8c7a6a65a11be4bdad63782990a0a9c2118d..1e8fcc88d7605bf80978549e117bf8b5b4e86830 100644 (file)
@@ -70,7 +70,6 @@ static void pre_post_agc_cb(GtkWidget *widget, gpointer data) {
 }
 
 static void nr2_gain_cb(GtkWidget *widget, gpointer data) {
-// DL1YCF changed == to =
   active_receiver->nr2_gain_method=(uintptr_t)data;
   SetRXAEMNRgainMethod(active_receiver->id, active_receiver->nr2_gain_method);
 }
index 325c24922d2e54f5c6ae49f5baaca5b4377dece1..d999d0b23ee8716b8f1052452377ee82ad685ef0 100644 (file)
@@ -70,9 +70,6 @@ static gboolean tx_rb_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat
     gtk_range_set_value(GTK_RANGE(mid_scale),(double)tx_equalizer[2]);
     gtk_range_set_value(GTK_RANGE(high_scale),(double)tx_equalizer[3]);
   }
-  // DL1YCF added return statement to make the compiler happy.
-  // however I am unsure about the correct return value.
-  // I would have coded this as a void function.
   return FALSE;
 }
 
@@ -86,9 +83,6 @@ static gboolean rx_rb_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat
     gtk_range_set_value(GTK_RANGE(mid_scale),(double)rx_equalizer[2]);
     gtk_range_set_value(GTK_RANGE(high_scale),(double)rx_equalizer[3]);
   }
-  // DL1YCF added return statement to make the compiler happy.
-  // however I am unsure about the correct return value.
-  // I would have coded this as a void function.
   return FALSE;
 }
 
@@ -100,9 +94,6 @@ static gboolean enable_cb (GtkWidget *widget, GdkEventButton *event, gpointer da
     enable_rx_equalizer=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
     SetRXAEQRun(active_receiver->id, enable_rx_equalizer);
   }
-  // DL1YCF added return statement to make the compiler happy.
-  // however I am unsure about the correct return value.
-  // I would have coded this as a void function.
   return FALSE;
 }
 
index 800b04d13c4a47881e0b546b98201255cbc833e1..5802a337e2b3df93aa55d729dbea4fd178005fab 100644 (file)
@@ -22,9 +22,6 @@ int show_error(void *data) {
   gtk_widget_show(label);
   timer=g_timeout_add(5000,timeout_cb,NULL);
   int result=gtk_dialog_run(GTK_DIALOG(dialog));
-  // DL1YCF added return statement to make the compiler happy.
-  // however I am unsure about the correct return value.
-  // I would have coded this as a void function.
   return FALSE;
 }
 
index 9d63ab26247518cdf4fa73eb67e3e1c77d9be7c3..3bc85709893190f5fdc59aa644d12d0a4d707d0e 100644 (file)
@@ -88,9 +88,6 @@ static gboolean deviation_select_cb (GtkWidget *widget, gpointer data) {
   last_filter=widget;
   set_button_text_color(last_filter,"orange");
   vfo_update();
-  // DL1YCF added return statement to make the compiler happy.
-  // however I am unsure about the correct return value.
-  // I would have coded this as a void function.
   return FALSE;
 }
 
index 0370ff723273d069bc4973d673136887d601d637..59d49e324758bb7e29432f13aeb1ca12f260e8fe 100644 (file)
@@ -146,7 +146,6 @@ static gboolean freqent_select_cb (GtkWidget *widget, gpointer data) {
         }
     }
     vfo_update();
-    // DL1YCF added return statement
     return FALSE;
 }
 
index 31e6903406929749d3a9d0562ef5a9a36d48015d..6ecf73c46168f011d9e251bdd220b1592da58d99 100644 (file)
@@ -1,5 +1,7 @@
+//#define MICSAMPLES   // define to send microphone samples (triggered by attenuator slider)
+//#define TX_ENVELOPE  // define to dump TX envelope 1 sec after first PTT
 /*
- * HPSDR simulator, (C) Christoph van Wuellen, April 2019
+ * HPSDR simulator, (C) Christoph van Wuellen, April/Mai 2019
  *
  * This program simulates a HPSDR board.
  * If an SDR program such as phipsdr "connects" with this program, it
  *
  * RF1: ADC noise (16-bit ADC) plus a  800 Hz signal at -100dBm
  * RF2: ADC noise (16-bit ADC) plus a 2000 Hz signal at - 80dBm
- * RF3: TX feedback signal with some distortion. This signal is modulated
+ * RF3: TX feedback signal with some distortion. Signal strength
  *      according to the "TX drive" and "TX ATT" settings.
- * RF4: TX signal with a peak value of 0.400
+ * RF4: normalized undistorted TX signal with a peak value of 0.400
  *
- * RF1 and RF2 are attenuated according to the preamp/attenuator settings.
- * RF3 respects the "TX drive" and "TX ATT" settings
- * RF4 is the TX signal multiplied with 0.4 (ignores TX_DRIVE and TX_ATT).
+ * RF1 and RF2 respect the Preamp and Attenuator settings
  *
  * Depending on the device type, the receivers see different signals
  * (This is necessary for PURESIGNAL). We chose the association such that
  * DEVICE=HERMES:   RX3=RF3, RX4=RF4  (also for DEVICE=StemLab)
  * DEVICE=ORION2:   RX4=RF3, RX5=RF5  (also for DEVICE=ANGELIA and ORION)
  *
+ *
+ * Audio sent to the "radio" is played via the first available output channel.
+ * This works on MacOS (PORTAUDIO) and Linux (ALSA).
+ *
+ * Additional feature include the recording of the TX envelope of the first second
+ * of TXing, and the possiblity to read a file with mic samples and "send"
+ * them to the SDR. Both features are meant for testing RX/TX timings.
  */
 #include <stdio.h>
 #include <errno.h>
@@ -60,7 +67,7 @@
 // Forward declarations for the audio functions
 void audio_get_cards(void);
 void audio_open_output();
-void audio_write(short, short);
+void audio_write(int16_t, int16_t);
 
 
 #ifndef __APPLE__
@@ -109,8 +116,8 @@ static int          LineGain = -1;
 static int             MicPTT = -1;
 static int             tip_ring = -1;
 static int             MicBias = -1;
-static int             ptt=-1;
-static int             att=-1;
+static int             ptt=0;
+static int             AlexAtt=-1;
 static int             TX_class_E = -1;
 static int             OpenCollectorOutputs=-1;
 static long            tx_freq=-1;
@@ -138,10 +145,32 @@ static int              freq=-1;
 
 // floating-point represeners of TX att, RX att, and RX preamp settings
 
-static double txdrv_dbl = 1.0;
+static double txdrv_dbl = 0.99;
 static double txatt_dbl = 1.0;
 static double rxatt_dbl[4] = {1.0, 1.0, 1.0, 1.0};   // this reflects both ATT and PREAMP
 
+#ifdef TX_ENVELOPE
+//
+// This records the size of the first MAXENV TX samples after the first RX-TX transition.
+// This can be used to detect whether RX/TX transitions are fast enough not to chop
+// the first part of an SSB transmission using VOX, or of the first CW element.
+//
+#define MAXENV 48000
+static float envelope[MAXENV];
+int          envptr=0;
+#endif
+
+#ifdef MICSAMPLES
+//
+// Raw audio data (48000 16-bit int words) is read from a file and stored.
+// As soon as the ALEX attenuators are engaged, these mic samples are
+// sent to the SDR program ONCE.
+//
+static int16_t micsamples[48000];
+int micsamples_ptr=-2;
+int micsamples_rate=0;
+#endif
+
 static int sock_ep2;
 
 static struct sockaddr_in addr_ep6;
@@ -203,7 +232,18 @@ int main(int argc, char *argv[])
        int udp_retries=0;
        int bytes_read, bytes_left;
        uint32_t *code0 = (uint32_t *) buffer;  // fast access to code of first buffer
-
+        int fd;
+
+#ifdef MICSAMPLES
+        fd=open("micsamples", O_RDONLY);
+        if (fd >= 0) {
+         if (read(fd, micsamples, 48000*sizeof(int16_t)) == 48000*sizeof(int16_t)) {
+           fprintf(stderr,"MIC SAMPLES available\n");
+           micsamples_ptr=-1;
+         }
+       }
+#endif
+        
        audio_get_cards();
         audio_open_output();
 /*
@@ -446,6 +486,20 @@ int main(int argc, char *argv[])
                                        sample |= (int) ((signed char) *bp++ & 0xFF);
                                        dqsample=(double) sample / 32768.0;
 
+#ifdef TX_ENVELOPE
+                                       if (ptt || envptr > 0) {
+                                         if (envptr < MAXENV) envelope[envptr++]=(disample*disample+dqsample*dqsample);
+                                         if (envptr == MAXENV) {
+                                           fd=open("dump.envelope", O_RDWR | O_CREAT | O_TRUNC, (mode_t) 0777);
+                                           if (fd >= 0) {
+                                             write (fd, envelope, MAXENV*sizeof(float));
+                                             close (fd);
+                                             fprintf(stderr,"TX ENV dumped\n");
+                                           }
+                                           envptr++;
+                                         }
+                                       }
+#endif
                                        switch (rate) {
                                            case 0:  // RX sample rate = TX sample rate = 48000
                                                isample[txptr  ]=disample;
@@ -655,7 +709,7 @@ void process_ep2(uint8_t *frame)
           chk_data(frame[2] & 1, TX_class_E, "TX CLASS-E");
           chk_data((frame[2] & 0xfe) >> 1, OpenCollectorOutputs,"OpenCollector");
 
-          chk_data((frame[3] & 0x03) >> 0, att, "ALEX Attenuator");
+          chk_data((frame[3] & 0x03) >> 0, AlexAtt, "ALEX Attenuator");
           chk_data((frame[3] & 0x04) >> 2, preamp, "ALEX preamp");
           chk_data((frame[3] & 0x08) >> 3, LTdither, "LT2208 Dither");
           chk_data((frame[3] & 0x10) >> 4, LTrandom, "LT2208 Random");
@@ -669,11 +723,15 @@ void process_ep2(uint8_t *frame)
           chk_data(((frame[4] >> 7) & 1), CommonMercuryFreq,"Common Mercury Freq");
 
          if (isc25) {
-             // 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!
-               rxatt_dbl[0]=pow(10.0, -0.05*(12*att-18*LTdither-18*preamp));
-               rxatt_dbl[1]=1.0;
+              // 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!
+              rxatt_dbl[0]=pow(10.0, -0.05*(12*AlexAtt-18*LTdither-18*preamp));
+              rxatt_dbl[1]=1.0;
+          } else {
+             // Assume that it has ALEX attenuators in addition to the Step Attenuators
+              rxatt_dbl[0]=pow(10.0, -0.05*(10*AlexAtt+rx_att[0]));
+              rxatt_dbl[1]=1.0;
           }
          break;
 
@@ -728,8 +786,8 @@ void process_ep2(uint8_t *frame)
           chk_data(frame[3] & 0x40,lna6m,"ALEX 6m LNA");
           chk_data(frame[3] & 0x80,alexTRdisable,"ALEX T/R disable");
           chk_data(frame[4],alex_lpf,"ALEX LPF");
-           // reset TX level
-          txdrv_dbl=(double) txdrive / 255.0;
+           // reset TX level. Leve a little head-room for noise
+          txdrv_dbl=(double) txdrive / 256.0;
           break;
 
        case 20:
@@ -753,12 +811,16 @@ 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");
 
+#ifdef MICSAMPLES
+         if (rx_att[0] > 20 && micsamples_ptr == -1) micsamples_ptr =  0;
+         if (rx_att[0] < 10 && micsamples_ptr == 48000) micsamples_ptr = -1;
+#endif
           if (!isc25) {
-            // Set RX amplification factors. Assume 20 dB preamps
-             rxatt_dbl[0]=pow(10.0, -0.05*(rx_att[0]-20*rx_preamp[0]));
-             rxatt_dbl[1]=pow(10.0, -0.05*(rx_att[1]-20*rx_preamp[1]));
-             rxatt_dbl[2]=pow(10.0, (double) rx_preamp[2]);
-             rxatt_dbl[3]=pow(10.0, (double) rx_preamp[3]);
+            // 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]));
+             rxatt_dbl[2]=1.0;
+             rxatt_dbl[3]=1.0;
           }
           break;
 
@@ -771,8 +833,8 @@ void process_ep2(uint8_t *frame)
            chk_data(frame[4] & 127, cw_weight,"CW WEIGHT");
            chk_data((frame[4] >> 7) & 1, cw_spacing, "CW SPACING");
 
-          // Set RX amplification factors. Assume 20 dB preamps
-           rxatt_dbl[1]=pow(10.0, -0.05*(rx_att[1]-20*rx_preamp[1]));
+          // Set RX amplification factors.
+           rxatt_dbl[1]=pow(10.0, -0.05*(rx_att[1]));
           break;
 
        case 24:
@@ -850,6 +912,7 @@ void *handler_ep6(void *arg)
         int32_t rf4isample,rf4qsample;
 
        int32_t myisample,myqsample;
+        int16_t ssample;
 
         struct timespec delay;
 #ifdef __APPLE__
@@ -959,13 +1022,13 @@ void *handler_ep6(void *arg)
                        rf2qsample=noiseQtab[noiseIQpt] * 8388607.0;
                        rf2qsample += T2000Qtab[pt2000] * 838.86070 * rxatt_dbl[1];
                        //
-                       // RF3: TX signal distorted
+                       // RF3: TX signal distorted, with some ADC noise
                        //
                        i1=isample[rxptr]*txdrv_dbl;
                        q1=qsample[rxptr]*txdrv_dbl;
                        fac=IM3a+IM3b*(i1*i1+q1*q1);
-                       rf3isample= txatt_dbl*i1*fac * 8388607.0;
-                       rf3qsample= txatt_dbl*q1*fac * 8388607.0;
+                       rf3isample= (txatt_dbl*i1*fac+noiseItab[noiseIQpt]) * 8388607.0;
+                       rf3qsample= (txatt_dbl*q1*fac+noiseItab[noiseIQpt]) * 8388607.0;
                        //
                        // RF4: TX signal with peak=0.4
                        //
@@ -1028,8 +1091,24 @@ void *handler_ep6(void *arg)
                            *pointer++ = (myqsample >>  8) & 0xFF;
                            *pointer++ = (myqsample >>  0) & 0xFF;
                        }
+#ifdef MICSAMPLES
+                       if (micsamples_ptr >= 0 && micsamples_ptr < 48000) {
+                         ssample=micsamples[micsamples_ptr];
+                         *pointer++ = (ssample >> 8) & 0xFF;
+                         *pointer++ = (ssample     ) & 0xFF;
+                         micsamples_rate++;
+                         if (micsamples_rate == 1 << rate) {
+                               micsamples_rate=0;
+                               micsamples_ptr++;
+                         }
+                       } else {
+                         *pointer++ = 0;
+                         *pointer++ = 0;
+                       }
+#else
                        // Microphone samples: silence
                        pointer += 2;
+#endif
                        rxptr++;     if (rxptr >= RTXLEN) rxptr=0;
                        noiseIQpt++; if (noiseIQpt == LENNOISE) noiseIQpt=rand() / NOISEDIV;
                        pt2000++;    if (pt2000 == len2000) pt2000=0;
@@ -1161,7 +1240,7 @@ void audio_open_output()
   return;
 }
 
-void audio_write (short l, short r)
+void audio_write (int16_t l, int16_t r)
 {
   PaError err;
   if (playback_handle != NULL) {
@@ -1342,7 +1421,7 @@ void audio_open_output() {
   return;
 }
 
-void audio_write(short left_sample,short right_sample) {
+void audio_write(int16_t left_sample,int16_t right_sample) {
   snd_pcm_sframes_t delay;
   int error;
   long trim;
index 70bdde6e1c2096a04a8b83146c468dcde470712d..56d11b2d3681caec0e88ac80745436d06b8feefc 100644 (file)
--- a/iambic.c
+++ b/iambic.c
@@ -312,11 +312,6 @@ void keyer_event(int left, int state) {
     if (state) {
         // This is for aborting CAT CW messages if a key is hit.
        cw_key_hit = 1;
-        // do PTT already here, unless TX mode was activated before
-        if (running && !cwvox && !mox) {
-          g_idle_add(ext_mox_update, (gpointer)(long) 1);
-       }
-        cwvox=(int) cw_keyer_hang_time;
     }
     if (left) {
       // left paddle hit or released
@@ -377,10 +372,29 @@ static void* keyer_thread(void *arg) {
         sem_wait(&cw_event);
 #endif
 
+       // swallow any cw_events posted during the last "cw hang" time.
+        if (!kcwl && !kcwr) continue;
+
+        if (!mox) {
+          g_idle_add(ext_mox_update, (gpointer)(long) 1);
+          // Wait for mox, that is, wait for WDSP shutting down the RX and
+          // firing up the TX. This induces a small delay when hitting the key for
+          // the first time, but excludes that the first dot is swallowed.
+          // Note: if out-of-band, mox will never come, therefore
+          // give up after 100 msec.
+          i=100;
+          while (!mox && i-- > 0) usleep(1000);
+          cwvox=(int) cw_keyer_hang_time;
+       }
+
         key_state = CHECK;
 
         clock_gettime(CLOCK_MONOTONIC, &loop_delay);
         while (key_state != EXITLOOP || cwvox > 0) {
+         //
+         // if key_state == EXITLOOP and cwvox == 0, then
+         // just leave the while-loop without removing MOX
+         //
          // re-trigger VOX if *not* busy-spinning
           if (cwvox > 0 && key_state != EXITLOOP && key_state != CHECK) cwvox=(int) cw_keyer_hang_time;
 
diff --git a/main.c b/main.c
index 75a757836b3eee6d1d9cc54d46c757ced113f8ee..74e8099aff6bc532098ea9ea8d85c8df42868dc4 100644 (file)
--- a/main.c
+++ b/main.c
@@ -54,6 +54,7 @@
 #include "discovery.h"
 #include "new_protocol.h"
 #include "old_protocol.h"
+#include "frequency.h"   // for canTransmit
 #include "ext.h"
 
 struct utsname unameData;
@@ -109,6 +110,31 @@ fprintf(stderr,"Creating wisdom file: %s\n", (char *)arg);
   return NULL;
 }
 
+//
+// handler for key press events.
+// SpaceBar presses toggle MOX, everything else downstream
+// code to switch mox copied from mox_cb() in toolbar.c,
+// but added the correct return values.
+//
+gboolean keypress_cb(GtkWidget *widget, GdkEventKey *event, gpointer data) {
+
+  if (event->keyval == GDK_KEY_space && radio != NULL) {
+    if(getTune()==1) {
+      setTune(0);
+    }
+    if(getMox()==1) {
+      setMox(0);
+    } else if(canTransmit() || tx_out_of_band) {
+      setMox(1);
+    } else {
+      transmitter_set_out_of_band(transmitter);
+    }
+    g_idle_add(ext_vfo_update,NULL);
+    return TRUE;
+  }
+  return FALSE;
+}
+
 gboolean main_delete (GtkWidget *widget) {
   if(radio!=NULL) {
 #ifdef GPIO
@@ -232,6 +258,13 @@ fprintf(stderr,"full screen\n");
   g_signal_connect (top_window, "delete-event", G_CALLBACK (main_delete), NULL);
   //g_signal_connect (top_window,"draw", G_CALLBACK (main_draw_cb), NULL);
 
+  //
+  // We want to use the space-bar as an alternative to go to TX
+  //
+  gtk_widget_add_events(top_window, GDK_KEY_PRESS_MASK);
+  g_signal_connect(top_window, "key_press_event", G_CALLBACK(keypress_cb), NULL);
+
+
 //fprintf(stderr,"create fixed container\n");
   //fixed=gtk_fixed_new();
   //gtk_container_add(GTK_CONTAINER(top_window), fixed);
index 634d99d349190f3b7eae1172be31806e25365f5a..3fed57e589d7ca6b728bbb5a9c2f17c0e995c9da 100644 (file)
@@ -185,7 +185,6 @@ void new_discover(struct ifaddrs* iface) {
 //void* new_discover_receive_thread(void* arg) {
 gpointer new_discover_receive_thread(gpointer data) {
     struct sockaddr_in addr;
-    // DL1YCF change from int to socklen_t
     socklen_t len;
     unsigned char buffer[2048];
     int bytes_read;
@@ -276,6 +275,5 @@ gpointer new_discover_receive_thread(gpointer data) {
     }
     fprintf(stderr,"new_discover: exiting new_discover_receive_thread\n");
     g_thread_exit(NULL);
-    // DL1YCF added return statement to make compiler happy.
     return NULL;
 }
index 9d855e7b12fc557b5a9d1f4f4d2efd4519d7f7a0..4e839d985f01068f9c7d879fb375778e9461b6f9 100644 (file)
@@ -74,13 +74,6 @@ int data_socket=-1;
 static int running;
 
 #ifdef __APPLE__
-//
-//DL1YCF:
-//Mac OS does not have sem_init for un-named semaphores,
-//we have to use named semaphores created with sem_open.
-//As a side effect, we consistently have to use sem_t
-//pointers instead of sem_t variables
-//
 sem_t *response_sem;
 #else
 sem_t response_sem;
@@ -200,7 +193,6 @@ static int psk_resample=6;  // convert from 48000 to 8000
 #define NET_BUFFER_SIZE 2048
 // Network buffers
 static struct sockaddr_in addr;
-// DL1YCF next line: changed int to socklen_t
 static socklen_t length;
 //static unsigned char buffer[NET_BUFFER_SIZE];
 static unsigned char *iq_buffer[MAX_RECEIVERS];
@@ -383,12 +375,6 @@ void new_protocol_init(int pixels) {
       rc=sem_init(&iq_sem_buffer[ddc], 0, 0);
 #endif
       iq_thread_id[ddc] = g_thread_new( "iq thread", iq_thread, (gpointer)(long)i);
-      //DL1YCF: g_thread new always returns a value, upon failure the program aborts
-      //        so the next four lines have been deactivated.
-      //if( ! iq_thread_id ) {
-      //  fprintf(stderr,"g_thread_new failed for iq_thread: rx=%d\n",i);
-      //  exit( -1 );
-      //}
       fprintf(stderr, "iq_thread: rx=%d ddc=%d thread=%p\n",i, ddc, iq_thread_id);
     }
 
@@ -1374,7 +1360,6 @@ static void process_iq_data(RECEIVER *rx) {
   }
   rx->iq_sequence++;
 
-// DL1YCF: changed semicolon at end of next line to a plus sign
   timestamp=((long long)(buffer[4]&0xFF)<<56)+((long long)(buffer[5]&0xFF)<<48)+((long long)(buffer[6]&0xFF)<<40)+((long long)(buffer[7]&0xFF)<<32)+
   ((long long)(buffer[8]&0xFF)<<24)+((long long)(buffer[9]&0xFF)<<16)+((long long)(buffer[10]&0xFF)<<8)+(long long)(buffer[11]&0xFF);
   bitspersample=((buffer[12]&0xFF)<<8)+(buffer[13]&0xFF);
@@ -1545,8 +1530,6 @@ static void process_mic_data(int bytes) {
   sequence=((mic_line_buffer[0]&0xFF)<<24)+((mic_line_buffer[1]&0xFF)<<16)+((mic_line_buffer[2]&0xFF)<<8)+(mic_line_buffer[3]&0xFF);
   b=4;
   for(i=0;i<MIC_SAMPLES;i++) {
-    // DL1YCF: changed this to two statements such that the order of pointer increments
-    //         becomes clearly defined.
     sample=(short)(mic_line_buffer[b++]<<8);
     sample |= (short) (mic_line_buffer[b++]&0xFF);
 #ifdef FREEDV
@@ -1569,13 +1552,9 @@ void new_protocol_process_local_mic(unsigned char *buffer,int le) {
   b=0;
   for(i=0;i<MIC_SAMPLES;i++) {
     if(le) {
-      // DL1YCF: changed this to two statements such that the order of pointer increments
-      //         becomes clearly defined.
       sample = (short)(buffer[b++]&0xFF);
       sample |= (short) (buffer[b++]<<8);
     } else {
-      // DL1YCF: changed this to two statements such that the order of pointer increments
-      //         becomes clearly defined.
       sample = (short)(buffer[b++]<<8);
       sample |= (short) (buffer[b++]&0xFF);
     }
@@ -1663,6 +1642,5 @@ fprintf(stderr,"new_protocol_timer_thread\n");
 //      }
 //    }
   }
-  // DL1YCF: added return statement to make compiler happy.
   return NULL;
 }
index 939ef04a5993876546d13f86c7723949beb93865..38d20105790a5777ff609ed56e0f959758c76822 100644 (file)
@@ -240,6 +240,5 @@ void *programmer_thread(void *arg) {
         block_sequence++;
     }
 
-    // DL1YCF added return statement to make compiler happy.
     return NULL;    
 }
index 3704bb52c6ca344fa3f7be2486419a122ced84dd..c5a71592d724380e7ed36d0ac0b3e7175d1efe31 100644 (file)
@@ -468,7 +468,6 @@ fprintf(stderr,"discover_receive_thread\n");
     }
     fprintf(stderr,"discovery: exiting discover_receive_thread\n");
     g_thread_exit(NULL);
-    // DL1YCF added return statement to make compiler happy.
     return NULL;
 }
 
index 9ed692693531bcd2e901e83914efb78bd8b9e802..3ef7d433bf6dfa6e2c398833731299a14593b586 100644 (file)
@@ -557,12 +557,29 @@ static void process_ozy_input_buffer(unsigned char  *buffer) {
   double right_sample_double_rx;
   double left_sample_double_tx;
   double right_sample_double_tx;
-  int nreceivers;
 
   int id=active_receiver->id;
 
   int tx_vfo=split?VFO_B:VFO_A;
 
+  int nreceivers;
+
+#ifdef PURESIGNAL
+    // DL1YCF:
+    // 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.
+    nreceivers=3;
+    if (device == DEVICE_HERMES) nreceivers=4;
+    if (device == DEVICE_ANGELIA || device == DEVICE_ORION || device == DEVICE_ORION2) nreceivers=5;
+#else
+#if defined(RADIOBERRY) || defined(PI_SDR)
+       nreceivers = receivers;
+#else
+       nreceivers=RECEIVERS;
+#endif
+#endif
+
   if(buffer[b++]==SYNC && buffer[b++]==SYNC && buffer[b++]==SYNC) {
     // extract control bytes
     control_in[0]=buffer[b++];
@@ -623,23 +640,6 @@ static void process_ozy_input_buffer(unsigned char  *buffer) {
         break;
     }
 
-
-#ifdef PURESIGNAL
-    // DL1YCF:
-    // 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.
-    nreceivers=3;
-    if (device == DEVICE_HERMES) nreceivers=4;
-    if (device == DEVICE_ANGELIA || device == DEVICE_ORION || device == DEVICE_ORION2) nreceivers=5;
-#else
-       #if defined(RADIOBERRY) || defined(PI_SDR)
-               nreceivers = receivers;
-       #else
-               nreceivers=RECEIVERS;
-       #endif
-#endif
-
     int iq_samples=(512-8)/((nreceivers*6)+2);
 
     for(i=0;i<iq_samples;i++) {
@@ -818,13 +818,9 @@ void old_protocol_process_local_mic(unsigned char *buffer,int le) {
     // avoid pointer increments in logical-or constructs, as the sequence
     // is undefined
     if(le) {
-      // DL1YCF: changed this to two statements such that the order of pointer increments
-      //         becomes clearly defined.
       sample = (short) (buffer[b++]&0xFF);
       sample |= (short) (buffer[b++]<<8);
     } else {
-      // DL1YCF: changed this to two statements such that the order of pointer increments
-      //         becomes clearly defined.
       sample = (short)(buffer[b++]<<8);
       sample |=  (short) (buffer[b++]&0xFF);
     }
@@ -852,6 +848,22 @@ void ozy_send_buffer() {
   BAND *band;
   int nreceivers;
 
+#ifdef PURESIGNAL
+    // DL1YCF:
+    // 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.
+    nreceivers=3;
+    if (device == DEVICE_HERMES) nreceivers=4;
+    if (device == DEVICE_ANGELIA || device == DEVICE_ORION || device == DEVICE_ORION2) nreceivers=5;
+#else
+#if defined(RADIOBERRY) || defined(PI_SDR)
+       nreceivers = receivers;
+#else
+       nreceivers=RECEIVERS;
+#endif
+#endif
+
   output_buffer[SYNC0]=SYNC;
   output_buffer[SYNC1]=SYNC;
   output_buffer[SYNC2]=SYNC;
@@ -944,25 +956,17 @@ void ozy_send_buffer() {
     //
     // Upon TX, we might have to activate a different RX path for the
     // attenuated feedback signal. Use feedback_antenna == 0, if
-    // the feedback signal is routed automatically/internally (e.g.
-    // ANAN-7000DLE, when using the internal feedback path).
+    // the feedback signal is routed automatically/internally
     //
     if (isTransmitting() && transmitter->puresignal) i=receiver[PS_RX_FEEDBACK]->feedback_antenna;
 #endif
     switch(i) {
-      case 0:  // ANT 1
-      case 1:  // ANT 2
-      case 2:  // ANT 3
-        break;
       case 3:  // Alex: RX2 IN, ANAN: EXT1, ANAN7000: EXT
         output_buffer[C3]|=0xC0;
         break;
       case 4:  // Alex: RX1 IN, ANAN: EXT2, ANAN7000: RX BYPASS
         output_buffer[C3]|=0xA0;
         break;
-      case 5:  // XVTR
-        output_buffer[C3]|=0xE0;
-        break;
       default:
         break;
     }
@@ -970,21 +974,9 @@ void ozy_send_buffer() {
 
 // TODO - add Alex TX relay, duplex, receivers Mercury board frequency
     output_buffer[C4]=0x04;  // duplex
-#ifdef PURESIGNAL
-    // DL1YCF: see comment on "nreceivers" above. The number is reduced by 1 here
-    nreceivers=2;
-    if (device == DEVICE_HERMES) nreceivers=3;
-    if (device == DEVICE_ANGELIA || device == DEVICE_ORION || device == DEVICE_ORION2) nreceivers=4;
-#else
-       #ifdef RADIOBERRY
-               nreceivers = receivers-1;
-       #else
-               nreceivers=RECEIVERS-1;
-       #endif
-#endif
 
     // 0 ... 7 maps on 1 ... 8 receivers
-    output_buffer[C4]|=nreceivers<<3;
+    output_buffer[C4]|=(nreceivers-1)<<3;
     
     if(isTransmitting()) {
       switch(transmitter->alex_antenna) {
@@ -1030,9 +1022,8 @@ void ozy_send_buffer() {
     }
   } else {
     //
-    // metis_offset !=8: send "command" C&C packets in round-robin
-    // using the value of "command" from 1 to 10,
-    // and "command==2" packets are repeated for each RX
+    // metis_offset !=8: send the other C&C packets in round-robin
+    // RX frequency commands are repeated for each RX
     switch(command) {
       case 1: // tx frequency
         output_buffer[C0]=0x02;
@@ -1056,19 +1047,6 @@ void ozy_send_buffer() {
         output_buffer[C4]=txFrequency;
         break;
       case 2: // rx frequency
-#ifdef PURESIGNAL
-       // DL1YCF: see comment on "nreceivers" above.
-       nreceivers=3;
-       if (device == DEVICE_HERMES) nreceivers=4;
-       if (device == DEVICE_ANGELIA || device == DEVICE_ORION || device == DEVICE_ORION2) nreceivers=5;
-#else
-               #ifdef RADIOBERRY
-                       nreceivers = receivers;
-               #else
-                       nreceivers=RECEIVERS;
-               #endif
-#endif
-
         if(current_rx<nreceivers) {
           output_buffer[C0]=0x04+(current_rx*2);
 #ifdef PURESIGNAL
@@ -1311,6 +1289,11 @@ void ozy_send_buffer() {
         if(receiver[0]->alex_antenna==5) { // XVTR
           output_buffer[C2]=0x02;          // Alex2 XVTR enable
         }
+#ifdef PURESIGNAL
+        if(transmitter->puresignal) {
+          output_buffer[C2]|=0x40;        // Synchronize RX5 andh TX frequency on transmit
+        }
+#endif
         output_buffer[C3]=0x00;            // Alex2 filters
         output_buffer[C4]=0x00;            // Alex2 filters
         break;
index 9312459f21a1b2e191f996bba0e4b9032ee20431..5008ff0cbc91d0ff52beb8ea454b3fc536b56061 100644 (file)
--- a/ps_menu.c
+++ b/ps_menu.c
@@ -404,18 +404,22 @@ void ps_menu(GtkWidget *parent) {
   col++;
 
   GtkWidget *ps_ant_auto=gtk_radio_button_new_with_label(NULL,"AUTO");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ps_ant_auto), 
+    (receiver[PS_RX_FEEDBACK]->feedback_antenna!=3) && (receiver[PS_RX_FEEDBACK]->feedback_antenna!=4));
   gtk_widget_show(ps_ant_auto);
   gtk_grid_attach(GTK_GRID(grid), ps_ant_auto, col, row, 1, 1);
   g_signal_connect(ps_ant_auto,"toggled", G_CALLBACK(ps_ant_cb), (gpointer) (long) 0);
   col++;
 
   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]->feedback_antenna==3);
   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);
   col++;
 
   GtkWidget *ps_ant_ext2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ps_ant_auto),"EXT2");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ps_ant_ext2), receiver[PS_RX_FEEDBACK]->feedback_antenna==4);
   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);
diff --git a/radio.c b/radio.c
index 850e2713e29bdc3078fa3095cb29d593c745d5bb..3c029b4cd7236b0a3c58e7f8163f97c0404d43b8 100644 (file)
--- a/radio.c
+++ b/radio.c
@@ -729,9 +729,10 @@ static void rxtx(int state) {
     for(i=0;i<receivers;i++) {
 #ifdef PURESIGNAL
       // When using PURESIGNAL, delivery of RX samples
-      // comes to an abrupt stop (since they are "fed"
-      // to pscc()) upon a TX-RX transition.
-      // Therefore, wait for all receivers to complete
+      // to WDSP via fexchange0() comes to an abrupt stop
+      // since they go through add_ps_iq_samples()
+      // rather than add_iq_samples().
+      // Therefore, wait for *all* receivers to complete
       // their slew-down before going TX.
       SetChannelState(receiver[i]->id,0,1);
 #else
@@ -793,12 +794,13 @@ static void rxtx(int state) {
 }
 
 void setMox(int state) {
+  vox_cancel();  // remove time-out
+  if (vox) {     // if VOX active, turn it off
+    rxtx(0);
+    vox=0;
+  }
   if(mox!=state) {
-    if(vox_enabled && vox) {
-      vox_cancel();
-    } else {
-      rxtx(state);
-    }
+    rxtx(state);
     mox=state;
   }
 }
@@ -807,25 +809,25 @@ int getMox() {
     return mox;
 }
 
-void setVox(int state) {
-  if(vox!=state && !tune) {
+void vox_changed(int state) {
+  if(vox!=state && !tune && !mox) {
     rxtx(state);
-    vox=state;
   }
-  g_idle_add(ext_vfo_update,(gpointer)NULL);
-}
-
-void vox_changed(int state) {
-  setVox(state);
+  vox=state;
 }
 
 
 void setTune(int state) {
   int i;
 
+  // if state==tune, this function is a no-op
+
   if(tune!=state) {
-    if(vox_enabled && vox) {
-      vox_cancel();
+    vox_cancel();
+    if (vox || mox) {
+      rxtx(0);
+      vox=0;
+      mox=0;
     }
     if(state) {
       if(full_tune) {
@@ -851,9 +853,10 @@ void setTune(int state) {
       for(i=0;i<receivers;i++) {
 #ifdef PURESIGNAL
         // When using PURESIGNAL, delivery of RX samples
-        // comes to an abrupt stop (since they are "fed"
-        // to pscc()) upon a TX-RX transition.
-        // Therefore, wait for all receivers to complete
+        // to WDSP via fexchange0() comes to an abrupt stop
+        // since they go through add_ps_iq_samples()
+        // rather than add_iq_samples().
+        // Therefore, wait for *all* receivers to complete
         // their slew-down before going TX.
         SetChannelState(receiver[i]->id,0,1);
 #else
@@ -925,27 +928,6 @@ int getTune() {
   return tune;
 }
 
-// DL1YCF: because of the new CW algorithm,
-//         this function is no longer used
-void radio_cw_setup() {
-  int mode=vfo[VFO_A].mode;;
-  if(split) {
-    mode=vfo[VFO_B].mode;
-  }
-
-  // DL1YCF: to be "transceive" in CW, our signal
-  // needs to be spot-on the nominal frequency
-  SetTXAPostGenToneFreq(transmitter->id,(double) 0.0);
-  SetTXAPostGenMode(transmitter->id,0);
-  SetTXAPostGenToneMag(transmitter->id,0.99999);
-}
-
-// DL1YCF: because of the new CW algorithm,
-//         this function is no longer used
-void radio_cw_key(int state) {
-  SetTXAPostGenRun(transmitter->id,state);
-}
-
 int isTransmitting() {
   return mox | vox | tune;
 }
@@ -1032,21 +1014,6 @@ static int calcLevel(double d) {
 
   level=(int)(actual_volts*255.0);
 
-#ifdef __APPLE__
-#ifdef PURESIGNAL
-//
-//  DL1YCF: I do not know exactly why: if the drive level
-//          is set to zero while PS is active, the program
-//          reproducably crashes when the drive is set from 1 Watt
-//          to 0 Watt, possibly a division by zero or the evaluation
-//          of a logarithm within WDSP.
-//          QuickAndDirty Fix: use "1" as minimum drive level
-//          which corresponds to a fraction of a Watt.
-//
-  if (level < 1) level=1;
-#endif
-#endif
 //fprintf(stderr,"calcLevel: %f calib=%f level=%d\n",d, gbb, level);
   return level;
 }
diff --git a/radio.h b/radio.h
index 3f38bfc08bbd74014d369809b677953ddfb845ae..8a7656d43ac980d4e3ddff5fc6373d4eb9b59101 100644 (file)
--- a/radio.h
+++ b/radio.h
@@ -261,7 +261,6 @@ extern void setMox(int state);
 extern int getMox();
 extern void setTune(int state);
 extern int getTune();
-extern void setVox(int state);
 extern void vox_changed(int state);
 extern double getDrive();
 extern void setDrive(double d);
@@ -289,10 +288,6 @@ extern void calculate_display_average();
 extern void set_filter_type(int filter_type);
 extern void set_filter_size(int filter_size);
 
-extern void radio_cw_setup();
-
-extern void radio_cw_key(int state);
-
 #ifdef FREEDV
 extern void set_freedv(int state);
 #endif
index 7ec96d95ecfb696c14b4a21e61304517d6b04e72..81b40dc9810c3dd74dac6af0a32617b1ac517845 100644 (file)
--- a/rigctl.c
+++ b/rigctl.c
@@ -79,7 +79,6 @@ int connect_cnt = 0;
 
 int rigctlGetFilterLow();
 int rigctlGetFilterHigh();
-// DL1YCF changed next to function to void
 void rigctlSetFilterLow(int val);
 void rigctlSetFilterHigh(int val);
 int new_level;
@@ -197,7 +196,6 @@ static gpointer set_rigctl_timer (gpointer data) {
       // Wait throttle time
       usleep(RIGCTL_TIMER_DELAY);
       rigctl_timer = 0;
-      // DL1YCF added return statement to make compiler happy.
       return NULL;
 }
 
@@ -552,9 +550,9 @@ static gpointer rigctl_cw_thread(gpointer data)
         g_idle_add(ext_mox_update ,(gpointer)1);
        // have to wait until it is really there
        // Note that if out-of-band, we would wait
-       // forever here, so allow at most 500 msec
-       i=10;
-        while (!mox && (i--) > 0) usleep(50000L);
+       // forever here, so allow at most 100 msec
+       i=100;
+        while (!mox && i-- > 0) usleep(1000L);
        // still no MOX? --> silently discard CW character and give up
        if (!mox) {
            CAT_cw_is_active=0;
@@ -2101,16 +2099,16 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                     
                                                 if(agc_resp == 0) {
                                                    active_receiver->agc = AGC_OFF;
-                                                } else if((agc_resp >0 && agc_resp <= 5) || (agc_resp == 84)) {       // DL1YCF: added () to improve readability
+                                                } else if((agc_resp >0 && agc_resp <= 5) || (agc_resp == 84)) {
                                                    active_receiver->agc = AGC_FAST;
                                                   //  fprintf(stderr,"GT command FAST\n");
-                                                } else if((agc_resp >6 && agc_resp <= 10) || (agc_resp == 2*84)) {    // DL1YCF: added () to improve readability
+                                                } else if((agc_resp >6 && agc_resp <= 10) || (agc_resp == 2*84)) {
                                                    active_receiver->agc = AGC_MEDIUM;
                                                   // fprintf(stderr,"GT command MED\n");
-                                                } else if((agc_resp >11 && agc_resp <= 15) || (agc_resp == 3*84)) {   // DL1YCF: added () to improve readability
+                                                } else if((agc_resp >11 && agc_resp <= 15) || (agc_resp == 3*84)) {
                                                    active_receiver->agc = AGC_SLOW;
                                                    //fprintf(stderr,"GT command SLOW\n");
-                                                } else if((agc_resp >16 && agc_resp <= 20) || (agc_resp == 4*84)) {   // DL1YCF: added () to improve readability
+                                                } else if((agc_resp >16 && agc_resp <= 20) || (agc_resp == 4*84)) {
                                                    active_receiver->agc = AGC_LONG;
                                                    // fprintf(stderr,"GT command LONG\n");
                                                 }
index 2445bdf06f9c70b87bc1828e3304a84fcc001732..54f7e0e1567bd84d68c74cb2e058a1edaef8f09d 100644 (file)
--- a/rx_menu.c
+++ b/rx_menu.c
@@ -247,6 +247,9 @@ void rx_menu(GtkWidget *parent) {
   // Instead, we offer these checkboxes in either case and must rely on the user
   // not playing around with features that are not there.
   //
+  // NOTE: Preamps are not present on most current HPSDR models, and ALEX attenuators
+  //       are not present e.g. in ANAN-7000.
+  //
   if (filter_board != CHARLY25) {
     switch(protocol) {
       case ORIGINAL_PROTOCOL:
index 233a5b08e4de4f8bc405a5ac4365b41bf6cf5003..e656379f7ccf879dd9130f36985eb4bb41e29ecd 100644 (file)
@@ -52,9 +52,6 @@ static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_d
 static gboolean step_select_cb (GtkWidget *widget, gpointer        data) {
   step=steps[(uintptr_t)data];
   vfo_update();
-  // DL1YCF added return statement to make the compiler happy.
-  // however I am unsure about the correct return value.
-  // I would have coded this as a void function.
   return FALSE;
 }
 
index 7c14767177cae468ed5ea077d9adfac35036b97c..465ec9f89e60f6f2b23c902569c9d7ff66dcb071 100644 (file)
@@ -317,10 +317,61 @@ static gboolean update_display(gpointer data) {
     // if "MON" button is active (tx->feedback is TRUE),
     // then obtain spectrum pixels from PS_RX_FEEDBACK,
     // that is, display the (attenuated) TX signal from the "antenna"
+    //
+    // POSSIBLE MISMATCH OF SAMPLE RATES:
+    // 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.
+    //
     if(tx->puresignal && tx->feedback) {
       RECEIVER *rx_feedback=receiver[PS_RX_FEEDBACK];
       GetPixels(rx_feedback->id,0,rx_feedback->pixel_samples,&rc);
-      memcpy(tx->pixel_samples,rx_feedback->pixel_samples,sizeof(float)*tx->pixels);
+      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);
+      }
     } else {
 #endif
       GetPixels(tx->id,0,tx->pixel_samples,&rc);
@@ -890,12 +941,11 @@ void add_mic_sample(TRANSMITTER *tx,short mic_sample) {
   int i,s;
 
 //
-// silence TX audio if not transmitting, if tuning, or
-// when doing CW. Note: CW side tone added later on by a
-// separate mechanism.
+// silence TX audio if tuning, or when doing CW.
+// (in order not to fire VOX)
 //
 
-  if (tune || !isTransmitting() || mode==modeCWL || mode==modeCWU) {
+  if (tune || mode==modeCWL || mode==modeCWU) {
     mic_sample_double=0.0;
   } else {
     mic_sample_double=(double)mic_sample/32768.0;
diff --git a/vfo.c b/vfo.c
index 7d041a7bba3bd001d21ad6447d5faf1522fb9ff2..20ead0caf4c3fb32768092c1263e8a32749ac9ea 100644 (file)
--- a/vfo.c
+++ b/vfo.c
@@ -601,9 +601,6 @@ vfo_scroll_event_cb (GtkWidget      *widget,
   } else {
     vfo_move(-step);
   }
-  // DL1YCF added return statement to make the compiler happy.
-  // however I am unsure about the correct return value.
-  // I would have coded this as a void function.
   return FALSE;
 }
 
index 0b50e6e7e5301983b58ea50f1368850bb1b14a26..1d7778159583dfc81ead0c9000b457a44b1947c8 100644 (file)
@@ -161,9 +161,6 @@ static gboolean freqent_select_cb (GtkWidget *widget, gpointer data) {
     }
   }
   vfo_update();
-  // DL1YCF added return statement to make the compiler happy.
-  // however I am unsure about the correct return value.
-  // I would have coded this as a void function.
   return FALSE;
 }
 
diff --git a/vox.c b/vox.c
index 5b9cbb2292c623f2b743b00ae89109a3d33ff553..1f9dc8084fe22b2a689918fa14a7da6de9019619 100644 (file)
--- a/vox.c
+++ b/vox.c
 #include "vfo.h"
 #include "ext.h"
 
-static guint vox_timeout;
+static guint vox_timeout=0;
 
 static double peak=0.0;
 
 static int vox_timeout_cb(gpointer data) {
-  //setVox(0);
+  //
+  // First set vox_timeout to zero indicating no "hanging" timeout
+  // then, remove VOX and update display
+  //
+  vox_timeout=0;
   g_idle_add(ext_vox_changed,(gpointer)0);
   g_idle_add(ext_vfo_update,NULL);
   return FALSE;
@@ -45,7 +49,6 @@ double vox_get_peak() {
 void update_vox(TRANSMITTER *tx) {
   // calculate peak microphone input
   // assumes it is interleaved left and right channel with length samples
-  int previous_vox=vox;
   int i;
   double sample;
   peak=0.0;
@@ -60,25 +63,32 @@ void update_vox(TRANSMITTER *tx) {
   }
 
   if(vox_enabled) {
-    if(peak>vox_threshold) {
-      if(previous_vox) {
+    if(peak > vox_threshold) {
+      // we use the value of vox_timeout to determine whether
+      // the time-out is "hanging". We cannot use the value of vox
+      // since this may be set with a delay, and we MUST NOT miss
+      // a "hanging" timeout. Note that if a time-out fires, vox_timeout
+      // is set to zero.
+      if(vox_timeout) {
         g_source_remove(vox_timeout);
       } else {
+       //
+       // no hanging time-out, assume that we just fired VOX
         g_idle_add(ext_vox_changed,(gpointer)1);
+        g_idle_add(ext_vfo_update,NULL);
       }
+      // re-init "vox hang" time
       vox_timeout=g_timeout_add((int)vox_hang,vox_timeout_cb,NULL);
     }
-    if(vox!=previous_vox) {
-      g_idle_add(ext_vfo_update,NULL);
-    }
+    // if peak is not above threshold, do nothing (this shall be done later in the timeout event
   }
 }
 
+//
+// If no vox time-out is hanging, this function is a no-op
+//
 void vox_cancel() {
-  if(vox) {
+  if(vox_timeout) {
     g_source_remove(vox_timeout);
-    //setVox(0);
-    g_idle_add(ext_vox_changed,(gpointer)0);
-    g_idle_add(ext_vfo_update,NULL);
   }
 }
index bccebcc4e0846d79587c1987bc8ef766747162d0..740273635493925ff93bc8d17710abc0a2205911 100644 (file)
@@ -63,7 +63,6 @@ waterfall_configure_event_cb (GtkWidget         *widget,
   display_height=gtk_widget_get_allocated_height (widget);
   rx->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, display_width, display_height);
 
-  // DL1YCF changed to uchar
   unsigned char *pixels = gdk_pixbuf_get_pixels (rx->pixbuf);
 
   memset(pixels, 0, display_width*display_height*3);
@@ -123,7 +122,6 @@ void waterfall_update(RECEIVER *rx) {
 
   float *samples;
   if(rx->pixbuf) {
-    // DL1YCF changed to uchar
     unsigned char *pixels = gdk_pixbuf_get_pixels (rx->pixbuf);
 
     int width=gdk_pixbuf_get_width(rx->pixbuf);
@@ -171,7 +169,6 @@ void waterfall_update(RECEIVER *rx) {
 
     float sample;
     int average=0;
-    // DL1YCF changed to uchar
     unsigned char *p;
     p=pixels;
     samples=rx->pixel_samples;