#define DEVICE_ANGELIA 4
#define DEVICE_ORION 5
#define DEVICE_HERMES_LITE 6
-// 8000DLE uses 10 as the device type in old protocol
+// ANAN 7000DLE and 8000DLE uses 10 as the device type in old protocol
#define DEVICE_ORION2 10
// Newer STEMlab hpsdr emulators use 100 instead of 1
#define DEVICE_STEMLAB 100
* This is the "Layer-1" for Apple Macintosh.
*
* This file implements the function register_midi_device,
- * which is called with the name of a supported MIDI device and
- * the number of characters in the name that must be equal to
- * the name of the MIDI device as known in the operating system.
+ * which is called with the name of a supported MIDI device.
+ * This name may be truncated: For example, the call
+ * register_midi_device("COMPANY MIDI")
+ * will accept both "COMPANY MIDI X" and "COMPANY MIDI Y" devices.
*
- * For example, the call
- * register_midi_device("COMPANY MIDI X",13)
- * will also use a MIDI device named "COMPANY MIDI Y".
+ * If more than one MIDI device matches the name, the LAST ONE
+ * found will be taken. This may not be predictable, so it is
+ * better to say that one of the matching MIDI devices will be taken.
+ * It is easy to change the code such that ALL devices matching the
+ * name will be taken. But who cares? Normally there will only be a
+ * single MIDI controller connected to the computer running the SDR
+ * program.
+ *
+ * The name is actually specified by the user in the midi.inp file
+ * (see midi2.c)
*
* This file must generate calls to Layer-2 NewMidiEvent().
* Some type of messages are not consideres (pressure change, etc.),
#ifdef __APPLE__
+/*
+ * For MacOS, things are easy:
+ * The OS takes care of everything, we only have to register a callback
+ * routine.
+ */
+
#include <Carbon/Carbon.h>
#include <CoreMIDI/MIDIServices.h>
//
// MIDI callback function
+// called by MacOSX when data from the specified MIDI device arrives.
+// We process *all* data but only generate calls to layer-2 for Note On/Off
+// and ControllerChange events.
//
static void ReadMIDIdevice(const MIDIPacketList *pktlist, void *refCon, void *connRefCon) {
int i,j,k,command,chan;
switch (command & 0xF0) {
case 0x80: // Note off
NewMidiEvent(MIDI_NOTE, chan, packet->data[i+1], 0);
- fprintf(stderr,"NOTE OFF: Note=%d Chan=%d Vel=%d\n", packet->data[i+1], chan, packet->data[i+2]);
+ //fprintf(stderr,"NOTE OFF: Note=%d Chan=%d Vel=%d\n", packet->data[i+1], chan, packet->data[i+2]);
i +=3;
break;
case 0x90: // Note on
NewMidiEvent(MIDI_NOTE, chan, packet->data[i+1], 1);
- fprintf(stderr,"NOTE ON : Note=%d Chan=%d Vel=%d\n", packet->data[i+1], chan, packet->data[i+2]);
+ //fprintf(stderr,"NOTE ON : Note=%d Chan=%d Vel=%d\n", packet->data[i+1], chan, packet->data[i+2]);
i +=3;
break;
case 0xA0: // Polyph. Press.
break;
case 0xB0: // Control change
NewMidiEvent(MIDI_CTRL, chan, packet->data[i+1], packet->data[i+2]);
- fprintf(stderr,"CtlChang: Ctrl=%d Chan=%d Val=%d\n", packet->data[i+1], chan, packet->data[i+2]);
+ //fprintf(stderr,"CtlChang: Ctrl=%d Chan=%d Val=%d\n", packet->data[i+1], chan, packet->data[i+2]);
i +=3;
break;
case 0xC0: // Program change
break;
case 0xE0: // Pitch Bend
NewMidiEvent(MIDI_PITCH, chan, 0, packet->data[i+1] + 128*packet->data[i+2]);
- fprintf(stderr,"Pitch : val =%d Chan=%d\n", packet->data[i+1] + 128*packet->data[i+2], chan);
+ //fprintf(stderr,"Pitch : val =%d Chan=%d\n", packet->data[i+1] + 128*packet->data[i+2], chan);
i +=3;
break;
case 0xF0:
FoundMIDIref=i;
fprintf(stderr,"MIDI device found and selected: >>>%s<<<\n", name);
} else {
- fprintf(stderr,"MIDI device we were looking for : >>>%s<<<\n", myname);
fprintf(stderr,"MIDI device found BUT NOT SELECTED: >>>%s<<<\n", name);
}
}
DoTheMidi(desc->action, desc->type, new);
}
break;
- default:
+ case EVENT_NONE:
break;
}
break;
break;
}
break;
- default:
+ case COMPRESS:
+ case ACTION_NONE:
fprintf(stderr,"Unimplemented in DoTheMidi: A=%d T=%d val=%d\n", action, type, val);
break;
}
#include <string.h>
#include <errno.h>
#include <fcntl.h>
+#include <sys/select.h>
#include "discovered.h"
#include "discovery.h"
struct sockaddr_in to_addr={0};
int flags;
struct timeval tv;
+ int optval;
+ socklen_t optlen;
+ fd_set fds;
+ unsigned char buffer[1032];
+ int i, len;
if (iface == NULL) {
//
return;
}
//
- // We make a time-out of 3 secs, otherwise we might "hang" in connect()
+ // Here I tried a bullet-proof approach to connect() such that the program
+ // does not "hang" under any circumstances.
+ // - First, one makes the socket non-blocking. Then, the connect() will
+ // immediately return with error EINPROGRESS.
+ // - Then, one uses select() to look for *writeability* and check
+ // the socket error if everything went right. Since one calls select()
+ // with a time-out, one either succeed within this time or gives up.
+ // - Do not forget to make the socket blocking again.
//
+ // Step 1. Make socket non-blocking and connect()
flags=fcntl(discovery_socket, F_GETFL, 0);
fcntl(discovery_socket, F_SETFL, flags | O_NONBLOCK);
+ rc=connect(discovery_socket, (const struct sockaddr *)&to_addr, sizeof(to_addr));
+ if ((errno != EINPROGRESS) && (rc < 0)) {
+ perror("discover: connect() failed for TCP discovery_socket:");
+ close(discovery_socket);
+ return;
+ }
+ // Step 2. Use select to wait for the connection
tv.tv_sec=3;
tv.tv_usec=0;
- setsockopt(discovery_socket, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(tv));
-
-
- if (connect(discovery_socket, (const struct sockaddr *)&to_addr, sizeof(to_addr)) < 0) {
- perror("discover: connect() failed for TCP discovery_socket:");
+ FD_ZERO(&fds);
+ FD_SET(discovery_socket, &fds);
+ rc=select(discovery_socket+1, NULL, &fds, NULL, &tv);
+ if (rc < 0) {
+ perror("discover: select() failed on TCP discovery_socket:");
+ close(discovery_socket);
+ return;
+ }
+ // If no connection occured, return
+ if (rc == 0) {
+ // select timed out
+ fprintf(stderr,"discover: select() timed out on TCP discovery socket\n");
close(discovery_socket);
return;
}
+ // Step 3. select() succeeded. Check success of connect()
+ optlen=sizeof(int);
+ rc=getsockopt(discovery_socket, SOL_SOCKET, SO_ERROR, &optval, &optlen);
+ if (rc < 0) {
+ // this should very rarely happen
+ perror("discover: getsockopt() failed on TCP discovery_socket:");
+ close(discovery_socket);
+ return;
+ }
+ if (optval != 0) {
+ // connect did not succeed
+ fprintf(stderr,"discover: connect() on TCP socket did not succeed\n");
+ close(discovery_socket);
+ return;
+ }
+ // Step 4. reset the socket to normal (blocking) mode
+ fcntl(discovery_socket, F_SETFL, flags & ~O_NONBLOCK);
} else {
strcpy(interface_name,iface->ifa_name);
to_addr.sin_port=htons(DISCOVERY_PORT);
to_addr.sin_addr.s_addr=htonl(INADDR_BROADCAST);
}
- int optval = 1;
+ optval = 1;
setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
// send discovery packet
// If this is a TCP connection, send a "long" packet
- unsigned char buffer[1032];
- int len=63;
+ len=63;
if (iface == NULL) len=1032;
buffer[0]=0xEF;
buffer[1]=0xFE;
buffer[2]=0x02;
- int i;
for(i=3;i<len;i++) {
buffer[i]=0x00;
}
#define SPEED_384K 0x03
#define MODE_CLASS_E 0x01
#define MODE_OTHERS 0x00
-#define ALEX_ATTENUATION_0DB 0x00
-#define ALEX_ATTENUATION_10DB 0x01
-#define ALEX_ATTENUATION_20DB 0x02
-#define ALEX_ATTENUATION_30DB 0x03
#define LT2208_GAIN_OFF 0x00
#define LT2208_GAIN_ON 0x04
#define LT2208_DITHER_OFF 0x00
#ifdef PURESIGNAL
- nreceivers=(RECEIVERS*2)+1;
+ // DL1YCF:
+ // 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.
+ nreceivers=3;
+ if (device == DEVICE_HERMES) nreceivers=4;
+ if (device == DEVICE_ANGELIA || device == DEVICE_ORION || device == DEVICE_ORION2) nreceivers=5;
#else
#if defined(RADIOBERRY) || defined(PI_SDR)
nreceivers = receivers;
output_buffer[SYNC2]=SYNC;
if(metis_offset==8) {
+ //
+ // Every second packet is a "C0=0" packet
+ //
output_buffer[C0]=0x00;
output_buffer[C1]=0x00;
switch(active_receiver->sample_rate) {
output_buffer[C2]|=band->OCrx<<1;
}
-// TODO - add Alex Antenna
output_buffer[C3] = (receiver[0]->alex_attenuation) & 0x03; // do not set higher bits
if(active_receiver->random) {
output_buffer[C3]|=LT2208_RANDOM_ON;
output_buffer[C3]|=LT2208_GAIN_ON;
}
- switch(receiver[0]->alex_antenna) {
+ i=receiver[0]->alex_antenna;
+#ifdef PURESIGNAL
+ //
+ // Upon TX, we might have to activate a different RX path for the
+ // attenuated feedback signal. Use feedback_antenna == 0, if
+ // the feedback signal is routed automatically/internally (e.g.
+ // ANAN-7000DLE, when using the internal feedback path).
+ //
+ if (isTransmitting() && transmitter->puresignal) i=receiver[PS_RX_FEEDBACK]->feedback_antenna;
+#endif
+ switch(i) {
case 0: // ANT 1
- break;
case 1: // ANT 2
- break;
case 2: // ANT 3
break;
- case 3: // EXT 1
- //output_buffer[C3]|=0xA0;
+ case 3: // Alex: RX2 IN, ANAN: EXT1, ANAN7000: EXT
output_buffer[C3]|=0xC0;
break;
- case 4: // EXT 2
- //output_buffer[C3]|=0xC0;
+ case 4: // Alex: RX1 IN, ANAN: EXT2, ANAN7000: RX BYPASS
output_buffer[C3]|=0xA0;
break;
case 5: // XVTR
// TODO - add Alex TX relay, duplex, receivers Mercury board frequency
output_buffer[C4]=0x04; // duplex
#ifdef PURESIGNAL
- nreceivers=(RECEIVERS*2)-1;
- nreceivers+=1; // for PS TX Feedback
+ // DL1YCF: see comment on "nreceivers" above. The number is reduced by 1 here
+ nreceivers=2;
+ if (device == DEVICE_HERMES) nreceivers=3;
+ if (device == DEVICE_ANGELIA || device == DEVICE_ORION || device == DEVICE_ORION2) nreceivers=4;
#else
#ifdef RADIOBERRY
nreceivers = receivers-1;
#endif
#endif
+ // 0 ... 7 maps on 1 ... 8 receivers
output_buffer[C4]|=nreceivers<<3;
if(isTransmitting()) {
}
}
} else {
+ //
+ // metis_offset !=8: send "command" C&C packets in round-robin
+ // using the value of "command" from 1 to 10,
+ // and "command==2" packets are repeated for each RX
switch(command) {
case 1: // tx frequency
output_buffer[C0]=0x02;
break;
case 2: // rx frequency
#ifdef PURESIGNAL
- nreceivers=(RECEIVERS*2)+1;
+ // DL1YCF: see comment on "nreceivers" above.
+ nreceivers=3;
+ if (device == DEVICE_HERMES) nreceivers=4;
+ if (device == DEVICE_ANGELIA || device == DEVICE_ORION || device == DEVICE_ORION2) nreceivers=5;
#else
#ifdef RADIOBERRY
nreceivers = receivers;
}
#endif
output_buffer[C3]=0x00;
+ output_buffer[C4]=0x00;
if(radio->device==DEVICE_HERMES || radio->device==DEVICE_ANGELIA || radio->device==DEVICE_ORION || radio->device==DEVICE_ORION2) {
- output_buffer[C4]=0x20|adc_attenuation[receiver[0]->adc];
+ // DL1YCF: if attenuation is zero, then disable attenuator
+ i = adc_attenuation[receiver[0]->adc] & 0x1F;
+ if (i >0) output_buffer[C4]=0x20| i;
} else {
#ifdef RADIOBERRY
- int att = 63 - rx_gain_slider[active_receiver->adc];
+ int att = 63 - rx_gain_slider[active_receiver->adc];
output_buffer[C4]=0x20|att;
-#else
- output_buffer[C4]=0x00;
#endif
}
break;
case 5:
- // need to add adc 2 and 3 attenuation
output_buffer[C0]=0x16;
output_buffer[C1]=0x00;
if(receivers==2) {
if(radio->device==DEVICE_HERMES || radio->device==DEVICE_ANGELIA || radio->device==DEVICE_ORION || radio->device==DEVICE_ORION2) {
- output_buffer[C1]=0x20|adc_attenuation[receiver[1]->adc];
+ // DL1YCF: if attenuation is zero, then disable attenuator
+ i = adc_attenuation[receiver[1]->adc] & 0x1F;
+ if (i > 0) output_buffer[C1]=0x20|i;
}
}
- output_buffer[C2]=0x00;
+ output_buffer[C2]=0x00; // ADC3 attenuator disabled.
if(cw_keys_reversed!=0) {
output_buffer[C2]|=0x40;
}
output_buffer[C0]=0x1C;
output_buffer[C1]=0x00;
#ifdef PURESIGNAL
- output_buffer[C1]|=receiver[0]->adc;
- output_buffer[C1]|=(receiver[0]->adc<<2);
- output_buffer[C1]|=receiver[1]->adc<<4;
- output_buffer[C1]|=(receiver[1]->adc<<6);
+
+ // The whole setup here implicitly assumes
+ // that receiver[0]->adc is 0 and receiver[1]->adc is 1
+
+ // This is the correct setting for DEVICE_METIS and DEVICE_HERMES
+ output_buffer[C1]|=receiver[0]->adc; // RX1 bound to ADC0
+ output_buffer[C1]|=(receiver[0]->adc<<2); // RX2 bound to ADC0
+ output_buffer[C1]|=receiver[1]->adc<<4; // RX3 bound to ADC1
+
+ // DL1YCF:
+ // For Orion, Angelia and OrionMk2 RX4 must show the FeedBack signal.
+ // In most cases this is routed back to RX1 so we need ADC0 for RX4
+ // Since I could test this only on my ANAN7000, I changed to code
+ // to associate RX4 with ADC0 only on Orion2 -- but I guess this will
+ // be necessary for other SDRs as well.
+
+ if (device == DEVICE_ORION2) {
+ output_buffer[C1]|=(receiver[0]->adc<<6); // This works on ANAN7000
+ } else {
+ output_buffer[C1]|=(receiver[1]->adc<<6); // Does this work for somebody?
+ }
output_buffer[C2]=0x00;
if(transmitter->puresignal) {
+ // This should not be necessary since RX5 is hard-wired to the TX DAC on TX
output_buffer[C2]|=receiver[2]->adc;
}
#else
output_buffer[C0]=0x24;
output_buffer[C1]=0x00;
if(isTransmitting()) {
- output_buffer[C1]|=0x80; // ground RX1 on transmit
+ output_buffer[C1]|=0x80; // ground RX2 on transmit, bit0-6 are Alex2 filters
}
output_buffer[C2]=0x00;
if(receiver[0]->alex_antenna==5) { // XVTR
- output_buffer[C2]=0x02;
+ output_buffer[C2]=0x02; // Alex2 XVTR enable
}
- output_buffer[C3]=0x00;
- output_buffer[C4]=0x00;
+ output_buffer[C3]=0x00; // Alex2 filters
+ output_buffer[C4]=0x00; // Alex2 filters
break;
}
switch(state) {
case 0:
if(newcal && (info[4]>181 || (info[4]<=128 && transmitter->attenuation>0))) {
- ddb= 20.0 * log10((double)info[4]/152.293);
- if(isnan(ddb)) {
- // this means feedback lvl is < 1, switch OFF attenuation
- ddb=-100.0;
- }
+ if (info[4] > 0) {
+ ddb= 20.0 * log10((double)info[4]/152.293);
+ } else {
+ // This happens when the "Drive" slider is moved to zero
+ ddb= -100.0;
+ }
new_att=transmitter->attenuation + (int)ddb;
// keep new value of attenuation in allowed range
if (new_att < 0) new_att= 0;
return TRUE;
}
+static void ps_ant_cb(GtkWidget *widget, gpointer data) {
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
+ receiver[PS_RX_FEEDBACK]->feedback_antenna = (int) (uintptr_t) data;
+ }
+}
+
static void enable_cb(GtkWidget *widget, gpointer data) {
g_idle_add(ext_tx_set_ps,(gpointer)(long)gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)));
}
set_button_text_color(twotone_b,"red");
}
-
col++;
GtkWidget *auto_b=gtk_check_button_new_with_label("Auto Attenuate");
row++;
col=0;
+ GtkWidget *ps_ant_label=gtk_label_new("PS FeedBk ANT:");
+ gtk_widget_show(ps_ant_label);
+ gtk_grid_attach(GTK_GRID(grid), ps_ant_label, col, row, 1, 1);
+ col++;
+
+ GtkWidget *ps_ant_auto=gtk_radio_button_new_with_label(NULL,"AUTO");
+ gtk_widget_show(ps_ant_auto);
+ gtk_grid_attach(GTK_GRID(grid), ps_ant_auto, col, row, 1, 1);
+ g_signal_connect(ps_ant_auto,"toggled", G_CALLBACK(ps_ant_cb), (gpointer) (long) 0);
+ col++;
+
+ GtkWidget *ps_ant_ext1=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ps_ant_auto),"EXT1");
+ gtk_widget_show(ps_ant_ext1);
+ gtk_grid_attach(GTK_GRID(grid), ps_ant_ext1, col, row, 1, 1);
+ g_signal_connect(ps_ant_ext1,"toggled", G_CALLBACK(ps_ant_cb), (gpointer) (long) 3);
+ col++;
+
+ GtkWidget *ps_ant_ext2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ps_ant_auto),"EXT2");
+ gtk_widget_show(ps_ant_ext2);
+ gtk_grid_attach(GTK_GRID(grid), ps_ant_ext2, col, row, 1, 1);
+ g_signal_connect(ps_ant_ext2,"toggled", G_CALLBACK(ps_ant_cb), (gpointer) (long) 4);
+
+ row++;
+ col=0;
feedback_l=gtk_label_new("Feedback Lvl");
gtk_widget_show(feedback_l);
gtk_grid_attach(GTK_GRID(grid),feedback_l,col,row,1,1);
}
static gboolean menu_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
- new_menu(top_window);
+ new_menu();
return TRUE;
}
level=(int)(actual_volts*255.0);
+#ifdef __APPLE__
+#ifdef PURESIGNAL
+//
+// DL1YCF: I do not know exactly why: if the drive level
+// is set to zero while PS is active, the program
+// reproducably crashes when the drive is set from 1 Watt
+// to 0 Watt, possibly a division by zero or the evaluation
+// of a logarithm within WDSP.
+// QuickAndDirty Fix: use "1" as minimum drive level
+// which corresponds to a fraction of a Watt.
+//
+ if (level < 1) level=1;
+#endif
+#endif
+
//fprintf(stderr,"calcLevel: %f calib=%f level=%d\n",d, gbb, level);
return level;
}
for(i=0;i<receivers;i++) {
receiver_save_state(receiver[i]);
}
+#ifdef PURESIGNAL
+ // There is little to save.
+ // An exception is the feedback_antenna stored in PS_RX_FEEDBACK
+ receiver_save_state(receiver[PS_RX_FEEDBACK]);
+#endif
transmitter_save_state(transmitter);
#ifdef FREEDV
freedv_save_state();
int x, y;
GdkModifierType state;
RECEIVER *rx=(RECEIVER *)data;
- if(!making_active) {
+ // DL1YCF: if !pressed, we may come from the destruction
+ // of a menu, and should not move the VFO.
+ if(!making_active && pressed) {
gdk_window_get_device_position (event->window,
event->device,
&x,
&y,
&state);
- // DL1YCF added a pair of () to fix an error
- if(((state & GDK_BUTTON1_MASK) == GDK_BUTTON1_MASK) || pressed) {
+ if(state & GDK_BUTTON1_MASK) {
int moved=last_x-x;
vfo_move((long long)((float)moved*rx->hz_per_pixel));
last_x=x;
sprintf(value,"%d",rx->waterfall_automatic);
setProperty(name,value);
+#ifdef PURESIGNAL
+ sprintf(name,"receiver.%d.feedback_antenna",rx->id);
+ sprintf(value,"%d",rx->feedback_antenna);
+ setProperty(name,value);
+#endif
sprintf(name,"receiver.%d.alex_antenna",rx->id);
sprintf(value,"%d",rx->alex_antenna);
setProperty(name,value);
sprintf(name,"receiver.%d.sample_rate",rx->id);
value=getProperty(name);
if(value) rx->sample_rate=atoi(value);
-#ifdef STEMLAB_FIX
- // HPSDR apps on the RedPitay have hard-wired connections
- // that should not be changed
- fprintf(stderr,"STEMLAB: ignoring ADC settings for RX%d\n",rx->id);
-#else
sprintf(name,"receiver.%d.adc",rx->id);
value=getProperty(name);
if(value) rx->adc=atoi(value);
-#endif
sprintf(name,"receiver.%d.filter_low",rx->id);
value=getProperty(name);
if(value) rx->filter_low=atoi(value);
value=getProperty(name);
if(value) rx->waterfall_automatic=atoi(value);
+#ifdef PURESIGNAL
+ sprintf(name,"receiver.%d.feedback_antenna",rx->id);
+ value=getProperty(name);
+ if(value) rx->feedback_antenna=atoi(value);
+#endif
sprintf(name,"receiver.%d.alex_antenna",rx->id);
value=getProperty(name);
if(value) rx->alex_antenna=atoi(value);
rx->volume=0.0;
+ rx->squelch_enable=0;
+ rx->squelch=0;
+
rx->dither=0;
rx->random=0;
rx->preamp=0;
rx->nr2_npe_method=0;
rx->nr2_ae=1;
+ rx->feedback_antenna=0;
rx->alex_antenna=0;
rx->alex_attenuation=0;
rx->low_latency=0;
+ // not much to be restored, except feedback_antenna
+ if (id == PS_RX_FEEDBACK) receiver_restore_state(rx);
+
int result;
XCreateAnalyzer(rx->id, &result, 262144, 1, 1, "");
if(result != 0) {
}
break;
}
-#ifdef STEMLAB_FIX
-//
-// RedPitaya based HPSDR apps have hard-wired adc settings
-//
- if (id == 1) rx->adc=1;
-#endif
}
fprintf(stderr,"create_receiver: id=%d default ddc=%d adc=%d\n",rx->id, rx->ddc, rx->adc);
rx->sample_rate=48000;
rx->nr2_npe_method=0;
rx->nr2_ae=1;
+#ifdef PURESIGNAL
+ rx->feedback_antenna=0;
+#endif
+
BAND *b=band_get_band(vfo[rx->id].band);
rx->alex_antenna=b->alexRxAntenna;
rx->alex_attenuation=b->alexAttenuation;
int alex_antenna;
int alex_attenuation;
+#ifdef PURESIGNAL
+ // indicates to which ALEX RX antenna the attenuated feedback
+ // signal from the PA goes. The coding is the same as for alex_antenna,
+ // except that this connector is only used when transmitting.
+ int feedback_antenna;
+#endif
+
int filter_low;
int filter_high;
static void dither_cb(GtkWidget *widget, gpointer data) {
active_receiver->dither=active_receiver->dither==1?0:1;
- update_att_preamp();
}
static void random_cb(GtkWidget *widget, gpointer data) {
static void preamp_cb(GtkWidget *widget, gpointer data) {
active_receiver->preamp=active_receiver->preamp==1?0:1;
- update_att_preamp();
}
static void alex_att_cb(GtkWidget *widget, gpointer data) {
break;
#endif
}
-
+
+ //
// The CHARLY25 board (with RedPitaya) has no support for dither or random,
- // so those are left out. PreAmps and Alex Attenuator are controlled via sliders.
+ // so those are left out. For Charly25, PreAmps and Alex Attenuator are controlled via
+ // the sliders menu.
+ // On SDRs other than CHARLY25, preamps or Alex attenuators may be present or not, and we
+ // do not try to find out whether they are. This would overload the code, and we then
+ // also must have a menu to check e.g. which ANAN model is actually present.
+ // Instead, we offer these checkboxes in either case and must rely on the user
+ // not playing around with features that are not there.
+ //
if (filter_board != CHARLY25) {
switch(protocol) {
case ORIGINAL_PROTOCOL:
gtk_grid_attach(GTK_GRID(grid),random_b,x,3,1,1);
g_signal_connect(random_b,"toggled",G_CALLBACK(random_cb),NULL);
- if((protocol==ORIGINAL_PROTOCOL && device==DEVICE_METIS) ||
-#ifdef USBOZY
- (protocol==ORIGINAL_PROTOCOL && device==DEVICE_OZY) ||
-#endif
- (protocol==NEW_PROTOCOL && device==NEW_DEVICE_ATLAS)) {
+ GtkWidget *preamp_b=gtk_check_button_new_with_label("Preamp");
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (preamp_b), active_receiver->preamp);
+ gtk_grid_attach(GTK_GRID(grid),preamp_b,x,4,1,1);
+ g_signal_connect(preamp_b,"toggled",G_CALLBACK(preamp_cb),NULL);
- GtkWidget *preamp_b=gtk_check_button_new_with_label("Preamp");
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (preamp_b), active_receiver->preamp);
- gtk_grid_attach(GTK_GRID(grid),preamp_b,x,4,1,1);
- g_signal_connect(preamp_b,"toggled",G_CALLBACK(preamp_cb),NULL);
- }
GtkWidget *alex_att_label=gtk_label_new("Alex Attenuator");
gtk_grid_attach(GTK_GRID(grid), alex_att_label, x, 5, 1, 1);
GtkWidget *last_alex_att_b = NULL;
}
}
+ // Number of ADCs.
int n_adc=1;
switch(protocol) {
case ORIGINAL_PROTOCOL:
switch(device) {
case DEVICE_METIS:
- n_adc=1; // FIX for multiple Mercury cards
+ n_adc=1; // No support for multiple MERCURY cards on a single ATLAS bus.
break;
case DEVICE_HERMES:
case DEVICE_HERMES_LITE:
case NEW_PROTOCOL:
switch(device) {
case NEW_DEVICE_ATLAS:
- n_adc=1; // FIX for multiple Mercury cards
+ n_adc=1; // No support for multiple MERCURY cards on a single ATLAS bus.
break;
case NEW_DEVICE_HERMES:
case NEW_DEVICE_HERMES2:
break;
}
+ // If there is more than one ADC, let the user associate an ADC
+ // with the current receiver. Note: for PURESIGNAL, ADC0 has to
+ // be associated with the first receiver.
if(n_adc>1) {
for(i=0;i<n_adc;i++) {
sprintf(label,"ADC-%d",i);
gtk_combo_box_set_active_id(GTK_COMBO_BOX(c25_att_combobox), id);
sprintf(id, "%d", active_receiver->preamp + active_receiver->dither);
gtk_combo_box_set_active_id(GTK_COMBO_BOX(c25_preamp_combobox), id);
- } else {
- adc_attenuation[active_receiver->adc] = 10*active_receiver->alex_attenuation;
}
}