]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
a) P2 PURESIGNAL for HERMES, b) DIVERSITY, c) CW for P2, d) HPSDR Simulator:
authorc vw <dl1ycf@darc.de>
Wed, 24 Jul 2019 16:35:03 +0000 (18:35 +0200)
committerc vw <dl1ycf@darc.de>
Wed, 24 Jul 2019 16:35:03 +0000 (18:35 +0200)
now with man-made noise to test DIVERSITY

14 files changed:
Makefile
Makefile.mac
diversity_menu.c
hpsdrsim.c
new_menu.c
new_protocol.c
newhpsdrsim.c
old_protocol.c
radio.c
radio.h
receiver.c
receiver.h
transmitter.c
transmitter.h

index 652f9bb8a6cfcee65975e33ee0ff4ba0672f2468..f3a8cf4c079a4eeeb41fd264b59c25c96d0d29b0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -474,10 +474,10 @@ release: $(PROGRAM)
 #
 #############################################################################
 
-hpsdrsim.o:    hpsdrsim.c
+hpsdrsim.o:    hpsdrsim.c hpsdrsim.h
        $(CC) -c -O -DALSASOUND hpsdrsim.c
 
-newhpsdrsim.o: newhpsdrsim.c
+newhpsdrsim.o: newhpsdrsim.c hpsdrsim.h
        $(CC) -c -O newhpsdrsim.c
 
 hpsdrsim:      hpsdrsim.o newhpsdrsim.o
index efff0b6a75120a3fc24bdf050cf4d37a4390c2bd..e3fc0509c6c37c2bebcd56d6aeb23b6e6b4551f4 100644 (file)
@@ -456,10 +456,10 @@ release: $(PROGRAM)
 #
 #############################################################################
 
-hpsdrsim.o:     hpsdrsim.c 
+hpsdrsim.o:     hpsdrsim.c  hpsdrsim.h
        $(CC) -c -O -DPORTAUDIO hpsdrsim.c
         
-newhpsdrsim.o: newhpsdrsim.c
+newhpsdrsim.o: newhpsdrsim.c hpsdrsim.h
        $(CC) -c -O newhpsdrsim.c
 
 hpsdrsim:       hpsdrsim.o newhpsdrsim.o
index fc60b4788cf599a01ae687d66b433394bc9b3b3e..458143aa4f705be0d912d04c5655e4bb2324c004 100644 (file)
@@ -27,7 +27,7 @@
 #include "new_menu.h"
 #include "diversity_menu.h"
 #include "radio.h"
-#include <wdsp.h>
+#include "new_protocol.h"
 
 static GtkWidget *parent_window=NULL;
 
@@ -55,17 +55,18 @@ static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_d
 
 static void diversity_cb(GtkWidget *widget, gpointer data) {
   diversity_enabled=diversity_enabled==1?0:1;
-  SetEXTDIVRun(0,diversity_enabled);
+  if (protocol == NEW_PROTOCOL) {
+    schedule_high_priority();
+    schedule_receive_specific();
+  }
 }
 
 static void i_rotate_value_changed_cb(GtkWidget *widget, gpointer data) {
   i_rotate[1]=gtk_range_get_value(GTK_RANGE(widget));
-  SetEXTDIVRotate (0, 2, &i_rotate[0], &q_rotate[0]);
 }
 
 static void q_rotate_value_changed_cb(GtkWidget *widget, gpointer data) {
   q_rotate[1]=gtk_range_get_value(GTK_RANGE(widget));
-  SetEXTDIVRotate (0, 2, &i_rotate[0], &q_rotate[0]);
 }
 
 void diversity_menu(GtkWidget *parent) {
index f12ac22bcb47ed10151ae2f0a050a993821ae695..0f5e31a456796930b9a970e8da03e5aae4a9994a 100644 (file)
 #undef NEED_DUMMY_AUDIO
 #endif
 
-// Forward declarations for the audio functions
-void audio_get_cards(void);
-void audio_open_output();
-void audio_write(int16_t, int16_t);
+#define EXTERN 
+#include "hpsdrsim.h"
 
-
-#ifndef __APPLE__
-// using clock_nanosleep of librt
-extern int clock_nanosleep(clockid_t __clock_id, int __flags,
-      __const struct timespec *__req,
-      struct timespec *__rem);
-#endif
-
-
-static int sock_TCP_Server = -1;
-static int sock_TCP_Client = -1;
-
-//
-// Forward declarations for new protocol stuff
-//
-void   new_protocol_general_packet(unsigned char *buffer);
-int    new_protocol_running(void);
-
-#define LENNOISE 1536000
-#define NOISEDIV (RAND_MAX / 768000)
-
-double noiseItab[LENNOISE];
-double noiseQtab[LENNOISE];
-
-int diversity=0;
-
-#define LENDIV 16000
-double divtab[LENDIV];
-//
-// The tone is recorded with a sample rate of 1536 kHz. For lower TX
-// sample rates, one has to decimate it
-//
-#define LENTONE 15360
-double toneItab[LENTONE];
-double toneQtab[LENTONE];
-
-double c1,c2;  // shared. needed for power conversion
 /*
- * These variables store the state of the SDR.
+ * These variables store the state of the "old protocol" SDR.
  * Whenevery they are changed, this is reported.
  */
 
@@ -188,9 +149,9 @@ static double rxatt_dbl[4] = {1.0, 1.0, 1.0, 1.0};   // this reflects both ATT a
 /*
  * Socket for communicating with the "PC side"
  */
+static int sock_TCP_Server = -1;
+static int sock_TCP_Client = -1;
 static int sock_udp;
-struct sockaddr_in addr_new; // shared by newhpsdrsim.c
-static struct sockaddr_in addr_old;
 
 /*
  * These two variables monitor whether the TX thread is active
@@ -198,28 +159,10 @@ static struct sockaddr_in addr_old;
 static int enable_thread = 0;
 static int active_thread = 0;
 
-void process_ep2(uint8_t *frame);
-void *handler_ep6(void *arg);
+static void process_ep2(uint8_t *frame);
+static void *handler_ep6(void *arg);
 
 
-/*
- * The TX data ring buffer
- */
-
-// RTXLEN must be an sixteen-fold multiple of 63
-// because we have 63 samples per 512-byte METIS packet,
-// and two METIS packets per TCP/UDP packet,
-// and two/four/eight-fold up-sampling if the TX sample
-// rate is 96000/192000/384000
-//
-// In the new protocol, TX samples come in bunches of
-// 240 samples. So NEWRTXLEN is defined as a multiple of
-// 240 not exceeding RTXLEN
-//
-#define RTXLEN 64512
-#define NEWRTXLEN 64320
-double  isample[RTXLEN];  // shared with newhpsdrsim
-double  qsample[RTXLEN];  // shared with newhpsdrsim
 static double  last_i_sample=0.0;
 static double  last_q_sample=0.0;
 static int  txptr=0;
@@ -246,9 +189,6 @@ static int  txptr=0;
 #define NEW_DEVICE_ORION2      5
 #define NEW_DEVICE_HERMES_LITE 6
 
-static int OLDDEVICE=DEVICE_HERMES;
-static int NEWDEVICE=NEW_DEVICE_HERMES;
-
 int main(int argc, char *argv[])
 {
        int i, j, size;
@@ -291,6 +231,10 @@ int main(int argc, char *argv[])
  *      Examples for C25:      RedPitaya based boards with fixed ADC connections
  */
 
+        diversity=0;
+        OLDDEVICE=DEVICE_ORION2;
+        NEWDEVICE=NEW_DEVICE_ORION2;
+
         for (i=1; i<argc; i++) {
             if (!strncmp(argv[i],"-atlas"  ,      6))  {OLDDEVICE=DEVICE_ATLAS;       NEWDEVICE=NEW_DEVICE_ATLAS;}
             if (!strncmp(argv[i],"-hermes" ,      7))  {OLDDEVICE=DEVICE_HERMES;      NEWDEVICE=NEW_DEVICE_HERMES;}
@@ -313,6 +257,9 @@ int main(int argc, char *argv[])
             case   DEVICE_C25:     fprintf(stderr,"DEVICE is STEMlab/C25\n"); c1=3.3; c2=0.090; break;
         }
 
+//
+//      Initialize the data in the sample tables
+//
        fprintf(stderr,".... producing random noise\n");
         // Produce some noise
         j=RAND_MAX / 2;
@@ -356,8 +303,11 @@ int main(int argc, char *argv[])
          }
        }
        
-       memset (isample, 0, RTXLEN*sizeof(double));
-       memset (qsample, 0, RTXLEN*sizeof(double));
+//
+//      clear TX fifo
+//
+       memset (isample, 0, OLDRTXLEN*sizeof(double));
+       memset (qsample, 0, OLDRTXLEN*sizeof(double));
 
        audio_get_cards();
         audio_open_output();
@@ -612,7 +562,7 @@ int main(int argc, char *argv[])
                                        if (j == 62) bp+=8; // skip 8 SYNC/C&C bytes of second block
                                  }
                                 // wrap-around of ring buffer
-                                 if (txptr >= RTXLEN) txptr=0;
+                                 if (txptr >= OLDRTXLEN) txptr=0;
                                }
                                break;
 
@@ -708,9 +658,9 @@ int main(int argc, char *argv[])
                                // TX samples sent to the SDR and PURESIGNAL feedback
                                // samples arriving
                                //
-                                txptr=RTXLEN/2;
-                               memset(isample, 0, RTXLEN*sizeof(double));
-                               memset(qsample, 0, RTXLEN*sizeof(double));
+                                txptr=OLDRTXLEN/2;
+                               memset(isample, 0, OLDRTXLEN*sizeof(double));
+                               memset(qsample, 0, OLDRTXLEN*sizeof(double));
                                enable_thread = 1;
                                active_thread = 1;
                                CommonMercuryFreq = 0;
@@ -1134,10 +1084,10 @@ void *handler_ep6(void *arg)
        toneIQpt=0;
        divpt=0;
        // The rxptr should never "overtake" the txptr, but
-       // it also must not lag behind by too much. We choose
-       // about 50 msec
-        rxptr=txptr-(2500<<rate);
-        if (rxptr < 0) rxptr += RTXLEN;
+       // it also must not lag behind by too much. Let's take
+       // the typical TX FIFO size
+        rxptr=txptr-4096;
+        if (rxptr < 0) rxptr += OLDRTXLEN;
         
         clock_gettime(CLOCK_MONOTONIC, &delay);
        while (1)
