]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
Made gradient panadapter an option in Display Menu. Change Red band to start at S9...
authorJohn Melton G0ORX <john.d.melton@googlemail.com>
Sun, 16 Aug 2020 08:58:38 +0000 (09:58 +0100)
committerJohn Melton G0ORX <john.d.melton@googlemail.com>
Sun, 16 Aug 2020 08:58:38 +0000 (09:58 +0100)
discovery.c
display_menu.c
old_protocol.c
ozyio.c
radio.c
radio.h
radio_menu.c
rx_panadapter.c
zoompan.c

index c9261a7f99195c9bb7237094459b5ff5847fa548..234086e8317a74cd2a26b50b9ffd43827360db19 100644 (file)
@@ -525,6 +525,7 @@ fprintf(stderr,"%p Protocol=%d name=%s\n",d,d->protocol,d->name);
     }
 
 
+
 #ifdef CLIENT_SERVER
 
     loadProperties("remote.props");
@@ -611,7 +612,7 @@ fprintf(stderr,"%p Protocol=%d name=%s\n",d,d->protocol,d->name);
     gtk_widget_show_all(discovery_dialog);
 fprintf(stderr,"showing device dialog\n");
 
-    // autostart if enabled and only one device
+    // autostart if one device and autostart enabled
     g_print("%s: devices=%d autostart=%d\n",__FUNCTION__,devices,autostart);
 
     if(devices==1 && autostart) {
@@ -620,7 +621,6 @@ fprintf(stderr,"showing device dialog\n");
           if(start_cb(NULL,NULL,(gpointer)d)) return;
        }
     }
-
 }
 
 
index a47b683dee1675a063ac65ff80a5ab9119ef8067..7dbf1e3b5d0b681fa4c5315e1f52b74b067cdc04 100644 (file)
@@ -77,6 +77,10 @@ static void filled_cb(GtkWidget *widget, gpointer data) {
   display_filled=display_filled==1?0:1;
 }
 
