From 4f80fe26221150c93359ba8b37857ddcfd7985af Mon Sep 17 00:00:00 2001 From: c vw Date: Wed, 24 Jul 2019 18:35:03 +0200 Subject: [PATCH] a) P2 PURESIGNAL for HERMES, b) DIVERSITY, c) CW for P2, d) HPSDR Simulator: now with man-made noise to test DIVERSITY --- Makefile | 4 +- Makefile.mac | 4 +- diversity_menu.c | 9 +- hpsdrsim.c | 115 +++-------- new_menu.c | 7 +- new_protocol.c | 521 +++++++++++++++++++++++++++++------------------ newhpsdrsim.c | 131 +++++------- old_protocol.c | 145 ++++++++----- radio.c | 28 +-- radio.h | 7 +- receiver.c | 44 ++-- receiver.h | 2 +- transmitter.c | 27 ++- transmitter.h | 2 - 14 files changed, 556 insertions(+), 490 deletions(-) diff --git a/Makefile b/Makefile index 652f9bb..f3a8cf4 100644 --- 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 diff --git a/Makefile.mac b/Makefile.mac index efff0b6..e3fc050 100644 --- a/Makefile.mac +++ b/Makefile.mac @@ -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 diff --git a/diversity_menu.c b/diversity_menu.c index fc60b47..458143a 100644 --- a/diversity_menu.c +++ b/diversity_menu.c @@ -27,7 +27,7 @@ #include "new_menu.h" #include "diversity_menu.h" #include "radio.h" -#include +#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) { diff --git a/hpsdrsim.c b/hpsdrsim.c index f12ac22..0f5e31a 100644 --- a/hpsdrsim.c +++ b/hpsdrsim.c @@ -75,50 +75,11 @@ #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= 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<= 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 + diff --git a/new_menu.c b/new_menu.c index 7365ae3..ea9120e 100644 --- a/new_menu.c +++ b/new_menu.c @@ -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); diff --git a/new_protocol.c b/new_protocol.c index ec1ad8a..13fcda4 100644 --- a/new_protocol.c +++ b/new_protocol.c @@ -66,6 +66,19 @@ #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;iddc; -#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;iinfo.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;rddc; - 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;iid; + 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;iddc; - receive_specific_buffer[5]|=receiver[i]->dither<random<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<random<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;iinfo.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 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;imax_sample0) { - max_sample0=leftsample0; - } - if(leftsample1max_sample1) { - max_sample1=leftsample1; - } - } -#endif } - } -#endif static void process_command_response() { diff --git a/newhpsdrsim.c b/newhpsdrsim.c index 132016a..3cb1370 100644 --- a/newhpsdrsim.c +++ b/newhpsdrsim.c @@ -9,36 +9,10 @@ #include #include -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> (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; } - - diff --git a/old_protocol.c b/old_protocol.c index 01c300d..38b16c6 100644 --- a/old_protocol.c +++ b/old_protocol.c @@ -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 cdc365d..833f8fb 100644 --- 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;iid,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;iid,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 6be2ce2..3575709 100644 --- 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; diff --git a/receiver.c b/receiver.c index 38a59c9..46f0e71 100644 --- a/receiver.c +++ b/receiver.c @@ -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; + } +} diff --git a/receiver.h b/receiver.h index 39bf084..9954a78 100644 --- a/receiver.h +++ b/receiver.h @@ -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); diff --git a/transmitter.c b/transmitter.c index 663d2f9..bc4cf61 100644 --- a/transmitter.c +++ b/transmitter.c @@ -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 diff --git a/transmitter.h b/transmitter.h index ed8d82f..0defd5f 100644 --- a/transmitter.h +++ b/transmitter.h @@ -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; -- 2.45.2