@@ -1159,8 +1109,6 @@ void *handler_ep6(void *arg)
 //              Use PA settings such that there is full drive at full
 //              power (39 dB)
 //
-#define IM3a  0.60
-#define IM3b  0.20
 
                //  48 kHz   decimation=32
                //  96 kHz   decimation=16
@@ -1179,7 +1127,7 @@ void *handler_ep6(void *arg)
                    fac1=rxatt_dbl[0]*0.00001;          // Amplitude of 800-Hz-signal to ADC1
                    if (diversity) {
                        fac2=0.0001*rxatt_dbl[0];       // Amplitude of broad "man-made" noise to ADC1
-                       fac4=0.0002*rxatt_dbl[1];       // Amplitude of broad "man-made" noise to ADC2 (phase shifted 90 deg.)
+                       fac4=0.0003*rxatt_dbl[1];       // Amplitude of broad "man-made" noise to ADC2 (phase shifted 90 deg. and three times stronger)
                    }
                    for (j=0; j<n; j++) {
                        // ADC1: noise + weak tone on RX, feedback sig. on TX (except STEMlab)
@@ -1189,7 +1137,7 @@ void *handler_ep6(void *arg)
                          fac3=IM3a+IM3b*(i1*i1+q1*q1);
                          adc1isample= (txatt_dbl*i1*fac3+noiseItab[noiseIQpt]) * 8388607.0;
                          adc1qsample= (txatt_dbl*q1*fac3+noiseItab[noiseIQpt]) * 8388607.0;
-                       } else  if (diversity) {
+                       } else if (diversity) {
                          // man made noise only to I samples
                          adc1isample= (noiseItab[noiseIQpt]+toneItab[toneIQpt]*fac1+divtab[divpt]*fac2) * 8388607.0;
                          adc1qsample= (noiseQtab[noiseIQpt]+toneQtab[toneIQpt]*fac1                   ) * 8388607.0;
@@ -1206,7 +1154,7 @@ void *handler_ep6(void *arg)
                          adc2qsample= (txatt_dbl*q1*fac3+noiseItab[noiseIQpt]) * 8388607.0;
                        } else if (diversity) {
                          // man made noise to Q channel only
-                         adc2isample= noiseItab[noiseIQpt] * 8388607.0;                        // Noise
+                         adc2isample= noiseItab[noiseIQpt]                      * 8388607.0;           // Noise
                          adc2qsample= (noiseQtab[noiseIQpt]+divtab[divpt]*fac4) * 8388607.0;
                        } else {
                          adc2isample= noiseItab[noiseIQpt] * 8388607.0;                        // Noise
@@ -1259,7 +1207,7 @@ void *handler_ep6(void *arg)
                        }
                        // Microphone samples: silence
                        pointer += 2;
-                       rxptr++;              if (rxptr >= RTXLEN) rxptr=0;
+                       rxptr++;              if (rxptr >= OLDRTXLEN) rxptr=0;
                        noiseIQpt++;          if (noiseIQpt >= LENNOISE) noiseIQpt=rand() / NOISEDIV;
                        toneIQpt+=decimation; if (toneIQpt >= LENTONE) toneIQpt=0;
                        divpt+=decimation;    if (divpt >= LENDIV) divpt=0;
@@ -1625,3 +1573,4 @@ void audio_write (int16_t l, int16_t r)
 {
 }
 #endif
+
index 7365ae3d652e806c49488d3f524e1f5b29c942e5..ea9120ea4e0ea83547bb6c6242dec121082e392c 100644 (file)
@@ -557,14 +557,15 @@ void new_menu()
     gtk_grid_attach(GTK_GRID(grid),about_b,(i%5),i/5,1,1);
     i++;
 
