# uncomment the line to below include support local CW keyer
#LOCALCW_INCLUDE=LOCALCW
-# uncomment the line below to include support for STEMlab discovery (does not work on MacOS)
-#STEMLAB_DISCOVERY=STEMLAB_DISCOVERY
-
-# uncomment the line below to include support for stripped-down STEMlab discovery that works on MacOS
-STEMLAB_DISCOVERY=STEMLAB_DISCOVERY_MAC
+# uncomment the line below to include support for STEMlab discovery
+STEMLAB_DISCOVERY=STEMLAB_DISCOVERY
#uncomment the line below for the platform being compiled on
UNAME_N=MacOS
#UNAME_N=pine64
#UNAME_N=jetsen
+# Additional options that can be chosen at compile time:
+# -DDIGI_MODES wide filters and no noise reduction in DIGU/DIGL
+# -DSPLIT_RXTX if there is more than one receiver, TX panel only "hides" the first one
+# -DPROTOCOL_DEBUG logs (on stderr) all state changes sent to the SDR (only old protocol)
+#
+# leave the list empty if no such option should be used
+
+ADDITIONAL_OPTIONS= -DDIGI_MODES -DSPLIT_RXTX
+
CC=gcc
ifeq ($(UNAME_N),MacOS)
endif
#
-# STEMLAB_DISCOVERY_MAC depends on curl but not on avahi
+# Here in Makefile.mac, we use the version that does not need avahi
#
-ifeq ($(STEMLAB_DISCOVERY), STEMLAB_DISCOVERY_MAC)
-STEMLAB_OPTIONS=-D STEMLAB_DISCOVERY `pkg-config --cflags libcurl`
-STEMLAB_LIBS=`pkg-config --libs libcurl`
-STEMLAB_SOURCES=stemlab_discovery.c
-STEMLAB_HEADERS=stemlab_discovery.h
-STEMLAB_OBJS=stemlab_discovery.o
-endif
-
ifeq ($(STEMLAB_DISCOVERY), STEMLAB_DISCOVERY)
-STEMLAB_OPTIONS=-D STEMLAB_DISCOVERY \
- `pkg-config --cflags avahi-gobject` \
- `pkg-config --cflags libcurl`
-STEMLAB_LIBS=`pkg-config --libs avahi-gobject` `pkg-config --libs libcurl`
+STEMLAB_OPTIONS=-D STEMLAB_DISCOVERY -D NO_AVAHI `pkg-config --cflags libcurl`
+STEMLAB_LIBS=`pkg-config --libs libcurl`
STEMLAB_SOURCES=stemlab_discovery.c
STEMLAB_HEADERS=stemlab_discovery.h
STEMLAB_OBJS=stemlab_discovery.o
OPTIONS=-g -Wno-deprecated-declarations $(PURESIGNAL_OPTIONS) $(REMOTE_OPTIONS) $(RADIOBERRY_OPTIONS) \
$(USBOZY_OPTIONS) $(I2C_OPTIONS) $(GPIO_OPTIONS) $(LIMESDR_OPTIONS) $(FREEDV_OPTIONS) \
$(LOCALCW_OPTIONS) $(PSK_OPTIONS) $(STEMLAB_OPTIONS) $(STEMLAB_FIX_OPTION) \
- $(PORTAUDIO_OPTIONS) \
+ $(PORTAUDIO_OPTIONS) $(ADDITIONAL_OPTIONS) \
-D GIT_DATE='"$(GIT_DATE)"' -D GIT_VERSION='"$(GIT_VERSION)"' $(DEBUG_OPTION) -O3
LIBS= $(AUDIO_LIBS) $(USBOZY_LIBS) $(PSKLIBS) $(GTKLIBS) $(GPIO_LIBS) \
snd_pcm_sframes_t delay;
int error;
long trim;
-
- if (rx == active_receiver && isTransmitting()) return;
+ int mode=transmitter->mode;
+ //
+ // We have to stop the stream here if a CW side tone may occur.
+ // This might cause underflows, but we cannot use audio_write
+ // and cw_audio_write simultaneously on the same device.
+ // Instead, the side tone version will take over.
+ // If *not* doing CW, the stream continues because we might wish
+ // to listen to this rx while transmitting.
+ //
+ if (rx == active_receiver && isTransmitting() && (mode==modeCWU || mode==modeCWL)) return 0;
if(rx->playback_handle!=NULL && rx->playback_buffer!=NULL) {
rx->playback_buffer[rx->playback_offset++]=right_sample;
if (radio->protocol == STEMLAB_PROTOCOL) {
const int device_id = radio - discovered;
stemlab_start_app(gtk_combo_box_get_active_id(GTK_COMBO_BOX(apps_combobox[device_id])));
+#ifdef NO_AVAHI
+ // We only have started the app, but not queried e.g. the MAC address.
+ // Therefore, we have to clean up and re-start the discovery process.
+ stemlab_cleanup();
+ gtk_widget_destroy(discovery_dialog);
+ g_idle_add(ext_discovery,NULL);
+ return TRUE;
+#endif
}
stemlab_cleanup();
#endif
#endif
#ifdef STEMLAB_DISCOVERY
+#ifdef NO_AVAHI
+ status_text("Looking for STEMlab WEB apps");
+#else
status_text("STEMlab (Avahi) ... Discovering Devices");
+#endif
stemlab_discovery();
#endif
sprintf(text,"%s (%s) on USB /dev/ozy", d->name, d->protocol==ORIGINAL_PROTOCOL?"Protocol 1":"Protocol 2");
} else {
#endif
- sprintf(text,"%s (%s %s) %s (%02X:%02X:%02X:%02X:%02X:%02X) on %s",
+ sprintf(text,"%s (%s %s) %s (%02X:%02X:%02X:%02X:%02X:%02X) on %s ",
d->name,
d->protocol==ORIGINAL_PROTOCOL?"Protocol 1":"Protocol 2",
version,
#endif
#ifdef STEMLAB_DISCOVERY
case STEMLAB_PROTOCOL:
+#ifdef NO_AVAHI
+ sprintf(text,"Choose App from %s and re-Discover:",inet_ntoa(d->info.network.address.sin_addr));
+#else
sprintf(text, "STEMlab (%02X:%02X:%02X:%02X:%02X:%02X) on %s",
d->info.network.mac_address[0],
d->info.network.mac_address[1],
d->info.network.mac_address[4],
d->info.network.mac_address[5],
d->info.network.interface_name);
+#endif
#endif
}
GtkWidget *label=gtk_label_new(text);
gtk_widget_override_font(label, pango_font_description_from_string("FreeMono 12"));
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_show(label);
gtk_grid_attach(GTK_GRID(grid),label,0,i,3,1);
gtk_widget_override_font(apps_combobox[i],
pango_font_description_from_string("FreeMono 12"));
// We want the default selection priority for the STEMlab app to be
- // RP-Trx > Pavel-Trx > Pavel-Rx, so we add in decreasing order and
+ // RP-Trx > HAMlab-Trx > Pavel-Trx > Pavel-Rx, so we add in decreasing order and
// always set the newly added entry to be active.
if ((d->software_version & STEMLAB_PAVEL_RX) != 0) {
gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(apps_combobox[i]),
gtk_combo_box_set_active_id(GTK_COMBO_BOX(apps_combobox[i]),
"sdr_transceiver_hpsdr");
}
- if ((d->software_version & STEMLAB_RP_TRX) != 0) {
- gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(apps_combobox[i]),
- "stemlab_sdr_transceiver_hpsdr", "STEMlab-Trx");
- gtk_combo_box_set_active_id(GTK_COMBO_BOX(apps_combobox[i]),
- "stemlab_sdr_transceiver_hpsdr");
- }
if ((d->software_version & HAMLAB_RP_TRX) != 0) {
gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(apps_combobox[i]),
"hamlab_sdr_transceiver_hpsdr", "HAMlab-Trx");
gtk_combo_box_set_active_id(GTK_COMBO_BOX(apps_combobox[i]),
"hamlab_sdr_transceiver_hpsdr");
}
+ if ((d->software_version & STEMLAB_RP_TRX) != 0) {
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(apps_combobox[i]),
+ "stemlab_sdr_transceiver_hpsdr", "STEMlab-Trx");
+ gtk_combo_box_set_active_id(GTK_COMBO_BOX(apps_combobox[i]),
+ "stemlab_sdr_transceiver_hpsdr");
+ }
gtk_widget_show(apps_combobox[i]);
gtk_grid_attach(GTK_GRID(grid), apps_combobox[i], 4, i, 1, 1);
}
}
break;
+#ifdef DIGI_MODES
+ case modeDIGU:
+ case modeDIGL:
+ gtk_button_set_label(GTK_BUTTON(close_b), "DIGU/DIGL have a fixed wide filter.");
+ break;
+#endif
+
default:
for(i=0;i<FILTERS-2;i++) {
FILTER* band_filter=&band_filters[i];
#include "receiver.h"
#include "vfo.h"
#include "button_text.h"
+#ifdef DIGI_MODES
+#include "noise_menu.h" // for noise-on/off in DIGU/L
+#endif
static GtkWidget *parent_window=NULL;
set_button_text_color(last_mode,"black");
last_mode=widget;
set_button_text_color(last_mode,"orange");
+#ifdef DIGI_MODES
+ switch (m) {
+ case modeDIGL:
+ case modeDIGU:
+ noise_off(); // diable noise reduction machine completely for DIGI modes
+ break;
+ default:
+ update_noise(); // set noise reduction to the values stored in the current RECEIVER
+ }
+#endif
vfo_mode_changed(m);
- // DL1YCF added return statement to make the compiler happy.
- // however I am unsure about the correct return value.
- // I would have coded this as a void function.
return FALSE;
}
#include "vfo_menu.h"
#include "fft_menu.h"
#include "main.h"
+#include "button_text.h"
static GtkWidget *menu_b=NULL;
start_ps();
return TRUE;
}
+#else
+static gboolean tt_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
+ // even without PURESIGNAL, a two-tone generator is nice-to-have
+ // so whe "PS" button now is a "TT" (two-tone) button.
+ int state=transmitter->twotone?0:1;
+ tx_set_twotone(transmitter,state);
+ if(state) {
+ set_button_text_color(widget,"red");
+ } else {
+ set_button_text_color(widget,"black");
+ }
+ return TRUE;
+}
#endif
#ifdef GPIO
g_signal_connect (ps_b, "button-press-event", G_CALLBACK(ps_cb), NULL);
gtk_grid_attach(GTK_GRID(grid),ps_b,(i%5),i/5,1,1);
i++;
+#else
+ GtkWidget *tt_b=gtk_button_new_with_label("TT");
+ gtk_widget_show(tt_b);
+ gtk_grid_attach(GTK_GRID(grid),tt_b,(i%5),i/5,1,1);
+ g_signal_connect (tt_b, "pressed", G_CALLBACK(tt_cb), NULL);
+ if(transmitter->twotone) {
+ set_button_text_color(tt_b,"red");
+ }
+ i++;
#endif
GtkWidget *pa_b=gtk_button_new_with_label("PA");
rc=sem_init(&iq_sem_buffer[ddc], 0, 0);
#endif
iq_thread_id[ddc] = g_thread_new( "ps iq thread", ps_iq_thread, (gpointer)(long)PS_TX_FEEDBACK);
- if( ! iq_thread_id ) {
- fprintf(stderr,"g_thread_new failed for ps_iq_thread: rx=%d\n",PS_TX_FEEDBACK);
- exit( -1 );
- }
fprintf(stderr, "iq_thread: id=%p\n",iq_thread_id);
}
#endif
}
rx->iq_sequence++;
- 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);
+ 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);
bitspersample=((buffer[12]&0xFF)<<8)+(buffer[13]&0xFF);
samplesperframe=((buffer[14]&0xFF)<<8)+(buffer[15]&0xFF);
return FALSE;
}
+#ifdef DIGI_MODES
+void noise_off() {
+ SetEXTANBRun(active_receiver->id, 0);
+ SetEXTNOBRun(active_receiver->id, 0);
+ SetRXAANRRun(active_receiver->id, 0);
+ SetRXAEMNRRun(active_receiver->id, 0);
+ SetRXAANFRun(active_receiver->id, 0);
+ SetRXASNBARun(active_receiver->id, 0);
+}
+
+void update_noise() {
+#else
static void update_noise() {
+#endif
SetEXTANBRun(active_receiver->id, active_receiver->nb);
SetEXTNOBRun(active_receiver->id, active_receiver->nb2);
SetRXAANRRun(active_receiver->id, active_receiver->nr);
void noise_menu(GtkWidget *parent) {
GtkWidget *b;
int i;
+ int mode=vfo[active_receiver->id].mode;
parent_window=parent;
gtk_grid_set_column_spacing (GTK_GRID(grid),5);
gtk_grid_set_row_spacing (GTK_GRID(grid),5);
+#ifdef DIGI_MODES
+ if (mode == modeDIGU || mode == modeDIGL) {
+ GtkWidget *close_b=gtk_button_new_with_label("DIGU/DIGL have no noise options.");
+ g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
+ gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
+ }
+ else {
+#endif
GtkWidget *close_b=gtk_button_new_with_label("Close");
g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL);
gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1);
gtk_widget_show(b_nr2);
gtk_grid_attach(GTK_GRID(grid),b_nr2,col,row,1,1);
g_signal_connect(b_nr2,"pressed",G_CALLBACK(nr2_cb),NULL);
+#ifdef DIGI_MODES
+ }
+#endif
gtk_container_add(GTK_CONTAINER(content),grid);
*/
extern void noise_menu(GtkWidget *parent);
+
+#ifdef DIGI_MODES
+extern void noise_off();
+extern void update_noise();
+#endif
*/
#ifdef PROTOCOL_DEBUG
-// DL1YCF Debug: save last values and log changes
+// DL1YCF Debug: save last values and print any changes to stderr
static unsigned char last_c1[20], last_c2[20], last_c3[20], last_c4[20], last_mox;
+static long long last_tx, last_rx[8];
#endif
void ozy_send_buffer() {
output_buffer[C2]=txFrequency>>16;
output_buffer[C3]=txFrequency>>8;
output_buffer[C4]=txFrequency;
+#ifdef PROTOCOL_DEBUG
+ if (last_tx != txFrequency) {
+ fprintf(stderr,"TX1 FREQ CHANGE from %lld to %lld\n", last_tx, txFrequency);
+ last_tx=txFrequency;
+ }
+#endif
break;
case 2: // rx frequency
#ifdef PURESIGNAL
output_buffer[C2]=rxFrequency>>16;
output_buffer[C3]=rxFrequency>>8;
output_buffer[C4]=rxFrequency;
+#ifdef PROTOCOL_DEBUG
+ if (rxFrequency != last_rx[current_rx]) {
+ fprintf(stderr,"RX%d FREQ CHANGE from %lld to %lld\n", current_rx+1, last_rx[current_rx], rxFrequency);
+ last_rx[current_rx] = rxFrequency;
+ }
+#endif
#ifdef PURESIGNAL
}
#endif
// leave it here deactivated
//
int ind = output_buffer[C0] >> 1;
- if (last_c1[ind] != output_buffer[C1]) {
- fprintf(stderr, "C0=%x Old C1=%x New C1=%x\n", 2*ind,last_c1[ind], output_buffer[C1]);
- last_c1[ind]=output_buffer[C1];
- }
- if (last_c2[ind] != output_buffer[C2]) {
- fprintf(stderr, "C0=%x Old C2=%x New C2=%x\n", 2*ind,last_c2[ind], output_buffer[C2]);
- last_c2[ind]=output_buffer[C2];
- }
- if (last_c3[ind] != output_buffer[C3]) {
- fprintf(stderr, "C0=%x Old C3=%x New C3=%x\n", 2*ind,last_c3[ind], output_buffer[C3]);
- last_c3[ind]=output_buffer[C3];
- }
- if (last_c4[ind] != output_buffer[C4]) {
- fprintf(stderr, "C0=%x Old C4=%x New C4=%x\n", 2*ind,last_c4[ind], output_buffer[C4]);
- last_c4[ind]=output_buffer[C4];
+ if (ind == 0 || ind > 8) {
+ // Frequency changes are reported above.
+ if (last_c1[ind] != output_buffer[C1]) {
+ fprintf(stderr, "C0=%x Old C1=%x New C1=%x\n", 2*ind,last_c1[ind], output_buffer[C1]);
+ last_c1[ind]=output_buffer[C1];
+ }
+ if (last_c2[ind] != output_buffer[C2]) {
+ fprintf(stderr, "C0=%x Old C2=%x New C2=%x\n", 2*ind,last_c2[ind], output_buffer[C2]);
+ last_c2[ind]=output_buffer[C2];
+ }
+ if (last_c3[ind] != output_buffer[C3]) {
+ fprintf(stderr, "C0=%x Old C3=%x New C3=%x\n", 2*ind,last_c3[ind], output_buffer[C3]);
+ last_c3[ind]=output_buffer[C3];
+ }
+ if (last_c4[ind] != output_buffer[C4]) {
+ fprintf(stderr, "C0=%x Old C4=%x New C4=%x\n", 2*ind,last_c4[ind], output_buffer[C4]);
+ last_c4[ind]=output_buffer[C4];
+ }
}
if ((output_buffer[C0] & 1) != last_mox) {
fprintf(stderr, "Last Mox=%d New Mox=%d\n", last_mox, output_buffer[C0] & 1);
#endif
#include "radio.h"
#include "receiver.h"
+#include "mode.h"
#include "portaudio.h"
#include "math.h" // for sintab, two-tone generator
int audio_write (RECEIVER *rx, short r, short l)
{
PaError err;
+ int mode=transmitter->mode;
+ //
+ // We have to stop the stream here if a CW side tone may occur.
+ // This might cause underflows, but we cannot use audio_write
+ // and cw_audio_write simultaneously on the same device.
+ // Instead, the side tone version will take over.
+ // If *not* doing CW, the stream continues because we might wish
+ // to listen to this rx while transmitting.
+ //
+ if (rx == active_receiver && isTransmitting() && (mode==modeCWU || mode==modeCWL)) return 0;
- // this will cause massive underflow errors, since
- // we do not provide any data while transmitting.
- // Instead, the side tone version will take over
- if (rx == active_receiver && isTransmitting()) return 0;
if (rx->playback_handle != NULL && rx->playback_buffer != NULL) {
rx->playback_buffer[rx->playback_offset++] = (r + l) *0.000015259; // 65536 --> 1.0
if (rx->playback_offset == audio_buffer_size) {
usleep(10000); // 10 ms
}
gtk_entry_set_text(GTK_ENTRY(entry[15]),"");
+ return NULL;
}
static void enable_cb(GtkWidget *widget, gpointer data) {
}
}
+#ifdef SPLIT_RXTX
+ reconfigure_transmitter(transmitter,rx_height/receivers);
+#else
reconfigure_transmitter(transmitter,rx_height);
+#endif
}
if(display_sliders) {
rx_height-=SLIDERS_HEIGHT;
}
+#ifdef SPLIT_RXTX
+ int tx_height=rx_height/receivers;
+#else
int tx_height=rx_height;
+#endif
rx_height=rx_height/receivers;
#ifdef PURESIGNAL
tx_set_ps_sample_rate(transmitter,protocol==NEW_PROTOCOL?192000:active_receiver->sample_rate);
- if(((protocol==ORIGINAL_PROTOCOL) && (device!=DEVICE_METIS)) || ((protocol==NEW_PROTOCOL) && (device!=NEW_DEVICE_ATLAS))) {
- receiver[PS_TX_FEEDBACK]=create_pure_signal_receiver(PS_TX_FEEDBACK, buffer_size,protocol==ORIGINAL_PROTOCOL?active_receiver->sample_rate:192000,display_width);
- receiver[PS_RX_FEEDBACK]=create_pure_signal_receiver(PS_RX_FEEDBACK, buffer_size,protocol==ORIGINAL_PROTOCOL?active_receiver->sample_rate:192000,display_width);
- }
+ // DL1YCF: we must create these receivers in ANY case to avoid seg-faults.
+ receiver[PS_TX_FEEDBACK]=create_pure_signal_receiver(PS_TX_FEEDBACK, buffer_size,protocol==ORIGINAL_PROTOCOL?active_receiver->sample_rate:192000,display_width);
+ receiver[PS_RX_FEEDBACK]=create_pure_signal_receiver(PS_RX_FEEDBACK, buffer_size,protocol==ORIGINAL_PROTOCOL?active_receiver->sample_rate:192000,display_width);
#endif
#ifdef AUDIO_WATERFALL
tx_feedback->samples=0;
#endif
+#ifdef SPLIT_RXTX
+ for(i=0;i<1;i++) {
+#else
for(i=0;i<receivers;i++) {
+#endif
SetChannelState(receiver[i]->id,0,i==(receivers-1));
set_displaying(receiver[i],0);
if(protocol==NEW_PROTOCOL) {
// gtk_widget_hide(audio_waterfall);
// }
//#endif
+#ifdef SPLIT_RXTX
+ for(i=0;i<1;i++) {
+#else
for(i=0;i<receivers;i++) {
+#endif
gtk_fixed_put(GTK_FIXED(fixed),receiver[i]->panel,receiver[i]->x,receiver[i]->y);
SetChannelState(receiver[i]->id,1,0);
set_displaying(receiver[i],1);
//schedule_general();
}
if(tune) {
- for(i=0;i<receivers;i++) {
+#ifdef SPLIT_RXTX
+ for(i=0;i<1;i++) {
+#else
+ for(i=0;i<receivers;i++) {
+#endif
SetChannelState(receiver[i]->id,0,i==(receivers-1));
set_displaying(receiver[i],0);
if(protocol==NEW_PROTOCOL) {
void receiver_filter_changed(RECEIVER *rx) {
int m=vfo[rx->id].mode;
- if(m==modeFMN) {
- if(rx->deviation==2500) {
- set_filter(rx,-4000,4000);
- } else {
- set_filter(rx,-8000,8000);
- }
- set_deviation(rx);
- } else {
- FILTER *mode_filters=filters[m];
- FILTER *filter=&mode_filters[vfo[rx->id].filter];
- set_filter(rx,filter->low,filter->high);
+ switch (m) {
+ case modeFMN:
+ if(rx->deviation==2500) {
+ set_filter(rx,-4000,4000);
+ } else {
+ set_filter(rx,-8000,8000);
+ }
+ set_deviation(rx);
+ break;
+#ifdef DIGI_MODES
+ case modeDIGU:
+ set_filter(rx,0,3000);
+ break;
+ case modeDIGL:
+ set_filter(rx,-3000,0);
+ break;
+#endif
+ default:
+ {
+ FILTER *mode_filters=filters[m];
+ FILTER *filter=&mode_filters[vfo[rx->id].filter];
+ set_filter(rx,filter->low,filter->high);
+ }
}
}
short left_audio_sample;
short right_audio_sample;
int i;
+ int mute=0;
+ //
+ // DL1YCF: mute the receiver if we are transmitting on its frequency
+ //
+ if (isTransmitting()) {
+ if (!split && (rx->id == active_receiver->id)) mute=1;
+ if ( split && (rx->id != active_receiver->id)) mute=1;
+ }
for(i=0;i<rx->output_samples;i++) {
- if(isTransmitting()) {
+ if(mute) {
left_audio_sample=0;
right_audio_sample=0;
} else {
scale_status=ATTENUATION;
scale_dialog=gtk_dialog_new_with_buttons(title,GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
- attenuation_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 31.0, 1.00);
+ if (filter_board == CHARLY25) {
+ // although this slider is hidden, its value range does matter
+ attenuation_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 36.0, 1.00);
+ } else {
+ attenuation_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 31.0, 1.00);
+ }
gtk_widget_set_size_request (attenuation_scale, 400, 30);
gtk_range_set_value (GTK_RANGE(attenuation_scale),(double)adc_attenuation[active_receiver->adc]);
gtk_widget_show(attenuation_scale);
attenuation_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 60.0, 1.0);
gtk_range_set_value (GTK_RANGE(attenuation_scale),rx_gain_slider[active_receiver->adc]);
#else
- attenuation_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 31.0, 1.0);
+ if (filter_board == CHARLY25) {
+ attenuation_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 36.0, 1.0);
+ } else {
+ attenuation_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 31.0, 1.0);
+ }
gtk_range_set_value (GTK_RANGE(attenuation_scale),adc_attenuation[active_receiver->adc]);
#endif
*
*/
-#ifdef __APPLE__
+// DL1YCF: we provide a stripped-down version not relying on AVAHI.
+// this is compiled when defining NO_AVAHI
-//
-// MacOS has no vahi, but it does have libcurl.
-// Therefore we try to start the SDR app on the RedPitaya
-// assuming is has the (fixed) ip address which can be
-// read from $HOME/.rp.inet, if this does not succeed it
-// defaults to 192.168.1.3.
-//
-// So, on MacOS, just configure your STEMLAB/HAMLAB to this
-// fixed IP address and you need not open a browser to start
-// SDR *before* you can use piHPSDR.
-//
-// Sure it's not perfect, but it makes life much easier for me.
-//
#include <stdio.h>
#include <stdlib.h>
+#include <stdbool.h>
+#include <ifaddrs.h>
+#include <net/if.h>
+#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <curl/curl.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
#include <glib.h>
-
-extern void status_text(const char *);
-
-static const char *appid = NULL;
-
-//
-// Extract the list of apps from the JSON answer
-//
-static size_t app_list_callback(void *buffer, size_t size, size_t nmemb, void *data) {
- const gchar *needle;
-
- needle="\"sdr_receiver_hpsdr\"";
- if (g_strstr_len(buffer, size*nmemb, needle) != NULL) {
- appid="sdr_receiver_hpsdr";
- }
-
- needle="\"sdr_transceiver_hpsdr\"";
- if (g_strstr_len(buffer, size*nmemb, needle) != NULL) {
- appid="sdr_transceiver_hpsdr";
- }
-
- needle="\"stemlab_sdr_transceiver_hpsdr\"";
- if (g_strstr_len(buffer, size*nmemb, needle) != NULL) {
- appid="stemlab_sdr_transceiver_hpsdr";
- }
-
- needle="\"hamlab_sdr_transceiver_hpsdr\"";
- if (g_strstr_len(buffer, size*nmemb, needle) != NULL) {
- appid="hamlab_sdr_transceiver_hpsdr";
- }
-
- if (appid) fprintf(stderr,"RedPitay WEB application to start: %s\n", appid);
- return size * nmemb;
-}
-
-void stemlab_discovery() {
- // this one is used "as the last resort", if nothing else is found.
- size_t len;
- char inet[20];
- char txt[150];
- CURL *curl_handle;
- CURLcode curl_error;
- FILE *fpin;
- char *p;
-
- fprintf(stderr,"Stripped-down STEMLAB/HAMLAB discovery...\n");
-//
-// Try to read inet addr from $HOME/.rp.inet, otherwise take 192.168.1.3
-//
- strcpy(inet,"192,168.1.3");
- p=getenv("HOME");
- if (p) {
- strncpy(txt,p, (size_t) 100); // way less than size of txt
- } else {
- strcpy(txt,".");
- }
- strcat(txt,"/.rp.inet");
- fprintf(stderr,"Trying to read inet addr from file=%s\n", txt);
- fpin=fopen(txt, "r");
- if (fpin) {
- len=100;
- p=txt;
- len=getline(&p, &len, fpin);
- // not txt now contains the trailing newline character
- while (*p != 0) {
- if (*p == '\n') *p = 0;
- p++;
- }
- if (len < 20) strcpy(inet,txt);
- }
- fclose(fpin);
- fprintf(stderr,"STEMLAB: using inet addr %s\n", inet);
-//
-// Do a HEAD request (poor curl's ping) to see whether the device is on-line
-// allow a 15 sec time-out
- status_text("Looking for a STEMLAB web server ...");
- curl_handle = curl_easy_init();
- if (curl_handle == NULL) {
- fprintf(stderr, "stemlab_start: Failed to create cURL handle\n");
- return;
- }
- sprintf(txt,"http://%s",inet);
- curl_error = curl_easy_setopt(curl_handle, CURLOPT_URL, txt);
- curl_error = curl_easy_setopt(curl_handle, CURLOPT_NOBODY, (long) 1);
- curl_error = curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, (long) 15);
- curl_error = curl_easy_perform(curl_handle);
- curl_easy_cleanup(curl_handle);
- if (curl_error == CURLE_OPERATION_TIMEDOUT) {
- sprintf(txt,"No response from web server at %s", inet);
- status_text(txt);
- fprintf(stderr,"%s\n",txt);
- }
- if (curl_error != CURLE_OK) {
- fprintf(stderr, "STEMLAB ping error: %s\n", curl_easy_strerror(curl_error));
- return;
- }
-
-//
-//obtain a list of apps, and choose the right one by looking for the following
-//target strings (in that order). Whatever is found first, is started. Then, we rely
-//on the original discovery() to discover the device.
-//
-//hamlab_sdr_transceiver_hpsdr
-//stemlab_sdr_transceiver_hpsdr
-//sdr_transceiver_hpsdr
-//sdr_receiver_hpsdr
-//
- curl_handle = curl_easy_init();
- if (curl_handle == NULL) {
- fprintf(stderr, "stemlab_start: Failed to create cURL handle\n");
- return;
- }
- sprintf(txt,"http://%s/bazaar?apps=", inet);
- curl_error = curl_easy_setopt(curl_handle, CURLOPT_URL, txt);
- curl_error = curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, (long) 60);
- curl_error = curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, app_list_callback);
- curl_error = curl_easy_perform(curl_handle);
- curl_easy_cleanup(curl_handle);
- if (curl_error == CURLE_OPERATION_TIMEDOUT) {
- status_text("No Response from RedPitaya in 60 secs");
- fprintf(stderr,"60-sec TimeOut met when trying to get list of HPSDR apps from RedPitaya\n");
- }
- if (curl_error != CURLE_OK) {
- fprintf(stderr, "STEMLAB app-list error: %s\n", curl_easy_strerror(curl_error));
- return;
- }
-
-//
-// Now we actually start the hpsdr application
-// Actually, try to stop it first, then re-start it.
-//
- if (appid) {
- curl_handle = curl_easy_init();
- if (curl_handle == NULL) {
- fprintf(stderr, "stemlab_start: Failed to create cURL handle\n");
- return;
- }
- sprintf(txt,"http://%s/bazaar?stop=%s",inet,appid);
- curl_error = curl_easy_setopt(curl_handle, CURLOPT_URL, txt);
- curl_error = curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, (long) 60);
- curl_error = curl_easy_perform(curl_handle);
- if (curl_error == CURLE_OPERATION_TIMEDOUT) {
- fprintf(stderr,"60-sec TimeOut met when trying to stop HPSDR app on RedPitaya\n");
- }
- if (curl_error != CURLE_OK) {
- fprintf(stderr, "STEMLAB app-start error: %s\n", curl_easy_strerror(curl_error));
- }
- curl_handle = curl_easy_init();
- if (curl_handle == NULL) {
- fprintf(stderr, "stemlab_start: Failed to create cURL handle\n");
- return;
- }
- sprintf(txt,"http://%s/bazaar?start=%s",inet,appid);
- curl_error = curl_easy_setopt(curl_handle, CURLOPT_URL, txt);
- curl_error = curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, (long) 60);
- curl_error = curl_easy_perform(curl_handle);
- if (curl_error == CURLE_OPERATION_TIMEDOUT) {
- fprintf(stderr,"60-sec TimeOut met when trying to start HPSDR app on RedPitaya\n");
- }
- if (curl_error != CURLE_OK) {
- fprintf(stderr, "STEMLAB app-start error: %s\n", curl_easy_strerror(curl_error));
- }
-
- }
- // Whether or net we have successfully started the HPSDR application on the RedPitaya,
- // we now return to the regular HPSDR protocol handling code that will eventually detect
- // the "board". If this code does not work, you have to open a browser and start the HPSDR
- // application manually.
-}
-
-// dummy function
-void stemlab_cleanup() {
-}
-
-// dummy function, never called
-void stemlab_start_app() {
-}
-
-#else
-
#include <errno.h>
#include <ifaddrs.h>
-#include <net/if.h>
-#include <arpa/inet.h>
-#include <stdbool.h>
-#include <stddef.h>
#include <stdint.h>
-#include <stdio.h>
#include <string.h>
-#include <avahi-gobject/ga-client.h>
-#include <avahi-gobject/ga-service-browser.h>
-#include <avahi-gobject/ga-service-resolver.h>
-
-#include <curl/curl.h>
-
-#include <glib.h>
-
#include "discovered.h"
#include "radio.h"
-#define ERROR_PREFIX "stemlab_discovery: "
+#ifndef NO_AVAHI
+#include <avahi-gobject/ga-client.h>
+#include <avahi-gobject/ga-service-browser.h>
+#include <avahi-gobject/ga-service-resolver.h>
+#endif
// As we only run in the GTK+ main event loop, which is single-threaded and
// non-preemptive, we shouldn't need any additional synchronisation mechanisms.
static int pending_callbacks = 0;
static struct ifaddrs *ifaddrs = NULL;
static bool curl_initialised = FALSE;
+extern void status_text(const char *);
-static size_t app_list_cb(void *buffer, size_t size, size_t nmemb, void *data) {
- // cURL does *not* make any guarantees for this data to be the complete
- // However, as the STEMlab answers in one big chunk, we just hope for the
- // answer to be the complete json object, and avoid the hassle of manually
- // building up our buffer.
- int *software_version = (int*) data;
- // This is not 100% clean, but avoids requiring in a json library dependency
- const gchar *pavel_rx_json = "\"sdr_receiver_hpsdr\":";
- if (g_strstr_len(buffer, size*nmemb, pavel_rx_json) != NULL) {
- *software_version |= STEMLAB_PAVEL_RX;
- }
- const gchar *pavel_trx_json = "\"sdr_transceiver_hpsdr\":";
- if (g_strstr_len(buffer, size*nmemb, pavel_trx_json) != NULL) {
- *software_version |= STEMLAB_PAVEL_TRX;
- }
- const gchar *rp_trx_json = "\"stemlab_sdr_transceiver_hpsdr\":";
- if (g_strstr_len(buffer, size*nmemb, rp_trx_json) != NULL) {
- *software_version |= STEMLAB_RP_TRX;
- }
- const gchar *hamlab_trx_json = "\"hamlab_sdr_transceiver_hpsdr\":";
- if (g_strstr_len(buffer, size*nmemb, hamlab_trx_json) != NULL) {
- *software_version |= HAMLAB_RP_TRX;
- }
- // Returning the total amount of bytes "processed" to signal cURL that we
- // are done without any errors
- return size * nmemb;
-}
+#define ERROR_PREFIX "stemlab_discovery: "
+//
+// A bunch of callback-routines that use avahi, and are only needed by the
+// avahi-dependent version of stemlab_discovery(). These are only compiled
+// in the avahi case.
+//
+#ifndef NO_AVAHI
static void resolver_found_cb(GaServiceResolver *resolver, AvahiIfIndex if_index,
GaProtocol protocol, gchar *name, gchar *service, gchar *domain,
gchar *hostname, AvahiAddress *address, gint port, AvahiStringList *txt,
}
discovery_done = TRUE;
}
+#endif
+//
+// Some callback routines and functions that do not depend on avahi
+// and are compiled in either case.
+//
+static size_t app_list_cb(void *buffer, size_t size, size_t nmemb, void *data) {
+ // cURL does *not* make any guarantees for this data to be the complete
+ // However, as the STEMlab answers in one big chunk, we just hope for the
+ // answer to be the complete json object, and avoid the hassle of manually
+ // building up our buffer.
+ int *software_version = (int*) data;
+ // This is not 100% clean, but avoids requiring in a json library dependency
+ const gchar *pavel_rx_json = "\"sdr_receiver_hpsdr\":";
+ if (g_strstr_len(buffer, size*nmemb, pavel_rx_json) != NULL) {
+ *software_version |= STEMLAB_PAVEL_RX;
+ }
+ const gchar *pavel_trx_json = "\"sdr_transceiver_hpsdr\":";
+ if (g_strstr_len(buffer, size*nmemb, pavel_trx_json) != NULL) {
+ *software_version |= STEMLAB_PAVEL_TRX;
+ }
+ const gchar *rp_trx_json = "\"stemlab_sdr_transceiver_hpsdr\":";
+ if (g_strstr_len(buffer, size*nmemb, rp_trx_json) != NULL) {
+ *software_version |= STEMLAB_RP_TRX;
+ }
+ const gchar *hamlab_trx_json = "\"hamlab_sdr_transceiver_hpsdr\":";
+ if (g_strstr_len(buffer, size*nmemb, hamlab_trx_json) != NULL) {
+ *software_version |= HAMLAB_RP_TRX;
+ }
+ // Returning the total amount of bytes "processed" to signal cURL that we
+ // are done without any errors
+ return size * nmemb;
+}
+
+// This is essentially a no-op curl callback
+static size_t app_start_callback(void *buffer, size_t size, size_t nmemb, void *data) {
+ if (strncmp(buffer, "{\"status\":\"OK\"}", size*nmemb) != 0) {
+ fprintf(stderr, "stemlab_start: Receiver error from STEMlab\n");
+ return 0;
+ }
+ return size * nmemb;
+}
+
+void stemlab_start_app(const char * const app_id) {
+ // Dummy string, using the longest possible app id
+ char app_start_url[] = "http://123.123.123.123/bazaar?start=stemlab_sdr_transceiver_hpsdr";
+ sprintf(app_start_url, "http://%s/bazaar?start=%s",
+ inet_ntoa(radio->info.network.address.sin_addr),
+ app_id);
+ CURL *curl_handle = curl_easy_init();
+ if (curl_handle == NULL) {
+ fprintf(stderr, "stemlab_start: Failed to create cURL handle\n");
+ exit(-1);
+ }
+ CURLcode curl_error = CURLE_OK;
+#define check_curl(description) do { \
+ if (curl_error != CURLE_OK) { \
+ fprintf(stderr, "stemlab_start: " description ": %s\n", \
+ curl_easy_strerror(curl_error)); \
+ exit(-1); \
+ } \
+} while (0);
+ curl_error = curl_easy_setopt(curl_handle, CURLOPT_URL, app_start_url);
+ check_curl("Failed setting cURL URL");
+ curl_error = curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, app_start_callback);
+ check_curl("Failed install cURL callback");
+ curl_error = curl_easy_perform(curl_handle);
+ check_curl("Failed to start app");
+#undef check_curl
+ curl_easy_cleanup(curl_handle);
+ // Since the SDR application is now running, we can hand it over to the
+ // regular HPSDR protocol handling code
+ radio->protocol = ORIGINAL_PROTOCOL;
+}
+
+void stemlab_cleanup(void) {
+ if (curl_initialised) {
+ curl_global_cleanup();
+ }
+}
+
+#ifndef NO_AVAHI
+//
+// This is the avahi-dependent version of stemlab_discovery()
+//
void stemlab_discovery(void) {
discovery_done = FALSE;
GaClient * const avahi_client = ga_client_new(GA_CLIENT_FLAG_NO_FLAGS);
g_main_context_iteration(NULL, TRUE);
}
}
+#else
+//
+// This version of stemlab_discovery() needs libcurl
+// but does not need avahi.
+//
+// Therefore we try to find the SDR apps on the RedPitaya
+// assuming is has the (fixed) ip address which can be
+// read from $HOME/.rp.inet, if this does not succeed it
+// defaults to 192.168.1.3.
+//
+// So, on MacOS, just configure your STEMLAB/HAMLAB to this
+// fixed IP address and you need not open a browser to start
+// SDR *before* you can use piHPSDR.
+//
+// After starting the app in the main discover menu, we
+// have to re-discover to get full info and start the radio.
+//
-// This is essentially a no-op curl callback
-static size_t app_start_callback(void *buffer, size_t size, size_t nmemb, void *data) {
- if (strncmp(buffer, "{\"status\":\"OK\"}", size*nmemb) != 0) {
- fprintf(stderr, "stemlab_start: Receiver error from STEMlab\n");
- return 0;
- }
- return size * nmemb;
-}
-void stemlab_start_app(const char * const app_id) {
- // Dummy string, using the longest possible app id
- char app_start_url[] = "http://123.123.123.123/bazaar?start=stemlab_sdr_transceiver_hpsdr";
- sprintf(app_start_url, "http://%s/bazaar?start=%s",
- inet_ntoa(radio->info.network.address.sin_addr),
- app_id);
- CURL *curl_handle = curl_easy_init();
+void stemlab_discovery() {
+ size_t len;
+ char inet[20];
+ char txt[150];
+ CURL *curl_handle;
+ CURLcode curl_error;
+ FILE *fpin;
+ char *p;
+ int i;
+ int app_list;
+ struct sockaddr_in ip_address;
+ struct sockaddr_in netmask;
+
+ fprintf(stderr,"Stripped-down STEMLAB/HAMLAB discovery...\n");
+//
+// Try to read inet addr from $HOME/.rp.inet, otherwise take 192.168.1.3
+//
+ strcpy(inet,"192.168.1.3");
+ p=getenv("HOME");
+ if (p) {
+ strncpy(txt,p, (size_t) 100); // way less than size of txt
+ } else {
+ strcpy(txt,".");
+ }
+ strcat(txt,"/.rp.inet");
+ fprintf(stderr,"Trying to read inet addr from file=%s\n", txt);
+ fpin=fopen(txt, "r");
+ if (fpin) {
+ len=100;
+ p=txt;
+ len=getline(&p, &len, fpin);
+ // not txt now contains the trailing newline character
+ while (*p != 0) {
+ if (*p == '\n') *p = 0;
+ p++;
+ }
+ if (len < 20) strcpy(inet,txt);
+ }
+ fclose(fpin);
+ fprintf(stderr,"STEMLAB: using inet addr %s\n", inet);
+ ip_address.sin_family = AF_INET;
+ inet_aton(inet, &ip_address.sin_addr);
+
+ netmask.sin_family = AF_INET;
+ inet_aton("0.0.0.0", &netmask.sin_addr);
+
+
+//
+// Do a HEAD request (poor curl's ping) to see whether the device is on-line
+// allow a 15 sec time-out
+//
+ curl_handle = curl_easy_init();
if (curl_handle == NULL) {
fprintf(stderr, "stemlab_start: Failed to create cURL handle\n");
- exit(-1);
+ return;
}
- CURLcode curl_error = CURLE_OK;
-#define check_curl(description) do { \
- if (curl_error != CURLE_OK) { \
- fprintf(stderr, "stemlab_start: " description ": %s\n", \
- curl_easy_strerror(curl_error)); \
- exit(-1); \
- } \
-} while (0);
- curl_error = curl_easy_setopt(curl_handle, CURLOPT_URL, app_start_url);
- check_curl("Failed setting cURL URL");
- curl_error = curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, app_start_callback);
- check_curl("Failed install cURL callback");
+ sprintf(txt,"http://%s",inet);
+ curl_error = curl_easy_setopt(curl_handle, CURLOPT_URL, txt);
+ curl_error = curl_easy_setopt(curl_handle, CURLOPT_NOBODY, (long) 1);
+ curl_error = curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, (long) 15);
curl_error = curl_easy_perform(curl_handle);
- check_curl("Failed to start app");
-#undef check_curl
curl_easy_cleanup(curl_handle);
- // Since the SDR application is now running, we can hand it over to the
- // regular HPSDR protocol handling code
- radio->protocol = ORIGINAL_PROTOCOL;
-}
-
-void stemlab_cleanup(void) {
- if (curl_initialised) {
- curl_global_cleanup();
+ if (curl_error == CURLE_OPERATION_TIMEDOUT) {
+ sprintf(txt,"No response from web server at %s", inet);
+ status_text(txt);
+ fprintf(stderr,"%s\n",txt);
+ }
+ if (curl_error != CURLE_OK) {
+ fprintf(stderr, "STEMLAB ping error: %s\n", curl_easy_strerror(curl_error));
+ return;
+ }
+
+//
+// Determine which SDR apps are present on the RedPitaya. The list may be empty.
+//
+ curl_handle = curl_easy_init();
+ if (curl_handle == NULL) {
+ fprintf(stderr, "stemlab_start: Failed to create cURL handle\n");
+ return;
+ }
+ app_list=0;
+ sprintf(txt,"http://%s/bazaar?apps=", inet);
+ curl_error = curl_easy_setopt(curl_handle, CURLOPT_URL, txt);
+ curl_error = curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, (long) 60);
+ curl_error = curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, app_list_cb);
+ curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &app_list);
+ curl_error = curl_easy_perform(curl_handle);
+ curl_easy_cleanup(curl_handle);
+ if (curl_error == CURLE_OPERATION_TIMEDOUT) {
+ status_text("No Response from RedPitaya in 60 secs");
+ fprintf(stderr,"60-sec TimeOut met when trying to get list of HPSDR apps from RedPitaya\n");
}
+ if (curl_error != CURLE_OK) {
+ fprintf(stderr, "STEMLAB app-list error: %s\n", curl_easy_strerror(curl_error));
+ return;
+ }
+
+//
+// Constructe "device" descripter. Hi-Jack the software version to
+// encode which apps are present.
+// What is needed in the interface data is only info.network.address.sin_addr,
+// but the address and netmask of the interface must be compatible with this
+// address to avoid an error condition upstream. That means
+// (addr & mask) == (interface_addr & mask) must be fulfilled. This is easily
+// achieved by setting interface_addr = addr and mask = 0.
+//
+ DISCOVERED *device = &discovered[devices++];
+ device->protocol = STEMLAB_PROTOCOL;
+ device->device = DEVICE_METIS; // not used
+ strcpy(device->name, "STEMlab");
+ device->software_version = app_list; // encodes list of SDR apps present
+ device->status = STATE_AVAILABLE;
+ memset(device->info.network.mac_address, 0, 6); // not used
+ device->info.network.address_length = sizeof(struct sockaddr_in);
+ device->info.network.address.sin_family = AF_INET;
+ device->info.network.address.sin_addr = ip_address.sin_addr;
+ device->info.network.address.sin_port = htons(1024);
+ device->info.network.interface_length = sizeof(struct sockaddr_in);
+ device->info.network.interface_address = ip_address; // same as RP address
+ device->info.network.interface_netmask= netmask; // does not matter
+ strcpy(device->info.network.interface_name, "");
}
+
#endif
}
}
+#ifdef SPLIT_RXTX
+ // If the second RX is active, we rather want to see its S-meter instead of TX data
+ if (active_receiver == receiver[0]) {
+ meter_update(active_receiver,POWER,transmitter->fwd,transmitter->rev,transmitter->exciter,transmitter->alc);
+ }
+#else
meter_update(active_receiver,POWER,transmitter->fwd,transmitter->rev,transmitter->exciter,transmitter->alc);
+#endif
return TRUE; // keep going
}
tx->low_latency=0;
+ tx->twotone=0;
#ifdef PURESIGNAL
tx->puresignal=0;
tx->feedback=0;
- tx->twotone=0;
tx->auto_on=0;
tx->single_on=0;
#endif
+ tx->attenuation=0;
tx->ctcss=0;
tx->ctcss_frequency=100.0;
vfo_update();
}
+void tx_set_ps_sample_rate(TRANSMITTER *tx,int rate) {
+ SetPSFeedbackRate (tx->id,rate);
+}
+#endif
+
void tx_set_twotone(TRANSMITTER *tx,int state) {
transmitter->twotone=state;
if(state) {
+ // DL1YCF: set frequencies and levels
+ SetTXAPostGenTTFreq(transmitter->id, 900.0, 1700.0);
+ SetTXAPostGenTTMag (transmitter->id, 0.49, 0.49);
SetTXAPostGenMode(transmitter->id, 1);
SetTXAPostGenRun(transmitter->id, 1);
} else {
g_idle_add(ext_mox_update,(gpointer)(long)state);
}
-void tx_set_ps_sample_rate(TRANSMITTER *tx,int rate) {
- SetPSFeedbackRate (tx->id,rate);
-}
-#endif
//
// This is the old key-down/key-up interface for iambic.c
int low_latency;
+// want to have a two-tone generator in any case
+ int twotone;
#ifdef PURESIGNAL
int puresignal;
- int twotone;
int feedback;
int auto_on;
int single_on;
static gfloat filter_left;
static gfloat filter_right;
+#ifdef SPLIT_RXTX
+#include "new_menu.h"
+#include "ext.h"
+#include "sliders.h"
+static gboolean making_active = FALSE;
+#endif
/* Create a new surface of the appropriate size to store our scribbles */
static gboolean
has_moved=FALSE;
pressed=TRUE;
}
+#ifdef SPLIT_RXTX
+ making_active=(active_receiver != receiver[0]);
+#endif
return TRUE;
}
int display_width=gtk_widget_get_allocated_width (tx->panadapter);
int display_height=gtk_widget_get_allocated_height (tx->panadapter);
+#ifdef SPLIT_RXTX
+ if (making_active) {
+ active_receiver=receiver[0];
+ making_active=FALSE;
+ g_idle_add(menu_active_receiver_changed,NULL);
+ g_idle_add(ext_vfo_update,NULL);
+ g_idle_add(sliders_active_receiver_changed,NULL);
+ }
+#endif
if(pressed) {
int x=(int)event->x;
if (event->button == 1) {
{
int x, y;
GdkModifierType state;
+#ifdef SPLIT_RXTX
+ if (!making_active) {
+#endif
gdk_window_get_device_position (event->window,
event->device,
&x,
last_x=x;
has_moved=TRUE;
}
+#ifdef SPLIT_RXTX
+ }
+#endif
return TRUE;
}
int display_height=gtk_widget_get_allocated_height (tx->panadapter);
int id=0;
+#ifdef SPLIT_RXTX
+ id = active_receiver->id;
+ if (split) {
+ id = 1-id;
+ }
+#else
if(split) {
id=1;
}
+#endif
samples=tx->pixel_samples;
//hz_per_pixel=(double)tx->output_rate/(double)display_width;
int id=active_receiver->id;
FILTER* band_filters=filters[vfo[id].mode];
FILTER* band_filter=&band_filters[vfo[id].filter];
+ int have_noise=1;
if(vfo_surface) {
char temp_text[32];
cairo_t *cr;
case modeAM:
sprintf(temp_text,"%s %s %s",mode_string[vfo[id].mode],band_filter->title,dv);
break;
+#ifdef DIGI_MODES
+ case modeDIGU:
+ case modeDIGL:
+ // No band filter title
+ sprintf(temp_text,"%s %s",mode_string[vfo[id].mode],dv);
+ // used later on NOT to display noise reduction
+ have_noise=0;
+ break;
+#endif
default:
sprintf(temp_text,"%s %s",mode_string[vfo[id].mode],band_filter->title);
break;
}
cairo_show_text(cr, temp_text);
+ // DL1YCF: in what follows, we want to display the VFO frequency
+ // on which we currently transmit a signal with red colour.
+ // If it is out-of-band, we display "Out of band" in red.
+ // Frequencies we are not transmitting on are displayed in green
+ // (dimmed if the freq. does not belong to the active receiver).
+ // Depending on which receiver is the active one, and if we use slit,
+ // the following frequencies are used for transmitting (see old_protocol.c):
+ // id == 0, split == 0 : TX freq = VFO_A
+ // id == 0, split == 1 : TX freq = VFO_B
+ // id == 1, split == 0 : TX freq = VFO_B
+ // id == 1, split == 1 : TX freq = VFO_A
+
long long af=vfo[0].frequency+vfo[0].offset;
- if(transmitter->out_of_band && !split) {
- cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
- sprintf(temp_text,"VFO A: Out of band");
+ sprintf(temp_text,"VFO A: %0lld.%06lld",af/(long long)1000000,af%(long long)1000000);
+ if(isTransmitting() && ((id == 0 && !split) || (id == 1 && split))) {
+ if (transmitter->out_of_band) sprintf(temp_text,"VFO A: Out of band");
+ cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
} else {
- sprintf(temp_text,"VFO A: %0lld.%06lld",af/(long long)1000000,af%(long long)1000000);
- if(isTransmitting() && !split) {
- cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
- } else {
- if(active_receiver->id==0) {
- cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);
- } else {
- cairo_set_source_rgb(cr, 0.0, 0.65, 0.0);
- }
- }
+ if(id==0) {
+ cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);
+ } else {
+ cairo_set_source_rgb(cr, 0.0, 0.65, 0.0);
+ }
}
cairo_move_to(cr, 5, 38);
cairo_set_font_size(cr, 22);
long long bf=vfo[1].frequency+vfo[1].offset;
- if(transmitter->out_of_band && split) {
- cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
- sprintf(temp_text,"VFO B: Out of band");
+ sprintf(temp_text,"VFO B: %0lld.%06lld",bf/(long long)1000000,bf%(long long)1000000);
+ if(isTransmitting() && ((id == 0 && split) || (id == 1 && !split))) {
+ if (transmitter->out_of_band) sprintf(temp_text,"VFO B: Out of band");
+ cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
} else {
- sprintf(temp_text,"VFO B: %0lld.%06lld",bf/(long long)1000000,bf%(long long)1000000);
- if(isTransmitting() && split) {
- cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
- } else {
- if(active_receiver->id==1) {
- cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);
- } else {
- cairo_set_source_rgb(cr, 0.0, 0.65, 0.0);
- }
- }
+ if(id==1) {
+ cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);
+ } else {
+ cairo_set_source_rgb(cr, 0.0, 0.65, 0.0);
+ }
}
cairo_move_to(cr, 260, 38);
cairo_show_text(cr, temp_text);
cairo_show_text(cr, "NB");
cairo_move_to(cr, 175, 50);
- if(active_receiver->nb2) {
+ if(active_receiver->nb2 && have_noise) {
cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
} else {
cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
cairo_show_text(cr, "NB2");
cairo_move_to(cr, 200, 50);
- if(active_receiver->nr) {
+ if(active_receiver->nr && have_noise) {
cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
} else {
cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
cairo_show_text(cr, "NR");
cairo_move_to(cr, 225, 50);
- if(active_receiver->nr2) {
+ if(active_receiver->nr2 && have_noise) {
cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
} else {
cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
cairo_show_text(cr, "NR2");
cairo_move_to(cr, 250, 50);
- if(active_receiver->anf) {
+ if(active_receiver->anf && have_noise) {
cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
} else {
cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
cairo_show_text(cr, "ANF");
cairo_move_to(cr, 275, 50);
- if(active_receiver->snb) {
+ if(active_receiver->snb && have_noise) {
cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
} else {
cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
}
#endif
-#ifdef FREEDV
+#ifdef PURESIGNAL
static void enable_ps_cb(GtkWidget *widget, gpointer data) {
tx_set_ps(transmitter,gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)));
}