]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
made "CW behaviour" user-selectable
authorc vw <dl1ycf@darc.de>
Thu, 22 Aug 2019 16:21:57 +0000 (18:21 +0200)
committerc vw <dl1ycf@darc.de>
Thu, 22 Aug 2019 16:21:57 +0000 (18:21 +0200)
cw_menu.c
new_protocol.c
old_protocol.c
radio.c
radio.h
rx_panadapter.c

index 4849673d704be4f42e8bd4eddd1cc9164ca737d2..4911b5caaabcf1cf72f638e7d72e12192e591b00 100644 (file)
--- a/cw_menu.c
+++ b/cw_menu.c
@@ -68,6 +68,10 @@ static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_d
   return FALSE;
 }
 
+static void cw_vfo_cb(GtkWidget *widget, gpointer data) {
+  cw_is_on_vfo_freq=(uintptr_t)data;
+}
+
 static void cw_keyer_internal_cb(GtkWidget *widget, gpointer data) {
   cw_keyer_internal=cw_keyer_internal==1?0:1;
   cw_changed();
@@ -209,6 +213,18 @@ void cw_menu(GtkWidget *parent) {
   gtk_grid_attach(GTK_GRID(grid),cw_keyer_mode_b,0,5,1,1);
   g_signal_connect(cw_keyer_mode_b,"pressed",G_CALLBACK(cw_keyer_mode_cb),(gpointer *)KEYER_MODE_B);
 
+  GtkWidget *cw_vfo=gtk_radio_button_new_with_label(NULL,"CW on VFO freq");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cw_vfo), cw_is_on_vfo_freq);
+  gtk_widget_show(cw_vfo);
+  gtk_grid_attach(GTK_GRID(grid),cw_vfo,1,3,1,1);
+  g_signal_connect(cw_vfo,"pressed",G_CALLBACK(cw_vfo_cb),(gpointer *)1);
+
+  GtkWidget *cw_vfo_pm=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(cw_vfo),"CW on VFO +/- sidetone");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cw_vfo_pm), cw_is_on_vfo_freq==0);
+  gtk_widget_show(cw_vfo_pm);
+  gtk_grid_attach(GTK_GRID(grid),cw_vfo_pm,1,4,1,1);
+  g_signal_connect(cw_vfo_pm,"pressed",G_CALLBACK(cw_vfo_cb),(gpointer *)0);
+
   GtkWidget *cw_keys_reversed_b=gtk_check_button_new_with_label("Keys reversed");
   //gtk_widget_override_font(cw_keys_reversed_b, pango_font_description_from_string("Arial 18"));
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cw_keys_reversed_b), cw_keys_reversed);
index 0d9f833f941424bd6e50640de80ade8d360b4c47..62035e53ba7dd65517c1464bd5916c6a71a23d03 100644 (file)
@@ -614,8 +614,9 @@ static void new_protocol_high_priority() {
     long long rxFrequency;
     long long txFrequency;
     long phase;
-    int mode;
+    int txmode;
     int ddc;
+    int txvfo;
 
     if(data_socket==-1) {
       return;
@@ -629,16 +630,30 @@ static void new_protocol_high_priority() {
     high_priority_buffer_to_radio[2]=high_priority_sequence>>8;
     high_priority_buffer_to_radio[3]=high_priority_sequence;
 
-    if(split) {
-      mode=vfo[1].mode;
+    //
+    // Determine VFO controlling the TX frequency
+    // and the associated mode
+    //
+    if(active_receiver->id==VFO_A) {
+      if(split) {
+        txvfo=VFO_B;
+      } else {
+       txvfo=VFO_A;
+      }
     } else {
-      mode=vfo[0].mode;
+      if(split) {
+        txvfo=VFO_A;
+      } else {
+       txvfo=VFO_B;
+      }
     }
+    txmode=vfo[txvfo].mode;
+
     high_priority_buffer_to_radio[4]=running;
 //
 //  We need not set PTT of doing internal CW with break-in
 //
-    if(mode==modeCWU || mode==modeCWL) {
+    if(txmode==modeCWU || txmode==modeCWL) {
       if (isTransmitting() && (!cw_keyer_internal || !cw_breakin || CAT_cw_is_active)) high_priority_buffer_to_radio[4]|=0x02;
     } else {
       if(isTransmitting()) {
@@ -652,7 +667,7 @@ static void new_protocol_high_priority() {
 
     if (diversity_enabled) {
        //
-       // Use frequency of RX1 for both DDC0 and DDC1
+       // Use frequency of first receiver for both DDC0 and DDC1
        // This is overridden later if we do PURESIGNAL TX
        //
         rxFrequency=vfo[0].frequency-vfo[0].lo;
@@ -660,17 +675,14 @@ static void new_protocol_high_priority() {
           rxFrequency+=vfo[0].rit;
         }
 
-        switch(vfo[0].mode) {
-          case modeCWU:
-            rxFrequency-=cw_keyer_sidetone_frequency;
-            break;
-          case modeCWL:
-            rxFrequency+=cw_keyer_sidetone_frequency;
-            break;
-          default:
-            break;
+        if (cw_is_on_vfo_freq) {
+          if(vfo[0].mode==modeCWU) {
+            rxFrequency-=(long long)cw_keyer_sidetone_frequency;
+          } else if(vfo[0].mode==modeCWL) {
+            rxFrequency+=(long long)cw_keyer_sidetone_frequency;
+          }
         }
+
         phase=(long)((4294967296.0*(double)rxFrequency)/122880000.0);
         high_priority_buffer_to_radio[ 9]=phase>>24;
         high_priority_buffer_to_radio[10]=phase>>16;
@@ -694,54 +706,35 @@ static void new_protocol_high_priority() {
           if(vfo[v].rit_enabled) {
             rxFrequency+=vfo[v].rit;
           }
+          if (cw_is_on_vfo_freq) {
+            if(vfo[v].mode==modeCWU) {
+              rxFrequency-=(long long)cw_keyer_sidetone_frequency;
+            } else if(vfo[v].mode==modeCWL) {
+              rxFrequency+=(long long)cw_keyer_sidetone_frequency;
+            }
+          }
 
-          switch(vfo[v].mode) {
-            case modeCWU:
-              rxFrequency-=cw_keyer_sidetone_frequency;
-              break;
-            case modeCWL:
-              rxFrequency+=cw_keyer_sidetone_frequency;
-              break;
-            default:
-              break;
-       }
-
-       phase=(long)((4294967296.0*(double)rxFrequency)/122880000.0);
-       high_priority_buffer_to_radio[9+(ddc*4)]=phase>>24;
-       high_priority_buffer_to_radio[10+(ddc*4)]=phase>>16;
-       high_priority_buffer_to_radio[11+(ddc*4)]=phase>>8;
-       high_priority_buffer_to_radio[12+(ddc*4)]=phase;
-      }
+         phase=(long)((4294967296.0*(double)rxFrequency)/122880000.0);
+         high_priority_buffer_to_radio[9+(ddc*4)]=phase>>24;
+         high_priority_buffer_to_radio[10+(ddc*4)]=phase>>16;
+         high_priority_buffer_to_radio[11+(ddc*4)]=phase>>8;
+         high_priority_buffer_to_radio[12+(ddc*4)]=phase;
+        }
     }
 
 //
 //  Set DUC frequency
 //
 
-    if(active_receiver->id==VFO_A) {
-      txFrequency=vfo[VFO_A].frequency-vfo[VFO_A].lo+vfo[VFO_A].offset;
-      if(split) {
-        txFrequency=vfo[VFO_B].frequency-vfo[VFO_B].lo+vfo[VFO_B].offset;
-      }
-    } else {
-      txFrequency=vfo[VFO_B].frequency-vfo[VFO_B].lo+vfo[VFO_B].offset;
-      if(split) {
-        txFrequency=vfo[VFO_A].frequency-vfo[VFO_A].lo+vfo[VFO_A].offset;
-      }
-    }
+    txFrequency=vfo[txvfo].frequency-vfo[txvfo].lo+vfo[txvfo].offset;
 
-/*
-    switch(vfo[active_receiver->id].mode) {
-        case modeCWU:
-          txFrequency+=cw_keyer_sidetone_frequency;
-          break;
-        case modeCWL:
-          txFrequency-=cw_keyer_sidetone_frequency;
-          break;
-        default:
-          break;
+    if (!cw_is_on_vfo_freq) {
+      if(txmode==modeCWU) {
+        txFrequency+=(long long)cw_keyer_sidetone_frequency;
+      } else if(txmode==modeCWL) {
+        txFrequency-=(long long)cw_keyer_sidetone_frequency;
       }
-*/
+    }
 
     phase=(long)((4294967296.0*(double)txFrequency)/122880000.0);
 
index c38f135bdf57f1d8513ae4d146def096d789384b..06f32355e84293d26094bc3ae3a5085b76572d9c 100644 (file)
@@ -709,18 +709,27 @@ static long long channel_freq(int chan) {
   if (vfonum < 0) {
     //
     // indicates that we should use the TX frequency.
+    // We have to adjust by the offset for CTUN mode
     //
     if(active_receiver->id==VFO_A) {
-      if(split) {
-       freq=vfo[VFO_B].frequency-vfo[VFO_B].lo+vfo[VFO_B].offset;
+      if(split) { 
+        vfonum=VFO_B;
       } else {
-       freq=vfo[VFO_A].frequency-vfo[VFO_A].lo+vfo[VFO_A].offset;
+        vfonum=VFO_A;
       }
     } else {
       if(split) {
-       freq=vfo[VFO_A].frequency-vfo[VFO_A].lo+vfo[VFO_A].offset;
+        vfonum=VFO_A;
       } else {
-       freq=vfo[VFO_B].frequency-vfo[VFO_B].lo+vfo[VFO_B].offset;
+        vfonum=VFO_B;
+      }
+    }
+    freq=vfo[vfonum].frequency-vfo[vfonum].lo+vfo[vfonum].offset;
+    if (!cw_is_on_vfo_freq) {
+      if(vfo[vfonum].mode==modeCWU) {
+        freq+=(long long)cw_keyer_sidetone_frequency;
+      } else if(vfo[vfonum].mode==modeCWL) {
+        freq-=(long long)cw_keyer_sidetone_frequency;
       }
     }
   } else {
@@ -731,10 +740,12 @@ static long long channel_freq(int chan) {
     if(vfo[vfonum].rit_enabled) {
       freq+=vfo[vfonum].rit;
     }
-    if(vfo[vfonum].mode==modeCWU) {
-      freq-=(long long)cw_keyer_sidetone_frequency;
-    } else if(vfo[vfonum].mode==modeCWL) {
-      freq+=(long long)cw_keyer_sidetone_frequency;
+    if (cw_is_on_vfo_freq) {
+      if(vfo[vfonum].mode==modeCWU) {
+        freq-=(long long)cw_keyer_sidetone_frequency;
+      } else if(vfo[vfonum].mode==modeCWL) {
+        freq+=(long long)cw_keyer_sidetone_frequency;
+      }
     }
   }
   return freq;
diff --git a/radio.c b/radio.c
index 6d82af4ea17d44c999dd2ae521d6dbc063083924..fd183f57b001ba29b437ccfaa21727b9fbffbe9d 100644 (file)
--- a/radio.c
+++ b/radio.c
@@ -221,6 +221,8 @@ int cw_keyer_hang_time=300; // ms
 int cw_keyer_sidetone_frequency=400; // Hz
 int cw_breakin=1; // 0=disabled 1=enabled
 
+int cw_is_on_vfo_freq=1;   // 1= signal on VFO freq, 0= signal offset by side tone
+
 int vfo_encoder_divisor=15;
 
 int protocol;
@@ -1236,6 +1238,8 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path);
 
     value=getProperty("step");
     if(value) step=atoll(value);
+    value=getProperty("cw_is_on_vfo_freq");
+    if(value) cw_is_on_vfo_freq=atoi(value);
     value=getProperty("cw_keys_reversed");
     if(value) cw_keys_reversed=atoi(value);
     value=getProperty("cw_keyer_speed");
@@ -1441,6 +1445,8 @@ void radioSaveState() {
 
     sprintf(value,"%lld",step);
     setProperty("step",value);
+    sprintf(value,"%d",cw_is_on_vfo_freq);
+    setProperty("cw_is_on_vfo_freq",value);
     sprintf(value,"%d",cw_keys_reversed);
     setProperty("cw_keys_reversed",value);
     sprintf(value,"%d",cw_keyer_speed);
diff --git a/radio.h b/radio.h
index f1898aeea3696c799169865da9030ace578aac4b..470eb8da5b6a16d468ea3b24e56e8cd1c5c89146 100644 (file)
--- a/radio.h
+++ b/radio.h
@@ -174,6 +174,7 @@ extern int cw_keyer_ptt_delay;
 extern int cw_keyer_hang_time;
 extern int cw_keyer_sidetone_frequency;
 extern int cw_breakin;
+extern int cw_is_on_vfo_freq;
 
 extern int vfo_encoder_divisor;
 
index 52a2eb816a2cb53a524e0fce53ff9f2a32742ed9..f810faa6d0fb2094f576c8774961127586fdd480 100644 (file)
@@ -142,18 +142,45 @@ void rx_panadapter_update(RECEIVER *rx) {
   cairo_fill(cr);
   //cairo_paint (cr);
 
+  double HzPerPixel = rx->hz_per_pixel;  // need this many times
+
+  int mode=vfo[rx->id].mode;
   long long frequency=vfo[rx->id].frequency;
   long half=(long)rx->sample_rate/2L;
+  BAND *band=band_get_band(vfo[rx->id].band);
+  double vfofreq=(double) display_width * 0.5;
+
+  //
+  // There are two options here in CW mode, depending on cw_is_on_vfo_freq.
+  //
+  // If true, the CW frequency is the VFO frequency and the center of the spectrum
+  // then is at the VFO frequency plus or minus the sidetone frequency. However we
+  // will keep the center of the PANADAPTER at the VFO frequency and shift the
+  // pixels of the spectrum.
+  //
+  // If false, the center of the spectrum is at the VFO frequency and the TX
+  // frequency is VFO freq +/- sidetone frequency. In this case we mark this
+  // freq by a yellow line.
+  //
+
+  if (cw_is_on_vfo_freq) {
+    if (mode == modeCWU) {
+      frequency -= cw_keyer_sidetone_frequency;
+      vfofreq += (double) cw_keyer_sidetone_frequency / HzPerPixel;
+    } else if (mode == modeCWL) {
+      frequency += cw_keyer_sidetone_frequency;
+      vfofreq -= (double) cw_keyer_sidetone_frequency / HzPerPixel;
+    }
+  }
   long long min_display=frequency-half;
   long long max_display=frequency+half;
-  BAND *band=band_get_band(vfo[rx->id].band);
 
   if(vfo[rx->id].band==band60) {
     for(i=0;i<channel_entries;i++) {
       long long low_freq=band_channels_60m[i].frequency-(band_channels_60m[i].width/(long long)2);
       long long hi_freq=band_channels_60m[i].frequency+(band_channels_60m[i].width/(long long)2);
-      x1=(low_freq-min_display)/(long long)rx->hz_per_pixel;
-      x2=(hi_freq-min_display)/(long long)rx->hz_per_pixel;
+      x1=(low_freq-min_display)/(long long)HzPerPixel;
+      x2=(hi_freq-min_display)/(long long)HzPerPixel;
       cairo_set_source_rgb (cr, 0.6, 0.3, 0.3);
       cairo_rectangle(cr, x1, 0.0, x2-x1, (double)display_height);
       cairo_fill(cr);
@@ -169,71 +196,18 @@ void rx_panadapter_update(RECEIVER *rx) {
     }
   }
 
-  double cwshift;
-  int begin,end,icwshift;
-
-  //
-  // In this program, when using CW, we will always transmit on exactly
-  // the frequency which is the "VFO display" frequency, not 800 Hz above
-  // or below. Therfore, the RX center frequency sent to the SDR is shifted
-  // by the sidetone frequency.
-  // Previous versions showed a "shifted" RX spectrum where the CW signal that
-  // was received exactly on the VFO frequency was shifted to the right (CWU)
-  // or to the left (CWL), the exact position shown by a yellow line.
-  // 
-  // Alternatively, one could arrange things such that the RX spectrum is
-  // shown correctly and that in CWU you "hear" a CW signal at 7000,0 kHz
-  // when the VFO display frequency is 7000.0 kHz. Then, the TX signal must
-  // have an offset, that is, you send a CW signal at 7000.8 kHz when the
-  // VFO display shows 7000.0 kHz, and the yellow line is at 7000.8 kHz.
-  //
-  // Instead of drawing a "yellow line" to show where the received CW
-  // signal is, we shift the displayed spectrum by the side tone such
-  // that the received signals occur at the nominal frequencies
-  // That is, in CW we TX at the VFO display frequency which is marked by
-  // a red line, and we also receive CW signals from exactly that position in
-  // the RX spectrum. Furthermore, when switching between CWU and CWL, the
-  // displayed RX spectrum remains unchanged except for the part at the right
-  // or left margin of the display.
-  //
-  // For me (DL1YCF) this seems more logical.
-  //
-  switch (vfo[rx->id].mode) {
-    case modeCWU:
-        // spectrum must be shifted to the left
-        cwshift=(double) cw_keyer_sidetone_frequency / rx->hz_per_pixel;
-        icwshift=(int) cwshift;
-        begin=0;
-        end=display_width-icwshift;
-        break;
-    case modeCWL:
-        // spectrum must shifted to the right
-        cwshift=-(double) cw_keyer_sidetone_frequency / rx->hz_per_pixel;
-        icwshift=(int) cwshift;
-        begin=-cwshift;
-        end=display_width;
-        break;
-    default:
-        cwshift=0.0;
-        icwshift=0;
-        begin=0;
-        end=display_width;
-        break;
-  }
-
-
   // filter
   cairo_set_source_rgba (cr, 0.25, 0.25, 0.25, 0.75);
-  filter_left =-cwshift+(double)display_width/2.0+(((double)rx->filter_low+vfo[rx->id].offset)/rx->hz_per_pixel);
-  filter_right=-cwshift+(double)display_width/2.0+(((double)rx->filter_high+vfo[rx->id].offset)/rx->hz_per_pixel);
+  filter_left =(double)display_width*0.5 +(((double)rx->filter_low+vfo[rx->id].offset)/HzPerPixel);
+  filter_right=(double)display_width*0.5 +(((double)rx->filter_high+vfo[rx->id].offset)/HzPerPixel);
   cairo_rectangle(cr, filter_left, 0.0, filter_right-filter_left, (double)display_height);
   cairo_fill(cr);
 
-/*
-  do not draw the "yellow line". Instead, shift the spectrum
-  such that the rx frequency offset is compensated
-
-  if(vfo[rx->id].mode==modeCWU || vfo[rx->id].mode==modeCWL) {
+  //
+  // Draw the "yellow line" indicating the CW frequency when
+  // it is not the VFO freq
+  //
+  if (!cw_is_on_vfo_freq && (vfo[rx->id].mode==modeCWU || vfo[rx->id].mode==modeCWL)) {
     if(active) {
       cairo_set_source_rgb (cr, 1.0, 1.0, 0.0);
     } else {
@@ -244,7 +218,6 @@ void rx_panadapter_update(RECEIVER *rx) {
     cairo_line_to(cr,cw_frequency,(double)display_height);
     cairo_stroke(cr);
   }
-*/
 
   // plot the levels
   if(active) {
@@ -300,9 +273,9 @@ void rx_panadapter_update(RECEIVER *rx) {
       break;
   }
   for(i=0;i<display_width;i++) {
-    f = frequency - half + (long) (rx->hz_per_pixel * i);
+    f = frequency - half + (long) (HzPerPixel * i);
     if (f > 0) {
-      if ((f % divisor) < (long) rx->hz_per_pixel) {
+      if ((f % divisor) < (long) HzPerPixel) {
         cairo_set_line_width(cr, 1.0);
         //cairo_move_to(cr,(double)i,0.0);
         cairo_move_to(cr,(double)i,10.0);
@@ -329,13 +302,13 @@ void rx_panadapter_update(RECEIVER *rx) {
       cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
       cairo_set_line_width(cr, 2.0);
       if((min_display<band->frequencyMin)&&(max_display>band->frequencyMin)) {
-        i=(band->frequencyMin-min_display)/(long long)rx->hz_per_pixel;
+        i=(band->frequencyMin-min_display)/(long long)HzPerPixel;
         cairo_move_to(cr,(double)i,0.0);
         cairo_line_to(cr,(double)i,(double)display_height);
         cairo_stroke(cr);
       }
       if((min_display<band->frequencyMax)&&(max_display>band->frequencyMax)) {
-        i=(band->frequencyMax-min_display)/(long long)rx->hz_per_pixel;
+        i=(band->frequencyMax-min_display)/(long long)HzPerPixel;
         cairo_move_to(cr,(double)i,0.0);
         cairo_line_to(cr,(double)i,(double)display_height);
         cairo_stroke(cr);
@@ -403,24 +376,24 @@ void rx_panadapter_update(RECEIVER *rx) {
     cairo_set_source_rgb (cr, 0.5, 0.0, 0.0);
   }
   cairo_set_line_width(cr, 1.0);
-  cairo_move_to(cr,(double)(display_width/2.0)+(vfo[rx->id].offset/rx->hz_per_pixel),0.0);
-  cairo_line_to(cr,(double)(display_width/2.0)+(vfo[rx->id].offset/rx->hz_per_pixel),(double)display_height);
+  cairo_move_to(cr,vfofreq+(vfo[rx->id].offset/HzPerPixel),0.0);
+  cairo_line_to(cr,vfofreq+(vfo[rx->id].offset/HzPerPixel),(double)display_height);
   cairo_stroke(cr);
 
   // signal
   double s1,s2;
 
-  samples[begin+icwshift]=-200.0;
-  samples[end-1+icwshift]=-200.0;
-  s1=(double)samples[begin+icwshift]+(double)adc_attenuation[rx->adc];
+  samples[0]=-200.0;
+  samples[display_width-1]=-200.0;
+  s1=(double)samples[0]+(double)adc_attenuation[rx->adc];
   if (filter_board == ALEX && rx->adc == 0) s1 += (double)(10*rx->alex_attenuation);
 
   s1 = floor((rx->panadapter_high - s1)
                         * (double) display_height
                         / (rx->panadapter_high - rx->panadapter_low));
-  cairo_move_to(cr, (double) begin, s1);
-  for(i=begin+1;i<end;i++) {
-    s2=(double)samples[i+icwshift]+(double)adc_attenuation[rx->adc];
+  cairo_move_to(cr, 0.0, s1);
+  for(i=1;i<display_width;i++) {
+    s2=(double)samples[i]+(double)adc_attenuation[rx->adc];
     if (filter_board == ALEX && rx->adc == 0) s2 += (double)(10*rx->alex_attenuation);
     s2 = floor((rx->panadapter_high - s2)
                             * (double) display_height