-#ifdef DIVERSITY
-    if(RECEIVERS==2) {
+//
+//  We need at least two receivers and two ADCs to do DIVERSITY
+//
+    if(RECEIVERS==2 && n_adc > 1) {
       GtkWidget *diversity_b=gtk_button_new_with_label("Diversity");
       g_signal_connect (diversity_b, "button-press-event", G_CALLBACK(diversity_cb), NULL);
       gtk_grid_attach(GTK_GRID(grid),diversity_b,(i%5),i/5,1,1);
       i++;
     }
-#endif
 
     gtk_container_add(GTK_CONTAINER(content),grid);
 
index ec1ad8a8502f1663c9cb4eb7a7549b6ebc8f4a62..13fcda4a6217b437f6a5e64d0932518b7cfa4a46 100644 (file)
 
 #define PI 3.1415926535897932F
 
+/*
+ * A new 'action table' defines what to to
+ * with a sample packet received from a DDC
+ */
+
+#define RXACTION_SKIP   0    // skip samples
+#define RXACTION_NORMAL 1    // deliver 238 samples to a receiver
+#define RXACTION_PS     2    // deliver 2*119 samples to PS engine
+#define RXACTION_DIV    3    // take 2*119 samples, mix them, deliver to a receiver
+
+static int rxcase[MAX_DDC];
+static int rxid  [MAX_DDC];
+
 int data_socket=-1;
 
 static int running;
@@ -94,18 +107,17 @@ static int audio_addr_length;
 static struct sockaddr_in iq_addr;
 static int iq_addr_length;
 
-static struct sockaddr_in data_addr[MAX_RECEIVERS];
-static int data_addr_length[MAX_RECEIVERS];
+static struct sockaddr_in data_addr[MAX_DDC];
+static int data_addr_length[MAX_DDC];
 
 static GThread *new_protocol_thread_id;
 static GThread *new_protocol_timer_thread_id;
 
-static long ps_rx_sequence = 0;
-
 static long high_priority_sequence = 0;
 static long general_sequence = 0;
 static long rx_specific_sequence = 0;
 static long tx_specific_sequence = 0;
+static long ddc_sequence[MAX_DDC];
 
 //static int buffer_size=BUFFER_SIZE;
 //static int fft_size=4096;
@@ -166,15 +178,14 @@ static sem_t mic_line_sem_buffer;
 #endif
 static GThread *mic_line_thread_id;
 #ifdef __APPLE__
-static sem_t *iq_sem_ready[MAX_RECEIVERS];
-static sem_t *iq_sem_buffer[MAX_RECEIVERS];
+static sem_t *iq_sem_ready[MAX_DDC];
+static sem_t *iq_sem_buffer[MAX_DDC];
 #else
-static sem_t iq_sem_ready[MAX_RECEIVERS];
-static sem_t iq_sem_buffer[MAX_RECEIVERS];
+static sem_t iq_sem_ready[MAX_DDC];
+static sem_t iq_sem_buffer[MAX_DDC];
 #endif
-static GThread *iq_thread_id[MAX_RECEIVERS];
+static GThread *iq_thread_id[MAX_DDC];
 
-static int samples[MAX_RECEIVERS];
 #ifdef INCLUDED
 static int outputsamples;
 #endif
@@ -196,7 +207,7 @@ static socklen_t length=sizeof(addr);
 
 // Network buffers
 #define NET_BUFFER_SIZE 2048
-static unsigned char *iq_buffer[MAX_RECEIVERS];
+static unsigned char *iq_buffer[MAX_DDC];
 static unsigned char *command_response_buffer;
 static unsigned char *high_priority_buffer;
 static unsigned char *mic_line_buffer;
@@ -230,13 +241,9 @@ static gpointer command_response_thread(gpointer data);
 static gpointer high_priority_thread(gpointer data);
 static gpointer mic_line_thread(gpointer data);
 static gpointer iq_thread(gpointer data);
-#ifdef PURESIGNAL
-static gpointer ps_iq_thread(gpointer data);
-#endif
-static void  process_iq_data(RECEIVER *rx);
-#ifdef PURESIGNAL
-static void  process_ps_iq_data(void);
-#endif
+static void  process_iq_data(unsigned char *buffer, RECEIVER *rx);
+static void  process_ps_iq_data(unsigned char *buffer);
+static void process_div_iq_data(unsigned char *buffer);
 static void  process_command_response();
 static void  process_high_priority();
 static void  process_mic_data(int bytes);
@@ -296,14 +303,79 @@ void tuner_changed() {
 }
 */
 
+void update_action_table() {
+  //
+  // Depending on the values of mox, puresignal, and diversity,
+  // determine the actions to be taken when a DDC packet arrives
+  //
+  int flag;
+  flag=0;
+  if (device==NEW_DEVICE_ANGELIA || device==NEW_DEVICE_ORION || device == NEW_DEVICE_ORION2) flag +=1000;
+  if (isTransmitting())                                                                      flag +=100;
+  if (transmitter->puresignal)                                                               flag +=10;
+  if (diversity_enabled)                                                                     flag +=1;
+
+  //
+  // Set up rxcase and rxid for each of the 16 possible cases
+  // note that rxid[i] can be left unspecified if rxcase[i] == RXACTION_SKIP
+  //
+  rxcase[0] = RXACTION_SKIP;
+  rxcase[1] = RXACTION_SKIP;
+  rxcase[2] = RXACTION_SKIP;
+  rxcase[3] = RXACTION_SKIP;
+  switch (flag) {
+    case    0:                                                         // HERMES, RX, no DIVERSITY
+    case   10:
+       rxid[0]=0;
+       rxcase[0] = RXACTION_NORMAL;
+        if (receivers > 1) {
+         rxid[1]=1;
+         rxcase[1] = RXACTION_NORMAL;
+        }
+       break;
+    case    1:                                                         // HERMES, RX, DIVERSITY
+    case   11:                                                         // ORION, RX, DIVERSITY
+    case 1001:
+    case 1011:
+       rxid[0]=0;
+       rxcase[0] = RXACTION_DIV;
+       break;
+    case  100:                                                         // HERMES, TX, no PURESIGNAL
+    case  101:
+    case 1100:                                                         // ORION, TX, no PURESIGNAL
+    case 1101:                                                         // ORION, TX, no PURESIGNAL
+       // just skip samples
+       break;
+    case  110:                                                         // HERMES, TX, PURESIGNAL
+    case  111:
+    case 1110:                                                         // ORION, TX, PURESIGNAL
+    case 1111:
+       rxcase[0] = RXACTION_PS;
+       break;
+    case 1000:                                                         // ORION, RX, no DIVERSITY
+    case 1010:
+       rxid[2]=0;
+       rxcase[2] = RXACTION_NORMAL;
+        if (receivers > 1) {
+         rxid[3]=1;
+         rxcase[3] = RXACTION_NORMAL;
+        }
+       break;
+  }
+}
+
 void new_protocol_init(int pixels) {
     int i;
     int rc;
-    int ddc;
     spectrumWIDTH=pixels;
 
     fprintf(stderr,"new_protocol_init: MIC_SAMPLES=%d\n",MIC_SAMPLES);
 
+    memset(rxcase      , 0, MAX_DDC*sizeof(int));
+    memset(rxid        , 0, MAX_DDC*sizeof(int));
+    memset(ddc_sequence, 0, MAX_DDC*sizeof(long));
+    update_action_table();
+
 #ifdef INCLUDED
     outputsamples=buffer_size;
 #endif
@@ -391,57 +463,35 @@ void new_protocol_init(int pixels) {
     }
     fprintf(stderr, "mic_line_thread: id=%p\n",mic_line_thread_id);
 
-    for(i=0;i<RECEIVERS;i++) {
+//
+//  Spawn off one IQ reading thread for each DDC to be used
+//  Note that IQ reading threads are associated with DDCs and
+//  not with RECEIVERs.
+//
+    for(i=0;i<MAX_DDC;i++) {
 #ifdef __APPLE__
       char sname[12];
-#endif
-      ddc=receiver[i]->ddc;
-#ifdef __APPLE__
-      sprintf(sname,"IQREADY%03d", ddc);
+      sprintf(sname,"IQREADY%03d", i);
       sem_unlink(sname);
-      iq_sem_ready[ddc]=sem_open(sname, O_CREAT | O_EXCL, 0700, 0);
-      if (iq_sem_ready[ddc] == SEM_FAILED) {
+      iq_sem_ready[i]=sem_open(sname, O_CREAT | O_EXCL, 0700, 0);
+      if (iq_sem_ready[i] == SEM_FAILED) {
         fprintf(stderr,"SEM=%s, ",sname);
         perror("IQreadySemaphore");
       }
-      sprintf(sname,"IQBUF%03d", ddc);
+      sprintf(sname,"IQBUF%03d", i);
       sem_unlink(sname);
-      iq_sem_buffer[ddc]=sem_open(sname, O_CREAT| O_EXCL, 0700, 0);
-      if (iq_sem_buffer[ddc] == SEM_FAILED) {
+      iq_sem_buffer[i]=sem_open(sname, O_CREAT| O_EXCL, 0700, 0);
+      if (iq_sem_buffer[i] == SEM_FAILED) {
         fprintf(stderr,"SEM=%s, ",sname);
         perror("IQbufferSemaphore");
       }
 #else
-      rc=sem_init(&iq_sem_ready[ddc], 0, 0);
-      rc=sem_init(&iq_sem_buffer[ddc], 0, 0);
+      rc=sem_init(&iq_sem_ready[i], 0, 0);
+      rc=sem_init(&iq_sem_buffer[i], 0, 0);
 #endif
-      iq_thread_id[ddc] = g_thread_new( "iq thread", iq_thread, (gpointer)(long)i);
+      iq_thread_id[i] = g_thread_new( "iq thread", iq_thread, (gpointer)(long)i);
     }
 
-#ifdef PURESIGNAL
-    if(device!=NEW_DEVICE_HERMES) {
-      // for PS the two feedback streams are DDC0 and DDC1 and synced on DDC0
-      // so only packets from DDC0 will arrive.
-      // This code *assumes* that DDC0 is un-used for RX
-#ifdef __APPLE__
-      sem_unlink("PSIQREADY");
-      iq_sem_ready[0]=sem_open("PSIQREADY", O_CREAT | O_EXCL, 0700, 0);
-      if (iq_sem_ready[0] == SEM_FAILED) {
-        perror("PS-IQreadySemaphore");
-      }
-      sem_unlink("PSIQBUF");
-      iq_sem_buffer[0]=sem_open("PSIQBUF", O_CREAT | O_EXCL, 0700, 0);
-      if (iq_sem_buffer[0] == SEM_FAILED) {
-        perror("PS-IQbufferSemaphore");
-      }
-#else
-      rc=sem_init(&iq_sem_ready[0], 0, 0);
-      rc=sem_init(&iq_sem_buffer[0], 0, 0);
-#endif
-      iq_thread_id[0] = g_thread_new( "ps iq thread", ps_iq_thread, NULL);
-    }
-#endif
-
 data_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
     if(data_socket<0) {
         fprintf(stderr,"NewProtocol: create socket failed for data_socket\n");
@@ -487,11 +537,10 @@ fprintf(stderr,"new_protocol_thread: high_priority_addr setup for port %d\n",HIG
     iq_addr.sin_port=htons(TX_IQ_FROM_HOST_PORT);
 
 
-    for(i=0;i<MAX_RECEIVERS;i++) {
+    for(i=0;i<MAX_DDC;i++) {
         memcpy(&data_addr[i],&radio->info.network.address,radio->info.network.address_length);
         data_addr_length[i]=radio->info.network.address_length;
         data_addr[i].sin_port=htons(RX_IQ_TO_HOST_PORT_0+i);
-        samples[i]=0;
     }
 
     new_protocol_thread_id = g_thread_new( "new protocol", new_protocol_thread, NULL);
@@ -556,7 +605,7 @@ static void new_protocol_general() {
 }
 
 static void new_protocol_high_priority() {
-    int i, r;
+    int i;
     BAND *band;
     int xvtr;
     long long rxFrequency;
@@ -602,30 +651,68 @@ static void new_protocol_high_priority() {
 
 // rx
 
-    for(r=0;r<receivers;r++) {
-      int ddc=receiver[r]->ddc;
-      int v=receiver[r]->id;
-      rxFrequency=vfo[v].frequency-vfo[v].lo;
-      if(vfo[v].rit_enabled) {
-        rxFrequency+=vfo[v].rit;
-      }
+    if (diversity_enabled) {
+       //
+       // Use frequency of RX1 for both DDC0 and DDC1
+       // This is overridden later if we do PURESIGNAL TX
+       //
+        rxFrequency=vfo[0].frequency-vfo[0].lo;
+        if(vfo[0].rit_enabled) {
+          rxFrequency+=vfo[0].rit;
+        }
 
-      switch(vfo[v].mode) {
-        case modeCWU:
-          rxFrequency-=cw_keyer_sidetone_frequency;
-          break;
-        case modeCWL:
-          rxFrequency+=cw_keyer_sidetone_frequency;
-          break;
-        default:
-          break;
+        switch(vfo[0].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]=phase>>24;
+        high_priority_buffer_to_radio[10]=phase>>16;
+        high_priority_buffer_to_radio[11]=phase>>8;
+        high_priority_buffer_to_radio[12]=phase;
+        high_priority_buffer_to_radio[13]=phase>>24;
+        high_priority_buffer_to_radio[14]=phase>>16;
+        high_priority_buffer_to_radio[15]=phase>>8;
+        high_priority_buffer_to_radio[16]=phase;
+    } else {
+       //
+       // Set frequencies for all receivers
+       //
+       for(i=0;i<receivers;i++) {
+          // note that for HERMES, receiver[i] is associated with DDC(i) but beyond
+          // (that is, ANGELIA, ORION, ORION2) receiver[i] is associated with DDC(i+2)
+          ddc=i;
+          if (device==NEW_DEVICE_ANGELIA || device==NEW_DEVICE_ORION || device == NEW_DEVICE_ORION2) ddc=2+i;
+          int v=receiver[i]->id;
+          rxFrequency=vfo[v].frequency-vfo[v].lo;
+          if(vfo[v].rit_enabled) {
+            rxFrequency+=vfo[v].rit;
+          }
+
+          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;
     }
 
     // tx
@@ -656,7 +743,6 @@ static void new_protocol_high_priority() {
 
     phase=(long)((4294967296.0*(double)txFrequency)/122880000.0);
 
-#ifdef PURESIGNAL
     if(isTransmitting() && transmitter->puresignal) {
       // set DDC0 and DDC1 frequency to transmit frequency
       high_priority_buffer_to_radio[9]=phase>>24;
@@ -669,7 +755,6 @@ static void new_protocol_high_priority() {
       high_priority_buffer_to_radio[15]=phase>>8;
       high_priority_buffer_to_radio[16]=phase;
     }
-#endif
 
     high_priority_buffer_to_radio[329]=phase>>24;
     high_priority_buffer_to_radio[330]=phase>>16;
@@ -719,11 +804,9 @@ static void new_protocol_high_priority() {
 
     if(isTransmitting()) {
       filters=0x08000000;               // Bit 27
-#ifdef PURESIGNAL
       if(transmitter->puresignal) {
         filters|=0x00040000;            // Bit 18
       }
-#endif
     }
 
     rxFrequency=vfo[VFO_A].frequency-vfo[VFO_A].lo;
@@ -949,6 +1032,7 @@ static void new_protocol_high_priority() {
     }
 
     high_priority_sequence++;
+    update_action_table();
     pthread_mutex_unlock(&hi_prio_mutex);
 }
 
@@ -1055,20 +1139,23 @@ static void new_protocol_receive_specific() {
 
     receive_specific_buffer[4]=n_adc;  // number of ADCs
 
-    // note that for HERMES, receiver[i]->ddc == i but beyone
-    // (that is, ANGELIA, ORION, ORION2) receiver[i]->ddc should be 2+i
     for(i=0;i<receivers;i++) {
-      ddc=receiver[i]->ddc;
-      receive_specific_buffer[5]|=receiver[i]->dither<<ddc; // dither enable
-      receive_specific_buffer[6]|=receiver[i]->random<<ddc; // random enable
-      receive_specific_buffer[7]|=(1<<ddc); // DDC enable
-      receive_specific_buffer[17+(ddc*6)]=receiver[i]->adc;
-      receive_specific_buffer[18+(ddc*6)]=((receiver[i]->sample_rate/1000)>>8)&0xFF;
-      receive_specific_buffer[19+(ddc*6)]=(receiver[i]->sample_rate/1000)&0xFF;
-      receive_specific_buffer[22+(ddc*6)]=24;
+       // note that for HERMES, receiver[i] is associated with DDC(i) but beyond
+       // (that is, ANGELIA, ORION, ORION2) receiver[i] is associated with DDC(i+2)
+        ddc=i;
+        if (device==NEW_DEVICE_ANGELIA || device==NEW_DEVICE_ORION || device == NEW_DEVICE_ORION2) ddc=2+i;
+        receive_specific_buffer[5]|=receiver[i]->dither<<ddc; // dither enable
+        receive_specific_buffer[6]|=receiver[i]->random<<ddc; // random enable
+       if (!isTransmitting() && !diversity_enabled) {
+         // Upon TX (with and without PURESIGNAL), and upon diversity reception, deactivate DDCs
+          receive_specific_buffer[7]|=(1<<ddc); // DDC enable
+       }
+        receive_specific_buffer[17+(ddc*6)]=receiver[i]->adc;
+        receive_specific_buffer[18+(ddc*6)]=((receiver[i]->sample_rate/1000)>>8)&0xFF;
+        receive_specific_buffer[19+(ddc*6)]=(receiver[i]->sample_rate/1000)&0xFF;
+        receive_specific_buffer[22+(ddc*6)]=24;
     }
 
-#ifdef PURESIGNAL
     if(transmitter->puresignal && isTransmitting()) {
 //
 //    Some things are fixed.
@@ -1078,23 +1165,44 @@ static void new_protocol_receive_specific() {
 //    dither and random are always off
 //    there are 24 bits per sample
 //
-      ddc=0;
-      receive_specific_buffer[17+(ddc*6)]=0;           // ADC associated with DDC0
-      receive_specific_buffer[18+(ddc*6)]=0;           // sample rate MSB
-      receive_specific_buffer[19+(ddc*6)]=192;         // sample rate LSB
-      receive_specific_buffer[22+(ddc*6)]=24;          // bits per sample
-
-      ddc=1;
-      receive_specific_buffer[17+(ddc*6)]=n_adc;       // ADC associated with DDC1
-      receive_specific_buffer[18+(ddc*6)]=0;           // sample rate MSB
-      receive_specific_buffer[19+(ddc*6)]=192;         // sample rate LSB
-      receive_specific_buffer[22+(ddc*6)]=24;          // bits per sample
-      receive_specific_buffer[1363]=0x02;              // sync DDC1 to DDC0
-
-      receive_specific_buffer[7]&=0xFD;                // disable DDC1
-      receive_specific_buffer[7]|=1;                   // enable  DDC0
+      receive_specific_buffer[17]=0;           // ADC0 associated with DDC0
+      receive_specific_buffer[18]=0;           // sample rate MSB
+      receive_specific_buffer[19]=192;         // sample rate LSB
+      receive_specific_buffer[22]=24;          // bits per sample
+
+      receive_specific_buffer[23]=n_adc;       // TX-DAC associated with DDC1
+      receive_specific_buffer[24]=0;           // sample rate MSB
+      receive_specific_buffer[25]=192;         // sample rate LSB
+      receive_specific_buffer[26]=24;          // bits per sample
+      receive_specific_buffer[1363]=0x02;       // sync DDC1 to DDC0
+
+      receive_specific_buffer[7]=1;            // enable  DDC0 but disable all others
+    }
+    if (diversity_enabled && ! isTransmitting()) {
+//
+//    Some things are fixed.
+//    We always use DDC0 for the signals from ADC0, and DDC1 for the signals from ADC1
+//    The sample rate of both DDCs is that of receiver[0].
+//    Boths ADCs take the dither/random setting from receiver[0]
+//
+      receive_specific_buffer[5]|=receiver[0]->dither;         // dither DDC0: take value from RX1
+      receive_specific_buffer[5]|=(receiver[0]->dither) << 1;  // dither DDC1: take value from RX1
+      receive_specific_buffer[6]|=receiver[0]->random;         // random DDC0: take value from RX1
+      receive_specific_buffer[6]|=(receiver[0]->random) << 1;  // random DDC1: take value from RX1
+
+      receive_specific_buffer[17]=0;                                           // ADC0 associated with DDC0
+      receive_specific_buffer[18]=((receiver[0]->sample_rate/1000)>>8)&0xFF;   // sample rate MSB
+      receive_specific_buffer[19]=(receiver[0]->sample_rate/1000)&0xFF;                // sample rate LSB
+      receive_specific_buffer[22]=24;                                          // bits per sample
+
+      receive_specific_buffer[23]=1;                                           // ADC1 associated with DDC1
+      receive_specific_buffer[24]=((receiver[0]->sample_rate/1000)>>8)&0xFF;   // sample rate MSB
+      receive_specific_buffer[25]=(receiver[0]->sample_rate/1000)&0xFF;;       // sample rate LSB
+      receive_specific_buffer[26]=24;                                          // bits per sample
+      receive_specific_buffer[1363]=0x02;                                      // sync DDC1 to DDC0
+
+      receive_specific_buffer[7]=1;                                            // enable  DDC0 but disable all others
     }
-#endif
 
 //fprintf(stderr,"new_protocol_receive_specific: enable=%02X\n",receive_specific_buffer[7]);
     if(sendto(data_socket,receive_specific_buffer,sizeof(receive_specific_buffer),0,(struct sockaddr*)&receiver_addr,receiver_addr_length)<0) {
@@ -1103,6 +1211,7 @@ static void new_protocol_receive_specific() {
     }
 
     rx_specific_sequence++;
+    update_action_table();
     pthread_mutex_unlock(&rx_spec_mutex);
 }
 
@@ -1198,11 +1307,10 @@ fprintf(stderr,"new_protocol_thread: high_priority_addr setup for port %d\n",HIG
     iq_addr.sin_port=htons(TX_IQ_FROM_HOST_PORT);
 
    
-    for(i=0;i<MAX_RECEIVERS;i++) {
+    for(i=0;i<MAX_DDC;i++) {
         memcpy(&data_addr[i],&radio->info.network.address,radio->info.network.address_length);
         data_addr_length[i]=radio->info.network.address_length;
         data_addr[i].sin_port=htons(RX_IQ_TO_HOST_PORT_0+i);
-        samples[i]=0;
     }
 */
     audioindex=4; // leave space for sequence
@@ -1235,7 +1343,7 @@ fprintf(stderr,"new_protocol_thread: high_priority_addr setup for port %d\n",HIG
             case RX_IQ_TO_HOST_PORT_7:
               ddc=sourceport-RX_IQ_TO_HOST_PORT_0;
 //fprintf(stderr,"iq packet from port=%d ddc=%d\n",sourceport,ddc);
-              if(ddc>=MAX_RECEIVERS)  {
+              if(ddc>=MAX_DDC)  {
                 fprintf(stderr,"unexpected iq data from ddc %d\n",ddc);
               } else {
 #ifdef __APPLE__
@@ -1351,9 +1459,10 @@ fprintf(stderr,"mic_line_thread\n");
 }
 
 static gpointer iq_thread(gpointer data) {
-  int rx=(uintptr_t)data;
-  int ddc=receiver[rx]->ddc;
-  fprintf(stderr,"iq_thread: rx=%d ddc=%d\n",rx,ddc);
+  int ddc=(uintptr_t)data;
+  long sequence;
+  unsigned char *buffer;
+  fprintf(stderr,"iq_thread: ddc=%d\n",ddc);
   while(1) {
 #ifdef __APPLE__
     sem_post(iq_sem_ready[ddc]);
@@ -1362,31 +1471,40 @@ static gpointer iq_thread(gpointer data) {
     sem_post(&iq_sem_ready[ddc]);
     sem_wait(&iq_sem_buffer[ddc]);
 #endif
-    if (iq_buffer[ddc] == NULL) continue;
-    process_iq_data(receiver[rx]);
-    free(iq_buffer[ddc]);
-  }
-}
-
-#ifdef PURESIGNAL
-static gpointer ps_iq_thread(void * data) {
-fprintf(stderr,"ps_iq_thread\n");
-  while(1) {
-#ifdef __APPLE__
-    sem_post(iq_sem_ready[0]);
-    sem_wait(iq_sem_buffer[0]);
-#else
-    sem_post(&iq_sem_ready[0]);
-    sem_wait(&iq_sem_buffer[0]);
-#endif
-    process_ps_iq_data();
-    free(iq_buffer[0]);
+    buffer=iq_buffer[ddc];
+    if (buffer == NULL) continue;
+//
+//  Perform sequence check HERE for all cases
+//
+    sequence=((buffer[0]&0xFF)<<24)+((buffer[1]&0xFF)<<16)+((buffer[2]&0xFF)<<8)+(buffer[3]&0xFF);
+    if(ddc_sequence[ddc] !=sequence) {
+      fprintf(stderr,"DDC %d sequence error: expected %ld got %ld\n",ddc,ddc_sequence[ddc],sequence);
+      ddc_sequence[ddc]=sequence;
+    }
+    ddc_sequence[ddc]++;
+//
+//  Now comes the action table:
+//  for each DDC we have set up which action to be taken
+//  (and, possibly, for which receiver)
+//
+    switch (rxcase[ddc]) {
+       case RXACTION_SKIP:
+         break;
+       case RXACTION_NORMAL:
+          process_iq_data(buffer,receiver[rxid[ddc]]);
+         break;
+       case RXACTION_PS:
+         process_ps_iq_data(buffer);
+         break;
+       case RXACTION_DIV:
+         process_div_iq_data(buffer);
+         break;
+    }
+    free(buffer);
   }
 }
-#endif
 
-static void process_iq_data(RECEIVER *rx) {
-  long sequence;
+static void process_iq_data(unsigned char *buffer, RECEIVER *rx) {
   long long timestamp;
   int bitspersample;
   int samplesperframe;
@@ -1395,17 +1513,6 @@ static void process_iq_data(RECEIVER *rx) {
   int rightsample;
   double leftsampledouble;
   double rightsampledouble;
-  unsigned char *buffer;
-
-  buffer=iq_buffer[rx->ddc];
-
-  sequence=((buffer[0]&0xFF)<<24)+((buffer[1]&0xFF)<<16)+((buffer[2]&0xFF)<<8)+(buffer[3]&0xFF);
-
-  if(rx->iq_sequence!=sequence) {
-    fprintf(stderr,"rx %d sequence error: expected %ld got %ld\n",rx->id,rx->iq_sequence,sequence);
-    rx->iq_sequence=sequence;
-  }
-  rx->iq_sequence++;
 
   timestamp=((long long)(buffer[4]&0xFF)<<56)
            +((long long)(buffer[5]&0xFF)<<48)
@@ -1418,7 +1525,7 @@ static void process_iq_data(RECEIVER *rx) {
   bitspersample=((buffer[12]&0xFF)<<8)+(buffer[13]&0xFF);
   samplesperframe=((buffer[14]&0xFF)<<8)+(buffer[15]&0xFF);
 
-//fprintf(stderr,"process_iq_data: rx=%d seq=%ld bitspersample=%d samplesperframe=%d\n",rx->id, sequence,bitspersample,samplesperframe);
+//fprintf(stderr,"process_iq_data: rx=%d bitspersample=%d samplesperframe=%d\n",rx->id, bitspersample,samplesperframe);
   b=16;
   int i;
   for(i=0;i<samplesperframe;i++) {
@@ -1429,17 +1536,20 @@ static void process_iq_data(RECEIVER *rx) {
     rightsample |= (int)((((unsigned char)buffer[b++])<<8)&0xFF00);
     rightsample |= (int)((unsigned char)buffer[b++]&0xFF);
 
-    //leftsampledouble=(double)leftsample/8388607.0; // for 24 bits
-    //rightsampledouble=(double)rightsample/8388607.0; // for 24 bits
-    leftsampledouble=(double)leftsample/16777215.0; // for 24 bits
-    rightsampledouble=(double)rightsample/16777215.0; // for 24 bits
+    leftsampledouble=(double)leftsample/8388608.0; // for 24 bits
+    rightsampledouble=(double)rightsample/8388608.0; // for 24 bits
+    //leftsampledouble=(double)leftsample/16777215.0; // for 24 bits
+    //rightsampledouble=(double)rightsample/16777215.0; // for 24 bits
 
     add_iq_samples(rx, leftsampledouble,rightsampledouble);
   }
 }
 
-#ifdef PURESIGNAL
-static void process_ps_iq_data() {
+//
+// This is the same as process_ps_iq_data except that add_div_iq_samples is called
+// at the end
+//
+static void process_div_iq_data(unsigned char*buffer) {
   long sequence;
   long long timestamp;
   int bitspersample;
@@ -1453,22 +1563,66 @@ static void process_ps_iq_data() {
   int rightsample1;
   double leftsampledouble1;
   double rightsampledouble1;
-  unsigned char *buffer;
+  
+  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)    );
 
-  int min_sample0;
-  int max_sample0;
-  int min_sample1;
-  int max_sample1;
+  bitspersample=((buffer[12]&0xFF)<<8)+(buffer[13]&0xFF);
+  samplesperframe=((buffer[14]&0xFF)<<8)+(buffer[15]&0xFF);
 
-  buffer=iq_buffer[0];
+  b=16;
+  int i;
+  for(i=0;i<samplesperframe;i+=2) {
+    leftsample0   = (int)((signed char) buffer[b++])<<16;
+    leftsample0  |= (int)((((unsigned char)buffer[b++])<<8)&0xFF00);
+    leftsample0  |= (int)((unsigned char)buffer[b++]&0xFF);
+    rightsample0  = (int)((signed char)buffer[b++]) << 16;
+    rightsample0 |= (int)((((unsigned char)buffer[b++])<<8)&0xFF00);
+    rightsample0 |= (int)((unsigned char)buffer[b++]&0xFF);
+    
+    leftsampledouble0=(double)leftsample0/8388608.0; 
+    rightsampledouble0=(double)rightsample0/8388608.0; 
+    
+    leftsample1   = (int)((signed char) buffer[b++])<<16;
+    leftsample1  |= (int)((((unsigned char)buffer[b++])<<8)&0xFF00);
+    leftsample1  |= (int)((unsigned char)buffer[b++]&0xFF);
+    rightsample1  = (int)((signed char)buffer[b++]) << 16;
+    rightsample1 |= (int)((((unsigned char)buffer[b++])<<8)&0xFF00);
+    rightsample1 |= (int)((unsigned char)buffer[b++]&0xFF);
 
-  sequence=((buffer[0]&0xFF)<<24)+((buffer[1]&0xFF)<<16)+((buffer[2]&0xFF)<<8)+(buffer[3]&0xFF);
+    leftsampledouble1=(double)leftsample1/8388608.0; // for 24 bits
+    rightsampledouble1=(double)rightsample1/8388608.0; // for 24 bits
 
-  if(ps_rx_sequence!=sequence) {
-    fprintf(stderr,"PS-RX sequence error: expected %ld got %ld\n",ps_rx_sequence,sequence);
-    ps_rx_sequence=sequence;
+    add_div_iq_samples(receiver[0], leftsampledouble0,rightsampledouble0,leftsampledouble1,rightsampledouble1);
+    //
+    // if both receivers share the sample rate, we can feed data to RX2
+    //
+    if (receivers > 1 && (receiver[0]->sample_rate == receiver[1]->sample_rate)) {
+      add_iq_samples(receiver[1], leftsampledouble1,rightsampledouble1);
+    }
   }
-  ps_rx_sequence++;
+}
+
+static void process_ps_iq_data(unsigned char *buffer) {
+  long sequence;
+  long long timestamp;
+  int bitspersample;
+  int samplesperframe;
+  int b;
+  int leftsample0;
+  int rightsample0;
+  double leftsampledouble0;
+  double rightsampledouble0;
+  int leftsample1;
+  int rightsample1;
+  double leftsampledouble1;
+  double rightsampledouble1;
 
   timestamp=((long long)(buffer[ 4]&0xFF)<<56)
            +((long long)(buffer[ 5]&0xFF)<<48)
@@ -1482,7 +1636,7 @@ static void process_ps_iq_data() {
   bitspersample=((buffer[12]&0xFF)<<8)+(buffer[13]&0xFF);
   samplesperframe=((buffer[14]&0xFF)<<8)+(buffer[15]&0xFF);
 
-//fprintf(stderr,"process_ps_iq_data: seq=%ld bitspersample=%d samplesperframe=%d\n", sequence,bitspersample,samplesperframe);
+//fprintf(stderr,"process_ps_iq_data: bitspersample=%d samplesperframe=%d\n", bitspersample,samplesperframe);
   b=16;
   int i;
   for(i=0;i<samplesperframe;i+=2) {
@@ -1493,8 +1647,8 @@ static void process_ps_iq_data() {
     rightsample0 |= (int)((((unsigned char)buffer[b++])<<8)&0xFF00);
     rightsample0 |= (int)((unsigned char)buffer[b++]&0xFF);
 
-    leftsampledouble0=(double)leftsample0/8388608.0; // for 24 bits
-    rightsampledouble0=(double)rightsample0/8388608.0; // for 24 bits
+    leftsampledouble0=(double)leftsample0/8388608.0;
+    rightsampledouble0=(double)rightsample0/8388608.0;
 
     leftsample1   = (int)((signed char) buffer[b++])<<16;
     leftsample1  |= (int)((((unsigned char)buffer[b++])<<8)&0xFF00);
@@ -1509,31 +1663,8 @@ static void process_ps_iq_data() {
     add_ps_iq_samples(transmitter, leftsampledouble1,rightsampledouble1,leftsampledouble0,rightsampledouble0);
 
 //fprintf(stderr,"%06x,%06x %06x,%06x\n",leftsample0,rightsample0,leftsample1,rightsample1);
-#if 0
-    if(i==0) {
-      min_sample0=leftsample0;
-      max_sample0=leftsample0;
-      min_sample1=leftsample1;
-      max_sample1=leftsample1;
-    } else {
-      if(leftsample0<min_sample0) {
-        min_sample0=leftsample0;
-      }
-      if(leftsample0>max_sample0) {
-        max_sample0=leftsample0;
-      }
-      if(leftsample1<min_sample1) {
-        min_sample1=leftsample1;
-      }
-      if(leftsample1>max_sample1) {
-        max_sample1=leftsample1;
-      }
-    }
-#endif
   }
-
 }
-#endif
 
 
 static void process_command_response() {
index 132016a388a9ae8941c06c24bb31635a30fea6c2..3cb137010ae8c225097106cc15c3db8328dad323 100644 (file)
@@ -9,36 +9,10 @@
 #include <arpa/inet.h>
 #include <math.h>
 
-extern struct sockaddr_in addr_new;
-extern void audio_write(int16_t r, int16_t l);
+#define EXTERN extern
+#include "hpsdrsim.h"
 
-#define NUMRECEIVERS 8
-
-#define LENNOISE 1536000
-#define NOISEDIV (RAND_MAX / 768000)
-
-double noiseItab[LENNOISE];
-double noiseQtab[LENNOISE];
-
-extern int diversity;
-
-#define LENDIV 16000
-double divtab[LENDIV];
-
-#define LENTONE 15360
-extern double toneItab[LENTONE];
-extern double toneQtab[LENTONE];
-
-extern double c1, c2;
-
-#define IM3a  0.60
-#define IM3b  0.20
-
-#define RTXLEN 64512
-#define NEWRTXLEN 64320
-extern double  isample[RTXLEN];  // shared with newhpsdrsim
-extern double  qsample[RTXLEN];  // shared with newhpsdrsim
-static int txptr = 10000;
+#define NUMRECEIVERS 4
 
 /*
  * These variables represent the state of the machine
@@ -123,6 +97,8 @@ static double txdrv_dbl = 0.0;
 
 // End of state variables
 
+static int txptr = 10000;
+
 static pthread_t ddc_specific_thread_id;
 static pthread_t duc_specific_thread_id;
 static pthread_t rx_thread_id[NUMRECEIVERS];
@@ -148,14 +124,14 @@ int new_protocol_running() {
 }
 
 void new_protocol_general_packet(unsigned char *buffer) {
-  static unsigned long seqnum=0;
+  static unsigned long gp_seqnum=0;
   unsigned long seqold;
   int rc;
 
-  seqold = seqnum;
-  seqnum = (buffer[0] >> 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3];
-  if (seqnum != 0 && seqnum != seqold+1 ) {
-    fprintf(stderr,"GP: SEQ ERROR, old=%lu new=%lu\n", seqold, seqnum);
+  seqold = gp_seqnum;
+  gp_seqnum = (buffer[0] >> 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3];
+  if (gp_seqnum != 0 && gp_seqnum != seqold+1 ) {
+    fprintf(stderr,"GP: SEQ ERROR, old=%lu new=%lu\n", seqold, gp_seqnum);
   }
 
   rc=(buffer[5] << 8) + buffer[6];
@@ -346,6 +322,7 @@ void *ddc_specific_thread(void *data) {
     return NULL;
   }
 
+  seqnum=0;
   while(run) {
      rc = recvfrom(sock, buffer, 1444, 0,(struct sockaddr *)&addr, &lenaddr);
      if (rc < 0 && errno != EAGAIN) {
@@ -354,13 +331,13 @@ void *ddc_specific_thread(void *data) {
      }
      if (rc < 0) continue;
      if (rc != 1444) {
-       fprintf(stderr,"RX: Received DDC specific packet with incorrect length");
+       fprintf(stderr,"RXspec: Received DDC specific packet with incorrect length");
        break;
      }
      seqold = seqnum;
      seqnum = (buffer[0] >> 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3];
-     if (seqnum != 0 &&seqnum != seqold+1 ) {
-       fprintf(stderr,"GP: SEQ ERROR, old=%lu new=%lu\n", seqold, seqnum);
+     if (seqnum != 0 && seqnum != seqold+1 ) {
+       fprintf(stderr,"RXspec: SEQ ERROR, old=%lu new=%lu\n", seqold, seqnum);
      }
      if (adc != buffer[4]) {
        adc=buffer[4];
@@ -384,12 +361,6 @@ void *ddc_specific_thread(void *data) {
      for (i=0; i<NUMRECEIVERS; i++) {
        int modified=0;
 
-       rc=(buffer[7 + (i/8)] >> (i % 8)) & 0x01;
-       if (rc != ddcenable[i]) {
-        modified=1;
-        ddcenable[i]=rc;
-       }
-       
        rc=buffer[17+6*i];
        if (rc != adcmap[i]) {
         modified=1;
@@ -416,7 +387,7 @@ void *ddc_specific_thread(void *data) {
         fprintf(stderr,"RX: DDC%d Enable=%d ADC%d Rate=%d SyncMap=%02x\n",
                i,ddcenable[i], adcmap[i], rxrate[i], syncddc[i]);
         rc=0;
-        for (i=0; i<8; i++) {
+        for (j=0; j<8; j++) {
           rc += (syncddc[i] >> i) & 0x01;
         }
         if (rc > 1) {
@@ -465,19 +436,19 @@ void *duc_specific_thread(void *data) {
   addr.sin_port = htons(duc_port);
 
   if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
-    perror("***** ERROR: TX specific: bind");
+    perror("***** ERROR: TXspec: bind");
     return NULL;
   }
 
   while(run) {
      rc = recvfrom(sock, buffer, 60, 0,(struct sockaddr *)&addr, &lenaddr);
      if (rc < 0 && errno != EAGAIN) {
-       perror("***** ERROR: DUC specific thread: recvmsg");
+       perror("***** ERROR: TXspec: recvmsg");
        break;
      }
      if (rc < 0) continue;
      if (rc != 60) {
-       fprintf(stderr,"TX: DUC Specific: wrong length\n");
+       fprintf(stderr,"TXspec: wrong length\n");
         break;
      }
      seqold = seqnum;
@@ -594,7 +565,7 @@ void *highprio_thread(void *data) {
      seqold = seqnum;
      seqnum = (buffer[0] >> 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3];
      if (seqnum != 0 &&seqnum != seqold+1 ) {
-       fprintf(stderr,"GP: SEQ ERROR, old=%lu new=%lu\n", seqold, seqnum);
+       fprintf(stderr,"HP: SEQ ERROR, old=%lu new=%lu\n", seqold, seqnum);
      }
      rc=(buffer[4] >> 0) & 0x01;
      if (rc != run) {
@@ -761,8 +732,8 @@ void *rx_thread(void *data) {
   long myrate;
   int sync,size;
   int myadc, syncadc;
-  int ps=0;
   int rxptr;
+  int divptr;
   int decimation;
   
   struct timespec delay;
@@ -796,13 +767,14 @@ void *rx_thread(void *data) {
   tonept=noisept=0;
   clock_gettime(CLOCK_MONOTONIC, &delay);
   fprintf(stderr,"RX thread %d, enabled=%d\n", myddc, ddcenable[myddc]);
-  rxptr=txptr-5000;  
+  rxptr=txptr-4096;  
   if (rxptr < 0) rxptr += NEWRTXLEN;
+  divptr=0;
   while (run) {
        if (!ddcenable[myddc] || rxrate[myddc] == 0 || rxfreq[myddc] == 0) {
          usleep(5000);
           clock_gettime(CLOCK_MONOTONIC, &delay);
-         rxptr=txptr-5000;  
+         rxptr=txptr-4096;  
          if (rxptr < 0) rxptr += NEWRTXLEN;
           continue;
         }
@@ -836,7 +808,6 @@ void *rx_thread(void *data) {
        // ADC2   : original TX signal
        //
          
-        ps=(sync && (rxrate[myadc]==192) && ptt && (syncadc == adc));
         p=buffer;
         *p++ =(seqnum >> 24) & 0xFF;
         *p++ =(seqnum >> 16) & 0xFF;
@@ -869,7 +840,11 @@ void *rx_thread(void *data) {
          // a) distorted TX data (with Drive and Attenuation) 
          // b) original TX data (normalized)
          //
-         if (ps) {
+         // DIV: produce sample PAIRS,
+         // a) add man-made-noise on I-sample of RX channel
+         // b) add man-made-noise on Q-sample of "synced" channel
+         //
+         if (sync && (rxrate[myadc]==192) && ptt && (syncadc == adc)) {
            irsample = isample[rxptr];
            qrsample = qsample[rxptr++];
            if (rxptr >= NEWRTXLEN) rxptr=0;
@@ -878,17 +853,27 @@ void *rx_thread(void *data) {
              i0sample += irsample*fac;
              q0sample += qrsample*fac;
            }
-         } else if (myddc == 0) {
+           i1sample = irsample * 0.2899;
+           q1sample = qrsample * 0.2899;
+         } else if (myadc == 0) {
            i0sample += toneItab[tonept] * 0.00001 * rxatt0_dbl;
            q0sample += toneQtab[tonept] * 0.00001 * rxatt0_dbl;
            tonept += decimation; if (tonept >= LENTONE) tonept=0;
          }
+         if (diversity && !sync && myadc == 0) {
+           i0sample += 0.0001 * rxatt0_dbl * divtab[divptr];
+           divptr += decimation; if (divptr >= LENDIV) divptr=0;
+         }
+         if (diversity && !sync && myadc == 1) {
+           q0sample += 0.0002 * rxatt1_dbl * divtab[divptr];
+           divptr += decimation; if (divptr >= LENDIV) divptr=0;
+         }
+         if (diversity && sync && !ptt) {
+           if (myadc == 0)   i0sample += 0.0001 * rxatt0_dbl * divtab[divptr];
+           if (syncadc == 1) q1sample += 0.0002 * rxatt1_dbl * divtab[divptr];
+           divptr += decimation; if (divptr >= LENDIV) divptr=0;
+         }
          if (sync) {
-           if (ps) {
-             // synchronized stream: undistorted TX signal with constant max. amplitude
-             i1sample = irsample * 0.2899;
-             q1sample = qrsample * 0.2899;
-           }
            sample=i0sample * 8388607.0;
            *p++=(sample >> 16) & 0xFF;
            *p++=(sample >>  8) & 0xFF;
@@ -1104,7 +1089,7 @@ void *send_highprio_thread(void *data) {
        break;
     }
     seqnum++;
-    usleep(50000); // wait 50 msec
+    usleep(50000); // wait 50 msec then send again
   }
   close(sock);
   return NULL;
@@ -1179,8 +1164,7 @@ void *audio_thread(void *data) {
 }
 
 //
-// The microphone thread generates
-// a two-tone signal
+// The microphone thread just sends silence
 //
 void *mic_thread(void *data) {
   int sock;
@@ -1191,25 +1175,11 @@ void *mic_thread(void *data) {
   int yes = 1;
   int rc;
   int i;
-  double arg1,arg2;
-  int sintab[480];  // microphone data
-  int sinptr = 0;
   struct timespec delay;
 #ifdef __APPLE__
   struct timespec now;
 #endif
 
-#define FREQ900  0.11780972450961724644234912687298
-#define FREQ1700 0.22252947962927702105777057298230
-
-  seqnum=0;
-  arg1=0.0;
-  arg2=0.0;
-  for (i=0; i<480; i++) {
-    sintab[i]=(int) round((sin(arg1)+sin(arg2)) * 5000.0);
-    arg1 += FREQ900;
-    arg2 += FREQ1700;
-  }
 
   sock=socket(AF_INET, SOCK_DGRAM, 0);
   if (sock < 0) {
@@ -1241,13 +1211,6 @@ void *mic_thread(void *data) {
     *p++ = (seqnum >>  8) & 0xFF;
     *p++ = (seqnum >>  0) & 0xFF;
     seqnum++;
-    // take periodic data from sintab as "microphone samples"
-    for (i=0; i< 64; i++) {
-       rc=sintab[sinptr++];
-        if (sinptr == 480) sinptr=0;
-        *p++ = (rc >> 8)  & 0xff;
-        *p++ = (rc & 0xff);
-    }
     // 64 samples with 48000 kHz, makes 1333333 nsec
     delay.tv_nsec += 1333333;
     while (delay.tv_nsec >= 1000000000) {
@@ -1280,5 +1243,3 @@ void *mic_thread(void *data) {
   close(sock);
   return NULL;
 }
-  
-
index 01c300d555f05638a1b6dabe6a0b9f58b4e2b865..38b16c69640b51b1ec5f635b8a2bc4197ea7425b 100644 (file)
@@ -535,6 +535,29 @@ static gpointer receive_thread(gpointer arg) {
   return NULL;
 }
 
+static int how_many_receivers() {
+  //
+  // Depending on how the program is compiled and which board we have,
+  // we use a FIXED number of receivers except for RADIOBERRY and PI_SDR,
+  // where the number may be dynamically changed
+  //
+  int num;
+#if defined(RADIOBERRY) || defined(PI_SDR)
+        num = receivers;   // 1 or 2
+#else
+        num = RECEIVERS;     // 2
+#endif
+
+#ifdef PURESIGNAL
+    // 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.
+    num = 3;
+    if (device == DEVICE_HERMES) num = 4;
+    if (device == DEVICE_ANGELIA || device == DEVICE_ORION || device == DEVICE_ORION2) num = 5;
+#endif
+    return num;
+}
 static void process_ozy_input_buffer(unsigned char  *buffer) {
   int i,j;
   int r;
@@ -562,22 +585,7 @@ static void process_ozy_input_buffer(unsigned char  *buffer) {
 
   int tx_vfo=split?VFO_B:VFO_A;
 
-  int num_hpsdr_receivers;
-
-#ifdef PURESIGNAL
-    // 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.
-    num_hpsdr_receivers=3;
-    if (device == DEVICE_HERMES) num_hpsdr_receivers=4;
-    if (device == DEVICE_ANGELIA || device == DEVICE_ORION || device == DEVICE_ORION2) num_hpsdr_receivers=5;
-#else
-#if defined(RADIOBERRY) || defined(PI_SDR)
-       num_hpsdr_receivers = receivers;
-#else
-       num_hpsdr_receivers=RECEIVERS;
-#endif
-#endif
+  int num_hpsdr_receivers=how_many_receivers();
 
   if(buffer[b++]==SYNC && buffer[b++]==SYNC && buffer[b++]==SYNC) {
     // extract control bytes
@@ -654,22 +662,10 @@ static void process_ozy_input_buffer(unsigned char  *buffer) {
         right_sample_double=(double)right_sample/8388607.0; // 24 bit sample 2^23-1
 
 #ifdef PURESIGNAL
-        if(!isTransmitting() || (isTransmitting() && !transmitter->puresignal)) {
-          switch(r) {
-            case 0:
-              add_iq_samples(receiver[0], left_sample_double,right_sample_double);
-              break;
-            case 1:
-              break;
-            case 2:
-              add_iq_samples(receiver[1], left_sample_double,right_sample_double);
-              break;
-            case 3:
-              break;
-            case 4:
-              break;
-          }
-        } else {
+       if (isTransmitting() && transmitter->puresignal) {
+         //
+         // case: transmitting with PURESIGNAL. Get sample pairs and feed to pscc
+         //
           switch(r) {
             case 0:
               if(device==DEVICE_METIS)  {
@@ -709,8 +705,68 @@ static void process_ozy_input_buffer(unsigned char  *buffer) {
               break;
           }
         }
+        if (!isTransmitting() && diversity_enabled) {
+         //
+         // case: compiled for PURESIGNAL and RX with DIVERSITY. Feed sample pair to diversity mixer for RX1 and original RX2 sample to RX2
+         //
+          switch(r) {
+            case 0:
+              left_sample_double_rx=left_sample_double;
+              right_sample_double_rx=right_sample_double;
+              break;
+            case 2:
+              left_sample_double_tx=left_sample_double;
+              right_sample_double_tx=right_sample_double;
+              add_div_iq_samples(receiver[0], left_sample_double_rx,right_sample_double_rx,left_sample_double_tx,right_sample_double_tx);
+              if (receivers >1) add_iq_samples(receiver[1], left_sample_double,right_sample_double);
+              break;
+          }
+        }
+        if (!isTransmitting() && !diversity_enabled) {
+         //
+         // case: compiled for PURESIGNAL and RX without DIVERSITY. Feed samples to RX1 and RX2
+         //
+          switch(r) {
+            case 0:
+              add_iq_samples(receiver[0], left_sample_double,right_sample_double);
+              break;
+            case 2:
+              if (receivers >1) add_iq_samples(receiver[1], left_sample_double,right_sample_double);
+              break;
+          }
+        }
 #else
-        add_iq_samples(receiver[r], left_sample_double,right_sample_double);
+        // no PURESIGNAL
+        if (diversity_enabled) {
+         //
+         // case: compiled without PURESIGNAL and using DIVERSITY: Feed sample pair to diversity mixer for RX1 and original RX2 sample to RX2
+         //
+          switch(r) {
+            case 0:
+              left_sample_double_rx=left_sample_double;
+              right_sample_double_rx=right_sample_double;
+              break;
+            case 1:
+              left_sample_double_tx=left_sample_double;
+              right_sample_double_tx=right_sample_double;
+              add_div_iq_samples(receiver[0], left_sample_double_rx,right_sample_double_rx,left_sample_double_tx,right_sample_double_tx);
+              if (receivers >1) add_iq_samples(receiver[1], left_sample_double,right_sample_double);
+              break;
+          }
+        }
+        if (!diversity_enabled) {
+         //
+         // case: compiled without PURESIGNAL and not using DIVERSITY: Feed samples to RX1 and RX2
+         //
+          switch(r) {
+            case 0:
+              add_iq_samples(receiver[0], left_sample_double,right_sample_double);
+              break;
+            case 1:
+              if (receivers >1) add_iq_samples(receiver[1], left_sample_double,right_sample_double);
+              break;
+          }
+       }
 #endif
       }
 
@@ -845,22 +901,7 @@ void ozy_send_buffer() {
   int mode;
   int i;
   BAND *band;
-  int num_hpsdr_receivers;
-
-#ifdef PURESIGNAL
-    // 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.
-    num_hpsdr_receivers=3;
-    if (device == DEVICE_HERMES) num_hpsdr_receivers=4;
-    if (device == DEVICE_ANGELIA || device == DEVICE_ORION || device == DEVICE_ORION2) num_hpsdr_receivers=5;
-#else
-#if defined(RADIOBERRY) || defined(PI_SDR)
-       num_hpsdr_receivers = receivers;
-#else
-       num_hpsdr_receivers=RECEIVERS;
-#endif
-#endif
+  int num_hpsdr_receivers=how_many_receivers();
 
   output_buffer[SYNC0]=SYNC;
   output_buffer[SYNC1]=SYNC;
@@ -953,7 +994,6 @@ void ozy_send_buffer() {
     // Set ALEX RX1_ANT and RX1_OUT
     //
     i=receiver[0]->alex_antenna;
-#ifdef PURESIGNAL
     //
     // Upon TX, we might have to activate a different RX path for the
     // attenuated feedback signal. Use alex_antenna == 0, if
@@ -961,7 +1001,6 @@ void ozy_send_buffer() {
     // If feedback is to the second ADC, leave RX1 ANT settings untouched
     //
     if (isTransmitting() && transmitter->puresignal) i=receiver[PS_RX_FEEDBACK]->alex_antenna;
-#endif
     switch(i) {
       case 3:  // Alex: RX2 IN, ANAN: EXT1, ANAN7000: still uses internal feedback 
         output_buffer[C3]|=0x80;
@@ -1175,11 +1214,9 @@ void ozy_send_buffer() {
         }
         output_buffer[C2]=0x00;
         output_buffer[C2]|=linein_gain;
-#ifdef PURESIGNAL
         if(transmitter->puresignal) {
           output_buffer[C2]|=0x40;
         }
-#endif
         output_buffer[C3]=0x00;
         output_buffer[C4]=0x00;
   
@@ -1281,11 +1318,9 @@ 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 and TX frequency on transmit
         }
-#endif
         output_buffer[C3]=0x00;            // Alex2 filters
         output_buffer[C4]=0x00;            // Alex2 filters
         break;
diff --git a/radio.c b/radio.c
index cdc365d30c1a077ae0cb97a96cb4ef68a6e187ba..833f8fbd4298a934905347034058a319b36aa8e2 100644 (file)
--- a/radio.c
+++ b/radio.c
@@ -708,11 +708,9 @@ void start_radio() {
 
   calcDriveLevel();
 
-#ifdef PURESIGNAL
   if(transmitter->puresignal) {
     tx_set_ps(transmitter,transmitter->puresignal);
   }
-#endif
 
   if(protocol==NEW_PROTOCOL) {
     schedule_high_priority();
@@ -771,9 +769,7 @@ void radio_change_sample_rate(int rate) {
 #endif
         old_protocol_set_mic_sample_rate(rate);
         old_protocol_run();
-#ifdef PURESIGNAL
         tx_set_ps_sample_rate(transmitter,rate);
-#endif
       }
       break;
 #ifdef LIMESDR
@@ -803,18 +799,12 @@ static void rxtx(int state) {
 #endif
 
     for(i=0;i<receivers;i++) {
-#ifdef PURESIGNAL
-      // When using PURESIGNAL, delivery of RX samples
-      // to WDSP via fexchange0() comes to an abrupt stop
-      // since they go through add_ps_iq_samples()
-      // rather than add_iq_samples().
+      // Delivery of RX samples
+      // to WDSP via fexchange0() may come to an abrupt stop
+      // (especially with PURESIGNAL or DIVERSITY).
       // Therefore, wait for *all* receivers to complete
       // their slew-down before going TX.
       SetChannelState(receiver[i]->id,0,1);
-#else
-      // Original code: wait for WDSP only for the last RX
-      SetChannelState(receiver[i]->id,0,i==(receivers-1));
-#endif
       set_displaying(receiver[i],0);
       g_object_ref((gpointer)receiver[i]->panel);
       g_object_ref((gpointer)receiver[i]->panadapter);
@@ -929,18 +919,12 @@ void setTune(int state) {
     }
     if(state) {
       for(i=0;i<receivers;i++) {
-#ifdef PURESIGNAL
-        // When using PURESIGNAL, delivery of RX samples
-        // to WDSP via fexchange0() comes to an abrupt stop
-        // since they go through add_ps_iq_samples()
-        // rather than add_iq_samples().
+        // Delivery of RX samples
+        // to WDSP via fexchange0() may come to an abrupt stop
+        // (especially with PURESIGNAL or DIVERSITY)
         // Therefore, wait for *all* receivers to complete
         // their slew-down before going TX.
         SetChannelState(receiver[i]->id,0,1);
-#else
-       // wait only for the last RX
-        SetChannelState(receiver[i]->id,0,i==(receivers-1));
-#endif
         set_displaying(receiver[i],0);
         if(protocol==NEW_PROTOCOL) {
           schedule_high_priority();
diff --git a/radio.h b/radio.h
index 6be2ce2e0de8eaf808324ee9fd5364228c694f27..3575709c2d87a0b726d6fb7d087bdf445e1112ee 100644 (file)
--- a/radio.h
+++ b/radio.h
@@ -60,13 +60,16 @@ extern char property_path[];
 
 extern int region;
 
-// specify how many receivers
-#define MAX_RECEIVERS 8
+// specify how many receivers: for PURESIGNAL need two extra
 #define RECEIVERS 2
 #ifdef PURESIGNAL
+#define MAX_RECEIVERS (RECEIVERS+2)
 #define PS_TX_FEEDBACK (RECEIVERS)
 #define PS_RX_FEEDBACK (RECEIVERS+1)
+#else
+#define MAX_RECEIVERS RECEIVERS
 #endif
+#define MAX_DDC (RECEIVERS+2)
 
 extern RECEIVER *receiver[];
 extern RECEIVER *active_receiver;
index 38a59c980a33f12a536eaf9700263b3991096ffd..46f0e71e0aaf4aea91c943945acce13415cd785c 100644 (file)
@@ -331,6 +331,10 @@ fprintf(stderr,"receiver_restore_state: id=%d\n",rx->id);
   sprintf(name,"receiver.%d.adc",rx->id);
   value=getProperty(name);
   if(value) rx->adc=atoi(value);
+  //
+  // Do not specify a second ADC if there is only one
+  //
+  if (n_adc == 1) rx->adc=0;
   sprintf(name,"receiver.%d.filter_low",rx->id);
   value=getProperty(name);
   if(value) rx->filter_low=atoi(value);
@@ -756,8 +760,6 @@ fprintf(stderr,"create_pure_signal_receiver: id=%d buffer_size=%d\n",id,buffer_s
   RECEIVER *rx=malloc(sizeof(RECEIVER));
   rx->id=id;
 
-  // Note that fixed DDC/ADC settings are used in old_protocol and new_protocol.
-  rx->ddc=0;   // unused in old protocol
   rx->adc=0;
 
   rx->sample_rate=sample_rate;
@@ -786,7 +788,6 @@ fprintf(stderr,"create_pure_signal_receiver: id=%d buffer_size=%d\n",id,buffer_s
     }
   }
   // allocate buffers
-  rx->iq_sequence=0;
   rx->iq_input_buffer=malloc(sizeof(double)*2*rx->buffer_size);
   rx->audio_buffer=NULL;
   rx->audio_sequence=0L;
@@ -863,19 +864,9 @@ fprintf(stderr,"create_receiver: id=%d buffer_size=%d fft_size=%d pixels=%d fps=
   rx->id=id;
   switch(id) {
     case 0:
-      if(protocol==NEW_PROTOCOL && device==NEW_DEVICE_HERMES) {
-        rx->ddc=0;
-      } else {
-        rx->ddc=2;
-      }
       rx->adc=0;
       break;
     default:
-      if(protocol==NEW_PROTOCOL && device==NEW_DEVICE_HERMES) {
-        rx->ddc=1;
-      } else {
-        rx->ddc=3;
-      }
       switch(protocol) {
         case ORIGINAL_PROTOCOL:
           switch(device) {
@@ -902,7 +893,7 @@ fprintf(stderr,"create_receiver: id=%d buffer_size=%d fft_size=%d pixels=%d fps=
           break;
       }
   }
-fprintf(stderr,"create_receiver: id=%d default ddc=%d adc=%d\n",rx->id, rx->ddc, rx->adc);
+fprintf(stderr,"create_receiver: id=%d default adc=%d\n",rx->id, rx->adc);
   rx->sample_rate=48000;
   rx->buffer_size=buffer_size;
   rx->fft_size=fft_size;
@@ -999,7 +990,7 @@ fprintf(stderr,"create_receiver: id=%d output_samples=%d\n",rx->id,rx->output_sa
 
   // setup wdsp for this receiver
 
-fprintf(stderr,"create_receiver: id=%d after restore ddc=%d adc=%d\n",rx->id, rx->ddc, rx->adc);
+fprintf(stderr,"create_receiver: id=%d after restore adc=%d\n",rx->id, rx->adc);
 
 fprintf(stderr,"create_receiver: OpenChannel id=%d buffer_size=%d fft_size=%d sample_rate=%d\n",
         rx->id,
@@ -1063,11 +1054,6 @@ fprintf(stderr,"RXASetMP %d\n",rx->low_latency);
     SetRXAEQRun(rx->id, 0);
   }
 
-  // setup for diversity
-  create_divEXT(0,0,2,rx->buffer_size);
-  SetEXTDIVRotate(0, 2, &i_rotate[0], &q_rotate[0]);
-  SetEXTDIVRun(0,diversity_enabled);
-  
   receiver_mode_changed(rx);
   //set_mode(rx,vfo[rx->id].mode);
   //set_filter(rx,rx->filter_low,rx->filter_high);
@@ -1399,3 +1385,21 @@ void add_iq_samples(RECEIVER *rx, double i_sample,double q_sample) {
     rx->samples=0;
   }
 }
+
+//
+// Note that we sum such that the first channel has a factor of 1,
+// so we do not use but rather hard-code the values
+// i_rotate[0]=1 and q_rotate[0]=0.
+//
+void add_div_iq_samples(RECEIVER *rx, double i0, double q0, double i1, double q1) {
+  double i_sample, q_sample;
+  i_sample = i0 + i_rotate[1]*i1 - q_rotate[1]*q1;
+  q_sample = q0 + q_rotate[1]*i1 + i_rotate[1]*q1;
+  rx->iq_input_buffer[rx->samples*2]=i_sample;
+  rx->iq_input_buffer[(rx->samples*2)+1]=q_sample;
+  rx->samples=rx->samples+1;
+  if(rx->samples>=rx->buffer_size) {
+    full_rx_buffer(rx);
+    rx->samples=0;
+  }
+}
index 39bf084e1683160bdb01052e5d36d09b3f0fecd2..9954a78a0633d181392851c72901b391a38abce3 100644 (file)
@@ -56,7 +56,6 @@ typedef struct _receiver {
   int pixels;
   int samples;
   int output_samples;
-  long iq_sequence;
   double *iq_input_buffer;
   double *audio_output_buffer;
   unsigned char *audio_buffer;
@@ -158,6 +157,7 @@ extern void set_offset(RECEIVER *rx, long long offset);
 extern void set_deviation(RECEIVER *rx);
 
 extern void add_iq_samples(RECEIVER *rx, double i_sample,double q_sample);
+extern void add_div_iq_samples(RECEIVER *rx, double i0,double q0, double i1, double q1);
 
 extern void reconfigure_receiver(RECEIVER *rx,int height);
 
index 663d2f91a5b155bb055380fb7b450026c2dc0402..bc4cf61255c3bf845bea74ee202c2837dda87452 100644 (file)
@@ -329,7 +329,6 @@ static gboolean update_display(gpointer data) {
       }
     }
 #endif
-#ifdef PURESIGNAL
     // 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"
@@ -353,11 +352,8 @@ static gboolean update_display(gpointer data) {
       // if full == width, then we just copy all samples
       memcpy(tfp, rfp, width*sizeof(float));
     } else {
-#endif
       GetPixels(tx->id,0,tx->pixel_samples,&rc);
-#ifdef PURESIGNAL
     }
-#endif
     if(rc) {
       tx_panadapter_update(tx);
     }
@@ -582,12 +578,10 @@ fprintf(stderr,"create_transmitter: id=%d buffer_size=%d mic_sample_rate=%d mic_
   tx->low_latency=0;
 
   tx->twotone=0;
-#ifdef PURESIGNAL
   tx->puresignal=0;
   tx->feedback=0;
   tx->auto_on=0;
   tx->single_on=0;
-#endif
 
   tx->attenuation=0;
   tx->ctcss=0;
@@ -844,11 +838,7 @@ static void full_tx_buffer(TRANSMITTER *tx) {
     }
   }
 
-#ifdef PURESIGNAL
   if(tx->displaying && !(tx->puresignal && tx->feedback)) {
-#else
-  if(tx->displaying) {
-#endif
     Spectrum0(1, tx->id, 0, 0, tx->iq_output_buffer);
   }
 
@@ -1058,8 +1048,11 @@ void add_mic_sample(TRANSMITTER *tx,short mic_sample) {
 #endif
 }
 
-#ifdef PURESIGNAL
 void add_ps_iq_samples(TRANSMITTER *tx, double i_sample_tx,double q_sample_tx, double i_sample_rx, double q_sample_rx) {
+//
+// If not compiled for PURESIGNAL, make this a dummy function
+//
+#ifdef PURESIGNAL
   RECEIVER *tx_feedback=receiver[PS_TX_FEEDBACK];
   RECEIVER *rx_feedback=receiver[PS_RX_FEEDBACK];
 
@@ -1083,8 +1076,8 @@ void add_ps_iq_samples(TRANSMITTER *tx, double i_sample_tx,double q_sample_tx, d
     rx_feedback->samples=0;
     tx_feedback->samples=0;
   }
-}
 #endif
+}
 
 #ifdef FREEDV
 void add_freedv_mic_sample(TRANSMITTER *tx, short mic_sample) {
@@ -1119,8 +1112,8 @@ void tx_set_displaying(TRANSMITTER *tx,int state) {
   }
 }
 
-#ifdef PURESIGNAL
 void tx_set_ps(TRANSMITTER *tx,int state) {
+#ifdef PURESIGNAL
   if(state) {
     tx->puresignal=1;
     SetPSControl(tx->id, 0, 0, 1, 0);
@@ -1130,7 +1123,12 @@ void tx_set_ps(TRANSMITTER *tx,int state) {
     usleep(100000);
     tx->puresignal=0;
   }
+  if (protocol == NEW_PROTOCOL) {
+    schedule_high_priority();
+    schedule_receive_specific();
+  }
   g_idle_add(ext_vfo_update,NULL);
+#endif
 }
 
 void tx_set_twotone(TRANSMITTER *tx,int state) {
@@ -1157,9 +1155,10 @@ void tx_set_twotone(TRANSMITTER *tx,int state) {
 }
 
 void tx_set_ps_sample_rate(TRANSMITTER *tx,int rate) {
+#ifdef PURESIGNAL
   SetPSFeedbackRate (tx->id,rate);
-}
 #endif
+}
 
 //
 // This is the old key-down/key-up interface for iambic.c
index ed8d82f605c4ade7c848e2872f734cfe820b2dac..0defd5ff5cf7edf84405f10c276ee3eb11874aa7 100644 (file)
@@ -76,12 +76,10 @@ typedef struct _transmitter {
   int low_latency;
 
   int twotone;
-#ifdef PURESIGNAL
   int puresignal;
   int feedback;
   int auto_on;
   int single_on;
-#endif
 
   double ctcss_frequency;
   int ctcss;