+static void gradient_cb(GtkWidget *widget, gpointer data) {
+  display_gradient=display_gradient==1?0:1;
+}
+
 static void frames_per_second_value_changed_cb(GtkWidget *widget, gpointer data) {
   updates_per_second=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
   active_receiver->fps=updates_per_second;
@@ -179,6 +183,15 @@ void display_menu(GtkWidget *parent) {
   gtk_grid_attach(GTK_GRID(grid),filled_b,col,row,1,1);
   g_signal_connect(filled_b,"toggled",G_CALLBACK(filled_cb),NULL);
 
+  col++;
+
+  GtkWidget *gradient_b=gtk_check_button_new_with_label("Gradient");
+  //gtk_widget_override_font(filled_b, pango_font_description_from_string("Arial 18"));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gradient_b), display_gradient);
+  gtk_widget_show(gradient_b);
+  gtk_grid_attach(GTK_GRID(grid),gradient_b,col,row,1,1);
+  g_signal_connect(gradient_b,"toggled",G_CALLBACK(gradient_cb),NULL);
+
   row++;
   col=0;
 
index ce59c047d607edea8e168bed32c8df56bc905f4f..595a4c527397606c8ecaf06ecc95edcf7a57184b 100644 (file)
 #define LT2208_RANDOM_OFF         0x00
 #define LT2208_RANDOM_ON          0x10
 
+// state machine buffer processing
+enum {
+  SYNC_0=0,
+  SYNC_1,
+  SYNC_2,
+  CONTROL_0,
+  CONTROL_1,
+  CONTROL_2,
+  CONTROL_3,
+  CONTROL_4,
+  LEFT_SAMPLE_HI,
+  LEFT_SAMPLE_MID,
+  LEFT_SAMPLE_LOW,
+  RIGHT_SAMPLE_HI,
+  RIGHT_SAMPLE_MID,
+  RIGHT_SAMPLE_LOW,
+  MIC_SAMPLE_HI,
+  MIC_SAMPLE_LOW,
+  SKIP
+};
+static int state=SYNC_0;
+
 //#define DEBUG_PROTO 1
 
 #ifdef DEBUG_PROTO
@@ -176,27 +198,6 @@ static int output_buffer_index=8;
 
 static int command=1;
 
-enum {
-  SYNC_0=0,
-  SYNC_1,
-  SYNC_2,
-  CONTROL_0,
-  CONTROL_1,
-  CONTROL_2,
-  CONTROL_3,
-  CONTROL_4,
-  LEFT_SAMPLE_HI,
-  LEFT_SAMPLE_MID,
-  LEFT_SAMPLE_LOW,
-  RIGHT_SAMPLE_HI,
-  RIGHT_SAMPLE_MID,
-  RIGHT_SAMPLE_LOW,
-  MIC_SAMPLE_HI,
-  MIC_SAMPLE_LOW,
-  SKIP
-};
-static int state=SYNC_0;
-
 static GThread *receive_thread_id;
 static gpointer receive_thread(gpointer arg);
 static void process_ozy_input_buffer(unsigned char  *buffer);
@@ -237,14 +238,52 @@ static void ozyusb_write(unsigned char* buffer,int length);
 static unsigned char usb_output_buffer[EP6_BUFFER_SIZE];
 static unsigned char ep6_inbuffer[EP6_BUFFER_SIZE];
 static unsigned char usb_buffer_block = 0;
+#define USB_TIMEOUT -7
 #endif
 
+static GMutex dump_mutex;
+
+void dump_buffer(unsigned char *buffer,int length,const char *who) {
+  g_mutex_lock(&dump_mutex);
+  g_print("%s: %s: %d\n",__FUNCTION__,who,length);
+  int i=0;
+  int line=0;
+  while(i<length) {
+    g_print("%02X",buffer[i]);
+    i++;
+    line++;
+    if(line==16) {
+      g_print("\n");
+      line=0;
+    }
+  }
+  if(line!=0) {
+    g_print("\n");
+  }
+  g_print("\n");
+  g_mutex_unlock(&dump_mutex);
+}
+
 void old_protocol_stop() {
-  metis_start_stop(0);
+#ifdef USBOZY
+  if(device!=DEVICE_OZY) {
+#endif
+    g_print("%s\n",__FUNCTION__);
+    metis_start_stop(0);
+#ifdef USBOZY
+  }
+#endif
 }
 
 void old_protocol_run() {
-  metis_restart();
+#ifdef USBOZY
+  if(device!=DEVICE_OZY) {
+#endif
+    g_print("%s\n",__FUNCTION__);
+    metis_restart();
+#ifdef USBOZY
+  }
+#endif
 }
 
 void old_protocol_set_mic_sample_rate(int rate) {
@@ -291,16 +330,15 @@ void old_protocol_init(int rx,int pixels,int rate) {
       exit( -1 );
     }
     g_print( "receive_thread: id=%p\n",receive_thread_id);
-  }
 
+    g_print("old_protocol_init: prime radio\n");
+    for(i=8;i<OZY_BUFFER_SIZE;i++) {
+      output_buffer[i]=0;
+    }
 
-  g_print("old_protocol_init: prime radio\n");
-  for(i=8;i<OZY_BUFFER_SIZE;i++) {
-    output_buffer[i]=0;
+    metis_restart();
   }
 
-  metis_restart();
-
 }
 
 #ifdef USBOZY
@@ -344,6 +382,9 @@ static gpointer ozy_ep6_rx_thread(gpointer arg) {
   {
     bytes = ozy_read(EP6_IN_ID,ep6_inbuffer,EP6_BUFFER_SIZE); // read a 2K buffer at a time
 
+    //g_print("%s: read %d bytes\n",__FUNCTION__,bytes);
+    //dump_buffer(ep6_inbuffer,bytes,__FUNCTION__);
+
     if (bytes == 0)
     {
       g_print("old_protocol_ep6_read: ozy_read returned 0 bytes... retrying\n");
@@ -422,7 +463,7 @@ g_print("binding UDP socket to %s:%d\n",inet_ntoa(radio->info.network.interface_
     memcpy(&data_addr,&radio->info.network.address,radio->info.network.address_length);
     data_addr.sin_port=htons(DATA_PORT);
     data_socket=tmp;
-    g_print("UDP socket established: %d\n", data_socket);
+    g_print("%s: UDP socket established: %d for %s:%d\n",__FUNCTION__,data_socket,inet_ntoa(data_addr.sin_addr),ntohs(data_addr.sin_port));
 }
 
 static void open_tcp_socket() {
@@ -477,6 +518,8 @@ static gpointer receive_thread(gpointer arg) {
   g_print( "old_protocol: receive_thread\n");
   running=1;
 
+  //metis_restart();
+
   length=sizeof(addr);
   while(running) {
 
@@ -508,6 +551,7 @@ static gpointer receive_thread(gpointer arg) {
          } else if (data_socket >= 0) {
             bytes_read=recvfrom(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&addr,&length);
             if(bytes_read < 0 && errno != EAGAIN) perror("old_protocol recvfrom UDP:");
+           //g_print("%s: bytes_read=%d\n",__FUNCTION__,bytes_read);
           } else {
            // This could happen in METIS start/stop sequences
            usleep(100000);
@@ -770,6 +814,7 @@ static int how_many_receivers() {
     return ret;
 }
 
+/*
 static void process_ozy_input_buffer(unsigned char  *buffer) {
   int i;
   int r;
@@ -994,6 +1039,288 @@ static void process_ozy_input_buffer(unsigned char  *buffer) {
     metis_restart();
   }
 }
+*/
+
+static int nreceiver;
+static int left_sample;
+static int right_sample;
+static short mic_sample;
+static double left_sample_double;
+static double right_sample_double;
+double left_sample_double_rx;
+double right_sample_double_rx;
+double left_sample_double_tx;
+double right_sample_double_tx;
+double left_sample_double_main;
+double right_sample_double_main;
+double left_sample_double_aux;
+double right_sample_double_aux;
+
+static int nsamples;
+static int iq_samples;
+
+static void process_control_bytes() {
+  int previous_ptt;
+  int previous_dot;
+  int previous_dash;
+
+  // do not set ptt. In PURESIGNAL, this would stop the
+  // receiver sending samples to WDSP abruptly.
+  // Do the RX-TX change only via ext_mox_update.
+  previous_ptt=local_ptt;
+  previous_dot=dot;
+  previous_dash=dash;
+  local_ptt=(control_in[0]&0x01)==0x01;
+  dash=(control_in[0]&0x02)==0x02;
+  dot=(control_in[0]&0x04)==0x04;
+
+  if (cw_keyer_internal) {
+    // Stops CAT cw transmission if paddle hit in "internal" CW
+    if ((dash || dot) && cw_keyer_internal) cw_key_hit=1;
+  } else {
+#ifdef LOCALCW
+    //
+    // report "key hit" event to the local keyer
+    // (local keyer will stop CAT cw if necessary)
+    if (dash != previous_dash) keyer_event(0, dash);
+    if (dot  != previous_dot ) keyer_event(1, dot );
+#endif
+  }
+
+  if(previous_ptt!=local_ptt) {
+    g_idle_add(ext_mox_update,(gpointer)(long)(local_ptt));
+  }
+
+  switch((control_in[0]>>3)&0x1F) {
+    case 0:
+      adc_overload=control_in[1]&0x01;
+      if (device != DEVICE_HERMES_LITE2) {
+        //
+        // HL2 uses these bits of the protocol for a different purpose:
+        // C1 unused except the ADC overload bit
+        // C2/C3 contains underflow/overflow and TX FIFO count
+        //
+        IO1=(control_in[1]&0x02)?0:1;
+        IO2=(control_in[1]&0x04)?0:1;
+        IO3=(control_in[1]&0x08)?0:1;
+        if(mercury_software_version!=control_in[2]) {
+          mercury_software_version=control_in[2];
+          g_print("  Mercury Software version: %d (0x%0X)\n",mercury_software_version,mercury_software_version);
+        }
+        if(penelope_software_version!=control_in[3]) {
+          penelope_software_version=control_in[3];
+          g_print("  Penelope Software version: %d (0x%0X)\n",penelope_software_version,penelope_software_version);
+        }
+      }
+      if(ozy_software_version!=control_in[4]) {
+        ozy_software_version=control_in[4];
+        g_print("FPGA firmware version: %d.%d\n",ozy_software_version/10,ozy_software_version%10);
+      }
+      break;
+    case 1:
+      if (device != DEVICE_HERMES_LITE2) {
+        //
+        // HL2 uses C1/C2 for measuring the temperature
+        //
+        exciter_power=((control_in[1]&0xFF)<<8)|(control_in[2]&0xFF); // from Penelope or Hermes
+        temperature=0;
+      } else {
+        exciter_power=0;
+        temperature+=((control_in[1]&0xFF)<<8)|(control_in[2]&0xFF); // HL2
+        n_temperature++;
+        if(n_temperature==10) {
+          average_temperature=temperature/10;
+          temperature=0;
+          n_temperature=0;
+        }
+      }
+      alex_forward_power=((control_in[3]&0xFF)<<8)|(control_in[4]&0xFF); // from Alex or Apollo
+      break;
+    case 2:
+      alex_reverse_power=((control_in[1]&0xFF)<<8)|(control_in[2]&0xFF); // from Alex or Apollo
+      if (device != DEVICE_HERMES_LITE2) {
+        AIN3=((control_in[3]&0xFF)<<8)|(control_in[4]&0xFF); // For Penelope or Hermes
+        current=0;
+      } else {
+        AIN3=0;
+        current+=((control_in[3]&0xFF)<<8)|(control_in[4]&0xFF); // HL2
+        n_current++;
+        if(n_current==10) {
+          average_current=current/10;
+          current=0;
+          n_current=0;
+        }
+      }
+      break;
+    case 3:
+      AIN4=((control_in[1]&0xFF)<<8)|(control_in[2]&0xFF); // For Penelope or Hermes
+      AIN6=((control_in[3]&0xFF)<<8)|(control_in[4]&0xFF); // For Penelope or Hermes
+      break;
+  }
+
+}
+
+static int num_hpsdr_receivers;
+static int rxfdbk;
+static int txfdbk;
+static int rx1channel;
+static int rx2channel;
+
+static void process_ozy_byte(int b) {
+  int i,j;
+  switch(state) {
+    case SYNC_0:
+      if(b==SYNC) {
+        state++;
+      }
+      break;
+    case SYNC_1:
+      if(b==SYNC) {
+        state++;
+      }
+      break;
+    case SYNC_2:
+      if(b==SYNC) {
+        state++;
+      }
+      break;
+    case CONTROL_0:
+      control_in[0]=b;
+      state++;
+      break;
+    case CONTROL_1:
+      control_in[1]=b;
+      state++;
+      break;
+    case CONTROL_2:
+      control_in[2]=b;
+      state++;
+      break;
+    case CONTROL_3:
+      control_in[3]=b;
+      state++;
+      break;
+    case CONTROL_4:
+      control_in[4]=b;
+      process_control_bytes();
+      nreceiver=0;
+      iq_samples=(512-8)/((num_hpsdr_receivers*6)+2);
+      nsamples=0;
+      state++;
+      break;
+    case LEFT_SAMPLE_HI:
+      left_sample=(int)((signed char)b<<16);
+      state++;
+      break;
+    case LEFT_SAMPLE_MID:
+      left_sample|=(int)((((unsigned char)b)<<8)&0xFF00);
+      state++;
+      break;
+    case LEFT_SAMPLE_LOW:
+      left_sample|=(int)((unsigned char)b&0xFF);
+      left_sample_double=(double)left_sample/8388607.0; // 24 bit sample 2^23-1
+      state++;
+      break;
+    case RIGHT_SAMPLE_HI:
+      right_sample=(int)((signed char)b<<16);
+      state++;
+      break;
+    case RIGHT_SAMPLE_MID:
+      right_sample|=(int)((((unsigned char)b)<<8)&0xFF00);
+      state++;
+      break;
+    case RIGHT_SAMPLE_LOW:
+      right_sample|=(int)((unsigned char)b&0xFF);
+      right_sample_double=(double)right_sample/8388607.0; // 24 bit sample 2^23-1
+
+      if (isTransmitting() && transmitter->puresignal) {
+        //
+        // transmitting with PURESIGNAL. Get sample pairs and feed to pscc
+        //
+        if (nreceiver == rxfdbk) {
+          left_sample_double_rx=left_sample_double;
+          right_sample_double_rx=right_sample_double;
+        } else if (nreceiver == txfdbk) {
+          left_sample_double_tx=left_sample_double;
+          right_sample_double_tx=right_sample_double;
+        }
+        // this is pure paranoia, it allows for txfdbk < rxfdbk
+        if (nreceiver+1 == num_hpsdr_receivers) {
+          add_ps_iq_samples(transmitter, left_sample_double_tx,right_sample_double_tx,left_sample_double_rx,right_sample_double_rx);
+        }
+      }
+
+      if (!isTransmitting() && diversity_enabled) {
+        //
+        // receiving with DIVERSITY. Get sample pairs and feed to diversity mixer
+        //
+        if (nreceiver == rx1channel) {
+          left_sample_double_main=left_sample_double;
+          right_sample_double_main=right_sample_double;
+        } else if (nreceiver == rx2channel) {
+          left_sample_double_aux=left_sample_double;
+          right_sample_double_aux=right_sample_double;
+        }
+        // this is pure paranoia, it allows for rx2channel < rx1channel
+        if (nreceiver+1 == num_hpsdr_receivers) {
+          add_div_iq_samples(receiver[0], left_sample_double_main,right_sample_double_main,left_sample_double_aux,right_sample_double_aux);
+          // if we have a second receiver, display "auxiliary" receiver as well
+          if (receivers >1) add_iq_samples(receiver[1], left_sample_double_aux,right_sample_double_aux);
+        }
+      }
+
+      if ((!isTransmitting() || duplex) && !diversity_enabled) {
+        //
+        // RX without DIVERSITY. Feed samples to RX1 and RX2
+        //
+        if (nreceiver == rx1channel) {
+           add_iq_samples(receiver[0], left_sample_double,right_sample_double);
+        } else if (nreceiver == rx2channel && receivers > 1) {
+           add_iq_samples(receiver[1], left_sample_double,right_sample_double);
+        }
+      }
+      nreceiver++;
+      if(nreceiver==num_hpsdr_receivers) {
+        state++;
+      } else {
+        state=LEFT_SAMPLE_HI;
+      }
+      break;
+    case MIC_SAMPLE_HI:
+      mic_sample=(short)(b<<8);
+      state++;
+      break;
+    case MIC_SAMPLE_LOW:
+      mic_sample|=(short)(b&0xFF);
+      if(!transmitter->local_microphone) {
+        mic_samples++;
+        if(mic_samples>=mic_sample_divisor) { // reduce to 48000
+          add_mic_sample(transmitter,(float)mic_sample/32768.0);
+          mic_samples=0;
+        }
+      }
+      nsamples++;
+      if(nsamples==iq_samples) {
+        state=SYNC_0;
+      } else {
+        nreceiver=0;
+        state=LEFT_SAMPLE_HI;
+      }
+      break;
+  }
+}
+
+static void process_ozy_input_buffer(unsigned char  *buffer) {
+  int i;
+  num_hpsdr_receivers=how_many_receivers();
+  rxfdbk = rx_feedback_channel();
+  txfdbk = tx_feedback_channel();
+  rx1channel = first_receiver_channel();
+  rx2channel = second_receiver_channel();
+  for(i=0;i<512;i++) {
+    process_ozy_byte(buffer[i]&0xFF);
+  }
+}
 
 void old_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right_audio_sample) {
   if(!isTransmitting()) {
@@ -1060,6 +1387,7 @@ static void process_bandscope_buffer(char  *buffer) {
 
 void ozy_send_buffer() {
 
+
   int txmode=get_tx_mode();
   int txvfo=get_tx_vfo();
   int i;
@@ -1075,6 +1403,7 @@ void ozy_send_buffer() {
   if(metis_offset==8) {
     //
     // Every second packet is a "C0=0" packet
+    // Unless USB device
     //
     output_buffer[C0]=0x00;
     output_buffer[C1]=0x00;
@@ -1101,13 +1430,28 @@ void ozy_send_buffer() {
     if (device == DEVICE_METIS)
 #endif
     {
-      if (atlas_mic_source)
+      // atlas_mic_source is FALSE when using Janus
+      
+      if (atlas_mic_source) {
         output_buffer[C1] |= PENELOPE_MIC;
-      output_buffer[C1] |= CONFIG_BOTH;
+        output_buffer[C1] |= CONFIG_BOTH;
+      }
+
       if (atlas_clock_source_128mhz)
         output_buffer[C1] |= MERCURY_122_88MHZ_SOURCE;
       output_buffer[C1] |= ((atlas_clock_source_10mhz & 3) << 2);
+   }
+
+#ifdef USBOZY
+    // check for Janus
+    if (device == DEVICE_OZY && !atlas_mic_source) {
+      output_buffer[C2]=0x00;
+      output_buffer[C3]=0x00;
+      output_buffer[C4]=0x00;
+      ozyusb_write(output_buffer,OZY_BUFFER_SIZE);
+      return;
     }
+#endif
 
     output_buffer[C2]=0x00;
     if(classE) {
@@ -1606,6 +1950,16 @@ static int last_power=0;
 static void ozyusb_write(unsigned char* buffer,int length)
 {
   int i;
+  i = ozy_write(EP2_OUT_ID,buffer,length);
+  if(i!=length) {
+    if(i==USB_TIMEOUT) {
+      g_print("%s: ozy_write timeout for %d bytes\n",__FUNCTION__,length);
+    } else {
+      g_print("%s: ozy_write for %d bytes returned %d\n",__FUNCTION__,length,i);
+    }
+  }
+
+/*
 
 // batch up 4 USB frames (2048 bytes) then do a USB write
   switch(usb_buffer_block++)
@@ -1625,15 +1979,31 @@ static void ozyusb_write(unsigned char* buffer,int length)
 
     case 3:
       memcpy(usb_output_buffer + 1024 + 512, buffer, length);
-      usb_buffer_block = 0;           // reset counter
 // and write the 4 usb frames to the usb in one 2k packet
       i = ozy_write(EP2_OUT_ID,usb_output_buffer,EP6_BUFFER_SIZE);
+
+      //dump_buffer(usb_output_buffer,EP6_BUFFER_SIZE,__FUNCTION__);
+
+      //g_print("%s: written %d\n",__FUNCTION__,i);
+      //dump_buffer(usb_output_buffer,EP6_BUFFER_SIZE);
+
       if(i != EP6_BUFFER_SIZE)
       {
-        perror("old_protocol: OzyWrite ozy failed");
+       if(i==USB_TIMEOUT) {
+         while(i==USB_TIMEOUT) {
+            g_print("%s: USB_TIMEOUT: ozy_write ...\n",__FUNCTION__);
+            i = ozy_write(EP2_OUT_ID,usb_output_buffer,EP6_BUFFER_SIZE);
+         }
+         g_print("%s: ozy_write TIMEOUT\n",__FUNCTION__);
+        } else {
+          perror("old_protocol: OzyWrite ozy failed");
+       }
       }
+
+      usb_buffer_block = 0;           // reset counter
       break;
   }
+*/
 }
 #endif
 
@@ -1716,7 +2086,13 @@ static void metis_restart() {
   usleep(250000);
 
   // start the data flowing
-  metis_start_stop(1);
+#ifdef USBOZY
+  if(device!=DEVICE_OZY) {
+#endif
+    metis_start_stop(1);
+#ifdef USBOZY
+  }
+#endif
 }
 
 static void metis_start_stop(int command) {
@@ -1776,11 +2152,14 @@ static void metis_start_stop(int command) {
 }
 
 static void metis_send_buffer(unsigned char* buffer,int length) {
+  int bytes_sent;
   //
   // Send using either the UDP or TCP socket. Do not use TCP for
   // packets that are not 1032 bytes long
   //
 
+  //g_print("%s: length=%d\n",__FUNCTION__,length);
+
   if (tcp_socket >= 0) {
     if (length != 1032) {
        g_print("PROGRAMMING ERROR: TCP LENGTH != 1032\n");
@@ -1790,8 +2169,11 @@ static void metis_send_buffer(unsigned char* buffer,int length) {
       perror("sendto socket failed for TCP metis_send_data\n");
     }
   } else if (data_socket >= 0) {
-    if(sendto(data_socket,buffer,length,0,(struct sockaddr*)&data_addr,sizeof(data_addr))!=length) {
-      perror("sendto socket failed for UDP metis_send_data\n");
+//g_print("%s: sendto %d for %s:%d length=%d\n",__FUNCTION__,data_socket,inet_ntoa(data_addr.sin_addr),ntohs(data_addr.sin_port),length);
+    bytes_sent=sendto(data_socket,buffer,length,0,(struct sockaddr*)&data_addr,sizeof(data_addr));
+    if(bytes_sent!=length) {
+      g_print("%s: UDP sendto failed: %d: %s\n",__FUNCTION__,errno,strerror(errno));
+      //perror("sendto socket failed for UDP metis_send_data\n");
     }
   } else {
     // This should not happen
diff --git a/ozyio.c b/ozyio.c
index b4b99582ad811e0b480ce214d2fff6dce9aaa5ed..6b481293217bded7bd9ac91b0181b5ca1cbb658b 100644 (file)
--- a/ozyio.c
+++ b/ozyio.c
@@ -30,6 +30,7 @@
 * modified further Laurence Barker G8NJJ to add USB functionality to pihpsdr
 */
 
+#include <gtk/gtk.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>    // tolower
@@ -65,8 +66,9 @@
 
 #define OZY_BUFFER_SIZE 512
 
+#define OZY_IO_TIMEOUT 10
 //#define OZY_IO_TIMEOUT 500
-#define OZY_IO_TIMEOUT 2000
+//#define OZY_IO_TIMEOUT 2000
 #define MAX_EPO_PACKET_SIZE 64
 
 static int init=0;
@@ -156,11 +158,15 @@ int ozy_write(int ep,unsigned char* buffer,int buffer_size) {
        int rc;
        int bytes;
 
+       bytes=0;
        rc = libusb_bulk_transfer(ozy_handle,(unsigned char)ep,buffer,buffer_size,&bytes,OZY_IO_TIMEOUT);
        if(rc==0) {
                rc=bytes;
+       } else if(rc==-7) {
+         g_print("%s: timeout bytes=%d ep=%d\n",__FUNCTION__,bytes,ep);
+         libusb_clear_halt(ozy_handle,(unsigned char)ep);
        }
-
+        rc=buffer_size;
        return rc;
 }
 
@@ -649,7 +655,7 @@ int ozy_initialise()
        ozy_get_firmware_string(ozy_firmware_version,8);
        fprintf(stderr,"Ozy FX2 version: %s\n",ozy_firmware_version);
                
-       ozy_i2c_readvars();
+       //ozy_i2c_readvars();
        ozy_close();
        sleep(1);
        ozy_open();             
diff --git a/radio.c b/radio.c
index 62bba24385dfa090816c242b6f3976862a87808a..4f2d660831032935d60e080f733acd6238148f6d 100644 (file)
--- a/radio.c
+++ b/radio.c
@@ -142,6 +142,7 @@ int atlas_clock_source_10mhz=0;
 int atlas_clock_source_128mhz=0;
 int atlas_config=0;
 int atlas_mic_source=0;
+int atlas_janus=0;
 
 int classE=0;
 
@@ -164,6 +165,7 @@ int panadapter_high=-40;
 int panadapter_low=-140;
 
 int display_filled=1;
+int display_gradient=0;
 int display_detector_mode=DETECTOR_MODE_AVERAGE;
 int display_average_mode=AVERAGE_MODE_LOG_RECURSIVE;
 double display_average_time=120.0;
@@ -1830,6 +1832,8 @@ g_print("radioRestoreState: %s\n",property_path);
 
   value=getProperty("display_filled");
   if(value) display_filled=atoi(value);
+  value=getProperty("display_gradient");
+  if(value) display_gradient=atoi(value);
   value=getProperty("display_zoompan");
   if(value) display_zoompan=atoi(value);
   value=getProperty("display_sliders");
@@ -2117,6 +2121,8 @@ g_print("radioSaveState: %s\n",property_path);
 
   sprintf(value,"%d",display_filled);
   setProperty("display_filled",value);
+  sprintf(value,"%d",display_gradient);
+  setProperty("display_gradient",value);
   sprintf(value,"%d",display_zoompan);
   setProperty("display_zoompan",value);
   sprintf(value,"%d",display_sliders);
diff --git a/radio.h b/radio.h
index e0b834f5d36b79bd1048313767da1603fc7717f8..7e3d4c01ae98fc2af1ebe5188cf3ce980b4bf674 100644 (file)
--- a/radio.h
+++ b/radio.h
@@ -125,6 +125,7 @@ extern int atlas_clock_source_10mhz;
 extern int atlas_clock_source_128mhz;
 extern int atlas_config;
 extern int atlas_mic_source;
+extern int atlas_janus;
 
 extern int classE;
 
@@ -147,6 +148,7 @@ extern int panadapter_high;
 extern int panadapter_low;
 
 extern int display_filled;
+extern int display_gradient;
 extern int display_detector_mode;
 extern int display_average_mode;
 extern double display_average_time;
index 515579abdee36b24db33e7834bf6937c284a228a..25f07b41a01f808c1304afe4d83613e1b2786da8 100644 (file)
@@ -404,6 +404,10 @@ static void penelopetx_cb(GtkWidget *widget, gpointer data) {
   atlas_penelope=atlas_penelope==1?0:1;
 }
 
+static void janus_cb(GtkWidget *widget, gpointer data) {
+  atlas_janus=atlas_janus==1?0:1;
+}
+
 void radio_menu(GtkWidget *parent) {
   parent_window=parent;
 
@@ -742,6 +746,12 @@ void radio_menu(GtkWidget *parent) {
     g_signal_connect(pene_tx_b,"toggled",G_CALLBACK(penelopetx_cb),NULL);
     row++;
 
+    GtkWidget *janus_b=gtk_check_button_new_with_label("Janus");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (janus_b), atlas_janus);
+    gtk_grid_attach(GTK_GRID(grid),janus_b,col,row,1,1);
+    g_signal_connect(janus_b,"toggled",G_CALLBACK(janus_cb),NULL);
+    row++;
+
     if(row>temp_row) temp_row=row;
   }
 
index 56bee4952f17345e527229438d13cff13543333e..ece8eb77e22dd58128de6ddc090f7d8caf6ede4b 100644 (file)
@@ -45,6 +45,8 @@
 #include "client_server.h"
 #endif
 
+#define LINE_WIDTH 0.5
+
 //static float panadapter_max=-60.0;
 //static float panadapter_min=-160.0;
 
@@ -136,7 +138,7 @@ void rx_panadapter_update(RECEIVER *rx) {
   //clear_panadater_surface();
   cairo_t *cr;
   cr = cairo_create (rx->panadapter_surface);
-  cairo_set_line_width(cr, 1.0);
+  cairo_set_line_width(cr, LINE_WIDTH);
   cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
   cairo_rectangle(cr,0,0,display_width,display_height);
   cairo_fill(cr);
@@ -230,7 +232,7 @@ void rx_panadapter_update(RECEIVER *rx) {
   }
 
   double dbm_per_line=(double)display_height/((double)rx->panadapter_high-(double)rx->panadapter_low);
-  cairo_set_line_width(cr, 1.0);
+  cairo_set_line_width(cr, LINE_WIDTH);
   cairo_select_font_face(cr, "FreeMono", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
   cairo_set_font_size(cr, 12);
   char v[32];
@@ -384,7 +386,7 @@ void rx_panadapter_update(RECEIVER *rx) {
     // band edges
     if(band->frequencyMin!=0LL) {
       cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
-      cairo_set_line_width(cr, 1.0);
+      cairo_set_line_width(cr, LINE_WIDTH);
       if((min_display<band->frequencyMin)&&(max_display>band->frequencyMin)) {
         i=(band->frequencyMin-min_display)/(long long)HzPerPixel;
         cairo_move_to(cr,(double)i,0.0);
@@ -467,7 +469,7 @@ void rx_panadapter_update(RECEIVER *rx) {
   } else {
     cairo_set_source_rgb (cr, 0.5, 0.0, 0.0);
   }
-  cairo_set_line_width(cr, 1.0);
+  cairo_set_line_width(cr, LINE_WIDTH);
   cairo_move_to(cr,vfofreq+(offset/HzPerPixel),0.0);
   cairo_line_to(cr,vfofreq+(offset/HzPerPixel),(double)display_height);
   cairo_stroke(cr);
@@ -527,23 +529,50 @@ void rx_panadapter_update(RECEIVER *rx) {
     cairo_line_to(cr, (double)i, s2);
   }
 
-  if(display_filled) {
-    cairo_close_path (cr);
+  cairo_pattern_t *gradient;
+  if(display_gradient) {
+    gradient = cairo_pattern_create_linear(0.0, display_height, 0.0, 0.0);
+    // calculate where S9 is
+    double S9=-73;
+    if(vfo[rx->id].frequency>30000000LL) {
+      S9=-93;
+    }
+    S9 = floor((rx->panadapter_high - S9)
+                            * (double) display_height
+                            / (rx->panadapter_high - rx->panadapter_low));
+    S9 = 1.0-(S9/(double)display_height);
+  
+    if(active) {
+      cairo_pattern_add_color_stop_rgb (gradient,0.0,0.0,1.0,0.0); // Green
+      cairo_pattern_add_color_stop_rgb (gradient,S9/3.0,1.0,0.65,0.0); // Orange
+      cairo_pattern_add_color_stop_rgb (gradient,(S9/3.0)*2.0,1.0,1.0,0.0); // Yellow
+      cairo_pattern_add_color_stop_rgb (gradient,S9,1.0,0.0,0.0); // Red
+    } else {
+      cairo_pattern_add_color_stop_rgb (gradient,0.0,0.0,0.5,0.0); // Green
+      cairo_pattern_add_color_stop_rgb (gradient,S9/3.0,0.5,0.325,0.0); // Orange
+      cairo_pattern_add_color_stop_rgb (gradient,(S9/3.0)*2.0,0.5,0.5,0.0); // Yellow
+      cairo_pattern_add_color_stop_rgb (gradient,S9,0.5,0.0,0.0); // Red
+    }
+    cairo_set_source(cr, gradient);
+  } else {
     if(active) {
       cairo_set_source_rgba(cr, 1.0, 1.0, 1.0,0.5);
     } else {
       cairo_set_source_rgba(cr, 0.5, 0.5, 0.5,0.5);
     }
-    cairo_fill_preserve (cr);
   }
-  if(active) {
-    cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
-  } else {
-    cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
+
+  if(display_filled) {
+    cairo_close_path (cr);
+    cairo_fill_preserve (cr);
   }
-  cairo_set_line_width(cr, 1.0);
+  cairo_set_line_width(cr, LINE_WIDTH);
   cairo_stroke(cr);
 
+  if(display_gradient) {
+    cairo_pattern_destroy(gradient);
+  }
+
 #ifdef GPIO
   if(rx->id==0 && controller==CONTROLLER1) {
 
index 400f48059a032997eadb505587a1cda72db4a35d..c4aa3709b09f1a006061499e9eeac013e8d524f0 100644 (file)
--- a/zoompan.c
+++ b/zoompan.c
@@ -67,6 +67,7 @@ int zoompan_active_receiver_changed(void *data) {
 }
 
 static void zoom_value_changed_cb(GtkWidget *widget, gpointer data) {
+g_print("zoom_value_changed_cb\n");
   g_mutex_lock(&pan_zoom_mutex);
   g_mutex_lock(&active_receiver->display_mutex);
 #ifdef CLIENT_SERVER
@@ -95,21 +96,10 @@ static void zoom_value_changed_cb(GtkWidget *widget, gpointer data) {
 }
 
 void set_zoom(int rx,double value) {
+g_print("set_zoom: %f\n",value);
   receiver[rx]->zoom=value;
-  receiver_change_zoom(receiver[rx],value);
   if(display_zoompan) {
-    g_signal_handler_block(G_OBJECT(zoom_scale),zoom_signal_id);
     gtk_range_set_value (GTK_RANGE(zoom_scale),receiver[rx]->zoom);
-    g_signal_handler_unblock(G_OBJECT(zoom_scale),zoom_signal_id);
-    g_signal_handler_block(G_OBJECT(pan_scale),pan_signal_id);
-    gtk_range_set_range(GTK_RANGE(pan_scale),0.0,(double)(active_receiver->zoom==1?active_receiver->pixels:active_receiver->pixels-active_receiver->width));
-    gtk_range_set_value (GTK_RANGE(pan_scale),active_receiver->pan);
-    g_signal_handler_unblock(G_OBJECT(pan_scale),pan_signal_id);
-    if(active_receiver->zoom==1) {
-      gtk_widget_set_sensitive(pan_scale, FALSE);
-    } else {
-      gtk_widget_set_sensitive(pan_scale, TRUE);
-    }
   } else {
     if(scale_status!=ZOOM || scale_rx!=rx) {
       if(scale_status!=NO_FUNCTION) {
@@ -142,6 +132,7 @@ void set_zoom(int rx,double value) {
 }
 
 void remote_set_zoom(int rx,double value) {
+g_print("remote_set_zoom: rx=%d zoom=%f\n",rx,value);
   g_mutex_lock(&pan_zoom_mutex);
   g_signal_handler_block(G_OBJECT(zoom_scale),zoom_signal_id);
   g_signal_handler_block(G_OBJECT(pan_scale),pan_signal_id);
@@ -149,9 +140,11 @@ void remote_set_zoom(int rx,double value) {
   g_signal_handler_unblock(G_OBJECT(pan_scale),pan_signal_id);
   g_signal_handler_unblock(G_OBJECT(zoom_scale),zoom_signal_id);
   g_mutex_unlock(&pan_zoom_mutex);
+g_print("remote_set_zoom: EXIT\n");
 }
 
 void update_zoom(double zoom) {
+g_print("update_zoom: %f\n",zoom);
   int z=active_receiver->zoom+(int)zoom;
   if(z>MAX_ZOOM) z=MAX_ZOOM;
   if(z<1) z=1;
@@ -159,6 +152,7 @@ void update_zoom(double zoom) {
 }
 
 static void pan_value_changed_cb(GtkWidget *widget, gpointer data) {
+g_print("pan_value_changed_cb\n");
   g_mutex_lock(&pan_zoom_mutex);
 #ifdef CLIENT_SERVER
   if(radio_is_remote) {
@@ -173,11 +167,10 @@ static void pan_value_changed_cb(GtkWidget *widget, gpointer data) {
 }
 
 void set_pan(int rx,double value) {
+g_print("set_pan: %f\n",value);
   receiver[rx]->pan=(int)value;
   if(display_zoompan) {
-    g_signal_handler_block(G_OBJECT(pan_scale),pan_signal_id);
     gtk_range_set_value (GTK_RANGE(pan_scale),receiver[rx]->pan);
-    g_signal_handler_unblock(G_OBJECT(pan_scale),pan_signal_id);
   } else {
     if(scale_status!=PAN || scale_rx!=rx) {
       if(scale_status!=NO_FUNCTION) {
@@ -209,28 +202,32 @@ void set_pan(int rx,double value) {
 }
 
 void remote_set_pan(int rx,double value) {
+g_print("remote_set_pan: rx=%d pan=%f\n",rx,value);
   g_mutex_lock(&pan_zoom_mutex);
   g_signal_handler_block(G_OBJECT(pan_scale),pan_signal_id);
   gtk_range_set_range(GTK_RANGE(pan_scale),0.0,(double)(receiver[rx]->zoom==1?receiver[rx]->pixels:receiver[rx]->pixels-receiver[rx]->width));
   set_pan(rx,value);
   g_signal_handler_unblock(G_OBJECT(pan_scale),pan_signal_id);
   g_mutex_unlock(&pan_zoom_mutex);
+g_print("remote_set_pan: EXIT\n");
 }
 
 void update_pan(double pan) {
+  g_mutex_lock(&pan_zoom_mutex);
   if(active_receiver->zoom>1) {
     int p=active_receiver->pan+(int)pan;
     if(p<0) p=0;
     if(p>(active_receiver->pixels-active_receiver->width)) p=active_receiver->pixels-active_receiver->width;
     set_pan(active_receiver->id,(double)p);
   }
+  g_mutex_lock(&pan_zoom_mutex);
 }
 
 GtkWidget *zoompan_init(int my_width, int my_height) {
   width=my_width;
   height=my_height;
 
-g_print("%s: width=%d height=%d\n",__FUNCTION__,width,height);
+fprintf(stderr,"zoompan_init: width=%d height=%d\n", width,height);
 
   zoompan=gtk_grid_new();
   gtk_widget_set_size_request (zoompan, width, height);