#
#############################################################################
-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
#
#############################################################################
-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
#include "new_menu.h"
#include "diversity_menu.h"
#include "radio.h"
-#include <wdsp.h>
+#include "new_protocol.h"
static GtkWidget *parent_window=NULL;
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) {
#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.
*/
/*
* 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
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;
#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;
* 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;}
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;
}
}
- 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();
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;
// 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;
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)
// 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
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)
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;
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
}
// 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;
{
}
#endif
+
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);
#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;
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;
#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
// 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;
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);
}
*/
+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
}
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");
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);
}
static void new_protocol_high_priority() {
- int i, r;
+ int i;
BAND *band;
int xvtr;
long long rxFrequency;
// 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
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;
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;
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;
}
high_priority_sequence++;
+ update_action_table();
pthread_mutex_unlock(&hi_prio_mutex);
}
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.
// 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) {
}
rx_specific_sequence++;
+ update_action_table();
pthread_mutex_unlock(&rx_spec_mutex);
}
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
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__
}
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]);
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;
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)
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++) {
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;
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)
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) {
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);
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() {
#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
// 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];
}
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];
return NULL;
}
+ seqnum=0;
while(run) {
rc = recvfrom(sock, buffer, 1444, 0,(struct sockaddr *)&addr, &lenaddr);
if (rc < 0 && errno != EAGAIN) {
}
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];
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;
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) {
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;
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) {
long myrate;
int sync,size;
int myadc, syncadc;
- int ps=0;
int rxptr;
+ int divptr;
int decimation;
struct timespec delay;
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;
}
// ADC2 : original TX signal
//
- ps=(sync && (rxrate[myadc]==192) && ptt && (syncadc == adc));
p=buffer;
*p++ =(seqnum >> 24) & 0xFF;
*p++ =(seqnum >> 16) & 0xFF;
// 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;
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;
break;
}
seqnum++;
- usleep(50000); // wait 50 msec
+ usleep(50000); // wait 50 msec then send again
}
close(sock);
return NULL;
}
//
-// The microphone thread generates
-// a two-tone signal
+// The microphone thread just sends silence
//
void *mic_thread(void *data) {
int sock;
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) {
*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) {
close(sock);
return NULL;
}
-
-
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;
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
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) {
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
}
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;
// 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
// 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;
}
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;
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;
calcDriveLevel();
-#ifdef PURESIGNAL
if(transmitter->puresignal) {
tx_set_ps(transmitter,transmitter->puresignal);
}
-#endif
if(protocol==NEW_PROTOCOL) {
schedule_high_priority();
#endif
old_protocol_set_mic_sample_rate(rate);
old_protocol_run();
-#ifdef PURESIGNAL
tx_set_ps_sample_rate(transmitter,rate);
-#endif
}
break;
#ifdef LIMESDR
#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);
}
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();
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;
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);
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;
}
}
// 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;
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) {
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;
// 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,
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);
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;
+ }
+}
int pixels;
int samples;
int output_samples;
- long iq_sequence;
double *iq_input_buffer;
double *audio_output_buffer;
unsigned char *audio_buffer;
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);
}
}
#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"
// 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);
}
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;
}
}
-#ifdef PURESIGNAL
if(tx->displaying && !(tx->puresignal && tx->feedback)) {
-#else
- if(tx->displaying) {
-#endif
Spectrum0(1, tx->id, 0, 0, tx->iq_output_buffer);
}
#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];
rx_feedback->samples=0;
tx_feedback->samples=0;
}
-}
#endif
+}
#ifdef FREEDV
void add_freedv_mic_sample(TRANSMITTER *tx, short mic_sample) {
}
}
-#ifdef PURESIGNAL
void tx_set_ps(TRANSMITTER *tx,int state) {
+#ifdef PURESIGNAL
if(state) {
tx->puresignal=1;
SetPSControl(tx->id, 0, 0, 1, 0);
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) {
}
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
int low_latency;
int twotone;
-#ifdef PURESIGNAL
int puresignal;
int feedback;
int auto_on;
int single_on;
-#endif
double ctcss_frequency;
int ctcss;