From: John Melton - G0ORX/N6LYT Date: Mon, 13 Feb 2017 09:37:30 +0000 (+0000) Subject: New version to support 2 receivers X-Git-Url: https://git.rkrishnan.org/pf/$top_link?a=commitdiff_plain;h=a035bb13f22e9f5e1dac9e5089a58e12b0ae45d0;p=pihpsdr.git New version to support 2 receivers --- diff --git a/Makefile b/Makefile index 773c00b..78ab4d5 100644 --- a/Makefile +++ b/Makefile @@ -3,11 +3,17 @@ GIT_DATE := $(firstword $(shell git --no-pager show --date=short --format="%ai" --name-only)) GIT_VERSION := $(shell git describe --abbrev=0 --tags) +# uncomment the line below to include GPIO +GPIO_INCLUDE=GPIO + +# uncomment the line below to include USB Ozy support +USBOZY_INCLUDE=USBOZY + # uncomment the line below to include support for psk31 -PSK_INCLUDE=PSK +#PSK_INCLUDE=PSK # uncomment the line to below include support for FreeDV codec2 -FREEDV_INCLUDE=FREEDV +#FREEDV_INCLUDE=FREEDV # uncomment the line to below include support for sx1509 i2c expander #SX1509_INCLUDE=sx1509 @@ -15,12 +21,15 @@ FREEDV_INCLUDE=FREEDV # uncomment the line to below include support local CW keyer #LOCALCW_INCLUDE=LOCALCW +# uncomment the line below to include MCP23017 I2C +#I2C_INCLUDE=I2C + #uncomment the line below for the platform being compiled on -UNAME_N=raspberrypi +#UNAME_N=raspberrypi #UNAME_N=odroid #UNAME_N=up #UNAME_N=pine64 -#UNAME_N=x86 +UNAME_N=x86 CC=gcc LINK=gcc @@ -28,6 +37,17 @@ LINK=gcc # uncomment the line below for various debug facilities #DEBUG_OPTION=-D DEBUG +ifeq ($(USBOZY_INCLUDE),USBOZY) +USBOZY_OPTIONS=-D USBOZY +USBOZY_LIBS=-lusb-1.0 +USBOZY_SOURCES= \ +ozyio.c +USBOZY_HEADERS= \ +ozyio.h +USBOZY_OBJS= \ +ozyio.o +endif + # uncomment the line below for LimeSDR (uncomment line below) #LIMESDR_INCLUDE=LIMESDR @@ -88,50 +108,39 @@ beep.o \ iambic.o endif -#required for MRAA GPIO -#MRAA_INCLUDE=MRAA - -ifeq ($(MRAA_INCLUDE),MRAA) - GPIO_OPTIONS=-D GPIO - GPIO_LIBS=-lmraa - GPIO_SOURCES= \ - gpio_mraa.c - GPIO_HEADERS= \ - gpio.h - GPIO_OBJS= \ - gpio_mraa.o -else - ifeq ($(UNAME_N),raspberrypi) +ifeq ($(GPIO_INCLUDE),GPIO) GPIO_OPTIONS=-D GPIO GPIO_LIBS=-lwiringPi -lpigpio - endif - ifeq ($(UNAME_N),odroid) - GPIO_LIBS=-lwiringPi - endif - ifeq ($(SX1509_INCLUDE),sx1509) - GPIO_OPTIONS=-D GPIO - GPIO_OPTIONS+=-D sx1509 - GPIO_LIBS+=-lsx1509 - endif GPIO_SOURCES= \ - gpio.c + gpio.c \ + encoder_menu.c GPIO_HEADERS= \ - gpio.h + gpio.h \ + encoder_menu.h GPIO_OBJS= \ - gpio.o + gpio.o \ + encoder_menu.o +endif + +ifeq ($(I2C_INCLUDE),I2C) + I2C_OPTIONS=-D I2C + I2C_SOURCES=i2c.c + I2C_HEADERS=i2c.h + I2C_OBJS=i2c.o endif #uncomment if build for SHORT FRAMES (MIC and Audio) -SHORT_FRAMES="-D SHORT_FRAMES" +SHORT_FRAMES=-D SHORT_FRAMES GTKINCLUDES=`pkg-config --cflags gtk+-3.0` GTKLIBS=`pkg-config --libs gtk+-3.0` AUDIO_LIBS=-lasound +#AUDIO_LIBS=-lsoundio -OPTIONS=-g -D $(UNAME_N) $(GPIO_OPTIONS) $(LIMESDR_OPTIONS) $(FREEDV_OPTIONS) $(LOCALCW_OPTIONS) $(PSK_OPTIONS) $(SHORT_FRAMES) -D GIT_DATE='"$(GIT_DATE)"' -D GIT_VERSION='"$(GIT_VERSION)"' $(DEBUG_OPTION) -O3 +OPTIONS=-g -Wno-deprecated-declarations -D $(UNAME_N) $(USBOZY_OPTIONS) $(I2C_OPTIONS) $(GPIO_OPTIONS) $(LIMESDR_OPTIONS) $(FREEDV_OPTIONS) $(LOCALCW_OPTIONS) $(PSK_OPTIONS) $(SHORT_FRAMES) -D GIT_DATE='"$(GIT_DATE)"' -D GIT_VERSION='"$(GIT_VERSION)"' $(DEBUG_OPTION) -O3 -LIBS=-lrt -lm -lwdsp -lpthread $(AUDIO_LIBS) $(PSKLIBS) $(GTKLIBS) $(GPIO_LIBS) $(SOAPYSDRLIBS) $(FREEDVLIBS) +LIBS=-lrt -lm -lwdsp -lpthread $(AUDIO_LIBS) $(USBOZY_LIBS) $(PSKLIBS) $(GTKLIBS) $(GPIO_LIBS) $(SOAPYSDRLIBS) $(FREEDVLIBS) INCLUDES=$(GTKINCLUDES) COMPILE=$(CC) $(OPTIONS) $(INCLUDES) @@ -144,12 +153,13 @@ band.c \ configure.c \ frequency.c \ discovered.c \ +discovery.c \ filter.c \ main.c \ new_menu.c \ exit_menu.c \ -general_menu.c \ -audio_menu.c \ +radio_menu.c \ +rx_menu.c \ ant_menu.c \ display_menu.c \ dsp_menu.c \ @@ -166,12 +176,12 @@ mode_menu.c \ filter_menu.c \ noise_menu.c \ agc_menu.c \ -fm_menu.c \ vox_menu.c \ diversity_menu.c \ freqent_menu.c \ +tx_menu.c \ +vfo_menu.c \ test_menu.c \ -rit.c \ meter.c \ mode.c \ old_discovery.c \ @@ -179,21 +189,23 @@ new_discovery.c \ old_protocol.c \ new_protocol.c \ new_protocol_programmer.c \ -panadapter.c \ +rx_panadapter.c \ +tx_panadapter.c \ property.c \ radio.c \ +receiver.c \ rigctl.c \ -signal.c \ -splash.c \ toolbar.c \ +transmitter.c \ sliders.c \ version.c \ vfo.c \ waterfall.c \ -wdsp_init.c \ button_text.c \ vox.c \ update.c \ +store.c \ +store_menu.c \ memory.c @@ -207,11 +219,12 @@ frequency.h \ bandstack.h \ channel.h \ discovered.h \ +discovery.h \ filter.h \ new_menu.h \ +rx_menu.h \ exit_menu.h \ -general_menu.h \ -audio_menu.h \ +radio_menu.h \ ant_menu.h \ display_menu.h \ dsp_menu.h \ @@ -228,33 +241,35 @@ mode_menu.h \ filter_menu.h \ noise_menu.h \ agc_menu.h \ -fm_menu.h \ vox_menu.h \ diversity_menu.h \ freqent_menu.h \ +tx_menu.h \ +vfo_menu.h \ test_menu.h \ -rit.h \ meter.h \ mode.h \ old_discovery.h \ new_discovery.h \ old_protocol.h \ new_protocol.h \ -panadapter.h \ +rx_panadapter.h \ +tx_panadapter.h \ property.h \ radio.h \ +receiver.h \ rigctl.h \ -signal.h \ -splash.h \ toolbar.h \ +transmitter.h \ sliders.h \ version.h \ vfo.h \ waterfall.h \ -wdsp_init.h \ button_text.h \ vox.h \ update.h \ +store.h \ +store_menu.h \ memory.h @@ -264,13 +279,14 @@ band.o \ configure.o \ frequency.o \ discovered.o \ +discovery.o \ filter.o \ version.o \ main.o \ new_menu.o \ +rx_menu.o \ exit_menu.o \ -general_menu.o \ -audio_menu.o \ +radio_menu.o \ ant_menu.o \ display_menu.o \ dsp_menu.o \ @@ -287,12 +303,12 @@ mode_menu.o \ filter_menu.o \ noise_menu.o \ agc_menu.o \ -fm_menu.o \ vox_menu.o \ diversity_menu.o \ freqent_menu.o \ +tx_menu.o \ +vfo_menu.o \ test_menu.o \ -rit.o \ meter.o \ mode.o \ old_discovery.o \ @@ -300,29 +316,31 @@ new_discovery.o \ old_protocol.o \ new_protocol.o \ new_protocol_programmer.o \ -panadapter.o \ +rx_panadapter.o \ +tx_panadapter.o \ property.o \ radio.o \ +receiver.o \ rigctl.o \ -signal.o \ -splash.o \ toolbar.o \ +transmitter.o \ sliders.o \ vfo.o \ waterfall.o \ -wdsp_init.o \ button_text.o \ vox.o \ update.o \ +store.o \ +store_menu.o \ memory.o -all: prebuild $(PROGRAM) $(HEADERS) $(LIMESDR_HEADERS) $(FREEDV_HEADERS) $(LOCALCW_HEADERS) $(GPIO_HEADERS) $(PSK_HEADERS) $(SOURCES) $(LIMESDR_SOURCES) $(FREEDV_SOURCES) $(GPIO_SOURCES) $(PSK_SOURCES) +all: prebuild $(PROGRAM) $(HEADERS) $(USBOZY_HEADERS) $(LIMESDR_HEADERS) $(FREEDV_HEADERS) $(LOCALCW_HEADERS) $(I2C_HEADERS) $(GPIO_HEADERS) $(PSK_HEADERS) $(SOURCES) $(USBOZY_SOURCES) $(LIMESDR_SOURCES) $(FREEDV_SOURCES) $(I2C_SOURCES) $(GPIO_SOURCES) $(PSK_SOURCES) prebuild: rm -f version.o -$(PROGRAM): $(OBJS) $(LIMESDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(GPIO_OBJS) $(PSK_OBJS) - $(LINK) -o $(PROGRAM) $(OBJS) $(GPIO_OBJS) $(LIMESDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(PSK_OBJS) $(LIBS) +$(PROGRAM): $(OBJS) $(USBOZY_OBJS) $(LIMESDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(I2C_OBJS) $(GPIO_OBJS) $(PSK_OBJS) + $(LINK) -o $(PROGRAM) $(OBJS) $(USBOZY_OBJS) $(I2C_OBJS) $(GPIO_OBJS) $(LIMESDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(PSK_OBJS) $(LIBS) .c.o: $(COMPILE) -c -o $@ $< diff --git a/agc_menu.c b/agc_menu.c index 1c88fcb..1f8485c 100644 --- a/agc_menu.c +++ b/agc_menu.c @@ -27,6 +27,7 @@ #include "band.h" #include "channel.h" #include "radio.h" +#include "receiver.h" #include "vfo.h" #include "button_text.h" @@ -44,8 +45,9 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat } static gboolean agc_select_cb (GtkWidget *widget, gpointer data) { - agc=(int)data; - wdsp_set_agc(CHANNEL_RX0, agc); + active_receiver->agc=(int)data; + //wdsp_set_agc(CHANNEL_RX0, agc); + set_agc(active_receiver, active_receiver->agc); vfo_update(NULL); } @@ -80,37 +82,42 @@ void agc_menu(GtkWidget *parent) { g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL); gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1); + char label[32]; + sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B"); + GtkWidget *rx_label=gtk_label_new(label); + gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1); + GtkWidget *b_off=gtk_radio_button_new_with_label(NULL,"Off"); //gtk_widget_override_font(b_off, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_off), agc==AGC_OFF); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_off), active_receiver->agc==AGC_OFF); gtk_widget_show(b_off); gtk_grid_attach(GTK_GRID(grid),b_off,0,1,2,1); g_signal_connect(b_off,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_OFF); GtkWidget *b_long=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_off),"Long"); //gtk_widget_override_font(b_long, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_long), agc==AGC_LONG); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_long), active_receiver->agc==AGC_LONG); gtk_widget_show(b_long); gtk_grid_attach(GTK_GRID(grid),b_long,0,2,2,1); g_signal_connect(b_long,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_LONG); GtkWidget *b_slow=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_long),"Slow"); //gtk_widget_override_font(b_slow, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_slow), agc==AGC_SLOW); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_slow), active_receiver->agc==AGC_SLOW); gtk_widget_show(b_slow); gtk_grid_attach(GTK_GRID(grid),b_slow,0,3,2,1); g_signal_connect(b_slow,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_SLOW); GtkWidget *b_medium=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_slow),"Medium"); //gtk_widget_override_font(b_medium, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_medium), agc==AGC_MEDIUM); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_medium), active_receiver->agc==AGC_MEDIUM); gtk_widget_show(b_medium); gtk_grid_attach(GTK_GRID(grid),b_medium,0,4,2,1); g_signal_connect(b_medium,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_MEDIUM); GtkWidget *b_fast=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_medium),"Fast"); //gtk_widget_override_font(b_fast, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_fast), agc==AGC_FAST); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_fast), active_receiver->agc==AGC_FAST); gtk_widget_show(b_fast); gtk_grid_attach(GTK_GRID(grid),b_fast,0,5,2,1); g_signal_connect(b_fast,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_FAST); diff --git a/ant_menu.c b/ant_menu.c index de36b4c..9cef503 100644 --- a/ant_menu.c +++ b/ant_menu.c @@ -47,14 +47,18 @@ static void rx_ant_cb(GtkWidget *widget, gpointer data) { int ant=((int)data)&0xF; BAND *band=band_get_band(b); band->alexRxAntenna=ant; - set_alex_rx_antenna(ant); + if(active_receiver->id==0) { + set_alex_rx_antenna(ant); + } } static void rx_lime_ant_cb(GtkWidget *widget, gpointer data) { int ant=((int)data)&0xF; BAND *band=band_get_current_band(); band->alexRxAntenna=ant; - set_alex_rx_antenna(ant); + if(active_receiver->id==0) { + set_alex_rx_antenna(ant); + } } static void tx_ant_cb(GtkWidget *widget, gpointer data) { @@ -62,7 +66,9 @@ static void tx_ant_cb(GtkWidget *widget, gpointer data) { int ant=((int)data)&0xF; BAND *band=band_get_band(b); band->alexTxAntenna=ant; - set_alex_tx_antenna(ant); + if(active_receiver->id==0) { + set_alex_tx_antenna(ant); + } } void ant_menu(GtkWidget *parent) { diff --git a/audio.c b/audio.c index 0b3ae13..d7fa469 100644 --- a/audio.c +++ b/audio.c @@ -32,16 +32,17 @@ #include -#include "audio.h" #include "new_protocol.h" #include "old_protocol.h" #include "radio.h" +#include "receiver.h" +#include "audio.h" int audio = 0; int audio_buffer_size = 256; // samples (both left and right) int mic_buffer_size = 720; // samples (both left and right) -static snd_pcm_t *playback_handle=NULL; +//static snd_pcm_t *playback_handle=NULL; static snd_pcm_t *record_handle=NULL; // each buffer contains 63 samples of left and right audio at 16 bits @@ -49,16 +50,16 @@ static snd_pcm_t *record_handle=NULL; #define AUDIO_SAMPLE_SIZE 2 #define AUDIO_CHANNELS 2 #define AUDIO_BUFFERS 10 -#define AUDIO_BUFFER_SIZE (AUDIO_SAMPLE_SIZE*AUDIO_CHANNELS*audio_buffer_size) +#define OUTPUT_BUFFER_SIZE (AUDIO_SAMPLE_SIZE*AUDIO_CHANNELS*audio_buffer_size) #define MIC_BUFFER_SIZE (AUDIO_SAMPLE_SIZE*AUDIO_CHANNELS*mic_buffer_size) -static unsigned char *audio_buffer=NULL; -static int audio_offset=0; +//static unsigned char *audio_buffer=NULL; +//static int audio_offset=0; static unsigned char *mic_buffer=NULL; -static pthread_t mic_read_thread_id; +static GThread *mic_read_thread_id; static int running=FALSE; @@ -66,29 +67,29 @@ static void *mic_read_thread(void *arg); char *input_devices[16]; int n_input_devices=0; -int n_selected_input_device=-1; +//int n_selected_input_device=-1; char *output_devices[16]; int n_output_devices=0; -int n_selected_output_device=-1; +//int n_selected_output_device=-1; -int audio_open_output() { +int audio_open_output(RECEIVER *rx) { int err; snd_pcm_hw_params_t *hw_params; int rate=48000; int dir=0; - if(n_selected_output_device<0 || n_selected_output_device>=n_output_devices) { - n_selected_output_device=-1; + if(rx->audio_device<0 || rx->audio_device>=n_output_devices) { + rx->audio_device=-1; return -1; } int i; - char hw[16]; - char *selected=output_devices[n_selected_output_device]; + char hw[64]; + char *selected=output_devices[rx->audio_device]; -fprintf(stderr,"audio_open_output: selected=%d:%s\n",n_selected_output_device,selected); +fprintf(stderr,"audio_open_output: selected=%d:%s\n",rx->audio_device,selected); i=0; while(selected[i]!=' ') { @@ -97,7 +98,7 @@ fprintf(stderr,"audio_open_output: selected=%d:%s\n",n_selected_output_device,se } hw[i]='\0'; - if ((err = snd_pcm_open (&playback_handle, hw, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { + if ((err = snd_pcm_open (&rx->playback_handle, hw, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { fprintf (stderr, "audio_open_output: cannot open audio device %s (%s)\n", hw, snd_strerror (err)); @@ -111,38 +112,38 @@ fprintf(stderr,"audio_open_output: selected=%d:%s\n",n_selected_output_device,se return -1; } - if ((err = snd_pcm_hw_params_any (playback_handle, hw_params)) < 0) { + if ((err = snd_pcm_hw_params_any (rx->playback_handle, hw_params)) < 0) { fprintf (stderr, "audio_open_output: cannot initialize hardware parameter structure (%s)\n", snd_strerror (err)); return -1; } - if ((err = snd_pcm_hw_params_set_access (playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { + if ((err = snd_pcm_hw_params_set_access (rx->playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf (stderr, "audio_open_output: cannot set access type (%s)\n", snd_strerror (err)); return -1; } - if ((err = snd_pcm_hw_params_set_format (playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { + if ((err = snd_pcm_hw_params_set_format (rx->playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { fprintf (stderr, "audio_open_output: cannot set sample format (%s)\n", snd_strerror (err)); return -1; } - if ((err = snd_pcm_hw_params_set_rate_near (playback_handle, hw_params, &rate, &dir)) < 0) { + if ((err = snd_pcm_hw_params_set_rate_near (rx->playback_handle, hw_params, &rate, &dir)) < 0) { fprintf (stderr, "audio_open_output: cannot set sample rate (%s)\n", snd_strerror (err)); return -1; } - if ((err = snd_pcm_hw_params_set_channels (playback_handle, hw_params, 2)) < 0) { + if ((err = snd_pcm_hw_params_set_channels (rx->playback_handle, hw_params, 2)) < 0) { fprintf (stderr, "audio_open_output: cannot set channel count (%s)\n", snd_strerror (err)); return -1; } - if ((err = snd_pcm_hw_params (playback_handle, hw_params)) < 0) { + if ((err = snd_pcm_hw_params (rx->playback_handle, hw_params)) < 0) { fprintf (stderr, "audio_open_output: cannot set parameters (%s)\n", snd_strerror (err)); return -1; @@ -150,8 +151,8 @@ fprintf(stderr,"audio_open_output: selected=%d:%s\n",n_selected_output_device,se snd_pcm_hw_params_free (hw_params); - audio_offset=0; - audio_buffer=(unsigned char *)malloc(AUDIO_BUFFER_SIZE); + rx->playback_offset=0; + rx->playback_buffer=(unsigned char *)malloc(OUTPUT_BUFFER_SIZE); return 0; } @@ -162,16 +163,16 @@ int audio_open_input() { int rate=48000; int dir=0; -fprintf(stderr,"audio_open_input: %d\n",n_selected_input_device); - if(n_selected_input_device<0 || n_selected_input_device>=n_input_devices) { - n_selected_input_device=-1; +fprintf(stderr,"audio_open_input: %d\n",transmitter->input_device); + if(transmitter->input_device<0 || transmitter->input_device>=n_input_devices) { + transmitter->input_device=0; return -1; } int i; char hw[16]; - char *selected=input_devices[n_selected_input_device]; - fprintf(stderr,"audio_open_input: selected=%d:%s\n",n_selected_input_device,selected); + char *selected=input_devices[transmitter->input_device]; + fprintf(stderr,"audio_open_input: selected=%d:%s\n",transmitter->input_device,selected); switch(protocol) { case ORIGINAL_PROTOCOL: @@ -248,23 +249,24 @@ fprintf(stderr,"audio_open_input: %d\n",n_selected_input_device); mic_buffer=(unsigned char *)malloc(MIC_BUFFER_SIZE); running=TRUE; - err=pthread_create(&mic_read_thread_id,NULL,mic_read_thread,NULL); - if(err != 0) { - fprintf(stderr,"pthread_create failed on mic_read_thread: rc=%d\n", err); - return -1; + mic_read_thread_id = g_thread_new( "local mic", mic_read_thread, NULL); + if(!mic_read_thread_id ) + { + fprintf(stderr,"g_thread_new failed on mic_read_thread\n"); } + return 0; } -void audio_close_output() { - if(playback_handle!=NULL) { - snd_pcm_close (playback_handle); - playback_handle=NULL; +void audio_close_output(RECEIVER *rx) { + if(rx->playback_handle!=NULL) { + snd_pcm_close (rx->playback_handle); + rx->playback_handle=NULL; } - if(audio_buffer!=NULL) { - free(audio_buffer); - audio_buffer=NULL; + if(rx->playback_buffer!=NULL) { + free(rx->playback_buffer); + rx->playback_buffer=NULL; } } @@ -280,49 +282,49 @@ void audio_close_input() { } } -int audio_write(short left_sample,short right_sample) { +int audio_write(RECEIVER *rx,short left_sample,short right_sample) { snd_pcm_sframes_t delay; int error; long trim; - if(playback_handle!=NULL && audio_buffer!=NULL) { - audio_buffer[audio_offset++]=left_sample; - audio_buffer[audio_offset++]=left_sample>>8; - audio_buffer[audio_offset++]=right_sample; - audio_buffer[audio_offset++]=right_sample>>8; + if(rx->playback_handle!=NULL && rx->playback_buffer!=NULL) { + rx->playback_buffer[rx->playback_offset++]=right_sample; + rx->playback_buffer[rx->playback_offset++]=right_sample>>8; + rx->playback_buffer[rx->playback_offset++]=left_sample; + rx->playback_buffer[rx->playback_offset++]=left_sample>>8; - if(audio_offset==AUDIO_BUFFER_SIZE) { + if(rx->playback_offset==OUTPUT_BUFFER_SIZE) { trim=0; - if(snd_pcm_delay(playback_handle,&delay)==0) { + if(snd_pcm_delay(rx->playback_handle,&delay)==0) { if(delay>2048) { trim=delay-2048; //fprintf(stderr,"audio delay=%ld trim=%ld\n",delay,trim); } } - if ((error = snd_pcm_writei (playback_handle, audio_buffer, audio_buffer_size-trim)) != audio_buffer_size-trim) { + if ((error = snd_pcm_writei (rx->playback_handle, rx->playback_buffer, audio_buffer_size-trim)) != audio_buffer_size-trim) { if(error==-EPIPE) { - if ((error = snd_pcm_prepare (playback_handle)) < 0) { + if ((error = snd_pcm_prepare (rx->playback_handle)) < 0) { fprintf (stderr, "audio_write: cannot prepare audio interface for use (%s)\n", snd_strerror (error)); return -1; } - if ((error = snd_pcm_writei (playback_handle, audio_buffer, audio_buffer_size)) != audio_buffer_size) { + if ((error = snd_pcm_writei (rx->playback_handle, rx->playback_buffer, audio_buffer_size-trim)) != audio_buffer_size) { fprintf (stderr, "audio_write: write to audio interface failed (%s)\n", snd_strerror (error)); return -1; } } } - audio_offset=0; + rx->playback_offset=0; } } return 0; } -static void *mic_read_thread(void *arg) { +static gpointer mic_read_thread(gpointer arg) { int rc; if ((rc = snd_pcm_prepare (record_handle)) < 0) { fprintf (stderr, "mic_read_thread: cannot prepare audio interface for use (%s)\n", @@ -359,25 +361,27 @@ fprintf(stderr,"mic_read_thread: exiting\n"); } -void audio_get_cards(int input) { +void audio_get_cards() { snd_ctl_card_info_t *info; snd_pcm_info_t *pcminfo; snd_ctl_card_info_alloca(&info); snd_pcm_info_alloca(&pcminfo); int i; + char *device_id=malloc(64); + int card = -1; - if(input) { - for(i=0;i= 0 && card >= 0) { int err = 0; snd_ctl_t *handle; @@ -393,29 +397,60 @@ void audio_get_cards(int input) { } int dev = -1; + while (snd_ctl_pcm_next_device(handle, &dev) >= 0 && dev >= 0) { snd_pcm_info_set_device(pcminfo, dev); snd_pcm_info_set_subdevice(pcminfo, 0); - snd_pcm_info_set_stream(pcminfo, input ? SND_PCM_STREAM_CAPTURE - : SND_PCM_STREAM_PLAYBACK); - if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) { - continue; - } - char *device_id=malloc(64); - - snprintf(device_id, 64, "plughw:%d,%d %s", card, dev, snd_ctl_card_info_get_name(info)); - if(input) { -fprintf(stderr,"input_device: %s\n",device_id); + // input devices + snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE); + if ((err = snd_ctl_pcm_info(handle, pcminfo)) == 0) { + snprintf(device_id, 64, "plughw:%d,%d %s", card, dev, snd_ctl_card_info_get_name(info)); input_devices[n_input_devices++]=device_id; - } else { +fprintf(stderr,"input_device: %s\n",device_id); + } + + // ouput devices + snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK); + if ((err = snd_ctl_pcm_info(handle, pcminfo)) == 0) { + snprintf(device_id, 64, "plughw:%d,%d %s", card, dev, snd_ctl_card_info_get_name(info)); output_devices[n_output_devices++]=device_id; fprintf(stderr,"output_device: %s\n",device_id); } - } snd_ctl_close(handle); + + } + + // look for dmix + void **hints, **n; + char *name, *descr, *io; + + if (snd_device_name_hint(-1, "pcm", &hints) < 0) + return; + n = hints; + while (*n != NULL) { + name = snd_device_name_get_hint(*n, "NAME"); + descr = snd_device_name_get_hint(*n, "DESC"); + io = snd_device_name_get_hint(*n, "IOID"); + + if(strncmp("dmix:", name, 5)==0/* || strncmp("pulse", name, 5)==0*/) { + fprintf(stderr,"name=%s descr=%s io=%s\n",name, descr, io); + char *device_id=malloc(64); + + snprintf(device_id, 64, "%s", name); + output_devices[n_output_devices++]=device_id; +fprintf(stderr,"output_device: %s\n",device_id); + } + if (name != NULL) + free(name); + if (descr != NULL) + free(descr); + if (io != NULL) + free(io); + n++; } + snd_device_name_free_hint(hints); } diff --git a/audio.h b/audio.h index 57ad396..e8a56f4 100644 --- a/audio.h +++ b/audio.h @@ -20,18 +20,20 @@ #ifndef _AUDIO_H #define _AUDIO_H +#include "receiver.h" + extern char *input_devices[]; extern int n_input_devices; -extern int n_selected_input_device; +//extern int n_selected_input_device; extern char *output_devices[]; extern int n_output_devices; -extern int n_selected_output_device; +//extern int n_selected_output_device; -extern int audio_open_output(); extern int audio_open_input(); -extern void audio_close_output(); extern void audio_close_input(); -extern int audio_write(short left_sample,short right_sample); +extern int audio_open_output(RECEIVER *rx); +extern void audio_close_output(RECEIVER *rx); +extern int audio_write(RECEIVER *rx,short left_sample,short right_sample); extern void audio_get_cards(); #endif diff --git a/audio_menu.c b/audio_menu.c index 2045be8..2826dce 100644 --- a/audio_menu.c +++ b/audio_menu.c @@ -50,7 +50,7 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat static void binaural_cb(GtkWidget *widget, gpointer data) { binaural=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)); - SetRXAPanelBinaural(CHANNEL_RX0, binaural); + SetRXAPanelBinaural(active_receiver->id, binaural); } static void micboost_cb(GtkWidget *widget, gpointer data) { @@ -59,7 +59,7 @@ static void micboost_cb(GtkWidget *widget, gpointer data) { static void linein_cb(GtkWidget *widget, gpointer data) { mic_linein=mic_linein==1?0:1; - linein_changed(); + g_idle_add(linein_changed,NULL); } static void local_audio_cb(GtkWidget *widget, gpointer data) { diff --git a/band.c b/band.c index 980d94f..c3fa969 100644 --- a/band.c +++ b/band.c @@ -39,135 +39,135 @@ int xvtr_band=BANDS; */ /* ----------------------------------------------------------------------------*/ BANDSTACK_ENTRY bandstack_entries136[] = - {{135800,135800,modeCWL,filterF4,-2800,-200,-2800,-200}, - {137100,137100,modeCWL,filterF4,-2800,-200,-2800,-200}}; + {{135800,modeCWL,filterF6,-2800,-200,-2800,-200}, + {137100,modeCWL,filterF6,-2800,-200,-2800,-200}}; BANDSTACK_ENTRY bandstack_entries472[] = - {{472100LL,472100LL,modeCWL,filterF4,-2800,-200,-2800,-200}, - {475100LL,475100LL,modeCWL,filterF4,-2800,-200,-2800,-200}}; + {{472100LL,modeCWL,filterF6,-2800,-200,-2800,-200}, + {475100LL,modeCWL,filterF6,-2800,-200,-2800,-200}}; BANDSTACK_ENTRY bandstack_entries160[] = - {{1810000LL,1810000LL,modeCWL,filterF4,-2800,-200,-2800,-200}, - {1835000LL,1835000LL,modeCWU,filterF0,-2800,-200,-2800,-200}, - {1845000LL,1845000LL,modeUSB,filterF5,-2800,-200,-2800,-200}}; + {{1810000LL,modeCWL,filterF6,-2800,-200,-2800,-200}, + {1835000LL,modeCWU,filterF6,-2800,-200,-2800,-200}, + {1845000LL,modeUSB,filterF5,-2800,-200,-2800,-200}}; BANDSTACK_ENTRY bandstack_entries80[] = - {{3501000LL,3501000LL,modeCWL,filterF0,-2800,-200,-2800,-200}, - {3751000LL,3751000LL,modeLSB,filterF5,-2800,-200,-2800,-200}, - {3850000LL,3850000LL,modeLSB,filterF5,-2800,-200,-2800,-200}}; + {{3501000LL,modeCWL,filterF6,-2800,-200,-2800,-200}, + {3751000LL,modeLSB,filterF5,-2800,-200,-2800,-200}, + {3850000LL,modeLSB,filterF5,-2800,-200,-2800,-200}}; BANDSTACK_ENTRY bandstack_entries60[] = - {{5330500LL,5330500LL,modeUSB,filterF5,-2800,-200,-2800,-200}, - {5346500LL,5346500LL,modeUSB,filterF5,-2800,-200,-2800,-200}, - {5366500LL,5366500LL,modeUSB,filterF5,-2800,-200,-2800,-200}, - {5371500LL,5371500LL,modeUSB,filterF5,-2800,-200,-2800,-200}, - {5403500LL,5403500LL,modeUSB,filterF5,-2800,-200,-2800,-200}}; + {{5330500LL,modeUSB,filterF5,-2800,-200,-2800,-200}, + {5346500LL,modeUSB,filterF5,-2800,-200,-2800,-200}, + {5366500LL,modeUSB,filterF5,-2800,-200,-2800,-200}, + {5371500LL,modeUSB,filterF5,-2800,-200,-2800,-200}, + {5403500LL,modeUSB,filterF5,-2800,-200,-2800,-200}}; BANDSTACK_ENTRY bandstack_entries40[] = - {{7001000LL,7001000LL,modeCWL,filterF0,-2800,-200,-2800,-200}, - {7152000LL,7152000LL,modeLSB,filterF5,-2800,-200,-2800,-200}, - {7255000LL,7255000LL,modeLSB,filterF5,-2800,-200,-2800,-200}}; + {{7001000LL,modeCWL,filterF6,-2800,-200,-2800,-200}, + {7152000LL,modeLSB,filterF5,-2800,-200,-2800,-200}, + {7255000LL,modeLSB,filterF5,-2800,-200,-2800,-200}}; BANDSTACK_ENTRY bandstack_entries30[] = - {{10120000LL,10120000LL,modeCWU,filterF0,200,2800,200,2800}, - {10130000LL,10130000LL,modeCWU,filterF0,200,2800,200,2800}, - {10140000LL,10140000LL,modeCWU,filterF4,200,2800,200,2800}}; + {{10120000LL,modeCWU,filterF6,200,2800,200,2800}, + {10130000LL,modeCWU,filterF6,200,2800,200,2800}, + {10140000LL,modeCWU,filterF6,200,2800,200,2800}}; BANDSTACK_ENTRY bandstack_entries20[] = - {{14010000LL,14010000LL,modeCWU,filterF0,200,2800,200,2800}, - {14150000LL,14010000LL,modeUSB,filterF5,200,2800,200,2800}, - {14230000LL,14010000LL,modeUSB,filterF5,200,2800,200,2800}, - {14336000LL,14010000LL,modeUSB,filterF5,200,2800,200,2800}}; + {{14010000LL,modeCWU,filterF6,200,2800,200,2800}, + {14150000LL,modeUSB,filterF5,200,2800,200,2800}, + {14230000LL,modeUSB,filterF5,200,2800,200,2800}, + {14336000LL,modeUSB,filterF5,200,2800,200,2800}}; BANDSTACK_ENTRY bandstack_entries18[] = - {{18068600LL,18068600LL,modeCWU,filterF0,200,2800,200,2800}, - {18125000LL,18068600LL,modeUSB,filterF5,200,2800,200,2800}, - {18140000LL,18068600LL,modeUSB,filterF5,200,2800,200,2800}}; + {{18068600LL,modeCWU,filterF6,200,2800,200,2800}, + {18125000LL,modeUSB,filterF5,200,2800,200,2800}, + {18140000LL,modeUSB,filterF5,200,2800,200,2800}}; BANDSTACK_ENTRY bandstack_entries15[] = - {{21001000LL,21001000LL,modeCWU,filterF0,200,2800,200,2800}, - {21255000LL,21001000LL,modeUSB,filterF5,200,2800,200,2800}, - {21300000LL,21001000LL,modeUSB,filterF5,200,2800,200,2800}}; + {{21001000LL,modeCWU,filterF6,200,2800,200,2800}, + {21255000LL,modeUSB,filterF5,200,2800,200,2800}, + {21300000LL,modeUSB,filterF5,200,2800,200,2800}}; BANDSTACK_ENTRY bandstack_entries12[] = - {{24895000LL,24895000LL,modeCWU,filterF0,200,2800,200,2800}, - {24900000LL,24895000LL,modeUSB,filterF5,200,2800,200,2800}, - {24910000LL,24895000LL,modeUSB,filterF5,200,2800,200,2800}}; + {{24895000LL,modeCWU,filterF6,200,2800,200,2800}, + {24900000LL,modeUSB,filterF5,200,2800,200,2800}, + {24910000LL,modeUSB,filterF5,200,2800,200,2800}}; BANDSTACK_ENTRY bandstack_entries10[] = - {{28010000LL,28010000LL,modeCWU,filterF0,200,2800,200,2800}, - {28300000LL,28010000LL,modeUSB,filterF5,200,2800,200,2800}, - {28400000LL,28010000LL,modeUSB,filterF5,200,2800,200,2800}}; + {{28010000LL,modeCWU,filterF6,200,2800,200,2800}, + {28300000LL,modeUSB,filterF5,200,2800,200,2800}, + {28400000LL,modeUSB,filterF5,200,2800,200,2800}}; BANDSTACK_ENTRY bandstack_entries50[] = - {{50010000LL,50010000LL,modeCWU,filterF0,200,2800,200,2800}, - {50125000LL,50010000LL,modeUSB,filterF5,200,2800,200,2800}, - {50200000LL,50010000LL,modeUSB,filterF5,200,2800,200,2800}}; + {{50010000LL,modeCWU,filterF6,200,2800,200,2800}, + {50125000LL,modeUSB,filterF5,200,2800,200,2800}, + {50200000LL,modeUSB,filterF5,200,2800,200,2800}}; #ifdef LIMESDR BANDSTACK_ENTRY bandstack_entries70[] = - {{70010000LL,70010000LL,modeCWU,filterF0,200,2800,200,2800}, - {70200000LL,70010000LL,modeUSB,filterF5,200,2800,200,2800}, - {70250000LL,70010000LL,modeUSB,filterF5,200,2800,200,2800}}; + {{70010000LL,modeCWU,filterF6,200,2800,200,2800}, + {70200000LL,modeUSB,filterF5,200,2800,200,2800}, + {70250000LL,modeUSB,filterF5,200,2800,200,2800}}; BANDSTACK_ENTRY bandstack_entries144[] = - {{144010000LL,144010000LL,modeCWU,filterF0,200,2800,200,2800}, - {144200000LL,144010000LL,modeUSB,filterF5,200,2800,200,2800}, - {144250000LL,144010000LL,modeUSB,filterF5,200,2800,200,2800}, - {145600000LL,144010000LL,modeFMN,filterF1,200,2800,200,2800}, - {145725000LL,144010000LL,modeFMN,filterF1,200,2800,200,2800}, - {145900000LL,144010000LL,modeFMN,filterF1,200,2800,200,2800}}; + {{144010000LL,modeCWU,filterF6,200,2800,200,2800}, + {144200000LL,modeUSB,filterF5,200,2800,200,2800}, + {144250000LL,modeUSB,filterF5,200,2800,200,2800}, + {145600000LL,modeFMN,filterF1,200,2800,200,2800}, + {145725000LL,modeFMN,filterF1,200,2800,200,2800}, + {145900000LL,modeFMN,filterF1,200,2800,200,2800}}; BANDSTACK_ENTRY bandstack_entries220[] = - {{220010000LL,220010000,modeCWU,filterF0,200,2800,200,2800}, - {220200000LL,220010000,modeUSB,filterF5,200,2800,200,2800}, - {220250000LL,220010000,modeUSB,filterF5,200,2800,200,2800}}; + {{220010000LL,modeCWU,filterF6,200,2800,200,2800}, + {220200000LL,modeUSB,filterF5,200,2800,200,2800}, + {220250000LL,modeUSB,filterF5,200,2800,200,2800}}; BANDSTACK_ENTRY bandstack_entries430[] = - {{430010000LL,430010000LL,modeCWU,filterF0,200,2800,200,2800}, - {432100000LL,430010000LL,modeUSB,filterF5,200,2800,200,2800}, - {432300000LL,430010000LL,modeUSB,filterF5,200,2800,200,2800}}; + {{430010000LL,modeCWU,filterF6,200,2800,200,2800}, + {432100000LL,modeUSB,filterF5,200,2800,200,2800}, + {432300000LL,modeUSB,filterF5,200,2800,200,2800}}; BANDSTACK_ENTRY bandstack_entries902[] = - {{902010000LL,902010000LL,modeCWU,filterF0,200,2800,200,2800}, - {902100000LL,902010000LL,modeUSB,filterF5,200,2800,200,2800}, - {902300000LL,902010000LL,modeUSB,filterF5,200,2800,200,2800}}; + {{902010000LL,modeCWU,filterF6,200,2800,200,2800}, + {902100000LL,modeUSB,filterF5,200,2800,200,2800}, + {902300000LL,modeUSB,filterF5,200,2800,200,2800}}; BANDSTACK_ENTRY bandstack_entries1240[] = - {{1240010000LL,1240010000LL,modeCWU,filterF0,200,2800,200,2800}, - {1240100000LL,1240010000LL,modeUSB,filterF5,200,2800,200,2800}, - {1240300000LL,1240010000LL,modeUSB,filterF5,200,2800,200,2800}}; + {{1240010000LL,modeCWU,filterF6,200,2800,200,2800}, + {1240100000LL,modeUSB,filterF5,200,2800,200,2800}, + {1240300000LL,modeUSB,filterF5,200,2800,200,2800}}; BANDSTACK_ENTRY bandstack_entries2300[] = - {{2300010000LL,2300010000LL,modeCWU,filterF0,200,2800,200,2800}, - {2300100000LL,2300010000LL,modeUSB,filterF5,200,2800,200,2800}, - {2300300000LL,2300010000LL,modeUSB,filterF5,200,2800,200,2800}}; + {{2300010000LL,modeCWU,filterF6,200,2800,200,2800}, + {2300100000LL,modeUSB,filterF5,200,2800,200,2800}, + {2300300000LL,modeUSB,filterF5,200,2800,200,2800}}; BANDSTACK_ENTRY bandstack_entries3400[] = - {{3400010000LL,3400010000LL,modeCWU,filterF0,200,2800,200,2800}, - {3400100000LL,3400010000LL,modeUSB,filterF5,200,2800,200,2800}, - {3400300000LL,3400010000LL,modeUSB,filterF5,200,2800,200,2800}}; + {{3400010000LL,modeCWU,filterF6,200,2800,200,2800}, + {3400100000LL,modeUSB,filterF5,200,2800,200,2800}, + {3400300000LL,modeUSB,filterF5,200,2800,200,2800}}; BANDSTACK_ENTRY bandstack_entriesAIR[] = - {{118800000LL,118800000LL,modeAM,filterF1,200,2800,200,2800}, - {120000000LL,118800000LL,modeAM,filterF1,200,2800,200,2800}, - {121700000LL,118800000LL,modeAM,filterF1,200,2800,200,2800}, - {124100000LL,118800000LL,modeAM,filterF1,200,2800,200,2800}, - {126600000LL,118800000LL,modeAM,filterF1,200,2800,200,2800}, - {136500000LL,118800000LL,modeAM,filterF1,200,2800,200,2800}}; + {{118800000LL,modeAM,filterF3,200,2800,200,2800}, + {120000000LL,modeAM,filterF3,200,2800,200,2800}, + {121700000LL,modeAM,filterF3,200,2800,200,2800}, + {124100000LL,modeAM,filterF3,200,2800,200,2800}, + {126600000LL,modeAM,filterF3,200,2800,200,2800}, + {136500000LL,modeAM,filterF3,200,2800,200,2800}}; #endif BANDSTACK_ENTRY bandstack_entriesGEN[] = - {{909000LL,909000LL,modeAM,filterF6,-6000,6000,-6000,60000}, - {5975000LL,909000LL,modeAM,filterF6,-6000,6000,-6000,60000}, - {13845000LL,909000LL,modeAM,filterF6,-6000,6000,-6000,60000}}; + {{909000LL,modeAM,filterF3,-6000,6000,-6000,60000}, + {5975000LL,modeAM,filterF3,-6000,6000,-6000,60000}, + {13845000LL,modeAM,filterF3,-6000,6000,-6000,60000}}; BANDSTACK_ENTRY bandstack_entriesWWV[] = - {{2500000LL,2500000LL,modeSAM,filterF6,200,2800,200,2800}, - {5000000LL,2500000LL,modeSAM,filterF6,200,2800,200,2800}, - {10000000LL,2500000LL,modeSAM,filterF6,200,2800,200,2800}, - {15000000LL,2500000LL,modeSAM,filterF6,200,2800,200,2800}, - {20000000LL,2500000LL,modeSAM,filterF6,200,2800,200,2800}}; + {{2500000LL,modeSAM,filterF3,200,2800,200,2800}, + {5000000LL,modeSAM,filterF3,200,2800,200,2800}, + {10000000LL,modeSAM,filterF3,200,2800,200,2800}, + {15000000LL,modeSAM,filterF3,200,2800,200,2800}, + {20000000LL,modeSAM,filterF3,200,2800,200,2800}}; BANDSTACK bandstack160={3,1,bandstack_entries160}; BANDSTACK bandstack80={3,1,bandstack_entries80}; @@ -231,8 +231,8 @@ BANDSTACK bandstack_xvtr_7={1,0,bandstack_entries_xvtr_7}; BAND bands[BANDS+XVTRS] = - {{"160",&bandstack160,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,1800000LL,1800000LL,0LL,0}, - {"80",&bandstack80,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,3500000LL,3500000LL,0LL,0}, + {{"160",&bandstack160,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,1800000LL,2000000LL,0LL,0}, + {"80",&bandstack80,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,3500000LL,4000000LL,0LL,0}, {"60",&bandstack60,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,5330500LL,5403500LL,0LL,0}, {"40",&bandstack40,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,7000000LL,7300000LL,0LL,0}, {"30",&bandstack30,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,10100000LL,10150000LL,0LL,0}, @@ -269,6 +269,15 @@ BAND bands[BANDS+XVTRS] = }; +BANDSTACK *bandstack_get_bandstack(int band) { + return bands[band].bandstack; +} + +BANDSTACK_ENTRY *bandstack_get_bandstack_entry(int band,int entry) { + BANDSTACK *bandstack=bands[band].bandstack; + return &bandstack->entry[entry]; +} + BANDSTACK_ENTRY *bandstack_entry_get_current() { BANDSTACK *bandstack=bands[band].bandstack; BANDSTACK_ENTRY *entry=&bandstack->entry[bandstack->current_entry]; @@ -385,7 +394,7 @@ void bandSaveState() { entry=bands[b].bandstack->entry; entry+=stack; - sprintf(value,"%lld",entry->frequencyA); + sprintf(value,"%lld",entry->frequency); sprintf(name,"band.%d.stack.%d.a",b,stack); setProperty(name,value); @@ -502,7 +511,7 @@ fprintf(stderr,"bandRestoreState: restore bands\n"); sprintf(name,"band.%d.stack.%d.a",b,stack); value=getProperty(name); - if(value) entry->frequencyA=atoll(value); + if(value) entry->frequency=atoll(value); sprintf(name,"band.%d.stack.%d.mode",b,stack); value=getProperty(name); diff --git a/band.h b/band.h index 5f99de7..3653294 100644 --- a/band.h +++ b/band.h @@ -83,14 +83,17 @@ typedef struct _BAND BAND; int band; gboolean displayHF; -int band_get_current(); -BAND *band_get_current_band(); -BAND *band_get_band(int b); -BAND *band_set_current(int b); -int get_band_from_frequency(long long f); +extern int band_get_current(); +extern BAND *band_get_current_band(); +extern BAND *band_get_band(int b); +extern BAND *band_set_current(int b); +extern int get_band_from_frequency(long long f); -BANDSTACK_ENTRY *bandstack_entry_next(); -BANDSTACK_ENTRY *bandstack_entry_previous(); -BANDSTACK_ENTRY *bandstack_entry_get_current(); +extern BANDSTACK *bandstack_get_bandstack(int band); +extern BANDSTACK_ENTRY *bandstack_get_bandstack_entry(int band,int entry); + +extern BANDSTACK_ENTRY *bandstack_entry_next(); +extern BANDSTACK_ENTRY *bandstack_entry_previous(); +extern BANDSTACK_ENTRY *bandstack_entry_get_current(); #endif diff --git a/band_menu.c b/band_menu.c index b4d8c2d..d55ceff 100644 --- a/band_menu.c +++ b/band_menu.c @@ -27,6 +27,7 @@ #include "bandstack.h" #include "filter.h" #include "radio.h" +#include "receiver.h" #include "vfo.h" #include "button_text.h" @@ -48,33 +49,16 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat static gboolean band_select_cb (GtkWidget *widget, gpointer data) { GtkWidget *label; int b=(int)data; - BANDSTACK_ENTRY *entry; - if(b==band_get_current()) { - entry=bandstack_entry_next(); - } else { - BAND* band=band_set_current(b); - entry=bandstack_entry_get_current(); - set_button_text_color(last_band,"black"); - last_band=widget; - set_button_text_color(last_band,"orange"); - } - setMode(entry->mode); - FILTER* band_filters=filters[entry->mode]; - FILTER* band_filter=&band_filters[entry->filter]; - setFilter(band_filter->low,band_filter->high); - setFrequency(entry->frequencyA); - - BAND *band=band_get_current_band(); - set_alex_rx_antenna(band->alexRxAntenna); - set_alex_tx_antenna(band->alexTxAntenna); - set_alex_attenuation(band->alexAttenuation); - - vfo_update(NULL); + set_button_text_color(last_band,"black"); + last_band=widget; + set_button_text_color(last_band,"orange"); - setFrequency(entry->frequencyA); + vfo_band_changed(b); +} - calcDriveLevel(); - calcTuneDriveLevel(); +int band_update(void *data) { + band_select_cb(NULL,(gpointer)data); + return 0; } void band_menu(GtkWidget *parent) { @@ -108,6 +92,11 @@ void band_menu(GtkWidget *parent) { g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL); gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1); + char label[32]; + sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B"); + GtkWidget *rx_label=gtk_label_new(label); + gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1); + for(i=0;ititle)>0) { GtkWidget *b=gtk_button_new_with_label(band->title); set_button_text_color(b,"black"); - if(i==band_get_current()) { + //if(i==band_get_current()) { + if(i==vfo[active_receiver->id].band) { set_button_text_color(b,"orange"); last_band=b; } diff --git a/band_menu.h b/band_menu.h index f7b5a14..f77fc1a 100644 --- a/band_menu.h +++ b/band_menu.h @@ -18,3 +18,4 @@ */ void band_menu(GtkWidget *parent); +int band_update(void *data); diff --git a/bandstack.h b/bandstack.h index 9e8b30e..2950b6c 100644 --- a/bandstack.h +++ b/bandstack.h @@ -25,8 +25,7 @@ * @brief Bandstack definition */ struct _BANDSTACK_ENTRY { - long long frequencyA; - long long frequencyB; + long long frequency; int mode; int filter; int var1Low; diff --git a/bandstack_menu.c b/bandstack_menu.c index 4dc5f3c..001ea45 100644 --- a/bandstack_menu.c +++ b/bandstack_menu.c @@ -27,6 +27,7 @@ #include "bandstack.h" #include "filter.h" #include "radio.h" +#include "receiver.h" #include "vfo.h" #include "button_text.h" @@ -47,31 +48,10 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat static gboolean bandstack_select_cb (GtkWidget *widget, gpointer data) { int b=(int)data; - BAND *band=band_get_current_band(); - BANDSTACK *bandstack=band->bandstack; - - bandstack->current_entry=b; - set_button_text_color(last_bandstack,"black"); last_bandstack=widget; set_button_text_color(last_bandstack,"orange"); - - BANDSTACK_ENTRY *entry; - entry=&(bandstack->entry[b]); - - setMode(entry->mode); - FILTER* band_filters=filters[entry->mode]; - FILTER* band_filter=&band_filters[entry->filter]; - setFilter(band_filter->low,band_filter->high); - setFrequency(entry->frequencyA); - - set_alex_rx_antenna(band->alexRxAntenna); - set_alex_tx_antenna(band->alexTxAntenna); - set_alex_attenuation(band->alexAttenuation); - - vfo_update(NULL); - - setFrequency(entry->frequencyA); + vfo_bandstack_changed(b); } void bandstack_menu(GtkWidget *parent) { @@ -104,18 +84,21 @@ void bandstack_menu(GtkWidget *parent) { g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL); gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1); - char label[16]; + char label[32]; + sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B"); + GtkWidget *rx_label=gtk_label_new(label); + gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1); - BAND *band=band_get_current_band(); + BAND *band=band_get_band(vfo[active_receiver->id].band); BANDSTACK *bandstack=band->bandstack; for(i=0;ientries;i++) { BANDSTACK_ENTRY *entry=&bandstack->entry[i]; - sprintf(label,"%lld %s",entry->frequencyA,mode_string[entry->mode]); + sprintf(label,"%lld %s",entry->frequency,mode_string[entry->mode]); GtkWidget *b=gtk_button_new_with_label(label); set_button_text_color(b,"black"); //gtk_widget_override_font(b, pango_font_description_from_string("Arial 20")); - if(i==bandstack->current_entry) { + if(i==vfo[active_receiver->id].bandstack) { set_button_text_color(b,"orange"); last_bandstack=b; } diff --git a/configure.c b/configure.c index c882cd4..688d7ea 100644 --- a/configure.c +++ b/configure.c @@ -30,311 +30,484 @@ #include "main.h" #include "channel.h" #include "discovered.h" -#include "radio.h" +//#include "radio.h" #include "gpio.h" + #ifdef GPIO + +static GtkWidget *dialog; + +static GtkWidget *b_enable_vfo_encoder; +static GtkWidget *vfo_a_label; +static GtkWidget *vfo_a; +static GtkWidget *vfo_b_label; +static GtkWidget *vfo_b; +static GtkWidget *b_enable_vfo_pullup; +static GtkWidget *b_enable_E1_encoder; +static GtkWidget *E1_a_label; +static GtkWidget *E1_a; +static GtkWidget *E1_b_label; +static GtkWidget *E1_b; +static GtkWidget *b_enable_E1_pullup; +static GtkWidget *b_enable_E2_encoder; +static GtkWidget *E2_a_label; +static GtkWidget *E2_a; +static GtkWidget *E2_b_label; +static GtkWidget *E2_b; +static GtkWidget *b_enable_E2_pullup; +static GtkWidget *b_enable_E3_encoder; +static GtkWidget *E3_a_label; +static GtkWidget *E3_a; +static GtkWidget *E3_b_label; +static GtkWidget *E3_b; +static GtkWidget *b_enable_E3_pullup; +static GtkWidget *b_enable_mox; +static GtkWidget *mox_label; +static GtkWidget *mox; + +static GtkWidget *b_enable_S1; +static GtkWidget *S1_label; +static GtkWidget *S1; + +static GtkWidget *b_enable_S2; +static GtkWidget *S2_label; +static GtkWidget *S2; + +static GtkWidget *b_enable_S3; +static GtkWidget *S3_label; +static GtkWidget *S3; + +static GtkWidget *b_enable_S4; +static GtkWidget *S4_label; +static GtkWidget *S4; + +static GtkWidget *b_enable_S5; +static GtkWidget *S5_label; +static GtkWidget *S5; + +static GtkWidget *b_enable_S6; +static GtkWidget *S6_label; +static GtkWidget *S6; + +static GtkWidget *b_enable_function; +static GtkWidget *function_label; +static GtkWidget *function; + +#ifdef LOCALCW +static GtkWidget *cwl_label; +static GtkWidget *cwl_gpio_label; +static GtkWidget *cwl; +static GtkWidget *cwr_label; +static GtkWidget *cwr_gpio_label; +static GtkWidget *cwr; +#endif + +static gboolean save_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { + if(dialog!=NULL) { + ENABLE_VFO_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_vfo_encoder))?1:0; + VFO_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(vfo_a)); + VFO_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(vfo_b)); + ENABLE_VFO_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_vfo_pullup))?1:0; + + ENABLE_E1_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E1_encoder))?1:0; + E1_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E1_a)); + E1_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E1_b)); + ENABLE_E1_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E1_pullup))?1:0; + + ENABLE_E2_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E2_encoder))?1:0; + E2_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E2_a)); + E2_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E2_b)); + ENABLE_E2_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E2_pullup))?1:0; + + ENABLE_E3_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E3_encoder))?1:0; + E3_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E3_a)); + E3_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E3_b)); + ENABLE_E3_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E3_pullup))?1:0; + + ENABLE_MOX_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_mox))?1:0; + MOX_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(mox)); + + ENABLE_S1_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S1))?1:0; + S1_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S1)); + + ENABLE_S2_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S2))?1:0; + S2_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S2)); + + ENABLE_S3_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S3))?1:0; + S3_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S3)); + + ENABLE_S4_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S4))?1:0; + S4_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S4)); + + ENABLE_S5_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S5))?1:0; + S5_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S5)); + + ENABLE_S6_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S6))?1:0; + S6_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S6)); + + ENABLE_FUNCTION_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_function))?1:0; + FUNCTION_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(function)); +#ifdef LOCALCW + CWL_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(cwl)); + CWR_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(cwr)); +#endif + + gpio_save_state(); + gtk_widget_destroy(dialog); + } + return TRUE; +} + +static gboolean cancel_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { + if(dialog!=NULL) { + gtk_widget_destroy(dialog); + } + return TRUE; +} + void configure_gpio(GtkWidget *parent) { gpio_restore_state(); - GtkWidget *dialog=gtk_dialog_new_with_buttons("Configure GPIO",GTK_WINDOW(parent),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); + dialog=gtk_dialog_new_with_buttons("Configure GPIO",GTK_WINDOW(parent),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog)); GtkWidget *grid=gtk_grid_new(); //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE); gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE); + int y=0; - GtkWidget *b_enable_vfo_encoder=gtk_check_button_new_with_label("Enable VFO"); + b_enable_vfo_encoder=gtk_check_button_new_with_label("Enable VFO"); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_vfo_encoder), ENABLE_VFO_ENCODER); gtk_widget_show(b_enable_vfo_encoder); - gtk_grid_attach(GTK_GRID(grid),b_enable_vfo_encoder,0,0,1,1); + gtk_grid_attach(GTK_GRID(grid),b_enable_vfo_encoder,0,y,1,1); - GtkWidget *vfo_a_label=gtk_label_new("GPIO A:"); + vfo_a_label=gtk_label_new("GPIO A:"); gtk_widget_show(vfo_a_label); - gtk_grid_attach(GTK_GRID(grid),vfo_a_label,1,0,1,1); + gtk_grid_attach(GTK_GRID(grid),vfo_a_label,1,y,1,1); - GtkWidget *vfo_a=gtk_spin_button_new_with_range (0.0,100.0,1.0); + vfo_a=gtk_spin_button_new_with_range (0.0,100.0,1.0); gtk_spin_button_set_value (GTK_SPIN_BUTTON(vfo_a),VFO_ENCODER_A); gtk_widget_show(vfo_a); - gtk_grid_attach(GTK_GRID(grid),vfo_a,2,0,1,1); + gtk_grid_attach(GTK_GRID(grid),vfo_a,2,y,1,1); - GtkWidget *vfo_b_label=gtk_label_new("GPIO B:"); + vfo_b_label=gtk_label_new("GPIO B:"); gtk_widget_show(vfo_b_label); - gtk_grid_attach(GTK_GRID(grid),vfo_b_label,3,0,1,1); + gtk_grid_attach(GTK_GRID(grid),vfo_b_label,3,y,1,1); - GtkWidget *vfo_b=gtk_spin_button_new_with_range (0.0,100.0,1.0); + vfo_b=gtk_spin_button_new_with_range (0.0,100.0,1.0); gtk_spin_button_set_value (GTK_SPIN_BUTTON(vfo_b),VFO_ENCODER_B); gtk_widget_show(vfo_b); - gtk_grid_attach(GTK_GRID(grid),vfo_b,4,0,1,1); + gtk_grid_attach(GTK_GRID(grid),vfo_b,4,y,1,1); - GtkWidget *b_enable_vfo_pullup=gtk_check_button_new_with_label("Enable Pull-up"); + b_enable_vfo_pullup=gtk_check_button_new_with_label("Enable Pull-up"); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_vfo_pullup), ENABLE_VFO_PULLUP); gtk_widget_show(b_enable_vfo_pullup); - gtk_grid_attach(GTK_GRID(grid),b_enable_vfo_pullup,5,0,1,1); + gtk_grid_attach(GTK_GRID(grid),b_enable_vfo_pullup,5,y,1,1); + y++; - GtkWidget *b_enable_af_encoder=gtk_check_button_new_with_label("Enable E1"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_af_encoder), ENABLE_E1_ENCODER); - gtk_widget_show(b_enable_af_encoder); - gtk_grid_attach(GTK_GRID(grid),b_enable_af_encoder,0,1,1,1); + b_enable_E1_encoder=gtk_check_button_new_with_label("Enable E1"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_E1_encoder), ENABLE_E1_ENCODER); + gtk_widget_show(b_enable_E1_encoder); + gtk_grid_attach(GTK_GRID(grid),b_enable_E1_encoder,0,y,1,1); - GtkWidget *af_a_label=gtk_label_new("GPIO A:"); - gtk_widget_show(af_a_label); - gtk_grid_attach(GTK_GRID(grid),af_a_label,1,1,1,1); + E1_a_label=gtk_label_new("GPIO A:"); + gtk_widget_show(E1_a_label); + gtk_grid_attach(GTK_GRID(grid),E1_a_label,1,y,1,1); - GtkWidget *af_a=gtk_spin_button_new_with_range (0.0,100.0,1.0); - gtk_spin_button_set_value (GTK_SPIN_BUTTON(af_a),E1_ENCODER_A); - gtk_widget_show(af_a); - gtk_grid_attach(GTK_GRID(grid),af_a,2,1,1,1); + E1_a=gtk_spin_button_new_with_range (0.0,100.0,1.0); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(E1_a),E1_ENCODER_A); + gtk_widget_show(E1_a); + gtk_grid_attach(GTK_GRID(grid),E1_a,2,y,1,1); - GtkWidget *af_b_label=gtk_label_new("GPIO B:"); - gtk_widget_show(af_b_label); - gtk_grid_attach(GTK_GRID(grid),af_b_label,3,1,1,1); + E1_b_label=gtk_label_new("GPIO B:"); + gtk_widget_show(E1_b_label); + gtk_grid_attach(GTK_GRID(grid),E1_b_label,3,y,1,1); - GtkWidget *af_b=gtk_spin_button_new_with_range (0.0,100.0,1.0); - gtk_spin_button_set_value (GTK_SPIN_BUTTON(af_b),E1_ENCODER_B); - gtk_widget_show(af_b); - gtk_grid_attach(GTK_GRID(grid),af_b,4,1,1,1); + E1_b=gtk_spin_button_new_with_range (0.0,100.0,1.0); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(E1_b),E1_ENCODER_B); + gtk_widget_show(E1_b); + gtk_grid_attach(GTK_GRID(grid),E1_b,4,y,1,1); - GtkWidget *b_enable_af_pullup=gtk_check_button_new_with_label("Enable Pull-up"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_af_pullup), ENABLE_E1_PULLUP); - gtk_widget_show(b_enable_af_pullup); - gtk_grid_attach(GTK_GRID(grid),b_enable_af_pullup,5,1,1,1); + b_enable_E1_pullup=gtk_check_button_new_with_label("Enable Pull-up"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_E1_pullup), ENABLE_E1_PULLUP); + gtk_widget_show(b_enable_E1_pullup); + gtk_grid_attach(GTK_GRID(grid),b_enable_E1_pullup,5,y,1,1); + y++; - GtkWidget *b_enable_rf_encoder=gtk_check_button_new_with_label("Enable RF"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_rf_encoder), ENABLE_E2_ENCODER); - gtk_widget_show(b_enable_rf_encoder); - gtk_grid_attach(GTK_GRID(grid),b_enable_rf_encoder,0,2,1,1); + b_enable_E2_encoder=gtk_check_button_new_with_label("Enable E2"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_E2_encoder), ENABLE_E2_ENCODER); + gtk_widget_show(b_enable_E2_encoder); + gtk_grid_attach(GTK_GRID(grid),b_enable_E2_encoder,0,y,1,1); - GtkWidget *rf_a_label=gtk_label_new("GPIO A:"); - gtk_widget_show(rf_a_label); - gtk_grid_attach(GTK_GRID(grid),rf_a_label,1,2,1,1); + E2_a_label=gtk_label_new("GPIO A:"); + gtk_widget_show(E2_a_label); + gtk_grid_attach(GTK_GRID(grid),E2_a_label,1,y,1,1); - GtkWidget *rf_a=gtk_spin_button_new_with_range (0.0,100.0,1.0); - gtk_spin_button_set_value (GTK_SPIN_BUTTON(rf_a),E2_ENCODER_A); - gtk_widget_show(rf_a); - gtk_grid_attach(GTK_GRID(grid),rf_a,2,2,1,1); + E2_a=gtk_spin_button_new_with_range (0.0,100.0,1.0); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(E2_a),E2_ENCODER_A); + gtk_widget_show(E2_a); + gtk_grid_attach(GTK_GRID(grid),E2_a,2,y,1,1); - GtkWidget *rf_b_label=gtk_label_new("GPIO B:"); - gtk_widget_show(rf_b_label); - gtk_grid_attach(GTK_GRID(grid),rf_b_label,3,2,1,1); + E2_b_label=gtk_label_new("GPIO B:"); + gtk_widget_show(E2_b_label); + gtk_grid_attach(GTK_GRID(grid),E2_b_label,3,y,1,1); - GtkWidget *rf_b=gtk_spin_button_new_with_range (0.0,100.0,1.0); - gtk_spin_button_set_value (GTK_SPIN_BUTTON(rf_b),E2_ENCODER_B); - gtk_widget_show(rf_b); - gtk_grid_attach(GTK_GRID(grid),rf_b,4,2,1,1); + E2_b=gtk_spin_button_new_with_range (0.0,100.0,1.0); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(E2_b),E2_ENCODER_B); + gtk_widget_show(E2_b); + gtk_grid_attach(GTK_GRID(grid),E2_b,4,y,1,1); - GtkWidget *b_enable_rf_pullup=gtk_check_button_new_with_label("Enable Pull-up"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_rf_pullup), ENABLE_E2_PULLUP); - gtk_widget_show(b_enable_rf_pullup); - gtk_grid_attach(GTK_GRID(grid),b_enable_rf_pullup,5,2,1,1); + b_enable_E2_pullup=gtk_check_button_new_with_label("Enable Pull-up"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_E2_pullup), ENABLE_E2_PULLUP); + gtk_widget_show(b_enable_E2_pullup); + gtk_grid_attach(GTK_GRID(grid),b_enable_E2_pullup,5,y,1,1); + y++; - GtkWidget *b_enable_agc_encoder=gtk_check_button_new_with_label("Enable AGC"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_agc_encoder), ENABLE_E3_ENCODER); - gtk_widget_show(b_enable_agc_encoder); - gtk_grid_attach(GTK_GRID(grid),b_enable_agc_encoder,0,3,1,1); + b_enable_E3_encoder=gtk_check_button_new_with_label("Enable E3"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_E3_encoder), ENABLE_E3_ENCODER); + gtk_widget_show(b_enable_E3_encoder); + gtk_grid_attach(GTK_GRID(grid),b_enable_E3_encoder,0,y,1,1); - GtkWidget *agc_a_label=gtk_label_new("GPIO A:"); - gtk_widget_show(agc_a_label); - gtk_grid_attach(GTK_GRID(grid),agc_a_label,1,3,1,1); + E3_a_label=gtk_label_new("GPIO A:"); + gtk_widget_show(E3_a_label); + gtk_grid_attach(GTK_GRID(grid),E3_a_label,1,y,1,1); - GtkWidget *agc_a=gtk_spin_button_new_with_range (0.0,100.0,1.0); - gtk_spin_button_set_value (GTK_SPIN_BUTTON(agc_a),E3_ENCODER_A); - gtk_widget_show(agc_a); - gtk_grid_attach(GTK_GRID(grid),agc_a,2,3,1,1); + E3_a=gtk_spin_button_new_with_range (0.0,100.0,1.0); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(E3_a),E3_ENCODER_A); + gtk_widget_show(E3_a); + gtk_grid_attach(GTK_GRID(grid),E3_a,2,y,1,1); - GtkWidget *agc_b_label=gtk_label_new("GPIO B:"); - gtk_widget_show(agc_b_label); - gtk_grid_attach(GTK_GRID(grid),agc_b_label,3,3,1,1); + E3_b_label=gtk_label_new("GPIO B:"); + gtk_widget_show(E3_b_label); + gtk_grid_attach(GTK_GRID(grid),E3_b_label,3,y,1,1); - GtkWidget *agc_b=gtk_spin_button_new_with_range (0.0,100.0,1.0); - gtk_spin_button_set_value (GTK_SPIN_BUTTON(agc_b),E3_ENCODER_B); - gtk_widget_show(agc_b); - gtk_grid_attach(GTK_GRID(grid),agc_b,4,3,1,1); + E3_b=gtk_spin_button_new_with_range (0.0,100.0,1.0); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(E3_b),E3_ENCODER_B); + gtk_widget_show(E3_b); + gtk_grid_attach(GTK_GRID(grid),E3_b,4,y,1,1); - GtkWidget *b_enable_agc_pullup=gtk_check_button_new_with_label("Enable Pull-up"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_agc_pullup), ENABLE_E3_PULLUP); - gtk_widget_show(b_enable_agc_pullup); - gtk_grid_attach(GTK_GRID(grid),b_enable_agc_pullup,5,3,1,1); + b_enable_E3_pullup=gtk_check_button_new_with_label("Enable Pull-up"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_E3_pullup), ENABLE_E3_PULLUP); + gtk_widget_show(b_enable_E3_pullup); + gtk_grid_attach(GTK_GRID(grid),b_enable_E3_pullup,5,y,1,1); + y++; - GtkWidget *b_enable_band=gtk_check_button_new_with_label("Enable Band"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_band), ENABLE_S1_BUTTON); - gtk_widget_show(b_enable_band); - gtk_grid_attach(GTK_GRID(grid),b_enable_band,0,4,1,1); + b_enable_mox=gtk_check_button_new_with_label("Enable MOX/TUN"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_mox), ENABLE_MOX_BUTTON); + gtk_widget_show(b_enable_mox); + gtk_grid_attach(GTK_GRID(grid),b_enable_mox,0,y,1,1); - GtkWidget *band_label=gtk_label_new("GPIO:"); - gtk_widget_show(band_label); - gtk_grid_attach(GTK_GRID(grid),band_label,1,4,1,1); + mox_label=gtk_label_new("GPIO:"); + gtk_widget_show(mox_label); + gtk_grid_attach(GTK_GRID(grid),mox_label,1,y,1,1); - GtkWidget *band=gtk_spin_button_new_with_range (0.0,100.0,1.0); - gtk_spin_button_set_value (GTK_SPIN_BUTTON(band),S1_BUTTON); - gtk_widget_show(band); - gtk_grid_attach(GTK_GRID(grid),band,2,4,1,1); + mox=gtk_spin_button_new_with_range (0.0,100.0,1.0); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(mox),MOX_BUTTON); + gtk_widget_show(mox); + gtk_grid_attach(GTK_GRID(grid),mox,2,y,1,1); + y++; - GtkWidget *b_enable_mode=gtk_check_button_new_with_label("Enable Mode"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_mode), ENABLE_S3_BUTTON); - gtk_widget_show(b_enable_mode); - gtk_grid_attach(GTK_GRID(grid),b_enable_mode,0,5,1,1); + b_enable_S1=gtk_check_button_new_with_label("Enable S1"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_S1), ENABLE_S1_BUTTON); + gtk_widget_show(b_enable_S1); + gtk_grid_attach(GTK_GRID(grid),b_enable_S1,0,y,1,1); - GtkWidget *mode_label=gtk_label_new("GPIO:"); - gtk_widget_show(mode_label); - gtk_grid_attach(GTK_GRID(grid),mode_label,1,5,1,1); + S1_label=gtk_label_new("GPIO:"); + gtk_widget_show(S1_label); + gtk_grid_attach(GTK_GRID(grid),S1_label,1,y,1,1); - GtkWidget *mode=gtk_spin_button_new_with_range (0.0,100.0,1.0); - gtk_spin_button_set_value (GTK_SPIN_BUTTON(mode),S3_BUTTON); - gtk_widget_show(mode); - gtk_grid_attach(GTK_GRID(grid),mode,2,5,1,1); + S1=gtk_spin_button_new_with_range (0.0,100.0,1.0); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(S1),S1_BUTTON); + gtk_widget_show(S1); + gtk_grid_attach(GTK_GRID(grid),S1,2,y,1,1); - GtkWidget *b_enable_filter=gtk_check_button_new_with_label("Enable Filter"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_filter), ENABLE_S4_BUTTON); - gtk_widget_show(b_enable_filter); - gtk_grid_attach(GTK_GRID(grid),b_enable_filter,0,6,1,1); + y++; - GtkWidget *filter_label=gtk_label_new("GPIO:"); - gtk_widget_show(filter_label); - gtk_grid_attach(GTK_GRID(grid),filter_label,1,6,1,1); + b_enable_S2=gtk_check_button_new_with_label("Enable S2"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_S2), ENABLE_S2_BUTTON); + gtk_widget_show(b_enable_S2); + gtk_grid_attach(GTK_GRID(grid),b_enable_S2,0,y,1,1); - GtkWidget *filter=gtk_spin_button_new_with_range (0.0,100.0,1.0); - gtk_spin_button_set_value (GTK_SPIN_BUTTON(filter),S4_BUTTON); - gtk_widget_show(filter); - gtk_grid_attach(GTK_GRID(grid),filter,2,6,1,1); + S2_label=gtk_label_new("GPIO:"); + gtk_widget_show(S2_label); + gtk_grid_attach(GTK_GRID(grid),S2_label,1,y,1,1); + S2=gtk_spin_button_new_with_range (0.0,100.0,1.0); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(S2),S2_BUTTON); + gtk_widget_show(S2); + gtk_grid_attach(GTK_GRID(grid),S2,2,y,1,1); - GtkWidget *b_enable_noise=gtk_check_button_new_with_label("Enable Noise"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_noise), ENABLE_S5_BUTTON); - gtk_widget_show(b_enable_noise); - gtk_grid_attach(GTK_GRID(grid),b_enable_noise,0,7,1,1); + y++; - GtkWidget *noise_label=gtk_label_new("GPIO:"); - gtk_widget_show(noise_label); - gtk_grid_attach(GTK_GRID(grid),noise_label,1,7,1,1); + b_enable_S3=gtk_check_button_new_with_label("Enable S3"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_S3), ENABLE_S3_BUTTON); + gtk_widget_show(b_enable_S3); + gtk_grid_attach(GTK_GRID(grid),b_enable_S3,0,y,1,1); - GtkWidget *noise=gtk_spin_button_new_with_range (0.0,100.0,1.0); - gtk_spin_button_set_value (GTK_SPIN_BUTTON(noise),S5_BUTTON); - gtk_widget_show(noise); - gtk_grid_attach(GTK_GRID(grid),noise,2,7,1,1); + S3_label=gtk_label_new("GPIO:"); + gtk_widget_show(S3_label); + gtk_grid_attach(GTK_GRID(grid),S3_label,1,y,1,1); + S3=gtk_spin_button_new_with_range (0.0,100.0,1.0); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(S3),S3_BUTTON); + gtk_widget_show(S3); + gtk_grid_attach(GTK_GRID(grid),S3,2,y,1,1); - GtkWidget *b_enable_agc=gtk_check_button_new_with_label("Enable AGC"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_agc), ENABLE_S6_BUTTON); - gtk_widget_show(b_enable_agc); - gtk_grid_attach(GTK_GRID(grid),b_enable_agc,0,8,1,1); + y++; - GtkWidget *agc_label=gtk_label_new("GPIO:"); - gtk_widget_show(agc_label); - gtk_grid_attach(GTK_GRID(grid),agc_label,1,8,1,1); + b_enable_S4=gtk_check_button_new_with_label("Enable S4"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_S4), ENABLE_S4_BUTTON); + gtk_widget_show(b_enable_S4); + gtk_grid_attach(GTK_GRID(grid),b_enable_S4,0,y,1,1); - GtkWidget *agc=gtk_spin_button_new_with_range (0.0,100.0,1.0); - gtk_spin_button_set_value (GTK_SPIN_BUTTON(agc),S6_BUTTON); - gtk_widget_show(agc); - gtk_grid_attach(GTK_GRID(grid),agc,2,8,1,1); + S4_label=gtk_label_new("GPIO:"); + gtk_widget_show(S4_label); + gtk_grid_attach(GTK_GRID(grid),S4_label,1,y,1,1); + S4=gtk_spin_button_new_with_range (0.0,100.0,1.0); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(S4),S4_BUTTON); + gtk_widget_show(S4); + gtk_grid_attach(GTK_GRID(grid),S4,2,y,1,1); - GtkWidget *b_enable_mox=gtk_check_button_new_with_label("Enable MOX"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_mox), ENABLE_MOX_BUTTON); - gtk_widget_show(b_enable_mox); - gtk_grid_attach(GTK_GRID(grid),b_enable_mox,0,9,1,1); + y++; - GtkWidget *mox_label=gtk_label_new("GPIO:"); - gtk_widget_show(mox_label); - gtk_grid_attach(GTK_GRID(grid),mox_label,1,9,1,1); + b_enable_S5=gtk_check_button_new_with_label("Enable S5"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_S5), ENABLE_S5_BUTTON); + gtk_widget_show(b_enable_S5); + gtk_grid_attach(GTK_GRID(grid),b_enable_S5,0,y,1,1); - GtkWidget *mox=gtk_spin_button_new_with_range (0.0,100.0,1.0); - gtk_spin_button_set_value (GTK_SPIN_BUTTON(mox),MOX_BUTTON); - gtk_widget_show(mox); - gtk_grid_attach(GTK_GRID(grid),mox,2,9,1,1); + S5_label=gtk_label_new("GPIO:"); + gtk_widget_show(S5_label); + gtk_grid_attach(GTK_GRID(grid),S5_label,1,y,1,1); + + S5=gtk_spin_button_new_with_range (0.0,100.0,1.0); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(S5),S5_BUTTON); + gtk_widget_show(S5); + gtk_grid_attach(GTK_GRID(grid),S5,2,y,1,1); + + y++; + b_enable_S6=gtk_check_button_new_with_label("Enable S6"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_S6), ENABLE_S6_BUTTON); + gtk_widget_show(b_enable_S6); + gtk_grid_attach(GTK_GRID(grid),b_enable_S6,0,y,1,1); - GtkWidget *b_enable_function=gtk_check_button_new_with_label("Enable Function"); + S6_label=gtk_label_new("GPIO:"); + gtk_widget_show(S6_label); + gtk_grid_attach(GTK_GRID(grid),S6_label,1,y,1,1); + + S6=gtk_spin_button_new_with_range (0.0,100.0,1.0); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(S6),S6_BUTTON); + gtk_widget_show(S6); + gtk_grid_attach(GTK_GRID(grid),S6,2,y,1,1); + + y++; + + b_enable_function=gtk_check_button_new_with_label("Enable Function"); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_function), ENABLE_FUNCTION_BUTTON); gtk_widget_show(b_enable_function); - gtk_grid_attach(GTK_GRID(grid),b_enable_function,0,10,1,1); + gtk_grid_attach(GTK_GRID(grid),b_enable_function,0,y,1,1); - GtkWidget *function_label=gtk_label_new("GPIO:"); + function_label=gtk_label_new("GPIO:"); gtk_widget_show(function_label); - gtk_grid_attach(GTK_GRID(grid),function_label,1,10,1,1); + gtk_grid_attach(GTK_GRID(grid),function_label,1,y,1,1); - GtkWidget *function=gtk_spin_button_new_with_range (0.0,100.0,1.0); + function=gtk_spin_button_new_with_range (0.0,100.0,1.0); gtk_spin_button_set_value (GTK_SPIN_BUTTON(function),FUNCTION_BUTTON); gtk_widget_show(function); - gtk_grid_attach(GTK_GRID(grid),function,2,10,1,1); + gtk_grid_attach(GTK_GRID(grid),function,2,y,1,1); + + y++; #ifdef LOCALCW - GtkWidget *cwl_label=gtk_label_new("CWL"); + cwl_label=gtk_label_new("CWL"); gtk_widget_show(cwl_label); - gtk_grid_attach(GTK_GRID(grid),cwl_label,0,11,1,1); + gtk_grid_attach(GTK_GRID(grid),cwl_label,0,y,1,1); - GtkWidget *cwl_gpio_label=gtk_label_new("GPIO:"); + cwl_gpio_label=gtk_label_new("GPIO:"); gtk_widget_show(cwl_gpio_label); - gtk_grid_attach(GTK_GRID(grid),cwl_gpio_label,1,11,1,1); + gtk_grid_attach(GTK_GRID(grid),cwl_gpio_label,1,y,1,1); - GtkWidget *cwl=gtk_spin_button_new_with_range (0.0,100.0,1.0); + cwl=gtk_spin_button_new_with_range (0.0,100.0,1.0); gtk_spin_button_set_value (GTK_SPIN_BUTTON(cwl),CWL_BUTTON); gtk_widget_show(cwl); - gtk_grid_attach(GTK_GRID(grid),cwl,2,11,1,1); + gtk_grid_attach(GTK_GRID(grid),cwl,2,y,1,1); + + y++; - GtkWidget *cwr_label=gtk_label_new("CWR"); + cwr_label=gtk_label_new("CWR"); gtk_widget_show(cwr_label); - gtk_grid_attach(GTK_GRID(grid),cwr_label,0,12,1,1); + gtk_grid_attach(GTK_GRID(grid),cwr_label,0,y,1,1); - GtkWidget *cwr_gpio_label=gtk_label_new("GPIO:"); + cwr_gpio_label=gtk_label_new("GPIO:"); gtk_widget_show(cwr_gpio_label); - gtk_grid_attach(GTK_GRID(grid),cwr_gpio_label,1,12,1,1); + gtk_grid_attach(GTK_GRID(grid),cwr_gpio_label,1,y,1,1); - GtkWidget *cwr=gtk_spin_button_new_with_range (0.0,100.0,1.0); + cwr=gtk_spin_button_new_with_range (0.0,100.0,1.0); gtk_spin_button_set_value (GTK_SPIN_BUTTON(cwr),CWR_BUTTON); gtk_widget_show(cwr); - gtk_grid_attach(GTK_GRID(grid),cwr,2,12,1,1); -#endif + gtk_grid_attach(GTK_GRID(grid),cwr,2,y,1,1); + y++; +#endif + + GtkWidget *save_b=gtk_button_new_with_label("Save"); + g_signal_connect (save_b, "button_press_event", G_CALLBACK(save_cb), NULL); + gtk_grid_attach(GTK_GRID(grid),save_b,4,y-1,1,1); - gtk_container_add(GTK_CONTAINER(content),grid); + GtkWidget *cancel_b=gtk_button_new_with_label("Cancel"); + g_signal_connect (cancel_b, "button_press_event", G_CALLBACK(cancel_cb), NULL); + gtk_grid_attach(GTK_GRID(grid),cancel_b,5,y-1,1,1); gtk_container_add(GTK_CONTAINER(content),grid); - GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK); +/* + GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Save",GTK_RESPONSE_OK); //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 20")); +*/ gtk_widget_show_all(dialog); - int result=gtk_dialog_run(GTK_DIALOG(dialog)); +/* ENABLE_VFO_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_vfo_encoder))?1:0; VFO_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(vfo_a)); VFO_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(vfo_b)); ENABLE_VFO_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_vfo_pullup))?1:0; - ENABLE_E1_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_af_encoder))?1:0; - E1_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(af_a)); - E1_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(af_b)); - ENABLE_E1_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_af_pullup))?1:0; - ENABLE_E2_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_rf_encoder))?1:0; - E2_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(rf_a)); - E2_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(rf_b)); - ENABLE_E2_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_rf_pullup))?1:0; - ENABLE_E3_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_agc_encoder))?1:0; - E3_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(agc_a)); - E3_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(agc_b)); - ENABLE_E3_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_agc_pullup))?1:0; - ENABLE_S1_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_band))?1:0; - S1_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(band)); - ENABLE_S2_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_band))?1:0; - S2_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(band)); - ENABLE_S3_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_mode))?1:0; - S3_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(mode)); - ENABLE_S4_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_filter))?1:0; - S4_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(filter)); - ENABLE_S5_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_noise))?1:0; - S5_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(noise)); - ENABLE_S6_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_agc))?1:0; - S6_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(agc)); + ENABLE_E1_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E1_encoder))?1:0; + E1_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E1_a)); + E1_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E1_b)); + ENABLE_E1_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E1_pullup))?1:0; + ENABLE_E2_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E2_encoder))?1:0; + E2_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E2_a)); + E2_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E2_b)); + ENABLE_E2_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E2_pullup))?1:0; + ENABLE_E3_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S6_encoder))?1:0; + E3_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S6_a)); + E3_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S6_b)); + ENABLE_E3_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S6_pullup))?1:0; + ENABLE_S1_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S1))?1:0; + S1_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S1)); + ENABLE_S2_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S2))?1:0; + S2_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S2)); + ENABLE_S3_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S3))?1:0; + S3_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S3)); + ENABLE_S4_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S4))?1:0; + S4_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S4)); + ENABLE_S5_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S5))?1:0; + S5_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S5)); + ENABLE_S6_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S6))?1:0; + S6_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S6)); ENABLE_MOX_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_mox))?1:0; MOX_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(mox)); ENABLE_FUNCTION_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_function))?1:0; @@ -343,10 +516,12 @@ void configure_gpio(GtkWidget *parent) { CWL_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(cwl)); CWR_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(cwr)); #endif +*/ gtk_widget_destroy(dialog); - gpio_save_state(); +// gpio_save_state(); + } #endif diff --git a/cw_menu.c b/cw_menu.c index b1e263c..176d1ec 100644 --- a/cw_menu.c +++ b/cw_menu.c @@ -28,6 +28,7 @@ #include "bandstack.h" #include "filter.h" #include "radio.h" +#include "receiver.h" static GtkWidget *parent_window=NULL; @@ -91,12 +92,15 @@ static void cw_keyer_sidetone_level_value_changed_cb(GtkWidget *widget, gpointer static void cw_keyer_sidetone_frequency_value_changed_cb(GtkWidget *widget, gpointer data) { cw_keyer_sidetone_frequency=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); - if(mode==modeCWL || mode==modeCWU) { +/* + if(transmitter->mode==modeCWL || transmitter->mode==modeCWU) { BANDSTACK_ENTRY *entry=bandstack_entry_get_current(); FILTER* band_filters=filters[entry->mode]; FILTER* band_filter=&band_filters[entry->filter]; - setFilter(band_filter->low,band_filter->high); + //setFilter(band_filter->low,band_filter->high); + set_filter(active_receiver,band_filter->low,band_filter->high); } +*/ cw_changed(); } diff --git a/discovered.h b/discovered.h index 28b41e0..d4f6322 100644 --- a/discovered.h +++ b/discovered.h @@ -27,12 +27,19 @@ #define MAX_DEVICES 16 + #define DEVICE_METIS 0 #define DEVICE_HERMES 1 #define DEVICE_GRIFFIN 2 #define DEVICE_ANGELIA 4 #define DEVICE_ORION 5 #define DEVICE_HERMES_LITE 6 +// 8000DLE uses 10 as the device type in old protocol +#define DEVICE_ORION2 10 + +#ifdef USBOZY +#define DEVICE_OZY 7 +#endif #define NEW_DEVICE_ATLAS 0 #define NEW_DEVICE_HERMES 1 diff --git a/discovery.c b/discovery.c new file mode 100644 index 0000000..3fc509d --- /dev/null +++ b/discovery.c @@ -0,0 +1,263 @@ +/* Copyright (C) +* 2015 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "discovered.h" +#include "discovery.h" +#include "main.h" +#include "radio.h" +#ifdef USBOZY +#include "ozyio.h" +#endif + +static GtkWidget *discovery_dialog; +static DISCOVERED *d; + +int discovery(void *data); + +static gboolean start_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { +fprintf(stderr,"start_cb: %p\n",data); + radio=(DISCOVERED *)data; + gtk_widget_destroy(discovery_dialog); + start_radio(); + return TRUE; +} + +#ifdef GPIO +static gboolean gpio_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { + configure_gpio(discovery_dialog); + return TRUE; +} +#endif + +static gboolean discover_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { + gtk_widget_destroy(discovery_dialog); + g_idle_add(discovery,NULL); + return TRUE; +} + +static gboolean exit_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { + gtk_widget_destroy(discovery_dialog); + _exit(0); + return TRUE; +} + +int discovery(void *data) { +fprintf(stderr,"discovery\n"); + selected_device=0; + devices=0; + +#ifdef USBOZY +// +// first: look on USB for an Ozy +// + fprintf(stderr,"looking for USB based OZY devices\n"); + + if (ozy_discover() != 0) + { + discovered[devices].protocol = ORIGINAL_PROTOCOL; + discovered[devices].device = DEVICE_OZY; + discovered[devices].software_version = 10; // we can't know yet so this isn't a real response + discovered[devices].status = STATE_AVAILABLE; + strcpy(discovered[devices].name,"Ozy on USB"); + + strcpy(discovered[devices].info.network.interface_name,"USB"); + devices++; + } +#endif + + + status_text("Old Protocol ... Discovering Devices"); + old_discovery(); + + status_text("New Protocol ... Discovering Devices"); + new_discovery(); + +#ifdef LIMESDR + status_text("LimeSDR ... Discovering Devices"); + lime_discovery(); +#endif + + + if(devices==0) { + gdk_window_set_cursor(gtk_widget_get_window(top_window),gdk_cursor_new(GDK_ARROW)); + discovery_dialog = gtk_dialog_new(); + gtk_window_set_transient_for(GTK_WINDOW(discovery_dialog),GTK_WINDOW(top_window)); + gtk_window_set_decorated(GTK_WINDOW(discovery_dialog),FALSE); + + gtk_widget_override_font(discovery_dialog, pango_font_description_from_string("FreeMono 16")); + + GdkRGBA color; + color.red = 1.0; + color.green = 1.0; + color.blue = 1.0; + color.alpha = 1.0; + gtk_widget_override_background_color(discovery_dialog,GTK_STATE_FLAG_NORMAL,&color); + + GtkWidget *content; + + content=gtk_dialog_get_content_area(GTK_DIALOG(discovery_dialog)); + + GtkWidget *grid=gtk_grid_new(); + gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE); + gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE); + gtk_grid_set_row_spacing (GTK_GRID(grid),10); + + GtkWidget *label=gtk_label_new("No devices found!"); + gtk_grid_attach(GTK_GRID(grid),label,0,0,2,1); + + GtkWidget *exit_b=gtk_button_new_with_label("Exit"); + g_signal_connect (exit_b, "button-press-event", G_CALLBACK(exit_cb), NULL); + gtk_grid_attach(GTK_GRID(grid),exit_b,0,1,1,1); + + GtkWidget *discover_b=gtk_button_new_with_label("Retry Discovery"); + g_signal_connect (discover_b, "button-press-event", G_CALLBACK(discover_cb), NULL); + gtk_grid_attach(GTK_GRID(grid),discover_b,1,1,1,1); + + gtk_container_add (GTK_CONTAINER (content), grid); + gtk_widget_show_all(discovery_dialog); + } else { + fprintf(stderr,"discovery: found %d devices\n", devices); + gdk_window_set_cursor(gtk_widget_get_window(top_window),gdk_cursor_new(GDK_ARROW)); + discovery_dialog = gtk_dialog_new(); + gtk_window_set_transient_for(GTK_WINDOW(discovery_dialog),GTK_WINDOW(top_window)); + gtk_window_set_decorated(GTK_WINDOW(discovery_dialog),FALSE); + + gtk_widget_override_font(discovery_dialog, pango_font_description_from_string("FreeMono 16")); + + GdkRGBA color; + color.red = 1.0; + color.green = 1.0; + color.blue = 1.0; + color.alpha = 1.0; + gtk_widget_override_background_color(discovery_dialog,GTK_STATE_FLAG_NORMAL,&color); + + GtkWidget *content; + + content=gtk_dialog_get_content_area(GTK_DIALOG(discovery_dialog)); + + GtkWidget *grid=gtk_grid_new(); + gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE); + gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE); + gtk_grid_set_row_spacing (GTK_GRID(grid),10); + + int i; + char version[16]; + char text[128]; + for(i=0;iprotocol,d->name); + if(d->protocol==ORIGINAL_PROTOCOL) { + sprintf(version,"%d.%d", + d->software_version/10, + d->software_version%10); + } else { + sprintf(version,"%d.%d", + d->software_version/10, + d->software_version%10); + } + switch(d->protocol) { + case ORIGINAL_PROTOCOL: + case NEW_PROTOCOL: +#ifdef USBOZY + if(d->device==DEVICE_OZY) { + sprintf(text,"%s (%s) on USB /dev/ozy\n", d->name, d->protocol==ORIGINAL_PROTOCOL?"old":"new"); + } else { +#endif + sprintf(text,"%s (%s %s) %s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n", + d->name, + d->protocol==ORIGINAL_PROTOCOL?"old":"new", + version, + inet_ntoa(d->info.network.address.sin_addr), + d->info.network.mac_address[0], + d->info.network.mac_address[1], + d->info.network.mac_address[2], + d->info.network.mac_address[3], + d->info.network.mac_address[4], + d->info.network.mac_address[5], + d->info.network.interface_name); +#ifdef USBOZY + } +#endif + break; +#ifdef LIMESDR + case LIMESDR_PROTOCOL: + sprintf(text,"%s\n", + d->name); + break; +#endif + } + + GtkWidget *label=gtk_label_new(text); + gtk_widget_override_font(label, pango_font_description_from_string("FreeMono 12")); + gtk_widget_show(label); + gtk_grid_attach(GTK_GRID(grid),label,0,i,3,1); + + GtkWidget *start_button=gtk_button_new_with_label("Start"); + gtk_widget_override_font(start_button, pango_font_description_from_string("FreeMono 18")); + gtk_widget_show(start_button); + gtk_grid_attach(GTK_GRID(grid),start_button,3,i,1,1); + g_signal_connect(start_button,"button_press_event",G_CALLBACK(start_cb),(gpointer)d); + + // if not available then cannot start it + if(d->status!=STATE_AVAILABLE) { + gtk_button_set_label(GTK_BUTTON(start_button),"In Use"); + gtk_widget_set_sensitive(start_button, FALSE); + } + + // if not on the same subnet then cannot start it + if((d->info.network.interface_address.sin_addr.s_addr&d->info.network.interface_netmask.sin_addr.s_addr) != (d->info.network.address.sin_addr.s_addr&d->info.network.interface_netmask.sin_addr.s_addr)) { + gtk_button_set_label(GTK_BUTTON(start_button),"Subnet!"); + gtk_widget_set_sensitive(start_button, FALSE); + } + + } +#ifdef GPIO + GtkWidget *gpio_b=gtk_button_new_with_label("Config GPIO"); + g_signal_connect (gpio_b, "button-press-event", G_CALLBACK(gpio_cb), NULL); + gtk_grid_attach(GTK_GRID(grid),gpio_b,0,i,1,1); +#endif + GtkWidget *discover_b=gtk_button_new_with_label("Discover"); + g_signal_connect (discover_b, "button-press-event", G_CALLBACK(discover_cb), NULL); + gtk_grid_attach(GTK_GRID(grid),discover_b,1,i,1,1); + + GtkWidget *exit_b=gtk_button_new_with_label("Exit"); + g_signal_connect (exit_b, "button-press-event", G_CALLBACK(exit_cb), NULL); + gtk_grid_attach(GTK_GRID(grid),exit_b,2,i,1,1); + + gtk_container_add (GTK_CONTAINER (content), grid); + gtk_widget_show_all(discovery_dialog); +fprintf(stderr,"showing device dialog\n"); + } + + return 0; + +} + + diff --git a/discovery.h b/discovery.h new file mode 100644 index 0000000..74600f0 --- /dev/null +++ b/discovery.h @@ -0,0 +1,20 @@ +/* Copyright (C) +* 2015 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +int discovery(void *data); diff --git a/display_menu.c b/display_menu.c index 1030325..027e0e4 100644 --- a/display_menu.c +++ b/display_menu.c @@ -45,19 +45,17 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat static void detector_mode_cb(GtkWidget *widget, gpointer data) { display_detector_mode=(int)data; - SetDisplayDetectorMode(CHANNEL_RX0, 0, display_detector_mode); + SetDisplayDetectorMode(active_receiver->id, 0, display_detector_mode); } static void average_mode_cb(GtkWidget *widget, gpointer data) { display_average_mode=(int)data; - SetDisplayAverageMode(CHANNEL_RX0, 0, display_average_mode); + SetDisplayAverageMode(active_receiver->id, 0, display_average_mode); } static void time_value_changed_cb(GtkWidget *widget, gpointer data) { display_average_time=gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget)); - calculate_display_average(); - //SetDisplayAvBackmult(CHANNEL_RX0, 0, display_avb); - //SetDisplayNumAverage(CHANNEL_RX0, 0, display_average); + calculate_display_average(active_receiver); } static void filled_cb(GtkWidget *widget, gpointer data) { @@ -66,54 +64,50 @@ static void filled_cb(GtkWidget *widget, gpointer data) { static void frames_per_second_value_changed_cb(GtkWidget *widget, gpointer data) { updates_per_second=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); - calculate_display_average(); + calculate_display_average(active_receiver); } static void panadapter_high_value_changed_cb(GtkWidget *widget, gpointer data) { - panadapter_high=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); + active_receiver->panadapter_high=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); } static void panadapter_low_value_changed_cb(GtkWidget *widget, gpointer data) { - panadapter_low=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); + active_receiver->panadapter_low=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); } static void waterfall_high_value_changed_cb(GtkWidget *widget, gpointer data) { - waterfall_high=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); + active_receiver->waterfall_high=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); } static void waterfall_low_value_changed_cb(GtkWidget *widget, gpointer data) { - waterfall_low=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); + active_receiver->waterfall_low=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); } static void waterfall_automatic_cb(GtkWidget *widget, gpointer data) { - waterfall_automatic=waterfall_automatic==1?0:1; + active_receiver->waterfall_automatic=active_receiver->waterfall_automatic==1?0:1; } static void display_panadapter_cb(GtkWidget *widget, gpointer data) { - display_panadapter=display_panadapter==1?0:1; - reconfigure_display(); + active_receiver->display_panadapter=active_receiver->display_panadapter==1?0:1; + reconfigure_radio(); } static void display_waterfall_cb(GtkWidget *widget, gpointer data) { - display_waterfall=display_waterfall==1?0:1; - reconfigure_display(); + active_receiver->display_waterfall=active_receiver->display_waterfall==1?0:1; + reconfigure_radio(); } static void display_sliders_cb(GtkWidget *widget, gpointer data) { display_sliders=display_sliders==1?0:1; - reconfigure_display(); + reconfigure_radio(); } +/* static void display_toolbar_cb(GtkWidget *widget, gpointer data) { display_toolbar=display_toolbar==1?0:1; - reconfigure_display(); + reconfigure_radio(); } - -static void toolbar_dialog_buttons_cb(GtkWidget *widget, gpointer data) { - toolbar_dialog_buttons=toolbar_dialog_buttons==1?0:1; - update_toolbar_labels(); -} - +*/ void display_menu(GtkWidget *parent) { int i; @@ -169,7 +163,7 @@ void display_menu(GtkWidget *parent) { GtkWidget *panadapter_high_r=gtk_spin_button_new_with_range(-220.0,100.0,1.0); //gtk_widget_override_font(panadapter_high_r, pango_font_description_from_string("Arial 18")); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(panadapter_high_r),(double)panadapter_high); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(panadapter_high_r),(double)active_receiver->panadapter_high); gtk_widget_show(panadapter_high_r); gtk_grid_attach(GTK_GRID(grid),panadapter_high_r,1,3,1,1); g_signal_connect(panadapter_high_r,"value_changed",G_CALLBACK(panadapter_high_value_changed_cb),NULL); @@ -181,7 +175,7 @@ void display_menu(GtkWidget *parent) { GtkWidget *panadapter_low_r=gtk_spin_button_new_with_range(-220.0,100.0,1.0); //gtk_widget_override_font(panadapter_low_r, pango_font_description_from_string("Arial 18")); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(panadapter_low_r),(double)panadapter_low); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(panadapter_low_r),(double)active_receiver->panadapter_low); gtk_widget_show(panadapter_low_r); gtk_grid_attach(GTK_GRID(grid),panadapter_low_r,1,4,1,1); g_signal_connect(panadapter_low_r,"value_changed",G_CALLBACK(panadapter_low_value_changed_cb),NULL); @@ -193,7 +187,7 @@ void display_menu(GtkWidget *parent) { GtkWidget *waterfall_automatic_b=gtk_check_button_new(); //gtk_widget_override_font(waterfall_automatic_b, pango_font_description_from_string("Arial 18")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (waterfall_automatic_b), waterfall_automatic); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (waterfall_automatic_b), active_receiver->waterfall_automatic); gtk_widget_show(waterfall_automatic_b); gtk_grid_attach(GTK_GRID(grid),waterfall_automatic_b,1,5,1,1); g_signal_connect(waterfall_automatic_b,"toggled",G_CALLBACK(waterfall_automatic_cb),NULL); @@ -205,7 +199,7 @@ void display_menu(GtkWidget *parent) { GtkWidget *waterfall_high_r=gtk_spin_button_new_with_range(-220.0,100.0,1.0); //gtk_widget_override_font(waterfall_high_r, pango_font_description_from_string("Arial 18")); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(waterfall_high_r),(double)waterfall_high); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(waterfall_high_r),(double)active_receiver->waterfall_high); gtk_widget_show(waterfall_high_r); gtk_grid_attach(GTK_GRID(grid),waterfall_high_r,1,6,1,1); g_signal_connect(waterfall_high_r,"value_changed",G_CALLBACK(waterfall_high_value_changed_cb),NULL); @@ -217,7 +211,7 @@ void display_menu(GtkWidget *parent) { GtkWidget *waterfall_low_r=gtk_spin_button_new_with_range(-220.0,100.0,1.0); //gtk_widget_override_font(waterfall_low_r, pango_font_description_from_string("Arial 18")); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(waterfall_low_r),(double)waterfall_low); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(waterfall_low_r),(double)active_receiver->waterfall_low); gtk_widget_show(waterfall_low_r); gtk_grid_attach(GTK_GRID(grid),waterfall_low_r,1,7,1,1); g_signal_connect(waterfall_low_r,"value_changed",G_CALLBACK(waterfall_low_value_changed_cb),NULL); @@ -294,16 +288,18 @@ void display_menu(GtkWidget *parent) { gtk_grid_attach(GTK_GRID(grid),time_r,4,6,1,1); g_signal_connect(time_r,"value_changed",G_CALLBACK(time_value_changed_cb),NULL); +/* GtkWidget *b_display_panadapter=gtk_check_button_new_with_label("Display Panadapter"); //gtk_widget_override_font(b_display_panadapter, pango_font_description_from_string("Arial 18")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_display_panadapter), display_panadapter); gtk_widget_show(b_display_panadapter); gtk_grid_attach(GTK_GRID(grid),b_display_panadapter,0,8,1,1); g_signal_connect(b_display_panadapter,"toggled",G_CALLBACK(display_panadapter_cb),(gpointer *)NULL); +*/ GtkWidget *b_display_waterfall=gtk_check_button_new_with_label("Display Waterfall"); //gtk_widget_override_font(b_display_waterfall, pango_font_description_from_string("Arial 18")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_display_waterfall), display_waterfall); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_display_waterfall), active_receiver->display_waterfall); gtk_widget_show(b_display_waterfall); gtk_grid_attach(GTK_GRID(grid),b_display_waterfall,1,8,1,1); g_signal_connect(b_display_waterfall,"toggled",G_CALLBACK(display_waterfall_cb),(gpointer *)NULL); @@ -315,20 +311,14 @@ void display_menu(GtkWidget *parent) { gtk_grid_attach(GTK_GRID(grid),b_display_sliders,2,8,1,1); g_signal_connect(b_display_sliders,"toggled",G_CALLBACK(display_sliders_cb),(gpointer *)NULL); +/* GtkWidget *b_display_toolbar=gtk_check_button_new_with_label("Display Toolbar"); //gtk_widget_override_font(b_display_toolbar, pango_font_description_from_string("Arial 18")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_display_toolbar), display_toolbar); gtk_widget_show(b_display_toolbar); gtk_grid_attach(GTK_GRID(grid),b_display_toolbar,3,8,1,1); g_signal_connect(b_display_toolbar,"toggled",G_CALLBACK(display_toolbar_cb),(gpointer *)NULL); - - GtkWidget *b_toolbar_dialog_buttons=gtk_check_button_new_with_label("Buttons Display Dialog"); - //gtk_widget_override_font(b_toolbar_dialog_buttons, pango_font_description_from_string("Arial 18")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_toolbar_dialog_buttons), toolbar_dialog_buttons); - gtk_widget_show(b_toolbar_dialog_buttons); - gtk_grid_attach(GTK_GRID(grid),b_toolbar_dialog_buttons,0,9,1,1); - g_signal_connect(b_toolbar_dialog_buttons,"toggled",G_CALLBACK(toolbar_dialog_buttons_cb),(gpointer *)NULL); - +*/ gtk_container_add(GTK_CONTAINER(content),grid); sub_menu=dialog; diff --git a/dsp_menu.c b/dsp_menu.c index 1878d79..690a90e 100644 --- a/dsp_menu.c +++ b/dsp_menu.c @@ -27,6 +27,7 @@ #include "agc.h" #include "channel.h" #include "radio.h" +#include "receiver.h" #include "wdsp.h" static GtkWidget *parent_window=NULL; @@ -45,35 +46,35 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat } static void agc_hang_threshold_value_changed_cb(GtkWidget *widget, gpointer data) { - agc_hang_threshold=(int)gtk_range_get_value(GTK_RANGE(widget)); - if(agc==AGC_LONG || agc==AGC_SLOW) { - SetRXAAGCHangThreshold(CHANNEL_RX0, (int)agc_hang_threshold); + active_receiver->agc_hang_threshold=(int)gtk_range_get_value(GTK_RANGE(widget)); + if(active_receiver->agc==AGC_LONG || active_receiver->agc==AGC_SLOW) { + SetRXAAGCHangThreshold(active_receiver->id, (int)active_receiver->agc_hang_threshold); } } static void pre_post_agc_cb(GtkWidget *widget, gpointer data) { - nr_agc=(int)data; - SetRXAEMNRPosition(CHANNEL_RX0, nr_agc); + active_receiver->nr_agc=(int)data; + SetRXAEMNRPosition(active_receiver->id, active_receiver->nr_agc); } static void nr2_gain_cb(GtkWidget *widget, gpointer data) { - nr2_gain_method==(int)data; - SetRXAEMNRgainMethod(CHANNEL_RX0, nr2_gain_method); + active_receiver->nr2_gain_method==(int)data; + SetRXAEMNRgainMethod(active_receiver->id, active_receiver->nr2_gain_method); } static void nr2_npe_method_cb(GtkWidget *widget, gpointer data) { - nr2_npe_method=(int)data; - SetRXAEMNRnpeMethod(CHANNEL_RX0, nr2_npe_method); + active_receiver->nr2_npe_method=(int)data; + SetRXAEMNRnpeMethod(active_receiver->id, active_receiver->nr2_npe_method); } static void ae_cb(GtkWidget *widget, gpointer data) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { - nr2_ae=1; + active_receiver->nr2_ae=1; } else { - nr2_ae=0; + active_receiver->nr2_ae=0; } - SetRXAEMNRaeRun(CHANNEL_RX0, nr2_ae); + SetRXAEMNRaeRun(active_receiver->id, active_receiver->nr2_ae); } void dsp_menu(GtkWidget *parent) { @@ -108,7 +109,7 @@ void dsp_menu(GtkWidget *parent) { gtk_widget_show(agc_hang_threshold_label); gtk_grid_attach(GTK_GRID(grid),agc_hang_threshold_label,0,1,1,1); GtkWidget *agc_hang_threshold_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0.0, 100.0, 1.0); - gtk_range_set_value (GTK_RANGE(agc_hang_threshold_scale),agc_hang_threshold); + gtk_range_set_value (GTK_RANGE(agc_hang_threshold_scale),active_receiver->agc_hang_threshold); gtk_widget_show(agc_hang_threshold_scale); gtk_grid_attach(GTK_GRID(grid),agc_hang_threshold_scale,1,1,2,1); g_signal_connect(G_OBJECT(agc_hang_threshold_scale),"value_changed",G_CALLBACK(agc_hang_threshold_value_changed_cb),NULL); @@ -119,13 +120,13 @@ void dsp_menu(GtkWidget *parent) { gtk_grid_attach(GTK_GRID(grid),pre_post_agc_label,0,2,1,1); GtkWidget *pre_agc_b=gtk_radio_button_new_with_label(NULL,"Pre AGC"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pre_agc_b),nr_agc==0); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pre_agc_b),active_receiver->nr_agc==0); gtk_widget_show(pre_agc_b); gtk_grid_attach(GTK_GRID(grid),pre_agc_b,1,2,1,1); g_signal_connect(pre_agc_b,"pressed",G_CALLBACK(pre_post_agc_cb),(gpointer *)0); GtkWidget *post_agc_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(pre_agc_b),"Post AGC"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (post_agc_b), nr_agc==1); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (post_agc_b), active_receiver->nr_agc==1); gtk_widget_show(post_agc_b); gtk_grid_attach(GTK_GRID(grid),post_agc_b,2,2,1,1); g_signal_connect(post_agc_b,"pressed",G_CALLBACK(pre_post_agc_cb),(gpointer *)1); @@ -136,19 +137,19 @@ void dsp_menu(GtkWidget *parent) { gtk_grid_attach(GTK_GRID(grid),nr2_gain_label,0,3,1,1); GtkWidget *linear_b=gtk_radio_button_new_with_label(NULL,"Linear"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (linear_b),nr2_gain_method==0); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (linear_b),active_receiver->nr2_gain_method==0); gtk_widget_show(linear_b); gtk_grid_attach(GTK_GRID(grid),linear_b,1,3,1,1); g_signal_connect(linear_b,"pressed",G_CALLBACK(nr2_gain_cb),(gpointer *)0); GtkWidget *log_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(linear_b),"Log"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (log_b), nr2_gain_method==1); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (log_b), active_receiver->nr2_gain_method==1); gtk_widget_show(log_b); gtk_grid_attach(GTK_GRID(grid),log_b,2,3,1,1); g_signal_connect(log_b,"pressed",G_CALLBACK(nr2_gain_cb),(gpointer *)1); GtkWidget *gamma_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(log_b),"Gamma"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gamma_b), nr2_gain_method==2); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gamma_b), active_receiver->nr2_gain_method==2); gtk_widget_show(gamma_b); gtk_grid_attach(GTK_GRID(grid),gamma_b,3,3,1,1); g_signal_connect(gamma_b,"pressed",G_CALLBACK(nr2_gain_cb),(gpointer *)2); @@ -159,20 +160,20 @@ void dsp_menu(GtkWidget *parent) { gtk_grid_attach(GTK_GRID(grid),nr2_npe_method_label,0,4,1,1); GtkWidget *osms_b=gtk_radio_button_new_with_label(NULL,"OSMS"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (osms_b),nr2_npe_method==0); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (osms_b),active_receiver->nr2_npe_method==0); gtk_widget_show(osms_b); gtk_grid_attach(GTK_GRID(grid),osms_b,1,4,1,1); g_signal_connect(osms_b,"pressed",G_CALLBACK(nr2_npe_method_cb),(gpointer *)0); GtkWidget *mmse_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(osms_b),"MMSE"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mmse_b), nr2_npe_method==1); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mmse_b), active_receiver->nr2_npe_method==1); gtk_widget_show(mmse_b); gtk_grid_attach(GTK_GRID(grid),mmse_b,2,4,1,1); g_signal_connect(mmse_b,"pressed",G_CALLBACK(nr2_npe_method_cb),(gpointer *)1); GtkWidget *ae_b=gtk_check_button_new_with_label("NR2 AE Filter"); //gtk_widget_override_font(ae_b, pango_font_description_from_string("Arial 18")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ae_b), nr2_ae); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ae_b), active_receiver->nr2_ae); gtk_widget_show(ae_b); gtk_grid_attach(GTK_GRID(grid),ae_b,0,5,1,1); g_signal_connect(ae_b,"toggled",G_CALLBACK(ae_cb),NULL); diff --git a/encoder_menu.c b/encoder_menu.c new file mode 100644 index 0000000..f2dabf7 --- /dev/null +++ b/encoder_menu.c @@ -0,0 +1,289 @@ +/* Copyright (C) +* 2016 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#include +#include +#include + +#include "main.h" +#include "new_menu.h" +#include "agc_menu.h" +#include "agc.h" +#include "band.h" +#include "channel.h" +#include "radio.h" +#include "receiver.h" +#include "vfo.h" +#include "button_text.h" +#include "gpio.h" + +static GtkWidget *parent_window=NULL; + +static GtkWidget *dialog=NULL; + +static GtkWidget *b_af_gain; +static GtkWidget *b_agc_gain; +static GtkWidget *b_attenuation; +static GtkWidget *b_mic_gain; +static GtkWidget *b_drive; +static GtkWidget *b_tune_drive; +static GtkWidget *b_rit; +static GtkWidget *b_cw_speed; +static GtkWidget *b_cw_frequency; +static GtkWidget *b_panadapter_high; +static GtkWidget *b_panadapter_low; + +static int encoder; + + +static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { + if(dialog!=NULL) { + gtk_widget_destroy(dialog); + dialog=NULL; + sub_menu=NULL; + } + active_menu=NO_MENU; + return TRUE; +} + +void encoder_select(int pos) { + int action; + GtkWidget *button; + switch(encoder) { + case 1: + if(pos>0) { + e1_encoder_action--; + if(e1_encoder_action<0) { + e1_encoder_action=ENCODER_LAST; + } + } if(pos<0) { + e1_encoder_action++; + if(e1_encoder_action>ENCODER_LAST) { + e1_encoder_action=0; + } + } + action=e1_encoder_action; + break; + case 2: + if(pos>0) { + e2_encoder_action--; + if(e2_encoder_action<0) { + e2_encoder_action=ENCODER_LAST; + } + } if(pos<0) { + e2_encoder_action++; + if(e2_encoder_action>ENCODER_LAST) { + e2_encoder_action=0; + } + } + action=e2_encoder_action; + break; + case 3: + if(pos>0) { + e3_encoder_action--; + if(e3_encoder_action<0) { + e3_encoder_action=ENCODER_LAST; + } + } if(pos<0) { + e3_encoder_action++; + if(e3_encoder_action>ENCODER_LAST) { + e3_encoder_action=0; + } + } + action=e3_encoder_action; + break; + } + + switch(action) { + case ENCODER_AF_GAIN: + button=b_af_gain; + break; + case ENCODER_AGC_GAIN: + button=b_agc_gain; + break; + case ENCODER_ATTENUATION: + button=b_attenuation; + break; + case ENCODER_MIC_GAIN: + button=b_mic_gain; + break; + case ENCODER_DRIVE: + button=b_drive; + break; + case ENCODER_TUNE_DRIVE: + button=b_tune_drive; + break; + case ENCODER_RIT: + button=b_rit; + break; + case ENCODER_CW_SPEED: + button=b_cw_speed; + break; + case ENCODER_CW_FREQUENCY: + button=b_cw_frequency; + break; + case ENCODER_PANADAPTER_HIGH: + button=b_panadapter_high; + break; + case ENCODER_PANADAPTER_LOW: + button=b_panadapter_low; + break; + } + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); + +} + +static gboolean action_select_cb (GtkWidget *widget, gpointer data) { + int action=(int)data; + switch(encoder) { + case 1: + e1_encoder_action=action; + break; + case 2: + e2_encoder_action=action; + break; + case 3: + e3_encoder_action=action; + break; + } +} + +void encoder_menu(GtkWidget *parent,int e) { + GtkWidget *b; + int i; + BAND *band; + + encoder=e; + + int encoder_action; + switch(encoder) { + case 1: + encoder_action=e1_encoder_action; + break; + case 2: + encoder_action=e2_encoder_action; + break; + case 3: + encoder_action=e3_encoder_action; + break; + } + parent_window=parent; + + dialog=gtk_dialog_new(); + gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window)); + gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE); + + GdkRGBA color; + color.red = 1.0; + color.green = 1.0; + color.blue = 1.0; + color.alpha = 1.0; + gtk_widget_override_background_color(dialog,GTK_STATE_FLAG_NORMAL,&color); + + GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + + GtkWidget *grid=gtk_grid_new(); + + gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE); + gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE); + gtk_grid_set_column_spacing (GTK_GRID(grid),5); + gtk_grid_set_row_spacing (GTK_GRID(grid),5); + + 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); + + char label_text[32]; + sprintf(label_text,"Encoder E%d Action:",encoder); + GtkWidget *label=gtk_label_new(label_text); + gtk_grid_attach(GTK_GRID(grid),label,0,1,2,1); + + b_af_gain=gtk_radio_button_new_with_label(NULL,"AF Gain"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_af_gain), encoder_action==ENCODER_AF_GAIN); + gtk_widget_show(b_af_gain); + gtk_grid_attach(GTK_GRID(grid),b_af_gain,0,2,2,1); + g_signal_connect(b_af_gain,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_AF_GAIN); + + b_agc_gain=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_af_gain),"AGC Gain"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_agc_gain), encoder_action==ENCODER_AGC_GAIN); + gtk_widget_show(b_agc_gain); + gtk_grid_attach(GTK_GRID(grid),b_agc_gain,0,3,2,1); + g_signal_connect(b_agc_gain,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_AGC_GAIN); + + b_attenuation=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_agc_gain),"Attenuation"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_attenuation), encoder_action==ENCODER_ATTENUATION); + gtk_widget_show(b_attenuation); + gtk_grid_attach(GTK_GRID(grid),b_attenuation,0,4,2,1); + g_signal_connect(b_attenuation,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_ATTENUATION); + + b_mic_gain=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_attenuation),"Mic Gain"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_mic_gain), encoder_action==ENCODER_MIC_GAIN); + gtk_widget_show(b_mic_gain); + gtk_grid_attach(GTK_GRID(grid),b_mic_gain,0,5,2,1); + g_signal_connect(b_mic_gain,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_MIC_GAIN); + + b_drive=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_mic_gain),"Drive"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_drive), encoder_action==ENCODER_DRIVE); + gtk_widget_show(b_drive); + gtk_grid_attach(GTK_GRID(grid),b_drive,0,6,2,1); + g_signal_connect(b_drive,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_DRIVE); + + b_tune_drive=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_drive),"Tune Drive"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_tune_drive), encoder_action==ENCODER_TUNE_DRIVE); + gtk_widget_show(b_tune_drive); + gtk_grid_attach(GTK_GRID(grid),b_tune_drive,0,7,2,1); + g_signal_connect(b_tune_drive,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_TUNE_DRIVE); + + b_rit=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_tune_drive),"RIT"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_rit), encoder_action==ENCODER_RIT); + gtk_widget_show(b_rit); + gtk_grid_attach(GTK_GRID(grid),b_rit,2,2,2,1); + g_signal_connect(b_rit,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_RIT); + + b_cw_speed=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_rit),"CW Speed"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_cw_speed), encoder_action==ENCODER_CW_SPEED); + gtk_widget_show(b_cw_speed); + gtk_grid_attach(GTK_GRID(grid),b_cw_speed,2,3,2,1); + g_signal_connect(b_cw_speed,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_CW_SPEED); + + b_cw_frequency=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_cw_speed),"CW Freq"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_cw_frequency), encoder_action==ENCODER_CW_FREQUENCY); + gtk_widget_show(b_cw_frequency); + gtk_grid_attach(GTK_GRID(grid),b_cw_frequency,2,4,2,1); + g_signal_connect(b_cw_frequency,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_CW_FREQUENCY); + + b_panadapter_high=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_cw_frequency),"Panadapter High"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_panadapter_high), encoder_action==ENCODER_PANADAPTER_HIGH); + gtk_widget_show(b_panadapter_high); + gtk_grid_attach(GTK_GRID(grid),b_panadapter_high,2,6,2,1); + g_signal_connect(b_panadapter_high,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_PANADAPTER_HIGH); + + b_panadapter_low=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_cw_frequency),"Panadapter Low"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_panadapter_low), encoder_action==ENCODER_PANADAPTER_LOW); + gtk_widget_show(b_panadapter_low); + gtk_grid_attach(GTK_GRID(grid),b_panadapter_low,2,7,2,1); + g_signal_connect(b_panadapter_low,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_PANADAPTER_LOW); + + gtk_container_add(GTK_CONTAINER(content),grid); + + sub_menu=dialog; + + gtk_widget_show_all(dialog); + +} diff --git a/encoder_menu.h b/encoder_menu.h new file mode 100644 index 0000000..8b45595 --- /dev/null +++ b/encoder_menu.h @@ -0,0 +1,26 @@ +/* Copyright (C) +* 2016 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#ifndef _ENCODER_MENU_H +#define _ENCODER_MENU_H + +extern void encoder_menu(GtkWidget *parent,int e); + +extern void encoder_select(int pos); +#endif diff --git a/equalizer_menu.c b/equalizer_menu.c index c474baa..f2c7582 100644 --- a/equalizer_menu.c +++ b/equalizer_menu.c @@ -76,10 +76,10 @@ static gboolean rx_rb_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat static gboolean enable_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { if(tx_menu) { enable_tx_equalizer=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); - SetTXAEQRun(CHANNEL_TX, enable_tx_equalizer); + SetTXAEQRun(transmitter->id, enable_tx_equalizer); } else { enable_rx_equalizer=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); - SetRXAEQRun(CHANNEL_RX0, enable_rx_equalizer); + SetRXAEQRun(active_receiver->id, enable_rx_equalizer); } } @@ -87,10 +87,10 @@ static gboolean rx_value_changed_cb (GtkWidget *widget, GdkEventButton *event, g int i=(int)data; if(tx_menu) { tx_equalizer[i]=(int)gtk_range_get_value(GTK_RANGE(widget)); - SetTXAGrphEQ(CHANNEL_TX, tx_equalizer); + SetTXAGrphEQ(transmitter->id, tx_equalizer); } else { rx_equalizer[i]=(int)gtk_range_get_value(GTK_RANGE(widget)); - SetRXAGrphEQ(CHANNEL_RX0, rx_equalizer); + SetRXAGrphEQ(active_receiver->id, rx_equalizer); } } diff --git a/filter.c b/filter.c index 84492ad..63d959c 100644 --- a/filter.c +++ b/filter.c @@ -17,7 +17,9 @@ * */ +#include #include "filter.h" +#include "property.h" FILTER filterLSB[FILTERS]={ {-5150,-150,"5.0k"}, @@ -29,9 +31,9 @@ FILTER filterLSB[FILTERS]={ {-2550,-150,"2.4k"}, {-2250,-150,"2.1k"}, {-1950,-150,"1.8k"}, - {-1150,-150,"1.0k"}/*, + {-1150,-150,"1.0k"}, {-2850,-150,"Var1"}, - {-2850,-150,"Var2"}*/ + {-2850,-150,"Var2"} }; FILTER filterDIGL[FILTERS]={ @@ -44,9 +46,9 @@ FILTER filterDIGL[FILTERS]={ {-2550,-150,"2.4k"}, {-2250,-150,"2.1k"}, {-1950,-150,"1.8k"}, - {-1150,-150,"1.0k"}/*, + {-1150,-150,"1.0k"}, {-2850,-150,"Var1"}, - {-2850,-150,"Var2"}*/ + {-2850,-150,"Var2"} }; FILTER filterUSB[FILTERS]={ @@ -59,9 +61,9 @@ FILTER filterUSB[FILTERS]={ {150,2550,"2.4k"}, {150,2250,"2.1k"}, {150,1950,"1.8k"}, - {150,1150,"1.0k"}/*, + {150,1150,"1.0k"}, {150,2850,"Var1"}, - {150,2850,"Var2"}*/ + {150,2850,"Var2"} }; FILTER filterDIGU[FILTERS]={ @@ -74,9 +76,9 @@ FILTER filterDIGU[FILTERS]={ {150,2550,"2.4k"}, {150,2250,"2.1k"}, {150,1950,"1.8k"}, - {150,1150,"1.0k"}/*, + {150,1150,"1.0k"}, {150,2850,"Var1"}, - {150,2850,"Var2"}*/ + {150,2850,"Var2"} }; FILTER filterCWL[FILTERS]={ @@ -89,9 +91,9 @@ FILTER filterCWL[FILTERS]={ {125,125,"250"}, {50,50,"100"}, {25,25,"50"}, - {13,13,"25"}/*, + {13,13,"25"}, {250,250,"Var1"}, - {250,250,"Var2"}*/ + {250,250,"Var2"} }; FILTER filterCWU[FILTERS]={ @@ -104,9 +106,9 @@ FILTER filterCWU[FILTERS]={ {125,125,"250"}, {50,50,"100"}, {25,25,"50"}, - {13,13,"25"}/*, + {13,13,"25"}, {250,250,"Var1"}, - {250,250,"Var2"}*/ + {250,250,"Var2"} }; FILTER filterAM[FILTERS]={ @@ -119,9 +121,9 @@ FILTER filterAM[FILTERS]={ {-2000,2000,"4.0k"}, {-1550,1550,"3.1k"}, {-1450,1450,"2.9k"}, - {-1200,1200,"2.4k"}/*, + {-1200,1200,"2.4k"}, {-3300,3300,"Var1"}, - {-3300,3300,"Var2"}*/ + {-3300,3300,"Var2"} }; FILTER filterSAM[FILTERS]={ @@ -134,9 +136,9 @@ FILTER filterSAM[FILTERS]={ {-2000,2000,"4.0k"}, {-1550,1550,"3.1k"}, {-1450,1450,"2.9k"}, - {-1200,1200,"2.4k"}/*, + {-1200,1200,"2.4k"}, {-3300,3300,"Var1"}, - {-3300,3300,"Var2"}*/ + {-3300,3300,"Var2"} }; FILTER filterFMN[FILTERS]={ @@ -149,9 +151,9 @@ FILTER filterFMN[FILTERS]={ {-2000,2000,"4.0k"}, {-1550,1550,"3.1k"}, {-1450,1450,"2.9k"}, - {-1200,1200,"2.4k"}/*, + {-1200,1200,"2.4k"}, {-3300,3300,"Var1"}, - {-3300,3300,"Var2"}*/ + {-3300,3300,"Var2"} }; FILTER filterDSB[FILTERS]={ @@ -164,9 +166,9 @@ FILTER filterDSB[FILTERS]={ {-2000,2000,"4.0k"}, {-1550,1550,"3.1k"}, {-1450,1450,"2.9k"}, - {-1200,1200,"2.4k"}/*, + {-1200,1200,"2.4k"}, {-3300,3300,"Var1"}, - {-3300,3300,"Var2"}*/ + {-3300,3300,"Var2"} }; FILTER filterSPEC[FILTERS]={ @@ -179,9 +181,9 @@ FILTER filterSPEC[FILTERS]={ {-2000,2000,"4.0k"}, {-1550,1550,"3.1k"}, {-1450,1450,"2.9k"}, - {-1200,1200,"2.4k"}/*, + {-1200,1200,"2.4k"}, {-3300,3300,"Var1"}, - {-3300,3300,"Var2"}*/ + {-3300,3300,"Var2"} }; FILTER filterDRM[FILTERS]={ @@ -194,9 +196,9 @@ FILTER filterDRM[FILTERS]={ {-2000,2000,"4.0k"}, {-1550,1550,"3.1k"}, {-1450,1450,"2.9k"}, - {-1200,1200,"2.4k"}/*, + {-1200,1200,"2.4k"}, {-3300,3300,"Var1"}, - {-3300,3300,"Var2"}*/ + {-3300,3300,"Var2"} }; #ifdef FREEDV @@ -210,9 +212,9 @@ FILTER filterFREEDV[FILTERS]={ {150,2550,"2.4k"}, {150,2250,"2.1k"}, {150,1950,"1.8k"}, - {150,1150,"1.0k"}/*, + {150,1150,"1.0k"}, {150,2850,"Var1"}, - {150,2850,"Var2"}*/ + {150,2850,"Var2"} }; #endif @@ -227,9 +229,9 @@ FILTER filterPSK[FILTERS]={ {150,2550,"2.4k"}, {150,2250,"2.1k"}, {150,1950,"1.8k"}, - {150,1150,"1.0k"}/*, + {150,1150,"1.0k"}, {150,2850,"Var1"}, - {150,2850,"Var2"}*/ + {150,2850,"Var2"} }; #endif @@ -256,3 +258,194 @@ FILTER *filters[]={ }; +void filterSaveState() { + char value[128]; + + // save the Var1 and Var2 settings + sprintf(value,"%d",filterLSB[filterVar1].low); + setProperty("filter.lsb.var1.low",value); + sprintf(value,"%d",filterLSB[filterVar1].high); + setProperty("filter.lsb.var1.high",value); + sprintf(value,"%d",filterLSB[filterVar2].low); + setProperty("filter.lsb.var2.low",value); + sprintf(value,"%d",filterLSB[filterVar2].high); + setProperty("filter.lsb.var2.high",value); + + sprintf(value,"%d",filterDIGL[filterVar1].low); + setProperty("filter.digl.var1.low",value); + sprintf(value,"%d",filterDIGL[filterVar1].high); + setProperty("filter.digl.var1.high",value); + sprintf(value,"%d",filterDIGL[filterVar2].low); + setProperty("filter.digl.var2.low",value); + sprintf(value,"%d",filterDIGL[filterVar2].high); + setProperty("filter.digl.var2.high",value); + + sprintf(value,"%d",filterCWL[filterVar1].low); + setProperty("filter.cwl.var1.low",value); + sprintf(value,"%d",filterCWL[filterVar1].high); + setProperty("filter.cwl.var1.high",value); + sprintf(value,"%d",filterCWL[filterVar2].low); + setProperty("filter.cwl.var2.low",value); + sprintf(value,"%d",filterCWL[filterVar2].high); + setProperty("filter.cwl.var2.high",value); + + sprintf(value,"%d",filterUSB[filterVar1].low); + setProperty("filter.usb.var1.low",value); + sprintf(value,"%d",filterUSB[filterVar1].high); + setProperty("filter.usb.var1.high",value); + sprintf(value,"%d",filterUSB[filterVar2].low); + setProperty("filter.usb.var2.low",value); + sprintf(value,"%d",filterUSB[filterVar2].high); + setProperty("filter.usb.var2.high",value); + + sprintf(value,"%d",filterDIGU[filterVar1].low); + setProperty("filter.digu.var1.low",value); + sprintf(value,"%d",filterDIGU[filterVar1].high); + setProperty("filter.digu.var1.high",value); + sprintf(value,"%d",filterDIGU[filterVar2].low); + setProperty("filter.digu.var2.low",value); + sprintf(value,"%d",filterDIGU[filterVar2].high); + setProperty("filter.digu.var2.high",value); + + sprintf(value,"%d",filterCWU[filterVar1].low); + setProperty("filter.cwu.var1.low",value); + sprintf(value,"%d",filterCWU[filterVar1].high); + setProperty("filter.cwu.var1.high",value); + sprintf(value,"%d",filterCWU[filterVar2].low); + setProperty("filter.cwu.var2.low",value); + sprintf(value,"%d",filterCWU[filterVar2].high); + setProperty("filter.cwu.var2.high",value); + + sprintf(value,"%d",filterAM[filterVar1].low); + setProperty("filter.am.var1.low",value); + sprintf(value,"%d",filterAM[filterVar1].high); + setProperty("filter.am.var1.high",value); + sprintf(value,"%d",filterAM[filterVar2].low); + setProperty("filter.am.var2.low",value); + sprintf(value,"%d",filterAM[filterVar2].high); + setProperty("filter.am.var2.high",value); + + sprintf(value,"%d",filterSAM[filterVar1].low); + setProperty("filter.sam.var1.low",value); + sprintf(value,"%d",filterSAM[filterVar1].high); + setProperty("filter.sam.var1.high",value); + sprintf(value,"%d",filterSAM[filterVar2].low); + setProperty("filter.sam.var2.low",value); + sprintf(value,"%d",filterSAM[filterVar2].high); + setProperty("filter.sam.var2.high",value); + + sprintf(value,"%d",filterFMN[filterVar1].low); + setProperty("filter.fmn.var1.low",value); + sprintf(value,"%d",filterFMN[filterVar1].high); + setProperty("filter.fmn.var1.high",value); + sprintf(value,"%d",filterFMN[filterVar2].low); + setProperty("filter.fmn.var2.low",value); + sprintf(value,"%d",filterFMN[filterVar2].high); + setProperty("filter.fmn.var2.high",value); + + sprintf(value,"%d",filterDSB[filterVar1].low); + setProperty("filter.dsb.var1.low",value); + sprintf(value,"%d",filterDSB[filterVar1].high); + setProperty("filter.dsb.var1.high",value); + sprintf(value,"%d",filterDSB[filterVar2].low); + setProperty("filter.dsb.var2.low",value); + sprintf(value,"%d",filterDSB[filterVar2].high); + setProperty("filter.dsb.var2.high",value); + +} + +void filterRestoreState() { + char* value; + + value=getProperty("filter.lsb.var1.low"); + if(value) filterLSB[filterVar1].low=atoi(value); + value=getProperty("filter.lsb.var1.high"); + if(value) filterLSB[filterVar1].high=atoi(value); + value=getProperty("filter.lsb.var2.low"); + if(value) filterLSB[filterVar2].low=atoi(value); + value=getProperty("filter.lsb.var2.high"); + if(value) filterLSB[filterVar2].high=atoi(value); + + value=getProperty("filter.digl.var1.low"); + if(value) filterDIGL[filterVar1].low=atoi(value); + value=getProperty("filter.digl.var1.high"); + if(value) filterDIGL[filterVar1].high=atoi(value); + value=getProperty("filter.digl.var2.low"); + if(value) filterDIGL[filterVar2].low=atoi(value); + value=getProperty("filter.digl.var2.high"); + if(value) filterDIGL[filterVar2].high=atoi(value); + + value=getProperty("filter.cwl.var1.low"); + if(value) filterCWL[filterVar1].low=atoi(value); + value=getProperty("filter.cwl.var1.high"); + if(value) filterCWL[filterVar1].high=atoi(value); + value=getProperty("filter.cwl.var2.low"); + if(value) filterCWL[filterVar2].low=atoi(value); + value=getProperty("filter.cwl.var2.high"); + if(value) filterCWL[filterVar2].high=atoi(value); + + value=getProperty("filter.usb.var1.low"); + if(value) filterUSB[filterVar1].low=atoi(value); + value=getProperty("filter.usb.var1.high"); + if(value) filterUSB[filterVar1].high=atoi(value); + value=getProperty("filter.usb.var2.low"); + if(value) filterUSB[filterVar2].low=atoi(value); + value=getProperty("filter.usb.var2.high"); + if(value) filterUSB[filterVar2].high=atoi(value); + + value=getProperty("filter.digu.var1.low"); + if(value) filterDIGU[filterVar1].low=atoi(value); + value=getProperty("filter.digu.var1.high"); + if(value) filterDIGU[filterVar1].high=atoi(value); + value=getProperty("filter.digu.var2.low"); + if(value) filterDIGU[filterVar2].low=atoi(value); + value=getProperty("filter.digu.var2.high"); + if(value) filterDIGU[filterVar2].high=atoi(value); + + value=getProperty("filter.cwu.var1.low"); + if(value) filterCWU[filterVar1].low=atoi(value); + value=getProperty("filter.cwu.var1.high"); + if(value) filterCWU[filterVar1].high=atoi(value); + value=getProperty("filter.cwu.var2.low"); + if(value) filterCWU[filterVar2].low=atoi(value); + value=getProperty("filter.cwu.var2.high"); + if(value) filterCWU[filterVar2].high=atoi(value); + + value=getProperty("filter.am.var1.low"); + if(value) filterAM[filterVar1].low=atoi(value); + value=getProperty("filter.am.var1.high"); + if(value) filterAM[filterVar1].high=atoi(value); + value=getProperty("filter.am.var2.low"); + if(value) filterAM[filterVar2].low=atoi(value); + value=getProperty("filter.am.var2.high"); + if(value) filterAM[filterVar2].high=atoi(value); + + value=getProperty("filter.sam.var1.low"); + if(value) filterSAM[filterVar1].low=atoi(value); + value=getProperty("filter.sam.var1.high"); + if(value) filterSAM[filterVar1].high=atoi(value); + value=getProperty("filter.sam.var2.low"); + if(value) filterSAM[filterVar2].low=atoi(value); + value=getProperty("filter.sam.var2.high"); + if(value) filterSAM[filterVar2].high=atoi(value); + + value=getProperty("filter.fmn.var1.low"); + if(value) filterFMN[filterVar1].low=atoi(value); + value=getProperty("filter.fmn.var1.high"); + if(value) filterFMN[filterVar1].high=atoi(value); + value=getProperty("filter.fmn.var2.low"); + if(value) filterFMN[filterVar2].low=atoi(value); + value=getProperty("filter.fmn.var2.high"); + if(value) filterFMN[filterVar2].high=atoi(value); + + value=getProperty("filter.dsb.var1.low"); + if(value) filterDSB[filterVar1].low=atoi(value); + value=getProperty("filter.dsb.var1.high"); + if(value) filterDSB[filterVar1].high=atoi(value); + value=getProperty("filter.dsb.var2.low"); + if(value) filterDSB[filterVar2].low=atoi(value); + value=getProperty("filter.dsb.var2.high"); + if(value) filterDSB[filterVar2].high=atoi(value); + +} + diff --git a/filter.h b/filter.h index 8c91cfe..ea95003 100644 --- a/filter.h +++ b/filter.h @@ -22,8 +22,7 @@ #include "mode.h" -// disable Var1 and Var2 (change to 12 to enable) -#define FILTERS 10 +#define FILTERS 12 #define CW_PITCH 600 @@ -56,12 +55,8 @@ int filterHigh; int txFilterLowCut; int txFilterHighCut; -int filterVar1Low; -int filterVar1High; -int filterVar2Low; -int filterVar2High; - - FILTER *filters[MODES]; +void filterSaveState(); +void filterRestoreState(); #endif diff --git a/filter_menu.c b/filter_menu.c index 9b9b0dc..f0aa005 100644 --- a/filter_menu.c +++ b/filter_menu.c @@ -1,6 +1,4 @@ -/* Copyright (C) -* 2016 - John Melton, G0ORX/N6LYT -* +/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -28,9 +26,9 @@ #include "filter.h" #include "mode.h" #include "radio.h" +#include "receiver.h" #include "vfo.h" #include "button_text.h" -#include "wdsp_init.h" static GtkWidget *parent_window=NULL; @@ -47,38 +45,67 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat return TRUE; } -static gboolean filter_select_cb (GtkWidget *widget, gpointer data) { +int filter_select(void *data) { int f=(int)data; - BANDSTACK_ENTRY *entry; - entry=bandstack_entry_get_current(); - entry->filter=f; - FILTER* band_filters=filters[entry->mode]; - FILTER* band_filter=&band_filters[entry->filter]; - setFilter(band_filter->low,band_filter->high); + vfo_filter_changed(f); + return 0; +} + +static gboolean filter_select_cb (GtkWidget *widget, gpointer data) { + filter_select(data); set_button_text_color(last_filter,"black"); last_filter=widget; set_button_text_color(last_filter,"orange"); - vfo_update(NULL); } -static gboolean deviation_select_cb (GtkWidget *widget, gpointer data) { +static gboolean deviation_select_cb (GtkWidget *widget, gpointer data) { deviation=(int)data; if(deviation==2500) { - setFilter(-4000,4000); + //setFilter(-4000,4000); + set_filter(active_receiver,-4000,4000); } else { - setFilter(-8000,8000); + //setFilter(-8000,8000); + set_filter(active_receiver,-8000,8000); } - wdsp_set_deviation((double)deviation); + set_deviation(active_receiver,(double)deviation); set_button_text_color(last_filter,"black"); last_filter=widget; set_button_text_color(last_filter,"orange"); vfo_update(NULL); } +static void var_spin_low_cb (GtkWidget *widget, gpointer data) { + int f=(int)data; + int id=active_receiver->id; + + FILTER *mode_filters=filters[vfo[id].mode]; + FILTER *filter=&mode_filters[f]; + + filter->low=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); + if(vfo[id].mode==modeCWL || vfo[id].mode==modeCWU) { + filter->high=filter->low; + } + if(f==vfo[id].filter) { + receiver_filter_changed(receiver[id]); + } +} + +static void var_spin_high_cb (GtkWidget *widget, gpointer data) { + int f=(int)data; + int id=active_receiver->id; + + FILTER *mode_filters=filters[vfo[id].mode]; + FILTER *filter=&mode_filters[f]; + + filter->high=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); + if(f==vfo[id].filter) { + receiver_filter_changed(receiver[id]); + } +} + void filter_menu(GtkWidget *parent) { GtkWidget *b; int i; - BAND *band; parent_window=parent; @@ -106,8 +133,16 @@ void filter_menu(GtkWidget *parent) { g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL); gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1); - BANDSTACK_ENTRY *entry=bandstack_entry_get_current(); - FILTER* band_filters=filters[entry->mode]; + char label[32]; + sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B"); + GtkWidget *rx_label=gtk_label_new(label); + gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1); + + BAND *band=band_get_band(vfo[active_receiver->id].band); + BANDSTACK *bandstack=band->bandstack; + BANDSTACK_ENTRY *entry=&bandstack->entry[vfo[active_receiver->id].bandstack]; + FILTER* band_filters=filters[vfo[active_receiver->id].mode]; + FILTER* band_filter=&band_filters[vfo[active_receiver->id].filter]; switch(entry->mode) { case modeFMN: @@ -138,10 +173,10 @@ void filter_menu(GtkWidget *parent) { break; default: - for(i=0;ifilter) { + if(i==vfo[active_receiver->id].filter) { set_button_text_color(b,"orange"); last_filter=b; } else { @@ -150,6 +185,57 @@ void filter_menu(GtkWidget *parent) { gtk_grid_attach(GTK_GRID(grid),b,i%5,1+(i/5),1,1); g_signal_connect(b,"pressed",G_CALLBACK(filter_select_cb),(gpointer *)i); } + + // last 2 are var1 and var2 + int row=1+((i+4)/5); + FILTER* band_filter=&band_filters[i]; + GtkWidget *b=gtk_button_new_with_label(band_filters[i].title); + if(i==vfo[active_receiver->id].filter) { + set_button_text_color(b,"orange"); + last_filter=b; + } else { + set_button_text_color(b,"black"); + } + gtk_grid_attach(GTK_GRID(grid),b,0,row,1,1); + g_signal_connect(b,"pressed",G_CALLBACK(filter_select_cb),(gpointer *)i); + + GtkWidget *var1_spin_low=gtk_spin_button_new_with_range(-8000.0,+8000.0,1.0); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(var1_spin_low),(double)band_filter->low); + gtk_grid_attach(GTK_GRID(grid),var1_spin_low,1,row,1,1); + g_signal_connect(var1_spin_low,"value-changed",G_CALLBACK(var_spin_low_cb),(gpointer *)i); + + if(vfo[active_receiver->id].mode!=modeCWL && vfo[active_receiver->id].mode!=modeCWU) { + GtkWidget *var1_spin_high=gtk_spin_button_new_with_range(-8000.0,+8000.0,1.0); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(var1_spin_high),(double)band_filter->high); + gtk_grid_attach(GTK_GRID(grid),var1_spin_high,2,row,1,1); + g_signal_connect(var1_spin_high,"value-changed",G_CALLBACK(var_spin_high_cb),(gpointer *)i); + } + + row++; + i++; + band_filter=&band_filters[i]; + b=gtk_button_new_with_label(band_filters[i].title); + if(i==vfo[active_receiver->id].filter) { + set_button_text_color(b,"orange"); + last_filter=b; + } else { + set_button_text_color(b,"black"); + } + gtk_grid_attach(GTK_GRID(grid),b,0,row,1,1); + g_signal_connect(b,"pressed",G_CALLBACK(filter_select_cb),(gpointer *)i); + + GtkWidget *var2_spin_low=gtk_spin_button_new_with_range(-8000.0,+8000.0,1.0); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(var2_spin_low),(double)band_filter->low); + gtk_grid_attach(GTK_GRID(grid),var2_spin_low,1,row,1,1); + g_signal_connect(var2_spin_low,"value-changed",G_CALLBACK(var_spin_low_cb),(gpointer *)i); + + if(vfo[active_receiver->id].mode!=modeCWL && vfo[active_receiver->id].mode!=modeCWU) { + GtkWidget *var2_spin_high=gtk_spin_button_new_with_range(-8000.0,+8000.0,1.0); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(var2_spin_high),(double)band_filter->high); + gtk_grid_attach(GTK_GRID(grid),var2_spin_high,2,row,1,1); + g_signal_connect(var2_spin_high,"value-changed",G_CALLBACK(var_spin_high_cb),(gpointer *)i); + } + break; } diff --git a/filter_menu.h b/filter_menu.h index fbc39be..057532a 100644 --- a/filter_menu.h +++ b/filter_menu.h @@ -18,3 +18,4 @@ */ extern void filter_menu(GtkWidget *parent); +extern int filter_select(void *data); diff --git a/fm_menu.c b/fm_menu.c index 00d1d6c..d3d8847 100644 --- a/fm_menu.c +++ b/fm_menu.c @@ -24,7 +24,7 @@ #include "new_menu.h" #include "fm_menu.h" #include "radio.h" -#include "wdsp_init.h" +#include "transmitter.h" static GtkWidget *parent_window=NULL; @@ -47,7 +47,7 @@ static gboolean emp_cb (GtkWidget *widget, gpointer data) { } else { pre_emphasize=0; } - wdsp_set_pre_emphasize(pre_emphasize); + tx_set_pre_emphasize(transmitter,pre_emphasize); } void fm_menu(GtkWidget *parent) { diff --git a/freqent_menu.c b/freqent_menu.c index 0b34ff0..987de81 100644 --- a/freqent_menu.c +++ b/freqent_menu.c @@ -27,6 +27,7 @@ #include "filter.h" #include "mode.h" #include "radio.h" +#include "receiver.h" #include "vfo.h" static GtkWidget *parent_window=NULL; @@ -117,14 +118,17 @@ static gboolean freqent_select_cb (GtkWidget *widget, gpointer data) { if(b!=band_get_current()) { BAND *band=band_set_current(b); BANDSTACK_ENTRY *entry=bandstack_entry_get_current(); - setMode(entry->mode); + //setMode(entry->mode); + set_mode(active_receiver,entry->mode); FILTER* band_filters=filters[entry->mode]; FILTER* band_filter=&band_filters[entry->filter]; - setFilter(band_filter->low,band_filter->high); - set_alex_rx_antenna(band->alexRxAntenna); - set_alex_tx_antenna(band->alexTxAntenna); - set_alex_attenuation(band->alexAttenuation); - + //setFilter(band_filter->low,band_filter->high); + set_filter(active_receiver,band_filter->low,band_filter->high); + if(active_receiver->id==0) { + set_alex_rx_antenna(band->alexRxAntenna); + set_alex_tx_antenna(band->alexTxAntenna); + set_alex_attenuation(band->alexAttenuation); + } } setFrequency(f); vfo_update(NULL); @@ -169,7 +173,12 @@ void freqent_menu(GtkWidget *parent) { label = gtk_label_new (NULL); gtk_label_set_markup (GTK_LABEL (label), "0"); gtk_misc_set_alignment (GTK_MISC (label), 1, .5); - gtk_grid_attach(GTK_GRID(grid),label,1,0,1,1); + gtk_grid_attach(GTK_GRID(grid),label,1,0,2,1); + + char label[32]; + sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B"); + GtkWidget *rx_label=gtk_label_new(label); + gtk_grid_attach(GTK_GRID(grid),rx_label,3,0,1,1); GtkWidget *step_rb=NULL; for (i=0; i<16; i++) { diff --git a/general_menu.c b/general_menu.c index f3757df..da5bb15 100644 --- a/general_menu.c +++ b/general_menu.c @@ -27,6 +27,7 @@ #include "band.h" #include "filter.h" #include "radio.h" +#include "receiver.h" static GtkWidget *parent_window=NULL; @@ -47,10 +48,12 @@ static void vfo_divisor_value_changed_cb(GtkWidget *widget, gpointer data) { vfo_encoder_divisor=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); } +/* static void toolbar_dialog_buttons_cb(GtkWidget *widget, gpointer data) { toolbar_dialog_buttons=toolbar_dialog_buttons==1?0:1; update_toolbar_labels(); } +*/ static void ptt_cb(GtkWidget *widget, gpointer data) { mic_ptt_enabled=mic_ptt_enabled==1?0:1; @@ -88,14 +91,18 @@ static void alex_cb(GtkWidget *widget, gpointer data) { if(filter_board==ALEX) { BAND *band=band_get_current_band(); BANDSTACK_ENTRY* entry=bandstack_entry_get_current(); - setFrequency(entry->frequencyA); - setMode(entry->mode); + setFrequency(entry->frequency); + //setMode(entry->mode); + set_mode(active_receiver,entry->mode); FILTER* band_filters=filters[entry->mode]; FILTER* band_filter=&band_filters[entry->filter]; - setFilter(band_filter->low,band_filter->high); - set_alex_rx_antenna(band->alexRxAntenna); - set_alex_tx_antenna(band->alexTxAntenna); - set_alex_attenuation(band->alexAttenuation); + //setFilter(band_filter->low,band_filter->high); + set_filter(active_receiver,band_filter->low,band_filter->high); + if(active_receiver->id==0) { + set_alex_rx_antenna(band->alexRxAntenna); + set_alex_tx_antenna(band->alexTxAntenna); + set_alex_attenuation(band->alexAttenuation); + } } } @@ -116,53 +123,18 @@ static void apollo_cb(GtkWidget *widget, gpointer data) { if(filter_board==APOLLO) { BAND *band=band_get_current_band(); BANDSTACK_ENTRY* entry=bandstack_entry_get_current(); - setFrequency(entry->frequencyA); - setMode(entry->mode); + setFrequency(entry->frequency); + //setMode(entry->mode); + set_mode(active_receiver,entry->mode); FILTER* band_filters=filters[entry->mode]; FILTER* band_filter=&band_filters[entry->filter]; - setFilter(band_filter->low,band_filter->high); - } -} -/* -static void apollo_tuner_cb(GtkWidget *widget, gpointer data) { - apollo_tuner=apollo_tuner==1?0:1; - if(protocol==NEW_PROTOCOL) { - tuner_changed(); - } -} - -static void pa_cb(GtkWidget *widget, gpointer data) { - pa=pa==1?0:1; - if(protocol==NEW_PROTOCOL) { - pa_changed(); - } -} -*/ - -static void rx_dither_cb(GtkWidget *widget, gpointer data) { - rx_dither=rx_dither==1?0:1; - if(protocol==NEW_PROTOCOL) { - } -} - -static void rx_random_cb(GtkWidget *widget, gpointer data) { - rx_random=rx_random==1?0:1; - if(protocol==NEW_PROTOCOL) { - } -} - -static void rx_preamp_cb(GtkWidget *widget, gpointer data) { - rx_preamp=rx_preamp==1?0:1; - if(protocol==NEW_PROTOCOL) { + //setFilter(band_filter->low,band_filter->high); + set_filter(active_receiver,band_filter->low,band_filter->high); } } static void sample_rate_cb(GtkWidget *widget, gpointer data) { - if(protocol==ORIGINAL_PROTOCOL) { - old_protocol_new_sample_rate((int)data); - } else { - new_protocol_new_sample_rate((int)data); - } + radio_change_sample_rate((int)data); } static void rit_cb(GtkWidget *widget,gpointer data) { @@ -204,21 +176,11 @@ void general_menu(GtkWidget *parent) { g_signal_connect(vfo_divisor,"value_changed",G_CALLBACK(vfo_divisor_value_changed_cb),NULL); if(protocol==ORIGINAL_PROTOCOL || protocol==NEW_PROTOCOL) { - GtkWidget *rx_dither_b=gtk_check_button_new_with_label("Dither"); - //gtk_widget_override_font(rx_dither_b, pango_font_description_from_string("Arial 18")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx_dither_b), rx_dither); - gtk_grid_attach(GTK_GRID(grid),rx_dither_b,1,4,1,1); - g_signal_connect(rx_dither_b,"toggled",G_CALLBACK(rx_dither_cb),NULL); - - GtkWidget *rx_random_b=gtk_check_button_new_with_label("Random"); - //gtk_widget_override_font(rx_random_b, pango_font_description_from_string("Arial 18")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx_random_b), rx_random); - gtk_grid_attach(GTK_GRID(grid),rx_random_b,1,5,1,1); - g_signal_connect(rx_random_b,"toggled",G_CALLBACK(rx_random_cb),NULL); if((protocol==NEW_PROTOCOL && device==NEW_DEVICE_ORION) || (protocol==NEW_PROTOCOL && device==NEW_DEVICE_ORION2) || - (protocol==ORIGINAL_PROTOCOL && device==DEVICE_ORION)) { + (protocol==ORIGINAL_PROTOCOL && device==DEVICE_ORION) || + (protocol==ORIGINAL_PROTOCOL && device==DEVICE_ORION2)) { GtkWidget *ptt_ring_b=gtk_radio_button_new_with_label(NULL,"PTT On Ring, Mic and Bias on Tip"); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptt_ring_b), mic_ptt_tip_bias_ring==0); @@ -289,7 +251,7 @@ void general_menu(GtkWidget *parent) { gtk_grid_attach(GTK_GRID(grid),sample_rate_1536,0,7,1,1); g_signal_connect(sample_rate_1536,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)1536000); -#ifdef raspberrypi +#ifdef GPIO gtk_widget_set_sensitive(sample_rate_768,FALSE); gtk_widget_set_sensitive(sample_rate_1536,FALSE); #endif diff --git a/gpio.c b/gpio.c index 9586924..d3ec303 100644 --- a/gpio.c +++ b/gpio.c @@ -1,3 +1,4 @@ +#include #ifdef GPIO #include @@ -9,10 +10,10 @@ #include #include #include -#include +//#include #include #include -#ifdef raspberrypi +#ifdef GPIO #include #endif #ifdef sx1509 @@ -36,13 +37,15 @@ #ifdef PSK #include "psk.h" #endif +#include "new_menu.h" +#include "encoder_menu.h" #define SYSFS_GPIO_DIR "/sys/class/gpio" int ENABLE_VFO_ENCODER=1; int ENABLE_VFO_PULLUP=1; -int VFO_ENCODER_A=17; -int VFO_ENCODER_B=18; +int VFO_ENCODER_A=18; +int VFO_ENCODER_B=17; #if defined odroid && !defined sx1509 int VFO_ENCODER_A_PIN=0; int VFO_ENCODER_B_PIN=1; @@ -51,11 +54,11 @@ int ENABLE_E1_ENCODER=1; int ENABLE_E1_PULLUP=0; int E1_ENCODER_A=20; int E1_ENCODER_B=26; -#ifndef sx1509 +//#ifndef sx1509 int E1_FUNCTION=25; -#else -int E1_FUNCTION=2; //RRK, was 25 now taken by waveshare LCD TS, disable i2c -#endif +//#else +//int E1_FUNCTION=2; //RRK, was 25 now taken by waveshare LCD TS, disable i2c +//#endif int ENABLE_E2_ENCODER=1; int ENABLE_E2_PULLUP=0; int E2_ENCODER_A=16; @@ -65,11 +68,11 @@ int ENABLE_E3_ENCODER=1; int ENABLE_E3_PULLUP=0; int E3_ENCODER_A=4; int E3_ENCODER_B=21; -#if defined sx1509 +//#if defined sx1509 int E3_FUNCTION=7; -#else -int E3_FUNCTION=3; //RRK, was 7 now taken by waveshare LCD TS, disable i2c -#endif +//#else +//int E3_FUNCTION=3; //RRK, was 7 now taken by waveshare LCD TS, disable i2c +//#endif int ENABLE_S1_BUTTON=1; int S1_BUTTON=13; int ENABLE_S2_BUTTON=1; @@ -87,10 +90,14 @@ int MOX_BUTTON=27; int ENABLE_FUNCTION_BUTTON=1; int FUNCTION_BUTTON=22; int ENABLE_E1_BUTTON=1; +int ENABLE_E2_BUTTON=1; +int ENABLE_E3_BUTTON=1; int ENABLE_CW_BUTTONS=1; // make sure to disable UART0 for next 2 gpios +#ifdef LOCALCW int CWL_BUTTON=9; int CWR_BUTTON=10; +#endif #ifdef sx1509 /* Hardware Hookup: @@ -153,10 +160,13 @@ int SX1509_INT_PIN=0; static volatile int vfoEncoderPos; static volatile int e1EncoderPos; static volatile int e1Function; +int e1_encoder_action=ENCODER_AF_GAIN; static volatile int e2EncoderPos; static volatile int e2Function; +int e2_encoder_action=ENCODER_DRIVE; static volatile int e3EncoderPos; static volatile int e3Function; +int e3_encoder_action=ENCODER_ATTENUATION; static volatile int function_state; static volatile int band_state; static volatile int bandstack_state; @@ -167,13 +177,17 @@ static volatile int agc_state; static volatile int mox_state; static volatile int lock_state; -static void* rotary_encoder_thread(void *arg); -static pthread_t rotary_encoder_thread_id; +//static void* rotary_encoder_thread(void *arg); +static gpointer rotary_encoder_thread(gpointer data); +//static pthread_t rotary_encoder_thread_id; +static GThread *rotary_encoder_thread_id; static int previous_function_button=0; static int e1_function=0; static int previous_e1_function=0; static int e2_function=0; static int previous_e2_function=0; +static int e3_function=0; +static int previous_e3_function=0; static int band_button=0; static int previous_band_button=0; static int bandstack_button=0; @@ -188,68 +202,190 @@ static int agc_button=0; static int previous_agc_button=0; static int mox_button=0; static int previous_mox_button=0; -static int lock_button=0; -static int previous_lock_button=0; -static int running=1; +//static GMutex m_running; +static int running=0; + +char *encoder_string[] = { +"AF GAIN", +"AGC GAIN", +"ATTENUATION", +"MIC GAIN", +"DRIVE", +"TUNE DRIVE", +"RIT", +"CW SPEED", +"CW FREQUENCY", +"PANADAPTER HIGH", +"PANADAPTER LOW", +}; -static void e1FunctionAlert(int gpio, int level, uint32_t tick) { - e1Function=(level==0); +static int mox_pressed(void *data) { + if(running) sim_mox_cb(NULL,NULL); + return 0; } -static void e3FunctionAlert(int gpio, int level, uint32_t tick) { +static int s1_pressed(void *data) { + if(running) sim_s1_pressed_cb(NULL,NULL); + return 0; +} + +static int s1_released(void *data) { + if(running) sim_s1_released_cb(NULL,NULL); + return 0; +} + +static int s2_pressed(void *data) { + if(running) sim_s2_pressed_cb(NULL,NULL); + return 0; +} + +static int s2_released(void *data) { + if(running) sim_s2_released_cb(NULL,NULL); + return 0; +} + +static int s3_pressed(void *data) { + if(running) sim_s3_pressed_cb(NULL,NULL); + return 0; +} + +static int s3_released(void *data) { + if(running) sim_s3_released_cb(NULL,NULL); + return 0; +} + +static int s4_pressed(void *data) { + if(running) sim_s4_pressed_cb(NULL,NULL); + return 0; +} + +static int s4_released(void *data) { + if(running) sim_s4_released_cb(NULL,NULL); + return 0; +} + +static int s5_pressed(void *data) { + if(running) sim_s5_pressed_cb(NULL,NULL); + return 0; +} + +static int s5_released(void *data) { + if(running) sim_s5_released_cb(NULL,NULL); + return 0; +} + +static int s6_pressed(void *data) { + if(running) sim_s6_pressed_cb(NULL,NULL); + return 0; +} + +static int s6_released(void *data) { + if(running) sim_s6_released_cb(NULL,NULL); + return 0; +} + +static int function_pressed(void *data) { + if(running) sim_function_cb(NULL,NULL); + return 0; +} + +static int e_function_pressed(void *data) { + int encoder=(int)data; + start_encoder(encoder); + return 0; +} + +static void e1FunctionAlert(int gpio, int level, uint32_t tick) { if(level==0) { - e3Function=e3Function==0?1:0; + if(running) g_idle_add(e_function_pressed,(gpointer)1); } } static void e2FunctionAlert(int gpio, int level, uint32_t tick) { - e2Function=(level==0); + if(level==0) { + if(running) g_idle_add(e_function_pressed,(gpointer)2); + } +} + +static void e3FunctionAlert(int gpio, int level, uint32_t tick) { + if(level==0) { + if(running) g_idle_add(e_function_pressed,(gpointer)3); + } } static void functionAlert(int gpio, int level, uint32_t tick) { - function_state=(level==0); + if(level==0) { + if(running) g_idle_add(function_pressed,NULL); + } } -static void bandAlert(int gpio, int level, uint32_t tick) { - band_state=(level==0); + +static void s1Alert(int gpio, int level, uint32_t tick) { + if(level==0) { + g_idle_add(s1_pressed,NULL); + } else { + g_idle_add(s1_released,NULL); + } } -static void bandstackAlert(int gpio, int level, uint32_t tick) { - bandstack_state=(level==0); +static void s2Alert(int gpio, int level, uint32_t tick) { + if(level==0) { + g_idle_add(s2_pressed,NULL); + } else { + g_idle_add(s2_released,NULL); + } } -static void modeAlert(int gpio, int level, uint32_t tick) { - mode_state=(level==0); +static void s3Alert(int gpio, int level, uint32_t tick) { + if(level==0) { + g_idle_add(s3_pressed,NULL); + } else { + g_idle_add(s3_released,NULL); + } } -static void filterAlert(int gpio, int level, uint32_t tick) { - filter_state=(level==0); +static void s4Alert(int gpio, int level, uint32_t tick) { + if(level==0) { + g_idle_add(s4_pressed,NULL); + } else { + g_idle_add(s4_released,NULL); + } } -static void noiseAlert(int gpio, int level, uint32_t tick) { - noise_state=(level==0); +static void s5Alert(int gpio, int level, uint32_t tick) { + if(level==0) { + g_idle_add(s5_pressed,NULL); + } else { + g_idle_add(s5_released,NULL); + } } -static void agcAlert(int gpio, int level, uint32_t tick) { - agc_state=(level==0); +static void s6Alert(int gpio, int level, uint32_t tick) { + if(level==0) { + g_idle_add(s6_pressed,NULL); + } else { + g_idle_add(s6_released,NULL); + } } static void moxAlert(int gpio, int level, uint32_t tick) { - mox_state=(level==0); + if(level==0) { + g_idle_add(mox_pressed,(gpointer)NULL); + } else { + } } static void lockAlert(int gpio, int level, uint32_t tick) { lock_state=(level==0); } -static void cwAlert(int gpio, int level, uint32_t tick) { -fprintf(stderr,"cwAlert: gpio=%d level=%d internal=%d\n",gpio,level,cw_keyer_internal); #ifdef LOCALCW +static void cwAlert(int gpio, int level, uint32_t tick) { if (cw_keyer_internal == 0 && (mode==modeCWL || mode==modeCWU)) keyer_event(gpio, cw_active_level == 0 ? level : (level==0)); -#endif } +#endif static void vfoEncoderPulse(int gpio, int level, unsigned int tick) { static int levA=0, levB=0, lastGpio = -1; @@ -483,12 +619,29 @@ void gpio_restore_state() { value=getProperty("E1_FUNCTION"); if(value) E1_FUNCTION=atoi(value); #endif + + value=getProperty("ENABLE_E2_BUTTON"); + if(value) ENABLE_E2_BUTTON=atoi(value); +#ifndef sx1509 + value=getProperty("E2_FUNCTION"); + if(value) E2_FUNCTION=atoi(value); +#endif + + value=getProperty("ENABLE_E3_BUTTON"); + if(value) ENABLE_E3_BUTTON=atoi(value); +#ifndef sx1509 + value=getProperty("E3_FUNCTION"); + if(value) E3_FUNCTION=atoi(value); +#endif + +#ifdef LOCALCW value=getProperty("ENABLE_CW_BUTTONS"); if(value) ENABLE_CW_BUTTONS=atoi(value); value=getProperty("CWL_BUTTON"); if(value) CWL_BUTTON=atoi(value); value=getProperty("CWR_BUTTON"); if(value) CWR_BUTTON=atoi(value); +#endif } void gpio_save_state() { @@ -564,25 +717,54 @@ void gpio_save_state() { setProperty("ENABLE_MOX_BUTTON",value); sprintf(value,"%d",MOX_BUTTON); setProperty("MOX_BUTTON",value); + sprintf(value,"%d",ENABLE_E1_BUTTON); setProperty("ENABLE_E1_BUTTON",value); #ifndef sx1509 sprintf(value,"%d",E1_FUNCTION); setProperty("E1_FUNCTION",value); #endif + + sprintf(value,"%d",ENABLE_E2_BUTTON); + setProperty("ENABLE_E2_BUTTON",value); +#ifndef sx1509 + sprintf(value,"%d",E2_FUNCTION); + setProperty("E2_FUNCTION",value); +#endif + + sprintf(value,"%d",ENABLE_E3_BUTTON); + setProperty("ENABLE_E3_BUTTON",value); +#ifndef sx1509 + sprintf(value,"%d",E3_FUNCTION); + setProperty("E3_FUNCTION",value); +#endif + +#ifdef LOCALCW sprintf(value,"%d",ENABLE_CW_BUTTONS); setProperty("ENABLE_CW_BUTTONS",value); sprintf(value,"%d",CWL_BUTTON); setProperty("CWL_BUTTON",value); sprintf(value,"%d",CWR_BUTTON); setProperty("CWR_BUTTON",value); +#endif saveProperties("gpio.props"); } +#define BUTTON_STEADY_TIME_US 5000 +static void setup_button(int button, gpioAlertFunc_t pAlert) { + gpioSetMode(button, PI_INPUT); + gpioSetPullUpDown(button,PI_PUD_UP); + // give time to settle to avoid false triggers + usleep(10000); + gpioSetAlertFunc(button, pAlert); + gpioGlitchFilter(button, BUTTON_STEADY_TIME_US); +} int gpio_init() { -fprintf(stderr,"encoder_init\n"); + fprintf(stderr,"gpio_init\n"); + + //g_mutex_init(&m_running); #if defined odroid && !defined sx1509 VFO_ENCODER_A=88; @@ -590,22 +772,11 @@ fprintf(stderr,"encoder_init\n"); #endif gpio_restore_state(); -#ifdef raspberrypi - -#define BUTTON_STEADY_TIME_US 5000 - - void setup_button(int button, gpioAlertFunc_t pAlert) { - gpioSetMode(button, PI_INPUT); - gpioSetPullUpDown(button,PI_PUD_UP); - // give time to settle to avoid false triggers - usleep(10000); - gpioSetAlertFunc(button, pAlert); - gpioGlitchFilter(button, BUTTON_STEADY_TIME_US); - } +#ifdef GPIO - fprintf(stderr,"encoder_init: VFO_ENCODER_A=%d VFO_ENCODER_B=%d\n",VFO_ENCODER_A,VFO_ENCODER_B); + fprintf(stderr,"gpio_init: VFO_ENCODER_A=%d VFO_ENCODER_B=%d\n",VFO_ENCODER_A,VFO_ENCODER_B); - fprintf(stderr,"gpioInitialize\n"); + fprintf(stderr,"gpioInitialise\n"); if(gpioInitialise()<0) { fprintf(stderr,"Cannot initialize GPIO\n"); return -1; @@ -639,6 +810,7 @@ fprintf(stderr,"encoder_init\n"); } +fprintf(stderr,"setup_button: E1 %d\n",E1_FUNCTION); setup_button(E1_FUNCTION, e1FunctionAlert); e1Function=0; @@ -657,13 +829,14 @@ fprintf(stderr,"encoder_init\n"); e1EncoderPos=0; } - setup_button(E2_FUNCTION, e2FunctionAlert); - e2Function=0; +fprintf(stderr,"setup_button: E2 %d\n",E2_FUNCTION); + setup_button(E2_FUNCTION, e2FunctionAlert); + e2Function=0; if(ENABLE_E2_ENCODER) { gpioSetMode(E2_ENCODER_A, PI_INPUT); gpioSetMode(E2_ENCODER_B, PI_INPUT); - if(ENABLE_E1_PULLUP) { + if(ENABLE_E2_PULLUP) { gpioSetPullUpDown(E2_ENCODER_A, PI_PUD_UP); gpioSetPullUpDown(E2_ENCODER_B, PI_PUD_UP); } else { @@ -675,13 +848,14 @@ fprintf(stderr,"encoder_init\n"); e2EncoderPos=0; } +fprintf(stderr,"setup_button: E3 %d\n",E3_FUNCTION); setup_button(E3_FUNCTION, e3FunctionAlert); e3Function=0; if(ENABLE_E3_ENCODER) { gpioSetMode(E3_ENCODER_A, PI_INPUT); gpioSetMode(E3_ENCODER_B, PI_INPUT); - if(ENABLE_E1_PULLUP) { + if(ENABLE_E3_PULLUP) { gpioSetPullUpDown(E3_ENCODER_A, PI_PUD_UP); gpioSetPullUpDown(E3_ENCODER_B, PI_PUD_UP); } else { @@ -695,39 +869,42 @@ fprintf(stderr,"encoder_init\n"); if(ENABLE_S1_BUTTON) { - setup_button(S1_BUTTON, bandAlert); + setup_button(S1_BUTTON, s1Alert); } if(ENABLE_S2_BUTTON) { - setup_button(S2_BUTTON, bandstackAlert); + setup_button(S2_BUTTON, s2Alert); } if(ENABLE_S3_BUTTON) { - setup_button(S3_BUTTON, modeAlert); + setup_button(S3_BUTTON, s3Alert); } if(ENABLE_S4_BUTTON) { - setup_button(S4_BUTTON, filterAlert); + setup_button(S4_BUTTON, s4Alert); } if(ENABLE_S5_BUTTON) { - setup_button(S5_BUTTON, noiseAlert); + setup_button(S5_BUTTON, s5Alert); } if(ENABLE_S6_BUTTON) { - setup_button(S6_BUTTON, agcAlert); + setup_button(S6_BUTTON, s6Alert); } if(ENABLE_MOX_BUTTON) { setup_button(MOX_BUTTON, moxAlert); } +/* #ifndef sx1509 if(ENABLE_E1_BUTTON) { setup_button(E1_FUNCTION, lockAlert); } #endif +*/ +#ifdef LOCALCW fprintf(stderr,"GPIO: ENABLE_CW_BUTTONS=%d CWL_BUTTON=%d CWR_BUTTON=%d\n",ENABLE_CW_BUTTONS, CWL_BUTTON, CWR_BUTTON); if(ENABLE_CW_BUTTONS) { setup_button(CWL_BUTTON, cwAlert); @@ -741,6 +918,7 @@ fprintf(stderr,"GPIO: ENABLE_CW_BUTTONS=%d CWL_BUTTON=%d CWR_BUTTON=%d\n",ENABL gpioGlitchFilter(CWR_BUTTON, 5000); */ } +#endif #endif @@ -755,7 +933,7 @@ fprintf(stderr,"GPIO: ENABLE_CW_BUTTONS=%d CWL_BUTTON=%d CWR_BUTTON=%d\n",ENABL E3_ENCODER_A=14; E3_ENCODER_B=15; - fprintf(stderr,"sx1509 encoder_init: VFO_ENCODER_A=%d VFO_ENCODER_B=%d\n",VFO_ENCODER_A,VFO_ENCODER_B); + fprintf(stderr,"sx1509 gpio_init: VFO_ENCODER_A=%d VFO_ENCODER_B=%d\n",VFO_ENCODER_A,VFO_ENCODER_B); pSX1509 = newSX1509(); @@ -819,7 +997,7 @@ fprintf(stderr,"GPIO: ENABLE_CW_BUTTONS=%d CWL_BUTTON=%d CWR_BUTTON=%d\n",ENABL //VFO_ENCODER_A_PIN=ODROID_VFO_ENCODER_A_PIN; //VFO_ENCODER_B_PIN=ODROID_VFO_ENCODER_B_PIN; - fprintf(stderr,"encoder_init: VFO_ENCODER_A=%d VFO_ENCODER_B=%d\n",VFO_ENCODER_A,VFO_ENCODER_B); + fprintf(stderr,"gpio_init: VFO_ENCODER_A=%d VFO_ENCODER_B=%d\n",VFO_ENCODER_A,VFO_ENCODER_B); fprintf(stderr,"wiringPiSetup\n"); if (wiringPiSetup () < 0) { @@ -854,22 +1032,33 @@ fprintf(stderr,"GPIO: ENABLE_CW_BUTTONS=%d CWL_BUTTON=%d CWR_BUTTON=%d\n",ENABL } #endif - int rc=pthread_create(&rotary_encoder_thread_id, NULL, rotary_encoder_thread, NULL); - if(rc<0) { - fprintf(stderr,"pthread_create for rotary_encoder_thread failed %d\n",rc); + rotary_encoder_thread_id = g_thread_new( "rotary encoder", rotary_encoder_thread, NULL); + if( ! rotary_encoder_thread_id ) + { + fprintf(stderr,"g_thread_new failed on rotary_encoder_thread\n"); + exit( -1 ); } + fprintf(stderr, "rotary_encoder_thread: id=%p\n",rotary_encoder_thread_id); return 0; } void gpio_close() { +fprintf(stderr,"gpio_close: lock\n"); + //g_mutex_lock(&m_running); running=0; +#ifdef GPIO +fprintf(stderr,"gpioTerminate\n"); + gpioTerminate(); +#endif +fprintf(stderr,"gpio_close: unlock\n"); + //g_mutex_unlock(&m_running); #if defined odroid && !defined sx1509 FILE *fp; - fp = popen("echo 97 > /sys/class/gpio/unexport\n", "r"); + fp = popen("echo 87 > /sys/class/gpio/unexport\n", "r"); pclose(fp); - fp = popen("echo 108 > /sys/class/gpio/unexport\n", "r"); + fp = popen("echo 88 > /sys/class/gpio/unexport\n", "r"); pclose(fp); #endif } @@ -897,10 +1086,6 @@ int e1_encoder_get_pos() { return pos; } -int e1_function_get_state() { - return e1Function; -} - int e2_encoder_get_pos() { int pos=e2EncoderPos; e2EncoderPos=0; @@ -912,15 +1097,10 @@ int e3_encoder_get_pos() { e3EncoderPos=0; return pos; } - -int agc_function_get_state() { +int e3_function_get_state() { return e3Function; } -int e2_function_get_state() { - return e2Function; -} - int function_get_state() { return function_state; } @@ -960,282 +1140,190 @@ int lock_get_state() { static int vfo_encoder_changed(void *data) { if(!locked) { - int pos=*(int*)data; - - // VFO - BANDSTACK_ENTRY* entry=bandstack_entry_get_current(); - setFrequency(entry->frequencyA+ddsOffset+(pos*step)); - vfo_update(NULL); + int pos=(int)data; + vfo_step(pos); } - free(data); + //free(data); return 0; } -static int e1_encoder_changed(void *data) { - int pos=*(int*)data; - if(pos!=0) { - if(function || isTransmitting()) { - // mic gain - double gain=mic_gain; +static encoder_changed(int action,int pos) { + double value; + switch(action) { + case ENCODER_AF_GAIN: + value=active_receiver->volume; + value+=(double)pos/100.0; + if(value<0.0) { + value=0.0; + } else if(value>1.0) { + value=1.0; + } + set_af_gain(value); + break; + case ENCODER_AGC_GAIN: + value=active_receiver->agc_gain; + value+=(double)pos; + if(value<-20.0) { + value=-20.0; + } else if(value>120.0) { + value=120.0; + } + set_agc_gain(value); + break; + case ENCODER_ATTENUATION: + value=active_receiver->attenuation; + value+=pos; + if(value<0) { + value=0; + } else if (value>31) { + value=31; + } + set_attenuation_value(value); + break; + case ENCODER_MIC_GAIN: + value=mic_gain; //gain+=(double)pos/100.0; - gain+=(double)pos; - if(gain<-10.0) { - gain=-10.0; - } else if(gain>50.0) { - gain=50.0; + value+=(double)pos; + if(value<-10.0) { + value=-10.0; + } else if(value>50.0) { + value=50.0; } - set_mic_gain(gain); - } else { - // af gain - double gain=volume; - gain+=(double)pos/100.0; - if(gain<0.0) { - gain=0.0; - } else if(gain>1.0) { - gain=1.0; + set_mic_gain(value); + break; + case ENCODER_DRIVE: + value=getDrive(); + value+=(double)pos; + if(value<0.0) { + value=0.0; + } else if(value>100.0) { + value=100.0; } - set_af_gain(gain); - } - } - free(data); - return 0; -} - -static int e2_encoder_changed(void *data) { - int pos=*(int*)data; - if(pos!=0) { - if(function || tune) { - // tune drive - double d=getTuneDrive(); - d+=(double)pos; - if(d<0.0) { - d=0.0; - } else if(d>100.0) { - d=100.0; + set_drive(value); + break; + case ENCODER_TUNE_DRIVE: + value=getTuneDrive(); + value+=(double)pos; + if(value<0.0) { + value=0.0; + } else if(value>100.0) { + value=100.0; } - set_tune(d); - } else { - // drive - double d=getDrive(); - d+=(double)pos; - if(d<0.0) { - d=0.0; - } else if(d>100.0) { - d=100.0; + set_tune(value); + break; + case ENCODER_RIT: + value=(double)vfo[active_receiver->id].rit; + value+=(double)(pos*rit_increment); + if(value<-1000.0) { + value=-1000.0; + } else if(value>1000.0) { + value=1000.0; } - set_drive(d); - } - } - free(data); - return 0; -} - -static int e3_encoder_changed(void *data) { - int pos=*(int*)data; - if(pos!=0) { - if(function) { - int att=attenuation; - att+=pos; - if(att<0) { - att=0; - } else if (att>31) { - att=31; + vfo[active_receiver->id].rit=(int)value; + vfo_update(NULL); + break; + case ENCODER_CW_SPEED: + value=(double)cw_keyer_speed; + value+=(double)pos; + if(value<1.0) { + value=1.0; + } else if(value>60.0) { + value=60.0; } - set_attenuation_value((double)att); - } else { - double gain=agc_gain; - gain+=(double)pos; - if(gain<-20.0) { - gain=-20.0; - } else if(gain>120.0) { - gain=120.0; + cw_keyer_speed=(int)value; + vfo_update(NULL); + break; + case ENCODER_CW_FREQUENCY: + value=(double)cw_keyer_sidetone_frequency; + value+=(double)pos; + if(value<0.0) { + value=0.0; + } else if(value>1000.0) { + value=1000.0; } - set_agc_gain(gain); - } + cw_keyer_sidetone_frequency=(int)value; + vfo_update(NULL); + break; + case ENCODER_PANADAPTER_HIGH: + value=(double)active_receiver->panadapter_high; + value+=(double)pos; + active_receiver->panadapter_high=(int)value; + break; + case ENCODER_PANADAPTER_LOW: + value=(double)active_receiver->panadapter_low; + value+=(double)pos; + active_receiver->panadapter_low=(int)value; + break; } - return 0; -} - -static int band_pressed(void *data) { - sim_s1_pressed_cb(NULL,NULL); - return 0; -} - -static int band_released(void *data) { - sim_s1_released_cb(NULL,NULL); - return 0; -} - -static int bandstack_pressed(void *data) { - sim_s2_pressed_cb(NULL,NULL); - return 0; } -static int bandstack_released(void *data) { - sim_s2_released_cb(NULL,NULL); - return 0; -} - -static int function_pressed(void *data) { - sim_function_cb(NULL,NULL); - return 0; -} - -static int mox_pressed(void *data) { - sim_mox_cb(NULL,NULL); - return 0; -} - -static int lock_pressed(void *data) { - lock_cb((GtkWidget *)NULL, (gpointer)NULL); +static int e1_encoder_changed(void *data) { + int pos=(int)data; + if(active_menu==E1_MENU) { + encoder_select(pos); + } else { + encoder_changed(e1_encoder_action,pos); + } + //free(data); return 0; } -static int mode_pressed(void *data) { - sim_s3_cb(NULL,NULL); +static int e2_encoder_changed(void *data) { + int pos=(int)data; + if(active_menu==E2_MENU) { + encoder_select(pos); + } else { + encoder_changed(e2_encoder_action,pos); + } + //free(data); return 0; } -static int filter_pressed(void *data) { - sim_s4_cb(NULL,NULL); +static int e3_encoder_changed(void *data) { + int pos=(int)data; + if(active_menu==E3_MENU) { + encoder_select(pos); + } else { + encoder_changed(e3_encoder_action,pos); + } + //free(data); return 0; } -static int noise_pressed(void *data) { - sim_s5_cb(NULL,NULL); - return 0; -} +static gpointer rotary_encoder_thread(gpointer data) { + int pos; -static int agc_pressed(void *data) { - sim_s6_cb(NULL,NULL); - return 0; -} + // ignore startup glitches + sleep(2); -static void* rotary_encoder_thread(void *arg) { - int pos; + //g_mutex_lock(&m_running); running=1; - while(running) { - - int function_button=function_get_state(); - if(function_button!=previous_function_button) { - previous_function_button=function_button; - if(function_button) { - g_idle_add(function_pressed,(gpointer)NULL); - } - } + //g_mutex_unlock(&m_running); + while(1) { pos=vfo_encoder_get_pos(); if(pos!=0) { - int *p=malloc(sizeof(int)); - *p=pos; - g_idle_add(vfo_encoder_changed,(gpointer)p); + g_idle_add(vfo_encoder_changed,(gpointer)pos); } -/* - e1_function=e1_function_get_state(); - if(e1_function!=previous_e1_function) { - previous_e1_function=e1_function; - } -*/ pos=e1_encoder_get_pos(); if(pos!=0) { - int *p=malloc(sizeof(int)); - *p=pos; - g_idle_add(e1_encoder_changed,(gpointer)p); + g_idle_add(e1_encoder_changed,(gpointer)pos); } -/* - e2_function=e2_function_get_state(); - if(e2_function!=previous_e2_function) { - previous_e2_function=e2_function; - } -*/ pos=e2_encoder_get_pos(); if(pos!=0) { - int *p=malloc(sizeof(int)); - *p=pos; - g_idle_add(e2_encoder_changed,(gpointer)p); + g_idle_add(e2_encoder_changed,(gpointer)pos); } pos=e3_encoder_get_pos(); if(pos!=0) { - int *p=malloc(sizeof(int)); - *p=pos; - g_idle_add(e3_encoder_changed,(gpointer)p); - } - - - int band_button=band_get_state(); - if(band_button!=previous_band_button) { - previous_band_button=band_button; - if(band_button) { - g_idle_add(band_pressed,(gpointer)NULL); - } else { - g_idle_add(band_released,(gpointer)NULL); - } - } - - int bandstack_button=bandstack_get_state(); - if(bandstack_button!=previous_bandstack_button) { - previous_bandstack_button=bandstack_button; - if(bandstack_button) { - g_idle_add(bandstack_pressed,(gpointer)NULL); - } else { - g_idle_add(bandstack_released,(gpointer)NULL); - } - } - - int mode_button=mode_get_state(); - if(mode_button!=previous_mode_button) { - previous_mode_button=mode_button; - if(mode_button) { - g_idle_add(mode_pressed,(gpointer)NULL); - } - } - - int filter_button=filter_get_state(); - if(filter_button!=previous_filter_button) { - previous_filter_button=filter_button; - if(filter_button) { - g_idle_add(filter_pressed,(gpointer)NULL); - } - } - - int noise_button=noise_get_state(); - if(noise_button!=previous_noise_button) { - previous_noise_button=noise_button; - if(noise_button) { - g_idle_add(noise_pressed,(gpointer)NULL); - } - } - - int agc_button=agc_get_state(); - if(agc_button!=previous_agc_button) { - previous_agc_button=agc_button; - if(agc_button) { - g_idle_add(agc_pressed,(gpointer)NULL); - } - } - - int mox_button=mox_get_state(); - if(mox_button!=previous_mox_button) { - previous_mox_button=mox_button; - if(mox_button) { - g_idle_add(mox_pressed,(gpointer)NULL); - } - } - - int lock_button=lock_get_state(); - if(lock_button!=previous_lock_button) { - previous_lock_button=lock_button; - if(lock_button) { - g_idle_add(lock_pressed,(gpointer)NULL); - } + g_idle_add(e3_encoder_changed,(gpointer)pos); } #ifdef sx1509 // buttons only generate interrupt when - // pushed on, so clear them now + // pushed onODER_AF_GAIN = 0, function_state = 0; band_state = 0; bandstack_state = 0; @@ -1246,16 +1334,23 @@ static void* rotary_encoder_thread(void *arg) { mox_state = 0; lock_state = 0; #endif - -#ifdef raspberrypi - if(running) gpioDelay(100000); // 10 per second +//fprintf(stderr,"gpio_thread: lock\n"); + //g_mutex_lock(&m_running); + if(running==0) { +fprintf(stderr,"gpio_thread: unlock (running==0)\n"); + //g_mutex_unlock(&m_running); + g_thread_exit(NULL); + } +#ifdef GPIO + usleep(100000); + //gpioDelay(100000); // 10 per second #endif #ifdef odroid - if(running) usleep(100000); + usleep(100000); #endif +//fprintf(stderr,"gpio_thread: unlock (running==1)\n"); + //g_mutex_unlock(&m_running); } -#ifdef raspberrypi - gpioTerminate(); -#endif + return NULL; } #endif diff --git a/gpio.h b/gpio.h index cb8fcf3..fb60859 100644 --- a/gpio.h +++ b/gpio.h @@ -20,6 +20,29 @@ #ifndef _GPIO_H #define _GPIO_H +enum { + ENCODER_AF_GAIN=0, + ENCODER_AGC_GAIN, + ENCODER_ATTENUATION, + ENCODER_MIC_GAIN, + ENCODER_DRIVE, + ENCODER_TUNE_DRIVE, + ENCODER_RIT, + ENCODER_CW_SPEED, + ENCODER_CW_FREQUENCY, + ENCODER_PANADAPTER_HIGH, + ENCODER_PANADAPTER_LOW +}; + + +#define ENCODER_LAST ENCODER_PANADAPTER_LOW + +extern char *encoder_string[ENCODER_LAST+1]; + +extern int e1_encoder_action; +extern int e2_encoder_action; +extern int e3_encoder_action; + extern int ENABLE_VFO_ENCODER; extern int ENABLE_VFO_PULLUP; extern int VFO_ENCODER_A; diff --git a/gpio_mraa.c b/gpio_mraa.c index 45c8f9c..8b054ae 100644 --- a/gpio_mraa.c +++ b/gpio_mraa.c @@ -771,9 +771,9 @@ static int vfo_encoder_changed(void *data) { if(!locked) { int pos=*(int*)data; BANDSTACK_ENTRY* entry=bandstack_entry_get_current(); - //entry->frequencyA=entry->frequencyA+(pos*step); - //setFrequency(entry->frequencyA); - setFrequency(entry->frequencyA+ddsOffset+(pos*step)); + //entry->frequency=entry->frequency+(pos*step); + //setFrequency(entry->frequency); + setFrequency(entry->frequency+ddsOffset+(pos*step)); vfo_update(NULL); } free(data); diff --git a/i2c.c b/i2c.c new file mode 100644 index 0000000..d33dbec --- /dev/null +++ b/i2c.c @@ -0,0 +1,258 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "i2c.h" +#include "band.h" +#include "band_menu.h" +#include "bandstack.h" +#include "radio.h" +#include "toolbar.h" +#include "vfo.h" + +#define I2C_DEVICE "/dev/i2c-1" +#define ADDRESS_1 0X20 +#define ADDRESS_2 0X23 + +//static pthread_t i2c_thread_id; +static GThread *i2c_thread_id; + +static int write_byte_data(unsigned char addr,unsigned char reg, unsigned char data) { + int fd; + int rc; + + if((fd=open(I2C_DEVICE, O_RDWR))<0) { + fprintf(stderr,"cannot open %s: %s\n",I2C_DEVICE,strerror(errno)); + return(-1); + } + + if(ioctl(fd,I2C_SLAVE,addr)<0) { + fprintf(stderr,"cannot aquire access to I2C device at 0x%02X\n",addr); + return(-1); + } + + rc=i2c_smbus_write_byte_data(fd,reg,data); + if(rc<0) { + fprintf(stderr,"i2c_smbus_write_byte_data failed: device=%02X 0x%02X to 0x%02X: %s\n",addr,data,reg,strerror(errno)); + return(-1); + } + + close(fd); + + return 0; +} + +static unsigned char read_byte_data(unsigned char addr,unsigned char reg) { + int fd; + int rc; + + if((fd=open(I2C_DEVICE, O_RDWR))<0) { + fprintf(stderr,"c$cannot open %s: %s\n",I2C_DEVICE,strerror(errno)); + exit(1); + } + + if(ioctl(fd,I2C_SLAVE,addr)<0) { + fprintf(stderr,"cannot aquire access to I2C device at 0x%x\n",addr); + exit(1); + } + + rc=i2c_smbus_read_byte_data(fd,reg); + if(rc<0) { + fprintf(stderr,"i2c_smbus_read_byte_data failed: 0x%2X: %s\n",reg,strerror(errno)); + exit(1); + } + + close(fd); + + return rc; +} + +static void frequencyStep(int pos) { + BANDSTACK_ENTRY* entry=bandstack_entry_get_current(); + setFrequency(entry->frequency+ddsOffset+(pos*step)); + vfo_update(NULL); +} + +static void *i2c_thread(void *arg) { + int rc_1_a; + int rc_1_b; + int prev_rc_1_a=0; + int prev_rc_1_b=0; + int rc_2_a; + int rc_2_b; + int prev_rc_2_a=0; + int prev_rc_2_b=0; + + while(1) { + rc_1_a=read_byte_data(ADDRESS_1,0x12); + if(rc_1_a!=0 && rc_1_a!=prev_rc_1_a) { + fprintf(stderr,"Dev 1: GPIOA: 0x%02X\n",rc_1_a); + switch(rc_1_a) { + case 0x01: + g_idle_add(band_update,(void *)band160); + break; + case 0x02: + g_idle_add(band_update,(void *)band80); + break; + case 0x04: + g_idle_add(band_update,(void *)band60); + break; + case 0x08: + g_idle_add(band_update,(void *)band40); + break; + case 0x10: + g_idle_add(band_update,(void *)band30); + break; + case 0x20: + g_idle_add(band_update,(void *)band20); + break; + case 0x40: + g_idle_add(band_update,(void *)band17); + break; + case 0x80: + g_idle_add(band_update,(void *)band15); + break; + } + } + prev_rc_1_a=rc_1_a; + + rc_1_b=read_byte_data(ADDRESS_1,0x13); + if(rc_1_b!=0 && rc_1_b!=prev_rc_1_b) { + fprintf(stderr,"Dev 1: GPIOB: 0x%02X\n",rc_1_b); + switch(rc_1_b) { + case 0x01: + g_idle_add(band_update,(void *)band12); + break; + case 0x02: + g_idle_add(band_update,(void *)band10); + break; + case 0x04: + g_idle_add(band_update,(void *)band6); + break; + case 0x08: + g_idle_add(band_update,(void *)bandGen); + break; + case 0x10: + frequencyStep(+1); + break; + case 0x20: + break; + case 0x40: + break; + case 0x80: + frequencyStep(-1); + break; + } + } + prev_rc_1_b=rc_1_b; + + rc_2_a=read_byte_data(ADDRESS_2,0x12); + if(rc_2_a!=0 && rc_2_a!=prev_rc_2_a) { + fprintf(stderr,"Dev 2: GPIOA: 0x%02X\n",rc_2_a); + switch(rc_2_a) { + case 0x01: + break; + case 0x02: + mox_cb(NULL,NULL); + break; + case 0x04: + tune_cb(NULL,NULL); + break; + case 0x08: + break; + case 0x10: + break; + case 0x20: + break; + case 0x40: + break; + case 0x80: + break; + } + } + prev_rc_2_a=rc_2_a; + + rc_2_b=read_byte_data(ADDRESS_2,0x13); + if(rc_2_b!=0 && rc_2_b!=prev_rc_2_b) { + fprintf(stderr,"Dev 2: GPIOB: 0x%02X\n",rc_2_b); + switch(rc_2_b) { + case 0x01: + break; + case 0x02: + break; + case 0x04: + break; + case 0x08: + break; + case 0x10: + break; + case 0x20: + break; + case 0x40: + break; + case 0x80: + break; + } + } + prev_rc_2_b=rc_2_b; + + usleep(200); + } + +} + +void i2c_init() { + +fprintf(stderr,"i2c_init\n"); + // setup i2c + if(write_byte_data(ADDRESS_1,0x0A,0x22)<0) return; + + // set GPIOA/B for input + if(write_byte_data(ADDRESS_1,0x00,0xFF)<0) return; + if(write_byte_data(ADDRESS_1,0x01,0xFF)<0) return; + + // set GPIOA for pullups + if(write_byte_data(ADDRESS_1,0x0C,0xFF)<0) return; + if(write_byte_data(ADDRESS_1,0x0D,0xFF)<0) return; + + // reverse polarity + if(write_byte_data(ADDRESS_1,0x02,0xFF)<0) return; + if(write_byte_data(ADDRESS_1,0x03,0xFF)<0) return; + + // setup i2c + if(write_byte_data(ADDRESS_2,0x0A,0x22)<0) return; + + // set GPIOA/B for input + if(write_byte_data(ADDRESS_2,0x00,0xFF)<0) return; + if(write_byte_data(ADDRESS_2,0x01,0xFF)<0) return; + + // set GPIOA for pullups + if(write_byte_data(ADDRESS_2,0x0C,0xFF)<0) return; + if(write_byte_data(ADDRESS_2,0x0D,0xFF)<0) return; + + // reverse polarity + if(write_byte_data(ADDRESS_2,0x02,0xFF)<0) return; + if(write_byte_data(ADDRESS_2,0x03,0xFF)<0) return; + +/* + int rc; + rc=pthread_create(&i2c_thread_id,NULL,i2c_thread,NULL); + if(rc != 0) { + fprintf(stderr,"i2c_init: pthread_create failed on i2c_thread: rc=%d\n", rc); + } +*/ + i2c_thread_id = g_thread_new( "i2c", i2c_thread, NULL); + if( ! i2c_thread_id ) + { + fprintf(stderr,"g_thread_new failed on i2c_thread\n"); + } + + +} diff --git a/i2c.h b/i2c.h new file mode 100644 index 0000000..14ec886 --- /dev/null +++ b/i2c.h @@ -0,0 +1,2 @@ + +void i2c_init(); diff --git a/libusbio.c b/libusbio.c new file mode 100644 index 0000000..0f52c6b --- /dev/null +++ b/libusbio.c @@ -0,0 +1,99 @@ +/* + * File: libusbio.c + * Author: jm57878 + * + * Created on 18 February 2009, 21:16 + */ + + +#include +#include +#include + +#include "libusbio.h" + +/* + * interface to libusb1.0 + */ + +#define OZY_PID (0x0007) +#define OZY_VID (0xfffe) + +#define VRQ_SDR1K_CTL 0x0d +#define SDR1KCTRL_READ_VERSION 0x7 +#define VRT_VENDOR_IN 0xC0 + +#define OZY_IO_TIMEOUT 500 + +static int init=0; +static libusb_device_handle* ozy_handle; +static libusb_context* context; + +int libusb_open_ozy(void) { + int rc; + +fprintf(stderr,"libusb_open_ozy\n"); + + if(init==0) { + rc=libusb_init(NULL); + if(rc<0) { + fprintf(stderr,"libusb_init failed: %d\n",rc); + return rc; + } + init=1; + } + + ozy_handle=libusb_open_device_with_vid_pid(NULL, OZY_VID, OZY_PID); + if(ozy_handle==NULL) { + fprintf(stderr,"libusbio: cannot find ozy device\n"); + return -1; + } + + rc=libusb_claim_interface(ozy_handle,0); + if(rc<0) { + fprintf(stderr,"libusb_claim_interface failed: %d\n",rc); + return rc; + } + +fprintf(stderr,"libusb_open_ozy: SUCCESS\n"); + return 0; + +} + +void libusb_close_ozy() { + libusb_close(ozy_handle); +} + +int libusb_get_ozy_firmware_string(char* buffer,int buffersize) { + int rc; + rc=libusb_control_transfer(ozy_handle, VRT_VENDOR_IN, VRQ_SDR1K_CTL, SDR1KCTRL_READ_VERSION, 0, buffer, buffersize, OZY_IO_TIMEOUT); + if(rc<0) { + fprintf(stderr,"libusb_get_ozy_firmware failed: %d\n",rc); + return rc; + } + buffer[rc]=0x00; + return 0; +} + +int libusb_write_ozy(int ep,void* buffer,int buffersize) +{ + int rc; + int bytes; + rc = libusb_bulk_transfer(ozy_handle, (unsigned char)ep, (unsigned char *)buffer, buffersize,&bytes, OZY_IO_TIMEOUT); + if(rc==0) { + rc=bytes; + } + return rc; +} + + +int libusb_read_ozy(int ep,void* buffer,int buffersize) +{ + int rc; + int bytes; + rc = libusb_bulk_transfer(ozy_handle, (unsigned char)ep, (unsigned char *)buffer, buffersize,&bytes, OZY_IO_TIMEOUT); + if(rc==0) { + rc=bytes; + } + return rc; +} diff --git a/libusbio.h b/libusbio.h new file mode 100644 index 0000000..eb3660b --- /dev/null +++ b/libusbio.h @@ -0,0 +1,19 @@ +/** +* @file libusbio.h +* @brief Header file for the USB I/O functions, interface to libusb1.0 +* @author +* @version 0.1 +* @date 2009-05-18 +*/ + +#ifndef _LIBUSBIO_H +#define _LIBUSBIO_H + +int libusb_open_ozy(void); +void libusb_close_ozy(); +int libusb_get_ozy_firmware_string(char* buffer,int buffersize); +int libusb_write_ozy(int ep,void* buffer,int buffersize); +int libusb_read_ozy(int ep,void* buffer,int buffersize); + +#endif /* _LIBUSBIO_H */ + diff --git a/main.c b/main.c index c0fd576..d340d05 100644 --- a/main.c +++ b/main.c @@ -29,61 +29,22 @@ #include #include "audio.h" +#include "band.h" +#include "bandstack.h" #include "main.h" #include "channel.h" #include "discovered.h" #include "configure.h" #include "gpio.h" -#include "old_discovery.h" -#include "new_discovery.h" -#ifdef LIMESDR -#include "lime_discovery.h" -#endif -#include "old_protocol.h" -#include "new_protocol.h" -#ifdef LIMESDR -#include "lime_protocol.h" -#endif #include "wdsp.h" -#include "vfo.h" -//#include "menu.h" #include "new_menu.h" -#include "rit.h" -#include "meter.h" -#include "panadapter.h" -#include "splash.h" -#include "waterfall.h" -#include "toolbar.h" -#include "sliders.h" #include "radio.h" -#include "rigctl.h" -#include "wdsp_init.h" #include "version.h" -#include "mode.h" -#ifdef PSK -#include "psk.h" -#include "psk_waterfall.h" -#endif - -#define DISPLAY_INCREMENT (display_height/32) -#define VFO_HEIGHT (DISPLAY_INCREMENT*4) -//#define VFO_HEIGHT (DISPLAY_INCREMENT*8) -#define VFO_WIDTH ((display_width/32)*21) -#define MENU_HEIGHT VFO_HEIGHT -//#define MENU_HEIGHT (DISPLAY_INCREMENT*4) -#define MENU_WIDTH ((display_width/32)*3) -//#define RIT_WIDTH ((MENU_WIDTH/3)*2) -#define METER_HEIGHT VFO_HEIGHT -//#define METER_HEIGHT (DISPLAY_INCREMENT*4) -#define METER_WIDTH ((display_width/32)*8) -#define PANADAPTER_HEIGHT (DISPLAY_INCREMENT*8) -#define SLIDERS_HEIGHT (DISPLAY_INCREMENT*6) -#define TOOLBAR_HEIGHT (DISPLAY_INCREMENT*2) -#define WATERFALL_HEIGHT (display_height-(VFO_HEIGHT+PANADAPTER_HEIGHT+SLIDERS_HEIGHT+TOOLBAR_HEIGHT)) -#ifdef PSK -#define PSK_WATERFALL_HEIGHT (DISPLAY_INCREMENT*6) -#define PSK_HEIGHT (display_height-(VFO_HEIGHT+PSK_WATERFALL_HEIGHT+SLIDERS_HEIGHT+TOOLBAR_HEIGHT)) +#include "button_text.h" +#ifdef I2C +#include "i2c.h" #endif +#include "discovery.h" struct utsname unameData; @@ -91,12 +52,6 @@ gint display_width; gint display_height; gint full_screen=1; -static gint update_timer_id; - -static gint save_timer_id; - -static float *samples; - static GtkWidget *discovery_dialog; static sem_t wisdom_sem; @@ -104,189 +59,21 @@ static sem_t wisdom_sem; static GdkCursor *cursor_arrow; static GdkCursor *cursor_watch; -static GdkWindow *splash_window; - -static GtkWidget *window; -static GtkWidget *grid; -static GtkWidget *fixed; -static GtkWidget *vfo; -static GtkWidget *rit_control; -static GtkWidget *menu; -static GtkWidget *meter; -static GtkWidget *sliders; -static GtkWidget *toolbar; -static GtkWidget *panadapter; -static GtkWidget *waterfall; -#ifdef PSK -static GtkWidget *psk; -static GtkWidget *psk_waterfall; -#endif +static GtkWidget *splash; + +GtkWidget *top_window; +GtkWidget *grid; static DISCOVERED* d; -static void start_radio(); -static void discover_devices(); - -gint update(gpointer data) { - int result; - double fwd; - double rev; - double exciter; - int channel=CHANNEL_RX0; -#ifdef PSK - if(mode==modePSK) { - channel=CHANNEL_PSK; - } -#endif - if(isTransmitting()) { - channel=CHANNEL_TX; - } - GetPixels(channel,0,samples,&result); - if(result==1) { - if(display_panadapter) { -#ifdef PSK - if(mode==modePSK) { - psk_waterfall_update(samples); - } else { -#endif - panadapter_update(samples,isTransmitting()); -#ifdef PSK - } -#endif - } - if(!isTransmitting()) { -#ifdef PSK - if(mode!=modePSK) { -#endif - if(display_waterfall) { - waterfall_update(samples); - } -#ifdef PSK - } -#endif - } - } - - if(!isTransmitting()) { - double m; - switch(mode) { -#ifdef PSK - case modePSK: - m=(double)psk_get_signal_level(); - meter_update(PSKMETER,m,0.0,0.0,0.0); - break; -#endif - default: - m=GetRXAMeter(CHANNEL_RX0, smeter); - meter_update(SMETER,m,0.0,0.0,0.0); - break; - } - } else { - - double alc=GetTXAMeter(CHANNEL_TX, alc); - - DISCOVERED *d=&discovered[selected_device]; - - double constant1=3.3; - double constant2=0.095; - - if(d->protocol==ORIGINAL_PROTOCOL) { - switch(d->device) { - case DEVICE_METIS: - constant1=3.3; - constant2=0.09; - break; - case DEVICE_HERMES: - constant1=3.3; - constant2=0.095; - break; - case DEVICE_ANGELIA: - constant1=3.3; - constant2=0.095; - break; - case DEVICE_ORION: - constant1=5.0; - constant2=0.108; - break; - case DEVICE_HERMES_LITE: - break; - } - - int power=alex_forward_power; - if(power==0) { - power=exciter_power; - } - double v1; - v1=((double)power/4095.0)*constant1; - fwd=(v1*v1)/constant2; - - power=exciter_power; - v1=((double)power/4095.0)*constant1; - exciter=(v1*v1)/constant2; - - rev=0.0; - if(alex_forward_power!=0) { - power=alex_reverse_power; - v1=((double)power/4095.0)*constant1; - rev=(v1*v1)/constant2; - } - - } else { - switch(d->device) { - case NEW_DEVICE_ATLAS: - constant1=3.3; - constant2=0.09; - break; - case NEW_DEVICE_HERMES: - constant1=3.3; - constant2=0.09; - break; - case NEW_DEVICE_HERMES2: - constant1=3.3; - constant2=0.095; - break; - case NEW_DEVICE_ANGELIA: - constant1=3.3; - constant2=0.095; - break; - case NEW_DEVICE_ORION: - constant1=5.0; - constant2=0.108; - break; - case NEW_DEVICE_ORION2: - constant1=5.0; - constant2=0.108; - break; - case NEW_DEVICE_HERMES_LITE: - constant1=3.3; - constant2=0.09; - break; - } - - int power=alex_forward_power; - if(power==0) { - power=exciter_power; - } - double v1; - v1=((double)power/4095.0)*constant1; - fwd=(v1*v1)/constant2; - - power=exciter_power; - v1=((double)power/4095.0)*constant1; - exciter=(v1*v1)/constant2; - - rev=0.0; - if(alex_forward_power!=0) { - power=alex_reverse_power; - v1=((double)power/4095.0)*constant1; - rev=(v1*v1)/constant2; - } - } - - meter_update(POWER,fwd,rev,exciter,alc); - } +static GtkWidget *status; - return TRUE; +void status_text(char *text) { + //fprintf(stderr,"splash_status: %s\n",text); + gtk_label_set_text(GTK_LABEL(status),text); + usleep(10000); + while (gtk_events_pending ()) + gtk_main_iteration (); } static gint save_cb(gpointer data) { @@ -297,7 +84,7 @@ static gint save_cb(gpointer data) { static pthread_t wisdom_thread_id; static void* wisdom_thread(void *arg) { - splash_status("Creating FFTW Wisdom file ..."); + status_text("Creating FFTW Wisdom file ..."); WDSPwisdom ((char *)arg); sem_post(&wisdom_sem); } @@ -323,620 +110,45 @@ gboolean main_delete (GtkWidget *widget) { _exit(0); } -static gboolean start_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { -fprintf(stderr,"start_cb: %p\n",data); - radio=(DISCOVERED *)data; - gtk_widget_destroy(discovery_dialog); - start_radio(); - return TRUE; -} - -#ifdef GPIO -static gboolean gpio_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { - configure_gpio(discovery_dialog); - return TRUE; -} -#endif - -static gboolean discover_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { - gtk_widget_destroy(discovery_dialog); - discover_devices(); - return TRUE; -} - -static gboolean exit_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { - gtk_widget_destroy(discovery_dialog); - _exit(0); - return TRUE; -} - -static void discover_devices() { - - gdk_window_set_cursor(splash_window,cursor_watch); - selected_device=0; - devices=0; - splash_status("Old Protocol ... Discovering Devices"); - old_discovery(); - splash_status("New Protocol ... Discovering Devices"); - new_discovery(); -#ifdef LIMESDR - splash_status("LimeSDR ... Discovering Devices"); - lime_discovery(); -#endif - splash_status("Discovery"); - if(devices==0) { - gdk_window_set_cursor(splash_window,cursor_arrow); - fprintf(stderr,"No devices found!\n"); - GtkDialogFlags flags = GTK_DIALOG_DESTROY_WITH_PARENT; -/* - discovery_dialog = gtk_message_dialog_new (GTK_WINDOW(splash_screen), - flags, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK_CANCEL, - "No devices found! Retry Discovery?"); -*/ - discovery_dialog = gtk_dialog_new(); - gtk_window_set_transient_for(GTK_WINDOW(discovery_dialog),GTK_WINDOW(splash_screen)); - gtk_window_set_decorated(GTK_WINDOW(discovery_dialog),FALSE); - - gtk_widget_override_font(discovery_dialog, pango_font_description_from_string("FreeMono 16")); - - GdkRGBA color; - color.red = 1.0; - color.green = 1.0; - color.blue = 1.0; - color.alpha = 1.0; - gtk_widget_override_background_color(discovery_dialog,GTK_STATE_FLAG_NORMAL,&color); - - GtkWidget *content; - - content=gtk_dialog_get_content_area(GTK_DIALOG(discovery_dialog)); - - GtkWidget *grid=gtk_grid_new(); - gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE); - gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE); - gtk_grid_set_row_spacing (GTK_GRID(grid),10); - - GtkWidget *label=gtk_label_new("No devices found!"); - gtk_grid_attach(GTK_GRID(grid),label,0,0,2,1); - - GtkWidget *exit_b=gtk_button_new_with_label("Exit"); - g_signal_connect (exit_b, "button-press-event", G_CALLBACK(exit_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),exit_b,0,1,1,1); - - GtkWidget *discover_b=gtk_button_new_with_label("Retry Discovery"); - g_signal_connect (discover_b, "button-press-event", G_CALLBACK(discover_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),discover_b,1,1,1,1); - - gtk_container_add (GTK_CONTAINER (content), grid); - gtk_widget_show_all(discovery_dialog); - } else { - //fprintf(stderr,"%s: found %d devices.\n", (char *)arg, devices); - gdk_window_set_cursor(splash_window,cursor_arrow); -/* - GtkDialogFlags flags=GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT; - discovery_dialog = gtk_dialog_new_with_buttons ("Discovered", - GTK_WINDOW(splash_window), - flags, -#ifdef GPIO - "Configure GPIO", - GTK_RESPONSE_YES, -#endif - "Discover", - GTK_RESPONSE_REJECT, - "Exit", - GTK_RESPONSE_CLOSE, - NULL); -*/ - - discovery_dialog = gtk_dialog_new(); - gtk_window_set_transient_for(GTK_WINDOW(discovery_dialog),GTK_WINDOW(splash_screen)); - gtk_window_set_decorated(GTK_WINDOW(discovery_dialog),FALSE); - - gtk_widget_override_font(discovery_dialog, pango_font_description_from_string("FreeMono 16")); - - GdkRGBA color; - color.red = 1.0; - color.green = 1.0; - color.blue = 1.0; - color.alpha = 1.0; - gtk_widget_override_background_color(discovery_dialog,GTK_STATE_FLAG_NORMAL,&color); - - GtkWidget *content; - - content=gtk_dialog_get_content_area(GTK_DIALOG(discovery_dialog)); - - GtkWidget *grid=gtk_grid_new(); - gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE); - gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE); - gtk_grid_set_row_spacing (GTK_GRID(grid),10); - - int i; - char version[16]; - char text[128]; - for(i=0;iprotocol,d->name); - if(d->protocol==ORIGINAL_PROTOCOL) { - sprintf(version,"%d.%d", - d->software_version/10, - d->software_version%10); - } else { - sprintf(version,"%d.%d.%d", - d->software_version/100, - (d->software_version%100)/10, - d->software_version%10); - } - switch(d->protocol) { - case ORIGINAL_PROTOCOL: - case NEW_PROTOCOL: - sprintf(text,"%s (%s %s) %s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n", - d->name, - d->protocol==ORIGINAL_PROTOCOL?"old":"new", - version, - inet_ntoa(d->info.network.address.sin_addr), - d->info.network.mac_address[0], - d->info.network.mac_address[1], - d->info.network.mac_address[2], - d->info.network.mac_address[3], - d->info.network.mac_address[4], - d->info.network.mac_address[5], - d->info.network.interface_name); - break; -#ifdef LIMESDR - case LIMESDR_PROTOCOL: -/* - sprintf(text,"%s (%s %s)\n", - d->name, - "lime", - version); -*/ - sprintf(text,"%s\n", - d->name); - break; -#endif - } - - GtkWidget *label=gtk_label_new(text); - gtk_widget_override_font(label, pango_font_description_from_string("FreeMono 12")); - gtk_widget_show(label); - gtk_grid_attach(GTK_GRID(grid),label,0,i,3,1); - - GtkWidget *start_button=gtk_button_new_with_label("Start"); - gtk_widget_override_font(start_button, pango_font_description_from_string("FreeMono 18")); - gtk_widget_show(start_button); - gtk_grid_attach(GTK_GRID(grid),start_button,3,i,1,1); - g_signal_connect(start_button,"button_press_event",G_CALLBACK(start_cb),(gpointer)d); - - // if not available then cannot start it - if(d->status!=STATE_AVAILABLE) { - gtk_button_set_label(GTK_BUTTON(start_button),"In Use"); - gtk_widget_set_sensitive(start_button, FALSE); - } - - // if not on the same subnet then cannot start it - if((d->info.network.interface_address.sin_addr.s_addr&d->info.network.interface_netmask.sin_addr.s_addr) != (d->info.network.address.sin_addr.s_addr&d->info.network.interface_netmask.sin_addr.s_addr)) { - gtk_button_set_label(GTK_BUTTON(start_button),"Subnet!"); - gtk_widget_set_sensitive(start_button, FALSE); - } - - } - -#ifdef GPIO - GtkWidget *gpio_b=gtk_button_new_with_label("Config GPIO"); - g_signal_connect (gpio_b, "button-press-event", G_CALLBACK(gpio_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),gpio_b,0,i,1,1); -#endif - GtkWidget *discover_b=gtk_button_new_with_label("Discover"); - g_signal_connect (discover_b, "button-press-event", G_CALLBACK(discover_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),discover_b,1,i,1,1); - - GtkWidget *exit_b=gtk_button_new_with_label("Exit"); - g_signal_connect (exit_b, "button-press-event", G_CALLBACK(exit_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),exit_b,2,i,1,1); - - - gtk_container_add (GTK_CONTAINER (content), grid); - gtk_widget_show_all(discovery_dialog); - } -} - -static gboolean minimize_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { - gtk_window_iconify(GTK_WINDOW(window)); - return TRUE; -} - -static void start_radio() { - int y; -fprintf(stderr,"start: selected radio=%p device=%d\n",radio,radio->device); - gdk_window_set_cursor(splash_window,cursor_watch); - - splash_status("Initializing wdsp ..."); - protocol=radio->protocol; - device=radio->device; - - switch(radio->protocol) { - case ORIGINAL_PROTOCOL: - case NEW_PROTOCOL: - sprintf(property_path,"%02X-%02X-%02X-%02X-%02X-%02X.props", - radio->info.network.mac_address[0], - radio->info.network.mac_address[1], - radio->info.network.mac_address[2], - radio->info.network.mac_address[3], - radio->info.network.mac_address[4], - radio->info.network.mac_address[5]); - break; -#ifdef LIMESDR - case LIMESDR_PROTOCOL: - sprintf(property_path,"limesdr.props"); - break; -#endif - } - - radioRestoreState(); - - fprintf(stderr,"malloc samples\n"); - if(radio->protocol==NEW_PROTOCOL) { - samples=malloc(display_width*sizeof(float)*2*4); // 192 -> 48 - } else { - samples=malloc(display_width*sizeof(float)*2); - } - - //splash_status("Initializing wdsp ..."); - fprintf(stderr,"wdsp_init\n"); - wdsp_init(0,display_width,radio->protocol); - - switch(radio->protocol) { - case ORIGINAL_PROTOCOL: - splash_status("Initializing old protocol ..."); - fprintf(stderr,"old_protocol_init\n"); - old_protocol_init(0,display_width); - break; - case NEW_PROTOCOL: - splash_status("Initializing new protocol ..."); - fprintf(stderr,"new_protocol_init\n"); - new_protocol_init(display_width); - break; -#ifdef LIMESDR - case LIMESDR_PROTOCOL: - splash_status("Initializing lime protocol ..."); - lime_protocol_init(0,display_width); - break; -#endif - } - -#ifdef GPIO - fprintf(stderr,"gpio_init\n"); - splash_status("Initializing GPIO ..."); - if(gpio_init()<0) { - } -#ifdef LOCALCW - // init local keyer if enabled - else if (cw_keyer_internal == 0) - keyer_update(); -#endif -#endif - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (window), "pihpsdr"); - gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER_ALWAYS); - gtk_window_set_resizable(GTK_WINDOW(window), FALSE); - g_signal_connect (window, "delete-event", G_CALLBACK (main_delete), NULL); - - fixed=gtk_fixed_new(); - gtk_container_add(GTK_CONTAINER(window), fixed); - y=0; - - vfo = vfo_init(VFO_WIDTH,VFO_HEIGHT,window); - gtk_fixed_put(GTK_FIXED(fixed),vfo,0,0); - - - - //rit_control = rit_init(RIT_WIDTH,MENU_HEIGHT,window); - //gtk_fixed_put(GTK_FIXED(fixed),rit_control,VFO_WIDTH,y); - - GtkWidget *minimize_b=gtk_button_new_with_label("Hide"); - gtk_widget_override_font(minimize_b, pango_font_description_from_string("FreeMono Bold 10")); - gtk_widget_set_size_request (minimize_b, MENU_WIDTH, MENU_HEIGHT/2); - g_signal_connect (minimize_b, "button-press-event", G_CALLBACK(minimize_cb), NULL); - gtk_widget_show(minimize_b); - gtk_fixed_put(GTK_FIXED(fixed),minimize_b,VFO_WIDTH,y); - - //menu = menu_init(MENU_WIDTH,MENU_HEIGHT,window); - menu = new_menu_init(MENU_WIDTH,MENU_HEIGHT/2,window); - gtk_fixed_put(GTK_FIXED(fixed),menu,VFO_WIDTH,y+(MENU_HEIGHT/2)); - - meter = meter_init(METER_WIDTH,METER_HEIGHT,window); - gtk_fixed_put(GTK_FIXED(fixed),meter,VFO_WIDTH+MENU_WIDTH,y); - y+=VFO_HEIGHT; - - if(display_panadapter) { - int height=PANADAPTER_HEIGHT; - if(!display_waterfall) { - height+=WATERFALL_HEIGHT; - if(!display_sliders) { - height+=SLIDERS_HEIGHT; - } - if(!display_toolbar) { - height+=TOOLBAR_HEIGHT; - } - } else { - if(!display_sliders) { - height+=SLIDERS_HEIGHT/2; - } - } - panadapter = panadapter_init(display_width,height); - gtk_fixed_put(GTK_FIXED(fixed),panadapter,0,VFO_HEIGHT); - y+=height; - } - - if(display_waterfall) { - int height=WATERFALL_HEIGHT; - if(!display_panadapter) { - height+=PANADAPTER_HEIGHT; - } - if(!display_sliders) { - if(display_panadapter) { - height+=SLIDERS_HEIGHT/2; - } else { - height+=SLIDERS_HEIGHT; - } - } - if(!display_toolbar) { - height+=TOOLBAR_HEIGHT; - } - waterfall = waterfall_init(display_width,height); - gtk_fixed_put(GTK_FIXED(fixed),waterfall,0,y); - y+=height; - - } - -#ifdef PSK - int psk_height=PSK_WATERFALL_HEIGHT; - if(!display_sliders) { - psk_height+=SLIDERS_HEIGHT/2; - } - if(!display_toolbar) { - psk_height+=TOOLBAR_HEIGHT/2; - } - psk_waterfall = psk_waterfall_init(display_width,psk_height); - gtk_fixed_put(GTK_FIXED(fixed),psk_waterfall,0,VFO_HEIGHT); - psk = init_psk(); - gtk_fixed_put(GTK_FIXED(fixed),psk,0,VFO_HEIGHT+psk_height); -#endif - - if(display_sliders) { - sliders = sliders_init(display_width,SLIDERS_HEIGHT,window); - gtk_fixed_put(GTK_FIXED(fixed),sliders,0,y); - y+=SLIDERS_HEIGHT; - } - - if(display_toolbar) { - toolbar = toolbar_init(display_width,TOOLBAR_HEIGHT,window); - gtk_fixed_put(GTK_FIXED(fixed),toolbar,0,y); - y+=TOOLBAR_HEIGHT; - } - - splash_close(); - - gtk_widget_show_all (window); - - linein_changed(); - - if(full_screen) { - gtk_window_fullscreen(GTK_WINDOW(window)); - } - - GdkWindow *gdk_window = gtk_widget_get_window(window); - gdk_window_set_cursor(gdk_window,cursor_arrow); - - // start the receiver - SetChannelState(CHANNEL_RX0,1,1); - - //update_timer_id=gdk_threads_add_timeout(1000/updates_per_second, update, NULL); - update_timer_id=gdk_threads_add_timeout_full(G_PRIORITY_HIGH_IDLE,1000/updates_per_second, update, NULL, NULL); - - // save every 30 seconds - save_timer_id=gdk_threads_add_timeout(30000, save_cb, NULL); - - - if(protocol!=NEW_PROTOCOL) { - setFrequency(getFrequency()); - } - -#ifdef PSK - if(mode==modePSK) { - show_psk(); - } else { - show_waterfall(); - } -#endif - - launch_rigctl(); - - g_idle_add(vfo_update,(gpointer)NULL); - -} - -#ifdef PSK -void show_psk() { - if(display_waterfall) { - gtk_widget_hide(waterfall); - } - if(display_panadapter) { - gtk_widget_hide(panadapter); - } - gtk_widget_show(psk); - gtk_widget_show(psk_waterfall); -} - -void show_waterfall() { - gtk_widget_hide(psk_waterfall); - gtk_widget_hide(psk); - if(display_panadapter) { - gtk_widget_show(panadapter); - } - if(display_waterfall) { - gtk_widget_show(waterfall); - } -} -#endif - -void reconfigure_display() { - int y=VFO_HEIGHT; - - // configure panadapter - if(display_panadapter) { - int height=PANADAPTER_HEIGHT; - if(!display_waterfall) { - height+=WATERFALL_HEIGHT; - if(!display_sliders) { - height+=SLIDERS_HEIGHT; - } - if(!display_toolbar) { - height+=TOOLBAR_HEIGHT; - } - } else { - if(!display_sliders) { - height+=SLIDERS_HEIGHT/2; - } - if(!display_toolbar) { - height+=TOOLBAR_HEIGHT/2; - } - } -fprintf(stderr,"panadapter_height=%d\n",height); - if(panadapter==NULL) { -fprintf(stderr,"reconfigure_display: panadapter_init: width:%d height:%d\n",display_width,height); - panadapter = panadapter_init(display_width,height); - gtk_fixed_put(GTK_FIXED(fixed),panadapter,0,y); - } else { - // set the size -fprintf(stderr,"reconfigure_display: panadapter set_size_request: width:%d height:%d\n",display_width,height); - gtk_widget_set_size_request(panadapter, display_width, height); - // move the current one - gtk_fixed_move(GTK_FIXED(fixed),panadapter,0,y); - } - gtk_widget_show_all(panadapter); - y+=height; - } else { - gtk_widget_hide(panadapter); - } - - // configure waterfall - if(display_waterfall) { - int height=WATERFALL_HEIGHT; - - if(!display_panadapter) { - height+=PANADAPTER_HEIGHT; - if(!display_sliders) { - height+=SLIDERS_HEIGHT; - } - if(!display_toolbar) { - height+=TOOLBAR_HEIGHT; - } - } else { - if(!display_sliders) { - height+=SLIDERS_HEIGHT/2; - } - if(!display_toolbar) { - height+=TOOLBAR_HEIGHT/2; - } - } -fprintf(stderr,"waterfall_height=%d\n",height); - if(waterfall==NULL) { -fprintf(stderr,"reconfigure_display: waterfall_init: width:%d height:%d\n",display_width,height); - waterfall = waterfall_init(display_width,height); - gtk_fixed_put(GTK_FIXED(fixed),waterfall,0,y); - } else { - // set the size -fprintf(stderr,"reconfigure_display: waterfall set_size_request: width:%d height:%d\n",display_width,height); - gtk_widget_set_size_request (waterfall, display_width, height); - // move the current one - gtk_fixed_move(GTK_FIXED(fixed),waterfall,0,y); - } - gtk_widget_show_all(waterfall); - y+=height; - } else { - gtk_widget_hide(waterfall); - } - - if(display_sliders) { -fprintf(stderr,"sliders_height=%d\n",SLIDERS_HEIGHT); - if(sliders==NULL) { -fprintf(stderr,"reconfigure_display: sliders_init: width:%d height:%d\n",display_width,SLIDERS_HEIGHT); - sliders = sliders_init(display_width,SLIDERS_HEIGHT,window); - gtk_fixed_put(GTK_FIXED(fixed),sliders,0,y); - } else { - gtk_fixed_move(GTK_FIXED(fixed),sliders,0,y); - gtk_widget_show(sliders); - } - gtk_widget_show_all(sliders); - linein_changed(); - y+=SLIDERS_HEIGHT; - } else { - gtk_widget_hide(sliders); - } - - if(display_toolbar) { -fprintf(stderr,"toolbar_height=%d\n",TOOLBAR_HEIGHT); - if(toolbar==NULL) { -fprintf(stderr,"reconfigure_display: toolbar_init: width:%d height:%d\n",display_width,TOOLBAR_HEIGHT); - toolbar = toolbar_init(display_width,TOOLBAR_HEIGHT,window); - gtk_fixed_put(GTK_FIXED(fixed),toolbar,0,y); - } else { - gtk_fixed_move(GTK_FIXED(fixed),toolbar,0,y); - gtk_widget_show(toolbar); - } - gtk_widget_show_all(toolbar); - y+=TOOLBAR_HEIGHT; - } else { - gtk_widget_hide(toolbar); - } - -} - -gint init(void* arg) { +static int init(void *data) { char *res; char wisdom_directory[1024]; char wisdom_file[1024]; fprintf(stderr,"init\n"); - audio_get_cards(0); - audio_get_cards(1); + audio_get_cards(); cursor_arrow=gdk_cursor_new(GDK_ARROW); cursor_watch=gdk_cursor_new(GDK_WATCH); - splash_window = gtk_widget_get_window(splash_screen); - gdk_window_set_cursor(splash_window,cursor_watch); - - init_radio(); + gdk_window_set_cursor(gtk_widget_get_window(top_window),cursor_watch); // check if wisdom file exists res=getcwd(wisdom_directory, sizeof(wisdom_directory)); strcpy(&wisdom_directory[strlen(wisdom_directory)],"/"); strcpy(wisdom_file,wisdom_directory); strcpy(&wisdom_file[strlen(wisdom_file)],"wdspWisdom"); - splash_status("Checking FFTW Wisdom file ..."); + status_text("Checking FFTW Wisdom file ..."); if(access(wisdom_file,F_OK)<0) { int rc=sem_init(&wisdom_sem, 0, 0); rc=pthread_create(&wisdom_thread_id, NULL, wisdom_thread, (void *)wisdom_directory); while(sem_trywait(&wisdom_sem)<0) { - splash_status(wisdom_get_status()); + status_text(wisdom_get_status()); while (gtk_events_pending ()) gtk_main_iteration (); usleep(100000); // 100ms } } - discover_devices(); - + g_idle_add(discovery,NULL); return 0; } -int main (int argc, char *argv[]) { - gtk_init (&argc, &argv); +static void activate_pihpsdr(GtkApplication *app, gpointer data) { + + + //gtk_init (&argc, &argv); fprintf(stderr,"Build: %s %s\n",build_date,version); @@ -964,13 +176,87 @@ fprintf(stderr,"width=%d height=%d\n", display_width, display_height); full_screen=0; } - fprintf(stderr,"display_width=%d display_height=%d\n", display_width, display_height); +fprintf(stderr,"display_width=%d display_height=%d\n", display_width, display_height); - splash_show("hpsdr.png", display_width, display_height, full_screen); + fprintf(stderr,"create top level window\n"); + top_window = gtk_application_window_new (app); + if(full_screen) { +fprintf(stderr,"full screen\n"); + gtk_window_fullscreen(GTK_WINDOW(top_window)); + } + gtk_widget_set_size_request(top_window, display_width, display_height); + gtk_window_set_title (GTK_WINDOW (top_window), "pihpsdr"); + gtk_window_set_position(GTK_WINDOW(top_window),GTK_WIN_POS_CENTER_ALWAYS); + gtk_window_set_resizable(GTK_WINDOW(top_window), FALSE); + g_signal_connect (top_window, "delete-event", G_CALLBACK (main_delete), NULL); + //g_signal_connect (top_window,"draw", G_CALLBACK (main_draw_cb), NULL); + +//fprintf(stderr,"create fixed container\n"); + //fixed=gtk_fixed_new(); + //gtk_container_add(GTK_CONTAINER(top_window), fixed); + +fprintf(stderr,"create grid\n"); + grid = gtk_grid_new(); + gtk_widget_set_size_request(grid, display_width, display_height); + gtk_grid_set_row_homogeneous(GTK_GRID(grid),FALSE); + gtk_grid_set_column_homogeneous(GTK_GRID(grid),FALSE); +fprintf(stderr,"add grid\n"); + gtk_container_add (GTK_CONTAINER (top_window), grid); + +fprintf(stderr,"create image\n"); + GtkWidget *image=gtk_image_new_from_file("hpsdr.png"); +fprintf(stderr,"add image to grid\n"); + gtk_grid_attach(GTK_GRID(grid), image, 0, 0, 1, 4); + +fprintf(stderr,"create pi label\n"); + char build[64]; + sprintf(build,"build: %s %s",build_date, version); + GtkWidget *pi_label=gtk_label_new("pihpsdr by John Melton g0orx/n6lyt"); + gtk_label_set_justify(GTK_LABEL(pi_label),GTK_JUSTIFY_LEFT); + gtk_widget_show(pi_label); +fprintf(stderr,"add pi label to grid\n"); + gtk_grid_attach(GTK_GRID(grid),pi_label,1,0,1,1); + +fprintf(stderr,"create build label\n"); + GtkWidget *build_date_label=gtk_label_new(build); + gtk_label_set_justify(GTK_LABEL(build_date_label),GTK_JUSTIFY_LEFT); + gtk_widget_show(build_date_label); +fprintf(stderr,"add build label to grid\n"); + gtk_grid_attach(GTK_GRID(grid),build_date_label,1,1,1,1); + +fprintf(stderr,"create status\n"); + status=gtk_label_new(""); + gtk_label_set_justify(GTK_LABEL(status),GTK_JUSTIFY_LEFT); + gtk_widget_override_font(status, pango_font_description_from_string("FreeMono 18")); + gtk_widget_show(status); +fprintf(stderr,"add status to grid\n"); + gtk_grid_attach(GTK_GRID(grid), status, 1, 3, 1, 1); - g_idle_add(init,(void *)argv[0]); +/* +fprintf(stderr,"create exit button\n"); + GtkWidget *button = gtk_button_new_with_label ("Exit"); + //g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL); + g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), top_window); +fprintf(stderr,"add exit button to grid\n"); + gtk_grid_attach(GTK_GRID(grid), button, 1, 4, 1, 1); +*/ - gtk_main(); + gtk_widget_show_all(top_window); - return 0; + g_idle_add(init,NULL); + //g_idle_add(discovery,NULL); + + +} + +int main(int argc,char **argv) { + GtkApplication *pihpsdr; + int status; + + pihpsdr=gtk_application_new("org.g0orx.pihpsdr", G_APPLICATION_FLAGS_NONE); + g_signal_connect(pihpsdr, "activate", G_CALLBACK(activate_pihpsdr), NULL); + status=g_application_run(G_APPLICATION(pihpsdr), argc, argv); +fprintf(stderr,"exiting ...\n"); + g_object_unref(pihpsdr); + return status; } diff --git a/main.h b/main.h index ba49d5b..49a76c9 100644 --- a/main.h +++ b/main.h @@ -20,12 +20,30 @@ #ifndef _MAIN_H #define _MAIN_H -#include -extern struct utsname unameData; -void reconfigure_display(); +#define DISPLAY_INCREMENT (display_height/32) +#define MENU_HEIGHT (DISPLAY_INCREMENT*2) +#define MENU_WIDTH ((display_width/32)*3) +#define VFO_HEIGHT (DISPLAY_INCREMENT*4) +#define VFO_WIDTH (display_width-METER_WIDTH-MENU_WIDTH) +#define METER_HEIGHT (DISPLAY_INCREMENT*4) +#define METER_WIDTH ((display_width/32)*8) +#define PANADAPTER_HEIGHT (DISPLAY_INCREMENT*8) +#define SLIDERS_HEIGHT (DISPLAY_INCREMENT*6) +#define TOOLBAR_HEIGHT (DISPLAY_INCREMENT*2) +#define WATERFALL_HEIGHT (display_height-(VFO_HEIGHT+PANADAPTER_HEIGHT+SLIDERS_HEIGHT+TOOLBAR_HEIGHT)) #ifdef PSK -void show_psk(); -void show_waterfall(); +#define PSK_WATERFALL_HEIGHT (DISPLAY_INCREMENT*6) +#define PSK_HEIGHT (display_height-(VFO_HEIGHT+PSK_WATERFALL_HEIGHT+SLIDERS_HEIGHT+TOOLBAR_HEIGHT)) #endif +#include +extern struct utsname unameData; + +extern gint display_width; +extern gint display_height; +extern gint full_screen; +extern GtkWidget *top_window; +extern GtkWidget *grid; +extern void status_text(char *text); + #endif diff --git a/meter.c b/meter.c index f95b790..426d1c0 100644 --- a/meter.c +++ b/meter.c @@ -55,7 +55,7 @@ meter_clear_surface (void) cr = cairo_create (meter_surface); cairo_set_source_rgb (cr, 0, 0, 0); - cairo_paint (cr); + cairo_fill (cr); cairo_destroy (cr); } @@ -64,9 +64,6 @@ meter_configure_event_cb (GtkWidget *widget, GdkEventConfigure *event, gpointer data) { -fprintf(stderr,"meter_configure_event_cb: width=%d height=%d\n", - gtk_widget_get_allocated_width (widget), - gtk_widget_get_allocated_height (widget)); if (meter_surface) cairo_surface_destroy (meter_surface); @@ -76,7 +73,11 @@ fprintf(stderr,"meter_configure_event_cb: width=%d height=%d\n", gtk_widget_get_allocated_height (widget)); /* Initialize the surface to black */ - meter_clear_surface (); + cairo_t *cr; + cr = cairo_create (meter_surface); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_paint (cr); + cairo_destroy (cr); return TRUE; } @@ -89,8 +90,7 @@ static gboolean meter_draw_cb (GtkWidget *widget, cairo_t *cr, gpointer data) { cairo_set_source_surface (cr, meter_surface, 0, 0); cairo_paint (cr); - - return FALSE; + return TRUE; } /* @@ -225,11 +225,13 @@ void meter_update(int meter_type,double value,double reverse,double exciter,doub cairo_select_font_face(cr, "FreeMono", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); - cairo_set_source_rgb(cr, 0.5, 0.5, 0.5); - cairo_set_font_size(cr, 10); + + cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); + cairo_set_font_size(cr, 12); cairo_move_to(cr, 5, 15); cairo_show_text(cr, text); + if(last_meter_type!=meter_type) { last_meter_type=meter_type; max_count=0; @@ -321,7 +323,7 @@ void meter_update(int meter_type,double value,double reverse,double exciter,doub cairo_show_text(cr, sf); #ifdef FREEDV - if(mode==modeFREEDV) { + if(active_receiver->mode==modeFREEDV) { if(freedv_sync) { cairo_set_source_rgb(cr, 0, 1, 0); } else { diff --git a/meter.h b/meter.h index 44df101..868dc6c 100644 --- a/meter.h +++ b/meter.h @@ -20,6 +20,8 @@ #ifndef _METER_H #define _METER_H +#include + #define SMETER 0 #define POWER 1 #ifdef PSK diff --git a/meter_menu.c b/meter_menu.c index bccabdc..e43361d 100644 --- a/meter_menu.c +++ b/meter_menu.c @@ -69,7 +69,7 @@ void meter_menu (GtkWidget *parent) { gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE); gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE); - GtkWidget *close_b=gtk_button_new_with_label("Close Meter"); + 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); diff --git a/mode.c b/mode.c index 7bb8cd0..37bd12b 100644 --- a/mode.c +++ b/mode.c @@ -38,3 +38,4 @@ char *mode_string[]={ #endif }; +//int mode; diff --git a/mode.h b/mode.h index e2839d2..ec68810 100644 --- a/mode.h +++ b/mode.h @@ -50,8 +50,7 @@ #endif #endif -int mode; - char *mode_string[MODES]; +//extern int mode; #endif diff --git a/mode_menu.c b/mode_menu.c index 0784302..de525c6 100644 --- a/mode_menu.c +++ b/mode_menu.c @@ -28,6 +28,7 @@ #include "filter.h" #include "mode.h" #include "radio.h" +#include "receiver.h" #include "vfo.h" #include "button_text.h" @@ -48,17 +49,10 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat static gboolean mode_select_cb (GtkWidget *widget, gpointer data) { int m=(int)data; - BANDSTACK_ENTRY *entry; - entry=bandstack_entry_get_current(); - entry->mode=m; - setMode(entry->mode); - FILTER* band_filters=filters[entry->mode]; - FILTER* band_filter=&band_filters[entry->filter]; - setFilter(band_filter->low,band_filter->high); set_button_text_color(last_mode,"black"); last_mode=widget; set_button_text_color(last_mode,"orange"); - vfo_update(NULL); + vfo_mode_changed(m); } void mode_menu(GtkWidget *parent) { @@ -92,11 +86,16 @@ void mode_menu(GtkWidget *parent) { g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL); gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1); - BANDSTACK_ENTRY *entry=bandstack_entry_get_current(); + char label[32]; + sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B"); + GtkWidget *rx_label=gtk_label_new(label); + gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1); + + int mode=vfo[active_receiver->id].mode; for(i=0;imode) { + if(i==mode) { set_button_text_color(b,"orange"); last_mode=b; } else { diff --git a/new_discovery.c b/new_discovery.c index b8a21ca..110d3eb 100644 --- a/new_discovery.c +++ b/new_discovery.c @@ -17,6 +17,7 @@ * */ +#include #include #include #include @@ -48,8 +49,10 @@ static struct sockaddr_in discovery_addr; void new_discover(struct ifaddrs* iface); -static pthread_t discover_thread_id; -void* new_discover_receive_thread(void* arg); +//static pthread_t discover_thread_id; +static GThread *discover_thread_id; +//void* new_discover_receive_thread(void* arg); +gpointer new_discover_receive_thread(gpointer data); void print_device(int i) { fprintf(stderr,"discovery: found protocol=%d device=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n", @@ -121,7 +124,7 @@ void new_discover(struct ifaddrs* iface) { // bind to this interface and the discovery port interface_addr.sin_family = AF_INET; interface_addr.sin_addr.s_addr = sa->sin_addr.s_addr; - interface_addr.sin_port = htons(DISCOVERY_PORT); + interface_addr.sin_port = htons(0); if(bind(discovery_socket,(struct sockaddr*)&interface_addr,sizeof(interface_addr))<0) { perror("new_discover: bind socket failed for discovery_socket\n"); exit(-1); @@ -147,11 +150,21 @@ void new_discover(struct ifaddrs* iface) { to_addr.sin_addr.s_addr=htonl(INADDR_BROADCAST); // start a receive thread to collect discovery response packets +/* rc=pthread_create(&discover_thread_id,NULL,new_discover_receive_thread,NULL); if(rc != 0) { fprintf(stderr,"pthread_create failed on new_discover_receive_thread: rc=%d\n", rc); exit(-1); } +*/ + discover_thread_id = g_thread_new( "new discover receive", new_discover_receive_thread, NULL); + if( ! discover_thread_id ) + { + fprintf(stderr,"g_thread_new failed on new_discover_receive_thread\n"); + exit( -1 ); + } + fprintf(stderr,"new_disovery: thread_id=%p\n",discover_thread_id); + // send discovery packet unsigned char buffer[60]; @@ -171,15 +184,19 @@ void new_discover(struct ifaddrs* iface) { } // wait for receive thread to complete +/* void* status; pthread_join(discover_thread_id,&status); +*/ + g_thread_join(discover_thread_id); close(discovery_socket); fprintf(stderr,"new_discover: exiting discover for %s\n",iface->ifa_name); } -void* new_discover_receive_thread(void* arg) { +//void* new_discover_receive_thread(void* arg) { +gpointer new_discover_receive_thread(gpointer data) { struct sockaddr_in addr; int len; unsigned char buffer[2048]; @@ -270,5 +287,6 @@ void* new_discover_receive_thread(void* arg) { } } fprintf(stderr,"new_discover: exiting new_discover_receive_thread\n"); - pthread_exit(NULL); + //pthread_exit(NULL); + g_thread_exit(NULL); } diff --git a/new_menu.c b/new_menu.c index 6be6ec2..9734c42 100644 --- a/new_menu.c +++ b/new_menu.c @@ -25,8 +25,8 @@ #include "audio.h" #include "new_menu.h" #include "exit_menu.h" -#include "general_menu.h" -#include "audio_menu.h" +#include "radio_menu.h" +#include "rx_menu.h" #include "ant_menu.h" #include "display_menu.h" #include "dsp_menu.h" @@ -46,21 +46,26 @@ #include "filter_menu.h" #include "noise_menu.h" #include "agc_menu.h" -#include "fm_menu.h" #include "test_menu.h" #include "vox_menu.h" #include "diversity_menu.h" #include "freqent_menu.h" +#include "tx_menu.h" +#ifdef GPIO +#include "encoder_menu.h" +#endif +#include "vfo_menu.h" +#include "main.h" -static GtkWidget *parent_window=NULL; - static GtkWidget *menu_b=NULL; static GtkWidget *dialog=NULL; GtkWidget *sub_menu=NULL; +int active_menu=NO_MENU; + static cleanup() { if(dialog!=NULL) { gtk_widget_destroy(dialog); @@ -70,6 +75,7 @@ static cleanup() { gtk_widget_destroy(sub_menu); sub_menu=NULL; } + active_menu=NO_MENU; } static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { @@ -80,81 +86,81 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat static gboolean exit_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { cleanup(); - exit_menu(parent_window); + exit_menu(top_window); return TRUE; } -static gboolean general_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { +static gboolean radio_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { cleanup(); - general_menu(parent_window); + radio_menu(top_window); return TRUE; } -static gboolean audio_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { +static gboolean rx_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { cleanup(); - audio_menu(parent_window); + rx_menu(top_window); return TRUE; } static gboolean ant_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { cleanup(); - ant_menu(parent_window); + ant_menu(top_window); return TRUE; } static gboolean display_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { cleanup(); - display_menu(parent_window); + display_menu(top_window); return TRUE; } static gboolean dsp_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { cleanup(); - dsp_menu(parent_window); + dsp_menu(top_window); return TRUE; } static gboolean pa_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { cleanup(); - pa_menu(parent_window); + pa_menu(top_window); return TRUE; } static gboolean cw_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { cleanup(); - cw_menu(parent_window); + cw_menu(top_window); return TRUE; } static gboolean oc_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { cleanup(); - oc_menu(parent_window); + oc_menu(top_window); return TRUE; } #ifdef FREEDV static gboolean freedv_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { cleanup(); - freedv_menu(parent_window); + freedv_menu(top_window); return TRUE; } #endif static gboolean xvtr_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { cleanup(); - xvtr_menu(parent_window); + xvtr_menu(top_window); return TRUE; } static gboolean equalizer_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { cleanup(); - equalizer_menu(parent_window); + equalizer_menu(top_window); return TRUE; } void start_step() { cleanup(); - step_menu(parent_window); + step_menu(top_window); } static gboolean step_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { @@ -164,7 +170,7 @@ static gboolean step_cb (GtkWidget *widget, GdkEventButton *event, gpointer data void start_meter() { cleanup(); - meter_menu(parent_window); + meter_menu(top_window); } static gboolean meter_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { @@ -173,8 +179,12 @@ static gboolean meter_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat } void start_band() { + int old_menu=active_menu; cleanup(); - band_menu(parent_window); + if(old_menu!=BAND_MENU) { + band_menu(top_window); + active_menu=BAND_MENU; + } } static gboolean band_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { @@ -183,8 +193,12 @@ static gboolean band_cb (GtkWidget *widget, GdkEventButton *event, gpointer data } void start_bandstack() { + int old_menu=active_menu; cleanup(); - bandstack_menu(parent_window); + if(old_menu!=BANDSTACK_MENU) { + bandstack_menu(top_window); + active_menu=BANDSTACK_MENU; + } } static gboolean bandstack_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { @@ -193,8 +207,12 @@ static gboolean bandstack_cb (GtkWidget *widget, GdkEventButton *event, gpointer } void start_mode() { + int old_menu=active_menu; cleanup(); - mode_menu(parent_window); + if(old_menu!=MODE_MENU) { + mode_menu(top_window); + active_menu=MODE_MENU; + } } static gboolean mode_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { @@ -203,8 +221,12 @@ static gboolean mode_cb (GtkWidget *widget, GdkEventButton *event, gpointer data } void start_filter() { + int old_menu=active_menu; cleanup(); - filter_menu(parent_window); + if(old_menu!=FILTER_MENU) { + filter_menu(top_window); + active_menu=FILTER_MENU; + } } static gboolean filter_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { @@ -213,8 +235,12 @@ static gboolean filter_cb (GtkWidget *widget, GdkEventButton *event, gpointer da } void start_noise() { + int old_menu=active_menu; cleanup(); - noise_menu(parent_window); + if(old_menu!=NOISE_MENU) { + noise_menu(top_window); + active_menu=NOISE_MENU; + } } static gboolean noise_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { @@ -223,8 +249,12 @@ static gboolean noise_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat } void start_agc() { + int old_menu=active_menu; cleanup(); - agc_menu(parent_window); + if(old_menu!=AGC_MENU) { + agc_menu(top_window); + active_menu=AGC_MENU; + } } static gboolean agc_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { @@ -232,29 +262,19 @@ static gboolean agc_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) return TRUE; } -void start_fm() { - cleanup(); - fm_menu(parent_window); -} - -static gboolean fm_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { - start_fm(); - return TRUE; -} - void start_vox() { cleanup(); - vox_menu(parent_window); + vox_menu(top_window); } -static gboolean vox_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { +static gboolean vox_b_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { start_vox(); return TRUE; } void start_diversity() { cleanup(); - diversity_menu(parent_window); + diversity_menu(top_window); } static gboolean diversity_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { @@ -264,7 +284,7 @@ static gboolean diversity_cb (GtkWidget *widget, GdkEventButton *event, gpointer void start_freqent() { cleanup(); - freqent_menu(parent_window); + freqent_menu(top_window); } static gboolean freqent_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { @@ -272,9 +292,73 @@ static gboolean freqent_cb (GtkWidget *widget, GdkEventButton *event, gpointer d return TRUE; } +void start_vfo() { + cleanup(); + vfo_menu(top_window); +} + +static gboolean vfo_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { + start_vfo(); + return TRUE; +} + +void start_store() { + cleanup(); + store_menu(top_window); +} + +static gboolean store_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { + start_store(); + return TRUE; +} + +void start_tx() { + cleanup(); + tx_menu(top_window); +} + +static gboolean tx_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { + start_tx(); + return TRUE; +} + +#ifdef GPIO +void start_encoder(int encoder) { + int old_menu=active_menu; +fprintf(stderr,"start_encoder: encoder=%d active_menu=%d\n",encoder,active_menu); + cleanup(); + switch(encoder) { + case 1: + if(old_menu!=E1_MENU) { + encoder_menu(top_window,encoder); + active_menu=E1_MENU; + } + break; + case 2: + if(old_menu!=E2_MENU) { + encoder_menu(top_window,encoder); + active_menu=E2_MENU; + } + break; + case 3: + if(old_menu!=E3_MENU) { + encoder_menu(top_window,encoder); + active_menu=E3_MENU; + } + break; + } +} + +static gboolean encoder_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { + int encoder=(int)data; + start_encoder(encoder); + return TRUE; +} +#endif + void start_test() { cleanup(); - test_menu(parent_window); + test_menu(top_window); } static gboolean test_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { @@ -282,13 +366,10 @@ static gboolean test_cb (GtkWidget *widget, GdkEventButton *event, gpointer data return TRUE; } -static gboolean new_menu_pressed_event_cb (GtkWidget *widget, - GdkEventButton *event, - gpointer data) +void new_menu() { int i, j, id; - if(dialog==NULL) { if(sub_menu!=NULL) { @@ -297,7 +378,7 @@ static gboolean new_menu_pressed_event_cb (GtkWidget *widget, } dialog=gtk_dialog_new(); - gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window)); + gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(top_window)); gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE); GdkRGBA color; @@ -323,105 +404,93 @@ static gboolean new_menu_pressed_event_cb (GtkWidget *widget, g_signal_connect (exit_b, "button-press-event", G_CALLBACK(exit_cb), NULL); gtk_grid_attach(GTK_GRID(grid),exit_b,4,0,2,1); - GtkWidget *general_b=gtk_button_new_with_label("General"); - g_signal_connect (general_b, "button-press-event", G_CALLBACK(general_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),general_b,0,1,1,1); + i=5; - GtkWidget *audio_b=gtk_button_new_with_label("Audio"); - g_signal_connect (audio_b, "button-press-event", G_CALLBACK(audio_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),audio_b,1,1,1,1); + GtkWidget *radio_b=gtk_button_new_with_label("Radio"); + g_signal_connect (radio_b, "button-press-event", G_CALLBACK(radio_cb), NULL); + gtk_grid_attach(GTK_GRID(grid),radio_b,(i%5),i/5,1,1); + i++; - GtkWidget *ant_b=gtk_button_new_with_label("Ant"); - g_signal_connect (ant_b, "button-press-event", G_CALLBACK(ant_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),ant_b,2,1,1,1); + GtkWidget *rx_b=gtk_button_new_with_label("RX"); + g_signal_connect (rx_b, "button-press-event", G_CALLBACK(rx_cb), NULL); + gtk_grid_attach(GTK_GRID(grid),rx_b,(i%5),i/5,1,1); + i++; - GtkWidget *display_b=gtk_button_new_with_label("Display"); - g_signal_connect (display_b, "button-press-event", G_CALLBACK(display_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),display_b,3,1,1,1); - - GtkWidget *dsp_b=gtk_button_new_with_label("DSP"); - g_signal_connect (dsp_b, "button-press-event", G_CALLBACK(dsp_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),dsp_b,4,1,1,1); + GtkWidget *tx_b=gtk_button_new_with_label("TX"); + g_signal_connect (tx_b, "button-press-event", G_CALLBACK(tx_cb), NULL); + gtk_grid_attach(GTK_GRID(grid),tx_b,(i%5),i/5,1,1); + i++; GtkWidget *pa_b=gtk_button_new_with_label("PA"); g_signal_connect (pa_b, "button-press-event", G_CALLBACK(pa_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),pa_b,5,1,1,1); + gtk_grid_attach(GTK_GRID(grid),pa_b,(i%5),i/5,1,1); + i++; GtkWidget *cw_b=gtk_button_new_with_label("CW"); g_signal_connect (cw_b, "button-press-event", G_CALLBACK(cw_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),cw_b,0,2,1,1); + gtk_grid_attach(GTK_GRID(grid),cw_b,(i%5),i/5,1,1); + i++; + + GtkWidget *ant_b=gtk_button_new_with_label("Ant"); + g_signal_connect (ant_b, "button-press-event", G_CALLBACK(ant_cb), NULL); + gtk_grid_attach(GTK_GRID(grid),ant_b,(i%5),i/5,1,1); + i++; + + GtkWidget *dsp_b=gtk_button_new_with_label("DSP"); + g_signal_connect (dsp_b, "button-press-event", G_CALLBACK(dsp_cb), NULL); + gtk_grid_attach(GTK_GRID(grid),dsp_b,(i%5),i/5,1,1); + i++; GtkWidget *oc_b=gtk_button_new_with_label("OC"); g_signal_connect (oc_b, "button-press-event", G_CALLBACK(oc_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),oc_b,1,2,1,1); + gtk_grid_attach(GTK_GRID(grid),oc_b,(i%5),i/5,1,1); + i++; #ifdef FREEDV GtkWidget *freedv_b=gtk_button_new_with_label("FreeDV"); g_signal_connect (freedv_b, "button-press-event", G_CALLBACK(freedv_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),freedv_b,2,2,1,1); + gtk_grid_attach(GTK_GRID(grid),freedv_b,(i%5),i/5,1,1); + i++; #endif + GtkWidget *display_b=gtk_button_new_with_label("Display"); + g_signal_connect (display_b, "button-press-event", G_CALLBACK(display_cb), NULL); + gtk_grid_attach(GTK_GRID(grid),display_b,(i%5),i/5,1,1); + i++; + GtkWidget *xvtr_b=gtk_button_new_with_label("XVTR"); g_signal_connect (xvtr_b, "button-press-event", G_CALLBACK(xvtr_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),xvtr_b,3,2,1,1); + gtk_grid_attach(GTK_GRID(grid),xvtr_b,(i%5),i/5,1,1); + i++; GtkWidget *equalizer_b=gtk_button_new_with_label("Equalizer"); g_signal_connect (equalizer_b, "button-press-event", G_CALLBACK(equalizer_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),equalizer_b,4,2,1,1); - - GtkWidget *fm_b=gtk_button_new_with_label("FM"); - g_signal_connect (fm_b, "button-press-event", G_CALLBACK(fm_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),fm_b,5,2,1,1); + gtk_grid_attach(GTK_GRID(grid),equalizer_b,(i%5),i/5,1,1); + i++; GtkWidget *step_b=gtk_button_new_with_label("Step"); g_signal_connect (step_b, "button-press-event", G_CALLBACK(step_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),step_b,0,3,1,1); + gtk_grid_attach(GTK_GRID(grid),step_b,(i%5),i/5,1,1); + i++; GtkWidget *meter_b=gtk_button_new_with_label("Meter"); g_signal_connect (meter_b, "button-press-event", G_CALLBACK(meter_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),meter_b,1,3,1,1); + gtk_grid_attach(GTK_GRID(grid),meter_b,(i%5),i/5,1,1); + i++; GtkWidget *vox_b=gtk_button_new_with_label("VOX"); - g_signal_connect (vox_b, "button-press-event", G_CALLBACK(vox_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),vox_b,2,3,1,1); - - GtkWidget *frequency_b=gtk_button_new_with_label("Frequency"); - g_signal_connect (frequency_b, "button-press-event", G_CALLBACK(freqent_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),frequency_b,3,3,1,1); + g_signal_connect (vox_b, "button-press-event", G_CALLBACK(vox_b_cb), NULL); + gtk_grid_attach(GTK_GRID(grid),vox_b,(i%5),i/5,1,1); + i++; +#ifdef DIVERSITY if(RECEIVERS==2) { 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,4,3,1,1); + gtk_grid_attach(GTK_GRID(grid),diversity_b,(i%5),i/5,1,1); + i++; } - - GtkWidget *band_b=gtk_button_new_with_label("Band"); - g_signal_connect (band_b, "button-press-event", G_CALLBACK(band_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),band_b,0,4,1,1); - - GtkWidget *bandstack_b=gtk_button_new_with_label("Band Stack"); - g_signal_connect (bandstack_b, "button-press-event", G_CALLBACK(bandstack_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),bandstack_b,1,4,1,1); - - GtkWidget *mode_b=gtk_button_new_with_label("Mode"); - g_signal_connect (mode_b, "button-press-event", G_CALLBACK(mode_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),mode_b,2,4,1,1); - - GtkWidget *filter_b=gtk_button_new_with_label("Filter"); - g_signal_connect (filter_b, "button-press-event", G_CALLBACK(filter_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),filter_b,3,4,1,1); - - GtkWidget *noise_b=gtk_button_new_with_label("Noise"); - g_signal_connect (noise_b, "button-press-event", G_CALLBACK(noise_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),noise_b,4,4,1,1); - - GtkWidget *agc_b=gtk_button_new_with_label("AGC"); - g_signal_connect (agc_b, "button-press-event", G_CALLBACK(agc_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),agc_b,5,4,1,1); - - GtkWidget *test_b=gtk_button_new_with_label("Test"); - g_signal_connect (test_b, "button-press-event", G_CALLBACK(test_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),test_b,0,5,1,1); +#endif gtk_container_add(GTK_CONTAINER(content),grid); @@ -432,18 +501,4 @@ static gboolean new_menu_pressed_event_cb (GtkWidget *widget, dialog=NULL; } - return TRUE; -} - -GtkWidget* new_menu_init(int width,int height,GtkWidget *parent) { - - parent_window=parent; - - menu_b=gtk_button_new_with_label("Menu"); - gtk_widget_override_font(menu_b, pango_font_description_from_string("FreeMono Bold 10")); - gtk_widget_set_size_request (menu_b, width, height); - g_signal_connect (menu_b, "button-press-event", G_CALLBACK(new_menu_pressed_event_cb), NULL); - gtk_widget_show(menu_b); - - return menu_b; } diff --git a/new_menu.h b/new_menu.h index 3caac57..ea22179 100644 --- a/new_menu.h +++ b/new_menu.h @@ -1,11 +1,32 @@ GtkWidget *sub_menu; -GtkWidget* new_menu_init(int width,int height,GtkWidget *parent); - -void start_step(); -void start_meter(); -void start_band(); -void start_bandstack(); -void start_mode(); -void start_filter(); -void start_noise(); +extern void new_menu(); + +/* +extern GtkWidget* new_menu_init(int width,int height,GtkWidget *parent); +*/ +extern void start_step(); +extern void start_meter(); +extern void start_band(); +extern void start_bandstack(); +extern void start_mode(); +extern void start_filter(); +extern void start_noise(); +extern void start_encoder(); + +extern void encoder_step(int encoder,int step); + +enum { + NO_MENU = 0, + E1_MENU, + E2_MENU, + E3_MENU, + BAND_MENU, + BANDSTACK_MENU, + MODE_MENU, + FILTER_MENU, + NOISE_MENU, + AGC_MENU +}; + +extern int active_menu; diff --git a/new_protocol.c b/new_protocol.c index 75972ef..fa48079 100644 --- a/new_protocol.c +++ b/new_protocol.c @@ -35,24 +35,25 @@ #include #include #include -#include #include #include +#include + #include "alex.h" #include "audio.h" #include "band.h" #include "new_protocol.h" #include "channel.h" #include "discovered.h" -#include "wdsp.h" #include "mode.h" #include "filter.h" #include "radio.h" +#include "receiver.h" +#include "transmitter.h" #include "signal.h" #include "vfo.h" #include "toolbar.h" -#include "wdsp_init.h" #ifdef FREEDV #include "freedv.h" #endif @@ -89,11 +90,11 @@ static int audio_addr_length; static struct sockaddr_in iq_addr; static int iq_addr_length; -static struct sockaddr_in data_addr[RECEIVERS]; -static int data_addr_length[RECEIVERS]; +static struct sockaddr_in data_addr[MAX_RECEIVERS]; +static int data_addr_length[MAX_RECEIVERS]; -static pthread_t new_protocol_thread_id; -static pthread_t new_protocol_timer_thread_id; +static GThread *new_protocol_thread_id; +static GThread *new_protocol_timer_thread_id; static long rx_sequence = 0; @@ -102,18 +103,18 @@ static long general_sequence = 0; static long rx_specific_sequence = 0; static long tx_specific_sequence = 0; -static int buffer_size=BUFFER_SIZE; -static int fft_size=4096; +//static int buffer_size=BUFFER_SIZE; +//static int fft_size=4096; static int dspRate=48000; static int outputRate=48000; static int micSampleRate=48000; static int micDspRate=48000; static int micOutputRate=192000; -static int micoutputsamples=BUFFER_SIZE*4; // 48000 in, 192000 out +static int micoutputsamples; // 48000 in, 192000 out -static double micinputbuffer[BUFFER_SIZE*2]; // 48000 -static double iqoutputbuffer[BUFFER_SIZE*4*2]; //192000 +static double micinputbuffer[MAX_BUFFER_SIZE*2]; // 48000 +static double iqoutputbuffer[MAX_BUFFER_SIZE*4*2]; //192000 static long tx_iq_sequence; static unsigned char iqbuffer[1444]; @@ -133,11 +134,10 @@ static int send_high_priority=0; static sem_t send_general_sem; static int send_general=0; -static int samples[RECEIVERS]; -static int outputsamples=BUFFER_SIZE; - -static double iqinputbuffer[RECEIVERS][BUFFER_SIZE*2]; -static double audiooutputbuffer[BUFFER_SIZE*2]; +static int samples[MAX_RECEIVERS]; +#ifdef INCLUDED +static int outputsamples; +#endif static int leftaudiosample; static int rightaudiosample; @@ -158,40 +158,48 @@ static int psk_samples=0; static int psk_resample=6; // convert from 48000 to 8000 #endif +static struct sockaddr_in addr; +static int length; +static unsigned char buffer[2048]; +static int bytesread; + static void new_protocol_high_priority(int run); -static void* new_protocol_thread(void* arg); -static void* new_protocol_timer_thread(void* arg); -static void process_iq_data(int rx,unsigned char *buffer); +//static void* new_protocol_thread(void* arg); +static gpointer new_protocol_thread(gpointer data); +//static void* new_protocol_timer_thread(void* arg); +static gpointer new_protocol_timer_thread(gpointer data); +static void process_iq_data(RECEIVER *rx,unsigned char *buffer); static void process_command_response(unsigned char *buffer); static void process_high_priority(unsigned char *buffer); -static void process_mic_data(unsigned char *buffer); -static void full_rx_buffer(); +static void process_mic_data(unsigned char *buffer,int bytes); static void full_tx_buffer(); +#ifdef INCLUDED static void new_protocol_calc_buffers() { switch(sample_rate) { case 48000: - outputsamples=BUFFER_SIZE; + outputsamples=buffer_size; break; case 96000: - outputsamples=BUFFER_SIZE/2; + outputsamples=buffer_size/2; break; case 192000: - outputsamples=BUFFER_SIZE/4; + outputsamples=buffer_size/4; break; case 384000: - outputsamples=BUFFER_SIZE/8; + outputsamples=buffer_size/8; break; case 768000: - outputsamples=BUFFER_SIZE/16; + outputsamples=buffer_size/16; break; case 1536000: - outputsamples=BUFFER_SIZE/32; + outputsamples=buffer_size/32; break; } } +#endif -void schedule_high_priority(int source) { +void schedule_high_priority() { sem_wait(&send_high_priority_sem); send_high_priority=1; sem_post(&send_high_priority_sem); @@ -229,42 +237,46 @@ void new_protocol_init(int pixels) { int rc; spectrumWIDTH=pixels; - fprintf(stderr,"new_protocol_init\n"); + fprintf(stderr,"new_protocol_init: MIC_SAMPLES=%d\n",MIC_SAMPLES); +#ifdef INCLUDED + outputsamples=buffer_size; +#endif + micoutputsamples=buffer_size*4; + +#ifdef OLD_AUDIO if(local_audio) { if(audio_open_output()!=0) { fprintf(stderr,"audio_open_output failed\n"); local_audio=0; } } +#endif - if(local_microphone) { + if(transmitter->local_microphone) { if(audio_open_input()!=0) { fprintf(stderr,"audio_open_input failed\n"); - local_microphone=0; + transmitter->local_microphone=0; } } +#ifdef INCLUDED new_protocol_calc_buffers(); +#endif rc=sem_init(&response_sem, 0, 0); rc=sem_init(&send_high_priority_sem, 0, 1); rc=sem_init(&send_general_sem, 0, 1); - rc=pthread_create(&new_protocol_thread_id,NULL,new_protocol_thread,NULL); - if(rc != 0) { - fprintf(stderr,"pthread_create failed on new_protocol_thread: rc=%d\n", rc); - exit(-1); + new_protocol_thread_id = g_thread_new( "new protocol", new_protocol_thread, NULL); + if( ! new_protocol_thread_id ) + { + fprintf(stderr,"g_thread_new failed on new_protocol_thread\n"); + exit( -1 ); } + fprintf(stderr, "new_protocol_thread: id=%p\n",new_protocol_thread_id); -} -void new_protocol_new_sample_rate(int rate) { - new_protocol_high_priority(0); - sample_rate=rate; - new_protocol_calc_buffers(); - wdsp_new_sample_rate(rate); - new_protocol_high_priority(1); } static void new_protocol_general() { @@ -291,13 +303,19 @@ static void new_protocol_general() { } if(filter_board==APOLLO) { - buffer[58]|=0x02; // enable APOLLO tuner + buffer[58]|=0x02; // enable APOLLO tuner } if(filter_board==ALEX) { + if(device==NEW_DEVICE_ORION2) { + buffer[59]=0x03; // enable Alex 0 and 1 + } else { buffer[59]=0x01; // enable Alex 0 + } } +fprintf(stderr,"Alex Enable=%02X\n",buffer[59]); + if(sendto(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&base_addr,base_addr_length)<0) { fprintf(stderr,"sendto socket failed for general\n"); exit(1); @@ -307,9 +325,13 @@ static void new_protocol_general() { } static void new_protocol_high_priority(int run) { - int r; + int i, r; unsigned char buffer[1444]; - BAND *band=band_get_current_band(); + BAND *band; + long long rxFrequency; + long long txFrequency; + long phase; + int mode; memset(buffer, 0, sizeof(buffer)); @@ -318,6 +340,11 @@ static void new_protocol_high_priority(int run) { buffer[2]=high_priority_sequence>>8; buffer[3]=high_priority_sequence; + if(split) { + mode=vfo[1].mode; + } else { + mode=vfo[0].mode; + } buffer[4]=run; if(mode==modeCWU || mode==modeCWL) { if(tune) { @@ -340,28 +367,38 @@ static void new_protocol_high_priority(int run) { } } - long rxFrequency=ddsFrequency; - if(mode==modeCWU) { - rxFrequency-=cw_keyer_sidetone_frequency; - } else if(mode==modeCWL) { - rxFrequency+=cw_keyer_sidetone_frequency; - } - long phase=(long)((4294967296.0*(double)rxFrequency)/122880000.0); - // rx for(r=0;r>24; - buffer[10+(r*4)]=phase>>16; - buffer[11+(r*4)]=phase>>8; - buffer[12+(r*4)]=phase; + //long long rxFrequency=ddsFrequency; + //rxFrequency=receiver[r]->dds_frequency; + int v=receiver[r]->id; + rxFrequency=vfo[v].frequency-vfo[v].lo+vfo[v].rit; + + if(vfo[v].mode==modeCWU) { + rxFrequency-=cw_keyer_sidetone_frequency; + } else if(vfo[v].mode==modeCWL) { + rxFrequency+=cw_keyer_sidetone_frequency; + } + phase=(long)((4294967296.0*(double)rxFrequency)/122880000.0); + + i=r; + //if(device==NEW_DEVICE_ORION2 && r==1) i=3; + buffer[9+(i*4)]=phase>>24; + buffer[10+(i*4)]=phase>>16; + buffer[11+(i*4)]=phase>>8; + buffer[12+(i*4)]=phase; } -// tx (no split yet) - long long txFrequency=ddsFrequency; - if(ctun) { - txFrequency+=ddsOffset; + // tx + band=band_get_band(vfo[VFO_A].band); + rxFrequency=vfo[VFO_A].frequency-vfo[VFO_A].lo; + txFrequency=vfo[VFO_A].frequency-vfo[VFO_A].lo; + if(split) { + band=band_get_band(vfo[VFO_B].band); + txFrequency=vfo[VFO_B].frequency-vfo[VFO_B].lo; } + phase=(long)((4294967296.0*(double)txFrequency)/122880000.0); buffer[329]=phase>>24; @@ -381,21 +418,38 @@ static void new_protocol_high_priority(int run) { buffer[345]=power&0xFF; if(isTransmitting()) { - buffer[1401]=band->OCtx; + + if(split) { + band=band_get_band(vfo[VFO_B].band); + } else { + band=band_get_band(vfo[VFO_A].band); + } + buffer[1401]=band->OCtx<<1; if(tune) { if(OCmemory_tune_time!=0) { struct timeval te; gettimeofday(&te,NULL); long long now=te.tv_sec*1000LL+te.tv_usec/1000; if(tune_timeout>now) { - buffer[1401]|=OCtune; + buffer[1401]|=OCtune<<1; } } else { - buffer[1401]|=OCtune; + buffer[1401]|=OCtune<<1; } } } else { - buffer[1401]=band->OCrx; + band=band_get_band(vfo[VFO_A].band); + buffer[1401]=band->OCrx<<1; + } + + if((protocol==ORIGINAL_PROTOCOL && device==DEVICE_METIS) || +#ifdef USBOZY + (protocol==ORIGINAL_PROTOCOL && device==DEVICE_OZY) || +#endif + (protocol==NEW_PROTOCOL && device==NEW_DEVICE_ATLAS)) { + for(r=0;rpreamp; + } } @@ -405,59 +459,41 @@ static void new_protocol_high_priority(int run) { filters=0x08000000; } -// Alex RX HPF filters -/* -if (frequency < 1800000) HPF <= 6'b100000; // bypass -else if (frequency < 6500000) HPF <= 6'b010000; // 1.5MHz HPF -else if (frequency < 9500000) HPF <= 6'b001000; // 6.5MHz HPF -else if (frequency < 13000000) HPF <= 6'b000100; // 9.5MHz HPF -else if (frequency < 20000000) HPF <= 6'b000001; // 13MHz HPF -else HPF <= 6'b000010; // 20MHz HPF -*/ - - if(ddsFrequency<1800000L) { + if(rxFrequency<1800000L) { filters|=ALEX_BYPASS_HPF; - } else if(ddsFrequency<6500000L) { + } else if(rxFrequency<6500000L) { filters|=ALEX_1_5MHZ_HPF; - } else if(ddsFrequency<9500000L) { + } else if(rxFrequency<9500000L) { filters|=ALEX_6_5MHZ_HPF; - } else if(ddsFrequency<13000000L) { + } else if(rxFrequency<13000000L) { filters|=ALEX_9_5MHZ_HPF; - } else if(ddsFrequency<20000000L) { + } else if(rxFrequency<20000000L) { filters|=ALEX_13MHZ_HPF; } else { filters|=ALEX_20MHZ_HPF; } -// Alex TX LPF filters -/* -if (frequency > 32000000) LPF <= 7'b0010000; // > 10m so use 6m LPF^M -else if (frequency > 22000000) LPF <= 7'b0100000; // > 15m so use 12/10m LPF^M -else if (frequency > 15000000) LPF <= 7'b1000000; // > 20m so use 17/15m LPF^M -else if (frequency > 8000000) LPF <= 7'b0000001; // > 40m so use 30/20m LPF ^M -else if (frequency > 4500000) LPF <= 7'b0000010; // > 80m so use 60/40m LPF^M -else if (frequency > 2400000) LPF <= 7'b0000100; // > 160m so use 80m LPF ^M -else LPF <= 7'b0001000; // < 2.4MHz so use 160m LPF^M -*/ + if(rxFrequency>30000000L) { + filters|=ALEX_6M_PREAMP; + } - if(ddsFrequency>32000000) { + if(txFrequency>32000000) { filters|=ALEX_6_BYPASS_LPF; - } else if(ddsFrequency>22000000) { + } else if(txFrequency>22000000) { filters|=ALEX_12_10_LPF; - } else if(ddsFrequency>15000000) { + } else if(txFrequency>15000000) { filters|=ALEX_17_15_LPF; - } else if(ddsFrequency>8000000) { + } else if(txFrequency>8000000) { filters|=ALEX_30_20_LPF; - } else if(ddsFrequency>4500000) { + } else if(txFrequency>4500000) { filters|=ALEX_60_40_LPF; - } else if(ddsFrequency>2400000) { + } else if(txFrequency>2400000) { filters|=ALEX_80_LPF; } else { filters|=ALEX_160_LPF; } - - switch(band->alexRxAntenna) { + switch(receiver[0]->alex_antenna) { case 0: // ANT 1 break; case 1: // ANT 2 @@ -480,7 +516,7 @@ else LPF <= 7'b0001000; // < 2.4MHz so use 160m LPF^M } if(isTransmitting()) { - switch(band->alexTxAntenna) { + switch(transmitter->alex_antenna) { case 0: // ANT 1 filters|=ALEX_TX_ANTENNA_1; break; @@ -498,7 +534,7 @@ else LPF <= 7'b0001000; // < 2.4MHz so use 160m LPF^M } } else { - switch(band->alexRxAntenna) { + switch(receiver[0]->alex_antenna) { case 0: // ANT 1 filters|=ALEX_TX_ANTENNA_1; break; @@ -511,7 +547,7 @@ else LPF <= 7'b0001000; // < 2.4MHz so use 160m LPF^M case 3: // EXT 1 case 4: // EXT 2 case 5: // XVTR - switch(band->alexTxAntenna) { + switch(transmitter->alex_antenna) { case 0: // ANT 1 filters|=ALEX_TX_ANTENNA_1; break; @@ -530,12 +566,44 @@ else LPF <= 7'b0001000; // < 2.4MHz so use 160m LPF^M buffer[1433]=(filters>>16)&0xFF; buffer[1434]=(filters>>8)&0xFF; buffer[1435]=filters&0xFF; +//fprintf(stderr,"HPF: 0: %02X %02X for %lld\n",buffer[1434],buffer[1435],rxFrequency); + + filters=0x00000000; + rxFrequency=vfo[VFO_B].frequency-vfo[VFO_B].lo; + if(rxFrequency<1800000L) { + filters|=ALEX_BYPASS_HPF; + } else if(rxFrequency<6500000L) { + filters|=ALEX_1_5MHZ_HPF; + } else if(rxFrequency<9500000L) { + filters|=ALEX_6_5MHZ_HPF; + } else if(rxFrequency<13000000L) { + filters|=ALEX_9_5MHZ_HPF; + } else if(rxFrequency<20000000L) { + filters|=ALEX_13MHZ_HPF; + } else { + filters|=ALEX_20MHZ_HPF; + } + + if(rxFrequency>30000000L) { + filters|=ALEX_6M_PREAMP; + } - //buffer[1442]=attenuation; - buffer[1443]=attenuation; -//fprintf(stderr,"high_priority[4]=0x%02X\n", buffer[4]); -//fprintf(stderr,"filters=%04X\n", filters); + buffer[1428]=(filters>>24)&0xFF; + buffer[1429]=(filters>>16)&0xFF; + buffer[1430]=(filters>>8)&0xFF; + buffer[1431]=filters&0xFF; + +//fprintf(stderr,"HPF: 1: %02X %02X for %lld\n",buffer[1430],buffer[1431],rxFrequency); +// rx_frequency + +//fprintf(stderr,"new_protocol_high_priority: OC=%02X filters=%04X for frequency=%lld\n", buffer[1401], filters, rxFrequency); + + for(r=0;rattenuation; + } if(sendto(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&high_priority_addr,high_priority_addr_length)<0) { fprintf(stderr,"sendto socket failed for high priority\n"); @@ -547,6 +615,7 @@ else LPF <= 7'b0001000; // < 2.4MHz so use 160m LPF^M static void new_protocol_transmit_specific() { unsigned char buffer[60]; + int mode; memset(buffer, 0, sizeof(buffer)); @@ -555,6 +624,11 @@ static void new_protocol_transmit_specific() { buffer[2]=tx_specific_sequence>>8; buffer[3]=tx_specific_sequence; + if(split) { + mode=vfo[1].mode; + } else { + mode=vfo[0].mode; + } buffer[4]=1; // 1 DAC buffer[5]=0; // default no CW // may be using local pihpsdr OR hpsdr CW @@ -581,10 +655,12 @@ static void new_protocol_transmit_specific() { } buffer[6]=cw_keyer_sidetone_volume; // sidetone off - buffer[7]=cw_keyer_sidetone_frequency>>8; buffer[8]=cw_keyer_sidetone_frequency; // sidetone frequency + buffer[7]=cw_keyer_sidetone_frequency>>8; + buffer[8]=cw_keyer_sidetone_frequency; // sidetone frequency buffer[9]=cw_keyer_speed; // cw keyer speed buffer[10]=cw_keyer_weight; // cw weight - buffer[11]=cw_keyer_hang_time>>8; buffer[12]=cw_keyer_hang_time; // cw hang delay + buffer[11]=cw_keyer_hang_time>>8; + buffer[12]=cw_keyer_hang_time; // cw hang delay buffer[13]=0; // rf delay buffer[50]=0; if(mic_linein) { @@ -593,15 +669,15 @@ static void new_protocol_transmit_specific() { if(mic_boost) { buffer[50]|=0x02; } - if(mic_ptt_enabled==0) { + if(mic_ptt_enabled==0) { // set if disabled buffer[50]|=0x04; } - if(mic_bias_enabled) { - buffer[50]|=0x10; - } if(mic_ptt_tip_bias_ring) { buffer[50]|=0x08; } + if(mic_bias_enabled) { + buffer[50]|=0x10; + } // 0..31 buffer[51]=linein_gain; @@ -627,34 +703,19 @@ static void new_protocol_receive_specific() { buffer[3]=rx_specific_sequence; buffer[4]=2; // 2 ADCs - buffer[5]=0; // dither off - if(lt2208Dither) { - for(i=0;idither<random<adc; + buffer[18+(r*6)]=((receiver[i]->sample_rate/1000)>>8)&0xFF; + buffer[19+(r*6)]=(receiver[i]->sample_rate/1000)&0xFF; + buffer[22+(r*6)]=24; } - buffer[18]=((sample_rate/1000)>>8)&0xFF; - buffer[19]=(sample_rate/1000)&0xFF; - buffer[22]=24; - - buffer[24]=((sample_rate/1000)>>8)&0xFF; - buffer[25]=(sample_rate/1000)&0xFF; - buffer[28]=24; if(sendto(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&receiver_addr,receiver_addr_length)<0) { fprintf(stderr,"sendto socket failed for start\n"); @@ -668,17 +729,23 @@ static void new_protocol_start() { running=1; new_protocol_transmit_specific(); new_protocol_receive_specific(); - int rc=pthread_create(&new_protocol_timer_thread_id,NULL,new_protocol_timer_thread,NULL); - if(rc != 0) { - fprintf(stderr,"pthread_create failed on new_protocol_timer_thread: %d\n", rc); - exit(-1); + new_protocol_timer_thread_id = g_thread_new( "new protocol timer", new_protocol_timer_thread, NULL); + if( ! new_protocol_timer_thread_id ) + { + fprintf(stderr,"g_thread_new failed on new_protocol_timer_thread\n"); + exit( -1 ); } + fprintf(stderr, "new_protocol_timer_thread: id=%p\n",new_protocol_timer_thread_id); + } void new_protocol_stop() { new_protocol_high_priority(0); - running=0; - sleep(1); + usleep(100000); // 100 ms +} + +void new_protocol_run() { + new_protocol_high_priority(1); } double calibrate(int v) { @@ -689,13 +756,10 @@ double calibrate(int v) { return (v1*v1)/0.095; } -void* new_protocol_thread(void* arg) { +//void* new_protocol_thread(void* arg) { +static gpointer new_protocol_thread(gpointer data) { int i; - struct sockaddr_in addr; - int length; - unsigned char buffer[2048]; - int bytesread; short sourceport; fprintf(stderr,"new_protocol_thread\n"); @@ -704,7 +768,6 @@ fprintf(stderr,"new_protocol_thread\n"); iqindex=4; -fprintf(stderr,"outputsamples=%d\n", outputsamples); data_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP); if(data_socket<0) { fprintf(stderr,"metis: create socket failed for data_socket\n"); @@ -745,7 +808,7 @@ fprintf(stderr,"outputsamples=%d\n", outputsamples); iq_addr.sin_port=htons(TX_IQ_FROM_HOST_PORT); - for(i=0;iinfo.network.address,radio->info.network.address_length); data_addr_length[i]=radio->info.network.address_length; data_addr[i].sin_port=htons(RX_IQ_TO_HOST_PORT_0+i); @@ -779,7 +842,11 @@ fprintf(stderr,"outputsamples=%d\n", outputsamples); case RX_IQ_TO_HOST_PORT_5: case RX_IQ_TO_HOST_PORT_6: case RX_IQ_TO_HOST_PORT_7: - process_iq_data(sourceport-RX_IQ_TO_HOST_PORT_0,buffer); + i=sourceport-RX_IQ_TO_HOST_PORT_0; + //if(device==NEW_DEVICE_ORION2 && i==3) { + // i=1; + //} + process_iq_data(receiver[i],buffer); break; case COMMAND_RESPONCE_TO_HOST_PORT: process_command_response(buffer); @@ -788,8 +855,8 @@ fprintf(stderr,"outputsamples=%d\n", outputsamples); process_high_priority(buffer); break; case MIC_LINE_TO_HOST_PORT: - if(!local_microphone) { - process_mic_data(buffer); + if(!transmitter->local_microphone) { + process_mic_data(buffer,bytesread); } break; default: @@ -797,19 +864,19 @@ fprintf(stderr,"outputsamples=%d\n", outputsamples); } if(running) { - sem_wait(&send_general_sem); - if(send_general==1) { - new_protocol_general(); - send_general=0; - } - sem_post(&send_general_sem); - sem_wait(&send_high_priority_sem); if(send_high_priority==1) { new_protocol_high_priority(1); send_high_priority=0; } sem_post(&send_high_priority_sem); + + sem_wait(&send_general_sem); + if(send_general==1) { + new_protocol_general(); + send_general=0; + } + sem_post(&send_general_sem); } } @@ -817,47 +884,39 @@ fprintf(stderr,"outputsamples=%d\n", outputsamples); close(data_socket); } -static void process_iq_data(int rx,unsigned char *buffer) { - long sequence; - long long timestamp; - int bitspersample; - int samplesperframe; - int b; - int leftsample; - int rightsample; - double leftsampledouble; - double rightsampledouble; - - sequence=((buffer[0]&0xFF)<<24)+((buffer[1]&0xFF)<<16)+((buffer[2]&0xFF)<<8)+(buffer[3]&0xFF); - 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); - - //if(!isTransmitting()) { - b=16; - int i; - for(i=0;iid, sequence,bitspersample,samplesperframe); + b=16; + int i; + for(i=0;i>8; - audiobuffer[audioindex++]=leftaudiosample; - audiobuffer[audioindex++]=rightaudiosample>>8; - audiobuffer[audioindex++]=rightaudiosample; - - if(audioindex>=sizeof(audiobuffer)) { - // insert the sequence - audiobuffer[0]=audiosequence>>24; - audiobuffer[1]=audiosequence>>16; - audiobuffer[2]=audiosequence>>8; - audiobuffer[3]=audiosequence; - // send the buffer - if(sendto(data_socket,audiobuffer,sizeof(audiobuffer),0,(struct sockaddr*)&audio_addr,audio_addr_length)<0) { - fprintf(stderr,"sendto socket failed for audio\n"); - exit(1); - } - audioindex=4; - audiosequence++; - } - } - } - } - freedv_samples++; - if(freedv_samples==freedv_resample) { - freedv_samples=0; - } - } +static void process_mic_data(unsigned char *buffer,int bytes) { + long sequence; + int b; + short sample; + + sequence=((buffer[0]&0xFF)<<24)+((buffer[1]&0xFF)<<16)+((buffer[2]&0xFF)<<8)+(buffer[3]&0xFF); + b=4; + int i; + for(i=0;i>8; - audiobuffer[audioindex++]=leftaudiosample; - audiobuffer[audioindex++]=rightaudiosample>>8; - audiobuffer[audioindex++]=rightaudiosample; - - if(audioindex>=sizeof(audiobuffer)) { - // insert the sequence - audiobuffer[0]=audiosequence>>24; - audiobuffer[1]=audiosequence>>16; - audiobuffer[2]=audiosequence>>8; - audiobuffer[3]=audiosequence; - // send the buffer - if(sendto(data_socket,audiobuffer,sizeof(audiobuffer),0,(struct sockaddr*)&audio_addr,audio_addr_length)<0) { - fprintf(stderr,"sendto socket failed for audio\n"); - exit(1); - } - audioindex=4; - audiosequence++; - } - } -} + // insert the samples + audiobuffer[audioindex++]=left_audio_sample>>8; + audiobuffer[audioindex++]=left_audio_sample; + audiobuffer[audioindex++]=right_audio_sample>>8; + audiobuffer[audioindex++]=right_audio_sample; + + if(audioindex>=sizeof(audiobuffer)) { -static void full_rx_buffer(int rx) { - int j; - int error; + // insert the sequence + audiobuffer[0]=audiosequence>>24; + audiobuffer[1]=audiosequence>>16; + audiobuffer[2]=audiosequence>>8; + audiobuffer[3]=audiosequence; - Spectrum0(1, CHANNEL_RX0, 0, 0, iqinputbuffer[rx]); + // send the buffer - if(rx==active_receiver) { - fexchange0(CHANNEL_RX0, iqinputbuffer[rx], audiooutputbuffer, &error); - if(error!=0) { - fprintf(stderr,"full_rx_buffer: fexchange0: error=%d\n",error); - } -/* - switch(mode) { -#ifdef PSK - case modePSK: - break; -#endif - default: - Spectrum0(1, CHANNEL_RX0, 0, 0, iqinputbuffer[rx]); - break; - } -*/ - switch(mode) { -#ifdef FREEDV - case modeFREEDV: - process_freedv_rx_buffer(); - break; -#endif - default: - process_rx_buffer(); - break; + rc=sendto(data_socket,audiobuffer,sizeof(audiobuffer),0,(struct sockaddr*)&audio_addr,audio_addr_length); + if(rc!=sizeof(audiobuffer)) { + fprintf(stderr,"sendto socket failed for %d bytes of audio: %d\n",sizeof(audiobuffer),rc); } + audioindex=4; + audiosequence++; } } -static void full_tx_buffer() { - long isample; - long qsample; - double gain=8388607.0; - int j; - int error; - - if(vox_enabled) { - switch(mode) { - case modeLSB: - case modeUSB: - case modeDSB: - case modeFMN: - case modeAM: - case modeSAM: -#ifdef FREEDV - case modeFREEDV: -#endif - update_vox(micinputbuffer,BUFFER_SIZE); - break; +void new_protocol_iq_samples(int isample,int qsample) { + iqbuffer[iqindex++]=isample>>16; + iqbuffer[iqindex++]=isample>>8; + iqbuffer[iqindex++]=isample; + iqbuffer[iqindex++]=qsample>>16; + iqbuffer[iqindex++]=qsample>>8; + iqbuffer[iqindex++]=qsample; + + if(iqindex==sizeof(iqbuffer)) { + iqbuffer[0]=tx_iq_sequence>>24; + iqbuffer[1]=tx_iq_sequence>>16; + iqbuffer[2]=tx_iq_sequence>>8; + iqbuffer[3]=tx_iq_sequence; + + // send the buffer + if(sendto(data_socket,iqbuffer,sizeof(iqbuffer),0,(struct sockaddr*)&iq_addr,iq_addr_length)<0) { + fprintf(stderr,"sendto socket failed for iq\n"); + exit(1); } + iqindex=4; + tx_iq_sequence++; } +} - fexchange0(CHANNEL_TX, micinputbuffer, iqoutputbuffer, &error); - Spectrum0(1, CHANNEL_TX, 0, 0, iqoutputbuffer); - -#ifdef FREEDV - if(mode==modeFREEDV) { - gain=8388607.0; - } -#endif - - if(radio->device==NEW_DEVICE_ATLAS && atlas_penelope) { - if(tune) { - gain=gain*tune_drive; +void new_protocol_process_local_mic(unsigned char *buffer,int le) { + int b; + short micsample; + double micsampledouble; + double gain=pow(10.0, mic_gain / 20.0); + + b=0; + int i,j,s; + for(i=0;i>16; - iqbuffer[iqindex++]=isample>>8; - iqbuffer[iqindex++]=isample; - iqbuffer[iqindex++]=qsample>>16; - iqbuffer[iqindex++]=qsample>>8; - iqbuffer[iqindex++]=qsample; - - if(iqindex>=sizeof(iqbuffer)) { - // insert the sequence - iqbuffer[0]=tx_iq_sequence>>24; - iqbuffer[1]=tx_iq_sequence>>16; - iqbuffer[2]=tx_iq_sequence>>8; - iqbuffer[3]=tx_iq_sequence; - - // send the buffer - if(sendto(data_socket,iqbuffer,sizeof(iqbuffer),0,(struct sockaddr*)&iq_addr,iq_addr_length)<0) { - fprintf(stderr,"sendto socket failed for iq\n"); - exit(1); - } - iqindex=4; - tx_iq_sequence++; - } - - } -} - -void new_protocol_process_local_mic(unsigned char *buffer,int le) { - int b; - int micsample; - double micsampledouble; - double gain=pow(10.0, mic_gain / 20.0); - -// if(isTransmitting()) { - b=0; - int i,j,s; - for(i=0;i +#include "receiver.h" + // port definitions from host #define GENERAL_REGISTERS_FROM_HOST_PORT 1024 #define PROGRAMMING_FROM_HOST_PORT 1024 @@ -43,7 +46,7 @@ #define RX_IQ_TO_HOST_PORT_6 1041 #define RX_IQ_TO_HOST_PORT_7 1042 -#define BUFFER_SIZE 1024 +//#define BUFFER_SIZE 1024 #ifdef SHORT_FRAMES #define MIC_SAMPLES 64 @@ -68,11 +71,12 @@ extern int send_high_priority; extern int send_general; */ -void schedule_high_priority(int source); +void schedule_high_priority(); void schedule_general(); void new_protocol_init(int pixels); void new_protocol_stop(); +void new_protocol_run(); void filter_board_changed(); void pa_changed(); @@ -85,5 +89,7 @@ void setTune(int state); int getTune(); int isTransmitting(); -void new_protocol_process_local_mic(unsigned char *buffer,int le); +extern void new_protocol_process_local_mic(unsigned char *buffer,int le); +extern void new_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right_audio_sample); +extern void new_protocol_iq_samples(int isample,int qsample); #endif diff --git a/noise_menu.c b/noise_menu.c index 5283759..81ff5c0 100644 --- a/noise_menu.c +++ b/noise_menu.c @@ -48,80 +48,30 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat } static void update_noise() { - SetRXAANRRun(CHANNEL_RX0, nr); - SetRXAEMNRRun(CHANNEL_RX0, nr2); - SetRXAANFRun(CHANNEL_RX0, anf); - SetRXASNBARun(CHANNEL_RX0, snb); + SetRXAANRRun(active_receiver->id, active_receiver->nr); + SetRXAEMNRRun(active_receiver->id, active_receiver->nr2); + SetRXAANFRun(active_receiver->id, active_receiver->anf); + SetRXASNBARun(active_receiver->id, active_receiver->snb); vfo_update(NULL); } -static void nr_none_cb(GtkWidget *widget, gpointer data) { - nr=0; - nr2=0; - nb=0; - nb2=0; - anf=0; - snb=0; - update_noise(); -} - static void nr_cb(GtkWidget *widget, gpointer data) { - nr=1; - nr2=0; - nb=0; - nb2=0; - anf=0; - snb=0; + active_receiver->nr=active_receiver->nr==1?0:1; update_noise(); } static void nr2_cb(GtkWidget *widget, gpointer data) { - nr=0; - nr2=1; - nb=0; - nb2=0; - anf=0; - snb=0; - update_noise(); -} - -static void nb_cb(GtkWidget *widget, gpointer data) { - nr=0; - nr2=0; - nb=1; - nb2=0; - anf=0; - snb=0; - update_noise(); -} - -static void nb2_cb(GtkWidget *widget, gpointer data) { - nr=0; - nr2=0; - nb=0; - nb2=1; - anf=0; - snb=0; + active_receiver->nr2=active_receiver->nr2==1?0:1; update_noise(); } static void anf_cb(GtkWidget *widget, gpointer data) { - nr=0; - nr2=0; - nb=0; - nb2=0; - anf=1; - snb=0; + active_receiver->anf=active_receiver->anf==1?0:1; update_noise(); } static void snb_cb(GtkWidget *widget, gpointer data) { - nr=0; - nr2=0; - nb=0; - nb2=0; - anf=0; - snb=1; + active_receiver->snb=active_receiver->snb==1?0:1; update_noise(); } @@ -155,56 +105,35 @@ void noise_menu(GtkWidget *parent) { g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL); gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1); - GtkWidget *b_nr_none=gtk_radio_button_new_with_label(NULL,"None"); - //gtk_widget_override_font(b_none, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr_none), nr_none==1); - gtk_widget_show(b_nr_none); - gtk_grid_attach(GTK_GRID(grid),b_nr_none,0,1,2,1); - g_signal_connect(b_nr_none,"pressed",G_CALLBACK(nr_none_cb),NULL); + char label[32]; + sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B"); + GtkWidget *rx_label=gtk_label_new(label); + gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1); - GtkWidget *b_nr=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_nr_none),"NR"); - //gtk_widget_override_font(b_nr, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr), nr==1); + GtkWidget *b_nr=gtk_check_button_new_with_label("NR"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr), active_receiver->nr); gtk_widget_show(b_nr); gtk_grid_attach(GTK_GRID(grid),b_nr,0,2,2,1); - g_signal_connect(b_nr,"pressed",G_CALLBACK(nr_cb),NULL); + g_signal_connect(b_nr,"toggled",G_CALLBACK(nr_cb),NULL); - GtkWidget *b_nr2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_nr),"NR2"); - //gtk_widget_override_font(b_nr2, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr2), nr2==1); + GtkWidget *b_nr2=gtk_check_button_new_with_label("NR2"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr2), active_receiver->nr2); gtk_widget_show(b_nr2); gtk_grid_attach(GTK_GRID(grid),b_nr2,0,3,2,1); - g_signal_connect(b_nr2,"pressed",G_CALLBACK(nr2_cb),NULL); - -/* - GtkWidget *b_nb=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_nr2),"NB"); - //gtk_widget_override_font(b_nb, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nb), nb==1); - gtk_widget_show(b_nb); - gtk_grid_attach(GTK_GRID(grid),b_nb,0,4,2,1); - g_signal_connect(b_nb,"pressed",G_CALLBACK(nb_cb),NULL); - - GtkWidget *b_nb2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_nb),"NB2"); - //gtk_widget_override_font(b_nb2, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nb2), nb2==1); - gtk_widget_show(b_nb2); - gtk_grid_attach(GTK_GRID(grid),b_nb2,0,5,2,1); - g_signal_connect(b_nb2,"pressed",G_CALLBACK(nb2_cb),NULL); -*/ + g_signal_connect(b_nr2,"toggled",G_CALLBACK(nr2_cb),NULL); - GtkWidget *b_anf=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_nr2),"ANF"); - //gtk_widget_override_font(b_anf, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_anf), anf==1); + GtkWidget *b_anf=gtk_check_button_new_with_label("ANF"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_anf), active_receiver->anf); gtk_widget_show(b_anf); gtk_grid_attach(GTK_GRID(grid),b_anf,0,4,2,1); - g_signal_connect(b_anf,"pressed",G_CALLBACK(anf_cb),NULL); + g_signal_connect(b_anf,"toggled",G_CALLBACK(anf_cb),NULL); - GtkWidget *b_snb=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_anf),"SNB"); + GtkWidget *b_snb=gtk_check_button_new_with_label("SNB"); //gtk_widget_override_font(b_snb, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_snb), snb==1); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_snb), active_receiver->snb); gtk_widget_show(b_snb); gtk_grid_attach(GTK_GRID(grid),b_snb,0,5,2,1); - g_signal_connect(b_snb,"pressed",G_CALLBACK(snb_cb),NULL); + g_signal_connect(b_snb,"toggled",G_CALLBACK(snb_cb),NULL); gtk_container_add(GTK_CONTAINER(content),grid); diff --git a/oc_menu.c b/oc_menu.c index b85aa38..73fc567 100644 --- a/oc_menu.c +++ b/oc_menu.c @@ -48,29 +48,41 @@ static void oc_rx_cb(GtkWidget *widget, gpointer data) { int b=((int)data)>>4; int oc=((int)data)&0xF; BAND *band=band_get_band(b); - int mask=0x01<OCrx|=mask; } else { band->OCrx&=~mask; } + + if(protocol==NEW_PROTOCOL) { + schedule_high_priority(); + } } static void oc_tx_cb(GtkWidget *widget, gpointer data) { int b=((int)data)>>4; int oc=((int)data)&0xF; BAND *band=band_get_band(b); - int mask=0x01<OCtx|=mask; } else { band->OCtx&=~mask; } + if(protocol==NEW_PROTOCOL) { + schedule_high_priority(); + } } static void oc_tune_cb(GtkWidget *widget, gpointer data) { int oc=((int)data)&0xF; - int mask=0x01<OCrx&mask)==mask); @@ -184,7 +196,7 @@ void oc_menu(GtkWidget *parent) { gtk_widget_show(oc_tune_title); gtk_grid_attach(GTK_GRID(grid),oc_tune_title,18,j+1,1,1); - mask=0x01< #include #include #include @@ -44,8 +45,10 @@ static int interface_length; static int discovery_socket; static struct sockaddr_in discovery_addr; -static pthread_t discover_thread_id; -static void* discover_receive_thread(void* arg); +//static pthread_t discover_thread_id; +//static void* discover_receive_thread(void* arg); +static GThread *discover_thread_id; +static gpointer discover_receive_thread(gpointer data); static void discover(struct ifaddrs* iface) { int rc; @@ -96,11 +99,20 @@ static void discover(struct ifaddrs* iface) { to_addr.sin_addr.s_addr=htonl(INADDR_BROADCAST); // start a receive thread to collect discovery response packets +/* rc=pthread_create(&discover_thread_id,NULL,discover_receive_thread,NULL); if(rc != 0) { fprintf(stderr,"pthread_create failed on discover_receive_thread: rc=%d\n", rc); exit(-1); } +*/ + discover_thread_id = g_thread_new( "old discover receive", discover_receive_thread, NULL); + if( ! discover_thread_id ) + { + fprintf(stderr,"g_thread_new failed on discover_receive_thread\n"); + exit( -1 ); + } + // send discovery packet @@ -119,8 +131,11 @@ static void discover(struct ifaddrs* iface) { } // wait for receive thread to complete +/* void* status; pthread_join(discover_thread_id,&status); +*/ + g_thread_join(discover_thread_id); close(discovery_socket); @@ -128,7 +143,8 @@ static void discover(struct ifaddrs* iface) { } -static void* discover_receive_thread(void* arg) { +//static void *discover_receive_thread(void* arg) { +static gpointer discover_receive_thread(gpointer data) { struct sockaddr_in addr; int len; unsigned char buffer[2048]; @@ -177,6 +193,9 @@ fprintf(stderr,"discover_receive_thread\n"); case DEVICE_HERMES_LITE: strcpy(discovered[devices].name,"Hermes Lite"); break; + case DEVICE_ORION2: + strcpy(discovered[devices].name,"Orion 2"); + break; default: strcpy(discovered[devices].name,"Unknown"); break; @@ -211,7 +230,8 @@ fprintf(stderr,"discover_receive_thread\n"); } fprintf(stderr,"discovery: exiting discover_receive_thread\n"); - pthread_exit(NULL); + //pthread_exit(NULL); + g_thread_exit(NULL); } void old_discovery() { diff --git a/old_protocol.c b/old_protocol.c index 58cbd41..bccd042 100644 --- a/old_protocol.c +++ b/old_protocol.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -45,8 +44,11 @@ #include "filter.h" #include "old_protocol.h" #include "radio.h" +#include "receiver.h" +#include "transmitter.h" #include "signal.h" #include "toolbar.h" +#include "vfo.h" #ifdef FREEDV #include "freedv.h" #endif @@ -70,7 +72,7 @@ #define SYNC 0x7F #define OZY_BUFFER_SIZE 512 -#define OUTPUT_BUFFER_SIZE 1024 +//#define OUTPUT_BUFFER_SIZE 1024 // ozy command and control #define MOX_DISABLED 0x00 @@ -104,9 +106,8 @@ #define LT2208_RANDOM_OFF 0x00 #define LT2208_RANDOM_ON 0x10 -static int buffer_size=BUFFER_SIZE; +//static int buffer_size=BUFFER_SIZE; -static int receiver; static int display_width; static int speed; @@ -128,8 +129,11 @@ static double phase=0.0; static int running; static long ep4_sequence; +static int current_rx=0; + static int samples=0; static int mic_samples=0; +static int mic_sample_divisor=1; #ifdef FREEDV static int freedv_samples=0; static int freedv_divisor=6; @@ -141,22 +145,22 @@ static int psk_divisor=6; //static float left_input_buffer[BUFFER_SIZE]; //static float right_input_buffer[BUFFER_SIZE]; -static double iqinputbuffer[RECEIVERS][BUFFER_SIZE*2]; +//static double iqinputbuffer[MAX_RECEIVERS][MAX_BUFFER_SIZE*2]; -//static float mic_left_buffer[BUFFER_SIZE]; -//static float mic_right_buffer[BUFFER_SIZE]; -static double micinputbuffer[BUFFER_SIZE*2]; +//static float mic_left_buffer[MAX_BUFFER_SIZE]; +//static float mic_right_buffer[MAX_BUFFER_SIZE]; +static double micinputbuffer[MAX_BUFFER_SIZE*2]; //static float left_output_buffer[OUTPUT_BUFFER_SIZE]; //static float right_output_buffer[OUTPUT_BUFFER_SIZE]; -static double audiooutputbuffer[BUFFER_SIZE*2]; +//static double audiooutputbuffer[MAX_BUFFER_SIZE*2]; //static float left_subrx_output_buffer[OUTPUT_BUFFER_SIZE]; //static float right_subrx_output_buffer[OUTPUT_BUFFER_SIZE]; //static float left_tx_buffer[OUTPUT_BUFFER_SIZE]; //static float right_tx_buffer[OUTPUT_BUFFER_SIZE]; -static double iqoutputbuffer[BUFFER_SIZE*2]; +//static double iqoutputbuffer[MAX_BUFFER_SIZE*2]; static int left_rx_sample; static int right_rx_sample; @@ -168,9 +172,9 @@ static int output_buffer_index=8; static int command=0; -static pthread_t receive_thread_id; +static GThread *receive_thread_id; static void start_receive_thread(); -static void *receive_thread(void* arg); +static gpointer receive_thread(gpointer arg); static void process_ozy_input_buffer(char *buffer); static void process_bandscope_buffer(char *buffer); void ozy_send_buffer(); @@ -183,78 +187,76 @@ static int frequencyChanged=0; static sem_t frequency_changed_sem; static int metis_write(unsigned char ep,char* buffer,int length); -static void metis_restart(); static void metis_start_stop(int command); static void metis_send_buffer(char* buffer,int length); -static void full_rx_buffer(); -static void full_tx_buffer(); +static void metis_restart(); + +#define COMMON_MERCURY_FREQUENCY 0x80 +#define PENELOPE_MIC 0x80 + +#ifdef USBOZY +// +// additional defines if we include USB Ozy support +// +#include "ozyio.h" + +static GThread *ozy_EP4_rx_thread_id; +static GThread *ozy_EP6_rx_thread_id; +static gpointer ozy_ep4_rx_thread(gpointer arg); +static gpointer ozy_ep6_rx_thread(gpointer arg); +static void start_usb_receive_threads(); +static int ozyusb_write(char* buffer,int length); +#define EP6_IN_ID 0x86 // end point = 6, direction toward PC +#define EP2_OUT_ID 0x02 // end point = 2, direction from PC +#define EP6_BUFFER_SIZE 2048 +static unsigned char usb_output_buffer[EP6_BUFFER_SIZE]; +static unsigned char ep6_inbuffer[EP6_BUFFER_SIZE]; +static unsigned char usb_buffer_block = 0; +#endif void schedule_frequency_changed() { -//fprintf(stderr,"old_protocol: schedule_frequency_changed\n"); - //sem_wait(&frequency_changed_sem); frequencyChanged=1; - //sem_post(&frequency_changed_sem); } void old_protocol_stop() { metis_start_stop(0); - running=FALSE; } -void old_protocol_calc_buffers() { - switch(sample_rate) { - case 48000: - output_buffer_size=OUTPUT_BUFFER_SIZE; - break; - case 96000: - output_buffer_size=OUTPUT_BUFFER_SIZE/2; - break; - case 192000: - output_buffer_size=OUTPUT_BUFFER_SIZE/4; - break; - case 384000: - output_buffer_size=OUTPUT_BUFFER_SIZE/8; - break; - default: - fprintf(stderr,"Invalid sample rate: %d. Defaulting to 48K.\n",sample_rate); - break; - } +void old_protocol_run() { + metis_restart(); } -void old_protocol_new_sample_rate(int rate) { - metis_start_stop(0); - sample_rate=rate; - old_protocol_calc_buffers(); - wdsp_new_sample_rate(rate); - metis_restart(); +void old_protocol_set_mic_sample_rate(int rate) { + mic_sample_divisor=rate/48000; } -void old_protocol_init(int rx,int pixels) { +void old_protocol_init(int rx,int pixels,int rate) { int i; fprintf(stderr,"old_protocol_init\n"); - //int result=sem_init(&frequency_changed_sem, 0, 1); - - if(local_audio) { - if(audio_open_output()!=0) { - fprintf(stderr,"audio_open_output failed\n"); - local_audio=0; - } - } + old_protocol_set_mic_sample_rate(rate); - if(local_microphone) { + if(transmitter->local_microphone) { if(audio_open_input()!=0) { fprintf(stderr,"audio_open_input failed\n"); - local_microphone=0; + transmitter->local_microphone=0; } } - receiver=rx; display_width=pixels; - old_protocol_calc_buffers(); - +#ifdef USBOZY +// +// if we have a USB interfaced Ozy device: +// + if (device == DEVICE_OZY) { + fprintf(stderr,"old_protocol_init: initialise ozy on USB\n"); + ozy_initialise(); + start_usb_receive_threads(); + } + else +#endif start_receive_thread(); fprintf(stderr,"old_protocol_init: prime radio\n"); @@ -266,6 +268,73 @@ void old_protocol_init(int rx,int pixels) { } +#ifdef USBOZY +// +// starts the threads for USB receive +// EP4 is the bandscope endpoint (not yet used) +// EP6 is the "normal" USB frame endpoint +// +static void start_usb_receive_threads() +{ + int rc; + + fprintf(stderr,"old_protocol starting USB receive thread: buffer_size=%d\n",buffer_size); + + ozy_EP6_rx_thread_id = g_thread_new( "OZY EP6 RX", ozy_ep6_rx_thread, NULL); + if( ! ozy_EP6_rx_thread_id ) + { + fprintf(stderr,"g_thread_new failed for ozy_ep6_rx_thread\n"); + exit( -1 ); + } +} + +// +// receive threat for USB EP4 (bandscope) not currently used. +// +static gpointer ozy_ep4_rx_thread(gpointer arg) +{ +} + +// +// receive threat for USB EP6 (512 byte USB Ozy frames) +// this function loops reading 4 frames at a time through USB +// then processes them one at a time. +// +static gpointer ozy_ep6_rx_thread(gpointer arg) { + int bytes; + unsigned char buffer[2048]; + + fprintf(stderr, "old_protocol: USB EP6 receive_thread\n"); + running=1; + + while (running) + { + bytes = ozy_read(EP6_IN_ID,ep6_inbuffer,EP6_BUFFER_SIZE); // read a 2K buffer at a time + + if (bytes == 0) + { + fprintf(stderr,"old_protocol_ep6_read: ozy_read returned 0 bytes... retrying\n"); + continue; + } + else if (bytes != EP6_BUFFER_SIZE) + { + fprintf(stderr,"old_protocol_ep6_read: OzyBulkRead failed %d bytes\n",bytes); + perror("ozy_read(EP6 read failed"); + //exit(1); + } + else +// process the received data normally + { + process_ozy_input_buffer(&ep6_inbuffer[0]); + process_ozy_input_buffer(&ep6_inbuffer[512]); + process_ozy_input_buffer(&ep6_inbuffer[1024]); + process_ozy_input_buffer(&ep6_inbuffer[1024+512]); + } + + } +} +#endif + static void start_receive_thread() { int i; int rc; @@ -273,34 +342,44 @@ static void start_receive_thread() { fprintf(stderr,"old_protocol starting receive thread: buffer_size=%d output_buffer_size=%d\n",buffer_size,output_buffer_size); - data_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP); - if(data_socket<0) { - perror("old_protocol: create socket failed for data_socket\n"); - exit(-1); - } + switch(device) { +#ifdef USBOZY + case DEVICE_OZY: + break; +#endif + default: + data_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP); + if(data_socket<0) { + perror("old_protocol: create socket failed for data_socket\n"); + exit(-1); + } - int optval = 1; - setsockopt(data_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); + int optval = 1; + setsockopt(data_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); - // bind to the interface - if(bind(data_socket,(struct sockaddr*)&radio->info.network.interface_address,radio->info.network.interface_length)<0) { - perror("old_protocol: bind socket failed for data_socket\n"); - exit(-1); - } + // bind to the interface + if(bind(data_socket,(struct sockaddr*)&radio->info.network.interface_address,radio->info.network.interface_length)<0) { + perror("old_protocol: bind socket failed for data_socket\n"); + exit(-1); + } - memcpy(&data_addr,&radio->info.network.address,radio->info.network.address_length); - data_addr_length=radio->info.network.address_length; - data_addr.sin_port=htons(DATA_PORT); + memcpy(&data_addr,&radio->info.network.address,radio->info.network.address_length); + data_addr_length=radio->info.network.address_length; + data_addr.sin_port=htons(DATA_PORT); + break; + } - rc=pthread_create(&receive_thread_id,NULL,receive_thread,NULL); - if(rc != 0) { - fprintf(stderr,"old_protocol: pthread_create failed on receive_thread: rc=%d\n", rc); - exit(-1); + receive_thread_id = g_thread_new( "old protocol", receive_thread, NULL); + if( ! receive_thread_id ) + { + fprintf(stderr,"g_thread_new failed on receive_thread\n"); + exit( -1 ); } + fprintf(stderr, "receive_thread: id=%p\n",receive_thread_id); } -static void *receive_thread(void* arg) { +static gpointer receive_thread(gpointer arg) { struct sockaddr_in addr; int length; unsigned char buffer[2048]; @@ -313,56 +392,67 @@ static void *receive_thread(void* arg) { length=sizeof(addr); while(running) { - bytes_read=recvfrom(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&addr,&length); - if(bytes_read<0) { - perror("recvfrom socket failed for old_protocol: receive_thread"); - exit(1); - } - if(buffer[0]==0xEF && buffer[1]==0xFE) { - switch(buffer[2]) { - case 1: - // get the end point - ep=buffer[3]&0xFF; + switch(device) { +#ifdef USBOZY + case DEVICE_OZY: + // should not happen + break; +#endif - // get the sequence number - sequence=((buffer[4]&0xFF)<<24)+((buffer[5]&0xFF)<<16)+((buffer[6]&0xFF)<<8)+(buffer[7]&0xFF); + default: + bytes_read=recvfrom(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&addr,&length); + if(bytes_read<0) { + perror("recvfrom socket failed for old_protocol: receive_thread"); + exit(1); + } - switch(ep) { - case 6: // EP6 - // process the data - process_ozy_input_buffer(&buffer[8]); - process_ozy_input_buffer(&buffer[520]); - break; - case 4: // EP4 + if(buffer[0]==0xEF && buffer[1]==0xFE) { + switch(buffer[2]) { + case 1: + // get the end point + ep=buffer[3]&0xFF; + + // get the sequence number + sequence=((buffer[4]&0xFF)<<24)+((buffer[5]&0xFF)<<16)+((buffer[6]&0xFF)<<8)+(buffer[7]&0xFF); + + switch(ep) { + case 6: // EP6 + // process the data + process_ozy_input_buffer(&buffer[8]); + process_ozy_input_buffer(&buffer[520]); + break; + case 4: // EP4 /* - ep4_sequence++; - if(sequence!=ep4_sequence) { - ep4_sequence=sequence; - } else { - int seq=(int)(sequence%32L); - if((sequence%32L)==0L) { - reset_bandscope_buffer_index(); - } - process_bandscope_buffer(&buffer[8]); - process_bandscope_buffer(&buffer[520]); - } + ep4_sequence++; + if(sequence!=ep4_sequence) { + ep4_sequence=sequence; + } else { + int seq=(int)(sequence%32L); + if((sequence%32L)==0L) { + reset_bandscope_buffer_index(); + } + process_bandscope_buffer(&buffer[8]); + process_bandscope_buffer(&buffer[520]); + } */ + break; + default: + fprintf(stderr,"unexpected EP %d length=%d\n",ep,bytes_read); + break; + } + break; + case 2: // response to a discovery packet + fprintf(stderr,"unexepected discovery response when not in discovery mode\n"); break; default: - fprintf(stderr,"unexpected EP %d length=%d\n",ep,bytes_read); + fprintf(stderr,"unexpected packet type: 0x%02X\n",buffer[2]); break; } - break; - case 2: // response to a discovery packet - fprintf(stderr,"unexepected discovery response when not in discovery mode\n"); - break; - default: - fprintf(stderr,"unexpected packet type: 0x%02X\n",buffer[2]); - break; - } - } else { - fprintf(stderr,"received bad header bytes on data port %02X,%02X\n",buffer[0],buffer[1]); + } else { + fprintf(stderr,"received bad header bytes on data port %02X,%02X\n",buffer[0],buffer[1]); + } + break; } } } @@ -378,9 +468,9 @@ static void process_ozy_input_buffer(char *buffer) { int last_dash; int left_sample; int right_sample; - int mic_sample; - double left_sample_double[RECEIVERS]; - double right_sample_double[RECEIVERS]; + short mic_sample; + double left_sample_double; + double right_sample_double; double mic_sample_double; double gain=pow(10.0, mic_gain / 20.0); @@ -437,84 +527,29 @@ static void process_ozy_input_buffer(char *buffer) { } - int iq_samples = (512 -8) / ((RECEIVERS*6)+2); + int iq_samples=(512-8)/((RECEIVERS*6)+2); for(i=0;ilocal_microphone) { + mic_samples++; + if(mic_samples>=mic_sample_divisor) { // reduce to 48000 + add_mic_sample(transmitter,mic_sample); + mic_samples=0; } } } @@ -533,84 +568,16 @@ static void process_ozy_input_buffer(char *buffer) { } } -#ifdef FREEDV -static void process_freedv_rx_buffer() { - int j; - - int demod_samples; - for(j=0;j>8; - output_buffer[output_buffer_index++]=left_rx_sample; - output_buffer[output_buffer_index++]=right_rx_sample>>8; - output_buffer[output_buffer_index++]=right_rx_sample; - left_tx_sample=right_tx_sample=0; - output_buffer[output_buffer_index++]=left_tx_sample>>8; - output_buffer[output_buffer_index++]=left_tx_sample; - output_buffer[output_buffer_index++]=right_tx_sample>>8; - output_buffer[output_buffer_index++]=right_tx_sample; - if(output_buffer_index>=OZY_BUFFER_SIZE) { - ozy_send_buffer(); - output_buffer_index=8; - } - } - } - } - } - freedv_samples++; - if(freedv_samples==freedv_divisor) { - freedv_samples=0; - } - } -} -#endif - -static void process_rx_buffer() { - int j; - - for(j=0;j>8; - output_buffer[output_buffer_index++]=left_rx_sample; - output_buffer[output_buffer_index++]=right_rx_sample>>8; - output_buffer[output_buffer_index++]=right_rx_sample; - output_buffer[output_buffer_index++]=left_tx_sample>>8; - output_buffer[output_buffer_index++]=left_tx_sample; - output_buffer[output_buffer_index++]=right_tx_sample>>8; - output_buffer[output_buffer_index++]=right_tx_sample; +void old_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right_audio_sample) { + if(!isTransmitting()) { + output_buffer[output_buffer_index++]=left_audio_sample>>8; + output_buffer[output_buffer_index++]=left_audio_sample; + output_buffer[output_buffer_index++]=right_audio_sample>>8; + output_buffer[output_buffer_index++]=right_audio_sample; + output_buffer[output_buffer_index++]=0; + output_buffer[output_buffer_index++]=0; + output_buffer[output_buffer_index++]=0; + output_buffer[output_buffer_index++]=0; if(output_buffer_index>=OZY_BUFFER_SIZE) { ozy_send_buffer(); output_buffer_index=8; @@ -618,164 +585,38 @@ static void process_rx_buffer() { } } -static void full_rx_buffer() { - int j; - int error; - - if(vox_enabled && !local_microphone) { - switch(mode) { - case modeLSB: - case modeUSB: - case modeDSB: - case modeFMN: - case modeAM: - case modeSAM: -#ifdef FREEDV - case modeFREEDV: -#endif - update_vox(micinputbuffer,BUFFER_SIZE); - break; - } - } - - if(diversity_enabled) { - double *pin[2]; - pin[0]=iqinputbuffer[0]; - pin[1]=iqinputbuffer[1]; - - xdivEXT(0,BUFFER_SIZE,pin,iqinputbuffer[0]); - } - - fexchange0(CHANNEL_RX0, iqinputbuffer[0], audiooutputbuffer, &error); - -#ifdef PSK - if(mode!=modePSK) { -#endif - Spectrum0(1, CHANNEL_RX0, 0, 0, iqinputbuffer[0]); -#ifdef PSK - } -#endif - -#ifdef FREEDV - if(mode==modeFREEDV) { - process_freedv_rx_buffer(); - return; - } -#endif - process_rx_buffer(); -} - -static void full_tx_buffer() { - int j; - int error; - double gain=32767.0; // 2^16-1 - - if(vox_enabled && (vox || local_microphone)) { - update_vox(micinputbuffer,BUFFER_SIZE); - } - +void old_protocol_iq_samples(int isample,int qsample) { if(isTransmitting()) { - fexchange0(CHANNEL_TX, micinputbuffer, iqoutputbuffer, &error); - if(error!=0) { - fprintf(stderr,"full_tx_buffer: fexchange0: error=%d\n",error); - } - Spectrum0(1, CHANNEL_TX, 0, 0, iqoutputbuffer); - - if(radio->device==DEVICE_METIS && atlas_penelope) { - if(tune) { - gain=gain*tune_drive; - } else { - gain=gain*drive; - } - } - for(j=0;j>8; - output_buffer[output_buffer_index++]=left_tx_sample; - output_buffer[output_buffer_index++]=right_tx_sample>>8; - output_buffer[output_buffer_index++]=right_tx_sample; - if(output_buffer_index>=OZY_BUFFER_SIZE) { - ozy_send_buffer(); - output_buffer_index=8; - } + output_buffer[output_buffer_index++]=0; + output_buffer[output_buffer_index++]=0; + output_buffer[output_buffer_index++]=0; + output_buffer[output_buffer_index++]=0; + output_buffer[output_buffer_index++]=isample>>8; + output_buffer[output_buffer_index++]=isample; + output_buffer[output_buffer_index++]=qsample>>8; + output_buffer[output_buffer_index++]=qsample; + if(output_buffer_index>=OZY_BUFFER_SIZE) { + ozy_send_buffer(); + output_buffer_index=8; } } } + void old_protocol_process_local_mic(unsigned char *buffer,int le) { int b; - int mic_sample; - double mic_sample_double; - double gain=pow(10.0, mic_gain / 20.0); - - //if(isTransmitting()) { - b=0; - int i,j,s; - for(i=0;i<720;i++) { - if(le) { - mic_sample = (int)((unsigned char)buffer[b++] & 0xFF); - mic_sample |= (int)((signed char) buffer[b++]) << 8; - } else { - mic_sample = (int)((signed char) buffer[b++]) << 8; - mic_sample |= (int)((unsigned char)buffer[b++] & 0xFF); - } - mic_sample_double=(1.0 / 2147483648.0) * (double)(mic_sample<<16); -#ifdef FREEDV - if(mode==modeFREEDV && !tune) { - if(freedv_samples==0) { // 48K to 8K - int modem_samples=mod_sample_freedv(mic_sample*gain); - if(modem_samples!=0) { - for(s=0;ssample_rate) { case 48000: output_buffer[C1]|=SPEED_48K; break; @@ -814,46 +657,62 @@ void ozy_send_buffer() { output_buffer[C1]|=SPEED_384K; break; } - if(radio->device==DEVICE_METIS) { + +// set more bits for Atlas based device +// CONFIG_BOTH seems to be critical to getting ozy to respond +#ifdef USBOZY + if ((device == DEVICE_OZY) || (device == DEVICE_METIS)) +#else + if (device == DEVICE_METIS) +#endif + { + if (atlas_mic_source) + output_buffer[C1] |= PENELOPE_MIC; + output_buffer[C1] |= CONFIG_BOTH; + if (atlas_clock_source_128mhz) + output_buffer[C1] |= MERCURY_122_88MHZ_SOURCE; + output_buffer[C1] |= ((atlas_clock_source_10mhz & 3) << 2); } output_buffer[C2]=0x00; if(classE) { output_buffer[C2]|=0x01; } + band=band_get_band(vfo[VFO_A].band); if(isTransmitting()) { - output_buffer[C2]|=band->OCtx; + if(split) { + band=band_get_band(vfo[VFO_B].band); + } + output_buffer[C2]|=band->OCtx<<1; if(tune) { if(OCmemory_tune_time!=0) { struct timeval te; gettimeofday(&te,NULL); long long now=te.tv_sec*1000LL+te.tv_usec/1000; if(tune_timeout>now) { - output_buffer[C2]|=OCtune; + output_buffer[C2]|=OCtune<<1; } } else { - output_buffer[C2]|=OCtune; + output_buffer[C2]|=OCtune<<1; } } } else { - output_buffer[C2]|=band->OCrx; + output_buffer[C2]|=band->OCrx<<1; } // TODO - add Alex Attenuation and Alex Antenna output_buffer[C3]=0x00; - if(rx_random) { + if(active_receiver->random) { output_buffer[C3]|=LT2208_RANDOM_ON; } - if(rx_dither) { + if(active_receiver->dither) { output_buffer[C3]|=LT2208_DITHER_ON; } -/* - if(rx_preamp) { + if(active_receiver->preamp) { output_buffer[C3]|=LT2208_GAIN_ON; } -*/ - switch(band->alexRxAntenna) { + switch(receiver[0]->alex_antenna) { case 0: // ANT 1 break; case 1: // ANT 2 @@ -872,8 +731,6 @@ void ozy_send_buffer() { output_buffer[C3]|=0xE0; break; default: - // invalid - set to 0 - band->alexRxAntenna=0; break; } @@ -883,7 +740,7 @@ void ozy_send_buffer() { output_buffer[C4]|=(RECEIVERS-1)<<3; if(isTransmitting()) { - switch(band->alexTxAntenna) { + switch(transmitter->alex_antenna) { case 0: // ANT 1 output_buffer[C4]|=0x00; break; @@ -894,12 +751,10 @@ void ozy_send_buffer() { output_buffer[C4]|=0x02; break; default: - // invalid - set to 0 - band->alexRxAntenna=0; break; } } else { - switch(band->alexRxAntenna) { + switch(receiver[0]->alex_antenna) { case 0: // ANT 1 output_buffer[C4]|=0x00; break; @@ -912,7 +767,7 @@ void ozy_send_buffer() { case 3: // EXT 1 case 4: // EXT 2 case 5: // XVTR - switch(band->alexTxAntenna) { + switch(transmitter->alex_antenna) { case 0: // ANT 1 output_buffer[C4]|=0x00; break; @@ -930,9 +785,11 @@ void ozy_send_buffer() { break; case 1: // tx frequency output_buffer[C0]=0x02; - long long txFrequency=ddsFrequency; - if(ctun) { - txFrequency+=ddsOffset; + long long txFrequency; + if(split) { + txFrequency=vfo[VFO_B].frequency-vfo[VFO_A].lo+vfo[VFO_B].offset; + } else { + txFrequency=vfo[VFO_A].frequency-vfo[VFO_B].lo+vfo[VFO_A].offset; } output_buffer[C1]=txFrequency>>24; output_buffer[C2]=txFrequency>>16; @@ -940,19 +797,22 @@ void ozy_send_buffer() { output_buffer[C4]=txFrequency; break; case 2: // rx frequency - output_buffer[C0]=0x04+(current_rx*2); - long long rxFrequency=ddsFrequency+(long long)rit; - if(mode==modeCWU) { - rxFrequency-=(long long)cw_keyer_sidetone_frequency; - } else if(mode==modeCWL) { - rxFrequency+=(long long)cw_keyer_sidetone_frequency; + if(current_rxid; + long long rxFrequency=vfo[v].frequency+vfo[v].rit; + if(vfo[active_receiver->id].mode==modeCWU) { + rxFrequency-=(long long)cw_keyer_sidetone_frequency; + } else if(vfo[active_receiver->id].mode==modeCWL) { + rxFrequency+=(long long)cw_keyer_sidetone_frequency; + } + output_buffer[C1]=rxFrequency>>24; + output_buffer[C2]=rxFrequency>>16; + output_buffer[C3]=rxFrequency>>8; + output_buffer[C4]=rxFrequency; + current_rx++; } - output_buffer[C1]=rxFrequency>>24; - output_buffer[C2]=rxFrequency>>16; - output_buffer[C3]=rxFrequency>>8; - output_buffer[C4]=rxFrequency; - current_rx++; - if(current_rx==RECEIVERS) { + if(current_rx>=receivers) { current_rx=0; } break; @@ -996,6 +856,9 @@ void ozy_send_buffer() { case 4: output_buffer[C0]=0x14; output_buffer[C1]=0x00; + for(i=0;ipreamp<device==DEVICE_HERMES || radio->device==DEVICE_ANGELIA || radio->device==DEVICE_ORION) { - output_buffer[C4]=0x20|attenuation; + if(radio->device==DEVICE_HERMES || radio->device==DEVICE_ANGELIA || radio->device==DEVICE_ORION || radio->device==DEVICE_ORION2) { + output_buffer[C4]=0x20|receiver[0]->attenuation; } else { output_buffer[C4]=0x00; } @@ -1018,6 +881,11 @@ void ozy_send_buffer() { // 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|receiver[1]->attenuation; + } + } output_buffer[C2]=0x00; if(cw_keys_reversed!=0) { output_buffer[C2]|=0x40; @@ -1035,6 +903,11 @@ void ozy_send_buffer() { break; case 7: output_buffer[C0]=0x1E; + if(split) { + mode=vfo[1].mode; + } else { + mode=vfo[0].mode; + } if(mode!=modeCWU && mode!=modeCWL) { // output_buffer[C1]|=0x00; } else { @@ -1075,6 +948,14 @@ void ozy_send_buffer() { } } +#ifdef USBOZY +// +// if we have a USB interfaced Ozy device: +// + if (device == DEVICE_OZY) + ozyusb_write(output_buffer,OZY_BUFFER_SIZE); + else +#endif metis_write(0x02,output_buffer,OZY_BUFFER_SIZE); command++; @@ -1086,6 +967,41 @@ void ozy_send_buffer() { // output_buffer[C0],output_buffer[C1],output_buffer[C2],output_buffer[C3],output_buffer[C4]); } +#ifdef USBOZY +static int ozyusb_write(char* buffer,int length) +{ + int i; + +// batch up 4 USB frames (2048 bytes) then do a USB write + switch(usb_buffer_block++) + { + case 0: + default: + memcpy(usb_output_buffer, buffer, length); + break; + + case 1: + memcpy(usb_output_buffer + 512, buffer, length); + break; + + case 2: + memcpy(usb_output_buffer + 1024, buffer, length); + break; + + case 3: + memcpy(usb_output_buffer + 1024 + 512, buffer, length); + usb_buffer_block = 0; // reset counter +// and write the 4 usb frames to the usb in one 2k packet + i = ozy_write(EP2_OUT_ID,usb_output_buffer,EP6_BUFFER_SIZE); + if(i != EP6_BUFFER_SIZE) + { + perror("old_protocol: OzyWrite ozy failed"); + } + break; + } +} +#endif + static int metis_write(unsigned char ep,char* buffer,int length) { int i; @@ -1107,6 +1023,7 @@ static int metis_write(unsigned char ep,char* buffer,int length) { metis_buffer[6]=(send_sequence>>8)&0xFF; metis_buffer[7]=(send_sequence)&0xFF; + // send the buffer metis_send_buffer(&metis_buffer[0],1032); metis_offset=8; @@ -1135,6 +1052,11 @@ static void metis_start_stop(int command) { int i; unsigned char buffer[64]; +#ifdef USBOZY + if(device!=DEVICE_OZY) + { +#endif + buffer[0]=0xEF; buffer[1]=0xFE; buffer[2]=0x04; // start/stop command @@ -1145,6 +1067,9 @@ static void metis_start_stop(int command) { } metis_send_buffer(buffer,sizeof(buffer)); +#ifdef USBOZY + } +#endif } static void metis_send_buffer(char* buffer,int length) { diff --git a/old_protocol.h b/old_protocol.h index c38f554..45107ee 100644 --- a/old_protocol.h +++ b/old_protocol.h @@ -20,11 +20,14 @@ #ifndef _OLD_PROTOCOL_H #define _OLD_PROTOCOL_H -#define BUFFER_SIZE 1024 -void old_protocol_stop(); -void old_protocol_init(int rx,int pixels); -void old_protocol_new_sample_rate(int rate); -void schedule_frequency_changed(); -void old_protocol_process_local_mic(unsigned char *buffer,int le); +extern void old_protocol_stop(); +extern void old_protocol_run(); +extern void old_protocol_init(int rx,int pixels,int rate); +extern void old_protocol_set_mic_sample_rate(int rate); + +extern void schedule_frequency_changed(); +extern void old_protocol_process_local_mic(unsigned char *buffer,int le); +extern void old_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right_audio_sample); +extern void old_protocol_iq_samples(int isample,int qsample); #endif diff --git a/ozyio.c b/ozyio.c new file mode 100644 index 0000000..c71121e --- /dev/null +++ b/ozyio.c @@ -0,0 +1,707 @@ +/** +* @file ozyio.c +* @brief USB I/O with Ozy +* @author John Melton, G0ORX/N6LYT +* @version 0.1 +* @date 2009-10-13 +*/ + + +/* Copyright (C) +* 2009 - John Melton, G0ORX/N6LYT +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +/* +* modified by Bob Wisdom VK4YA May 2015 to create ozymetis +* modified further Laurence Barker G8NJJ to add USB functionality to pihpsdr +*/ + +#include +#include +#include // tolower +#include +#include +#include // for stat +#include // for readlink, sleep, getcwd + +#include + +#include "ozyio.h" + +#define OZY_PID (0x0007) +#define OZY_VID (0xfffe) + +#define VRQ_SDR1K_CTL 0x0d +#define SDR1KCTRL_READ_VERSION 0x7 +#define VRT_VENDOR_IN 0xC0 + +#define VENDOR_REQ_TYPE_IN 0xc0 +#define VENDOR_REQ_TYPE_OUT 0x40 + +#define VRQ_I2C_WRITE (0x08) +#define VRT_VENDOR_OUT (0x40) + + +#define VENDOR_REQ_SET_LED 0x01 +#define VENDOR_REQ_FPGA_LOAD 0x02 + +#define FL_BEGIN 0 +#define FL_XFER 1 +#define FL_END 2 + +#define OZY_BUFFER_SIZE 512 + +//#define OZY_IO_TIMEOUT 500 +#define OZY_IO_TIMEOUT 2000 +#define MAX_EPO_PACKET_SIZE 64 + +static int init=0; +extern unsigned char penny_fw, mercury_fw; +extern unsigned short penny_fp, penny_rp, penny_alc; +extern int adc_overflow; +void writepenny(unsigned char mode); +static libusb_device_handle* ozy_handle; +//static libusb_context* context; + + +static char ozy_firmware[64] = {0}; +static char ozy_fpga[64] = {0}; +static unsigned char ozy_firmware_version[9]; +static unsigned char ozy_output_buffer[OZY_BUFFER_SIZE]; + +// variables accessed via ozy_i2c_readvars: +unsigned char penny_fw =0, mercury_fw = 0; + +// variables accessed via ozy_i2c_readpwr +unsigned short penny_fp =0, penny_rp = 0, penny_alc = 0; +int adc_overflow; + + + + + +int ozy_open(void) { + int rc; + + if(init==0) { + rc=libusb_init(NULL); + if(rc<0) { + fprintf(stderr,"libusb_init failed: %d\n",rc); + return rc; + } + init=1; + } + + ozy_handle=libusb_open_device_with_vid_pid(NULL, OZY_VID, OZY_PID); + if(ozy_handle==NULL) { + fprintf(stderr,"libusbio: cannot find ozy device\n"); + return -1; + } + + rc=libusb_detach_kernel_driver(ozy_handle,0); + if(rc<0) { + // fprintf(stderr,"libusb_detach_kernel_driver failed: %d\n",rc); + } + + rc=libusb_claim_interface(ozy_handle,0); + if(rc<0) { + fprintf(stderr,"libusb_claim_interface failed: %d\n",rc); + return rc; + } + + return 0; +} + +int ozy_close() { + int rc; + + rc=libusb_attach_kernel_driver(ozy_handle,0); + if(rc<0) { + // fprintf(stderr,"libusb_attach_kernel_driver failed: %d\n",rc); + } + + libusb_close(ozy_handle); + + return 0; +} + +int ozy_get_firmware_string(unsigned char* buffer,int buffer_size) { + int rc; + + rc=libusb_control_transfer(ozy_handle, VRT_VENDOR_IN, VRQ_SDR1K_CTL, SDR1KCTRL_READ_VERSION, 0, buffer, buffer_size, OZY_IO_TIMEOUT); + if(rc<0) { + fprintf(stderr,"ozy__get_firmware_string failed: %d\n",rc); + return rc; + } + buffer[rc]='\0'; + + return 0; +} + +int ozy_write(int ep,unsigned char* buffer,int buffer_size) { + int rc; + int bytes; + + rc = libusb_bulk_transfer(ozy_handle,(unsigned char)ep,buffer,buffer_size,&bytes,OZY_IO_TIMEOUT); + if(rc==0) { + rc=bytes; + } + + return rc; +} + +int ozy_read(int ep,unsigned char* buffer,int buffer_size) { + int rc; + int bytes; + + rc = libusb_bulk_transfer(ozy_handle,(unsigned char)ep,buffer,buffer_size,&bytes,OZY_IO_TIMEOUT); + if(rc==0) { + rc=bytes; + } + + return rc; +} + +int ozy_write_ram(int fx2_start_addr, unsigned char *bufp, int count) { + int pkt_size = MAX_EPO_PACKET_SIZE; + int len = count; + int bytes_written = 0; + int addr; + int bytes_written_this_write; + int nsize; + + for ( addr = fx2_start_addr; addr < fx2_start_addr + len; addr += pkt_size, bufp += pkt_size ) { + nsize = len + fx2_start_addr - addr; + if ( nsize > pkt_size ) nsize = pkt_size; + bytes_written_this_write = libusb_control_transfer(ozy_handle, 0x40, 0xa0, addr, 0, bufp, nsize, OZY_IO_TIMEOUT); + if ( bytes_written_this_write >= 0 ) { + bytes_written += bytes_written_this_write; + } + else { + return bytes_written_this_write; + } + } + return bytes_written; +} + +int ozy_reset_cpu(int reset) { + unsigned char write_buf; + + if ( reset ) write_buf = 1; + else write_buf = 0; + + if ( ozy_write_ram(0xe600, &write_buf, 1) != 1 ) return 0; + else return 1; + +} + +static unsigned int hexitToUInt(char c) { + c = tolower(c); + if ( c >= '0' && c <= '9' ) { + return c - '0'; + } + else if ( c >= 'a' && c <= 'f' ) { + return 10 + (c - 'a'); + } + return 0; +} + +static int ishexit(unsigned char c) { + c = tolower(c); + if ( c >= '0' && c <= '9' ) return 1; + if ( c >= 'a' && c <= 'f' ) return 1; + return 0; +} + +static int hexitsToUInt(char *p, int count) { + unsigned int result = 0; + int i; + char c; + unsigned int this_hex; + for ( i = 0; i < count; i++ ) { + c = *p; + ++p; + if ( !ishexit(c) ) { + return -1; + } + this_hex = hexitToUInt(c); + result *= 16; + result += this_hex; + } + return result; +} + +int ozy_load_firmware(char *fnamep) { + FILE *ifile; + int linecount = 0; + int length; + int addr; + int type; + char readbuf[1030]; + unsigned char wbuf[256]; + unsigned char my_cksum; + unsigned char cksum; + int this_val; + int i; + + fprintf(stderr,"loading ozy firmware: %s\n",fnamep); + + ifile = fopen(fnamep, "r"); + if ( ifile == NULL ) { + fprintf(stderr, "Could not open: \'%s\'\n", fnamep); + return 0; + } + + while ( fgets(readbuf, sizeof(readbuf), ifile) != NULL ) { + ++linecount; + if ( readbuf[0] != ':' ) { + fprintf(stderr, "ozy_upload_firmware: bad record\n"); + return 0; + } + length = hexitsToUInt(readbuf+1, 2); + addr = hexitsToUInt(readbuf+3, 4); + type = hexitsToUInt(readbuf+7, 2); + if ( length < 0 || addr < 0 || type < 0 ) { + fprintf(stderr, "ozy_upload_firmware: bad length, addr or type\n"); + return 0; + } + switch ( type ) { + case 0: /* record */ + my_cksum = (unsigned char)(length + (addr & 0xff) + ((addr >> 8) + type)); + for ( i = 0; i < length; i++ ) { + this_val = hexitsToUInt(readbuf+9+(i*2),2); + #if 0 + printf("i: %d val: 0x%02x\n", i, this_val); + #endif + + if ( this_val < 0 ) { + fprintf(stderr, "ozy_upload_firmware: bad record data\n"); + return 0; + } + wbuf[i] = (unsigned char)this_val; + my_cksum += wbuf[i]; + } + + this_val = hexitsToUInt(readbuf+9+(length*2),2); + if ( this_val < 0 ) { + fprintf(stderr, "ozy_upload_firmware: bad checksum data\n"); + return 0; + } + cksum = (unsigned char)this_val; + #if 0 + printf("\n%s", readbuf); + printf("len: %d (0x%02x) addr: 0x%04x mychk: 0x%02x chk: 0x%02x", + length, length, addr, my_cksum, cksum); + #endif + + if ( ((cksum + my_cksum) & 0xff) != 0 ) { + fprintf(stderr, "ozy_upload_firmware: bad checksum\n"); + return 0; + } + if ( ozy_write_ram(addr, wbuf, length) < 1 ) { + fprintf(stderr, "ozy_upload_firmware: bad write\n"); + return 0; + } + break; + + case 1: /* EOF */ + break; + + default: /* invalid */ + fprintf(stderr, "ozy_upload_firmware: invalid type\n"); + return 0; + + } + } + // fprintf(stderr, "ozy_upload_firmware: Processed %d lines.\n", linecount); + return linecount; +} + +int ozy_set_led(int which, int on) { + int rc; + int val; + + if ( on ) { + val = 1; + } + else { + val = 0; + } + + rc = libusb_control_transfer(ozy_handle, VENDOR_REQ_TYPE_OUT, VENDOR_REQ_SET_LED, + val, which, NULL, 0, OZY_IO_TIMEOUT); + + if ( rc < 0 ) { + return 0; + } + return 1; +} + +int ozy_load_fpga(char *rbf_fnamep) { + + FILE *rbffile; + unsigned char buf[MAX_EPO_PACKET_SIZE]; + int bytes_read; + int total_bytes_xferd = 0; + int rc; + + fprintf(stderr,"loading ozy fpga: %s\n",rbf_fnamep); + + rbffile = fopen(rbf_fnamep, "rb"); + if ( rbffile == NULL ) { + fprintf(stderr, "Failed to open: \'%s\'\n", rbf_fnamep); + return 0; + } + + rc = libusb_control_transfer(ozy_handle, VENDOR_REQ_TYPE_OUT, VENDOR_REQ_FPGA_LOAD, + 0, FL_BEGIN, NULL, 0, OZY_IO_TIMEOUT); + + if ( rc < 0 ) { + fprintf(stderr, "ozy_load_fpga: failed @ FL_BEGIN rc=%d\n",rc); + fclose(rbffile); + return 0; + } + + /* + * read the rbf and send it over the wire, 64 bytes at a time + */ + while ( (bytes_read = fread(buf, 1, sizeof(buf), rbffile)) > 0 ) { + rc = libusb_control_transfer(ozy_handle, VENDOR_REQ_TYPE_OUT, VENDOR_REQ_FPGA_LOAD, + 0, FL_XFER, buf, bytes_read, OZY_IO_TIMEOUT); + total_bytes_xferd += bytes_read; + if ( rc < 0 ) { + fprintf(stderr, "ozy_load_fpga: failed @ FL_XFER\n"); + fclose(rbffile); + return 0; + } + } + printf("%d bytes transferred.\n", total_bytes_xferd); + fclose(rbffile); + rc = libusb_control_transfer(ozy_handle, VENDOR_REQ_TYPE_OUT, VENDOR_REQ_FPGA_LOAD, + 0, FL_END, NULL, 0, OZY_IO_TIMEOUT); + if ( rc < 0 ) { + fprintf(stderr, "ozy_load_fpga: failed @ FL_END\n"); + return 0; + } + + return 1; +} + +int ozy_i2c_write(unsigned char* buffer,int buffer_size, unsigned char cmd) { + int rc; + + rc=libusb_control_transfer(ozy_handle, VRT_VENDOR_OUT, VRQ_I2C_WRITE, cmd, 0, buffer, buffer_size, OZY_IO_TIMEOUT); + if(rc<0) { + fprintf(stderr,"ozy_i2c_write failed: %d\n",rc); + return rc; + } + return rc; +} + +int ozy_i2c_read(unsigned char* buffer,int buffer_size, unsigned char cmd) { + int rc; + + rc=libusb_control_transfer(ozy_handle, VRT_VENDOR_IN, VRQ_I2C_READ, cmd, 0, buffer, buffer_size, OZY_IO_TIMEOUT); + if(rc<0) { + fprintf(stderr,"ozy_i2c_read failed: %d\n",rc); + return rc; + } + return rc; +} + + +void ozy_i2c_readpwr(int addr) { + int rc = 0; + unsigned char buffer[8]; + + switch (addr) { + case I2C_PENNY_ALC: + rc = ozy_i2c_read(buffer,2,I2C_PENNY_ALC); + if(rc<0) { + perror("ozy_i2c_init4: failed"); + //exit(1); + } + penny_alc = (buffer[0] << 8) + buffer[1]; + break; + + case I2C_PENNY_FWD: + rc = ozy_i2c_read(buffer,2,I2C_PENNY_FWD); + if(rc<0) { + perror("ozy_i2c_init5: failed"); + //exit(1); + } + penny_fp = (buffer[0] << 8) + buffer[1]; + break; + + case I2C_PENNY_REV: + rc = ozy_i2c_read(buffer,2,I2C_PENNY_REV); + if(rc<0) { + perror("ozy_i2c_init6: failed"); + //exit(1); + } + penny_rp = (buffer[0] << 8) + buffer[1]; + break; + + case I2C_ADC_OFS: + // adc overload + rc = ozy_i2c_read(buffer,2,I2C_ADC_OFS); // adc1 overflow status + if(rc<0) { + perror("ozy_i2c_init6: failed"); + //exit(1); + } + if (buffer[0] == 0) { // its overloaded + adc_overflow = 2000; // counts down to give hold time to client + } + break; + + default: + break; + } +} + +void ozy_i2c_readvars() { + int rc = 0; + unsigned char buffer[8]; + + + fprintf(stderr,"ozy_i2c_init: starting\n"); + + if (rc != 0) { + fprintf(stderr,"ozy_i2c_init: failed open %d\n",rc); + } + + rc = ozy_i2c_read(buffer,2,I2C_MERC1_FW); + if(rc<0) { + perror("ozy_i2c_init2: failed"); + //exit(1); + } + mercury_fw = buffer[1]; + fprintf(stderr,"mercury firmware=%d\n",(int)buffer[1]); + + rc = ozy_i2c_read(buffer,2,I2C_PENNY_FW); + if(rc<0) { + perror("ozy_i2c_init3: failed"); + //exit(1); + } + penny_fw = buffer[1]; + fprintf(stderr,"penny firmware=%d\n",(int)buffer[1]); + + writepenny((unsigned char)1); +} + +void writepenny(unsigned char mode) +{ + unsigned char Penny_TLV320[2]; + unsigned char *Penny_TLV320_data; // 16 byte + int x; + // This is used to set the MicGain and Line in when Ozy/Magister is used + // The I2C settings are as follows: + + // For mic input and boost on/off + // 1E 00 - Reset chip + // 12 01 - set digital interface active + // 08 15 - D/A on, mic input, mic 20dB boost + // 08 14 - ditto but no mic boost + // 0C 00 - All chip power on + // 0E 02 - Slave, 16 bit, I2S + // 10 00 - 48k, Normal mode + // 0A 00 - turn D/A mute off + // 00 00 - set Line in gain to 0 + + // For line input + // 1E 00 - Reset chip + // 12 01 - set digital interface active + // 08 10 - D/A on, line input + // 0C 00 - All chip power on + // 0E 02 - Slave, 16 bit, I2S + // 10 00 - 48k, Normal mode + // 0A 00 - turn D/A mute off + // 00 00 - set Line in gain to 0 + fprintf(stderr,"write Penny\n"); + + // update mic gain on Penny or PennyLane TLV320 + + // need to select the config data depending on the Mic Gain (20dB) selected + if (mode == 0x01) + Penny_TLV320_data = (unsigned char []) { 0x1e, 0x00, 0x12, 0x01, 0x08, 0x15, 0x0c, 0x00, 0x0e, 0x02, 0x10, 0x00, 0x0a, 0x00, 0x00, 0x00 }; // mic in 20db gain + else if (mode & 2) // line in + Penny_TLV320_data = (unsigned char []) { 0x1e, 0x00, 0x12, 0x01, 0x08, 0x10, 0x0c, 0x00, 0x0e, 0x02, 0x10, 0x00, 0x0a, 0x00, 0x00, 0x00 }; // line in + else + Penny_TLV320_data = (unsigned char []) { 0x1e, 0x00, 0x12, 0x01, 0x08, 0x14, 0x0c, 0x00, 0x0e, 0x02, 0x10, 0x00, 0x0a, 0x00, 0x00, 0x00 }; // mic in not 20db gain + + // // set the I2C interface speed to 400kHZ + // if (!(OZY.Set_I2C_Speed(hdev, 1))) + // { + // fprintf(stderr,"Unable to set I2C speed to 400kHz", "System Error!", MessageBoxButtons.OK, MessageBoxIcon.Error); + // return; + + // send the configuration data to the TLV320 on Penelope or PennyLane + for (x = 0; x < 16; x += 2) + { + Penny_TLV320[0] = Penny_TLV320_data[x]; Penny_TLV320[1] = Penny_TLV320_data[x + 1]; + int ozy_write_i2c(int ep,unsigned char* buffer,int buffer_size); + if (!(ozy_i2c_write(Penny_TLV320,2, 0x1b))) + { + fprintf(stderr,"Unable to configure TLV320 on Penelope via I2C\n"); + // break out of the configuration loop + break; + } + } + fprintf(stderr,"write Penny done..\n"); +} + + + +static int file_exists (const char * fileName) +{ + struct stat buf; + int i = stat ( fileName, &buf ); + return ( i == 0 ) ? 1 : 0 ; +} + +#ifdef __linux__ +int filePath (char *sOut, const char *sIn) { + int rc = 0; + + if ((rc = file_exists (sIn))) { + strcpy (sOut, sIn); + rc = 1; + } else { + char cwd[PATH_MAX]; + char s[PATH_MAX]; + char xPath [PATH_MAX] = {0}; + char *p; + + int rc = readlink ("/proc/self/exe", xPath, sizeof(xPath)); + + // try to detect the directory from which the executable has been loaded + if (rc >= 0) { + + if ( (p = strrchr (xPath, '/')) ) *(p+1) = '\0'; + fprintf (stderr, "%d, Path of executable: [%s]\n", rc, xPath); + + strcpy (s, xPath); strcat (s, sIn); + + if ((rc = file_exists (s))) { + // found in the same dir of executable + fprintf (stderr, "File: [%s]\n", s); + strcpy(sOut, s); + } else { + if (getcwd(cwd, sizeof(cwd)) != NULL) { + fprintf(stdout, "Current working dir: %s\n", cwd); + + strcpy (s, cwd); strcat (s, "/"); strcat (s, sIn); + if ((rc = file_exists (s))) { + fprintf (stderr, "File: [%s]\n", s); + strcpy(sOut, s); + } + } + } + } else { + fprintf (stderr, "%d: %s\n", errno, strerror(errno)); + } + } + return rc; +} +#endif + + + +// +// initialise a USB ozy device. +// renamed as "initialise" and combined with the "ozyinit" code +// +int ozy_initialise() +{ + int rc; + + if (strlen(ozy_firmware) == 0) filePath (ozy_firmware,"ozyfw-sdr1k.hex"); + if (strlen(ozy_fpga) == 0) filePath (ozy_fpga,"Ozy_Janus.rbf"); + +// open ozy + rc = ozy_open(); + if (rc != 0) { + fprintf(stderr,"Cannot locate Ozy\n"); + //exit(1); + } +// load Ozy FW + ozy_reset_cpu(1); + ozy_load_firmware(ozy_firmware); + ozy_reset_cpu(0); + ozy_close(); + sleep(4); + ozy_open(); + ozy_set_led(1,1); + ozy_load_fpga(ozy_fpga); + ozy_set_led(1,0); + ozy_close(); + ozy_open(); + rc=ozy_get_firmware_string(ozy_firmware_version,8); + fprintf(stderr,"Ozy FX2 version: %s\n",ozy_firmware_version); + + ozy_i2c_readvars(); + ozy_close(); + sleep(1); + ozy_open(); + return 0; +} + + + +// +// modified from "ozy_open" code: just finds out if there is a USB +// ozy on the bus. Closes the connection after discovering. +// returns 1 if a device found on USB +// +// +int ozy_discover(void) +{ + int success = 0; // function return code + int rc; + + if(init==0) + { + rc=libusb_init(NULL); + if(rc<0) + { + fprintf(stderr,"libusb_init failed: %d\n",rc); + return success; + } + init=1; + } +// +// do a trial open with thr PID and VID of ozy +// + ozy_handle=libusb_open_device_with_vid_pid(NULL, OZY_VID, OZY_PID); + if(ozy_handle==NULL) + { + fprintf(stderr,"libusbio: cannot find ozy device\n"); + return success; + } + else + { + success = 1; + fprintf(stderr,"libusbio: ozy device found on USB port\n"); + } +// +// if we get this far, we have an ozy on the bus so discover successful. +// we don't know that it will be selected for use, so close it again +// for now; re-open if the user selects Ozy +// + libusb_close(ozy_handle); + return success; +} diff --git a/ozyio.h b/ozyio.h new file mode 100644 index 0000000..b643cfe --- /dev/null +++ b/ozyio.h @@ -0,0 +1,86 @@ +/** +* @file ozyio.h +* @brief USB I/O with Ozy +* @author John Melton, G0ORX/N6LYT +* @version 0.1 +* @date 2009-10-13 +*/ + +/* Copyright (C) +* 2009 - John Melton, G0ORX/N6LYT +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +/* +* modified by Bob Wisdom VK4YA May 2015 to create ozymetis +* modified further Laurence Barker G8NJJ to add USB functionality to pihpsdr +*/ + + +/* + * code modified from that in Ozy_Metis_RPI_Gateway + * Laurence Barker, G8NJJ December 2016 + * this gathers all Ozy functionality in one file (merging code + * from ozy.c). + * Further modified to add a "discover" function + * +*/ + +#if !defined __OZYIO_H__ +#define __OZYIO_H__ + +// +// penelope forward, reverse power and ALC settings +// +extern unsigned short penny_fp, penny_rp, penny_alc; +extern int adc_overflow; + +int ozy_open(void); +int ozy_close(); +int ozy_get_firmware_string(unsigned char* buffer,int buffer_size); +int ozy_write(int ep,unsigned char* buffer,int buffer_size); +int ozy_read(int ep,unsigned char* buffer,int buffer_size); + +void ozy_load_fw(); +int ozy_load_fpga(char *rbf_fnamep); +int ozy_set_led(int which, int on); +int ozy_reset_cpu(int reset); +int ozy_load_firmware(char *fnamep); +int ozy_initialise(); +int ozy_discover(void); // returns 1 if a device found on USB +void ozy_i2c_readpwr(int addr); // sets local variables + + + +// Ozy I2C commands for polling firmware versions, power levels, ADC overload. +#define I2C_MERC1_FW 0x10 // Mercury1 firmware version +#define I2C_MERC2_FW 0x11 // Mercury2 firmware version +#define I2C_MERC3_FW 0x12 // Mercury3 firmware version +#define I2C_MERC4_FW 0x13 // Mercury4 firmware version + +#define I2C_MERC1_ADC_OFS 0x10 // adc1 overflow status +#define I2C_MERC2_ADC_OFS 0x11 // adc2 overflow status +#define I2C_MERC3_ADC_OFS 0x12 // adc3 overflow status +#define I2C_MERC4_ADC_OFS 0x13 // adc4 overflow status + +#define I2C_PENNY_FW 0x15 // Penny firmware version +#define I2C_PENNY_ALC 0x16 // Penny forward power +#define I2C_PENNY_FWD 0x17 // Penny forward power from Alex +#define I2C_PENNY_REV 0x18 // Penny reverse power from Alex +#define I2C_ADC_OFS (0x10) // ADC overload status +#define VRQ_I2C_READ 0x81 // i2c address; length; how much to read + +#endif diff --git a/pa_menu.c b/pa_menu.c index 00882fc..67cb6e6 100644 --- a/pa_menu.c +++ b/pa_menu.c @@ -26,6 +26,7 @@ #include "pa_menu.h" #include "band.h" #include "radio.h" +#include "vfo.h" static GtkWidget *parent_window=NULL; @@ -45,8 +46,14 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat static void pa_value_changed_cb(GtkWidget *widget, gpointer data) { BAND *band=(BAND *)data; band->pa_calibration=gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget)); - calcDriveLevel(); - calcTuneDriveLevel(); + int v=VFO_A; + if(split) v=VFO_B; + int b=vfo[v].band; + BAND *current=band_get_band(b); + if(band==current) { + calcDriveLevel(); + calcTuneDriveLevel(); + } } static void tx_out_of_band_cb(GtkWidget *widget, gpointer data) { diff --git a/panadapter.c b/panadapter.c deleted file mode 100644 index 181c547..0000000 --- a/panadapter.c +++ /dev/null @@ -1,490 +0,0 @@ -/* Copyright (C) -* 2015 - John Melton, G0ORX/N6LYT -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -*/ - -#include -#include -#include -#include -#include -#include -#include -#include "agc.h" -#include "band.h" -#include "channel.h" -#include "discovered.h" -#include "radio.h" -#include "panadapter.h" -#include "vfo.h" -#include "mode.h" -#ifdef FREEDV -#include "freedv.h" -#endif -#include "wdsp_init.h" - -static GtkWidget *panadapter; -static cairo_surface_t *panadapter_surface = NULL; - -static float* samples; - -static gint last_x; -static gboolean has_moved=FALSE; -static gboolean pressed=FALSE; - -//static float panadapter_max=-60.0; -//static float panadapter_min=-160.0; - -static gfloat hz_per_pixel; -static gfloat filter_left; -static gfloat filter_right; - -static int display_width; -static int display_height; - -/* Create a new surface of the appropriate size to store our scribbles */ -static gboolean -panadapter_configure_event_cb (GtkWidget *widget, - GdkEventConfigure *event, - gpointer data) -{ - display_width=gtk_widget_get_allocated_width (widget); - display_height=gtk_widget_get_allocated_height (widget); - -fprintf(stderr,"panadapter_configure_event_cb: width:%d height:%d\n",display_width,display_height); - if (panadapter_surface) - cairo_surface_destroy (panadapter_surface); - - panadapter_surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget), - CAIRO_CONTENT_COLOR, - display_width, - display_height); - - cairo_t *cr=cairo_create(panadapter_surface); - cairo_set_source_rgb(cr, 0, 0, 0); - cairo_paint(cr); - cairo_destroy(cr); - - return TRUE; -} - -/* Redraw the screen from the surface. Note that the ::draw - * signal receives a ready-to-be-used cairo_t that is already - * clipped to only draw the exposed areas of the widget - */ -static gboolean -panadapter_draw_cb (GtkWidget *widget, - cairo_t *cr, - gpointer data) -{ - cairo_set_source_surface (cr, panadapter_surface, 0, 0); - cairo_paint (cr); - - return FALSE; -} - -static gboolean -panadapter_button_press_event_cb (GtkWidget *widget, - GdkEventButton *event, - gpointer data) -{ - int x=(int)event->x; - if (event->button == 1) { - last_x=(int)event->x; - has_moved=FALSE; - pressed=TRUE; - } - return TRUE; -} - -static gboolean -panadapter_button_release_event_cb (GtkWidget *widget, - GdkEventButton *event, - gpointer data) -{ - if(pressed) { - int x=(int)event->x; - if (event->button == 1) { - if(has_moved) { - // drag - vfo_move((int)((float)(x-last_x)*hz_per_pixel)); - } else { - // move to this frequency - vfo_move_to((int)((float)(x-(display_width/2))*hz_per_pixel)); - } - last_x=x; - pressed=FALSE; - } - } - return TRUE; -} - -static gboolean -panadapter_motion_notify_event_cb (GtkWidget *widget, - GdkEventMotion *event, - gpointer data) -{ - int x, y; - GdkModifierType state; - gdk_window_get_device_position (event->window, - event->device, - &x, - &y, - &state); - if((state & GDK_BUTTON1_MASK == GDK_BUTTON1_MASK) || pressed) { - int moved=last_x-x; - vfo_move((int)((float)moved*hz_per_pixel)); - last_x=x; - has_moved=TRUE; - } - - return TRUE; -} - -static gboolean -panadapter_scroll_event_cb (GtkWidget *widget, - GdkEventScroll *event, - gpointer data) -{ - if(event->direction==GDK_SCROLL_UP) { - vfo_move(step); - } else { - vfo_move(-step); - } -} - -static void -close_window (void) -{ - if (panadapter_surface) - cairo_surface_destroy (panadapter_surface); - - gtk_main_quit (); -} - -void panadapter_update(float *data,int tx) { - int i; - int result; - - float saved_max; - float saved_min; - gfloat saved_hz_per_pixel; - cairo_text_extents_t extents; - - hz_per_pixel=(double)getSampleRate()/(double)display_width; - samples=data; - //if(result==1) { - if(panadapter_surface) { - - if(tx) { - saved_max=panadapter_high; - saved_min=panadapter_low; - saved_hz_per_pixel=hz_per_pixel; - - panadapter_high=20; - panadapter_low=-80; - //if(protocol==ORIGINAL_PROTOCOL) { - hz_per_pixel=48000.0/(double)display_width; - //} else { - // hz_per_pixel=192000.0/(double)display_width; - //} - } - - //clear_panadater_surface(); - cairo_t *cr; - cr = cairo_create (panadapter_surface); - cairo_set_source_rgb (cr, 0, 0, 0); - cairo_paint (cr); - - // filter - cairo_set_source_rgb (cr, 0.25, 0.25, 0.25); - if(ctun && isTransmitting()) { - filter_left=(double)display_width/2.0+((double)getFilterLow()/hz_per_pixel); - filter_right=(double)display_width/2.0+((double)getFilterHigh()/hz_per_pixel); - } else { - filter_left=(double)display_width/2.0+(((double)getFilterLow()+ddsOffset)/hz_per_pixel); - filter_right=(double)display_width/2.0+(((double)getFilterHigh()+ddsOffset)/hz_per_pixel); - } - cairo_rectangle(cr, filter_left, 0.0, filter_right-filter_left, (double)display_height); - cairo_fill(cr); - - // plot the levels - int V = (int)(panadapter_high - panadapter_low); - int numSteps = V / 20; - for (i = 1; i < numSteps; i++) { - int num = panadapter_high - i * 20; - int y = (int)floor((panadapter_high - num) * display_height / V); - - cairo_set_source_rgb (cr, 0, 1, 1); - cairo_set_line_width(cr, 1.0); - cairo_move_to(cr,0.0,(double)y); - cairo_line_to(cr,(double)display_width,(double)y); - - cairo_set_source_rgb (cr, 0, 1, 1); - cairo_select_font_face(cr, "FreeMono", - CAIRO_FONT_SLANT_NORMAL, - CAIRO_FONT_WEIGHT_BOLD); - cairo_set_font_size(cr, 12); - char v[32]; - sprintf(v,"%d dBm",num); - cairo_move_to(cr, 1, (double)y); - cairo_show_text(cr, v); - } - cairo_stroke(cr); - - // plot frequency markers - long f; - long divisor=20000; - long half=(long)getSampleRate()/2L; - long long frequency=displayFrequency; - if(ctun && isTransmitting()) { - frequency+=ddsOffset; - } - switch(sample_rate) { - case 48000: - divisor=5000L; - break; - case 96000: - case 100000: - divisor=10000L; - break; - case 192000: - divisor=20000L; - break; - case 384000: - divisor=25000L; - break; - case 768000: - divisor=50000L; - break; - case 1048576: - case 1536000: - case 2097152: - divisor=100000L; - break; - } - for(i=0;i 0) { - if ((f % divisor) < (long) hz_per_pixel) { - cairo_set_source_rgb (cr, 0, 1, 1); - cairo_set_line_width(cr, 1.0); - //cairo_move_to(cr,(double)i,0.0); - cairo_move_to(cr,(double)i,10.0); - cairo_line_to(cr,(double)i,(double)display_height); - - cairo_set_source_rgb (cr, 0, 1, 1); - cairo_select_font_face(cr, "FreeMono", - CAIRO_FONT_SLANT_NORMAL, - CAIRO_FONT_WEIGHT_BOLD); - cairo_set_font_size(cr, 12); - char v[32]; - sprintf(v,"%0ld.%03ld",f/1000000,(f%1000000)/1000); - //cairo_move_to(cr, (double)i, (double)(display_height-10)); - cairo_text_extents(cr, v, &extents); - cairo_move_to(cr, (double)i-(extents.width/2.0), 10.0); - cairo_show_text(cr, v); - } - } - } - cairo_stroke(cr); - - // band edges - long long min_display=frequency-half; - long long max_display=frequency+half; - BAND *band=band_get_current_band(); - if(band->frequencyMin!=0LL) { - cairo_set_source_rgb (cr, 1, 0, 0); - cairo_set_line_width(cr, 2.0); - if((min_displayfrequencyMin)&&(max_display>band->frequencyMin)) { - i=(band->frequencyMin-min_display)/(long long)hz_per_pixel; - cairo_move_to(cr,(double)i,0.0); - cairo_line_to(cr,(double)i,(double)display_height); - cairo_stroke(cr); - } - if((min_displayfrequencyMax)&&(max_display>band->frequencyMax)) { - i=(band->frequencyMax-min_display)/(long long)hz_per_pixel; - cairo_move_to(cr,(double)i,0.0); - cairo_line_to(cr,(double)i,(double)display_height); - cairo_stroke(cr); - } - } - - // agc - if(agc!=AGC_OFF && !tx) { - double hang=0.0; - double thresh=0; - - GetRXAAGCHangLevel(CHANNEL_RX0, &hang); - GetRXAAGCThresh(CHANNEL_RX0, &thresh, 4096.0, (double)sample_rate); - - double knee_y=thresh+(double)get_attenuation(); - knee_y = floor((panadapter_high - knee_y) - * (double) display_height - / (panadapter_high - panadapter_low)); - - double hang_y=hang+(double)get_attenuation(); - hang_y = floor((panadapter_high - hang_y) - * (double) display_height - / (panadapter_high - panadapter_low)); - -//fprintf(stderr,"hang=%f thresh=%f hang_y=%f knee_y=%f\n",rx1_hang,rx1_thresh,hang_y,knee_y); - if(agc!=AGC_MEDIUM && agc!=AGC_FAST) { - cairo_set_source_rgb (cr, 1.0, 1.0, 0.0); - cairo_move_to(cr,40.0,hang_y-8.0); - cairo_rectangle(cr, 40, hang_y-8.0,8.0,8.0); - cairo_fill(cr); - cairo_move_to(cr,40.0,hang_y); - cairo_line_to(cr,(double)display_width-40.0,hang_y); - cairo_stroke(cr); - cairo_move_to(cr,48.0,hang_y); - cairo_show_text(cr, "-H"); - } - - cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); - cairo_move_to(cr,40.0,knee_y-8.0); - cairo_rectangle(cr, 40, knee_y-8.0,8.0,8.0); - cairo_fill(cr); - cairo_move_to(cr,40.0,knee_y); - cairo_line_to(cr,(double)display_width-40.0,knee_y); - cairo_stroke(cr); - cairo_move_to(cr,48.0,knee_y); - cairo_show_text(cr, "-G"); - } - - - // cursor - cairo_set_source_rgb (cr, 1, 0, 0); - cairo_set_line_width(cr, 1.0); - cairo_move_to(cr,(double)(display_width/2.0)+(ddsOffset/hz_per_pixel),0.0); - cairo_line_to(cr,(double)(display_width/2.0)+(ddsOffset/hz_per_pixel),(double)display_height); - cairo_stroke(cr); - - // signal - double s1,s2; - samples[0]=-200.0; - samples[display_width-1]=-200.0; - - if(tx && protocol==NEW_PROTOCOL) { - int offset=1200; - s1=(double)samples[0+offset]+(double)get_attenuation(); - s1 = floor((panadapter_high - s1) - * (double) display_height - / (panadapter_high - panadapter_low)); - cairo_move_to(cr, 0.0, s1); - for(i=1;ivalue,value); property->next_property=properties; properties=property; + if(strcmp(name,"property_version")==0) { + version=atof(value); + } } } fclose(f); } - fprintf(stderr,"loadProperties: done\n"); + + if(version!=PROPERTY_VERSION) { + properties=NULL; + fprintf(stderr,"loadProperties: version=%f expected version=%f ignoring\n",version,PROPERTY_VERSION); + } } /* --------------------------------------------------------------------------*/ @@ -75,8 +84,8 @@ void saveProperties(char* filename) { return; } - sprintf(version,"%0.2f", PROPERTY_VERSION); - setProperty("property_version",version); + sprintf(line,"%s=%0.2f\n","property_version",PROPERTY_VERSION); + fwrite(line,1,strlen(line),f); while(property) { sprintf(line,"%s=%s\n",property->name,property->value); fwrite(line,1,strlen(line),f); diff --git a/property.h b/property.h index 883025b..3fb103a 100644 --- a/property.h +++ b/property.h @@ -20,7 +20,7 @@ #ifndef _PROPERTY_H #define _PROPERTY_H -#define PROPERTY_VERSION 1.0 +#define PROPERTY_VERSION 2.0 typedef struct _PROPERTY PROPERTY; diff --git a/psk.c b/psk.c index a3905e5..a2b8280 100644 --- a/psk.c +++ b/psk.c @@ -8,7 +8,6 @@ #include "psk.h" #include "radio.h" #include "channel.h" -#include "wdsp_init.h" static void *detector; diff --git a/psk_waterfall.c b/psk_waterfall.c index 5572b9f..ba03e50 100644 --- a/psk_waterfall.c +++ b/psk_waterfall.c @@ -29,6 +29,7 @@ #include "vfo.h" #include "psk.h" #include "psk_waterfall.h" +#include "receiver.h" static GtkWidget *waterfall; static GdkPixbuf *pixbuf = NULL; @@ -130,10 +131,10 @@ waterfall_button_release_event_cb (GtkWidget *widget, if (event->button == 1) { if(has_moved) { // drag - vfo_move((int)((float)(x-last_x)*hz_per_pixel)); + vfo_move((long long)((float)(x-last_x)*hz_per_pixel)); } else { // move to this frequency - vfo_move_to((int)((float)(x-(display_width/2))*hz_per_pixel)); + vfo_move_to((long long)((float)(x-(display_width/2))*hz_per_pixel)); } last_x=x; pressed=FALSE; @@ -157,7 +158,7 @@ waterfall_motion_notify_event_cb (GtkWidget *widget, &state); if((state & GDK_BUTTON1_MASK == GDK_BUTTON1_MASK) || pressed) { int moved=last_x-x; - vfo_move((int)((float)moved*hz_per_pixel)); + vfo_move((long long)((float)moved*hz_per_pixel)); last_x=x; has_moved=TRUE; } @@ -180,7 +181,7 @@ waterfall_scroll_event_cb (GtkWidget *widget, return TRUE; } -void psk_waterfall_update(float *data) { +void psk_waterfall_update(RECEIVER *rx) { int i; diff --git a/psk_waterfall.h b/psk_waterfall.h index abdf8ae..648ef34 100644 --- a/psk_waterfall.h +++ b/psk_waterfall.h @@ -20,7 +20,7 @@ #ifndef _PSK_WATERFALL_H #define _PSK_WATERFALL_H -void psk_waterfall_update(float *data); +void psk_waterfall_update(RECEIVER *rx); GtkWidget* psk_waterfall_init(int width,int height); #endif diff --git a/radio.c b/radio.c index 4698dd7..e4a55d5 100644 --- a/radio.c +++ b/radio.c @@ -17,38 +17,101 @@ * */ +#include #include #include #include #include #include +#include + #include "audio.h" #include "discovered.h" //#include "discovery.h" +#include "filter.h" +#include "main.h" #include "mode.h" #include "radio.h" +#include "receiver.h" +#include "transmitter.h" #include "channel.h" #include "agc.h" #include "band.h" #include "property.h" #include "new_protocol.h" +#include "old_protocol.h" +#include "store.h" #ifdef LIMESDR #include "lime_protocol.h" #endif -#include "wdsp.h" #ifdef FREEDV #include "freedv.h" #endif +#ifdef GPIO +#include "gpio.h" +#endif +#include "vfo.h" +#include "meter.h" +#include "rx_panadapter.h" +#include "tx_panadapter.h" +#include "waterfall.h" +#include "sliders.h" +#include "toolbar.h" #define min(x,y) (xpanel,0,y); + y+=rx_height/receivers; + } + + if(display_sliders) { + if(sliders==NULL) { + sliders = sliders_init(display_width,SLIDERS_HEIGHT); + gtk_fixed_put(GTK_FIXED(fixed),sliders,0,y); + } else { + gtk_fixed_move(GTK_FIXED(fixed),sliders,0,y); + } + gtk_widget_show_all(sliders); + // force change of sliders for mic or linein + g_idle_add(linein_changed,NULL); + } else { + if(sliders!=NULL) { + gtk_container_remove(GTK_CONTAINER(fixed),sliders); + sliders=NULL; + } + } + + reconfigure_transmitter(transmitter,rx_height); + +} + +static gboolean save_cb(gpointer data) { + radioSaveState(); + return TRUE; +} + +static gboolean minimize_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { + gtk_window_iconify(GTK_WINDOW(top_window)); + return TRUE; +} + +static gboolean menu_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { + new_menu(top_window); + return TRUE; +} + +void start_radio() { + int i; + int x; + int y; +fprintf(stderr,"start_radio: selected radio=%p device=%d\n",radio,radio->device); + gdk_window_set_cursor(gtk_widget_get_window(top_window),gdk_cursor_new(GDK_WATCH)); + int rc; rc=sem_init(&property_sem, 0, 0); if(rc!=0) { - fprintf(stderr,"init_radio: sem_init failed for property_sem: %d\n", rc); + fprintf(stderr,"start_radio: sem_init failed for property_sem: %d\n", rc); exit(-1); } sem_post(&property_sem); + + status_text("starting radio ..."); + protocol=radio->protocol; + device=radio->device; + + switch(radio->protocol) { + case ORIGINAL_PROTOCOL: + case NEW_PROTOCOL: + switch(radio->device) { +#ifdef USBOZY + case DEVICE_OZY: + sprintf(property_path,"ozy.props"); + break; +#endif + default: + sprintf(property_path,"%02X-%02X-%02X-%02X-%02X-%02X.props", + radio->info.network.mac_address[0], + radio->info.network.mac_address[1], + radio->info.network.mac_address[2], + radio->info.network.mac_address[3], + radio->info.network.mac_address[4], + radio->info.network.mac_address[5]); + break; + } + break; +#ifdef LIMESDR + case LIMESDR_PROTOCOL: + sprintf(property_path,"limesdr.props"); + break; +#endif + } + + radioRestoreState(); + + y=0; + + fixed=gtk_fixed_new(); + gtk_container_remove(GTK_CONTAINER(top_window),grid); + gtk_container_add(GTK_CONTAINER(top_window), fixed); + +fprintf(stderr,"radio: vfo_init\n"); + vfo_panel = vfo_init(VFO_WIDTH,VFO_HEIGHT,top_window); + gtk_fixed_put(GTK_FIXED(fixed),vfo_panel,0,y); + +fprintf(stderr,"radio: meter_init\n"); + meter = meter_init(METER_WIDTH,METER_HEIGHT,top_window); + gtk_fixed_put(GTK_FIXED(fixed),meter,VFO_WIDTH,y); + + + GtkWidget *minimize_b=gtk_button_new_with_label("Hide"); + gtk_widget_override_font(minimize_b, pango_font_description_from_string("FreeMono Bold 10")); + gtk_widget_set_size_request (minimize_b, MENU_WIDTH, MENU_HEIGHT); + g_signal_connect (minimize_b, "button-press-event", G_CALLBACK(minimize_cb), NULL) ; + gtk_fixed_put(GTK_FIXED(fixed),minimize_b,VFO_WIDTH+METER_WIDTH,y); + y+=MENU_HEIGHT; + + GtkWidget *menu_b=gtk_button_new_with_label("Menu"); + gtk_widget_override_font(menu_b, pango_font_description_from_string("FreeMono Bold 10")); + gtk_widget_set_size_request (menu_b, MENU_WIDTH, MENU_HEIGHT); + g_signal_connect (menu_b, "button-press-event", G_CALLBACK(menu_cb), NULL) ; + gtk_fixed_put(GTK_FIXED(fixed),menu_b,VFO_WIDTH+METER_WIDTH,y); + y+=MENU_HEIGHT; + + + int rx_height=display_height-VFO_HEIGHT-TOOLBAR_HEIGHT; + if(display_sliders) { + rx_height-=SLIDERS_HEIGHT; + } + int tx_height=rx_height; + rx_height=rx_height/receivers; + + +fprintf(stderr,"Create %d receivers: height=%d\n",receivers,rx_height); + for(i=0;ipanel); + if(ipanel,0,y); +fprintf(stderr,"receiver %d: height=%d y=%d\n",receiver[i]->id,rx_height,y); + set_displaying(receiver[i],1); + y+=rx_height; + } else { + set_displaying(receiver[i],0); + } + } + active_receiver=receiver[0]; + + fprintf(stderr,"Create transmitter\n"); + transmitter=create_transmitter(CHANNEL_TX, buffer_size, fft_size, updates_per_second, display_width, tx_height); + g_object_ref((gpointer)transmitter->panel); + + switch(radio->protocol) { + case ORIGINAL_PROTOCOL: + old_protocol_init(0,display_width,receiver[0]->sample_rate); + break; + case NEW_PROTOCOL: + new_protocol_init(display_width); + break; +#ifdef LIMESDR + case LIMESDR_PROTOCOL: + lime_protocol_init(0,display_width); + break; +#endif + } + +#ifdef GPIO + if(gpio_init()<0) { + fprintf(stderr,"GPIO failed to initialize\n"); + } +#ifdef LOCALCW + // init local keyer if enabled + else if (cw_keyer_internal == 0) + keyer_update(); +#endif +#endif + +#ifdef I2C + i2c_init(); +#endif + + if(display_sliders) { +fprintf(stderr,"create sliders\n"); + sliders = sliders_init(display_width,SLIDERS_HEIGHT); + gtk_fixed_put(GTK_FIXED(fixed),sliders,0,y); + y+=SLIDERS_HEIGHT; + } + + toolbar = toolbar_init(display_width,TOOLBAR_HEIGHT,top_window); + gtk_fixed_put(GTK_FIXED(fixed),toolbar,0,y); + y+=TOOLBAR_HEIGHT; + + gtk_widget_show_all (fixed); + + // force change of sliders for mic or linein + g_idle_add(linein_changed,NULL); + + // save every 30 seconds +fprintf(stderr,"start save timer\n"); + save_timer_id=gdk_threads_add_timeout(30000, save_cb, NULL); + +#ifdef PSK + if(active_receiver->mode==modePSK) { + show_psk(); + } else { + show_waterfall(); + } +#endif + + launch_rigctl(); + + calcDriveLevel(); + calcTuneDriveLevel(); + + if(protocol==NEW_PROTOCOL) { + schedule_high_priority(); + } + + g_idle_add(vfo_update,(gpointer)NULL); + +fprintf(stderr,"set cursor\n"); + gdk_window_set_cursor(gtk_widget_get_window(top_window),gdk_cursor_new(GDK_ARROW)); + +for(i=0;ipanel); + } + receivers=1; + break; + case 2: + gtk_fixed_put(GTK_FIXED(fixed),receiver[1]->panel,0,0); + set_displaying(receiver[1],1); + receivers=2; + break; + } + reconfigure_radio(); + active_receiver=receiver[0]; } -int getSampleRate() { - return sample_rate; +void radio_change_sample_rate(int rate) { + int i; + switch(protocol) { + case ORIGINAL_PROTOCOL: + old_protocol_stop(); + for(i=0;iid,0,i==(receivers-1)); + set_displaying(receiver[i],0); + if(protocol==NEW_PROTOCOL) { + schedule_high_priority(); + } + gtk_container_remove(GTK_CONTAINER(fixed),receiver[i]->panel); } - SetChannelState(CHANNEL_TX,1,0); + gtk_fixed_put(GTK_FIXED(fixed),transmitter->panel,0,y); + SetChannelState(transmitter->id,1,0); + tx_set_displaying(transmitter,1); #ifdef FREEDV - if(mode==modeFREEDV) { + if(active_receiver->mode==modeFREEDV) { freedv_reset_tx_text_index(); } #endif } else { - SetChannelState(CHANNEL_TX,0,1); + SetChannelState(transmitter->id,0,1); if(protocol==NEW_PROTOCOL) { - schedule_high_priority(3); + schedule_high_priority(); + } + tx_set_displaying(transmitter,0); + gtk_container_remove(GTK_CONTAINER(fixed),transmitter->panel); + int rx_height=display_height-VFO_HEIGHT-TOOLBAR_HEIGHT; + if(display_sliders) { + rx_height-=SLIDERS_HEIGHT; + } + for(i=0;iid,1,0); + set_displaying(receiver[i],1); + gtk_fixed_put(GTK_FIXED(fixed),receiver[i]->panel,0,y); + y+=(rx_height/receivers); } - SetChannelState(CHANNEL_RX0,1,0); } + + gtk_widget_show_all(fixed); + g_idle_add(linein_changed,NULL); } void setMox(int state) { @@ -298,47 +623,99 @@ void setVox(int state) { } void setTune(int state) { + int i; + if(tune!=state) { tune=state; if(vox_enabled && vox) { vox_cancel(); } if(tune) { - if(OCmemory_tune_time!=0) { - struct timeval te; - gettimeofday(&te,NULL); - tune_timeout=(te.tv_sec*1000LL+te.tv_usec/1000)+(long long)OCmemory_tune_time; + if(full_tune) { + if(OCfull_tune_time!=0) { + struct timeval te; + gettimeofday(&te,NULL); + tune_timeout=(te.tv_sec*1000LL+te.tv_usec/1000)+(long long)OCfull_tune_time; + } + } + if(memory_tune) { + if(OCmemory_tune_time!=0) { + struct timeval te; + gettimeofday(&te,NULL); + tune_timeout=(te.tv_sec*1000LL+te.tv_usec/1000)+(long long)OCmemory_tune_time; + } } } if(protocol==NEW_PROTOCOL) { - schedule_high_priority(4); + schedule_high_priority(); //schedule_general(); } if(tune) { - SetChannelState(CHANNEL_RX0,0,1); - pre_tune_mode = mode; - if(mode==modeCWL) { - setMode(modeLSB); - } else if(mode==modeCWU) { - setMode(modeUSB); + for(i=0;iid,0,i==(receivers-1)); + set_displaying(receiver[i],0); + if(protocol==NEW_PROTOCOL) { + schedule_high_priority(); + } } - SetTXAPostGenMode(CHANNEL_TX,0); - if(mode==modeLSB || mode==modeCWL || mode==modeDIGL) { - SetTXAPostGenToneFreq(CHANNEL_TX,-(double)cw_keyer_sidetone_frequency); - } else { - SetTXAPostGenToneFreq(CHANNEL_TX,(double)cw_keyer_sidetone_frequency); + + int mode=vfo[VFO_A].mode;; + if(split) { + mode=vfo[VFO_B].mode; } - SetTXAPostGenToneMag(CHANNEL_TX,0.99999); - SetTXAPostGenRun(CHANNEL_TX,1); - SetChannelState(CHANNEL_TX,1,0); - } else { - SetChannelState(CHANNEL_TX,0,1); - SetTXAPostGenRun(CHANNEL_TX,0); - if(pre_tune_mode==modeCWL || pre_tune_mode==modeCWU) { - setMode(pre_tune_mode); + double freq=(double)cw_keyer_sidetone_frequency; + + pre_tune_filter_low=transmitter->filter_low; + pre_tune_filter_high=transmitter->filter_high; + + switch(mode) { + case modeUSB: + case modeCWU: + case modeDIGU: + SetTXAPostGenToneFreq(transmitter->id,(double)cw_keyer_sidetone_frequency); + transmitter->filter_low=cw_keyer_sidetone_frequency-100; + transmitter->filter_high=cw_keyer_sidetone_frequency+100; + freq=(double)(cw_keyer_sidetone_frequency+100); + break; + case modeLSB: + case modeCWL: + case modeDIGL: + SetTXAPostGenToneFreq(transmitter->id,-(double)cw_keyer_sidetone_frequency); + transmitter->filter_low=-cw_keyer_sidetone_frequency-100; + transmitter->filter_high=-cw_keyer_sidetone_frequency+100; + freq=(double)(-cw_keyer_sidetone_frequency-100); + break; + case modeDSB: + SetTXAPostGenToneFreq(transmitter->id,(double)cw_keyer_sidetone_frequency); + transmitter->filter_low=cw_keyer_sidetone_frequency-100; + transmitter->filter_high=cw_keyer_sidetone_frequency+100; + freq=(double)(cw_keyer_sidetone_frequency+100); + break; + case modeAM: + case modeSAM: + case modeFMN: + SetTXAPostGenToneFreq(transmitter->id,(double)cw_keyer_sidetone_frequency); + transmitter->filter_low=cw_keyer_sidetone_frequency-100; + transmitter->filter_high=cw_keyer_sidetone_frequency+100; + freq=(double)(cw_keyer_sidetone_frequency+100); + break; } - SetChannelState(CHANNEL_RX0,1,0); + + SetTXABandpassFreqs(transmitter->id,transmitter->filter_low,transmitter->filter_high); + + + SetTXAMode(transmitter->id,modeDIGU); + SetTXAPostGenMode(transmitter->id,0); + SetTXAPostGenToneMag(transmitter->id,0.99999); + SetTXAPostGenRun(transmitter->id,1); + } else { + SetTXAPostGenRun(transmitter->id,0); + SetTXAMode(transmitter->id,transmitter->mode); + transmitter->filter_low=pre_tune_filter_low; + transmitter->filter_high=pre_tune_filter_high; + SetTXABandpassFreqs(transmitter->id,transmitter->filter_low,transmitter->filter_high); } + rxtx(tune); } } @@ -353,30 +730,32 @@ int isTransmitting() { void setFrequency(long long f) { BAND *band=band_get_current_band(); BANDSTACK_ENTRY* entry=bandstack_entry_get_current(); + int v=active_receiver->id; switch(protocol) { case NEW_PROTOCOL: case ORIGINAL_PROTOCOL: - if(ctun) { - long long minf=entry->frequencyA-(long long)(sample_rate/2); - long long maxf=entry->frequencyA+(long long)(sample_rate/2); + if(vfo[v].ctun) { + long long minf=vfo[v].frequency-(long long)(active_receiver->sample_rate/2); + long long maxf=vfo[v].frequency+(long long)(active_receiver->sample_rate/2); if(fmaxf) f=maxf; - ddsOffset=f-entry->frequencyA; - wdsp_set_offset(ddsOffset); + vfo[v].offset=f-vfo[v].frequency; + set_offset(active_receiver,vfo[v].offset); return; } else { - entry->frequencyA=f; + //entry->frequency=f; + vfo[v].frequency=f; } break; #ifdef LIMESDR case LIMESDR_PROTOCOL: { - long long minf=entry->frequencyA-(long long)(sample_rate/2); - long long maxf=entry->frequencyA+(long long)(sample_rate/2); + long long minf=entry->frequency-(long long)(active_receiver->sample_rate/2); + long long maxf=entry->frequency+(long long)(active_receiver->sample_rate/2); if(fmaxf) f=maxf; - ddsOffset=f-entry->frequencyA; + ddsOffset=f-entry->frequency; wdsp_set_offset(ddsOffset); return; } @@ -384,14 +763,9 @@ void setFrequency(long long f) { #endif } - displayFrequency=f; - ddsFrequency=f; - if(band->frequencyLO!=0LL) { - ddsFrequency=f-band->frequencyLO; - } switch(protocol) { case NEW_PROTOCOL: - schedule_high_priority(5); + schedule_high_priority(); break; case ORIGINAL_PROTOCOL: schedule_frequency_changed(); @@ -407,7 +781,7 @@ void setFrequency(long long f) { } long long getFrequency() { - return ddsFrequency; + return vfo[active_receiver->id].frequency; } double getDrive() { @@ -416,28 +790,31 @@ double getDrive() { static int calcLevel(double d) { int level=0; - BAND *band=band_get_current_band(); + int v=VFO_A; + if(split) v=VFO_B; + + BAND *band=band_get_band(vfo[v].band); double target_dbm = 10.0 * log10(d * 1000.0); double gbb=band->pa_calibration; target_dbm-=gbb; double target_volts = sqrt(pow(10, target_dbm * 0.1) * 0.05); double volts=min((target_volts / 0.8), 1.0); - double v=volts*(1.0/0.98); + double actual_volts=volts*(1.0/0.98); - if(v<0.0) { - v=0.0; - } else if(v>1.0) { - v=1.0; + if(actual_volts<0.0) { + actual_volts=0.0; + } else if(actual_volts>1.0) { + actual_volts=1.0; } - level=(int)(v*255.0); + level=(int)(actual_volts*255.0); return level; } void calcDriveLevel() { drive_level=calcLevel(drive); if(mox && protocol==NEW_PROTOCOL) { - schedule_high_priority(6); + schedule_high_priority(); } } @@ -453,7 +830,7 @@ double getTuneDrive() { void calcTuneDriveLevel() { tune_drive_level=calcLevel(tune_drive); if(tune && protocol==NEW_PROTOCOL) { - schedule_high_priority(7); + schedule_high_priority(); } } @@ -463,10 +840,9 @@ void setTuneDrive(double value) { } void set_attenuation(int value) { - //attenuation=value; switch(protocol) { case NEW_PROTOCOL: - schedule_high_priority(8); + schedule_high_priority(); break; #ifdef LIMESDR case LIMESDR_PROTOCOL: @@ -477,13 +853,15 @@ void set_attenuation(int value) { } int get_attenuation() { - return attenuation; + return active_receiver->attenuation; } void set_alex_rx_antenna(int v) { - //alex_rx_antenna=v; - if(protocol==NEW_PROTOCOL) { - schedule_high_priority(1); + if(active_receiver->id==0) { + active_receiver->alex_antenna=v; + if(protocol==NEW_PROTOCOL) { + schedule_high_priority(); + } } #ifdef LIMESDR if(protocol==LIMESDR_PROTOCOL) { @@ -493,16 +871,18 @@ void set_alex_rx_antenna(int v) { } void set_alex_tx_antenna(int v) { - //alex_tx_antenna=v; + transmitter->alex_antenna=v; if(protocol==NEW_PROTOCOL) { - schedule_high_priority(2); + schedule_high_priority(); } } void set_alex_attenuation(int v) { - //alex_attenuation=v; - if(protocol==NEW_PROTOCOL) { - schedule_high_priority(0); + if(active_receiver->id==0) { + active_receiver->alex_attenuation=v; + if(protocol==NEW_PROTOCOL) { + schedule_high_priority(); + } } } @@ -513,12 +893,14 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path); sem_wait(&property_sem); loadProperties(property_path); + value=getProperty("buffer_size"); + if(value) buffer_size=atoi(value); + value=getProperty("fft_size"); + if(value) fft_size=atoi(value); value=getProperty("atlas_penelope"); if(value) atlas_penelope=atoi(value); value=getProperty("tx_out_of_band"); if(value) tx_out_of_band=atoi(value); - value=getProperty("sample_rate"); - if(value) sample_rate=atoi(value); value=getProperty("filter_board"); if(value) filter_board=atoi(value); /* @@ -529,8 +911,6 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path); */ value=getProperty("updates_per_second"); if(value) updates_per_second=atoi(value); - value=getProperty("display_panadapter"); - if(value) display_panadapter=atoi(value); value=getProperty("display_filled"); if(value) display_filled=atoi(value); value=getProperty("display_detector_mode"); @@ -543,22 +923,20 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path); if(value) panadapter_high=atoi(value); value=getProperty("panadapter_low"); if(value) panadapter_low=atoi(value); - value=getProperty("display_waterfall"); - if(value) display_waterfall=atoi(value); value=getProperty("display_sliders"); if(value) display_sliders=atoi(value); +/* value=getProperty("display_toolbar"); if(value) display_toolbar=atoi(value); - value=getProperty("toolbar_dialog_buttons"); - if(value) toolbar_dialog_buttons=atoi(value); +*/ value=getProperty("waterfall_high"); if(value) waterfall_high=atoi(value); value=getProperty("waterfall_low"); if(value) waterfall_low=atoi(value); value=getProperty("waterfall_automatic"); if(value) waterfall_automatic=atoi(value); - value=getProperty("volume"); - if(value) volume=atof(value); +// value=getProperty("volume"); +// if(value) volume=atof(value); value=getProperty("drive"); if(value) drive=atof(value); value=getProperty("tune_drive"); @@ -577,38 +955,14 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path); if(value) mic_bias_enabled=atof(value); value=getProperty("mic_ptt_tip_bias_ring"); if(value) mic_ptt_tip_bias_ring=atof(value); - value=getProperty("nr_none"); - if(value) nr_none=atoi(value); - value=getProperty("nr"); - if(value) nr=atoi(value); - value=getProperty("nr2"); - if(value) nr2=atoi(value); - value=getProperty("nb"); - if(value) nb=atoi(value); - value=getProperty("nb2"); - if(value) nb2=atoi(value); - value=getProperty("anf"); - if(value) anf=atoi(value); - value=getProperty("snb"); - if(value) snb=atoi(value); - value=getProperty("nr_agc"); - if(value) nr_agc=atoi(value); - value=getProperty("nr2_gain_method"); - if(value) nr2_gain_method=atoi(value); - value=getProperty("nr2_npe_method"); - if(value) nr2_npe_method=atoi(value); - value=getProperty("nr2_ae"); - if(value) nr2_ae=atoi(value); - value=getProperty("agc"); - if(value) agc=atoi(value); - value=getProperty("agc_gain"); - if(value) agc_gain=atof(value); - value=getProperty("agc_slope"); - if(value) agc_slope=atof(value); - value=getProperty("agc_hang_threshold"); - if(value) agc_hang_threshold=atof(value); + + value=getProperty("tx_filter_low"); + if(value) tx_filter_low=atoi(value); + value=getProperty("tx_filter_high"); + if(value) tx_filter_high=atoi(value); + value=getProperty("step"); - if(value) step=atoi(value); + if(value) step=atoll(value); value=getProperty("cw_keys_reversed"); if(value) cw_keys_reversed=atoi(value); value=getProperty("cw_keyer_speed"); @@ -643,14 +997,6 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path); if(value) OCfull_tune_time=atoi(value); value=getProperty("OCmemory_tune_time"); if(value) OCmemory_tune_time=atoi(value); - value=getProperty("attenuation"); - if(value) attenuation=atoi(value); - value=getProperty("rx_dither"); - if(value) rx_dither=atoi(value); - value=getProperty("rx_random"); - if(value) rx_random=atoi(value); - value=getProperty("rx_preamp"); - if(value) rx_preamp=atoi(value); #ifdef FREEDV strcpy(freedv_tx_text_data,"NO TEXT DATA"); value=getProperty("freedv_tx_text_data"); @@ -660,14 +1006,16 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path); if(value) smeter=atoi(value); value=getProperty("alc"); if(value) alc=atoi(value); +#ifdef OLD_AUDIO value=getProperty("local_audio"); if(value) local_audio=atoi(value); value=getProperty("n_selected_output_device"); if(value) n_selected_output_device=atoi(value); +#endif value=getProperty("local_microphone"); if(value) local_microphone=atoi(value); - value=getProperty("n_selected_input_device"); - if(value) n_selected_input_device=atoi(value); +// value=getProperty("n_selected_input_device"); +// if(value) n_selected_input_device=atoi(value); value=getProperty("enable_tx_equalizer"); if(value) enable_tx_equalizer=atoi(value); value=getProperty("tx_equalizer.0"); @@ -709,21 +1057,50 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path); value=getProperty("binaural"); if(value) binaural=atoi(value); + value=getProperty("frequencyB"); + if(value) frequencyB=atol(value); + + value=getProperty("modeB"); + if(value) modeB=atoi(value); + + value=getProperty("filterB"); + if(value) filterB=atoi(value); + +#ifdef GPIO + value=getProperty("e1_encoder_action"); + if(value) e1_encoder_action=atoi(value); + value=getProperty("e2_encoder_action"); + if(value) e2_encoder_action=atoi(value); + value=getProperty("e3_encoder_action"); + if(value) e3_encoder_action=atoi(value); +#endif + + value=getProperty("receivers"); + if(value) receivers=atoi(value); + + filterRestoreState(); bandRestoreState(); + memRestoreState(); + vfo_restore_state(); sem_post(&property_sem); } void radioSaveState() { + int i; char value[80]; sem_wait(&property_sem); + sprintf(value,"%d",buffer_size); + setProperty("buffer_size",value); + sprintf(value,"%d",fft_size); + setProperty("fft_size",value); sprintf(value,"%d",atlas_penelope); setProperty("atlas_penelope",value); - sprintf(value,"%d",sample_rate); - setProperty("sample_rate",value); sprintf(value,"%d",filter_board); setProperty("filter_board",value); + sprintf(value,"%d",tx_out_of_band); + setProperty("tx_out_of_band",value); /* sprintf(value,"%d",apollo_tuner); setProperty("apollo_tuner",value); @@ -732,8 +1109,6 @@ void radioSaveState() { */ sprintf(value,"%d",updates_per_second); setProperty("updates_per_second",value); - sprintf(value,"%d",display_panadapter); - setProperty("display_panadapter",value); sprintf(value,"%d",display_filled); setProperty("display_filled",value); sprintf(value,"%d",display_detector_mode); @@ -746,22 +1121,20 @@ void radioSaveState() { setProperty("panadapter_high",value); sprintf(value,"%d",panadapter_low); setProperty("panadapter_low",value); - sprintf(value,"%d",display_waterfall); - setProperty("display_waterfall",value); sprintf(value,"%d",display_sliders); setProperty("display_sliders",value); +/* sprintf(value,"%d",display_toolbar); setProperty("display_toolbar",value); - sprintf(value,"%d",toolbar_dialog_buttons); - setProperty("toolbar_dialog_buttons",value); +*/ sprintf(value,"%d",waterfall_high); setProperty("waterfall_high",value); sprintf(value,"%d",waterfall_low); setProperty("waterfall_low",value); sprintf(value,"%d",waterfall_automatic); setProperty("waterfall_automatic",value); - sprintf(value,"%f",volume); - setProperty("volume",value); +// sprintf(value,"%f",volume); +// setProperty("volume",value); sprintf(value,"%f",mic_gain); setProperty("mic_gain",value); sprintf(value,"%f",drive); @@ -780,37 +1153,12 @@ void radioSaveState() { setProperty("mic_bias_enabled",value); sprintf(value,"%d",mic_ptt_tip_bias_ring); setProperty("mic_ptt_tip_bias_ring",value); - sprintf(value,"%d",nr_none); - setProperty("nr_none",value); - sprintf(value,"%d",nr); - setProperty("nr",value); - sprintf(value,"%d",nr2); - setProperty("nr2",value); - sprintf(value,"%d",nb); - setProperty("nb",value); - sprintf(value,"%d",nb2); - setProperty("nb2",value); - sprintf(value,"%d",anf); - setProperty("anf",value); - sprintf(value,"%d",snb); - setProperty("snb",value); - sprintf(value,"%d",nr_agc); - setProperty("nr_agc",value); - sprintf(value,"%d",nr2_gain_method); - setProperty("nr2_gain_method",value); - sprintf(value,"%d",nr2_npe_method); - setProperty("nr2_npe_method",value); - sprintf(value,"%d",nr2_ae); - setProperty("nr2_ae",value); - sprintf(value,"%d",agc); - setProperty("agc",value); - sprintf(value,"%f",agc_gain); - setProperty("agc_gain",value); - sprintf(value,"%f",agc_slope); - setProperty("agc_slope",value); - sprintf(value,"%f",agc_hang_threshold); - setProperty("agc_hang_threshold",value); - sprintf(value,"%d",step); + sprintf(value,"%d",tx_filter_low); + setProperty("tx_filter_low",value); + sprintf(value,"%d",tx_filter_high); + setProperty("tx_filter_high",value); + + sprintf(value,"%lld",step); setProperty("step",value); sprintf(value,"%d",cw_keys_reversed); setProperty("cw_keys_reversed",value); @@ -844,14 +1192,6 @@ void radioSaveState() { setProperty("OCfull_tune_time",value); sprintf(value,"%d",OCmemory_tune_time); setProperty("OCmemory_tune_time",value); - sprintf(value,"%d",attenuation); - setProperty("attenuation",value); - sprintf(value,"%d",rx_dither); - setProperty("rx_dither",value); - sprintf(value,"%d",rx_random); - setProperty("rx_random",value); - sprintf(value,"%d",rx_preamp); - setProperty("rx_preamp",value); #ifdef FREEDV if(strlen(freedv_tx_text_data)>0) { setProperty("freedv_tx_text_data",freedv_tx_text_data); @@ -861,14 +1201,16 @@ void radioSaveState() { setProperty("smeter",value); sprintf(value,"%d",alc); setProperty("alc",value); +#ifdef OLD_AUDIO sprintf(value,"%d",local_audio); setProperty("local_audio",value); sprintf(value,"%d",n_selected_output_device); setProperty("n_selected_output_device",value); +#endif sprintf(value,"%d",local_microphone); setProperty("local_microphone",value); - sprintf(value,"%d",n_selected_input_device); - setProperty("n_selected_input_device",value); +// sprintf(value,"%d",n_selected_input_device); +// setProperty("n_selected_input_device",value); sprintf(value,"%d",enable_tx_equalizer); setProperty("enable_tx_equalizer",value); @@ -911,19 +1253,45 @@ void radioSaveState() { sprintf(value,"%d",binaural); setProperty("binaural",value); - bandSaveState(); + sprintf(value,"%lld",frequencyB); + setProperty("frequencyB",value); + sprintf(value,"%d",modeB); + setProperty("modeB",value); + sprintf(value,"%d",filterB); + setProperty("filterB",value); + +#ifdef GPIO + sprintf(value,"%d",e1_encoder_action); + setProperty("e1_encoder_action",value); + sprintf(value,"%d",e2_encoder_action); + setProperty("e2_encoder_action",value); + sprintf(value,"%d",e3_encoder_action); + setProperty("e3_encoder_action",value); +#endif + + vfo_save_state(); + sprintf(value,"%d",receivers); + setProperty("receivers",value); + for(i=0;ifps * t)); + display_average = max(2, (int)min(60, (double)rx->fps * t)); + SetDisplayAvBackmult(rx->id, 0, display_avb); + SetDisplayNumAverage(rx->id, 0, display_average); } diff --git a/radio.h b/radio.h index 9008961..0c41d56 100644 --- a/radio.h +++ b/radio.h @@ -21,6 +21,8 @@ #define _RADIO_H #include "discovered.h" +#include "receiver.h" +#include "transmitter.h" #define NEW_MIC_IN 0x00 #define NEW_LINE_IN 0x01 @@ -51,8 +53,14 @@ extern char property_path[]; #define ALEX 1 #define APOLLO 2 -// soecify how many receivers (only 1 or 2 for now) -#define RECEIVERS 1 +// specify how many receivers (only 1 or 2 for now) +#define MAX_RECEIVERS 2 +#define RECEIVERS 2 + +extern RECEIVER *receiver[]; +extern RECEIVER *active_receiver; + +extern TRANSMITTER *transmitter; /* #define PA_DISABLED 0 @@ -64,9 +72,12 @@ extern char property_path[]; #define KEYER_MODE_A 1 #define KEYER_MODE_B 2 -extern int rx_dither; -extern int rx_random; -extern int rx_preamp; +extern int echo; + +#define MAX_BUFFER_SIZE 2048 + +extern int buffer_size; +extern int fft_size; extern int atlas_penelope; extern int atlas_clock_source_10mhz; @@ -84,7 +95,6 @@ extern int tx_leveler; extern double tone_level; -extern int sample_rate; extern int filter_board; extern int pa; extern int apollo_tuner; @@ -107,28 +117,9 @@ extern int waterfall_automatic; extern int display_sliders; extern int display_toolbar; -extern int toolbar_dialog_buttons; -extern double volume; extern double mic_gain; extern int binaural; -extern int agc; -extern double agc_gain; -extern double agc_slope; -extern double agc_hang_threshold; - -extern int nr_none; -extern int nr; -extern int nr2; -extern int nb; -extern int nb2; -extern int anf; -extern int snb; - -extern int nr_agc; -extern int nr2_gain_method; -extern int nr2_npe_method; -extern int nr2_ae; extern int mic_linein; extern int linein_gain; @@ -144,14 +135,13 @@ extern int tune_drive_level; extern int drive_level; int receivers; -int active_receiver; int adc[2]; int locked; -extern int step; -extern int rit; +extern long long step; +//extern int rit; extern int rit_increment; extern int lt2208Dither; @@ -183,6 +173,8 @@ extern int mercury_software_version; extern int penelope_software_version; extern int mox; extern int tune; +extern int memory_tune; +extern int full_tune; extern int ptt; extern int dot; extern int dash; @@ -199,9 +191,15 @@ extern unsigned int AIN4; extern unsigned int AIN6; extern int supply_volts; -extern long long displayFrequency; -extern long long ddsFrequency; -extern long long ddsOffset; +//extern long long displayFrequency; +//extern long long ddsFrequency; +//extern long long ddsOffset; + +extern long long frequencyB; +extern int modeB; +extern int filterB; + +extern int split; extern unsigned char OCtune; extern int OCfull_tune_time; @@ -215,8 +213,8 @@ extern char freedv_tx_text_data[64]; extern int smeter; extern int alc; -extern int local_audio; -extern int local_microphone; +//extern int local_audio; +//extern int local_microphone; extern int eer_pwm_min; extern int eer_pwm_max; @@ -235,6 +233,7 @@ extern int rx_equalizer[4]; extern int deviation; extern int pre_emphasize; +extern int vox_setting; extern int vox_enabled; extern double vox_threshold; extern double vox_gain; @@ -245,9 +244,11 @@ extern int diversity_enabled; extern double i_rotate[2]; extern double q_rotate[2]; +extern void reconfigure_radio(); +extern void start_radio(); extern void init_radio(); -extern void setSampleRate(int rate); -extern int getSampleRate(); +extern void radio_change_receivers(int r); +extern void radio_change_sample_rate(int rate); extern void setMox(int state); extern int getMox(); extern void setTune(int state); diff --git a/radio_menu.c b/radio_menu.c new file mode 100644 index 0000000..8e62c11 --- /dev/null +++ b/radio_menu.c @@ -0,0 +1,407 @@ +/* Copyright (C) +* 2015 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#include +#include +#include +#include + +#include "new_menu.h" +#include "radio_menu.h" +#include "band.h" +#include "filter.h" +#include "radio.h" +#include "receiver.h" + +static GtkWidget *parent_window=NULL; + +static GtkWidget *menu_b=NULL; + +static GtkWidget *dialog=NULL; + +static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { + if(dialog!=NULL) { + gtk_widget_destroy(dialog); + dialog=NULL; + sub_menu=NULL; + } + return TRUE; +} + +static void vfo_divisor_value_changed_cb(GtkWidget *widget, gpointer data) { + vfo_encoder_divisor=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); +} + +/* +static void toolbar_dialog_buttons_cb(GtkWidget *widget, gpointer data) { + toolbar_dialog_buttons=toolbar_dialog_buttons==1?0:1; + update_toolbar_labels(); +} +*/ + +static void ptt_cb(GtkWidget *widget, gpointer data) { + mic_ptt_enabled=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); +} + +static void ptt_ring_cb(GtkWidget *widget, gpointer data) { + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { + mic_ptt_tip_bias_ring=0; + } +} + +static void ptt_tip_cb(GtkWidget *widget, gpointer data) { + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { + mic_ptt_tip_bias_ring=1; + } +} + +static void bias_cb(GtkWidget *widget, gpointer data) { + mic_bias_enabled=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); +} + +static void apollo_cb(GtkWidget *widget, gpointer data); + +static void alex_cb(GtkWidget *widget, gpointer data) { + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { + if(filter_board==ALEX) { + filter_board=NONE; + } else if(filter_board==NONE) { + filter_board=ALEX; + } else if(filter_board==APOLLO) { + GtkWidget *w=(GtkWidget *)data; + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), FALSE); + filter_board=ALEX; + } + + if(protocol==NEW_PROTOCOL) { + filter_board_changed(); + } + + if(filter_board==ALEX) { + BAND *band=band_get_current_band(); + BANDSTACK_ENTRY* entry=bandstack_entry_get_current(); + setFrequency(entry->frequency); + //setMode(entry->mode); + set_mode(active_receiver,entry->mode); + FILTER* band_filters=filters[entry->mode]; + FILTER* band_filter=&band_filters[entry->filter]; + //setFilter(band_filter->low,band_filter->high); + set_filter(active_receiver,band_filter->low,band_filter->high); + if(active_receiver->id==0) { + set_alex_rx_antenna(band->alexRxAntenna); + set_alex_tx_antenna(band->alexTxAntenna); + set_alex_attenuation(band->alexAttenuation); + } + } + } +} + +static void apollo_cb(GtkWidget *widget, gpointer data) { + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { + if(filter_board==APOLLO) { + filter_board=NONE; + } else if(filter_board==NONE) { + filter_board=APOLLO; + } else if(filter_board==ALEX) { + GtkWidget *w=(GtkWidget *)data; + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), FALSE); + filter_board=APOLLO; + } + if(protocol==NEW_PROTOCOL) { + filter_board_changed(); + } + + if(filter_board==APOLLO) { + BAND *band=band_get_current_band(); + BANDSTACK_ENTRY* entry=bandstack_entry_get_current(); + setFrequency(entry->frequency); + //setMode(entry->mode); + set_mode(active_receiver,entry->mode); + FILTER* band_filters=filters[entry->mode]; + FILTER* band_filter=&band_filters[entry->filter]; + //setFilter(band_filter->low,band_filter->high); + set_filter(active_receiver,band_filter->low,band_filter->high); + } + } +} + +static void sample_rate_cb(GtkWidget *widget, gpointer data) { + radio_change_sample_rate((int)data); +} + +static void receivers_cb(GtkWidget *widget, gpointer data) { + radio_change_receivers((int)data); +} + +static void rit_cb(GtkWidget *widget,gpointer data) { + rit_increment=(int)data; +} + +static void ck10mhz_cb(GtkWidget *widget, gpointer data) { + atlas_clock_source_10mhz = (int)data; +} + +static void ck128mhz_cb(GtkWidget *widget, gpointer data) { + atlas_clock_source_128mhz=atlas_clock_source_128mhz==1?0:1; +} + +static void micsource_cb(GtkWidget *widget, gpointer data) { + atlas_mic_source=atlas_mic_source==1?0:1; +} + +static void penelopetx_cb(GtkWidget *widget, gpointer data) { + atlas_penelope=atlas_penelope==1?0:1; +} + +void radio_menu(GtkWidget *parent) { + parent_window=parent; + + dialog=gtk_dialog_new(); + gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window)); + gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE); + + GdkRGBA color; + color.red = 1.0; + color.green = 1.0; + color.blue = 1.0; + color.alpha = 1.0; + gtk_widget_override_background_color(dialog,GTK_STATE_FLAG_NORMAL,&color); + + GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + + GtkWidget *grid=gtk_grid_new(); + gtk_grid_set_column_spacing (GTK_GRID(grid),10); + //gtk_grid_set_row_spacing (GTK_GRID(grid),10); + //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE); + //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE); + + GtkWidget *close_b=gtk_button_new_with_label("Close"); + g_signal_connect (close_b, "button_press_event", G_CALLBACK(close_cb), NULL); + gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1); + + int x=0; + + GtkWidget *receivers_label=gtk_label_new("Receivers: "); + gtk_grid_attach(GTK_GRID(grid),receivers_label,x,1,1,1); + + GtkWidget *receivers_1=gtk_radio_button_new_with_label(NULL,"1"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (receivers_1), receivers==1); + gtk_grid_attach(GTK_GRID(grid),receivers_1,x,2,1,1); + g_signal_connect(receivers_1,"pressed",G_CALLBACK(receivers_cb),(gpointer *)1); + + GtkWidget *receivers_2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(receivers_1),"2"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (receivers_2), receivers==2); + gtk_grid_attach(GTK_GRID(grid),receivers_2,x,3,1,1); + g_signal_connect(receivers_2,"pressed",G_CALLBACK(receivers_cb),(gpointer *)2); + + x++; + + switch(protocol) { + case ORIGINAL_PROTOCOL: + { + GtkWidget *sample_rate_label=gtk_label_new("Sample Rate:"); + gtk_grid_attach(GTK_GRID(grid),sample_rate_label,x,1,1,1); + + GtkWidget *sample_rate_48=gtk_radio_button_new_with_label(NULL,"48000"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_48), active_receiver->sample_rate==48000); + gtk_grid_attach(GTK_GRID(grid),sample_rate_48,x,2,1,1); + g_signal_connect(sample_rate_48,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)48000); + + GtkWidget *sample_rate_96=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_48),"96000"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_96), active_receiver->sample_rate==96000); + gtk_grid_attach(GTK_GRID(grid),sample_rate_96,x,3,1,1); + g_signal_connect(sample_rate_96,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)96000); + + GtkWidget *sample_rate_192=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_96),"192000"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_192), active_receiver->sample_rate==192000); + gtk_grid_attach(GTK_GRID(grid),sample_rate_192,x,4,1,1); + g_signal_connect(sample_rate_192,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)192000); + + GtkWidget *sample_rate_384=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_192),"384000"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_384), active_receiver->sample_rate==384000); + gtk_grid_attach(GTK_GRID(grid),sample_rate_384,x,5,1,1); + g_signal_connect(sample_rate_384,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)384000); + + if(protocol==NEW_PROTOCOL) { + GtkWidget *sample_rate_768=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_384),"768000"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_768), active_receiver->sample_rate==768000); + gtk_grid_attach(GTK_GRID(grid),sample_rate_768,x,6,1,1); + g_signal_connect(sample_rate_768,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)768000); + + GtkWidget *sample_rate_1536=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_768),"1536000"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_1536), active_receiver->sample_rate==1536000); + gtk_grid_attach(GTK_GRID(grid),sample_rate_1536,x,7,1,1); + g_signal_connect(sample_rate_1536,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)1536000); + + #ifdef GPIO + gtk_widget_set_sensitive(sample_rate_768,FALSE); + gtk_widget_set_sensitive(sample_rate_1536,FALSE); + #endif + } + x++; + } + break; + +#ifdef LIMESDR + case LIMESDR_PROTOCOL: + { + GtkWidget *sample_rate_label=gtk_label_new("Sample Rate:"); + gtk_grid_attach(GTK_GRID(grid),sample_rate_label,x,1,1,1); + + GtkWidget *sample_rate_1M=gtk_radio_button_new_with_label(NULL,"1000000"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_1M), active_receiver->sample_rate==1000000); + gtk_grid_attach(GTK_GRID(grid),sample_rate_1M,x,2,1,1); + g_signal_connect(sample_rate_1M,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)1000000); + + GtkWidget *sample_rate_2M=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_1M),"2000000"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_2M), active_receiver->sample_rate==2000000); + gtk_grid_attach(GTK_GRID(grid),sample_rate_2M,x,3,1,1); + g_signal_connect(sample_rate_2M,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)2000000); + x++; + } + break; +#endif + + + } + + + if(protocol==ORIGINAL_PROTOCOL || protocol==NEW_PROTOCOL) { + + if((protocol==NEW_PROTOCOL && device==NEW_DEVICE_ORION) || + (protocol==NEW_PROTOCOL && device==NEW_DEVICE_ORION2) || + (protocol==ORIGINAL_PROTOCOL && device==DEVICE_ORION) || + (protocol==ORIGINAL_PROTOCOL && device==DEVICE_ORION2)) { + + GtkWidget *ptt_ring_b=gtk_radio_button_new_with_label(NULL,"PTT On Ring, Mic and Bias on Tip"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptt_ring_b), mic_ptt_tip_bias_ring==0); + gtk_grid_attach(GTK_GRID(grid),ptt_ring_b,x,1,1,1); + g_signal_connect(ptt_ring_b,"toggled",G_CALLBACK(ptt_ring_cb),NULL); + + GtkWidget *ptt_tip_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ptt_ring_b),"PTT On Tip, Mic and Bias on Ring"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptt_tip_b), mic_ptt_tip_bias_ring==1); + gtk_grid_attach(GTK_GRID(grid),ptt_tip_b,x,2,1,1); + g_signal_connect(ptt_tip_b,"toggled",G_CALLBACK(ptt_tip_cb),NULL); + + GtkWidget *ptt_b=gtk_check_button_new_with_label("PTT Enabled"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptt_b), mic_ptt_enabled); + gtk_grid_attach(GTK_GRID(grid),ptt_b,x,3,1,1); + g_signal_connect(ptt_b,"toggled",G_CALLBACK(ptt_cb),NULL); + + GtkWidget *bias_b=gtk_check_button_new_with_label("BIAS Enabled"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bias_b), mic_bias_enabled); + gtk_grid_attach(GTK_GRID(grid),bias_b,x,4,1,1); + g_signal_connect(bias_b,"toggled",G_CALLBACK(bias_cb),NULL); + + x++; + } + + GtkWidget *alex_b=gtk_check_button_new_with_label("ALEX"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (alex_b), filter_board==ALEX); + gtk_grid_attach(GTK_GRID(grid),alex_b,x,1,1,1); + + GtkWidget *apollo_b=gtk_check_button_new_with_label("APOLLO"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (apollo_b), filter_board==APOLLO); + gtk_grid_attach(GTK_GRID(grid),apollo_b,x,2,1,1); + + g_signal_connect(alex_b,"toggled",G_CALLBACK(alex_cb),apollo_b); + g_signal_connect(apollo_b,"toggled",G_CALLBACK(apollo_cb),alex_b); + + x++; + } + + + GtkWidget *rit_label=gtk_label_new("RIT step: "); + gtk_grid_attach(GTK_GRID(grid),rit_label,x,1,1,1); + + GtkWidget *rit_1=gtk_radio_button_new_with_label(NULL,"1 Hz"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rit_1), rit_increment==1); + gtk_grid_attach(GTK_GRID(grid),rit_1,x,2,1,1); + g_signal_connect(rit_1,"pressed",G_CALLBACK(rit_cb),(gpointer *)1); + + GtkWidget *rit_10=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(rit_1),"10"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rit_10), rit_increment==10); + gtk_grid_attach(GTK_GRID(grid),rit_10,x,3,1,1); + g_signal_connect(rit_10,"pressed",G_CALLBACK(rit_cb),(gpointer *)10); + + GtkWidget *rit_100=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(rit_10),"100"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rit_100), rit_increment==100); + gtk_grid_attach(GTK_GRID(grid),rit_100,x,4,1,1); + g_signal_connect(rit_100,"pressed",G_CALLBACK(rit_cb),(gpointer *)100); + + x++; + + GtkWidget *vfo_divisor_label=gtk_label_new("VFO Encoder Divisor: "); + gtk_grid_attach(GTK_GRID(grid),vfo_divisor_label,x,1,1,1); + + GtkWidget *vfo_divisor=gtk_spin_button_new_with_range(1.0,60.0,1.0); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(vfo_divisor),(double)vfo_encoder_divisor); + gtk_grid_attach(GTK_GRID(grid),vfo_divisor,x,2,1,1); + g_signal_connect(vfo_divisor,"value_changed",G_CALLBACK(vfo_divisor_value_changed_cb),NULL); + + x++; + +#ifdef USBOZY + if (protocol==ORIGINAL_PROTOCOL && (device == DEVICE_OZY) || (device == DEVICE_METIS)) +#else + if (protocol==ORIGINAL_PROTOCOL && radio->device == DEVICE_METIS) +#endif + { + GtkWidget *atlas_label=gtk_label_new("Atlas bus: "); + gtk_grid_attach(GTK_GRID(grid),atlas_label,x,1,1,1); + + GtkWidget *ck10mhz_1=gtk_radio_button_new_with_label(NULL,"10MHz clock=Atlas"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ck10mhz_1), atlas_clock_source_10mhz==0); + gtk_grid_attach(GTK_GRID(grid),ck10mhz_1,x,2,1,1); + g_signal_connect(ck10mhz_1,"toggled",G_CALLBACK(ck10mhz_cb),(gpointer *)0); + + GtkWidget *ck10mhz_2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ck10mhz_1),"10MHz clock=Penelope"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ck10mhz_2), atlas_clock_source_10mhz==1); + gtk_grid_attach(GTK_GRID(grid),ck10mhz_2,x,3,1,1); + g_signal_connect(ck10mhz_2,"toggled",G_CALLBACK(ck10mhz_cb),(gpointer *)1); + + GtkWidget *ck10mhz_3=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ck10mhz_2),"10MHz clock=Mercury"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ck10mhz_3), atlas_clock_source_10mhz==2); + gtk_grid_attach(GTK_GRID(grid),ck10mhz_3,x,4,1,1); + g_signal_connect(ck10mhz_3,"toggled",G_CALLBACK(ck10mhz_cb),(gpointer *)2); + + GtkWidget *ck128_b=gtk_check_button_new_with_label("122.88MHz ck=Mercury"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ck128_b), atlas_clock_source_128mhz); + gtk_grid_attach(GTK_GRID(grid),ck128_b,x,5,1,1); + g_signal_connect(ck128_b,"toggled",G_CALLBACK(ck128mhz_cb),NULL); + + GtkWidget *mic_src_b=gtk_check_button_new_with_label("Mic src=Penelope"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mic_src_b), atlas_mic_source); + gtk_grid_attach(GTK_GRID(grid),mic_src_b,x,6,1,1); + g_signal_connect(mic_src_b,"toggled",G_CALLBACK(micsource_cb),NULL); + + GtkWidget *pene_tx_b=gtk_check_button_new_with_label("Penelope TX"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pene_tx_b), atlas_penelope); + gtk_grid_attach(GTK_GRID(grid),pene_tx_b,x,7,1,1); + g_signal_connect(pene_tx_b,"toggled",G_CALLBACK(penelopetx_cb),NULL); + } + + gtk_container_add(GTK_CONTAINER(content),grid); + + sub_menu=dialog; + + gtk_widget_show_all(dialog); + +} + diff --git a/radio_menu.h b/radio_menu.h new file mode 100644 index 0000000..9cd8b93 --- /dev/null +++ b/radio_menu.h @@ -0,0 +1,20 @@ +/* Copyright (C) +* 2015 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +extern void general_menu(GtkWidget *parent); diff --git a/receiver.c b/receiver.c new file mode 100644 index 0000000..cbec540 --- /dev/null +++ b/receiver.c @@ -0,0 +1,1029 @@ +/* Copyright (C) +* 2017 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#include +#include +#include +#include + +#include + +#include "agc.h" +#include "band.h" +#include "bandstack.h" +#include "discovered.h" +#include "filter.h" +#include "main.h" +#include "meter.h" +#include "mode.h" +#include "new_protocol.h" +#include "old_protocol.h" +#include "property.h" +#include "radio.h" +#include "receiver.h" +#include "vfo.h" +#include "meter.h" +#include "rx_panadapter.h" +#include "sliders.h" +#include "waterfall.h" +#ifdef FREEDV +#include "freedv.h" +#endif + + +#define min(x,y) (xx; + if (event->button == 1) { + last_x=(int)event->x; + has_moved=FALSE; + pressed=TRUE; + } + } else { + making_active=TRUE; + } + return TRUE; +} + +gboolean receiver_button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer data) { + RECEIVER *rx=(RECEIVER *)data; + if(making_active) { + active_receiver=rx; + making_active=FALSE; + g_idle_add(vfo_update,NULL); + g_idle_add(active_receiver_changed,NULL); + } else { + int display_width=gtk_widget_get_allocated_width (rx->panadapter); + int display_height=gtk_widget_get_allocated_height (rx->panadapter); + if(pressed) { + int x=(int)event->x; + if (event->button == 1) { + if(has_moved) { + // drag + vfo_move((long long)((float)(x-last_x)*rx->hz_per_pixel)); + } else { + // move to this frequency + vfo_move_to((long long)((float)(x-(display_width/2))*rx->hz_per_pixel)); + } + last_x=x; + pressed=FALSE; + } + } + } + return TRUE; +} + +gboolean receiver_motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data) { + int x, y; + GdkModifierType state; + RECEIVER *rx=(RECEIVER *)data; + if(!making_active) { + gdk_window_get_device_position (event->window, + event->device, + &x, + &y, + &state); + if((state & GDK_BUTTON1_MASK == GDK_BUTTON1_MASK) || pressed) { + int moved=last_x-x; + vfo_move((long long)((float)moved*rx->hz_per_pixel)); + last_x=x; + has_moved=TRUE; + } + } + + return TRUE; +} + +gboolean receiver_scroll_event(GtkWidget *widget, GdkEventScroll *event, gpointer data) { + if(event->direction==GDK_SCROLL_UP) { + if(vfo[active_receiver->id].ctun) { + vfo_move(-step); + } else { + vfo_move(step); + } + } else { + if(vfo[active_receiver->id].ctun) { + vfo_move(step); + } else { + vfo_move(-step); + } + } + return TRUE; +} + +void receiver_save_state(RECEIVER *rx) { + char name[128]; + char value[128]; + + sprintf(name,"receiver.%d.sample_rate",rx->id); + sprintf(value,"%d",rx->sample_rate); + setProperty(name,value); + sprintf(name,"receiver.%d.adc",rx->id); + sprintf(value,"%d",rx->adc); + setProperty(name,value); + sprintf(name,"receiver.%d.filter_low",rx->id); + sprintf(value,"%d",rx->filter_low); + setProperty(name,value); + sprintf(name,"receiver.%d.filter_high",rx->id); + sprintf(value,"%d",rx->filter_high); + setProperty(name,value); + sprintf(name,"receiver.%d.fps",rx->id); + sprintf(value,"%d",rx->fps); + setProperty(name,value); + sprintf(name,"receiver.%d.panadapter_low",rx->id); + sprintf(value,"%d",rx->panadapter_low); + setProperty(name,value); + sprintf(name,"receiver.%d.panadapter_high",rx->id); + sprintf(value,"%d",rx->panadapter_high); + setProperty(name,value); + sprintf(name,"receiver.%d.display_waterfall",rx->id); + sprintf(value,"%d",rx->display_waterfall); + setProperty(name,value); + sprintf(name,"receiver.%d.waterfall_low",rx->id); + sprintf(value,"%d",rx->waterfall_low); + setProperty(name,value); + sprintf(name,"receiver.%d.waterfall_high",rx->id); + sprintf(value,"%d",rx->waterfall_high); + setProperty(name,value); + sprintf(name,"receiver.%d.waterfall_automatic",rx->id); + sprintf(value,"%d",rx->waterfall_automatic); + setProperty(name,value); + + sprintf(name,"receiver.%d.alex_antenna",rx->id); + sprintf(value,"%d",rx->alex_antenna); + setProperty(name,value); + sprintf(name,"receiver.%d.alex_attenuation",rx->id); + sprintf(value,"%d",rx->alex_attenuation); + setProperty(name,value); + sprintf(name,"receiver.%d.volume",rx->id); + sprintf(value,"%f",rx->volume); + setProperty(name,value); + sprintf(name,"receiver.%d.agc",rx->id); + sprintf(value,"%d",rx->agc); + setProperty(name,value); + sprintf(name,"receiver.%d.agc_gain",rx->id); + sprintf(value,"%f",rx->agc_gain); + setProperty(name,value); + sprintf(name,"receiver.%d.agc_slope",rx->id); + sprintf(value,"%f",rx->agc_slope); + setProperty(name,value); + sprintf(name,"receiver.%d.agc_hang_threshold",rx->id); + sprintf(value,"%f",rx->agc_hang_threshold); + setProperty(name,value); + sprintf(name,"receiver.%d.attenuation",rx->id); + sprintf(value,"%d",rx->attenuation); + setProperty(name,value); + + sprintf(name,"receiver.%d.dither",rx->id); + sprintf(value,"%d",rx->dither); + setProperty(name,value); + sprintf(name,"receiver.%d.random",rx->id); + sprintf(value,"%d",rx->random); + setProperty(name,value); + sprintf(name,"receiver.%d.preamp",rx->id); + sprintf(value,"%d",rx->preamp); + setProperty(name,value); + sprintf(name,"receiver.%d.nr",rx->id); + sprintf(value,"%d",rx->nr); + setProperty(name,value); + sprintf(name,"receiver.%d.nr2",rx->id); + sprintf(value,"%d",rx->nr2); + setProperty(name,value); + sprintf(name,"receiver.%d.anf",rx->id); + sprintf(value,"%d",rx->anf); + setProperty(name,value); + sprintf(name,"receiver.%d.snb",rx->id); + sprintf(value,"%d",rx->snb); + setProperty(name,value); + sprintf(name,"receiver.%d.nr_agc",rx->id); + sprintf(value,"%d",rx->nr_agc); + setProperty(name,value); + sprintf(name,"receiver.%d.nr2_gain_method",rx->id); + sprintf(value,"%d",rx->nr2_gain_method); + setProperty(name,value); + sprintf(name,"receiver.%d.nr2_npe_method",rx->id); + sprintf(value,"%d",rx->nr2_npe_method); + setProperty(name,value); + sprintf(name,"receiver.%d.nr2_ae",rx->id); + sprintf(value,"%d",rx->nr2_ae); + setProperty(name,value); + + sprintf(name,"receiver.%d.audio_channel",rx->id); + sprintf(value,"%d",rx->audio_channel); + setProperty(name,value); + sprintf(name,"receiver.%d.local_audio",rx->id); + sprintf(value,"%d",rx->local_audio); + setProperty(name,value); + sprintf(name,"receiver.%d.audio_device",rx->id); + sprintf(value,"%d",rx->audio_device); + setProperty(name,value); + +} + +void receiver_restore_state(RECEIVER *rx) { + char name[128]; + char *value; + +fprintf(stderr,"receiver_restore_state: id=%d\n",rx->id); + sprintf(name,"receiver.%d.sample_rate",rx->id); + value=getProperty(name); + if(value) rx->sample_rate=atoi(value); + sprintf(name,"receiver.%d.adc",rx->id); + value=getProperty(name); + if(value) rx->adc=atoi(value); + sprintf(name,"receiver.%d.filter_low",rx->id); + value=getProperty(name); + if(value) rx->filter_low=atoi(value); + sprintf(name,"receiver.%d.filter_high",rx->id); + value=getProperty(name); + if(value) rx->filter_high=atoi(value); + sprintf(name,"receiver.%d.fps",rx->id); + value=getProperty(name); + if(value) rx->fps=atoi(value); +/* + sprintf(name,"receiver.%d.frequency",rx->id); + value=getProperty(name); + if(value) rx->frequency=atoll(value); + sprintf(name,"receiver.%d.display_frequency",rx->id); + value=getProperty(name); + if(value) rx->display_frequency=atoll(value); + sprintf(name,"receiver.%d.dds_frequency",rx->id); + value=getProperty(name); + if(value) rx->dds_frequency=atoll(value); + sprintf(name,"receiver.%d.dds_offset",rx->id); + value=getProperty(name); + if(value) rx->dds_offset=atoll(value); + sprintf(name,"receiver.%d.rit",rx->id); + value=getProperty(name); + if(value) rx->rit=atoi(value); +*/ + sprintf(name,"receiver.%d.panadapter_low",rx->id); + value=getProperty(name); + if(value) rx->panadapter_low=atoi(value); + sprintf(name,"receiver.%d.panadapter_high",rx->id); + value=getProperty(name); + if(value) rx->panadapter_high=atoi(value); + sprintf(name,"receiver.%d.display_waterfall",rx->id); + value=getProperty(name); + if(value) rx->display_waterfall=atoi(value); + sprintf(name,"receiver.%d.waterfall_low",rx->id); + value=getProperty(name); + if(value) rx->waterfall_low=atoi(value); + sprintf(name,"receiver.%d.waterfall_high",rx->id); + value=getProperty(name); + if(value) rx->waterfall_high=atoi(value); + sprintf(name,"receiver.%d.waterfall_automatic",rx->id); + value=getProperty(name); + if(value) rx->waterfall_automatic=atoi(value); + + sprintf(name,"receiver.%d.alex_antenna",rx->id); + value=getProperty(name); + if(value) rx->alex_antenna=atoi(value); + sprintf(name,"receiver.%d.alex_attenuation",rx->id); + value=getProperty(name); + if(value) rx->alex_attenuation=atoi(value); + sprintf(name,"receiver.%d.volume",rx->id); + value=getProperty(name); + if(value) rx->volume=atof(value); + sprintf(name,"receiver.%d.agc",rx->id); + value=getProperty(name); + if(value) rx->agc=atoi(value); + sprintf(name,"receiver.%d.agc_gain",rx->id); + value=getProperty(name); + if(value) rx->agc_gain=atof(value); + sprintf(name,"receiver.%d.agc_slope",rx->id); + value=getProperty(name); + if(value) rx->agc_slope=atof(value); + sprintf(name,"receiver.%d.hang_threshold",rx->id); + value=getProperty(name); + if(value) rx->agc_hang_threshold=atof(value); + sprintf(name,"receiver.%d.attenuation",rx->id); + value=getProperty(name); + if(value) rx->attenuation=atoi(value); + + sprintf(name,"receiver.%d.dither",rx->id); + value=getProperty(name); + if(value) rx->dither=atoi(value); + sprintf(name,"receiver.%d.random",rx->id); + value=getProperty(name); + if(value) rx->random=atoi(value); + sprintf(name,"receiver.%d.preamp",rx->id); + value=getProperty(name); + if(value) rx->preamp=atoi(value); + sprintf(name,"receiver.%d.nr",rx->id); + value=getProperty(name); + if(value) rx->nr=atoi(value); + sprintf(name,"receiver.%d.nr2",rx->id); + value=getProperty(name); + if(value) rx->nr2=atoi(value); + sprintf(name,"receiver.%d.anf",rx->id); + value=getProperty(name); + if(value) rx->anf=atoi(value); + sprintf(name,"receiver.%d.snb",rx->id); + value=getProperty(name); + if(value) rx->snb=atoi(value); + sprintf(name,"receiver.%d.nr_agc",rx->id); + value=getProperty(name); + if(value) rx->nr_agc=atoi(value); + sprintf(name,"receiver.%d.nr2_gain_method",rx->id); + value=getProperty(name); + if(value) rx->nr2_gain_method=atoi(value); + sprintf(name,"receiver.%d.nr2_npe_method",rx->id); + value=getProperty(name); + if(value) rx->nr2_npe_method=atoi(value); + sprintf(name,"receiver.%d.ae",rx->id); + value=getProperty(name); + if(value) rx->nr2_ae=atoi(value); + + sprintf(name,"receiver.%d.audio_channel",rx->id); + value=getProperty(name); + if(value) rx->audio_channel=atoi(value); + sprintf(name,"receiver.%d.local_audio",rx->id); + value=getProperty(name); + if(value) rx->local_audio=atoi(value); + sprintf(name,"receiver.%d.audio_device",rx->id); + value=getProperty(name); + if(value) rx->audio_device=atoi(value); +} + +void reconfigure_receiver(RECEIVER *rx,int height) { + int y=0; + + rx->height=height; + + if(rx->display_panadapter) { + int height=rx->height; + if(rx->display_waterfall) { + height=height/2; + } + if(rx->panadapter==NULL) { +fprintf(stderr,"reconfigure_receiver: panadapter_init: width:%d height:%d\n",rx->width,height); + rx_panadapter_init(rx, rx->width,height); + gtk_fixed_put(GTK_FIXED(rx->panel),rx->panadapter,0,y); + } else { + // set the size +fprintf(stderr,"reconfigure_receiver: panadapter set_size_request: width:%d height:%d\n",rx->width,height); + gtk_widget_set_size_request(rx->panadapter, rx->width, height); + // move the current one + gtk_fixed_move(GTK_FIXED(rx->panel),rx->panadapter,0,y); + } + y+=height; + } else { + if(rx->panadapter!=NULL) { + gtk_container_remove(GTK_CONTAINER(rx->panel),rx->panadapter); + gtk_widget_destroy(rx->panadapter); + rx->panadapter=NULL; + } + } + + if(rx->display_waterfall) { + int height=rx->height; + if(rx->display_panadapter) { + height=height/2; + } + if(rx->waterfall==NULL) { +fprintf(stderr,"reconfigure_receiver: waterfall_init: width:%d height:%d\n",rx->width,height); + waterfall_init(rx,rx->width,height); + gtk_fixed_put(GTK_FIXED(rx->panel),rx->waterfall,0,y); + } else { + // set the size +fprintf(stderr,"reconfigure_receiver: waterfall set_size_request: width:%d height:%d\n",rx->width,height); + gtk_widget_set_size_request(rx->waterfall, rx->width, height); + // move the current one + gtk_fixed_move(GTK_FIXED(rx->panel),rx->waterfall,0,y); + } + } else { + if(rx->waterfall!=NULL) { + gtk_container_remove(GTK_CONTAINER(rx->panel),rx->waterfall); + gtk_widget_destroy(rx->waterfall); + rx->waterfall=NULL; + } + } + + gtk_widget_show_all(rx->panel); +} + +static gint update_display(gpointer data) { + RECEIVER *rx=(RECEIVER *)data; + int rc; + + if(rx->displaying) { + GetPixels(rx->id,0,rx->pixel_samples,&rc); + if(rc) { + if(rx->display_panadapter) { + switch(vfo[rx->id].mode) { +#ifdef PSK + case modePSK: + psk_waterfall_update(rx); + break; +#endif + default: + rx_panadapter_update(rx); + break; + } + } + if(rx->display_waterfall) { + waterfall_update(rx); + } + } + + if(active_receiver==rx) { + double m=GetRXAMeter(rx->id,smeter); + meter_update(SMETER,m,0.0,0.0,0.0); + } + return TRUE; + } + return FALSE; +} + +void set_displaying(RECEIVER *rx,int state) { + rx->displaying=state; + if(state) { + rx->update_timer_id=gdk_threads_add_timeout_full(G_PRIORITY_HIGH_IDLE,1000/rx->fps, update_display, rx, NULL); + } +} + +void set_mode(RECEIVER *rx,int m) { + int local_mode=m; +#ifdef FREEDV + if(vfo[rx->d].mode!=modeFREEDV && m==modeFREEDV) { + local_mode=modeUSB; + init_freedv(); + } else if(vfo[rx->id].mode==modeFREEDV && m!=modeFREEDV) { + close_freedv(); + } +#endif +#ifdef PSK + if(vfo[rx->id].mode!=modePSK && m==modePSK) { + local_mode=modeUSB; + //init_psk(); + show_psk(); + } else if(vfo[rx->id].mode==modePSK && m!=modePSK) { + //close_psk(); + show_waterfall(); + } +#endif + vfo[rx->id].mode=m; + SetRXAMode(rx->id, vfo[rx->id].mode); +} + +void set_filter(RECEIVER *rx,int low,int high) { + if(vfo[rx->id].mode==modeCWL) { + rx->filter_low=-cw_keyer_sidetone_frequency-low; + rx->filter_high=-cw_keyer_sidetone_frequency+high; + } else if(vfo[rx->id].mode==modeCWU) { + rx->filter_low=cw_keyer_sidetone_frequency-low; + rx->filter_high=cw_keyer_sidetone_frequency+high; + } else { + rx->filter_low=low; + rx->filter_high=high; + } + + RXASetPassband(rx->id,(double)rx->filter_low,(double)rx->filter_high); +} + +void set_deviation(RECEIVER *rx,double deviation) { + SetRXAFMDeviation(rx->id, deviation); +} + +void set_agc(RECEIVER *rx, int agc) { + + SetRXAAGCMode(rx->id, agc); + //SetRXAAGCThresh(rx->id, agc_thresh_point, 4096.0, rx->sample_rate); + SetRXAAGCSlope(rx->id,rx->agc_slope); + SetRXAAGCTop(rx->id,rx->agc_gain); + switch(agc) { + case AGC_OFF: + break; + case AGC_LONG: + SetRXAAGCAttack(rx->id,2); + SetRXAAGCHang(rx->id,2000); + SetRXAAGCDecay(rx->id,2000); + SetRXAAGCHangThreshold(rx->id,(int)rx->agc_hang_threshold); + break; + case AGC_SLOW: + SetRXAAGCAttack(rx->id,2); + SetRXAAGCHang(rx->id,1000); + SetRXAAGCDecay(rx->id,500); + SetRXAAGCHangThreshold(rx->id,(int)rx->agc_hang_threshold); + break; + case AGC_MEDIUM: + SetRXAAGCAttack(rx->id,2); + SetRXAAGCHang(rx->id,0); + SetRXAAGCDecay(rx->id,250); + SetRXAAGCHangThreshold(rx->id,100); + break; + case AGC_FAST: + SetRXAAGCAttack(rx->id,2); + SetRXAAGCHang(rx->id,0); + SetRXAAGCDecay(rx->id,50); + SetRXAAGCHangThreshold(rx->id,100); + break; + } +} + +void set_offset(RECEIVER *rx,long long offset) { +fprintf(stderr,"set_offset: id=%d ofset=%lld\n",rx->id,offset); +fprintf(stderr,"set_offset: frequency=%lld ctun_freqeuncy=%lld offset=%lld\n",vfo[rx->id].frequency,vfo[rx->id].ctun_frequency,vfo[rx->id].offset); + if(offset==0) { + SetRXAShiftFreq(rx->id, (double)offset); + RXANBPSetShiftFrequency(rx->id, (double)offset); + SetRXAShiftRun(rx->id, 0); + } else { + SetRXAShiftFreq(rx->id, (double)offset); + RXANBPSetShiftFrequency(rx->id, (double)offset); + SetRXAShiftRun(rx->id, 1); + } +} + +static void init_analyzer(RECEIVER *rx) { + int flp[] = {0}; + double keep_time = 0.1; + int n_pixout=1; + int spur_elimination_ffts = 1; + int data_type = 1; + int fft_size = 8192; + int window_type = 4; + double kaiser_pi = 14.0; + int overlap = 2048; + int clip = 0; + int span_clip_l = 0; + int span_clip_h = 0; + int pixels=rx->pixels; + int stitches = 1; + int avm = 0; + double tau = 0.001 * 120.0; + int calibration_data_set = 0; + double span_min_freq = 0.0; + double span_max_freq = 0.0; + + int max_w = fft_size + (int) min(keep_time * (double) rx->fps, keep_time * (double) fft_size * (double) rx->fps); + + overlap = (int)max(0.0, ceil(fft_size - (double)rx->sample_rate / (double)rx->fps)); + + fprintf(stderr,"SetAnalyzer id=%d buffer_size=%d overlap=%d\n",rx->id,rx->buffer_size,overlap); + + + SetAnalyzer(rx->id, + n_pixout, + spur_elimination_ffts, //number of LO frequencies = number of ffts used in elimination + data_type, //0 for real input data (I only); 1 for complex input data (I & Q) + flp, //vector with one elt for each LO frequency, 1 if high-side LO, 0 otherwise + fft_size, //size of the fft, i.e., number of input samples + rx->buffer_size, //number of samples transferred for each OpenBuffer()/CloseBuffer() + window_type, //integer specifying which window function to use + kaiser_pi, //PiAlpha parameter for Kaiser window + overlap, //number of samples each fft (other than the first) is to re-use from the previous + clip, //number of fft output bins to be clipped from EACH side of each sub-span + span_clip_l, //number of bins to clip from low end of entire span + span_clip_h, //number of bins to clip from high end of entire span + pixels, //number of pixel values to return. may be either <= or > number of bins + stitches, //number of sub-spans to concatenate to form a complete span + calibration_data_set, //identifier of which set of calibration data to use + span_min_freq, //frequency at first pixel value8192 + span_max_freq, //frequency at last pixel value + max_w //max samples to hold in input ring buffers + ); + + +} + +static void create_visual(RECEIVER *rx) { + int y=0; + +fprintf(stderr,"receiver: create_visual: id=%d width=%d height=%d\n",rx->id, rx->width, rx->height); + rx->panel=gtk_fixed_new(); + gtk_widget_set_size_request (rx->panel, rx->width, rx->height); + + rx->panadapter=NULL; + rx->waterfall=NULL; + + int height=rx->height; + if(rx->display_waterfall) { + height=height/2; + } + +fprintf(stderr,"receiver: panadapter_init: height=%d y=%d\n",height,y); + rx_panadapter_init(rx, rx->width,height); + gtk_fixed_put(GTK_FIXED(rx->panel),rx->panadapter,0,y); + y+=height; + + if(rx->display_waterfall) { +fprintf(stderr,"receiver: waterfall_init: height=%d y=%d\n",height,y); + waterfall_init(rx,rx->width,height); + gtk_fixed_put(GTK_FIXED(rx->panel),rx->waterfall,0,y); + } +} + +RECEIVER *create_receiver(int id, int buffer_size, int fft_size, int pixels, int fps, int width, int height) { +fprintf(stderr,"create_receiver: id=%d buffer_size=%d fft_size=%d pixels=%d fps=%d\n",id,buffer_size, fft_size, pixels, fps); + RECEIVER *rx=malloc(sizeof(RECEIVER)); + rx->id=id; + switch(id) { + case 0: + rx->adc=0; + break; + default: + switch(protocol) { + case ORIGINAL_PROTOCOL: + switch(device) { + case DEVICE_METIS: + case DEVICE_HERMES: + case DEVICE_HERMES_LITE: + rx->adc=0; + break; + default: + rx->adc=1; + break; + } + break; + default: + switch(device) { + case NEW_DEVICE_ATLAS: + case NEW_DEVICE_HERMES: + rx->adc=0; + break; + default: + rx->adc=1; + break; + } + break; + } + } +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; + rx->pixels=pixels; + rx->fps=fps; + + BAND *b=band_get_band(vfo[rx->id].band); + +// rx->dds_offset=0; +// rx->rit=0; + + rx->width=width; + rx->height=height; + rx->display_panadapter=1; + rx->display_waterfall=1; + + // allocate buffers + rx->iq_input_buffer=malloc(sizeof(double)*2*rx->buffer_size); + rx->audio_buffer=malloc(AUDIO_BUFFER_SIZE); + rx->audio_sequence=0L; + rx->pixel_samples=malloc(sizeof(float)*pixels); + + rx->samples=0; + rx->displaying=0; + rx->display_panadapter=1; + rx->display_waterfall=1; + + rx->panadapter_high=-40; + rx->panadapter_low=-140; + + rx->volume=0.2; + rx->attenuation=0; + + rx->dither=0; + rx->random=0; + rx->preamp=0; + + rx->nr=0; + rx->nr2=0; + rx->anf=0; + rx->snb=0; + + rx->nr_agc=0; + rx->nr2_gain_method=2; + rx->nr2_npe_method=0; + rx->nr2_ae=1; + + rx->alex_antenna=b->alexRxAntenna; + rx->alex_attenuation=b->alexAttenuation; + + rx->agc=AGC_MEDIUM; + rx->agc_gain=80.0; + rx->agc_slope=35.0; + rx->agc_hang_threshold=0.0; + + rx->playback_handle=NULL; + rx->local_audio=0; + rx->audio_channel=STEREO; + rx->audio_device=-1; + + receiver_restore_state(rx); + + int scale=rx->sample_rate/48000; + rx->output_samples=rx->buffer_size/scale; + rx->audio_output_buffer=malloc(sizeof(double)*2*rx->output_samples); +fprintf(stderr,"create_receiver: id=%d output_samples=%d\n",rx->id,rx->output_samples); + + rx->hz_per_pixel=(double)rx->sample_rate/(double)rx->width; + // setup wdsp for this receiver + +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,rx->buffer_size, rx->fft_size, rx->sample_rate); + OpenChannel(rx->id, + rx->buffer_size, + rx->fft_size, + rx->sample_rate, + 48000, // dsp rate + 48000, // output rate + 0, // receive + 1, // run + 0.010, 0.025, 0.0, 0.010, 0); + + b=band_get_band(vfo[rx->id].band); + BANDSTACK *bs=b->bandstack; + BANDSTACK_ENTRY *entry=&bs->entry[vfo[rx->id].bandstack]; + FILTER *band_filters=filters[vfo[rx->id].mode]; + FILTER *band_filter=&band_filters[vfo[rx->id].filter]; + set_filter(rx,band_filter->low,band_filter->high); + + SetRXAFMDeviation(rx->id,(double)deviation); + + set_agc(rx, rx->agc); + + SetRXAAMDSBMode(rx->id, 0); + SetRXAShiftRun(rx->id, 0); + + SetRXAEMNRPosition(rx->id, rx->nr_agc); + SetRXAEMNRgainMethod(rx->id, rx->nr2_gain_method); + SetRXAEMNRnpeMethod(rx->id, rx->nr2_npe_method); + SetRXAEMNRRun(rx->id, rx->nr2); + SetRXAEMNRaeRun(rx->id, rx->nr2_ae); + + SetRXAANRVals(rx->id, 64, 16, 16e-4, 10e-7); // defaults + SetRXAANRRun(rx->id, rx->nr); + SetRXAANFRun(rx->id, rx->anf); + SetRXASNBARun(rx->id, rx->snb); + + SetRXAPanelGain1(rx->id, rx->volume); + SetRXAPanelBinaural(rx->id, binaural); + SetRXAPanelRun(rx->id, 1); + + if(enable_rx_equalizer) { + SetRXAGrphEQ(rx->id, rx_equalizer); + SetRXAEQRun(rx->id, 1); + } else { + SetRXAEQRun(rx->id, 0); + } + + // setup for diversity + create_divEXT(0,0,2,rx->buffer_size); + SetEXTDIVRotate(0, 2, &i_rotate, &q_rotate); + SetEXTDIVRun(0,diversity_enabled); + + + int result; + XCreateAnalyzer(rx->id, &result, 262144, 1, 1, ""); + if(result != 0) { + fprintf(stderr, "XCreateAnalyzer id=%d failed: %d\n", rx->id, result); + } else { + init_analyzer(rx); + } + + SetDisplayDetectorMode(rx->id, 0, display_detector_mode); + SetDisplayAverageMode(rx->id, 0, display_average_mode); + + calculate_display_average(rx); + + create_visual(rx); + + if(rx->local_audio) { + audio_open_output(rx); + } + + return rx; +} + +void receiver_change_adc(RECEIVER *rx,int adc) { + rx->adc=adc; +} + +void receiver_change_sample_rate(RECEIVER *rx,int sample_rate) { + + rx->sample_rate=sample_rate; + + SetChannelState(rx->id,0,1); + + int scale=rx->sample_rate/48000; + rx->output_samples=rx->buffer_size/scale; + free(rx->audio_output_buffer); + rx->audio_output_buffer=malloc(sizeof(double)*2*rx->output_samples); + rx->audio_buffer=malloc(AUDIO_BUFFER_SIZE); + rx->hz_per_pixel=(double)rx->sample_rate/(double)rx->width; + + SetInputSamplerate(rx->id, sample_rate); + + init_analyzer(rx); + +fprintf(stderr,"receiver_change_sample_rate: id=%d rate=%d buffer_size=%d output_samples=%d\n",rx->id, rx->sample_rate, rx->buffer_size, rx->output_samples); + SetChannelState(rx->id,1,0); +} + +void receiver_frequency_changed(RECEIVER *rx) { + int id=rx->id; + + if(vfo[id].ctun) { + vfo[id].offset=vfo[id].ctun_frequency-vfo[id].frequency; + set_offset(rx,vfo[id].offset); + } else if(protocol==NEW_PROTOCOL) { + schedule_high_priority(); // send new frequency + } +} + +void receiver_mode_changed(RECEIVER *rx) { + set_mode(rx,vfo[rx->id].mode); +} + +void receiver_filter_changed(RECEIVER *rx) { + FILTER *mode_filters=filters[vfo[rx->id].mode]; + FILTER *filter=&mode_filters[vfo[rx->id].filter]; + set_filter(rx,filter->low,filter->high); +} + +void receiver_vfo_changed(RECEIVER *rx) { + receiver_frequency_changed(rx); + receiver_mode_changed(rx); + receiver_filter_changed(rx); +} + +#ifdef FREEDV +static void process_freedv_rx_buffer(RECEIVER *rx) { + short left_audio_sample; + short right_audio_sample; + int i; + int demod_samples; + for(i=0;ioutput_samples;i++) { + if(freedv_samples==0) { + left_audio_sample=(short)(rx->audio_output_buffer[i*2]*32767.0); + right_audio_sample=(short)(rx->audio_output_buffer[(i*2)+1]*32767.0); + demod_samples=demod_sample_freedv(left_audio_sample); + if(demod_samples!=0) { + int s; + int t; + for(s=0;soutput_samples;i++) { + if(isTransmitting()) { + left_audio_sample=0; + right_audio_sample=0; + } else { + left_audio_sample=(short)(rx->audio_output_buffer[i*2]*32767.0); + right_audio_sample=(short)(rx->audio_output_buffer[(i*2)+1]*32767.0); +#ifdef PSK + if(vfo[rx->id].mode==modePSK) { + if(psk_samples==0) { + psk_demod((double)((left_audio_sample+right_audio_sample)/2)); + } + psk_samples++; + if(psk_samples==psk_resample) { + psk_samples=0; + } + } +#endif + } + + if(rx->local_audio) { + switch(rx->audio_channel) { + case STEREO: + audio_write(rx,left_audio_sample,right_audio_sample); + break; + case LEFT: + audio_write(rx,left_audio_sample,0); + break; + case RIGHT: + audio_write(rx,0,right_audio_sample); + break; + } + } + + if(rx==active_receiver) { + switch(protocol) { + case ORIGINAL_PROTOCOL: + old_protocol_audio_samples(rx,left_audio_sample,right_audio_sample); + break; + case NEW_PROTOCOL: + if(!(echo&&isTransmitting())) { + new_protocol_audio_samples(rx,left_audio_sample,right_audio_sample); + } + break; +#ifdef LIMESDR + case LIMESDR_PROTOCOL: + break; +#endif + } + } + + } +} + +void full_rx_buffer(RECEIVER *rx) { + int j; + int error; + + fexchange0(rx->id, rx->iq_input_buffer, rx->audio_output_buffer, &error); + if(error!=0) { + fprintf(stderr,"full_rx_buffer: id=%d fexchange0: error=%d\n",rx->id,error); + } + + if(rx->displaying) { + Spectrum0(1, rx->id, 0, 0, rx->iq_input_buffer); + } + + switch(vfo[rx->id].mode) { +#ifdef FREEDV + case modeFREEDV: + process_freedv_rx_buffer(rx); + break; +#endif + default: + process_rx_buffer(rx); + break; + } +} + +void add_iq_samples(RECEIVER *rx, double i_sample,double q_sample) { + rx->iq_input_buffer[rx->samples*2]=i_sample; + rx->iq_input_buffer[(rx->samples*2)+1]=q_sample; + rx->samples=rx->samples+1; + if(rx->samples==rx->buffer_size) { + full_rx_buffer(rx); + rx->samples=0; + } +} diff --git a/receiver.h b/receiver.h index 1d91a7e..75e36a7 100644 --- a/receiver.h +++ b/receiver.h @@ -1,13 +1,144 @@ -#define MAX_RECEIVERS 2 +/* Copyright (C) +* 2017 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ +#ifndef _RECEIVER_H +#define _RECEIVER_H -struct _receiver { +#include +#include + +#define AUDIO_BUFFER_SIZE 260 + +enum _audio_t { + STEREO=0, + LEFT, + RIGHT +}; + +typedef enum _audio_t audio_t; + +typedef struct _receiver { + int id; + + int adc; + + double volume; + int agc; + double agc_gain; + double agc_slope; + double agc_hang_threshold; + int fps; + int displaying; + audio_t audio_channel; int sample_rate; int buffer_size; - int band; - int bandstack; - int mode; - int filter; - int audio; -} rx[MAX_RECEIVERS]; + int fft_size; + int pixels; + int samples; + int output_samples; + double *iq_input_buffer; + double *audio_output_buffer; + unsigned char *audio_buffer; + int audio_index; + long audio_sequence; + float *pixel_samples; + int display_panadapter; + int display_waterfall; + gint update_timer_id; + + double hz_per_pixel; + +// long long frequency; +// long long display_frequency; +// long long dds_frequency; +// long long dds_offset; + +// int rit; + + int dither; + int random; + int preamp; + + int nr; + int nr2; + int anf; + int snb; + + int nr_agc; + int nr2_gain_method; + int nr2_npe_method; + int nr2_ae; + + + int attenuation; + int alex_antenna; + int alex_attenuation; + + int filter_low; + int filter_high; + + int width; + int height; + + GtkWidget *panel; + GtkWidget *panadapter; + GtkWidget *waterfall; + + int panadapter_low; + int panadapter_high; + + int waterfall_low; + int waterfall_high; + int waterfall_automatic; + + cairo_surface_t *panadapter_surface; + GdkPixbuf *pixbuf; + + int local_audio; + int audio_device; + snd_pcm_t *playback_handle; + int playback_offset; + unsigned char *playback_buffer; + +} RECEIVER; + +extern RECEIVER *create_receiver(int id, int buffer_size, int fft_size, int pixels, int fps, int width, int height); +extern void receiver_change_sample_rate(RECEIVER *rx,int sample_rate); +extern void receiver_frequency_changed(RECEIVER *rx); +extern void receiver_mode_changed(RECEIVER *rx); +extern void receiver_filter_changed(RECEIVER *rx); +extern void receiver_vfo_changed(RECEIVER *rx); + +extern void set_mode(RECEIVER* rx,int m); +extern void set_filter(RECEIVER *rx,int low,int high); +extern void set_agc(RECEIVER *rx, int agc); +extern void set_offset(RECEIVER *rx, long long offset); +extern void set_deviation(RECEIVER *rx, double deviation); + +extern void add_iq_samples(RECEIVER *rx, double i_sample,double q_sample); + +extern void reconfigure_receiver(RECEIVER *rx,int height); + +extern void receiver_save_state(RECEIVER *rx); +extern gboolean receiver_button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data); +extern gboolean receiver_button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer data); +extern gboolean receiver_motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data); +extern gboolean receiver_scroll_event(GtkWidget *widget, GdkEventScroll *event, gpointer data); +#endif diff --git a/rigctl.c b/rigctl.c index b1f7609..90b76dd 100644 --- a/rigctl.c +++ b/rigctl.c @@ -1,1508 +1,1780 @@ - -/* S-2000 emulation via TCP - * Copyright (C) 2016 Steve Wilson - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * PiHPSDR RigCtl by Steve KA6S Oct 16 2016 - * - */ -#include -#include -#include -#include -#include -#include -#include "toolbar.h" -#include "sliders.h" -#include "rigctl.h" -#include "radio.h" -#include "channel.h" -#include "filter.h" -#include -#include "mode.h" -#include "filter.h" -#include "wdsp_init.h" -#include "band.h" -#include "bandstack.h" -#include "vfo.h" -#include "sliders.h" -#include -#include - -// IP stuff below -#include -#include //inet_addr - -#undef RIGCTL_DEBUG - -// the port client will be connecting to -#define TELNET_PORT 19090 // This is the HAMLIB port -// max number of bytes we can get at once -#define MAXDATASIZE 300 - -int init_server (); - -int rigctlGetFilterLow(); -int rigctlGetFilterHigh(); -int rigctlSetFilterLow(int val); -int rigctlSetFilterHigh(int val); -int new_level; -void parse_cmd ( char *,int ); - -extern int enable_tx_equalizer; - -typedef struct com_list { - char cmd_string[80]; - struct com_list * next_ent; - } com_list_t; -com_list_t cmd_list; -char cmd_save[80]; - -char cmd_input[MAXDATASIZE] ; -char * wptr; -com_list_t * work_input; -com_list_t * work_list; -com_list_t * follow_list; -com_list_t * com_head = NULL; -com_list_t * cur_ent; -int cmdlistcnt; -int retcode = 1; -char workvar[100]; - -char command[80]; -char msg[80]; -char msg2[80]; -char * newf; - -FILE * TTYFILE; -FILE * out; -int output; -FILTER * band_filter; - -static pthread_t rigctl_thread_id; -static void * rigctl (void * arg); - -int squelch=100; //local sim of squelch level -// This stuff from the telnet server -int sockfd, numbytes; -char buf[MAXDATASIZE]; -struct hostent *he; - -// connector’s address information -struct sockaddr_in their_addr; - -int socket_desc , client_sock , c , read_size; -struct sockaddr_in server , client; -char client_message[MAXDATASIZE]; - -int freq_flag; // Determines if we are in the middle of receiving frequency info - -int digl_offset = 0; -int digl_pol = 0; -int digu_offset = 0; -int digu_pol = 0; -double new_vol = 0; - -// Radio functions - -// Memory channel stuff and things that aren't -// implemented - but here for a more complete emulation -int ctcss_tone; // Numbers 01-38 are legal values - set by CN command, read by CT command -int ctcss_mode; // Numbers 0/1 - on off. - -// Now my stuff -// -// Looks up entry INDEX_NUM in the command structure and -// returns the command string -// - -void send_resp (char * msg) { - #ifdef RIGCTL_DEBUG - fprintf(stderr,"RIGCTL: RESP=%s\n",msg); - #endif - write(client_sock, msg, strlen(msg)); -} - -char * cmd_lookup (int index_num) { - com_list_t * lcl_p; - lcl_p = com_head; - if(index_num == 0) { - return(lcl_p->cmd_string); - } else { - while((lcl_p->next_ent != (com_list_t * ) NULL) && (index_num != 0)) { - lcl_p = lcl_p->next_ent; - index_num--; - } - } - if(index_num == 0) { - return(lcl_p->cmd_string); - } else { - return ((char *) NULL); - } -} - -static void * rigctl (void * arg) { - int len; - init_server(); - int save_flag = 0; // Used to concatenate two cmd lines together - int semi_number = 0; - int i; - char * work_ptr; - char work_buf[MAXDATASIZE]; - - for(;;) { - fprintf(stderr,"RIGCTL - New run\n"); - while((numbytes=recv(client_sock , cmd_input , MAXDATASIZE-2 , 0)) > 0 ) { - //cmd_input[numbytes+1]='\0'; // Turn into a C string - //i=strlen(cmd_input); - //#ifdef RIGCTL_DEBUG - //fprintf(stderr,"RIGCTL: RCVD=%s NB=%d LEN=%d\n",cmd_input,numbytes,i); - //#endif - for(i=0;icmd_string[0]; // Assume the command is first thing! - char cmd_str[3]; - cmd_str[0] = cmd_input[0]; - cmd_str[1] = cmd_input[1]; - cmd_str[2] = '\0'; - if(strcmp(cmd_str,"AC")==0) { // Sets or reads the internal antenna tuner status - // P1 0:RX-AT Thru, 1: RX-AT IN - // P2 0: TX-AT Thru 1: TX-AT In - // - if(len <= 2) { - send_resp("AC000;"); - } - } - else if(strcmp(cmd_str,"AG")==0) { // Set Audio Gain - - // AG123; Value of 0- - // AG1 = Sub receiver - what is the value set - // Response - AG<0/1>123; Where 123 is 0-260 - if(len>4) { // Set Audio Gain - volume = (double) atoi(&cmd_input[3])/260; - g_idle_add(update_af_gain,NULL); - } else { // Read Audio Gain - sprintf(msg,"AG0%03d;",(int) (2.6 * volume)); - send_resp(msg); - #ifdef RIGCTL_DEBUG - fprintf(stderr,":%s\n",msg); - #endif - } - } - else if(strcmp(cmd_str,"AI")==0) { // Allow rebroadcast of set frequency after set - not supported - if(len <=2) { - send_resp("AI0;"); - } - } - else if(strcmp(cmd_str,"AL")==0) { // Set/Reads the auto Notch level - if(len <=2) { - send_resp("AL000;"); - } - } - else if(strcmp(cmd_str,"AM")==0) { // Sets or reads the Auto Mode - if(len <=2) { - send_resp("AM0;"); - } - } - else if(strcmp(cmd_str,"AN")==0) { // Selects the antenna connector (ANT1/2) - if(len <=2) { - send_resp("AN0;"); - } - } - else if(strcmp(cmd_str,"AR")==0) { // Sets or reads the ASC function on/off - if(len <=2) { - send_resp("AR0;"); - } - } - else if(strcmp(cmd_str,"AS")==0) { // Sets/reads automode function parameters - // AS<2xP2><11P3>; - // AS<2xP2><11P3>; - if(len < 6) { - sprintf(msg,"AS%1d%02d%011lld%01d;", - 0, // P1 - 0, // Automode - getFrequency(), - rigctlGetMode()); - send_resp(msg); - - } - } - else if(strcmp(cmd_str,"BC")==0) { // Beat Cancellor OFF - if(len <=2) { - send_resp("BC0;"); - } - } - else if(strcmp(cmd_str,"BD")==0) { // Moves down the frequency band - // No response - } - else if(strcmp(cmd_str,"BP")==0) { // Reads the manual beat canceller frequency setting - if(len <=2) { - send_resp("BP000;"); - } - } - else if(strcmp(cmd_str,"BS")==0) { // Sets or reads Beat Canceller status - if(len <=2) { - send_resp("BS0;"); - } - } - else if(strcmp(cmd_str,"BU")==0) { // Moves Up the frequency band - // No response - } - else if(strcmp(cmd_str,"BY")==0) { // Read the busy signal status - if(len <=2) { - send_resp("BY00;"); - } - } - else if(strcmp(cmd_str,"CA")==0) { // Sets/reads cw auto tune function status - if(len <=2) { - send_resp("CA0;"); - } - } - else if(strcmp(cmd_str,"CG")==0) { // Sets/reads the carrier gain status - // 0-100 legal values - if(len <=2) { - send_resp("CG000;"); - } - } - else if(strcmp(cmd_str,"CH")==0) { // Sets the current frequency to call Channel - // No response - } - else if(strcmp(cmd_str,"CI")==0) { // While in VFO mode or memory recall mode, sets freq to the call channel - // No response - } - else if(strcmp(cmd_str,"CM")==0) { // Sets or reads the packet cluster tune f(x) on/off - // 0-100 legal values - if(len <=2) { - send_resp("CM0;"); - } - } - else if(strcmp(cmd_str,"CN")==0) { // Sets and reads CTSS function - 01-38 legal values - // Stored locally in rigctl - not used. - if(len <=2) { - sprintf(msg,"CN%02d;",ctcss_tone); - send_resp(msg); - } else { - ctcss_tone = atoi(&cmd_input[2]); - } - } - else if(strcmp(cmd_str,"CT")==0) { // Sets and reads CTSS function status - // Stored locally in rigctl - not used. - if(len <=2) { - sprintf(msg,"CT%01d;",ctcss_mode); - send_resp(msg); - } else { - ctcss_mode = atoi(&cmd_input[2]); - } - } - else if(strcmp(cmd_str,"DC")==0) { // Sets/Reads TX band status - if(len <=2) { - send_resp("DC00;"); - } - } - else if(strcmp(cmd_str,"DN")==0) { // Emulate Mic down key - } - else if(strcmp(cmd_str,"DQ")==0) { // ETs/and reads the DCS function status - if(len <=2) { - send_resp("DQ0;"); - } - } - else if(strcmp(cmd_str,"EX")==0) { // Set/reads the extension menu - cmd_input[9] = '\0'; // Make sure we have a C string - sprintf(msg,"EX%s0;",&cmd_input[2]); - send_resp(msg); - } - else if(strcmp(cmd_str,"FA")==0) { // VFO A frequency - // LEN=7 - set frequency - // Next data will be rest of freq - if(len == 13) { //We are receiving freq info - long long new_freqA = atoll(&cmd_input[2]); - set_band(new_freqA); - //setFrequency(new_freqA); - //g_idle_add(vfo_update,NULL); - } else { - if(len==2) { - sprintf(msg,"FA%011lld;",getFrequency()); - send_resp(msg); - } - } - } - else if(strcmp(cmd_str,"FB")==0) { // VFO B frequency - if(len==13) { //We are receiving freq info - long long new_freqA = atoll(&cmd_input[2]); - set_band(new_freqA); - //setFrequency(new_freqA); - //g_idle_add(vfo_update,NULL); - } else if(len == 2) { - sprintf(msg,"FB%011lld;",getFrequency()); - send_resp(msg); - } - } - else if(strcmp(cmd_str,"FC")==0) { // Set Sub receiver freq - // LEN=7 - set frequency - // Next data will be rest of freq - // Len<7 - frequency? - if(len>4) { //We are receiving freq info - long long new_freqA = atoll(&cmd_input[2]); - //setFrequency(new_freqA); - } else { - sprintf(msg,"FC%011lld;",getFrequency()); -/* - send_resp(msg); -*/ - } - } - else if(strcmp(cmd_str,"FD")==0) { // Read the filter display dot pattern - send_resp("FD00000000;"); - } - else if(strcmp(cmd_str,"FR")==0) { // Set/reads the extension menu - if(len <=2) { - send_resp("FR0;"); - } - } - else if(strcmp(cmd_str,"FS")==0) { // Set/reads fine funct status - if(len <=2) { - send_resp("FS0;"); - } - } - else if(strcmp(cmd_str,"FT")==0) { // Sel or reads the transmitters VFO, M, ch or Call comm - if(len <=2) { - send_resp("FT0;"); - } - } - else if(strcmp(cmd_str,"FW")==0) { // Sets/Reas DSP receive filter width in hz 0-9999hz - // CW - legal values 50 80 100 150 200 300 400 500 600 1000 2000 - // PiHPSDR map 50 100 100 100 250 250 400 500 600 1000 - // 25 750 - entry= (BANDSTACK_ENTRY *) - bandstack_entry_get_current(); - FILTER* band_filters=filters[entry->mode]; - FILTER* band_filter=&band_filters[entry->filter]; - if(len <=2) { - // CW filter high and low are always the same and the filter value is 2*filter val - int filter_val = band_filter->high * 2; - switch(filter_val) { - case 25: - case 50: - work_int = 50; - break; - case 100: - work_int = 100; - break; - case 250: - work_int = 300; - break; - case 400: - work_int = 400; - break; - case 500: - work_int = 500; - break; - case 600: - work_int = 600; - break; - case 750: - work_int = 1000; - break; - case 800: - work_int = 1000; - break; - case 1000: - work_int = 1000; - break; - default: work_int = 500; - break; - } - sprintf(msg,"FW%04d;",work_int); - #ifdef RIGCTL_DEBUG - fprintf(stderr,"RIGCTL: FW Filter Act=%d work_int=%d\n",band_filter->high,work_int); - #endif - send_resp(msg); - } else { - // Try to set filters here! - // CW - legal values 50 80 100 150 200 300 400 500 600 1000 2000 - // PiHPSDR map 50 100 100 100 250 250 400 500 600 1000 - // 25 750 - work_int = atoi(&cmd_input[2]); - switch (work_int) { - - case 50: new_low = 25; new_high = 25; break; - case 80: new_low = 50; new_high = 50; break; - case 100: new_low = 50; new_high = 50; break; - case 150: new_low = 50; new_high = 50; break; - case 200: new_low = 125; new_high = 125; break; - case 300: new_low = 125; new_high = 125; break; - case 400: new_low = 200; new_high = 200; break; - case 500: new_low = 250; new_high = 250; break; - case 600: new_low = 300; new_high = 300; break; - case 1000: new_low = 500; new_high = 500; break; - case 2000: new_low = 500; new_high = 500; break; - default: new_low = band_filter->low; - new_high = band_filter->high; - - } - #ifdef RIGCTL_DEBUG - fprintf(stderr,"RIGCTL: FW Filter new_low=%d new_high=%d\n",new_low,new_high); - #endif - // entry->filter = new_low * 2 ; - setFilter(new_low,new_high); - g_idle_add(vfo_update,NULL); - } - } - else if(strcmp(cmd_str,"GT")==0) { // Sets/Reas AGC constant status - if(len <=2) { - send_resp("GT000;"); - } - } - else if(strcmp(cmd_str,"ID")==0) { // Read ID - Default to TS-2000 which is type 019. - sprintf(msg,"ID019;"); - send_resp(msg); - } - else if(strcmp(cmd_str,"IF")==0) { // Reads Transceiver status - // IFFFFFFFFFFFF - Frequency - // OFFS - 4 chars Offset in powers of 10 - // RITRIT - 6 chars RIT/XIT Frequency - Not supported =0 - // R - 1 char RIT Status = 0 is off - // X - 1 char XIT Status = 0 is off - // 0 - 1 char Channel Bank number - not used - // 00 - 2 char Channel Bank number - not used - // C - 1 char Mox Status 0=off, 1=on - // M - 1 char Operating mode - align with MD commands - // V - 1 char VFO Split status - not supported - // 0 - 1 char Scan status - not supported - // A - 1 char - same as FT command - // 0 - 1 char - CTCSS tone - not used - // 00 - 2 char - More tone control - // 0 - 1 char - Shift status - sprintf(msg,"IF%011lld%04d%06d%1d%1d%1d%02d%01d%01d%01d%01d%01d%01d%02d%01d;", - getFrequency(), - step, // Shift Offset - 0, // Rit Freq - 0, // Rit Status - 0, // XIT Status - 0, // Channel Bank num - 0, // Channel Bank num - 0, // Mox Status - rigctlGetMode(), // Mode Status - same as MD Command - 0, // VFO Status - 0, // Scan status - 0, // FT command - ctcss_tone, // CTSS Tone - 0, // More tone control - 0); // Shift status - send_resp(msg); - } - else if(strcmp(cmd_str,"IS")==0) { // Sets/Reas IF shift funct status - if(len <=2) { - send_resp("IS00000;"); - } - } - else if(strcmp(cmd_str,"KS")==0) { // Sets/Reads keying freq - 0-060 max - if(len <=2) { - sprintf(msg,"KS%03d;",cw_keyer_speed); - send_resp(msg); - } else { - int key_speed; - key_speed = atoi(&cmd_input[2]); - if(key_speed >1 && key_speed <= 60) { - cw_keyer_speed=key_speed; - g_idle_add(vfo_update,NULL); - } - } - } - else if(strcmp(cmd_str,"KY")==0) { // Convert char to morse code - if(len <=2) { - send_resp("KY0;"); - } - } - else if(strcmp(cmd_str,"LK")==0) { // Set/read key lock function status - if(len <=2) { - sprintf(msg,"LK%01d%01d;",locked,locked); - send_resp(msg); - } else { - if(cmd_input[3] == '0') { - locked = 0; - } else if(cmd_input[3] == '1') { - locked = 1; - } - g_idle_add(vfo_update,NULL); - } - } - else if(strcmp(cmd_str,"LM")==0) { // Set/read DRU 3A unit or elect keyer recording status - if(len <=2) { - send_resp("LM0;"); - } - } - else if(strcmp(cmd_str,"LT")==0) { // Set/read Alt function - if(len <=2) { - send_resp("LT0;"); - } - } - else if(strcmp(cmd_str,"MC")==0) { // Recalls or reads memory channel - if(len <=2) { - send_resp("MC000;"); // Link this to band stack at some point - } - } - else if(strcmp(cmd_str,"MD")==0) { // Mode - digit selects mode - // 1 = LSB - // 2 = USB - // 3 = CWU - // 4 = FM - // 5 = AM - // 6 = DIGL - // 7 = CWL - // 9 = DIGU - int new_mode; - if(len > 2) { // Set Mode - switch(atoi(&cmd_input[2])) { - case 1: - new_mode = modeLSB; - break; - case 2: - new_mode = modeUSB; - break; - case 3: - new_mode = modeCWU; - break; - case 4: - new_mode = modeFMN; - break; - case 5: - new_mode = modeAM; - break; - case 6: - new_mode = modeDIGL; - break; - case 7: - new_mode = modeCWL; - break; - case 9: - new_mode = modeDIGU; - break; - default: - break; - #ifdef RIGCTL_DEBUG - fprintf(stderr,"MD command Unknown\n"); - #endif - } - // Other stuff to switch modes goes here.. - // since new_mode has the interpreted command in - // in it now. - entry= (BANDSTACK_ENTRY *) - bandstack_entry_get_current(); - entry->mode=new_mode; - // BUG - kills the system when there is some - // GPIO activity and Mode sets occur. Used twittling the - // frequency along with setting mode between USB/LSB with - // flrig. Tried doing the g_idle_add trick - but don't know the - // the magic to get that to compile without warnings - setMode(entry->mode); - // Moved the vfo_update down after filter updated. (John G0ORX) - //g_idle_add(vfo_update,NULL); - - FILTER* band_filters=filters[entry->mode]; - FILTER* band_filter=&band_filters[entry->filter]; - setFilter(band_filter->low,band_filter->high); - /* Need a way to update VFO info here..*/ - g_idle_add(vfo_update,NULL); - } else { // Read Mode - int curr_mode; - switch (mode) { - case modeLSB: curr_mode = 1; - break; - case modeUSB: curr_mode = 2; - break; - case modeCWL: curr_mode = 7; // CWL - break; - case modeCWU: curr_mode = 3; // CWU - break; - case modeFMN: curr_mode = 4; // FMN - break; - case modeAM: curr_mode = 5; // AM - break; - case modeDIGU: curr_mode = 9; // DIGU - break; - case modeDIGL: curr_mode = 6; // DIGL - break; - default: - #ifdef RIGCTL_DEBUG - fprintf(stderr, - "RIGCTL: MD command doesn't support %d\n", - mode); - #endif - break; - } - sprintf(msg,"MD%1d;",curr_mode); - send_resp(msg); - } - } - else if(strcmp(cmd_str,"MF")==0) { // Set/read menu A/B - if(len <=2) { - send_resp("MF0;"); - } - } - else if(strcmp(cmd_str,"MG")==0) { // Mike Gain - 3 digit value - if(len <=2) { - work_int = (int) ((mic_gain +10.0)* 100.0/60.0); - sprintf(msg,"MG%03d;",work_int); - send_resp(msg); - } else { - int tval = atoi(&cmd_input[2]); - new_vol = (double) (tval * 60/100) - 10; - //set_mic_gain(new_vol); - double *p_mic_gain=malloc(sizeof(double)); - *p_mic_gain=new_vol; - g_idle_add(update_mic_gain,(void *)p_mic_gain); - } - } - else if(strcmp(cmd_str,"ML")==0) { // Set/read the monitor function level - if(len <=2) { - send_resp("ML000;"); - } - } - else if(strcmp(cmd_str,"MO")==0) { // Set Monitor on/off - if(len <=2) { - send_resp("MO0;"); - } - } - else if(strcmp(cmd_str,"MR")==0) { // Read Memory Channel data - sprintf(msg,"MR%1d%02d%02d%011lld%1d%1d%1d%02d%02d%03d%1d%1d%09d%02d%1d%08d;", - 0, // P1 - Rx Freq - 1 Tx Freq - 0, // P2 Bankd and channel number -- see MC comment - 0, // P3 - see MC comment - getFrequency(), // P4 - frequency - rigctlGetMode(), // P5 - Mode - locked, // P6 - Locked status - 0, // P7 - O-off, 1-tone, 2-CTCSS, 3 =DCS - 0, // P8 - Tone Number - see page 35 - ctcss_tone, // P9 - CTCSS tone number - see CN command - 0, // P10 - DCS code - see QC command - 0, // P11 - Reverse status - 0, // P12 - Shift status - see OS command - 0, // P13 - Offset freq - see OS command - 0, // P14 - Step Size - see ST command - 0, // P15 - Memory Group Number (0-9) - 0); // P16 - Memory Name - 8 char max - send_resp(msg); - } - else if(strcmp(cmd_str,"MU")==0) { // Set/Read Memory Group Data - if(len <=2) { - send_resp("MU0000000000;"); - } - } - else if(strcmp(cmd_str,"MW")==0) { // Store Data to Memory Channel - } - else if(strcmp(cmd_str,"NB")==0) { // Set/Read Noise Blanker func status (on/off) - if(len <=2) { - sprintf(msg,"NB%1d;",snb); - send_resp(msg); - } else { - if(cmd_input[2]=='0') { // Turn off ANF - snb=0; - } else { // Turn on ANF - snb=1; - } - // Update ALL the filters - SetRXAANRRun(CHANNEL_RX0, nr); - SetRXAEMNRRun(CHANNEL_RX0, nr2); - SetRXAANFRun(CHANNEL_RX0, anf); - SetRXASNBARun(CHANNEL_RX0, snb); - g_idle_add(vfo_update,NULL); - } - } - else if(strcmp(cmd_str,"NL")==0) { // Set/Read Noise Reduction Level - if(len <=2) { - send_resp("NL000;"); - } - } - else if(strcmp(cmd_str,"NR")==0) { // Set/Read Noise Reduction function status - if(len <=2) { - if(nr_none == 1) { - send_resp("NR0;"); - } else if ((nr_none == 0) && (nr==1)) { - send_resp("NR1;"); - } else if (nr2 == 1) { - send_resp("NR2;"); - } else { - send_resp("NR0;"); - } - } else { - if(cmd_input[2] == '0') { - nr_none = 1; - nr = 0; - nr2 = 0; - } else if(cmd_input[2] == '1') { - nr_none = 0; - nr = 1; - nr2 = 0; - } else if(cmd_input[2] == '2') { - nr_none = 0; - nr = 0; - nr2 = 1; - } - SetRXAANRRun(CHANNEL_RX0, nr_none); - SetRXAEMNRRun(CHANNEL_RX0, nr2); - SetRXAANFRun(CHANNEL_RX0, anf); - SetRXASNBARun(CHANNEL_RX0, snb); - g_idle_add(vfo_update,NULL); - } - } - else if(strcmp(cmd_str,"NT")==0) { // Set/Read autonotch function - if(len <=2) { - sprintf(msg,"NT%1d;",anf); - send_resp(msg); - } else { - if(cmd_input[2] == '0') { // Clear ANF - anf = 0; - } else { // Set ANF - anf = 1; - } - } - SetRXAANRRun(CHANNEL_RX0, nr_none); - SetRXAEMNRRun(CHANNEL_RX0, nr2); - SetRXAANFRun(CHANNEL_RX0, anf); - SetRXASNBARun(CHANNEL_RX0, snb); - g_idle_add(vfo_update,NULL); - } - else if(strcmp(cmd_str,"OF")==0) { // Set/Read Offset freq (9 digits - hz) - if(len <=2) { - send_resp("OF000000000;"); - } - } - else if(strcmp(cmd_str,"OI")==0) { // Read Memory Channel Data - if(len <=2) { - sprintf(msg,"OI%011lld%04d%06d%1d%1d%1d%02d%1d%1d%1d%1d%1d%1d%02d%1d;", - getFrequency(), - 0, // P2 - Freq Step size - 0, // P3 - Rit/Xit Freq - 0, // P4 - RIT off/Rit On - 0, // P5 - XIT off/on - 0, // P6 - Channel - 0, // P7 - Bank - 0, // P8 - 0RX, 1TX - rigctlGetMode(), // P10 - MD - 0, // P11 - SC command - 0, // P12 Split op - SP command - 0, // P13 Off, 1, 2, - 0,// P14 Tone freq - See TN command - 0,0); - send_resp(msg); - } - } - else if(strcmp(cmd_str,"OS")==0) { // Set/Read Offset freq (9 digits - hz) - if(len <=2) { - send_resp("OS0;"); - } - } - else if(strcmp(cmd_str,"PA")==0) { // Set/Read Preamp function status - if(len <=2) { - sprintf(msg,"PA0%1d;",enable_tx_equalizer); - send_resp(msg); - } else { - if(cmd_input[2] =='0') { - enable_tx_equalizer=0; - SetTXAEQRun(CHANNEL_TX, enable_tx_equalizer); - } else { - enable_tx_equalizer=1; - SetTXAEQRun(CHANNEL_TX, enable_tx_equalizer); - } - } - } - else if(strcmp(cmd_str,"PB")==0) { // Set/Read DRU-3A Playback status - if(len <=2) { - send_resp("PB0;"); - } - } - else if(strcmp(cmd_str,"PC")==0) { // Set/Read Drive Power output - if(len<=2) { - sprintf(msg,"PC%03d;",(int) drive); - send_resp(msg); - } else { - // Power Control - 3 digit number- 0 to 100 - //Scales to 0.00-1.00 - - double drive_val = - (double)(atoi(&cmd_input[2])); - // setDrive(drive_val); - double *p_drive=malloc(sizeof(double)); - *p_drive=drive_val; - g_idle_add(update_drive,(gpointer)p_drive); - //set_drive(drive_val); - } - } - else if(strcmp(cmd_str,"PI")==0) { // STore the programmable memory channel - } - else if(strcmp(cmd_str,"PK")==0) { // Reads the packet cluster data - send_resp("PK000000000000000000000000000000000000000000000000;"); - } - else if(strcmp(cmd_str,"PL")==0) { // Set/Read Speech processor level - // P1 000 - min-100 max - // P2 000 - min - 100 max - if(len <=2) { - send_resp("PL000000;"); - } - } - else if(strcmp(cmd_str,"PM")==0) { // Recalls the Programmable memory - if(len <=2) { - send_resp("PM0;"); - } - } - else if(strcmp(cmd_str,"PR")==0) { // Sets/reads the speech processor function on/off - // 0 - off, 1=on - if(len <=2) { - send_resp("PR0;"); - } - } - else if(strcmp(cmd_str,"PS")==0) { // Sets/reads Power on/off state - // 0 - off, 1=on - if(len <=2) { - send_resp("PS1;"); // Lets pretend we're powered up ;-) - } - } - else if(strcmp(cmd_str,"PS")==0) { // Sets/reads DCS code - // Codes numbered from 000 to 103. - if(len <=2) { - send_resp("QC000;"); // Lets pretend we're powered up ;-) - } - } - else if(strcmp(cmd_str,"QI")==0) { // Store the settings in quick memory - } - else if(strcmp(cmd_str,"QR")==0) { // Send the Quick memory channel data - // P1 - Quick mem off, 1 quick mem on - // P2 - Quick mem channel number - if(len <=2) { - send_resp("QR00;"); // Lets pretend we're powered up ;-) - } - } - else if(strcmp(cmd_str,"RA")==0) { // Sets/reads Attenuator function status - // 00-off, 1-99 -on - Main and sub receivers reported - if(len <=2) { - send_resp("RA0000;"); - } - } - else if(strcmp(cmd_str,"RC")==0) { // Clears the RIT offset freq - } - else if(strcmp(cmd_str,"RD")==0) { // Move the RIT offset freq down, slow down the scan speed in scan mode - if(len <=2) { - send_resp("RD0;"); - } - } - else if(strcmp(cmd_str,"RG")==0) { // RF Gain - 3 digit number - // RG123; 0-255 value - // Scale from -20 - 120 - if(len>4) { // Set Audio Gain - int base_value = atoi(&cmd_input[2]); - double new_gain = ((((double) base_value)/255) * 140) - 20; - //set_agc_gain(new_gain); - double *p_gain=malloc(sizeof(double)); - *p_gain=new_gain; - g_idle_add(update_agc_gain,(gpointer)p_gain); - } else { // Read Audio Gain - sprintf(msg,"RG%03d;",((256 * (int) agc_gain)/140)+36); - send_resp(msg); - } - } - else if(strcmp(cmd_str,"RL")==0) { // Set/read Noise reduction level - if(len <=2) { - send_resp("RL00;"); - } - } - else if(strcmp(cmd_str,"RM")==0) { // Set/read Meter function - // P1- 0, unsel, 1 SWR, 2 Comp, 3 ALC - // P2 - 4 dig - Meter value in dots - 000-0030 - if(len <=2) { - send_resp("RM00000;"); - } - } - else if(strcmp(cmd_str,"RT")==0) { // Set/read the RIT function status - if(len <=2) { - send_resp("RT0;"); - } - } - else if(strcmp(cmd_str,"RU")==0) { // Set/move RIT frequency up - if(len <=2) { - send_resp("RU0;"); - } - } - else if(strcmp(cmd_str,"RX")==0) { // Unkey Xmitter - setMox(0); - // 0-main, 1=sub - if(len <=2) { - send_resp("RX0;"); - } - } - else if(strcmp(cmd_str,"SA")==0) { // Set/reads satellite mode status - // 0-main, 1=sub - if(len <=2) { - send_resp("SA000000000000000;"); - } - } - else if(strcmp(cmd_str,"SB")==0) { // Set/read the SUB TF-W status - if(len <=2) { - send_resp("SB0;"); - } - } - else if(strcmp(cmd_str,"SC")==0) { // Set/read the Scan function status - if(len <=2) { - send_resp("SC0;"); - } - } - else if(strcmp(cmd_str,"SD")==0) { // Set/read CW break-in time delay - // 0000-1000 ms (in steps of 50 ms) 0000 is full break in - if(len <=2) { - send_resp("SD0000;"); - } - } - else if(strcmp(cmd_str,"SH")==0) { // Set/read the DSP filter settings - if(len <=2) { - send_resp("SH00;"); - } - } - else if(strcmp(cmd_str,"SI")==0) { // Enters the satellite memory name - } - else if(strcmp(cmd_str,"SL")==0) { // Set/read the DSP filter settings - this appears twice? See SH - if(len <=2) { - send_resp("SL00;"); - } - } - else if(strcmp(cmd_str,"SM")==0) { // Read SMETER - // SMx; x=0 RX1, x=1 RX2 - // meter is in dbm - value will be 0<260 - // Translate to 00-30 for main, 0-15 fo sub - // Resp= SMxAABB; - // Received range from the SMeter can be -127 for S0, S9 is -73, and S9+60=-13.; - // PowerSDR returns S9=0015 code. - // Let's make S9 half scale or a value of 70. - double level; - level = GetRXAMeter(CHANNEL_RX0, smeter); - // Determine how high above 127 we are..making a range of 114 from S0 to S9+60db - // 5 is a fugdge factor that shouldn't be there - but seems to get us to S9=SM015 - level = abs(127+(level + (double) get_attenuation()))+5; - - // Clip the value just in case - if(cmd_input[2] == '0') { - new_level = (int) ((level * 30.0)/114.0); - // Do saturation check - if(new_level < 0) { new_level = 0; } - if(new_level > 30) { new_level = 30;} - } else { //Assume we are using sub receiver where range is 0-15 - new_level = (int) ((level * 15.0)/114.0); - // Do saturation check - if(new_level < 0) { new_level = 0; } - if(new_level > 15) { new_level = 15;} - } - sprintf(msg,"SM%1c%04d;", - cmd_input[2],new_level); - send_resp(msg); - } - else if(strcmp(cmd_str,"SQ")==0) { // Set/read the squelch level - // P1 - 0- main, 1=sub - // P2 - 0-255 - if(len <=3) { - sprintf(msg,"SQ%04d;",squelch); - send_resp(msg); - } else { - squelch = atoi(&cmd_input[2]); - } - } - else if(strcmp(cmd_str,"SR")==0) { // Resets the transceiver - } - else if(strcmp(cmd_str,"SS")==0) { // Set/read Scan pause freq - if(len <=2) { - send_resp("SS0;"); - } - } - else if(strcmp(cmd_str,"ST")==0) { // Set/read the multi/ch control freq steps - // SSB/CW/FSK - values 00-03 - // 00: 1KHz, 01: 2.5Khz 02:5KHz 03: 10Khz - // AM/FM mode 00-09 - // 00: 5KHz, - // 01: 6.25KHz, - // 02:10Khz, - // 03: 12.5Khz, - // 04: 15Khz, - // 05: 20Khz, - // 06: 25KHz - // 07: 30Khz - // 08: 50Khz - // 09: 100Khz - int coded_step_val; - entry= (BANDSTACK_ENTRY *) - bandstack_entry_get_current(); - if(len <=2) { - switch(entry->mode) { - case modeLSB: - case modeUSB: - case modeCWL: - case modeCWU: - case modeDIGU: - case modeDIGL: - if(step >0 && step <= 1000) { - coded_step_val = 0; - } else if (step >1000 && step <=2500) { - coded_step_val = 1; - } else if (step >2500 && step <=5000) { - coded_step_val = 2; - } else { - coded_step_val = 3; - } - break; - case modeFMN: - case modeAM: - if(step >0 && step <= 5000) { - coded_step_val = 0; - } else if (step >5000 && step <=6250) { - coded_step_val = 1; - } else if (step >6250 && step <=10000) { - coded_step_val = 2; - } else if (step >10000 && step <=12500) { - coded_step_val = 3; - } else if (step >12500 && step <=15000) { - coded_step_val = 4; - } else if (step >15000 && step <=20000) { - coded_step_val = 5; - } else if (step >20000 && step <=25000) { - coded_step_val = 6; - } else if (step >25000 && step <=30000) { - coded_step_val = 7; - } else if (step >30000 && step <=50000) { - coded_step_val = 8; - } else if (step >50000 && step <=100000) { - coded_step_val = 9; - } else { - coded_step_val = 0; - } - break; - } - sprintf(msg,"ST%02d;",coded_step_val); - send_resp(msg); - } else { - coded_step_val = atoi(&cmd_input[2]); - switch(entry->mode) { - case modeLSB: - case modeUSB: - case modeCWL: - case modeCWU: - case modeDIGU: - case modeDIGL: - if(coded_step_val==0) { step = 1000;} - if(coded_step_val==1) { step = 2500;} - if(coded_step_val==2) { step = 5000;} - if(coded_step_val==3) { step = 10000;} - break; - case modeFMN: - case modeAM: - switch(coded_step_val) { - case 0: step = 5000; break; - case 1: step = 6250; break; - case 2: step = 10000; break; - case 3: step = 12500; break; - case 4: step = 15000; break; - case 5: step = 20000; break; - case 6: step = 25000; break; - case 7: step = 30000; break; - case 8: step = 50000; break; - case 9: step = 100000; break; - default: break; // No change if not a valid number - } - default: break; // No change if not a valid number - } - g_idle_add(vfo_update,NULL); - } - } - else if(strcmp(cmd_str,"SU")==0) { // Set/read the scan pause freq - if(len <=2) { - send_resp("SU00000000000;"); - } - } - else if(strcmp(cmd_str,"SV")==0) { // Execute the memory transfer function - } - else if(strcmp(cmd_str,"TC")==0) { // Set/read the internal TNC mode - if(len <=2) { - send_resp("TC00;"); - } - } - else if(strcmp(cmd_str,"TD")==0) { // Sends the DTMF memory channel - } - else if(strcmp(cmd_str,"TI")==0) { // Reads the TNC LED status - if(len <=2) { - send_resp("TI00;"); - } - } - else if(strcmp(cmd_str,"TN")==0) { // Set/Read sub tone freq - if(len <=2) { - send_resp("TN00;"); - } - } - else if(strcmp(cmd_str,"TO")==0) { // Set/Read tone function - if(len <=2) { - send_resp("TO0;"); - } - } - else if(strcmp(cmd_str,"TS")==0) { // Set/Read TF Set function status - if(len <=2) { - send_resp("TS0;"); - } - } - else if(strcmp(cmd_str,"TX")==0) { // Key Xmitter - P1 - transmit on main/sub freq - setMox(1); - if(len <=2) { - send_resp("TS0;"); - } - } - else if(strcmp(cmd_str,"TY")==0) { // Set/Read uP firmware type - if(len <=2) { - send_resp("TY000;"); - } - } - else if(strcmp(cmd_str,"UL")==0) { // Detects the PLL unlock status - this should never occur - xmit only - if(len <=2) { - send_resp("UL0;"); - } - } - else if(strcmp(cmd_str,"UP")==0) { // Emulates the mic up key - } - else if(strcmp(cmd_str,"VD")==0) { // Sets/Reads VOX dleay time - 0000-3000ms in steps of 150 - // We want vox_hang variable in PiHPSDR - // Max value in variable in ms... so 250 = 250ms - #ifdef RIGCTL_DEBUG - fprintf(stderr,"RIGCTL: Vox hang=%0.20f\n",vox_hang); - #endif - if(len <=2) { - work_int = (int) vox_hang; - sprintf(msg,"VD%04d;",work_int); - send_resp(msg); - } else { - work_int = atoi(&cmd_input[2]); - // Bounds check for legal values for PiHPSDR - if(work_int > 1000) { work_int = 1000; } - if(work_int < 0) { work_int = 0; } - vox_hang = (double) work_int; - #ifdef RIGCTL_DEBUG - fprintf(stderr,"RIGCTL: Vox hang=%0.20f\n",vox_hang); - #endif - } - } - else if(strcmp(cmd_str,"VG")==0) { // Sets/Reads VOX gain 000-009 - // We want vox_threshold variable in PiHPSDR - // Max value in variable 0.1 - // 3 char 000-009 valid ranges - #ifdef RIGCTL_DEBUG - fprintf(stderr,"RIGCTL: Vox thesh=%0.20f\n",vox_threshold); - #endif - if(len <=2) { - work_int = (int) ((vox_threshold) * 100.0); - sprintf(msg,"VG00%1d;",work_int); - send_resp(msg); - } else { - // Set the threshold here - work_int = atoi(&cmd_input[2]); - vox_threshold = ((double) work_int)/100.0; - #ifdef RIGCTL_DEBUG - fprintf(stderr,"RIGCTL: Vox thresh=%0.20f\n",vox_threshold); - #endif - } - } - else if(strcmp(cmd_str,"VR")==0) { // Emulates the voice 1/2 key - } - else if(strcmp(cmd_str,"VX")==0) { // Sets/reads vox f(x) state - if(len <=2) { - sprintf(msg,"VX%1d;",vox_enabled); - send_resp(msg); - } else { - work_int = atoi(&cmd_input[2]); - if(work_int>1) { vox_enabled = 1; vox= 1;} - if(work_int<1) { vox_enabled = 0; vox=0; } - } - } - else if(strcmp(cmd_str,"XT")==0) { // Sets/reads the XIT f(x) state - if(len <=2) { - send_resp("XT0;"); - } - } - else if(strcmp(cmd_str,"XX")==0) { // - // Format RL01234: First dig 0=neg, 1=pos number - // 1-4- digital offset in hertz. - if(len > 4) { // It is set instead of a read - digl_pol = (cmd_input[2]=='0') ? -1 : 1; - digl_offset = atoi(&cmd_input[3]); - #ifdef RIGCTL_DEBUG - fprintf(stderr,"RIGCTL:RL set %d %d\n",digl_pol,digl_offset); - #endif - } else { - if(digl_pol==1) { // Nah - its a read - sprintf(msg,"RL1%04d;",0); - } else { - sprintf(msg,"RL0%04d;",0); - } - send_resp(msg); - #ifdef RIGCTL_DEBUG - fprintf(stderr,":%s\n",msg); - #endif - } - } - else if(strcmp(cmd_str,"XY")==0) { // set/read RTTY DIGL offset frequency - Not available - just store values - // Format RL01234: First dig 0=neg, 1=pos number - // 1-4- digital offset in hertz. - if(len > 4) { // It is set instead of a read - digl_pol = (cmd_input[2]=='0') ? -1 : 1; - digl_offset = atoi(&cmd_input[3]); - #ifdef RIGCTL_DEBUG - fprintf(stderr,"RIGCTL:RL set %d %d\n",digl_pol,digl_offset); - #endif - } else { - if(digl_pol==1) { // Nah - its a read - sprintf(msg,"RL1%04d;",0); - } else { - sprintf(msg,"RL0%04d;",0); - } - send_resp(msg); - #ifdef RIGCTL_DEBUG - fprintf(stderr,":%s\n",msg); - #endif - } - } - else { - fprintf(stderr,"RIGCTL: UNKNOWN=%s\n",cmd_str); - } -} -// -// End of Parser -// -/* -char * rigctlGetFilter() -{ - - char * m = mode_string[mode]; - - if (strcmp(m,"CWU") == 0){ - return (char *) (getFilterHigh() + getFilterLow()); - } - else - if (strcmp(m,"CWL") == 0){ - return (char *) (getFilterHigh() + getFilterLow()); - } - else - return (char *) (getFilterHigh() - getFilterLow()); -} -*/ - -void launch_rigctl () { - int err; - fprintf(stderr, "LAUNCHING RIGCTL!!\n"); - // This routine encapsulates the pthread call - err = pthread_create (&rigctl_thread_id,NULL,rigctl,NULL); - if(err != 0) { - fprintf(stderr, "pthread_create failed on rigctl launch\n"); - } -} - -// -// Telnet Server Code below: -// - // max number of bytes we can get at once - #define MAXDATASIZE 300 - -int init_server () { - - //Create socket - socket_desc = socket(AF_INET , SOCK_STREAM , 0); - if (socket_desc == -1) - { - fprintf(stderr,"RIGCTL: Could not create socket"); - } - fprintf(stderr, "RIGCTL: Socket created\n"); - - //Prepare the sockaddr_in structure - server.sin_family = AF_INET; - server.sin_addr.s_addr = INADDR_ANY; - server.sin_port = htons( TELNET_PORT ); - - //Bind - if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0) - { - //print the error message - fprintf(stderr,"RIGCLT: bind failed. Error\n"); - return 1; - } - fprintf(stderr,"RIGCTL: bind done\n"); - - //Listen - listen(socket_desc , 3); - - //Accept and incoming connection - fprintf(stderr,"RIGCTL: Waiting for incoming connections...\n"); - c = sizeof(struct sockaddr_in); - - //accept connection from an incoming client - client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c); - if (client_sock < 0) - { - fprintf(stderr,"RIGCTL: Accept failed\n"); - return 1; - } - fprintf(stderr,"RIGCTL: Connection accepted\n"); -} -/* -int rigctlGetFilterLow() { - int lookup; - int rval; - - BANDSTACK_ENTRY *entry; - entry = (BANDSTACK_ENTRY *) bandstack_entry_get_current(); - - FILTER* band_filters=filters[entry->mode]; - FILTER* band_filter=&band_filters[entry->filter]; - rval = 0; - for(lookup = 0; lookup<=9; lookup++) { - if(band_filter[lookup].low == -150) { - rval = lookup; - break; - } - } - return rval; -} - -int rigctlGetFilterHigh() { - int lookup; - int rval; - - BANDSTACK_ENTRY *entry; - entry = (BANDSTACK_ENTRY *) bandstack_entry_get_current(); - - FILTER* band_filters=filters[entry->mode]; - FILTER* band_filter=&band_filters[entry->filter]; - rval = 0; - for(lookup = 0; lookup<=9; lookup++) { - if(band_filter[lookup].high == -150) { - rval = lookup; - break; - } - } - return rval; -} -*/ -int rigctlGetMode() { - BANDSTACK_ENTRY *entry; - entry= (BANDSTACK_ENTRY *) - bandstack_entry_get_current(); - switch(entry->mode) { - case modeLSB: return(1); // LSB - case modeUSB: return(2); // USB - case modeCWL: return(7); // CWL - case modeCWU: return(3); // CWU - case modeFMN: return(4); // FMN - case modeAM: return(5); // AM - case modeDIGU: return(9); // DIGU - case modeDIGL: return(6); // DIGL - default: return(0); - } -} - -int rigctlSetFilterLow(int val){ -}; -int rigctlSetFilterHigh(int val){ -}; - -void set_band(long long new_freqA) { - - BANDSTACK_ENTRY *entry; - int b = get_band_from_frequency(new_freqA); - if(b == -1) { // Out of ham bands... - setFrequency(new_freqA); - g_idle_add(vfo_update,NULL); - return; - } - - if(b==band_get_current()) { - entry = bandstack_entry_next(); - setFrequency(new_freqA); - g_idle_add(vfo_update,NULL); - return; - } else { - BAND* band=band_set_current(b); - entry=bandstack_entry_get_current(); - } - setMode(entry->mode); - FILTER* band_filters=filters[entry->mode]; - FILTER* band_filter=&band_filters[entry->filter]; - setFilter(band_filter->low,band_filter->high); - setFrequency(new_freqA); - - BAND *band=band_get_current_band(); - set_alex_rx_antenna(band->alexRxAntenna); - set_alex_tx_antenna(band->alexTxAntenna); - set_alex_attenuation(band->alexAttenuation); - - setFrequency(new_freqA); - g_idle_add(vfo_update,NULL); - - - calcDriveLevel(); - calcTuneDriveLevel(); -} + +/* TS-2000 emulation via TCP + * Copyright (C) 2016 Steve Wilson + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * PiHPSDR RigCtl by Steve KA6S Oct 16 2016 + * With a kindly assist from Jae, K5JAE who has helped + * greatly with hamlib integration! + */ +#include +#include +#include +//#include +#include +#include +#include "toolbar.h" +#include "sliders.h" +#include "rigctl.h" +#include "radio.h" +#include "receiver.h" +#include "channel.h" +#include "filter.h" +#include +#include "mode.h" +#include "filter.h" +#include "band.h" +#include "bandstack.h" +#include "vfo.h" +#include "sliders.h" +#include +#include "agc.h" +#include +#include "store.h" + +// IP stuff below +#include +#include //inet_addr + +//#undef RIGCTL_DEBUG +#define RIGCTL_DEBUG + +// the port client will be connecting to +// 2-26-17 K5JAE - Changed the defines to const ints to allow use via pointers. +static const int TelnetPortA = 19090; +static const int TelnetPortB = 19091; +static const int TelnetPortC = 19092; + +// max number of bytes we can get at once +#define MAXDATASIZE 300 + +int init_server (); +void parse_cmd (); + +int rigctlGetFilterLow(); +int rigctlGetFilterHigh(); +int rigctlSetFilterLow(int val); +int rigctlSetFilterHigh(int val); +int new_level; +int active_transmitter = 0; + +int cat_control; + +extern int enable_tx_equalizer; + +/* +pthread_mutex_t mutex_a = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t mutex_b = PTHREAD_MUTEX_INITIALIZER; +*/ +typedef struct {GMutex m; } GT_MUTEX; +GT_MUTEX * mutex_a; +GT_MUTEX * mutex_b; + +FILE * out; +int output; +FILTER * band_filter; + +//static pthread_t rigctl_a_thread_id, rigctl_b_thread_id, rigctl_c_thread_id; +static GThread *rigctl_a_thread_id, *rigctl_b_thread_id, *rigctl_c_thread_id; + +int squelch=100; //local sim of squelch level + + +int read_size; + +int freq_flag; // Determines if we are in the middle of receiving frequency info + +int digl_offset = 0; +int digl_pol = 0; +int digu_offset = 0; +int digu_pol = 0; +double new_vol = 0; +int lcl_cmd=0; +long long new_freqA = 0; +long long new_freqB = 0; +long long orig_freqA = 0; +long long orig_freqB = 0; +int lcl_split = 0; +int mox_state = 0; +// Radio functions - +// Memory channel stuff and things that aren't +// implemented - but here for a more complete emulation +int ctcss_tone; // Numbers 01-38 are legal values - set by CN command, read by CT command +int ctcss_mode; // Numbers 0/1 - on off. + +int vfo_sm=0; // VFO State Machine - this keeps track of + +// Now my stuff +// + +// This looks up the frequency of the Active receiver with +// protection for 1 versus 2 receivers +long long rigctl_getFrequency() { + if(receivers == 1) { + return vfo[VFO_A].frequency; + } else { + return vfo[active_receiver->id].frequency; + } +} +// Looks up entry INDEX_NUM in the command structure and +// returns the command string +// +void send_resp (int client_sock,char * msg) { + #ifdef RIGCTL_DEBUG + fprintf(stderr,"RIGCTL: RESP=%s\n",msg); + #endif + write(client_sock, msg, strlen(msg)); +} + +// +// 2-25-17 - K5JAE - removed duplicate rigctl +// + +//static void * rigctl_a (void * arg) { +static gpointer rigctl (gpointer data) { + int len; + int c; + int socket_desc; + struct sockaddr_in client; + struct sockaddr_in server; + + // user data void* is really an int* of the port + int port = *((int*) data); + int client_sock = init_server(&socket_desc, &client, &server, port); + + g_mutex_lock(&mutex_a->m); + cat_control++; +//#ifdef RIGCTL_DEBUG +fprintf(stderr,"RIGCTL: CTLA INC cat_contro=%d\n",cat_control); +//#endif + g_mutex_unlock(&mutex_a->m); + g_idle_add(vfo_update,NULL); + + int save_flag = 0; // Used to concatenate two cmd lines together + int semi_number = 0; + int i; + char * work_ptr; + char work_buf[MAXDATASIZE]; + int numbytes; + char cmd_input[MAXDATASIZE] ; + char cmd_save[80]; + + for(;;) { + fprintf(stderr,"RIGCTL - New run on server port: %d\n", port); + while((numbytes=recv(client_sock , cmd_input , MAXDATASIZE-2 , 0)) > 0 ) { + for(i=0;im); + parse_cmd(work_ptr,strlen(work_ptr),client_sock); + /* + pthread_mutex_unlock (& mutex_b); + */ + g_mutex_unlock(&mutex_b->m); + work_ptr = strtok(NULL,";"); + } + for(i=0;im); + cat_control--; +#ifdef RIGCTL_DEBUG +fprintf(stderr,"RIGCTL: CTLA DEC - cat_control=%d\n",cat_control); +#endif + g_mutex_unlock(&mutex_a->m); + g_idle_add(vfo_update,NULL); + + //sleep(1); + c = sizeof(struct sockaddr_in); + client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c); + + // Increment CAT_CONTROL + g_mutex_lock(&mutex_a->m); + cat_control++; +#ifdef RIGCTL_DEBUG +fprintf(stderr,"RIGCTL: CTLA INC - cat_control=%d\n",cat_control); +#endif + g_mutex_unlock(&mutex_a->m); + g_idle_add(vfo_update,NULL); + + //sleep(1); + } + } +} + +// +// FT command intepret vfo_sm state - used by IF command +// +int ft_read() { + return(active_transmitter); +} +// +// Determines RIT state - used by IF command +// +int rit_on () { + if(receivers == 1) { // Worry about 1 versus 2 radios + if(vfo[VFO_A].rit != 0) { + return 1; + } else { + return 0; + } + } else { // Well - we have two so use active_reciever->id + if(vfo[active_receiver->id].rit != 0) { + return 1 ; + } else { + return 0; + } + } +} +void parse_cmd ( char * cmd_input,int len,int client_sock) { + int work_int; + int new_low, new_high; + double meter; + char msg[80]; + char buf[80]; + BANDSTACK_ENTRY *entry; + // Parse the cmd_input + //int space = command.indexOf(' '); + //char cmd_char = com_head->cmd_string[0]; // Assume the command is first thing! + char cmd_str[3]; + cmd_str[0] = cmd_input[0]; + cmd_str[1] = cmd_input[1]; + cmd_str[2] = '\0'; + if(strcmp(cmd_str,"AC")==0) { // Sets or reads the internal antenna tuner status + // P1 0:RX-AT Thru, 1: RX-AT IN + // P2 0: TX-AT Thru 1: TX-AT In + // + if(len <= 2) { + send_resp(client_sock,"AC000;"); + } + } + else if(strcmp(cmd_str,"AG")==0) { // Set Audio Gain - + // AG123; Value of 0- + // AG1 = Sub receiver - what is the value set + // Response - AG<0/1>123; Where 123 is 0-260 + int lcl_receiver; + if(receivers == 1) { + lcl_receiver = 0; + } else { + lcl_receiver = active_receiver->id; + } + if(len>4) { // Set Audio Gain + active_receiver->volume = (double) atoi(&cmd_input[3])/260; + g_idle_add(update_af_gain,NULL); + } else { // Read Audio Gain + sprintf(msg,"AG%1d%03d;",lcl_receiver,(int) (2.6 * active_receiver->volume)); + send_resp(client_sock,msg); + } + } + else if(strcmp(cmd_str,"AI")==0) { // Allow rebroadcast of set frequency after set - not supported + if(len <=2) { + //send_resp(client_sock,"AI0;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"AL")==0) { // Set/Reads the auto Notch level + if(len <=2) { + //send_resp(client_sock,"AL000;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"AM")==0) { // Sets or reads the Auto Mode + if(len <=2) { + //send_resp(client_sock,"AM0;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"AN")==0) { // Selects the antenna connector (ANT1/2) + if(len <=2) { + //send_resp(client_sock,"AN0;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"AR")==0) { // Sets or reads the ASC function on/off + if(len <=2) { + //send_resp(client_sock,"AR0;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"AS")==0) { // Sets/reads automode function parameters + // AS<2xP2><11P3>; + // AS<2xP2><11P3>; + if(len < 6) { + /* sprintf(msg,"AS%1d%02d%011lld%01d;", + 0, // P1 + 0, // Automode + getFrequency(), + rigctlGetMode()); + send_resp(client_sock,msg);*/ + send_resp(client_sock,"?;"); + + } + } + else if(strcmp(cmd_str,"BC")==0) { // Beat Cancellor OFF + if(len <=2) { + //send_resp(client_sock,"BC0;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"BD")==0) { // Moves down the frequency band + // No response + } + else if(strcmp(cmd_str,"BP")==0) { // Reads the manual beat canceller frequency setting + if(len <=2) { + //send_resp(client_sock,"BP000;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"BS")==0) { // Sets or reads Beat Canceller status + if(len <=2) { + //send_resp(client_sock,"BS0;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"BU")==0) { // Moves Up the frequency band + // No response + } + else if(strcmp(cmd_str,"BY")==0) { // Read the busy signal status + if(len <=2) { + //send_resp(client_sock,"BY00;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"CA")==0) { // Sets/reads cw auto tune function status + if(len <=2) { + //send_resp(client_sock,"CA0;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"CG")==0) { // Sets/reads the carrier gain status + // 0-100 legal values + if(len <=2) { + //send_resp(client_sock,"CG000;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"CH")==0) { // Sets the current frequency to call Channel + // No response + } + else if(strcmp(cmd_str,"CI")==0) { // While in VFO mode or memory recall mode, sets freq to the call channel + // No response + } + else if(strcmp(cmd_str,"CM")==0) { // Sets or reads the packet cluster tune f(x) on/off + // 0-100 legal values + if(len <=2) { + //send_resp(client_sock,"CM0;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"CN")==0) { // Sets and reads CTSS function - 01-38 legal values + // Stored locally in rigctl - not used. + if(len <=2) { + sprintf(msg,"CN%02d;",ctcss_tone); + send_resp(client_sock,msg); + send_resp(client_sock,"?;"); + } else { + ctcss_tone = atoi(&cmd_input[2]); + } + } + else if(strcmp(cmd_str,"CT")==0) { // Sets and reads CTSS function status + // Stored locally in rigctl - not used. + if(len <=2) { + sprintf(msg,"CT%01d;",ctcss_mode); + send_resp(client_sock,msg); + } else { + ctcss_mode = atoi(&cmd_input[2]); + } + } + else if(strcmp(cmd_str,"DC")==0) { // Sets/Reads TX band status + if(len <=2) { + //send_resp(client_sock,"DC00;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"DN")==0) { // Emulate Mic down key + } + else if(strcmp(cmd_str,"DQ")==0) { // ETs/and reads the DCS function status + if(len <=2) { + //send_resp(client_sock,"DQ0;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"EX")==0) { // Set/reads the extension menu + // This routine only can look up specific information; + // And only performs reads at this point.. + // EX P1 P1 P1 P2 P2 P3 P4 ; - Read command + int p5=0; + strncpy(buf,cmd_input,9); // Get the front of the response + if(len == 10) { // Read command + // CW Sidetone frequendcy + if(strncmp(&cmd_input[2],"031",3) == 0) { + if(cw_keyer_sidetone_frequency <=400) { + p5 = 0; + } else if (cw_keyer_sidetone_frequency <=450) { + p5 = 1; + } else if (cw_keyer_sidetone_frequency <=500) { + p5 = 2; + } else if (cw_keyer_sidetone_frequency <=550) { + p5 = 3; + } else if (cw_keyer_sidetone_frequency <=600) { + p5 = 4; + } else if (cw_keyer_sidetone_frequency <=650) { + p5 = 5; + } else if (cw_keyer_sidetone_frequency <=700) { + p5 = 6; + } else if (cw_keyer_sidetone_frequency <=750) { + p5 = 7; + } else if (cw_keyer_sidetone_frequency <=800) { + p5 = 8; + } else if (cw_keyer_sidetone_frequency <=850) { + p5 = 9; + } + sprintf(msg,"%s%01d;",buf,p5); + send_resp(client_sock,msg); + // SPLIT + } else if(strncmp(&cmd_input[2],"06A",3) == 0) { + sprintf(msg,"%s%01d;",buf,split); + send_resp(client_sock,msg); + } else { + send_resp(client_sock,"?;"); + } + } + } + else if(strcmp(cmd_str,"FA")==0) { // VFO A frequency + // LEN=7 - set frequency + // Next data will be rest of freq + if(len == 13) { //We are receiving freq info + new_freqA = atoll(&cmd_input[2]); + set_band(new_freqA,(int)-1); + //setFrequency(new_freqA); + //g_idle_add(vfo_update,NULL); + } else { + if(len==2) { + //sprintf(msg,"FA%011lld;",getFrequency()); + sprintf(msg,"FA%011lld;",vfo[VFO_A].frequency); + send_resp(client_sock,msg); + } + } + } + else if(strcmp(cmd_str,"FB")==0) { // VFO B frequency + if(len==13) { //We are receiving freq info + new_freqB = atoll(&cmd_input[2]); + set_freqB(new_freqB); + //setFrequency(new_freqA); + //g_idle_add(vfo_update,NULL); + } else if(len == 2) { + sprintf(msg,"FB%011lld;",vfo[VFO_B].frequency); + send_resp(client_sock,msg); + } + } + /* Not supported */ + else if(strcmp(cmd_str,"FC")==0) { // Set Sub receiver freq + // LEN=7 - set frequency + // Next data will be rest of freq + // Len<7 - frequency? + if(len>4) { //We are receiving freq info + long long new_freqA = atoll(&cmd_input[2]); + //setFrequency(new_freqA); + } else { + sprintf(msg,"FC%011lld;",rigctl_getFrequency()); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"FD")==0) { // Read the filter display dot pattern + send_resp(client_sock,"FD00000000;"); + } + else if(strcmp(cmd_str,"FR")==0) { // Set/reads the extension menu + if(len <=2) { + if(receivers == 1) { + sprintf(msg,"FR0;"); + } else { + sprintf(msg,"FR%1d;",active_receiver->id); + } + send_resp(client_sock,msg); + } else if (receivers != 1) { + lcl_cmd = atoi(&cmd_input[2]); + if(active_transmitter != lcl_cmd) { + split = 1; + } + if(active_receiver->id != lcl_cmd) { + //active_receiver->id = lcl_cmd; + active_receiver = receiver[lcl_cmd]; + g_idle_add(vfo_update,NULL); + g_idle_add(active_receiver_changed,NULL); + } + } + } + else if(strcmp(cmd_str,"FS")==0) { // Set/reads fine funct status + if(len <=2) { + send_resp(client_sock,"FS0;"); + } + } + else if(strcmp(cmd_str,"FT")==0) { // Sel or reads the transmitters VFO, M, ch or Call comm + if(len <=2) { + sprintf(msg,"FT%1d",active_transmitter); + send_resp(client_sock,msg); + } else { + lcl_cmd = atoi(&cmd_input[2]); + if(lcl_cmd != active_receiver->id) { + split = 1; + } else { + split = 0; + } + active_transmitter = lcl_cmd; + g_idle_add(vfo_update,NULL); + } + } + else if(strcmp(cmd_str,"FW")==0) { // Sets/Reas DSP receive filter width in hz 0-9999hz + // CW - legal values 50 80 100 150 200 300 400 500 600 1000 2000 + // PiHPSDR map 50 100 100 100 250 250 400 500 600 1000 + // 25 750 + entry= (BANDSTACK_ENTRY *) + bandstack_entry_get_current(); + FILTER* band_filters=filters[entry->mode]; + FILTER* band_filter=&band_filters[entry->filter]; + if(len <=2) { + // CW filter high and low are always the same and the filter value is 2*filter val + int filter_val = band_filter->high * 2; + switch(filter_val) { + case 25: + case 50: + work_int = 50; + break; + case 100: + work_int = 100; + break; + case 250: + work_int = 300; + break; + case 400: + work_int = 400; + break; + case 500: + work_int = 500; + break; + case 600: + work_int = 600; + break; + case 750: + work_int = 1000; + break; + case 800: + work_int = 1000; + break; + case 1000: + work_int = 1000; + break; + default: work_int = 500; + break; + } + sprintf(msg,"FW%04d;",work_int); + #ifdef RIGCTL_DEBUG + fprintf(stderr,"RIGCTL: FW Filter Act=%d work_int=%d\n",band_filter->high,work_int); + #endif + send_resp(client_sock,msg); + } else { + // Try to set filters here! + // CW - legal values 50 80 100 150 200 300 400 500 600 1000 2000 + // PiHPSDR map 50 100 100 100 250 250 400 500 600 1000 + // 25 750 + work_int = atoi(&cmd_input[2]); + switch (work_int) { + + case 50: new_low = 25; new_high = 25; break; + case 80: new_low = 50; new_high = 50; break; + case 100: new_low = 50; new_high = 50; break; + case 150: new_low = 50; new_high = 50; break; + case 200: new_low = 125; new_high = 125; break; + case 300: new_low = 125; new_high = 125; break; + case 400: new_low = 200; new_high = 200; break; + case 500: new_low = 250; new_high = 250; break; + case 600: new_low = 300; new_high = 300; break; + case 1000: new_low = 500; new_high = 500; break; + case 2000: new_low = 500; new_high = 500; break; + default: new_low = band_filter->low; + new_high = band_filter->high; + + } + #ifdef RIGCTL_DEBUG + fprintf(stderr,"RIGCTL: FW Filter new_low=%d new_high=%d\n",new_low,new_high); + #endif + // entry->filter = new_low * 2 ; + //setFilter(new_low,new_high); + set_filter(active_receiver,new_low,new_high); + g_idle_add(vfo_update,NULL); + } + } + else if(strcmp(cmd_str,"GT")==0) { // Sets/Read AGC constant status 000-020 + // Map 000 - Off, 001-4 - Fast, 4-9 - Medium 10-14 Slow 15-20 Long + //fprintf(stderr,"GT command seen\n"); + int agc_resp = 0; + if(len <=2) { + + switch(active_receiver->agc) { + case AGC_OFF : agc_resp = 0; break; + case AGC_FAST: agc_resp = 5; break; + case AGC_MEDIUM: agc_resp = 10; break; + case AGC_SLOW: agc_resp = 15; break; + case AGC_LONG: agc_resp = 20; break; + default: agc_resp = 0; + } + + sprintf(msg,"GT%03d;",agc_resp); + send_resp(client_sock,msg); + } else { + //fprintf(stderr,"GT command Set\n"); + agc_resp = atoi(&cmd_input[2]); + + // AGC powers of 84 is broken Hamlib... + // Hamlib TS-2000 is broken here + + if(agc_resp == 0) { + active_receiver->agc = AGC_OFF; + } else if(agc_resp >0 && agc_resp <= 5 || (agc_resp == 84)) { + active_receiver->agc = AGC_FAST; + // fprintf(stderr,"GT command FAST\n"); + } else if(agc_resp >6 && agc_resp <= 10 || (agc_resp == 2*84)) { + active_receiver->agc = AGC_MEDIUM; + // fprintf(stderr,"GT command MED\n"); + } else if(agc_resp >11 && agc_resp <= 15 || (agc_resp == 3*84)) { + active_receiver->agc = AGC_SLOW; + //fprintf(stderr,"GT command SLOW\n"); + } else if(agc_resp >16 && agc_resp <= 20 || (agc_resp == 4*84)) { + active_receiver->agc = AGC_LONG; + // fprintf(stderr,"GT command LONG\n"); + } + g_idle_add(vfo_update,NULL); + + } + } + else if(strcmp(cmd_str,"ID")==0) { // Read ID - Default to TS-2000 which is type 019. + sprintf(msg,"ID019;"); + send_resp(client_sock,msg); + } + else if(strcmp(cmd_str,"IF")==0) { // Reads Transceiver status + // IF + // P1: FFFFFFFFFFF -11 chars : Frequency in Hz (blanks are "0") + // P2: OFFS - 4 chars : Offset in powers of 10 + // P3: RITXIT - 6 chars : RIT/XIT Frequency, Not supported = "000000" + // P4: R - 1 char : RIT Status "1"= On, "0"= off + // P5: X - 1 char : XIT Status "1"= On, "0"= off + // P6: 0 - 1 char : Channel Bank number - not used (see MC command) + // P7: 00 - 2 chars : Channel Bank number - not used + // P8: C - 1 char : Mox Status "1"= TX, "0"= RX + // P9: M - 1 char : Operating mode (see MD command) + // P10: V - 1 char : VFO Split status - not supported + // P11: 0 - 1 char : Scan status - not supported + // P12: A - 1 char : same as FT command + // P13: 0 - 1 char : CTCSS tone - not used + // P14: 00 - 2 chars : More tone control + // P15: 0 - 1 char : Shift status + + // convert first half of the msg + // IF P1 P2 P3 P4 P5 P6 + sprintf(msg,"IF%011lld%04lld%06d%01d%01d%01d", + //getFrequency(), + rigctl_getFrequency(), // P1 + step, // P2 + vfo[active_receiver->id].rit, // P3 + rit_on(), // P4 + rit_on(), // P5 + 0 // P6 + ); + + // convert second half of the msg + // P7 P8 P9 P10 P11 P12 P13 P14 P15; + sprintf(msg+26,"%02d%01d%01d%01d%01d%01d%01d%02d%01d;", + 0, // P7 + mox, // P8 + rigctlGetMode(), // P9 + 0, // P10 + 0, // P11 + ft_read(), // P12 + ctcss_tone, // P13 + 0, // P14 + 0); // P15 + send_resp(client_sock,msg); + } + else if(strcmp(cmd_str,"IS")==0) { // Sets/Reas IF shift funct status + if(len <=2) { + send_resp(client_sock,"IS00000;"); + } + } + else if(strcmp(cmd_str,"KS")==0) { // Sets/Reads keying freq - 0-060 max + if(len <=2) { + sprintf(msg,"KS%03d;",cw_keyer_speed); + send_resp(client_sock,msg); + } else { + int key_speed; + key_speed = atoi(&cmd_input[2]); + if(key_speed >1 && key_speed <= 60) { + cw_keyer_speed=key_speed; + g_idle_add(vfo_update,NULL); + } + } + } + else if(strcmp(cmd_str,"KY")==0) { // Convert char to morse code + if(len <=2) { + send_resp(client_sock,"KY0;"); + } + } + else if(strcmp(cmd_str,"LK")==0) { // Set/read key lock function status + if(len <=2) { + sprintf(msg,"LK%01d%01d;",locked,locked); + send_resp(client_sock,msg); + } else { + if(cmd_input[3] == '0') { + locked = 0; + } else if(cmd_input[3] == '1') { + locked = 1; + } + g_idle_add(vfo_update,NULL); + } + } + else if(strcmp(cmd_str,"LM")==0) { // Set/read DRU 3A unit or elect keyer recording status + if(len <=2) { + send_resp(client_sock,"LM0;"); + } + } + else if(strcmp(cmd_str,"LT")==0) { // Set/read Alt function + if(len <=2) { + send_resp(client_sock,"LT0;"); + } + } + else if(strcmp(cmd_str,"MC")==0) { // Recalls or reads memory channel + if(len <=2) { + send_resp(client_sock,"MC000;"); // Link this to band stack at some point + } + } + else if(strcmp(cmd_str,"MD")==0) { // Mode - digit selects mode + // 1 = LSB + // 2 = USB + // 3 = CWU + // 4 = FM + // 5 = AM + // 6 = DIGL + // 7 = CWL + // 9 = DIGU + int new_mode; + if(len > 2) { // Set Mode + switch(atoi(&cmd_input[2])) { + case 1: + new_mode = modeLSB; + break; + case 2: + new_mode = modeUSB; + break; + case 3: + new_mode = modeCWU; + break; + case 4: + new_mode = modeFMN; + break; + case 5: + new_mode = modeAM; + break; + case 6: + new_mode = modeDIGL; + break; + case 7: + new_mode = modeCWL; + break; + case 9: + new_mode = modeDIGU; + break; + default: + break; + #ifdef RIGCTL_DEBUG + fprintf(stderr,"MD command Unknown\n"); + #endif + } + // Other stuff to switch modes goes here.. + // since new_mode has the interpreted command in + // in it now. + entry= (BANDSTACK_ENTRY *) + bandstack_entry_get_current(); + entry->mode=new_mode; + // BUG - kills the system when there is some + // GPIO activity and Mode sets occur. Used twittling the + // frequency along with setting mode between USB/LSB with + // flrig. Tried doing the g_idle_add trick - but don't know the + // the magic to get that to compile without warnings + //setMode(entry->mode); + set_mode(active_receiver,entry->mode); + // Moved the vfo_update down after filter updated. (John G0ORX) + //g_idle_add(vfo_update,NULL); + + FILTER* band_filters=filters[entry->mode]; + FILTER* band_filter=&band_filters[entry->filter]; + //setFilter(band_filter->low,band_filter->high); + set_filter(active_receiver,band_filter->low,band_filter->high); + /* Need a way to update VFO info here..*/ + g_idle_add(vfo_update,NULL); + } else { // Read Mode + int curr_mode; + switch (vfo[active_receiver->id].mode) { + case modeLSB: curr_mode = 1; + break; + case modeUSB: curr_mode = 2; + break; + case modeCWL: curr_mode = 7; // CWL + break; + case modeCWU: curr_mode = 3; // CWU + break; + case modeFMN: curr_mode = 4; // FMN + break; + case modeAM: curr_mode = 5; // AM + break; + case modeDIGU: curr_mode = 9; // DIGU + break; + case modeDIGL: curr_mode = 6; // DIGL + break; + default: + #ifdef RIGCTL_DEBUG + fprintf(stderr, + "RIGCTL: MD command doesn't support %d\n", + vfo[active_receiver->id].mode); + #endif + break; + } + sprintf(msg,"MD%1d;",curr_mode); + send_resp(client_sock,msg); + } + } + else if(strcmp(cmd_str,"MF")==0) { // Set/read menu A/B + if(len <=2) { + send_resp(client_sock,"MF0;"); + } + } + else if(strcmp(cmd_str,"MG")==0) { // Mike Gain - 3 digit value + if(len <=2) { + work_int = (int) ((mic_gain +10.0)* 100.0/60.0); + sprintf(msg,"MG%03d;",work_int); + send_resp(client_sock,msg); + } else { + int tval = atoi(&cmd_input[2]); + new_vol = (double) (tval * 60/100) - 10; + //set_mic_gain(new_vol); + double *p_mic_gain=malloc(sizeof(double)); + *p_mic_gain=new_vol; + g_idle_add(update_mic_gain,(void *)p_mic_gain); + } + } + else if(strcmp(cmd_str,"ML")==0) { // Set/read the monitor function level + if(len <=2) { + send_resp(client_sock,"ML000;"); + } + } + else if(strcmp(cmd_str,"MO")==0) { // Set Monitor on/off + if(len <=2) { + send_resp(client_sock,"MO0;"); + } + } + /* Not supported */ + else if(strcmp(cmd_str,"MR")==0) { // Read Memory Channel data + sprintf(msg,"MR%1d%02d%02d%011lld%1d%1d%1d%02d%02d%03d%1d%1d%09d%02d%1d%08d;", + 0, // P1 - Rx Freq - 1 Tx Freq + 0, // P2 Bankd and channel number -- see MC comment + 0, // P3 - see MC comment + rigctl_getFrequency(), // P4 - frequency + rigctlGetMode(), // P5 - Mode + locked, // P6 - Locked status + 0, // P7 - O-off, 1-tone, 2-CTCSS, 3 =DCS + 0, // P8 - Tone Number - see page 35 + ctcss_tone, // P9 - CTCSS tone number - see CN command + 0, // P10 - DCS code - see QC command + 0, // P11 - Reverse status + 0, // P12 - Shift status - see OS command + 0, // P13 - Offset freq - see OS command + 0, // P14 - Step Size - see ST command + 0, // P15 - Memory Group Number (0-9) + 0); // P16 - Memory Name - 8 char max + //send_resp(client_sock,msg); + send_resp(client_sock,"?;"); + } + else if(strcmp(cmd_str,"MU")==0) { // Set/Read Memory Group Data + if(len <=2) { + send_resp(client_sock,"MU0000000000;"); + } + } + else if(strcmp(cmd_str,"MW")==0) { // Store Data to Memory Channel + } + else if(strcmp(cmd_str,"NB")==0) { // Set/Read Noise Blanker func status (on/off) + if(len <=2) { + sprintf(msg,"NB%1d;",active_receiver->snb); + send_resp(client_sock,msg); + } else { + if(cmd_input[2]=='0') { // Turn off ANF + active_receiver->snb=0; + } else { // Turn on ANF + active_receiver->snb=1; + } + // Update filters + SetRXASNBARun(active_receiver->id, active_receiver->snb); + g_idle_add(vfo_update,NULL); + } + } + else if(strcmp(cmd_str,"NL")==0) { // Set/Read Noise Reduction Level + if(len <=2) { + send_resp(client_sock,"NL000;"); + } + } + else if(strcmp(cmd_str,"NR")==0) { // Set/Read Noise Reduction function status + if(len <=2) { +/* + if(nr_none == 1) { + send_resp(client_sock,"NR0;"); + } else if ((nr_none == 0) && (nr==1)) { + send_resp(client_sock,"NR1;"); + } else if (nr2 == 1) { + send_resp(client_sock,"NR2;"); + } else { + send_resp(client_sock,"NR0;"); + } +*/ + + // FIX now allow multiple set + if (active_receiver->nr==1) { + send_resp(client_sock,"NR1;"); + } else { + send_resp(client_sock,"NR0;"); + } + } else { + if(cmd_input[2] == '0') { + active_receiver->nr = 0; + active_receiver->nr2 = 0; + } else if(cmd_input[2] == '1') { + active_receiver->nr = 1; + } else if(cmd_input[2] == '2') { + active_receiver->nr2 = 1; + } + SetRXAANRRun(active_receiver->id, active_receiver->nr); + SetRXAEMNRRun(active_receiver->id, active_receiver->nr2); + g_idle_add(vfo_update,NULL); + } + } + else if(strcmp(cmd_str,"NT")==0) { // Set/Read autonotch function + if(len <=2) { + sprintf(msg,"NT%1d;",active_receiver->anf); + send_resp(client_sock,msg); + } else { + if(cmd_input[2] == '0') { // Clear ANF + active_receiver->anf = 0; + } else { // Set ANF + active_receiver->anf = 1; + } + } + SetRXAANFRun(active_receiver->id, active_receiver->anf); + g_idle_add(vfo_update,NULL); + } + else if(strcmp(cmd_str,"OF")==0) { // Set/Read Offset freq (9 digits - hz) + if(len <=2) { + send_resp(client_sock,"OF000000000;"); + } + } + /* Not Supported */ + else if(strcmp(cmd_str,"OI")==0) { // Read Memory Channel Data + if(len <=2) { + sprintf(msg,"OI%011lld%04d%06d%1d%1d%1d%02d%1d%1d%1d%1d%1d%1d%02d%1d;", + rigctl_getFrequency(), + 0, // P2 - Freq Step size + 0, // P3 - Rit/Xit Freq + 0, // P4 - RIT off/Rit On + 0, // P5 - XIT off/on + 0, // P6 - Channel + 0, // P7 - Bank + 0, // P8 - 0RX, 1TX + rigctlGetMode(), // P10 - MD + 0, // P11 - SC command + 0, // P12 Split op - SP command + 0, // P13 Off, 1, 2, + 0,// P14 Tone freq - See TN command + 0,0); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"OS")==0) { // Set/Read Offset freq (9 digits - hz) + if(len <=2) { + //send_resp(client_sock,"OS0;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"PA")==0) { // Set/Read Preamp function status + if(len <=2) { + sprintf(msg,"PA0%1d;",enable_tx_equalizer); + send_resp(client_sock,msg); + } else { + if(cmd_input[2] =='0') { + enable_tx_equalizer=0; + SetTXAEQRun(transmitter->id, enable_tx_equalizer); + } else { + enable_tx_equalizer=1; + SetTXAEQRun(transmitter->id, enable_tx_equalizer); + } + } + } + else if(strcmp(cmd_str,"PB")==0) { // Set/Read DRU-3A Playback status + if(len <=2) { + send_resp(client_sock,"PB0;"); + } + } + else if(strcmp(cmd_str,"PC")==0) { // Set/Read Drive Power output + if(len<=2) { + sprintf(msg,"PC%03d;",(int) drive); + send_resp(client_sock,msg); + } else { + // Power Control - 3 digit number- 0 to 100 + //Scales to 0.00-1.00 + + double drive_val = + (double)(atoi(&cmd_input[2])); + // setDrive(drive_val); + double *p_drive=malloc(sizeof(double)); + *p_drive=drive_val; + g_idle_add(update_drive,(gpointer)p_drive); + //set_drive(drive_val); + } + } + else if(strcmp(cmd_str,"PI")==0) { // STore the programmable memory channel + } + else if(strcmp(cmd_str,"PK")==0) { // Reads the packet cluster data + // send_resp(client_sock,"PK000000000000000000000000000000000000000000000000;"); + send_resp(client_sock,"?;"); + + } + else if(strcmp(cmd_str,"PL")==0) { // Set/Read Speech processor level + // P1 000 - min-100 max + // P2 000 - min - 100 max + if(len <=2) { + // send_resp(client_sock,"PL000000;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"PM")==0) { // Recalls the Programmable memory + if(len <=2) { + //send_resp(client_sock,"PM0;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"PR")==0) { // Sets/reads the speech processor function on/off + // 0 - off, 1=on + if(len <=2) { + //send_resp(client_sock,"PR0;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"PS")==0) { // Sets/reads Power on/off state + // 0 - off, 1=on + if(len <=2) { + send_resp(client_sock,"PS1;"); // Lets pretend we're powered up ;-) + } + } + else if(strcmp(cmd_str,"QC")==0) { // Sets/reads DCS code + // Codes numbered from 000 to 103. + if(len <=2) { + //send_resp(client_sock,"QC000;"); // Lets pretend we're powered up ;-) + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"QI")==0) { // Store the settings in quick memory + } + else if(strcmp(cmd_str,"QR")==0) { // Send the Quick memory channel data + // P1 - Quick mem off, 1 quick mem on + // P2 - Quick mem channel number + if(len <=2) { + //send_resp(client_sock,"QR00;"); // Lets pretend we're powered up ;-) + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"RA")==0) { // Sets/reads Attenuator function status + // 00-off, 1-99 -on - Main and sub receivers reported + if(len <=2) { + //send_resp(client_sock,"RA0000;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"RC")==0) { // Clears the RIT offset freq + } + else if(strcmp(cmd_str,"RD")==0) { // Move the RIT offset freq down, slow down the scan speed in scan mode + if(len <=2) { + vfo[active_receiver->id].rit = vfo[active_receiver->id].rit-rit_increment; + sprintf(msg,"RD%1d;",rit_on()); + send_resp(client_sock,msg); + } else { + if(len > 3) { + // Non scan mode when RDxxxxx; - + vfo[active_receiver->id].rit = vfo[active_receiver->id].rit-rit_increment; + } + } + g_idle_add(vfo_update,NULL); + } + else if(strcmp(cmd_str,"RG")==0) { // RF Gain - 3 digit number + // RG123; 0-255 value + // Scale from -20 - 120 + if(len>4) { // Set Audio Gain + int base_value = atoi(&cmd_input[2]); + double new_gain = ((((double) base_value)/255) * 140) - 20; + //set_agc_gain(new_gain); + double *p_gain=malloc(sizeof(double)); + *p_gain=new_gain; + g_idle_add(update_agc_gain,(gpointer)p_gain); + } else { // Read Audio Gain + sprintf(msg,"RG%03d;",((256 * (int) active_receiver->agc_gain)/140)+36); + send_resp(client_sock,msg); + } + } + else if(strcmp(cmd_str,"RL")==0) { // Set/read Noise reduction level + if(len <=2) { + //send_resp(client_sock,"RL00;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"RM")==0) { // Set/read Meter function + // P1- 0, unsel, 1 SWR, 2 Comp, 3 ALC + // P2 - 4 dig - Meter value in dots - 000-0030 + if(len <=2) { + //send_resp(client_sock,"RM00000;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"RT")==0) { // Set/read the RIT function status + if(len <=2) { + sprintf(msg,"RT%01d;",rit_on()); + send_resp(client_sock,msg); + } else { + if(atoi(&cmd_input[2]) == 0) { + vfo[active_receiver->id].rit = 0; + } + } + } + else if(strcmp(cmd_str,"RU")==0) { // Set/move RIT frequency up + if(len <=2) { + vfo[active_receiver->id].rit = vfo[active_receiver->id].rit+rit_increment; + sprintf(msg,"RU%01d;",rit_on()); + send_resp(client_sock,msg); + } else { + if(len > 3) { + vfo[active_receiver->id].rit = vfo[active_receiver->id].rit+rit_increment; + } + } + g_idle_add(vfo_update,NULL); + } + else if(strcmp(cmd_str,"RX")==0) { // Unkey Xmitter + //setMox(0); + mox_state=0; + g_idle_add(mox_update,(gpointer)mox_state); + g_idle_add(vfo_update,NULL); + } + else if(strcmp(cmd_str,"SA")==0) { // Set/reads satellite mode status + // 0-main, 1=sub + if(len <=2) { + //send_resp(client_sock,"SA000000000000000;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"SB")==0) { // Set/read the SUB TF-W status + if(len <=2) { + //send_resp(client_sock,"SB0;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"SC")==0) { // Set/read the Scan function status + if(len <=2) { + //send_resp(client_sock,"SC0;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"SD")==0) { // Set/read CW break-in time delay + // 0000-1000 ms (in steps of 50 ms) 0000 is full break in + int local_cw_breakin=cw_keyer_hang_time; + // Limit report value to 1000 for TS-2000 + if(local_cw_breakin > 1000) { local_cw_breakin = 1000; } + if(len <=2) { + sprintf(msg,"SD%04d;",local_cw_breakin); + send_resp(client_sock,msg); + } else { + local_cw_breakin = atoi(&cmd_input[2]); + if(cw_keyer_hang_time <= 1000) { + if(local_cw_breakin==0) { + cw_breakin = 1; + } else { + cw_breakin = 0; + } + cw_keyer_hang_time = local_cw_breakin; + } + } + } + else if(strcmp(cmd_str,"SH")==0) { // Set/read the DSP filter settings + if(len <=2) { + // send_resp(client_sock,"SH00;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"SI")==0) { // Enters the satellite memory name + } + else if(strcmp(cmd_str,"SL")==0) { // Set/read the DSP filter settings - this appears twice? See SH + if(len <=2) { + //send_resp(client_sock,"SL00;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"SM")==0) { // Read SMETER + // SMx; x=0 RX1, x=1 RX2 + // meter is in dbm - value will be 0<260 + // Translate to 00-30 for main, 0-15 fo sub + // Resp= SMxAABB; + // Received range from the SMeter can be -127 for S0, S9 is -73, and S9+60=-13.; + // PowerSDR returns S9=0015 code. + // Let's make S9 half scale or a value of 70. + double level=0.0; + + if(cmd_input[2] == '0') { + level = GetRXAMeter(receiver[0]->id, smeter); + } else if(cmd_input[2] == '1') { + if(receivers==2) { + level = GetRXAMeter(receiver[1]->id, smeter); + } + } + + + level = GetRXAMeter(active_receiver->id, smeter); + // Determine how high above 127 we are..making a range of 114 from S0 to S9+60db + // 5 is a fugdge factor that shouldn't be there - but seems to get us to S9=SM015 + level = abs(127+(level + (double) get_attenuation()))+5; + + // Clip the value just in case + if(cmd_input[2] == '0') { + new_level = (int) ((level * 30.0)/114.0); + // Do saturation check + if(new_level < 0) { new_level = 0; } + if(new_level > 30) { new_level = 30;} + } else { //Assume we are using sub receiver where range is 0-15 + new_level = (int) ((level * 15.0)/114.0); + // Do saturation check + if(new_level < 0) { new_level = 0; } + if(new_level > 15) { new_level = 15;} + } + sprintf(msg,"SM%1c%04d;", + cmd_input[2],new_level); + send_resp(client_sock,msg); + } + else if(strcmp(cmd_str,"SQ")==0) { // Set/read the squelch level + // P1 - 0- main, 1=sub + // P2 - 0-255 + if(len <=3) { + sprintf(msg,"SQ%04d;",squelch); + send_resp(client_sock,msg); + } else { + squelch = atoi(&cmd_input[2]); + } + } + else if(strcmp(cmd_str,"SR")==0) { // Resets the transceiver + } + else if(strcmp(cmd_str,"SS")==0) { // Set/read Scan pause freq + if(len <=2) { + //send_resp(client_sock,"SS0;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"ST")==0) { // Set/read the multi/ch control freq steps + // SSB/CW/FSK - values 00-03 + // 00: 1KHz, 01: 2.5Khz 02:5KHz 03: 10Khz + // AM/FM mode 00-09 + // 00: 5KHz, + // 01: 6.25KHz, + // 02:10Khz, + // 03: 12.5Khz, + // 04: 15Khz, + // 05: 20Khz, + // 06: 25KHz + // 07: 30Khz + // 08: 50Khz + // 09: 100Khz + int coded_step_val; + entry= (BANDSTACK_ENTRY *) + bandstack_entry_get_current(); + if(len <=2) { + switch(entry->mode) { + case modeLSB: + case modeUSB: + case modeCWL: + case modeCWU: + case modeDIGU: + case modeDIGL: + if(step >0 && step <= 1000) { + coded_step_val = 0; + } else if (step >1000 && step <=2500) { + coded_step_val = 1; + } else if (step >2500 && step <=5000) { + coded_step_val = 2; + } else { + coded_step_val = 3; + } + break; + case modeFMN: + case modeAM: + if(step >0 && step <= 5000) { + coded_step_val = 0; + } else if (step >5000 && step <=6250) { + coded_step_val = 1; + } else if (step >6250 && step <=10000) { + coded_step_val = 2; + } else if (step >10000 && step <=12500) { + coded_step_val = 3; + } else if (step >12500 && step <=15000) { + coded_step_val = 4; + } else if (step >15000 && step <=20000) { + coded_step_val = 5; + } else if (step >20000 && step <=25000) { + coded_step_val = 6; + } else if (step >25000 && step <=30000) { + coded_step_val = 7; + } else if (step >30000 && step <=50000) { + coded_step_val = 8; + } else if (step >50000 && step <=100000) { + coded_step_val = 9; + } else { + coded_step_val = 0; + } + break; + } + sprintf(msg,"ST%02d;",coded_step_val); + send_resp(client_sock,msg); + } else { + coded_step_val = atoi(&cmd_input[2]); + switch(entry->mode) { + case modeLSB: + case modeUSB: + case modeCWL: + case modeCWU: + case modeDIGU: + case modeDIGL: + if(coded_step_val==0) { step = 1000;} + if(coded_step_val==1) { step = 2500;} + if(coded_step_val==2) { step = 5000;} + if(coded_step_val==3) { step = 10000;} + break; + case modeFMN: + case modeAM: + switch(coded_step_val) { + case 0: step = 5000; break; + case 1: step = 6250; break; + case 2: step = 10000; break; + case 3: step = 12500; break; + case 4: step = 15000; break; + case 5: step = 20000; break; + case 6: step = 25000; break; + case 7: step = 30000; break; + case 8: step = 50000; break; + case 9: step = 100000; break; + default: break; // No change if not a valid number + } + default: break; // No change if not a valid number + } + g_idle_add(vfo_update,NULL); + } + } + else if(strcmp(cmd_str,"SU")==0) { // Set/read the scan pause freq + if(len <=2) { + //send_resp(client_sock,"SU00000000000;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"SV")==0) { // Execute the memory transfer function + } + else if(strcmp(cmd_str,"TC")==0) { // Set/read the internal TNC mode + if(len <=2) { + //send_resp(client_sock,"TC00;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"TD")==0) { // Sends the DTMF memory channel + } + else if(strcmp(cmd_str,"TI")==0) { // Reads the TNC LED status + if(len <=2) { + //send_resp(client_sock,"TI00;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"TN")==0) { // Set/Read sub tone freq + if(len <=2) { + //send_resp(client_sock,"TN00;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"TO")==0) { // Set/Read tone function + if(len <=2) { + //send_resp(client_sock,"TO0;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"TS")==0) { // Set/Read TF Set function status + if(len <=2) { + //send_resp(client_sock,"TS0;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"TX")==0) { // Key Xmitter - P1 - transmit on main/sub freq + + /*if(len >=3) { + // K5JAE: The TS-2000 real hardware does not respond + // to this command, thus hamlib is not expecting response. + //send_resp(client_sock,"TX0;"); + }*/ + mox_state=1; + g_idle_add(mox_update,(gpointer)mox_state); + g_idle_add(vfo_update,NULL); + } + else if(strcmp(cmd_str,"TY")==0) { // Set/Read uP firmware type + if(len <=2) { + send_resp(client_sock,"TY000;"); + } + } + else if(strcmp(cmd_str,"UL")==0) { // Detects the PLL unlock status - this should never occur - xmit only + if(len <=2) { + //send_resp(client_sock,"UL0;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"UP")==0) { // Emulates the mic up key + } + else if(strcmp(cmd_str,"VD")==0) { // Sets/Reads VOX dleay time - 0000-3000ms in steps of 150 + // We want vox_hang variable in PiHPSDR + // Max value in variable in ms... so 250 = 250ms + if(len <=2) { + work_int = (int) vox_hang; + sprintf(msg,"VD%04d;",work_int); + send_resp(client_sock,msg); + } else { + work_int = atoi(&cmd_input[2]); + // Bounds check for legal values for PiHPSDR + if(work_int > 1000) { work_int = 1000; } + if(work_int < 0) { work_int = 0; } + vox_hang = (double) work_int; + #ifdef RIGCTL_DEBUG + fprintf(stderr,"RIGCTL: Vox hang=%0.20f\n",vox_hang); + #endif + } + } + else if(strcmp(cmd_str,"VG")==0) { // Sets/Reads VOX gain 000-009 + // We want vox_threshold variable in PiHPSDR + // Max value in variable 0.1 + // 3 char 000-009 valid ranges + if(len <=2) { + work_int = (int) ((vox_threshold) * 100.0); + sprintf(msg,"VG00%1d;",work_int); + send_resp(client_sock,msg); + } else { + // Set the threshold here + work_int = atoi(&cmd_input[2]); + vox_threshold = ((double) work_int)/100.0; + #ifdef RIGCTL_DEBUG + fprintf(stderr,"RIGCTL: Vox thresh=%0.20f\n",vox_threshold); + #endif + } + } + else if(strcmp(cmd_str,"VR")==0) { // Emulates the voice 1/2 key + } + else if(strcmp(cmd_str,"VX")==0) { // Sets/reads vox f(x) state + if(len <=2) { + sprintf(msg,"VX%1d;",vox_enabled); + send_resp(client_sock,msg); + } else { + work_int = atoi(&cmd_input[2]); + if(work_int>1) { vox_enabled = 1; vox= 1;} + if(work_int<1) { vox_enabled = 0; vox=0; } + } + } + else if(strcmp(cmd_str,"XT")==0) { // Sets/reads the XIT f(x) state + if(len <=2) { + //send_resp(client_sock,"XT0;"); + send_resp(client_sock,"?;"); + } + } + else if(strcmp(cmd_str,"XX")==0) { // + // Format RL01234: First dig 0=neg, 1=pos number + // 1-4- digital offset in hertz. + if(len > 4) { // It is set instead of a read + digl_pol = (cmd_input[2]=='0') ? -1 : 1; + digl_offset = atoi(&cmd_input[3]); + #ifdef RIGCTL_DEBUG + fprintf(stderr,"RIGCTL:RL set %d %d\n",digl_pol,digl_offset); + #endif + } else { + if(digl_pol==1) { // Nah - its a read + sprintf(msg,"RL1%04d;",0); + } else { + sprintf(msg,"RL0%04d;",0); + } + send_resp(client_sock,msg); + #ifdef RIGCTL_DEBUG + fprintf(stderr,":%s\n",msg); + #endif + } + } + else if(strcmp(cmd_str,"XY")==0) { // set/read RTTY DIGL offset frequency - Not available - just store values + // Format RL01234: First dig 0=neg, 1=pos number + // 1-4- digital offset in hertz. + if(len > 4) { // It is set instead of a read + digl_pol = (cmd_input[2]=='0') ? -1 : 1; + digl_offset = atoi(&cmd_input[3]); + #ifdef RIGCTL_DEBUG + fprintf(stderr,"RIGCTL:RL set %d %d\n",digl_pol,digl_offset); + #endif + } else { + if(digl_pol==1) { // Nah - its a read + sprintf(msg,"RL1%04d;",0); + } else { + sprintf(msg,"RL0%04d;",0); + } + send_resp(client_sock,msg); + #ifdef RIGCTL_DEBUG + fprintf(stderr,":%s\n",msg); + #endif + } + } + else { + fprintf(stderr,"RIGCTL: UNKNOWN=%s\n",cmd_str); + } +} +// +// End of Parser +// + + +// +// 2-25-17 - K5JAE - create each thread with the pointer to the port number +// (Port numbers now const ints instead of defines..) +// +void launch_rigctl () { + int err; + fprintf(stderr, "LAUNCHING RIGCTL!!\n"); + + mutex_a = g_new(GT_MUTEX,1); + g_mutex_init(&mutex_a->m); + + mutex_b = g_new(GT_MUTEX,1); + g_mutex_init(&mutex_b->m); + + // This routine encapsulates the pthread call +/* + err = pthread_create (&rigctl_a_thread_id,NULL,rigctl_a,NULL); + if(err != 0) { + fprintf(stderr, "pthread_create failed on rigctl_a launch\n"); + } +*/ + + rigctl_a_thread_id = g_thread_new( "rigctl a", rigctl, (gpointer)&TelnetPortA); + if( ! rigctl_a_thread_id ) + { + fprintf(stderr,"g_thread_new failed on rigctl_a\n"); + } + + +/* + err = pthread_create (&rigctl_b_thread_id,NULL,rigctl_b,NULL); + if(err != 0) { + fprintf(stderr, "pthread_create failed on rigctl_b launch\n"); + } +*/ + + rigctl_b_thread_id = g_thread_new( "rigctl b", rigctl, (gpointer)&TelnetPortB); + if( ! rigctl_b_thread_id ) + { + fprintf(stderr,"g_thread_new failed on rigctl_b\n"); + } + +/* + err = pthread_create (&rigctl_c_thread_id,NULL,rigctl_c,NULL); + if(err != 0) { + fprintf(stderr, "pthread_create failed on rigctl_c launch\n"); + } +*/ + + rigctl_c_thread_id = g_thread_new( "rigctl c", rigctl, (gpointer)&TelnetPortC); + if( ! rigctl_c_thread_id ) + { + fprintf(stderr,"g_thread_new failed on rigctl_c\n"); + } + +} + + +// Telnet Server launch code below +// max number of bytes we can get at once +#define MAXDATASIZE 300 + +// +// 2-25-17 - K5JAE - removed duplicate init servers. +// + + +int init_server ( int * socket_desc_ptr, struct sockaddr_in * client, struct sockaddr_in * server, int telnet_port) { + int client_sock; + int c; + //Create socket + *socket_desc_ptr = socket(AF_INET , SOCK_STREAM , 0); + + if (*socket_desc_ptr == -1) + { + fprintf(stderr,"RIGCTL: Could not create socket"); + } + fprintf(stderr, "RIGCTL: Socket created\n"); + + //Prepare the sockaddr_in structure + server->sin_family = AF_INET; + server->sin_addr.s_addr = INADDR_ANY; + server->sin_port = htons( telnet_port ); + + //Bind + if( bind(*socket_desc_ptr,(struct sockaddr *) server , sizeof(struct sockaddr_in)) < 0) + { + //print the error message + fprintf(stderr,"RIGCTL: bind failed. Error\n"); + return 1; + } + fprintf(stderr,"RIGCTL: Bind done on port %d\n",telnet_port); + + //Listen + listen(*socket_desc_ptr, 3); + + //Accept and incoming connection + fprintf(stderr,"RIGCTL: Waiting for incoming connections...\n"); + c = sizeof(struct sockaddr_in); + + //accept connection from an incoming client + client_sock = accept(*socket_desc_ptr,(struct sockaddr *)client, (socklen_t*)&c); + if (client_sock < 0) + { + fprintf(stderr,"RIGCTL: Accept failed\n"); + } + fprintf(stderr,"RIGCTL: Connection accepted\n"); + + return client_sock; +} + +int rigctlGetMode() { + switch(vfo[active_receiver->id].mode) { + case modeLSB: return(1); // LSB + case modeUSB: return(2); // USB + case modeCWL: return(7); // CWL + case modeCWU: return(3); // CWU + case modeFMN: return(4); // FMN + case modeAM: return(5); // AM + case modeDIGU: return(9); // DIGU + case modeDIGL: return(6); // DIGL + default: return(0); + } +} + +int rigctlSetFilterLow(int val){ +}; +int rigctlSetFilterHigh(int val){ +}; + +void set_band(long long new_freqA, int ctl) { + + fprintf(stderr,"set_band: f=%11lld ctl=%d\n",new_freqA,ctl ); + BANDSTACK_ENTRY *entry; + BAND *band; + FILTER* band_filters; + FILTER* band_filter; + + int b = get_band_from_frequency(new_freqA); + + if(b == -1) { // Out of ham bands... + fprintf(stderr,"set_band: out of ham bands\n"); + setFrequency(new_freqA); + g_idle_add(vfo_update,NULL); + return; + } + + band=band_set_current(b); + + entry=bandstack_entry_next(); + entry->mode = vfo[VFO_A].mode; + set_mode(active_receiver,entry->mode); // From current band setting + + + band_filters=filters[entry->mode]; + band_filter=&band_filters[entry->filter]; + + set_filter(active_receiver,band_filter->low,band_filter->high); + setFrequency(new_freqA); + + // BAND *band=band_get_current_band(); + band=band_set_current(b); + if(active_receiver->id==0) { + set_alex_rx_antenna(band->alexRxAntenna); + set_alex_tx_antenna(band->alexTxAntenna); + set_alex_attenuation(band->alexAttenuation); + } + + //setFrequency(new_freqA); + g_idle_add(vfo_update,NULL); + + calcDriveLevel(); + calcTuneDriveLevel(); +} + +void set_freqB(long long new_freqB) { + + //BANDSTACK_ENTRY *bandstack = bandstack_entry_get_current(); + //bandstack->frequencyB = new_freqB; + //frequencyB = new_freqB; + vfo[VFO_B].frequency = new_freqB; + g_idle_add(vfo_update,NULL); +} diff --git a/rigctl.h b/rigctl.h index 2d3ec1a..51e59ed 100644 --- a/rigctl.h +++ b/rigctl.h @@ -2,9 +2,10 @@ #define RIGCTL_H void launch_rigctl (); -void parse_cmd(char *,int); int rigctlGetMode(); char * rigctlGetFilter(); -void set_band(long long); +void set_freqB(long long); +void set_band(long long, int); +extern int cat_control; #endif // RIGCTL_H diff --git a/rit.c b/rit.c index da598f9..e9091b6 100644 --- a/rit.c +++ b/rit.c @@ -57,23 +57,22 @@ static gboolean ctun_pressed_event_cb (GtkWidget *widget, GdkEventButton *event, set_button_text_color(ctun_b,"red"); } else { set_button_text_color(ctun_b,"black"); - if(ddsOffset!=0) { - ddsOffset=0; - wdsp_set_offset(ddsOffset); - vfo_update(NULL); - } + vfo[active_receiver->id].offset=0; + set_offset(active_receiver,0); + vfo_update(NULL); } return TRUE; } static gboolean rit_timer_cb(gpointer data) { + int v=active_receiver->id; if((GtkWidget*)data==rit_plus_b) { - rit+=rit_increment; + vfo[v].rit+=rit_increment; } else { - rit-=rit_increment; + vfo[v].rit-=rit_increment; } - if(rit>1000) rit=1000; - if(rit<-1000) rit=-1000; + if(vfo[v].rit>1000) vfo[v].rit=1000; + if(vfo[v].rit<-1000) vfo[v].rit=-1000; vfo_update(NULL); return TRUE; } @@ -82,7 +81,7 @@ static gboolean rit_pressed_event_cb (GtkWidget *widget, GdkEventButton *event, if(rit_enabled) { rit_enabled=FALSE; set_button_text_color(rit_b,"black"); - rit=0; + vfo[active_receiver->id].offset=0; gtk_widget_set_sensitive(rit_plus_b,FALSE); gtk_widget_set_sensitive(rit_minus_b,FALSE); } else { @@ -95,13 +94,14 @@ static gboolean rit_pressed_event_cb (GtkWidget *widget, GdkEventButton *event, } static gboolean rit_step_pressed_event_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { + int v=active_receiver->id; if(widget==rit_plus_b) { - rit+=rit_increment; + vfo[v].rit+=rit_increment; } else { - rit-=rit_increment; + vfo[v].rit-=rit_increment; } - if(rit>1000) rit=1000; - if(rit<-1000) rit=-1000; + if(vfo[v].rit>1000) vfo[v].rit=1000; + if(vfo[v].rit<-1000) vfo[v].rit=-1000; vfo_update(NULL); rit_timer=g_timeout_add(200,rit_timer_cb,widget); return TRUE; diff --git a/rx_menu.c b/rx_menu.c new file mode 100644 index 0000000..3d1318d --- /dev/null +++ b/rx_menu.c @@ -0,0 +1,333 @@ +/* Copyright (C) +* 2015 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#include +#include +#include +#include + +#include "audio.h" +#include "new_menu.h" +#include "rx_menu.h" +#include "band.h" +#include "discovered.h" +#include "filter.h" +#include "radio.h" +#include "receiver.h" + +static GtkWidget *parent_window=NULL; + +static GtkWidget *menu_b=NULL; + +static GtkWidget *dialog=NULL; + +static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { + if(dialog!=NULL) { + gtk_widget_destroy(dialog); + dialog=NULL; + sub_menu=NULL; + } + return TRUE; +} + +static void dither_cb(GtkWidget *widget, gpointer data) { + active_receiver->dither=active_receiver->dither==1?0:1; +} + +static void random_cb(GtkWidget *widget, gpointer data) { + active_receiver->random=active_receiver->random==1?0:1; +} + +static void preamp_cb(GtkWidget *widget, gpointer data) { + active_receiver->preamp=active_receiver->preamp==1?0:1; +} + +static void sample_rate_cb(GtkWidget *widget, gpointer data) { + receiver_change_sample_rate(active_receiver,(int)data); +} + +static void adc_cb(GtkWidget *widget, gpointer data) { + receiver_change_adc(active_receiver,(int)data); +} + +static void local_audio_cb(GtkWidget *widget, gpointer data) { + if(gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) { + if(audio_open_output(active_receiver)==0) { + active_receiver->local_audio=1; + } else { + active_receiver->local_audio=0; + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE); + } + } else { + if(active_receiver->local_audio) { + active_receiver->local_audio=0; + audio_close_output(active_receiver); + } + } +} + +static void local_output_changed_cb(GtkWidget *widget, gpointer data) { + active_receiver->audio_device=(int)(long)data; + if(active_receiver->local_audio) { + audio_close_output(active_receiver); + if(audio_open_output(active_receiver)==0) { + active_receiver->local_audio=1; + } + } +} + +static void audio_channel_cb(GtkWidget *widget, gpointer data) { + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { + active_receiver->audio_channel=(int)data; + } +} + +void rx_menu(GtkWidget *parent) { + char label[32]; + GtkWidget *adc_b; + int i; + parent_window=parent; + + dialog=gtk_dialog_new(); + gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window)); + gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE); + + GdkRGBA color; + color.red = 1.0; + color.green = 1.0; + color.blue = 1.0; + color.alpha = 1.0; + gtk_widget_override_background_color(dialog,GTK_STATE_FLAG_NORMAL,&color); + + GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + + GtkWidget *grid=gtk_grid_new(); + gtk_grid_set_column_spacing (GTK_GRID(grid),10); + //gtk_grid_set_row_spacing (GTK_GRID(grid),10); + //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE); + //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE); + + GtkWidget *close_b=gtk_button_new_with_label("Close RX"); + g_signal_connect (close_b, "button_press_event", G_CALLBACK(close_cb), NULL); + gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1); + + sprintf(label,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B"); + GtkWidget *rx_label=gtk_label_new(label); + gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1); + + int x=0; + + switch(protocol) { + case NEW_PROTOCOL: + { + GtkWidget *sample_rate_label=gtk_label_new("Sample Rate"); + gtk_grid_attach(GTK_GRID(grid),sample_rate_label,x,1,1,1); + + GtkWidget *sample_rate_48=gtk_radio_button_new_with_label(NULL,"48000"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_48), active_receiver->sample_rate==48000); + gtk_grid_attach(GTK_GRID(grid),sample_rate_48,x,2,1,1); + g_signal_connect(sample_rate_48,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)48000); + + GtkWidget *sample_rate_96=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_48),"96000"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_96), active_receiver->sample_rate==96000); + gtk_grid_attach(GTK_GRID(grid),sample_rate_96,x,3,1,1); + g_signal_connect(sample_rate_96,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)96000); + + GtkWidget *sample_rate_192=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_96),"192000"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_192), active_receiver->sample_rate==192000); + gtk_grid_attach(GTK_GRID(grid),sample_rate_192,x,4,1,1); + g_signal_connect(sample_rate_192,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)192000); + + GtkWidget *sample_rate_384=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_192),"384000"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_384), active_receiver->sample_rate==384000); + gtk_grid_attach(GTK_GRID(grid),sample_rate_384,x,5,1,1); + g_signal_connect(sample_rate_384,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)384000); + +#ifndef GPIO + GtkWidget *sample_rate_768=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_384),"768000"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_768), active_receiver->sample_rate==768000); + gtk_grid_attach(GTK_GRID(grid),sample_rate_768,x,6,1,1); + g_signal_connect(sample_rate_768,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)768000); + + GtkWidget *sample_rate_1536=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_768),"1536000"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_1536), active_receiver->sample_rate==1536000); + gtk_grid_attach(GTK_GRID(grid),sample_rate_1536,x,7,1,1); + g_signal_connect(sample_rate_1536,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)1536000); +#endif + } + x++; + break; + +#ifdef LIMESDR + case LIMESDR_PROTOCOL: + { + GtkWidget *sample_rate_label=gtk_label_new("Sample Rate"); + gtk_grid_attach(GTK_GRID(grid),sample_rate_label,x,1,1,1); + + GtkWidget *sample_rate_1M=gtk_radio_button_new_with_label(NULL,"1000000"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_1M), active_receiver->sample_rate==1000000); + gtk_grid_attach(GTK_GRID(grid),sample_rate_1M,x,2,1,1); + g_signal_connect(sample_rate_1M,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)1000000); + + GtkWidget *sample_rate_2M=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate_1M),"2000000"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_2M), active_receiver->sample_rate==2000000); + gtk_grid_attach(GTK_GRID(grid),sample_rate_2M,x,3,1,1); + g_signal_connect(sample_rate_2M,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)2000000); + } + x++; + break; +#endif + } + + switch(protocol) { + case ORIGINAL_PROTOCOL: + case NEW_PROTOCOL: + { + GtkWidget *dither_b=gtk_check_button_new_with_label("Dither"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dither_b), active_receiver->dither); + gtk_grid_attach(GTK_GRID(grid),dither_b,x,2,1,1); + g_signal_connect(dither_b,"toggled",G_CALLBACK(dither_cb),NULL); + + GtkWidget *random_b=gtk_check_button_new_with_label("Random"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (random_b), active_receiver->random); + 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); + } + } + x++; + break; + default: + break; + } + + int n_adc=1; + switch(protocol) { + case ORIGINAL_PROTOCOL: + switch(device) { + case DEVICE_METIS: + n_adc=1; // FIX for multiple Mercury cards + break; + case DEVICE_HERMES: + case DEVICE_HERMES_LITE: + n_adc=1; + break; + default: + n_adc=2; + break; + } + break; + case NEW_PROTOCOL: + switch(device) { + case NEW_DEVICE_ATLAS: + n_adc=1; // FIX for multiple Mercury cards + break; + case NEW_DEVICE_HERMES: + case NEW_DEVICE_HERMES2: + case NEW_DEVICE_HERMES_LITE: + n_adc=1; + break; + default: + n_adc=2; + break; + } + break; + default: + break; + } + + if(n_adc>1) { + for(i=0;iadc==i); + gtk_grid_attach(GTK_GRID(grid),adc_b,x,2+i,1,1); + g_signal_connect(adc_b,"pressed",G_CALLBACK(adc_cb),(gpointer *)i); + } + x++; + } + + + int row=0; + if(n_output_devices>0) { + GtkWidget *local_audio_b=gtk_check_button_new_with_label("Local Audio Output"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (local_audio_b), active_receiver->local_audio); + gtk_widget_show(local_audio_b); + gtk_grid_attach(GTK_GRID(grid),local_audio_b,x,++row,1,1); + g_signal_connect(local_audio_b,"toggled",G_CALLBACK(local_audio_cb),NULL); + + if(active_receiver->audio_device==-1) active_receiver->audio_device=0; + + for(i=0;iaudio_device==i); + gtk_widget_show(output); + gtk_grid_attach(GTK_GRID(grid),output,x,++row,1,1); + g_signal_connect(output,"pressed",G_CALLBACK(local_output_changed_cb),(gpointer *)i); + } + + row=0; + x++; + + GtkWidget *stereo_b=gtk_radio_button_new_with_label(NULL,"Stereo"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (stereo_b), active_receiver->audio_channel==STEREO); + gtk_widget_show(stereo_b); + gtk_grid_attach(GTK_GRID(grid),stereo_b,x,++row,1,1); + g_signal_connect(stereo_b,"toggled",G_CALLBACK(audio_channel_cb),(gpointer)STEREO); + + GtkWidget *left_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(stereo_b),"Left"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (left_b), active_receiver->audio_channel==LEFT); + gtk_widget_show(left_b); + gtk_grid_attach(GTK_GRID(grid),left_b,x,++row,1,1); + g_signal_connect(left_b,"toggled",G_CALLBACK(audio_channel_cb),(gpointer)LEFT); + + GtkWidget *right_b=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(left_b),"Right"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (right_b), active_receiver->audio_channel==RIGHT); + gtk_widget_show(right_b); + gtk_grid_attach(GTK_GRID(grid),right_b,x,++row,1,1); + g_signal_connect(right_b,"toggled",G_CALLBACK(audio_channel_cb),(gpointer)RIGHT); + } + + gtk_container_add(GTK_CONTAINER(content),grid); + + sub_menu=dialog; + + gtk_widget_show_all(dialog); + +} + diff --git a/rx_menu.h b/rx_menu.h new file mode 100644 index 0000000..5206614 --- /dev/null +++ b/rx_menu.h @@ -0,0 +1,20 @@ +/* Copyright (C) +* 2015 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +extern void rx_menu(GtkWidget *parent); diff --git a/rx_panadapter.c b/rx_panadapter.c new file mode 100644 index 0000000..45f956d --- /dev/null +++ b/rx_panadapter.c @@ -0,0 +1,410 @@ +/* Copyright (C) +* 2015 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "agc.h" +#include "band.h" +#include "channel.h" +#include "discovered.h" +#include "radio.h" +#include "receiver.h" +#include "transmitter.h" +#include "rx_panadapter.h" +#include "vfo.h" +#include "mode.h" +#ifdef FREEDV +#include "freedv.h" +#endif +#include "gpio.h" + +//static float panadapter_max=-60.0; +//static float panadapter_min=-160.0; + +static gfloat filter_left; +static gfloat filter_right; + +/* Create a new surface of the appropriate size to store our scribbles */ +static gboolean +panadapter_configure_event_cb (GtkWidget *widget, + GdkEventConfigure *event, + gpointer data) +{ + + RECEIVER *rx=(RECEIVER *)data; + + int display_width=gtk_widget_get_allocated_width (widget); + int display_height=gtk_widget_get_allocated_height (widget); + + if (rx->panadapter_surface) + cairo_surface_destroy (rx->panadapter_surface); + + rx->panadapter_surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget), + CAIRO_CONTENT_COLOR, + display_width, + display_height); + + cairo_t *cr=cairo_create(rx->panadapter_surface); + cairo_set_source_rgb(cr, 0, 0, 0); + cairo_paint(cr); + cairo_destroy(cr); + return TRUE; +} + +/* Redraw the screen from the surface. Note that the ::draw + * signal receives a ready-to-be-used cairo_t that is already + * clipped to only draw the exposed areas of the widget + */ +static gboolean +panadapter_draw_cb (GtkWidget *widget, + cairo_t *cr, + gpointer data) +{ + RECEIVER *rx=(RECEIVER *)data; + if(rx->panadapter_surface) { + cairo_set_source_surface (cr, rx->panadapter_surface, 0, 0); + cairo_paint (cr); + } + + return TRUE; +} + +static gboolean panadapter_button_press_event_cb(GtkWidget *widget, GdkEventButton *event, gpointer data) { + return receiver_button_press_event(widget,event,data); +} + +static gboolean panadapter_button_release_event_cb(GtkWidget *widget, GdkEventButton *event, gpointer data) { + return receiver_button_release_event(widget,event,data); +} + +static gboolean panadapter_motion_notify_event_cb(GtkWidget *widget, GdkEventMotion *event, gpointer data) { + return receiver_motion_notify_event(widget,event,data); +} + +static gboolean panadapter_scroll_event_cb(GtkWidget *widget, GdkEventScroll *event, gpointer data) { + return receiver_scroll_event(widget,event,data); +} + +void rx_panadapter_update(RECEIVER *rx) { + int i; + int result; + float *samples; + float saved_max; + float saved_min; + cairo_text_extents_t extents; + + gboolean active=active_receiver==rx; + + int display_width=gtk_widget_get_allocated_width (rx->panadapter); + int display_height=gtk_widget_get_allocated_height (rx->panadapter); + + samples=rx->pixel_samples; + + //clear_panadater_surface(); + cairo_t *cr; + cr = cairo_create (rx->panadapter_surface); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_rectangle(cr,0,0,display_width,display_height); + cairo_fill(cr); + //cairo_paint (cr); + + // filter + cairo_set_source_rgb (cr, 0.25, 0.25, 0.25); + filter_left=(double)display_width/2.0+(((double)rx->filter_low+vfo[rx->id].offset)/rx->hz_per_pixel); + filter_right=(double)display_width/2.0+(((double)rx->filter_high+vfo[rx->id].offset)/rx->hz_per_pixel); + cairo_rectangle(cr, filter_left, 0.0, filter_right-filter_left, (double)display_height); + cairo_fill(cr); + + // plot the levels + if(active) { + cairo_set_source_rgb (cr, 0, 1, 1); + } else { + cairo_set_source_rgb (cr, 0, 0.5, 0.5); + } + + double dbm_per_line=(double)display_height/((double)rx->panadapter_high-(double)rx->panadapter_low); + cairo_set_line_width(cr, 1.0); + cairo_select_font_face(cr, "FreeMono", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); + cairo_set_font_size(cr, 12); + char v[32]; + + for(i=rx->panadapter_high;i>=rx->panadapter_low;i--) { + int mod=abs(i)%20; + if(mod==0) { + double y = (double)(rx->panadapter_high-i)*dbm_per_line; + cairo_move_to(cr,0.0,y); + cairo_line_to(cr,(double)display_width,y); + + sprintf(v,"%d dBm",i); + cairo_move_to(cr, 1, y); + cairo_show_text(cr, v); + } + } + cairo_stroke(cr); + + // plot frequency markers + long long f; + long divisor=20000; + long half=(long)rx->sample_rate/2L; + long long frequency=vfo[rx->id].frequency; + switch(rx->sample_rate) { + case 48000: + divisor=5000L; + break; + case 96000: + case 100000: + divisor=10000L; + break; + case 192000: + divisor=20000L; + break; + case 384000: + divisor=25000L; + break; + case 768000: + divisor=50000L; + break; + case 1048576: + case 1536000: + case 2097152: + divisor=100000L; + break; + } + for(i=0;ihz_per_pixel * i); + if (f > 0) { + if ((f % divisor) < (long) rx->hz_per_pixel) { + cairo_set_line_width(cr, 1.0); + //cairo_move_to(cr,(double)i,0.0); + cairo_move_to(cr,(double)i,10.0); + cairo_line_to(cr,(double)i,(double)display_height); + + cairo_select_font_face(cr, "FreeMono", + CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_BOLD); + cairo_set_font_size(cr, 12); + char v[32]; + sprintf(v,"%0lld.%03lld",f/1000000,(f%1000000)/1000); + //cairo_move_to(cr, (double)i, (double)(display_height-10)); + cairo_text_extents(cr, v, &extents); + cairo_move_to(cr, (double)i-(extents.width/2.0), 10.0); + cairo_show_text(cr, v); + } + } + } + cairo_stroke(cr); + + // band edges + long long min_display=frequency-half; + long long max_display=frequency+half; + BAND *band=band_get_band(vfo[rx->id].band); + if(band->frequencyMin!=0LL) { + cairo_set_source_rgb (cr, 1, 0, 0); + cairo_set_line_width(cr, 2.0); + if((min_displayfrequencyMin)&&(max_display>band->frequencyMin)) { + i=(band->frequencyMin-min_display)/(long long)rx->hz_per_pixel; + cairo_move_to(cr,(double)i,0.0); + cairo_line_to(cr,(double)i,(double)display_height); + cairo_stroke(cr); + } + if((min_displayfrequencyMax)&&(max_display>band->frequencyMax)) { + i=(band->frequencyMax-min_display)/(long long)rx->hz_per_pixel; + cairo_move_to(cr,(double)i,0.0); + cairo_line_to(cr,(double)i,(double)display_height); + cairo_stroke(cr); + } + } + + // agc + if(rx->agc!=AGC_OFF) { + double hang=0.0; + double thresh=0; + + GetRXAAGCHangLevel(rx->id, &hang); + GetRXAAGCThresh(rx->id, &thresh, 4096.0, (double)rx->sample_rate); + + double knee_y=thresh+(double)get_attenuation(); + knee_y = floor((rx->panadapter_high - knee_y) + * (double) display_height + / (rx->panadapter_high - rx->panadapter_low)); + + double hang_y=hang+(double)get_attenuation(); + hang_y = floor((rx->panadapter_high - hang_y) + * (double) display_height + / (rx->panadapter_high - rx->panadapter_low)); + +//fprintf(stderr,"hang=%f thresh=%f hang_y=%f knee_y=%f\n",rx1_hang,rx1_thresh,hang_y,knee_y); + if(rx->agc!=AGC_MEDIUM && rx->agc!=AGC_FAST) { + if(active) { + cairo_set_source_rgb (cr, 1.0, 1.0, 0.0); + } else { + cairo_set_source_rgb (cr, 0.5, 0.5, 0.0); + } + cairo_move_to(cr,40.0,hang_y-8.0); + cairo_rectangle(cr, 40, hang_y-8.0,8.0,8.0); + cairo_fill(cr); + cairo_move_to(cr,40.0,hang_y); + cairo_line_to(cr,(double)display_width-40.0,hang_y); + cairo_stroke(cr); + cairo_move_to(cr,48.0,hang_y); + cairo_show_text(cr, "-H"); + } + + if(active) { + cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); + } else { + cairo_set_source_rgb (cr, 0.0, 0.5, 0.0); + } + cairo_move_to(cr,40.0,knee_y-8.0); + cairo_rectangle(cr, 40, knee_y-8.0,8.0,8.0); + cairo_fill(cr); + cairo_move_to(cr,40.0,knee_y); + cairo_line_to(cr,(double)display_width-40.0,knee_y); + cairo_stroke(cr); + cairo_move_to(cr,48.0,knee_y); + cairo_show_text(cr, "-G"); + } + + + // cursor + if(active) { + cairo_set_source_rgb (cr, 1, 0, 0); + } else { + cairo_set_source_rgb (cr, 0.5, 0, 0); + } + cairo_set_line_width(cr, 1.0); + cairo_move_to(cr,(double)(display_width/2.0)+(vfo[rx->id].offset/rx->hz_per_pixel),0.0); + cairo_line_to(cr,(double)(display_width/2.0)+(vfo[rx->id].offset/rx->hz_per_pixel),(double)display_height); + cairo_stroke(cr); + + // signal + double s1,s2; + samples[0]=-200.0; + samples[display_width-1]=-200.0; + + s1=(double)samples[0]+(double)get_attenuation(); + s1 = floor((rx->panadapter_high - s1) + * (double) display_height + / (rx->panadapter_high - rx->panadapter_low)); + cairo_move_to(cr, 0.0, s1); + for(i=1;ipanadapter_high - s2) + * (double) display_height + / (rx->panadapter_high - rx->panadapter_low)); + cairo_line_to(cr, (double)i, s2); + } + + if(display_filled) { + cairo_close_path (cr); + if(active) { + cairo_set_source_rgba(cr, 1, 1, 1,0.5); + } else { + cairo_set_source_rgba(cr, 0.5, 0.5, 0.5,0.5); + } + cairo_fill_preserve (cr); + } + if(active) { + cairo_set_source_rgb(cr, 1, 1, 1); + } else { + cairo_set_source_rgb(cr, 0.5, 0.5, 0.5); + } + cairo_set_line_width(cr, 1.0); + cairo_stroke(cr); + +#ifdef FREEDV + int mode=rx->mode; + if(mode==modeFREEDV) { + cairo_set_source_rgb(cr, 0, 1, 0); + cairo_set_font_size(cr, 16); + cairo_text_extents(cr, freedv_text_data, &extents); + cairo_move_to(cr, (double)display_width/2.0-(extents.width/2.0),(double)display_height-2.0); + cairo_show_text(cr, freedv_text_data); + } +#endif + +#ifdef GPIO + if(active) { + cairo_set_source_rgb(cr,1,1,0); + cairo_set_font_size(cr,12); + if(ENABLE_E1_ENCODER) { + cairo_move_to(cr, display_width-100,20); + cairo_show_text(cr, encoder_string[e1_encoder_action]); + } + + if(ENABLE_E2_ENCODER) { + cairo_move_to(cr, display_width-100,40); + cairo_show_text(cr, encoder_string[e2_encoder_action]); + } + + if(ENABLE_E3_ENCODER) { + cairo_move_to(cr, display_width-100,60); + cairo_show_text(cr, encoder_string[e3_encoder_action]); + } + } +#endif + + cairo_destroy (cr); + gtk_widget_queue_draw (rx->panadapter); + +} + +void rx_panadapter_init(RECEIVER *rx, int width,int height) { + + int display_width=width; + int display_height=height; + + rx->panadapter_surface=NULL; + rx->panadapter = gtk_drawing_area_new (); + gtk_widget_set_size_request (rx->panadapter, width, height); + + /* Signals used to handle the backing surface */ + g_signal_connect (rx->panadapter, "draw", + G_CALLBACK (panadapter_draw_cb), rx); + g_signal_connect (rx->panadapter,"configure-event", + G_CALLBACK (panadapter_configure_event_cb), rx); + + /* Event signals */ + g_signal_connect (rx->panadapter, "motion-notify-event", + G_CALLBACK (panadapter_motion_notify_event_cb), rx); + g_signal_connect (rx->panadapter, "button-press-event", + G_CALLBACK (panadapter_button_press_event_cb), rx); + g_signal_connect (rx->panadapter, "button-release-event", + G_CALLBACK (panadapter_button_release_event_cb), rx); + g_signal_connect(rx->panadapter,"scroll_event", + G_CALLBACK(panadapter_scroll_event_cb),rx); + + /* Ask to receive events the drawing area doesn't normally + * subscribe to. In particular, we need to ask for the + * button press and motion notify events that want to handle. + */ + gtk_widget_set_events (rx->panadapter, gtk_widget_get_events (rx->panadapter) + | GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK + | GDK_BUTTON1_MOTION_MASK + | GDK_SCROLL_MASK + | GDK_POINTER_MOTION_MASK + | GDK_POINTER_MOTION_HINT_MASK); + +} diff --git a/rx_panadapter.h b/rx_panadapter.h new file mode 100644 index 0000000..3481d8a --- /dev/null +++ b/rx_panadapter.h @@ -0,0 +1,28 @@ +/* Copyright (C) +* 2015 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#ifndef _PANADAPTER_H +#define _PANADAPTER_H + +void rx_panadapter_update(RECEIVER* rx); + +void rx_panadapter_init(RECEIVER *rx,int width,int height); + + +#endif diff --git a/sliders.c b/sliders.c index d33cf94..4b02904 100644 --- a/sliders.c +++ b/sliders.c @@ -37,12 +37,13 @@ #include "channel.h" #include "wdsp.h" #include "radio.h" +#include "receiver.h" #include "property.h" +#include "main.h" static int width; static int height; -static GtkWidget *parent_window; static GtkWidget *sliders; #define NONE 0 @@ -76,7 +77,7 @@ static GtkWidget *dummy_label; static GdkRGBA white; static GdkRGBA gray; -void linein_changed() { +int linein_changed(void *data) { if(display_sliders) { if(mic_linein) { gtk_widget_hide(mic_gain_label); @@ -90,6 +91,15 @@ void linein_changed() { gtk_widget_show(mic_gain_scale); } } + return 0; +} + +int active_receiver_changed(void *data) { + if(display_sliders) { + gtk_range_set_value(GTK_RANGE(af_gain_scale),active_receiver->volume*100.0); + gtk_range_set_value (GTK_RANGE(agc_scale),active_receiver->agc_gain); + gtk_range_set_value (GTK_RANGE(attenuation_scale),active_receiver->attenuation); + } } int scale_timeout_cb(gpointer data) { @@ -99,14 +109,14 @@ int scale_timeout_cb(gpointer data) { } static void attenuation_value_changed_cb(GtkWidget *widget, gpointer data) { - attenuation=(int)gtk_range_get_value(GTK_RANGE(attenuation_scale)); - set_attenuation(attenuation); + active_receiver->attenuation=(int)gtk_range_get_value(GTK_RANGE(attenuation_scale)); + set_attenuation(active_receiver->attenuation); } void set_attenuation_value(double value) { - attenuation=(int)value; + active_receiver->attenuation=(int)value; if(display_sliders) { - gtk_range_set_value (GTK_RANGE(attenuation_scale),attenuation); + gtk_range_set_value (GTK_RANGE(attenuation_scale),active_receiver->attenuation); } else { if(scale_status!=ATTENUATION) { if(scale_status!=NONE) { @@ -117,11 +127,11 @@ void set_attenuation_value(double value) { } if(scale_status==NONE) { scale_status=ATTENUATION; - scale_dialog=gtk_dialog_new_with_buttons("Attenuation (dB)",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); + scale_dialog=gtk_dialog_new_with_buttons("Attenuation (dB)",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); gtk_widget_set_size_request (attenuation_scale, 400, 30); - gtk_range_set_value (GTK_RANGE(attenuation_scale),attenuation); + gtk_range_set_value (GTK_RANGE(attenuation_scale),active_receiver->attenuation); gtk_widget_show(attenuation_scale); gtk_container_add(GTK_CONTAINER(content),attenuation_scale); scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL); @@ -129,23 +139,23 @@ void set_attenuation_value(double value) { int result=gtk_dialog_run(GTK_DIALOG(scale_dialog)); } else { g_source_remove(scale_timer); - gtk_range_set_value (GTK_RANGE(attenuation_scale),attenuation); + gtk_range_set_value (GTK_RANGE(attenuation_scale),active_receiver->attenuation); scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL); } } - set_attenuation(attenuation); + set_attenuation(active_receiver->attenuation); } static void agcgain_value_changed_cb(GtkWidget *widget, gpointer data) { - agc_gain=gtk_range_get_value(GTK_RANGE(agc_scale)); - SetRXAAGCTop(CHANNEL_RX0, agc_gain); + active_receiver->agc_gain=gtk_range_get_value(GTK_RANGE(agc_scale)); + SetRXAAGCTop(active_receiver->id, active_receiver->agc_gain); } void set_agc_gain(double value) { - agc_gain=value; - SetRXAAGCTop(CHANNEL_RX0, agc_gain); + active_receiver->agc_gain=value; + SetRXAAGCTop(active_receiver->id, active_receiver->agc_gain); if(display_sliders) { - gtk_range_set_value (GTK_RANGE(agc_scale),agc_gain); + gtk_range_set_value (GTK_RANGE(agc_scale),active_receiver->agc_gain); } else { if(scale_status!=AGC_GAIN) { if(scale_status!=NONE) { @@ -156,11 +166,11 @@ void set_agc_gain(double value) { } if(scale_status==NONE) { scale_status=AGC_GAIN; - scale_dialog=gtk_dialog_new_with_buttons("AGC Gain",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); + scale_dialog=gtk_dialog_new_with_buttons("AGC Gain",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog)); agc_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,-20.0, 120.0, 1.00); gtk_widget_set_size_request (agc_scale, 400, 30); - gtk_range_set_value (GTK_RANGE(agc_scale),agc_gain); + gtk_range_set_value (GTK_RANGE(agc_scale),active_receiver->agc_gain); gtk_widget_show(agc_scale); gtk_container_add(GTK_CONTAINER(content),agc_scale); scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL); @@ -168,7 +178,7 @@ void set_agc_gain(double value) { int result=gtk_dialog_run(GTK_DIALOG(scale_dialog)); } else { g_source_remove(scale_timer); - gtk_range_set_value (GTK_RANGE(agc_scale),agc_gain); + gtk_range_set_value (GTK_RANGE(agc_scale),active_receiver->agc_gain); scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL); } } @@ -181,20 +191,20 @@ int update_agc_gain(void *data) { } static void afgain_value_changed_cb(GtkWidget *widget, gpointer data) { - volume=gtk_range_get_value(GTK_RANGE(af_gain_scale))/100.0; - SetRXAPanelGain1 (CHANNEL_RX0, volume); + active_receiver->volume=gtk_range_get_value(GTK_RANGE(af_gain_scale))/100.0; + SetRXAPanelGain1 (active_receiver->id, active_receiver->volume); } int update_af_gain(void *data) { - set_af_gain(volume); + set_af_gain(active_receiver->volume); return 0; } void set_af_gain(double value) { - volume=value; - SetRXAPanelGain1 (CHANNEL_RX0, volume); + active_receiver->volume=value; + SetRXAPanelGain1 (active_receiver->id, active_receiver->volume); if(display_sliders) { - gtk_range_set_value (GTK_RANGE(af_gain_scale),volume*100.0); + gtk_range_set_value (GTK_RANGE(af_gain_scale),active_receiver->volume*100.0); } else { if(scale_status!=AF_GAIN) { if(scale_status!=NONE) { @@ -205,11 +215,11 @@ void set_af_gain(double value) { } if(scale_status==NONE) { scale_status=AF_GAIN; - scale_dialog=gtk_dialog_new_with_buttons("AF Gain",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); + scale_dialog=gtk_dialog_new_with_buttons("AF Gain",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog)); af_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 100.0, 1.00); gtk_widget_set_size_request (af_gain_scale, 400, 30); - gtk_range_set_value (GTK_RANGE(af_gain_scale),volume*100.0); + gtk_range_set_value (GTK_RANGE(af_gain_scale),active_receiver->volume*100.0); gtk_widget_show(af_gain_scale); gtk_container_add(GTK_CONTAINER(content),af_gain_scale); scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL); @@ -217,7 +227,7 @@ void set_af_gain(double value) { int result=gtk_dialog_run(GTK_DIALOG(scale_dialog)); } else { g_source_remove(scale_timer); - gtk_range_set_value (GTK_RANGE(af_gain_scale),volume*100.0); + gtk_range_set_value (GTK_RANGE(af_gain_scale),active_receiver->volume*100.0); scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL); } } @@ -226,13 +236,13 @@ void set_af_gain(double value) { static void micgain_value_changed_cb(GtkWidget *widget, gpointer data) { mic_gain=gtk_range_get_value(GTK_RANGE(widget)); double gain=pow(10.0, mic_gain / 20.0); - SetTXAPanelGain1(CHANNEL_TX,gain); + SetTXAPanelGain1(transmitter->id,gain); } void set_mic_gain(double value) { mic_gain=value; double gain=pow(10.0, mic_gain / 20.0); - SetTXAPanelGain1(CHANNEL_TX,gain); + SetTXAPanelGain1(transmitter->id,gain); if(display_sliders) { gtk_range_set_value (GTK_RANGE(mic_gain_scale),mic_gain); } else { @@ -245,7 +255,7 @@ void set_mic_gain(double value) { } if(scale_status==NONE) { scale_status=MIC_GAIN; - scale_dialog=gtk_dialog_new_with_buttons("Mic Gain (dB)",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); + scale_dialog=gtk_dialog_new_with_buttons("Mic Gain (dB)",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog)); mic_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,-10.0, 50.0, 1.00); gtk_widget_set_size_request (mic_gain_scale, 400, 30); @@ -288,7 +298,7 @@ void set_linein_gain(int value) { } if(scale_status==NONE) { scale_status=LINEIN_GAIN; - scale_dialog=gtk_dialog_new_with_buttons("Linein Gain",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); + scale_dialog=gtk_dialog_new_with_buttons("Linein Gain",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog)); linein_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 31.0, 1.00); gtk_widget_set_size_request (linein_gain_scale, 400, 30); @@ -327,7 +337,7 @@ void set_drive(double value) { } if(scale_status==NONE) { scale_status=DRIVE; - scale_dialog=gtk_dialog_new_with_buttons("Drive",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); + scale_dialog=gtk_dialog_new_with_buttons("Drive",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog)); drive_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 100.0, 1.00); gtk_widget_set_size_request (drive_scale, 400, 30); @@ -369,7 +379,7 @@ void set_tune(double value) { } if(scale_status==NONE) { scale_status=TUNE_DRIVE; - scale_dialog=gtk_dialog_new_with_buttons("Tune Drive",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); + scale_dialog=gtk_dialog_new_with_buttons("Tune Drive",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog)); tune_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 100.0, 1.00); gtk_widget_set_size_request (tune_scale, 400, 30); @@ -391,10 +401,9 @@ static void tune_value_changed_cb(GtkWidget *widget, gpointer data) { setTuneDrive(gtk_range_get_value(GTK_RANGE(tune_scale))); } -GtkWidget *sliders_init(int my_width, int my_height, GtkWidget* parent) { +GtkWidget *sliders_init(int my_width, int my_height) { width=my_width; height=my_height; - parent_window=parent; fprintf(stderr,"sliders_init: width=%d height=%d\n", width,height); @@ -409,7 +418,7 @@ GtkWidget *sliders_init(int my_width, int my_height, GtkWidget* parent) { gtk_grid_attach(GTK_GRID(sliders),af_gain_label,0,0,1,1); af_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 100.0, 1.00); - gtk_range_set_value (GTK_RANGE(af_gain_scale),volume*100.0); + gtk_range_set_value (GTK_RANGE(af_gain_scale),active_receiver->volume*100.0); gtk_widget_show(af_gain_scale); gtk_grid_attach(GTK_GRID(sliders),af_gain_scale,1,0,2,1); g_signal_connect(G_OBJECT(af_gain_scale),"value_changed",G_CALLBACK(afgain_value_changed_cb),NULL); @@ -420,7 +429,7 @@ GtkWidget *sliders_init(int my_width, int my_height, GtkWidget* parent) { gtk_grid_attach(GTK_GRID(sliders),agc_gain_label,3,0,1,1); agc_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,-20.0, 120.0, 1.0); - gtk_range_set_value (GTK_RANGE(agc_scale),agc_gain); + gtk_range_set_value (GTK_RANGE(agc_scale),active_receiver->agc_gain); gtk_widget_show(agc_scale); gtk_grid_attach(GTK_GRID(sliders),agc_scale,4,0,2,1); g_signal_connect(G_OBJECT(agc_scale),"value_changed",G_CALLBACK(agcgain_value_changed_cb),NULL); @@ -431,7 +440,7 @@ GtkWidget *sliders_init(int my_width, int my_height, GtkWidget* parent) { gtk_grid_attach(GTK_GRID(sliders),attenuation_label,6,0,1,1); attenuation_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 31.0, 1.0); - gtk_range_set_value (GTK_RANGE(attenuation_scale),attenuation); + gtk_range_set_value (GTK_RANGE(attenuation_scale),active_receiver->attenuation); gtk_widget_show(attenuation_scale); gtk_grid_attach(GTK_GRID(sliders),attenuation_scale,7,0,2,1); g_signal_connect(G_OBJECT(attenuation_scale),"value_changed",G_CALLBACK(attenuation_value_changed_cb),NULL); diff --git a/sliders.h b/sliders.h index 1601753..17aa927 100644 --- a/sliders.h +++ b/sliders.h @@ -20,18 +20,19 @@ #ifndef _SLIDERS_H #define _SLIDERS_H -extern void linein_changed(); +extern int linein_changed(void *data); +extern int active_receiver_changed(void *data); extern int update_agc_gain(void *); extern int update_af_gain(void *); extern int update_mic_gain(void *); extern int update_drive(void *); -void set_agc_gain(double value); -void set_af_gain(double value); -void set_mic_gain(double value); -void set_drive(double drive); -void set_tune(double tune); -void set_attenuation_value(double attenuation); -GtkWidget *sliders_init(int my_width, int my_height, GtkWidget* parent); +extern void set_agc_gain(double value); +extern void set_af_gain(double value); +extern void set_mic_gain(double value); +extern void set_drive(double drive); +extern void set_tune(double tune); +extern void set_attenuation_value(double attenuation); +extern GtkWidget *sliders_init(int my_width, int my_height); #endif diff --git a/soundio.c b/soundio.c new file mode 100644 index 0000000..622d54a --- /dev/null +++ b/soundio.c @@ -0,0 +1,477 @@ +/* Copyright (C) +* 2016 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "new_protocol.h" +#include "old_protocol.h" +#include "radio.h" +#include "receiver.h" +#include "audio.h" + +int audio = 0; +int audio_buffer_size = 256; // samples (both left and right) +int mic_buffer_size = 720; // samples (both left and right) + +//static snd_pcm_t *playback_handle=NULL; +static snd_pcm_t *record_handle=NULL; + +// each buffer contains 63 samples of left and right audio at 16 bits +#define AUDIO_SAMPLES 63 +#define AUDIO_SAMPLE_SIZE 2 +#define AUDIO_CHANNELS 2 +#define AUDIO_BUFFERS 10 +#define OUTPUT_BUFFER_SIZE (AUDIO_SAMPLE_SIZE*AUDIO_CHANNELS*audio_buffer_size) + +#define MIC_BUFFER_SIZE (AUDIO_SAMPLE_SIZE*AUDIO_CHANNELS*mic_buffer_size) + +//static unsigned char *audio_buffer=NULL; +//static int audio_offset=0; + +static unsigned char *mic_buffer=NULL; + +static GThread *mic_read_thread_id; + +static int running=FALSE; + +static void *mic_read_thread(void *arg); + +char *input_devices[16]; +int n_input_devices=0; +int n_selected_input_device=-1; + +char *output_devices[16]; +int n_output_devices=0; +//int n_selected_output_device=-1; + +static double seconds_offset=0.0; +static int want_pause=0; + +#define BUFFER_SIZE 8192 + +static struct SoundIo *soundio; +static struct SoundIoDevice *audio_device; +static struct SoundIoOutStream *outstream; + +static short output_left_buffer[BUFFER_SIZE]; +static short output_right_buffer[BUFFER_SIZE]; +static int insert_index=0; +static int remove_index=0; +static int frames=0; + +static void write_callback(struct SoundIoOutStream *outstream, int frame_count_min, int frame_count_max) { +//fprintf(stderr,"write_callback: min=%d max=%d frames=%d insert_index=%d remove_index=%d\n",frame_count_min, frame_count_max, frames, insert_index, remove_index); + double float_sample_rate = outstream->sample_rate; + double seconds_per_frame = 1.0 / float_sample_rate; + struct SoundIoChannelArea *areas; + int err; + int frame; + int channel; + + if(frames!=0) { + int frames_left = frames; + if(frames>frame_count_max) { + frames_left=frame_count_max; + } + if ((err = soundio_outstream_begin_write(outstream, &areas, &frames_left))) { + fprintf(stderr, "unrecoverable stream error: %s\n", soundio_strerror(err)); + exit(1); + } + + const struct SoundIoChannelLayout *layout = &outstream->layout; + + for (frame=0; frame < frames_left; frame += 1) { + for (channel = 0; channel < layout->channel_count; channel += 1) { + int16_t *s=(int16_t *)areas[channel].ptr; + if(channel==0) { + *s=output_left_buffer[remove_index]; + } else { + *s=output_right_buffer[remove_index]; + } + areas[channel].ptr += areas[channel].step; + } + frames--; + remove_index++; + if(remove_index==BUFFER_SIZE) { + remove_index=0; + } + } + //seconds_offset += seconds_per_frame * frame_count; + + if ((err = soundio_outstream_end_write(outstream))) { + if (err == SoundIoErrorUnderflow) + return; + fprintf(stderr, "unrecoverable stream error: %s\n", soundio_strerror(err)); + exit(1); + } + } else { + //fprintf(stderr,"audio.c: write_callback: underflow: frames=%d insert_index=%d remove_index=%d\n",frames,insert_index,remove_index); + } +} + +static void underflow_callback(struct SoundIoOutStream *outstream) { + static int count = 0; + //fprintf(stderr, "underflow %d\n", count++); +} + +int audio_open_output(RECEIVER *rx) { + + int err; + +fprintf(stderr,"audio_open_output: id=%d device=%d\n", rx->id,rx->audio_device); + soundio = soundio_create(); + if (!soundio) { + fprintf(stderr, "audio_open_output: soundio_create failed\n"); + return -1; + } + + soundio_connect(soundio); + + soundio_flush_events(soundio); + + audio_device = soundio_get_output_device(soundio, rx->audio_device); + if(!audio_device) { + fprintf(stderr, "audio_open_output: soundio_get_output_device failed\n"); + return -1; + } + + if (audio_device->probe_error) { + fprintf(stderr, "audio_open_output: Cannot probe audio_device: %s\n", soundio_strerror(audio_device->probe_error)); + return -1; + } + + outstream = soundio_outstream_create(audio_device); + outstream->write_callback = write_callback; + outstream->underflow_callback = underflow_callback; + outstream->name = "pihpsdr:out"; + outstream->software_latency = 0.0; + outstream->sample_rate = 48000; + + if (soundio_device_supports_format(audio_device, SoundIoFormatS16LE)) { + outstream->format = SoundIoFormatS16LE; + } else { + fprintf(stderr,"audio_open_output: audio_device does not support S16LE\n"); + return -1; + } + + if ((err = soundio_outstream_open(outstream))) { + fprintf(stderr, "audio_open_output: unable to open audio_device: %s", soundio_strerror(err)); + return -1; + } + fprintf(stderr, "audio_open_output: Software latency: %f\n", outstream->software_latency); + + if (outstream->layout_error) { + fprintf(stderr, "audio_open_output: unable to set channel layout: %s\n", soundio_strerror(outstream->layout_error)); + } + + if ((err = soundio_outstream_start(outstream))) { + fprintf(stderr, "audio_open_output: unable to start audio_device: %s\n", soundio_strerror(err)); + return -1; + } + + return 0; +} + +int audio_open_input() { +/* + int err; + snd_pcm_hw_params_t *hw_params; + int rate=48000; + int dir=0; + +fprintf(stderr,"audio_open_input: %d\n",n_selected_input_device); + if(n_selected_input_device<0 || n_selected_input_device>=n_input_devices) { + n_selected_input_device=-1; + return -1; + } + + int i; + char hw[16]; + char *selected=input_devices[n_selected_input_device]; + fprintf(stderr,"audio_open_input: selected=%d:%s\n",n_selected_input_device,selected); + + switch(protocol) { + case ORIGINAL_PROTOCOL: + mic_buffer_size = 720; + break; + case NEW_PROTOCOL: + mic_buffer_size = 64; + break; + default: + break; + } + + fprintf(stderr,"audio_open_input: mic_buffer_size=%d\n",mic_buffer_size); + i=0; + while(selected[i]!=' ') { + hw[i]=selected[i]; + i++; + } + hw[i]='\0'; + + fprintf(stderr,"audio_open_input: hw=%s\n",hw); + + if ((err = snd_pcm_open (&record_handle, hw, SND_PCM_STREAM_CAPTURE, 0)) < 0) { + fprintf (stderr, "audio_open_input: cannot open audio device %s (%s)\n", + hw, + snd_strerror (err)); + return -1; + } + + if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { + fprintf (stderr, "audio_open_input: cannot allocate hardware parameter structure (%s)\n", + snd_strerror (err)); + return -1; + } + + if ((err = snd_pcm_hw_params_any (record_handle, hw_params)) < 0) { + fprintf (stderr, "audio_open_input: cannot initialize hardware parameter structure (%s)\n", + snd_strerror (err)); + return -1; + } + + if ((err = snd_pcm_hw_params_set_access (record_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { + fprintf (stderr, "audio_open_input: cannot set access type (%s)\n", + snd_strerror (err)); + return -1; +} + + if ((err = snd_pcm_hw_params_set_format (record_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { + fprintf (stderr, "audio_open_input: cannot set sample format (%s)\n", + snd_strerror (err)); + return -1; + } + + if ((err = snd_pcm_hw_params_set_rate_near (record_handle, hw_params, &rate, &dir)) < 0) { + fprintf (stderr, "audio_open_input: cannot set sample rate (%s)\n", + snd_strerror (err)); + return -1; + } + + if ((err = snd_pcm_hw_params_set_channels (record_handle, hw_params, 1)) < 0) { + fprintf (stderr, "audio_open_input: cannot set channel count (%s)\n", + snd_strerror (err)); + return -1; + } + + if ((err = snd_pcm_hw_params (record_handle, hw_params)) < 0) { + fprintf (stderr, "audio_open_input: cannot set parameters (%s)\n", + snd_strerror (err)); + return -1; + } + + snd_pcm_hw_params_free (hw_params); + + mic_buffer=(unsigned char *)malloc(MIC_BUFFER_SIZE); + + running=TRUE; + mic_read_thread_id = g_thread_new( "local mic", mic_read_thread, NULL); + if(!mic_read_thread_id ) + { + fprintf(stderr,"g_thread_new failed on mic_read_thread\n"); + } + +*/ + return 0; +} + +void audio_close_output(RECEIVER *rx) { + soundio_outstream_destroy(outstream); + soundio_device_unref(audio_device); + soundio_destroy(soundio); +/* + if(rx->playback_handle!=NULL) { + snd_pcm_close (rx->playback_handle); + rx->playback_handle=NULL; + } + if(rx->playback_buffer!=NULL) { + free(rx->playback_buffer); + rx->playback_buffer=NULL; + } +*/ +} + +void audio_close_input() { +/* + running=FALSE; + if(record_handle!=NULL) { + snd_pcm_close (record_handle); + record_handle=NULL; + } + if(mic_buffer!=NULL) { + free(mic_buffer); + mic_buffer=NULL; + } +*/ +} + +int audio_write(RECEIVER *rx,short left_sample,short right_sample) { +//fprintf(stderr,"audio_write: id=%d frames=%d insert_index=%d remove_index=%d\n",rx->id, frames, insert_index,remove_index); + if(frames<(BUFFER_SIZE-2)) { + output_left_buffer[insert_index]=left_sample; + output_right_buffer[insert_index]=right_sample; + insert_index++; + if(insert_index==BUFFER_SIZE) { + insert_index=0; + } + frames++; + } else { + fprintf(stderr,"audio_write: buffer_full: frames=%d insert_index-%d remove_index=%d\n",frames,insert_index,remove_index); + } + +/* + snd_pcm_sframes_t delay; + int error; + long trim; + + if(rx->playback_handle!=NULL && rx->playback_buffer!=NULL) { + rx->playback_buffer[rx->playback_offset++]=right_sample; + rx->playback_buffer[rx->playback_offset++]=right_sample>>8; + rx->playback_buffer[rx->playback_offset++]=left_sample; + rx->playback_buffer[rx->playback_offset++]=left_sample>>8; + + if(rx->playback_offset==OUTPUT_BUFFER_SIZE) { + + trim=0; + + if(snd_pcm_delay(rx->playback_handle,&delay)==0) { + if(delay>2048) { + trim=delay-2048; +//fprintf(stderr,"audio delay=%ld trim=%ld\n",delay,trim); + } + } + + if ((error = snd_pcm_writei (rx->playback_handle, rx->playback_buffer, audio_buffer_size-trim)) != audio_buffer_size-trim) { + if(error==-EPIPE) { + if ((error = snd_pcm_prepare (rx->playback_handle)) < 0) { + fprintf (stderr, "audio_write: cannot prepare audio interface for use (%s)\n", + snd_strerror (error)); + return -1; + } + if ((error = snd_pcm_writei (rx->playback_handle, rx->playback_buffer, audio_buffer_size-trim)) != audio_buffer_size) { + fprintf (stderr, "audio_write: write to audio interface failed (%s)\n", + snd_strerror (error)); + return -1; + } + } + } + rx->playback_offset=0; + } + } +*/ + return 0; +} + +static gpointer mic_read_thread(gpointer arg) { +/* + int rc; + if ((rc = snd_pcm_prepare (record_handle)) < 0) { + fprintf (stderr, "mic_read_thread: cannot prepare audio interface for use (%s)\n", + snd_strerror (rc)); + return; + } +fprintf(stderr,"mic_read_thread: mic_buffer_size=%d\n",mic_buffer_size); + while(running) { + if ((rc = snd_pcm_readi (record_handle, mic_buffer, mic_buffer_size)) != mic_buffer_size) { + if(running) { + if(rc<0) { + fprintf (stderr, "mic_read_thread: read from audio interface failed (%s)\n", + snd_strerror (rc)); + running=FALSE; + } else { + fprintf(stderr,"mic_read_thread: read %d\n",rc); + } + } + } else { + // process the mic input + switch(protocol) { + case ORIGINAL_PROTOCOL: + old_protocol_process_local_mic(mic_buffer,1); + break; + case NEW_PROTOCOL: + new_protocol_process_local_mic(mic_buffer,1); + break; + default: + break; + } + } + } +fprintf(stderr,"mic_read_thread: exiting\n"); +*/ +} + +void audio_get_cards() { + int i; + + for(i=0;iid,device->name); + char *device_id=malloc(64); + strncpy(device_id,device->id,64); + output_devices[i]=device_id; + soundio_device_unref(device); + } + + for(i=0;iid,device->name); + char *device_id=malloc(64); + strncpy(device_id,device->id,64); + input_devices[i]=device_id; + soundio_device_unref(device); + } + + soundio_destroy(soundio); +} diff --git a/soundio.h b/soundio.h new file mode 100644 index 0000000..ee4dcfe --- /dev/null +++ b/soundio.h @@ -0,0 +1,39 @@ +/* Copyright (C) +* 2016 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#ifndef _AUDIO_H +#define _AUDIO_H + +#include "receiver.h" + +extern char *input_devices[]; +extern int n_input_devices; +extern int n_selected_input_device; + +extern char *output_devices[]; +extern int n_output_devices; +//extern int n_selected_output_device; + +extern int audio_open_input(); +extern void audio_close_input(); +extern int audio_open_output(RECEIVER *rx); +extern void audio_close_output(RECEIVER *rx); +extern int audio_write(RECEIVER *rx,short left_sample,short right_sample); +extern void audio_get_cards(); +#endif diff --git a/splash.c b/splash.c index 9dded3e..0520d5b 100644 --- a/splash.c +++ b/splash.c @@ -20,53 +20,28 @@ #include #include "version.h" -GtkWidget *splash_screen; +GtkWidget *grid; GtkWidget *status; static cairo_surface_t *splash_surface = NULL; + /* Close the splash screen */ void splash_close() { - gtk_widget_destroy(splash_screen); -} - -static gboolean splash_configure_event_cb (GtkWidget *widget, - GdkEventConfigure *event, - gpointer data) -{ - if (splash_surface) - cairo_surface_destroy (splash_surface); - - splash_surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget), - CAIRO_CONTENT_COLOR, - gtk_widget_get_allocated_width (widget), - gtk_widget_get_allocated_height (widget)); - - return TRUE; + gtk_widget_destroy(grid); } - -void splash_show(char* image_name,int width,int height,int full_screen) +GtkWidget *splash_create(char* image_name,int width,int height) { GtkWidget *image; - splash_screen = gtk_window_new (GTK_WINDOW_TOPLEVEL); - if(full_screen) { - gtk_window_fullscreen(GTK_WINDOW(splash_screen)); - } - gtk_widget_set_size_request(splash_screen, width, height); - gtk_window_set_position(GTK_WINDOW(splash_screen),GTK_WIN_POS_CENTER_ALWAYS); - gtk_window_set_resizable(GTK_WINDOW(splash_screen), FALSE); - - GtkWidget *grid = gtk_grid_new(); + grid = gtk_grid_new(); + gtk_widget_set_size_request(grid, width, height); gtk_grid_set_row_homogeneous(GTK_GRID(grid),FALSE); gtk_grid_set_column_homogeneous(GTK_GRID(grid),FALSE); image=gtk_image_new_from_file(image_name); - //gtk_container_add(GTK_CONTAINER(splash_screen), image); gtk_grid_attach(GTK_GRID(grid), image, 0, 0, 1, 4); - g_signal_connect (splash_screen,"configure-event", - G_CALLBACK (splash_configure_event_cb), NULL); char build[64]; sprintf(build,"build: %s %s",build_date, version); @@ -84,11 +59,9 @@ void splash_show(char* image_name,int width,int height,int full_screen) gtk_label_set_justify(GTK_LABEL(status),GTK_JUSTIFY_LEFT); gtk_widget_override_font(status, pango_font_description_from_string("FreeMono 18")); gtk_widget_show(status); - //gtk_container_add(GTK_CONTAINER(splash_screen), status); gtk_grid_attach(GTK_GRID(grid), status, 1, 3, 1, 1); - gtk_container_add(GTK_CONTAINER(splash_screen), grid); - gtk_widget_show_all (splash_screen); + return grid; } void splash_status(char *text) { diff --git a/splash.h b/splash.h index 8c6e1ad..ada65a9 100644 --- a/splash.h +++ b/splash.h @@ -21,10 +21,9 @@ #ifndef _SPLASH_H #define _SPLASH_H -extern GtkWidget* splash_screen; void splash_close(void); -void splash_show(char *image_name,int time,int width,int height); +GtkWidget *splash_create(char *image_name,int width,int height); void splash_status(char *text); #endif diff --git a/store.c b/store.c new file mode 100644 index 0000000..0b6bb47 --- /dev/null +++ b/store.c @@ -0,0 +1,140 @@ +/* Copyright (C) +* 2015 - John Melton, G0ORX/N6LYT +* 2016 - Steve Wilson, KA6S +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#include +#include +#include + +#include "bandstack.h" +#include "band.h" +#include "filter.h" +#include "mode.h" +#include "alex.h" +#include "property.h" +#include "store.h" +#include "store_menu.h" + + +/* +struct MEM { + char title[16]; // Begin BAND Struct + BANDSTACK *bandstack; + unsigned char OCrx; + unsigned char OCtx; + int preamp; + int alexRxAntenna; + int alexTxAntenna; + int alexAttenuation; + double pa_calibration; + long long frequencyMin; + long long frequencyMax; + long long frequencyLO; + int disablePA; + long long frequency; // Begin BANDSTACK_ENTRY + int mode; + int filter; + int var1Low; + int var1High; + int var2Low; + int var2High; +}*/ +MEM mem[NUM_OF_MEMORYS]; // This makes it a compile time option + +/* */ +/* Memory uses the same format as Band Stack */ +/* Implement NUM_OF_MEMORYS memory locations for now... */ + +void memSaveState() { + char name[128]; + char value[128]; + int current; + BANDSTACK_ENTRY* entry; + int workvar; + int b; + int stack; + + for(b=0;b0) { + sprintf(name,"mem.%d.title",b); + setProperty(name,mem[b].title); + + sprintf(value,"%lld",mem[b].frequency); + sprintf(name,"mem.%d.freqA",b); + setProperty(name,value); + + sprintf(value,"%d",mem[b].mode); + sprintf(name,"mem.%d.mode",b); + setProperty(name,value); + + sprintf(value,"%d",mem[b].filter); + sprintf(name,"mem.%d.filter",b); + setProperty(name,value); + } + } + + //sprintf(value,"%d",band); + //setProperty("band",value); +} + +void memRestoreState() { + char* value; + int b; + int stack; + char name[128]; + BANDSTACK_ENTRY* entry; + int current; + + // Initialize the array with default values + // Allows this to be a compile time option.. + for(b=0; b +#include "bandstack.h" + + +/* --------------------------------------------------------------------------*/ +/** +* @brief Band definition +*/ +struct _MEM_STORE { + char title[16]; // Begin BAND Struct + long long frequency; // Begin BANDSTACK_ENTRY + int mode; + int filter; +}; + +typedef struct _MEM_STORE MEM; + +extern MEM mem[]; +void memRestoreState(); +void memSaveState(); + +#endif diff --git a/store_menu.c b/store_menu.c new file mode 100644 index 0000000..a91cada --- /dev/null +++ b/store_menu.c @@ -0,0 +1,140 @@ +/* Copyright (C) +* 2016 - John Melton, G0ORX/N6LYT +* 2016 - Steve Wilson, KA6S +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#include +#include +#include + +#include "new_menu.h" +#include "store_menu.h" +#include "band.h" +#include "bandstack.h" +#include "filter.h" +#include "mode.h" +#include "radio.h" +#include "rigctl.h" +#include "band.h" +#include "vfo.h" +#include "button_text.h" +#include "store.h" + +static GtkWidget *parent_window=NULL; + +static GtkWidget *dialog=NULL; + +static gboolean store_close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { + if(dialog!=NULL) { + gtk_widget_destroy(dialog); + dialog=NULL; + sub_menu=NULL; + } + return TRUE; +} + +static gboolean store_select_cb (GtkWidget *widget, gpointer data) { + int index = (int) data; + fprintf(stderr,"STORE BUTTON PUSHED=%d\n",index); + char workstr[16]; + + /* Update mem[data] with current info */ + + mem[index].frequency = vfo[active_receiver->id].frequency; // Store current frequency + mem[index].mode = vfo[active_receiver->id].mode; + mem[index].filter=vfo[active_receiver->id].filter; + + fprintf(stderr,"store_select_cb: Index=%d\n",index); + fprintf(stderr,"store_select_cb: freqA=%11lld\n",mem[index].frequency); + fprintf(stderr,"store_select_cb: mode=%d\n",mem[index].mode); + fprintf(stderr,"store_select_cb: filter=%d\n",mem[index].filter); + + // Save in the file now.. + memSaveState(); +} + +static gboolean recall_select_cb (GtkWidget *widget, gpointer data) { + int index = (int) data; + long long new_freq; + + //new_freq = mem[index].frequency; + strcpy(mem[index].title,"Active"); + new_freq = mem[index].frequency; + fprintf(stderr,"recall_select_cb: Index=%d\n",index); + fprintf(stderr,"recall_select_cb: freqA=%11lld\n",new_freq); + fprintf(stderr,"recall_select_cb: mode=%d\n",mem[index].mode); + fprintf(stderr,"recall_select_cb: filter=%d\n",mem[index].filter); + + //set_band(mem[index].frequency,index); + vfo[active_receiver->id].frequency = new_freq; + vfo[active_receiver->id].band = get_band_from_frequency(new_freq); + vfo[active_receiver->id].mode = mem[index].mode; + vfo[active_receiver->id].filter = mem[index].filter; + vfo_band_changed(vfo[active_receiver->id].band); +} + +void store_menu(GtkWidget *parent) { + GtkWidget *b; + int i; + BAND *band; + char label_str[20]; + + parent_window=parent; + + dialog=gtk_dialog_new(); + gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window)); + gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE); + + GdkRGBA color; + color.red = 1.0; + color.green = 1.0; + color.blue = 1.0; + color.alpha = 1.0; + gtk_widget_override_background_color(dialog,GTK_STATE_FLAG_NORMAL,&color); + + GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + + GtkWidget *grid=gtk_grid_new(); + + gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE); + gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE); + gtk_grid_set_column_spacing (GTK_GRID(grid),5); + gtk_grid_set_row_spacing (GTK_GRID(grid),5); + + GtkWidget *close_b=gtk_button_new_with_label("Close Store"); + g_signal_connect (close_b, "pressed", G_CALLBACK(store_close_cb), NULL); + gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1); + + for(i=0;iid].rit+=(i*rit_increment); + if(vfo[active_receiver->id].rit>1000) vfo[active_receiver->id].rit=1000; + if(vfo[active_receiver->id].rit<-1000) vfo[active_receiver->id].rit=-1000; + vfo_update(NULL); + return TRUE; } void update_toolbar_labels() { - if(toolbar_dialog_buttons) { - if(function) { - gtk_button_set_label(GTK_BUTTON(sim_mox),"Tune"); - gtk_button_set_label(GTK_BUTTON(sim_s1),"RIT+"); - gtk_button_set_label(GTK_BUTTON(sim_s2),"RIT-"); - gtk_button_set_label(GTK_BUTTON(sim_s3),"CTUN"); - gtk_button_set_label(GTK_BUTTON(sim_s4),""); - gtk_button_set_label(GTK_BUTTON(sim_s5),""); - gtk_button_set_label(GTK_BUTTON(sim_s6),"Lock"); - } else { - gtk_button_set_label(GTK_BUTTON(sim_mox),"Mox"); - gtk_button_set_label(GTK_BUTTON(sim_s1),"Band"); - gtk_button_set_label(GTK_BUTTON(sim_s2),"BStack"); - gtk_button_set_label(GTK_BUTTON(sim_s3),"Mode"); - gtk_button_set_label(GTK_BUTTON(sim_s4),"Filter"); - gtk_button_set_label(GTK_BUTTON(sim_s5),"Noise"); - gtk_button_set_label(GTK_BUTTON(sim_s6),"AGC"); + switch(function) { + case 0: + gtk_button_set_label(GTK_BUTTON(sim_mox),"Mox"); + gtk_button_set_label(GTK_BUTTON(sim_s1),"Band"); + gtk_button_set_label(GTK_BUTTON(sim_s2),"BStack"); + gtk_button_set_label(GTK_BUTTON(sim_s3),"Mode"); + gtk_button_set_label(GTK_BUTTON(sim_s4),"Filter"); + gtk_button_set_label(GTK_BUTTON(sim_s5),"Noise"); + gtk_button_set_label(GTK_BUTTON(sim_s6),"AGC"); + set_button_text_color(sim_s1,"black"); + set_button_text_color(sim_s2,"black"); + break; + + case 1: + gtk_button_set_label(GTK_BUTTON(sim_mox),"Mox"); + gtk_button_set_label(GTK_BUTTON(sim_s1),"Lock"); + gtk_button_set_label(GTK_BUTTON(sim_s2),"CTUN"); + gtk_button_set_label(GTK_BUTTON(sim_s3),"A>B"); + gtk_button_set_label(GTK_BUTTON(sim_s4),"AB"); + gtk_button_set_label(GTK_BUTTON(sim_s6),"Split"); + break; + case 2: + gtk_button_set_label(GTK_BUTTON(sim_mox),"Mox"); + gtk_button_set_label(GTK_BUTTON(sim_s1),"Freq"); + gtk_button_set_label(GTK_BUTTON(sim_s2),"Mem"); + gtk_button_set_label(GTK_BUTTON(sim_s3),"Vox"); + gtk_button_set_label(GTK_BUTTON(sim_s4),"RIT+"); + gtk_button_set_label(GTK_BUTTON(sim_s5),"RIT-"); + gtk_button_set_label(GTK_BUTTON(sim_s6),""); + if(full_tune) { + set_button_text_color(sim_s1,"red"); } - } else { - if(function) { - gtk_button_set_label(GTK_BUTTON(sim_s1),"Band v"); - gtk_button_set_label(GTK_BUTTON(sim_s2),"BStack v"); - gtk_button_set_label(GTK_BUTTON(sim_s3),"Mode v"); - gtk_button_set_label(GTK_BUTTON(sim_s4),"Filter v"); - gtk_button_set_label(GTK_BUTTON(sim_s5),"Noise v"); - gtk_button_set_label(GTK_BUTTON(sim_s6),"AGC v"); + if(memory_tune) { + set_button_text_color(sim_s2,"red"); + } + break; + case 3: gtk_button_set_label(GTK_BUTTON(sim_mox),"Tune"); - } else { - gtk_button_set_label(GTK_BUTTON(sim_s1),"Band ^"); - gtk_button_set_label(GTK_BUTTON(sim_s2),"BStack ^"); - gtk_button_set_label(GTK_BUTTON(sim_s3),"Mode ^"); - gtk_button_set_label(GTK_BUTTON(sim_s4),"Filter ^"); - gtk_button_set_label(GTK_BUTTON(sim_s5),"Noise ^"); - gtk_button_set_label(GTK_BUTTON(sim_s6),"AGC ^"); - gtk_button_set_label(GTK_BUTTON(sim_mox),"Mox"); - } + if(OCtune!=0 && OCfull_tune_time!=0) { + gtk_button_set_label(GTK_BUTTON(sim_s1),"Full"); + } else { + gtk_button_set_label(GTK_BUTTON(sim_s1),""); + } + if(OCtune!=0 && OCmemory_tune_time!=0) { + gtk_button_set_label(GTK_BUTTON(sim_s2),"Memory"); + } else { + gtk_button_set_label(GTK_BUTTON(sim_s2),""); + } + gtk_button_set_label(GTK_BUTTON(sim_s3),""); + gtk_button_set_label(GTK_BUTTON(sim_s4),""); + gtk_button_set_label(GTK_BUTTON(sim_s5),""); + gtk_button_set_label(GTK_BUTTON(sim_s6),""); + if(full_tune) { + set_button_text_color(sim_s1,"red"); + } + if(memory_tune) { + set_button_text_color(sim_s2,"red"); + } + break; } } @@ -127,539 +152,83 @@ static void close_cb(GtkWidget *widget, gpointer data) { last_dialog=NULL; } -/* -static void band_select_cb(GtkWidget *widget, gpointer data) { - GtkWidget *label; - int b=(int)data; - BANDSTACK_ENTRY *entry; - if(b==band_get_current()) { - entry=bandstack_entry_next(); - } else { - BAND* band=band_set_current(b); - entry=bandstack_entry_get_current(); - set_button_text_color(last_band,"black"); - last_band=widget; - set_button_text_color(last_band,"orange"); - } - setMode(entry->mode); - FILTER* band_filters=filters[entry->mode]; - FILTER* band_filter=&band_filters[entry->filter]; - setFilter(band_filter->low,band_filter->high); - setFrequency(entry->frequencyA); - - BAND *band=band_get_current_band(); - set_alex_rx_antenna(band->alexRxAntenna); - set_alex_tx_antenna(band->alexTxAntenna); - set_alex_attenuation(band->alexAttenuation); - - vfo_update(NULL); - - setFrequency(entry->frequencyA); - - calcDriveLevel(); - calcTuneDriveLevel(); -} -*/ - void band_cb(GtkWidget *widget, gpointer data) { start_band(); -/* - BAND* band; - int show=1; - if(last_dialog!=NULL) { - if(strcmp(gtk_window_get_title(GTK_WINDOW(last_dialog)),"Band")==0) { - show=0; - } - gtk_widget_destroy(last_dialog); - last_dialog=NULL; - } - if(show) { - GtkWidget *dialog=gtk_dialog_new_with_buttons("Band",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); - GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog)); - GtkWidget *grid=gtk_grid_new(); - gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE); - gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE); - GtkWidget *b; - int i; - for(i=0;i=band70 && i<=band3400) { - continue; - } - } -#endif - - band=(BAND*)band_get_band(i); - if(strlen(band->title)>0) { - GtkWidget *b=gtk_button_new_with_label(band->title); - set_button_text_color(b,"black"); - //gtk_widget_override_font(b, pango_font_description_from_string("Arial 20")); - if(i==band_get_current()) { - set_button_text_color(b,"orange"); - last_band=b; - } - gtk_widget_show(b); - gtk_grid_attach(GTK_GRID(grid),b,i%5,i/5,1,1); - g_signal_connect(b,"clicked",G_CALLBACK(band_select_cb),(gpointer *)i); - } - } - - gtk_container_add(GTK_CONTAINER(content),grid); - - GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK); - //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 20")); - g_signal_connect(close_button,"clicked",G_CALLBACK(close_cb),(gpointer *)NULL); - - gtk_widget_show_all(dialog); - last_dialog=dialog; - int result=gtk_dialog_run(GTK_DIALOG(dialog)); - } -*/ -} - -/* -static void bandstack_select_cb(GtkWidget *widget, gpointer data) { - int b=(int)data; - BAND *band=band_get_current_band(); - BANDSTACK *bandstack=band->bandstack; - - bandstack->current_entry=b; - - set_button_text_color(last_bandstack,"black"); - last_bandstack=widget; - set_button_text_color(last_bandstack,"orange"); - - BANDSTACK_ENTRY *entry; - entry=&(bandstack->entry[b]); - - setMode(entry->mode); - FILTER* band_filters=filters[entry->mode]; - FILTER* band_filter=&band_filters[entry->filter]; - setFilter(band_filter->low,band_filter->high); - setFrequency(entry->frequencyA); - - set_alex_rx_antenna(band->alexRxAntenna); - set_alex_tx_antenna(band->alexTxAntenna); - set_alex_attenuation(band->alexAttenuation); - - vfo_update(NULL); - - setFrequency(entry->frequencyA); } -*/ void bandstack_cb(GtkWidget *widget, gpointer data) { start_bandstack(); -/* - int show=1; - if(last_dialog!=NULL) { - if(strcmp(gtk_window_get_title(GTK_WINDOW(last_dialog)),"Band Stack")==0) { - show=0; - } - gtk_widget_destroy(last_dialog); - last_dialog=NULL; - } - if(show) { - GtkWidget *dialog=gtk_dialog_new_with_buttons("Band Stack",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); - GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog)); - GtkWidget *grid=gtk_grid_new(); - gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE); - gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE); - GtkWidget *b; - int i; - - char label[16]; - - BAND *band=band_get_current_band(); - BANDSTACK *bandstack=band->bandstack; - - for(i=0;ientries;i++) { - BANDSTACK_ENTRY *entry=&bandstack->entry[i]; - sprintf(label,"%lld %s",entry->frequencyA,mode_string[entry->mode]); - GtkWidget *b=gtk_button_new_with_label(label); - set_button_text_color(b,"black"); - //gtk_widget_override_font(b, pango_font_description_from_string("Arial 20")); - if(i==bandstack->current_entry) { - set_button_text_color(b,"orange"); - last_bandstack=b; - } - gtk_widget_show(b); - gtk_grid_attach(GTK_GRID(grid),b,i/5,i%5,1,1); - g_signal_connect(b,"clicked",G_CALLBACK(bandstack_select_cb),(gpointer *)i); - } - - gtk_container_add(GTK_CONTAINER(content),grid); - - GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK); - //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 20")); - g_signal_connect(close_button,"clicked",G_CALLBACK(close_cb),(gpointer *)NULL); - gtk_widget_show_all(dialog); - - last_dialog=dialog; - - int result=gtk_dialog_run(GTK_DIALOG(dialog)); - } -*/ } -void function_cb(GtkWidget *widget, gpointer data) { - function=function==1?0:1; - update_toolbar_labels(); - vfo_update(NULL); -} - -/* -static void mode_select_cb(GtkWidget *widget, gpointer data) { - int m=(int)data; - BANDSTACK_ENTRY *entry; - entry=bandstack_entry_get_current(); - entry->mode=m; - setMode(entry->mode); - FILTER* band_filters=filters[entry->mode]; - FILTER* band_filter=&band_filters[entry->filter]; - setFilter(band_filter->low,band_filter->high); - set_button_text_color(last_mode,"black"); - last_mode=widget; - set_button_text_color(last_mode,"orange"); - vfo_update(NULL); -} -*/ - void mode_cb(GtkWidget *widget, gpointer data) { start_mode(); -/* - int show=1; - if(last_dialog!=NULL) { - if(strcmp(gtk_window_get_title(GTK_WINDOW(last_dialog)),"Mode")==0) { - show=0; - } - gtk_widget_destroy(last_dialog); - last_dialog=NULL; - } - if(show) { - BANDSTACK_ENTRY *entry=bandstack_entry_get_current(); - GtkWidget *dialog=gtk_dialog_new_with_buttons("Mode",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); - GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog)); - GtkWidget *grid=gtk_grid_new(); - gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE); - gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE); - - GtkWidget *b; - int i; - for(i=0;imode) { - set_button_text_color(b,"orange"); - last_mode=b; - } else { - set_button_text_color(b,"black"); - } - //gtk_widget_override_font(b, pango_font_description_from_string("Arial 20")); - gtk_widget_show(b); - gtk_grid_attach(GTK_GRID(grid),b,i%5,i/5,1,1); - g_signal_connect(b,"pressed",G_CALLBACK(mode_select_cb),(gpointer *)i); - } - gtk_container_add(GTK_CONTAINER(content),grid); - GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK); - //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 20")); - g_signal_connect(close_button,"clicked",G_CALLBACK(close_cb),(gpointer *)NULL); - gtk_widget_show_all(dialog); - - last_dialog=dialog; - int result=gtk_dialog_run(GTK_DIALOG(dialog)); - - } -*/ } -/* -static void filter_select_cb(GtkWidget *widget, gpointer data) { - int f=(int)data; - BANDSTACK_ENTRY *entry; - entry=bandstack_entry_get_current(); - entry->filter=f; - FILTER* band_filters=filters[entry->mode]; - FILTER* band_filter=&band_filters[entry->filter]; - setFilter(band_filter->low,band_filter->high); - set_button_text_color(last_filter,"black"); - last_filter=widget; - set_button_text_color(last_filter,"orange"); - vfo_update(NULL); -} -*/ void filter_cb(GtkWidget *widget, gpointer data) { start_filter(); -/* - int show=1; - if(last_dialog!=NULL) { - if(strcmp(gtk_window_get_title(GTK_WINDOW(last_dialog)),"Filter")==0) { - show=0; - } - gtk_widget_destroy(last_dialog); - last_dialog=NULL; - } - if(show) { - BANDSTACK_ENTRY *entry=bandstack_entry_get_current(); - FILTER* band_filters=filters[entry->mode]; - GtkWidget *dialog=gtk_dialog_new_with_buttons("Filter",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); - GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog)); - GtkWidget *grid=gtk_grid_new(); - gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE); - gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE); - - GtkWidget *b; - int i; - for(i=0;ifilter) { - set_button_text_color(b,"orange"); - last_filter=b; - } else { - set_button_text_color(b,"black"); - } - gtk_widget_show(b); - gtk_grid_attach(GTK_GRID(grid),b,i%5,i/5,1,1); - g_signal_connect(b,"pressed",G_CALLBACK(filter_select_cb),(gpointer *)i); - } - gtk_container_add(GTK_CONTAINER(content),grid); - GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK); - //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 20")); - g_signal_connect(close_button,"clicked",G_CALLBACK(close_cb),(gpointer *)NULL); - gtk_widget_show_all(dialog); - - last_dialog=dialog; - int result=gtk_dialog_run(GTK_DIALOG(dialog)); - - } -*/ } -/* -static void agc_select_cb(GtkWidget *widget, gpointer data) { - agc=(int)data; - wdsp_set_agc(CHANNEL_RX0, agc); - //SetRXAAGCMode(CHANNEL_RX0, agc); +void agc_cb(GtkWidget *widget, gpointer data) { + start_agc(); } -*/ -/* -static void update_noise() { - SetRXAANRRun(CHANNEL_RX0, nr); - SetRXAEMNRRun(CHANNEL_RX0, nr2); - SetRXAANFRun(CHANNEL_RX0, anf); - SetRXASNBARun(CHANNEL_RX0, snb); - vfo_update(NULL); +void noise_cb(GtkWidget *widget, gpointer data) { + start_noise(); } -static void nr_none_cb(GtkWidget *widget, gpointer data) { - nr=0; - nr2=0; - nb=0; - nb2=0; - anf=0; - snb=0; - update_noise(); +void ctun_cb (GtkWidget *widget, gpointer data) { + int id=active_receiver->id; + vfo[id].ctun=vfo[id].ctun==1?0:1; + if(!vfo[id].ctun) { + vfo[id].offset=0; + } + vfo[id].ctun_frequency=vfo[id].frequency; + set_offset(active_receiver,vfo[id].offset); + vfo_update(NULL); } -static void nr_cb(GtkWidget *widget, gpointer data) { - nr=1; - nr2=0; - nb=0; - nb2=0; - anf=0; - snb=0; - update_noise(); +static void atob_cb (GtkWidget *widget, gpointer data) { + vfo_a_to_b(); } -static void nr2_cb(GtkWidget *widget, gpointer data) { - nr=0; - nr2=1; - nb=0; - nb2=0; - anf=0; - snb=0; - update_noise(); +static void btoa_cb (GtkWidget *widget, gpointer data) { + vfo_b_to_a(); } -static void nb_cb(GtkWidget *widget, gpointer data) { - nr=0; - nr2=0; - nb=1; - nb2=0; - anf=0; - snb=0; - update_noise(); +static void aswapb_cb (GtkWidget *widget, gpointer data) { + vfo_a_swap_b(); } -static void nb2_cb(GtkWidget *widget, gpointer data) { - nr=0; - nr2=0; - nb=0; - nb2=1; - anf=0; - snb=0; - update_noise(); +static void split_cb (GtkWidget *widget, gpointer data) { + split=split==1?0:1; + if(split) { + tx_set_mode(transmitter,vfo[VFO_B].mode); + } else { + tx_set_mode(transmitter,vfo[VFO_A].mode); + } + vfo_update(NULL); } -static void anf_cb(GtkWidget *widget, gpointer data) { - nr=0; - nr2=0; - nb=0; - nb2=0; - anf=1; - snb=0; - update_noise(); +static void rit_cb(GtkWidget *widget, gpointer data) { + int i=(int)data; + vfo[active_receiver->id].rit+=i*rit_increment; + if(vfo[active_receiver->id].rit>1000) vfo[active_receiver->id].rit=1000; + if(vfo[active_receiver->id].rit<-1000) vfo[active_receiver->id].rit=-1000; + vfo_update(NULL); + rit_timer=g_timeout_add(200,rit_timer_cb,(void *)i); } -static void snb_cb(GtkWidget *widget, gpointer data) { - nr=0; - nr2=0; - nb=0; - nb2=0; - anf=0; - snb=1; - update_noise(); +static void freq_cb(GtkWidget *widget, gpointer data) { + start_vfo(); } -*/ -void agc_cb(GtkWidget *widget, gpointer data) { - start_agc(); -/* - int show=1; - if(last_dialog!=NULL) { - if(strcmp(gtk_window_get_title(GTK_WINDOW(last_dialog)),"AGC")==0) { - show=0; - } - gtk_widget_destroy(last_dialog); - last_dialog=NULL; - } - if(show) { - GtkWidget *dialog=gtk_dialog_new_with_buttons("AGC",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); - - GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog)); - GtkWidget *grid=gtk_grid_new(); - - gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE); - gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE); - - GtkWidget *b_off=gtk_radio_button_new_with_label(NULL,"Off"); - //gtk_widget_override_font(b_off, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_off), agc==AGC_OFF); - gtk_widget_show(b_off); - gtk_grid_attach(GTK_GRID(grid),b_off,0,0,2,1); - g_signal_connect(b_off,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_OFF); - - GtkWidget *b_long=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_off),"Long"); - //gtk_widget_override_font(b_long, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_long), agc==AGC_LONG); - gtk_widget_show(b_long); - gtk_grid_attach(GTK_GRID(grid),b_long,0,1,2,1); - g_signal_connect(b_long,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_LONG); - - GtkWidget *b_slow=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_long),"Slow"); - //gtk_widget_override_font(b_slow, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_slow), agc==AGC_SLOW); - gtk_widget_show(b_slow); - gtk_grid_attach(GTK_GRID(grid),b_slow,0,2,2,1); - g_signal_connect(b_slow,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_SLOW); - - GtkWidget *b_medium=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_slow),"Medium"); - //gtk_widget_override_font(b_medium, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_medium), agc==AGC_MEDIUM); - gtk_widget_show(b_medium); - gtk_grid_attach(GTK_GRID(grid),b_medium,0,3,2,1); - g_signal_connect(b_medium,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_MEDIUM); - - GtkWidget *b_fast=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_medium),"Fast"); - //gtk_widget_override_font(b_fast, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_fast), agc==AGC_FAST); - gtk_widget_show(b_fast); - gtk_grid_attach(GTK_GRID(grid),b_fast,0,4,2,1); - g_signal_connect(b_fast,"pressed",G_CALLBACK(agc_select_cb),(gpointer *)AGC_FAST); - - gtk_container_add(GTK_CONTAINER(content),grid); - - GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK); - //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 16")); - g_signal_connect(close_button,"clicked",G_CALLBACK(close_cb),(gpointer *)NULL); - gtk_widget_show_all(dialog); - last_dialog=dialog; - int result=gtk_dialog_run(GTK_DIALOG(dialog)); - } -*/ +static void mem_cb(GtkWidget *widget, gpointer data) { + start_store(); } -void noise_cb(GtkWidget *widget, gpointer data) { - start_noise(); -/* - int show=1; - if(last_dialog!=NULL) { - if(strcmp(gtk_window_get_title(GTK_WINDOW(last_dialog)),"Noise")==0) { - show=0; - } - gtk_widget_destroy(last_dialog); - last_dialog=NULL; - } - if(show) { - GtkWidget *dialog=gtk_dialog_new_with_buttons("Noise",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); - - GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog)); - GtkWidget *grid=gtk_grid_new(); - - gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE); - gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE); - - GtkWidget *b_nr_none=gtk_radio_button_new_with_label(NULL,"None"); - //gtk_widget_override_font(b_none, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr_none), nr_none==1); - gtk_widget_show(b_nr_none); - gtk_grid_attach(GTK_GRID(grid),b_nr_none,0,0,2,1); - g_signal_connect(b_nr_none,"pressed",G_CALLBACK(nr_none_cb),NULL); - - GtkWidget *b_nr=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_nr_none),"NR"); - //gtk_widget_override_font(b_nr, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr), nr==1); - gtk_widget_show(b_nr); - gtk_grid_attach(GTK_GRID(grid),b_nr,0,1,2,1); - g_signal_connect(b_nr,"pressed",G_CALLBACK(nr_cb),NULL); - - GtkWidget *b_nr2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_nr),"NR2"); - //gtk_widget_override_font(b_nr2, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr2), nr2==1); - gtk_widget_show(b_nr2); - gtk_grid_attach(GTK_GRID(grid),b_nr2,0,2,2,1); - g_signal_connect(b_nr2,"pressed",G_CALLBACK(nr2_cb),NULL); - - GtkWidget *b_anf=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_nr2),"ANF"); - //gtk_widget_override_font(b_anf, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_anf), anf==1); - gtk_widget_show(b_anf); - gtk_grid_attach(GTK_GRID(grid),b_anf,0,3,2,1); - g_signal_connect(b_anf,"pressed",G_CALLBACK(anf_cb),NULL); - - GtkWidget *b_snb=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_anf),"SNB"); - //gtk_widget_override_font(b_snb, pango_font_description_from_string("Arial 16")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_snb), snb==1); - gtk_widget_show(b_snb); - gtk_grid_attach(GTK_GRID(grid),b_snb,0,4,2,1); - g_signal_connect(b_snb,"pressed",G_CALLBACK(snb_cb),NULL); - - gtk_container_add(GTK_CONTAINER(content),grid); - - GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK); - //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 16")); - g_signal_connect(close_button,"clicked",G_CALLBACK(close_cb),(gpointer *)NULL); - gtk_widget_show_all(dialog); - - last_dialog=dialog; - - int result=gtk_dialog_run(GTK_DIALOG(dialog)); - - } -*/ +static void vox_cb(GtkWidget *widget, gpointer data) { + vox=vox==1?0:1; + vfo_update(NULL); } static void stop() { @@ -954,37 +523,12 @@ static void cw_cb(GtkWidget *widget, gpointer data) { int result=gtk_dialog_run(GTK_DIALOG(dialog)); } -/* -static void adc_cb(GtkWidget *widget, gpointer data) { - int adc0=adc[0]; - adc[0]=adc[1]; - adc[1]=adc0; - - char label[16]; - gtk_grid_remove_row(GTK_GRID(toolbar_top_1),0); - - sprintf(label,"RX0=%d",adc[0]); - GtkWidget *rx0=gtk_label_new(label); - //gtk_widget_override_font(rx0, pango_font_description_from_string("Arial 16")); - gtk_widget_show(rx0); - gtk_grid_attach(GTK_GRID(toolbar_top_1),rx0,0,0,1,1); - - sprintf(label,"RX1=%d",adc[1]); - GtkWidget *rx1=gtk_label_new(label); - //gtk_widget_override_font(rx1, pango_font_description_from_string("Arial 16")); - gtk_widget_show(rx1); - gtk_grid_attach(GTK_GRID(toolbar_top_1),rx1,1,0,1,1); -} -*/ - void lock_cb(GtkWidget *widget, gpointer data) { locked=locked==1?0:1; vfo_update(NULL); } void mox_cb(GtkWidget *widget, gpointer data) { - - if(getTune()==1) { setTune(0); } @@ -996,17 +540,31 @@ void mox_cb(GtkWidget *widget, gpointer data) { } else if(canTransmit() || tx_out_of_band) { setMox(1); } - vfo_update(NULL); + g_idle_add(vfo_update,NULL); +} + +int mox_update(void *data) { + if(getTune()==1) { + setTune(0); + } + setMox((int)data); + return 0; } int ptt_update(void *data) { + int mode; + if(split) { + mode=vfo[1].mode; + } else { + mode=vfo[0].mode; + } if(protocol==NEW_PROTOCOL || (mode!=modeCWU && mode!=modeCWL)) { mox_cb(NULL,NULL); } return 0; } -static void tune_cb(GtkWidget *widget, gpointer data) { +void tune_cb(GtkWidget *widget, gpointer data) { if(getMox()==1) { setMox(0); } @@ -1018,270 +576,217 @@ static void tune_cb(GtkWidget *widget, gpointer data) { vfo_update(NULL); } -static gboolean rit_timer_cb(gpointer data) { - if((int)data==1) { - rit+=rit_increment; - } else { - rit-=rit_increment; - } - if(rit>1000) rit=1000; - if(rit<-1000) rit=-1000; - vfo_update(NULL); - return TRUE; -} - void sim_s1_pressed_cb(GtkWidget *widget, gpointer data) { - if(function) { - rit+=rit_increment; - if(rit>1000) rit=1000; - vfo_update(NULL); - rit_timer=g_timeout_add(200,rit_timer_cb,(gpointer)1); - } else { - BAND* band; - BANDSTACK_ENTRY *entry; - if(toolbar_dialog_buttons) { + switch(function) { + case 0: band_cb(widget,data); - } else { - int b=band_get_current(); - if(function) { - b--; - if(b<0) { - b=BANDS-1; - } -#ifdef LIMESDR - if(protocol!=LIMESDR_PROTOCOL) { - if(b==band3400) { - b=band6; - } - } -#endif + break; + case 1: + lock_cb(widget,data); + break; + case 2: + freq_cb(widget,data); + break; + case 3: + full_tune=full_tune==1?0:1; + if(full_tune) { + set_button_text_color(sim_s2,"black"); + set_button_text_color(sim_s1,"red"); } else { - b++; - if(b>=BANDS) { - b=0; - } -#ifdef LIMESDR - if(protocol!=LIMESDR_PROTOCOL) { - if(b==band70) { - b=bandGen; - } - } -#endif + set_button_text_color(sim_s1,"black"); } - band=band_set_current(b); - entry=bandstack_entry_get_current(); - - setFrequency(entry->frequencyA); - setMode(entry->mode); - FILTER* band_filters=filters[entry->mode]; - FILTER* band_filter=&band_filters[entry->filter]; - setFilter(band_filter->low,band_filter->high); - - band=band_get_current_band(); - set_alex_rx_antenna(band->alexRxAntenna); - set_alex_tx_antenna(band->alexTxAntenna); - set_alex_attenuation(band->alexAttenuation); - vfo_update(NULL); - - calcDriveLevel(); - calcTuneDriveLevel(); - } + break; } } void sim_s1_released_cb(GtkWidget *widget, gpointer data) { - if(function) { - g_source_remove(rit_timer); + switch(function) { + case 0: + break; + case 1: + break; + case 2: + break; + case 3: + break; } } void sim_s2_pressed_cb(GtkWidget *widget, gpointer data) { - if(function) { - rit-=rit_increment; - if(rit<-1000) rit=-1000; - vfo_update(NULL); - rit_timer=g_timeout_add(200,rit_timer_cb,(gpointer)-1); - } else { - BANDSTACK_ENTRY *entry; - if(toolbar_dialog_buttons) { + switch(function) { + case 0: bandstack_cb(widget,data); - } else { - if(function) { - entry=bandstack_entry_previous(); + break; + case 1: + ctun_cb(widget,data); + break; + case 2: + mem_cb(widget,data); + break; + case 3: + memory_tune=memory_tune==1?0:1; + if(memory_tune) { + set_button_text_color(sim_s1,"black"); + set_button_text_color(sim_s2,"red"); } else { - entry=bandstack_entry_next(); + set_button_text_color(sim_s2,"black"); } - setFrequency(entry->frequencyA); - setMode(entry->mode); - FILTER* band_filters=filters[entry->mode]; - FILTER* band_filter=&band_filters[entry->filter]; - setFilter(band_filter->low,band_filter->high); - vfo_update(NULL); - } + break; } } void sim_s2_released_cb(GtkWidget *widget, gpointer data) { - if(function) { - g_source_remove(rit_timer); + switch(function) { + case 0: + break; + case 1: + break; + case 2: + break; + case 3: + break; } } -void sim_s3_cb(GtkWidget *widget, gpointer data) { - if(function) { - ctun=ctun==1?0:1; - if(!ctun) { - ddsOffset=0; - wdsp_set_offset(ddsOffset); - } - vfo_update(NULL); - } else { - BAND* band; - BANDSTACK_ENTRY *entry; - - if(toolbar_dialog_buttons) { +void sim_s3_pressed_cb(GtkWidget *widget, gpointer data) { + switch(function) { + case 0: mode_cb(widget,data); - } else { - band=band_get_current_band(); - entry=bandstack_entry_get_current(); - if(function) { - entry->mode--; - if(entry->mode<0) { - entry->mode=MODES-1; - } - } else { - entry->mode++; - if(entry->mode>=MODES) { - entry->mode=0; - } - } - setMode(entry->mode); - - FILTER* band_filters=filters[entry->mode]; - FILTER* band_filter=&band_filters[entry->filter]; - setFilter(band_filter->low,band_filter->high); - - vfo_update(NULL); - } + break; + case 1: + // A>B + atob_cb(widget,data); + break; + case 2: + vox_cb(widget,data); + break; + case 3: + break; } } -void sim_s4_cb(GtkWidget *widget, gpointer data) { - BAND* band; - BANDSTACK_ENTRY *entry; +void sim_s3_released_cb(GtkWidget *widget, gpointer data) { + switch(function) { + case 0: + break; + case 1: + break; + case 2: + break; + case 3: + break; + } +} - if(toolbar_dialog_buttons) { - if(function) { - } else { +void sim_s4_pressed_cb(GtkWidget *widget, gpointer data) { + switch(function) { + case 0: filter_cb(widget,data); - } - } else { - band=band_get_current_band(); - entry=bandstack_entry_get_current(); - // note order of filter reversed (largest first) - if(function) { - entry->filter++; - if(entry->filter>=FILTERS) { - entry->filter=0; - } - } else { - entry->filter--; - if(entry->filter<0) { - entry->filter=FILTERS-1; - } - } - - FILTER* band_filters=filters[entry->mode]; - FILTER* band_filter=&band_filters[entry->filter]; - setFilter(band_filter->low,band_filter->high); - - vfo_update(NULL); + break; + case 1: + // AB + aswapb_cb(widget,data); + break; + case 2: + rit_cb(widget,(void *)-1); + break; + case 3: + break; } } -void sim_s6_cb(GtkWidget *widget, gpointer data) { - if(toolbar_dialog_buttons) { - if(function) { - lock_cb(widget,data); - } else { +void sim_s5_released_cb(GtkWidget *widget, gpointer data) { + switch(function) { + case 0: + break; + case 1: + break; + case 2: + g_source_remove(rit_timer); + break; + case 3: + break; + } +} + +void sim_s6_pressed_cb(GtkWidget *widget, gpointer data) { + switch(function) { + case 0: agc_cb(widget,data); - } - } else { - if(function) { - agc--; - if(agc<0) { - agc=3; - } - } else { - agc++; - if(agc>=4) { - agc=0; - } - } - SetRXAAGCMode(CHANNEL_RX0, agc); - vfo_update(NULL); + break; + case 1: + split_cb(widget,data); + break; + case 2: + break; + case 3: + break; + } +} + +void sim_s6_released_cb(GtkWidget *widget, gpointer data) { + switch(function) { + case 0: + break; + case 1: + break; + case 2: + break; + case 3: + break; } } void sim_mox_cb(GtkWidget *widget, gpointer data) { - if(function) { - tune_cb((GtkWidget *)NULL, (gpointer)NULL); - } else { - mox_cb((GtkWidget *)NULL, (gpointer)NULL); + switch(function) { + case 0: + case 1: + case 2: + mox_cb((GtkWidget *)NULL, (gpointer)NULL); + break; + case 3: + tune_cb((GtkWidget *)NULL, (gpointer)NULL); + break; } - //vfo_update(NULL); } void sim_function_cb(GtkWidget *widget, gpointer data) { - function=function==1?0:1; + function++; + if(function>MAX_FUNCTION) { + function=0; + } update_toolbar_labels(); vfo_update(NULL); } @@ -1314,46 +819,50 @@ GtkWidget *toolbar_init(int my_width, int my_height, GtkWidget* parent) { g_signal_connect(G_OBJECT(sim_mox),"clicked",G_CALLBACK(sim_mox_cb),NULL); gtk_grid_attach(GTK_GRID(toolbar),sim_mox,0,0,4,1); - sim_s1=gtk_button_new_with_label("Band ^"); + sim_s1=gtk_button_new_with_label("Band"); gtk_widget_set_size_request (sim_s1, button_width, 0); //gtk_widget_override_font(sim_s1, pango_font_description_from_string("Arial 16")); g_signal_connect(G_OBJECT(sim_s1),"pressed",G_CALLBACK(sim_s1_pressed_cb),NULL); g_signal_connect(G_OBJECT(sim_s1),"released",G_CALLBACK(sim_s1_released_cb),NULL); gtk_grid_attach(GTK_GRID(toolbar),sim_s1,4,0,4,1); - sim_s2=gtk_button_new_with_label("BStack ^"); + sim_s2=gtk_button_new_with_label("BStack"); gtk_widget_set_size_request (sim_s2, button_width, 0); //gtk_widget_override_font(sim_s2, pango_font_description_from_string("Arial 16")); g_signal_connect(G_OBJECT(sim_s2),"pressed",G_CALLBACK(sim_s2_pressed_cb),NULL); g_signal_connect(G_OBJECT(sim_s2),"released",G_CALLBACK(sim_s2_released_cb),NULL); gtk_grid_attach(GTK_GRID(toolbar),sim_s2,8,0,4,1); - sim_s3=gtk_button_new_with_label("Mode ^"); + sim_s3=gtk_button_new_with_label("Mode"); //gtk_widget_override_font(sim_s3, pango_font_description_from_string("Arial 16")); - g_signal_connect(G_OBJECT(sim_s3),"clicked",G_CALLBACK(sim_s3_cb),NULL); + g_signal_connect(G_OBJECT(sim_s3),"pressed",G_CALLBACK(sim_s3_pressed_cb),NULL); + g_signal_connect(G_OBJECT(sim_s3),"released",G_CALLBACK(sim_s3_released_cb),NULL); gtk_grid_attach(GTK_GRID(toolbar),sim_s3,12,0,4,1); - sim_s4=gtk_button_new_with_label("Filter ^"); + sim_s4=gtk_button_new_with_label("Filter"); //gtk_widget_override_font(sim_s4, pango_font_description_from_string("Arial 16")); - g_signal_connect(G_OBJECT(sim_s4),"clicked",G_CALLBACK(sim_s4_cb),NULL); + g_signal_connect(G_OBJECT(sim_s4),"pressed",G_CALLBACK(sim_s4_pressed_cb),NULL); + g_signal_connect(G_OBJECT(sim_s4),"released",G_CALLBACK(sim_s4_released_cb),NULL); gtk_grid_attach(GTK_GRID(toolbar),sim_s4,16,0,4,1); - sim_s5=gtk_button_new_with_label("Noise ^"); + sim_s5=gtk_button_new_with_label("Noise"); //gtk_widget_override_font(sim_s5, pango_font_description_from_string("Arial 16")); - g_signal_connect(G_OBJECT(sim_s5),"clicked",G_CALLBACK(sim_s5_cb),NULL); + g_signal_connect(G_OBJECT(sim_s5),"pressed",G_CALLBACK(sim_s5_pressed_cb),NULL); + g_signal_connect(G_OBJECT(sim_s5),"released",G_CALLBACK(sim_s5_released_cb),NULL); gtk_grid_attach(GTK_GRID(toolbar),sim_s5,20,0,4,1); - sim_s6=gtk_button_new_with_label("AGC ^"); + sim_s6=gtk_button_new_with_label("AGC"); //gtk_widget_override_font(sim_s6, pango_font_description_from_string("Arial 16")); - g_signal_connect(G_OBJECT(sim_s6),"clicked",G_CALLBACK(sim_s6_cb),NULL); + g_signal_connect(G_OBJECT(sim_s6),"pressed",G_CALLBACK(sim_s6_pressed_cb),NULL); + g_signal_connect(G_OBJECT(sim_s6),"released",G_CALLBACK(sim_s6_released_cb),NULL); gtk_grid_attach(GTK_GRID(toolbar),sim_s6,24,0,4,1); sim_function=gtk_button_new_with_label("Function"); //gtk_widget_override_font(sim_function, pango_font_description_from_string("Arial 16")); - g_signal_connect(G_OBJECT(sim_function),"clicked",G_CALLBACK(function_cb),NULL); + g_signal_connect(G_OBJECT(sim_function),"clicked",G_CALLBACK(sim_function_cb),NULL); gtk_grid_attach(GTK_GRID(toolbar),sim_function,28,0,4,1); - update_toolbar_labels(); + //update_toolbar_labels(); last_dialog=NULL; diff --git a/toolbar.h b/toolbar.h index 54cbf33..203b606 100644 --- a/toolbar.h +++ b/toolbar.h @@ -22,20 +22,25 @@ extern int function; + void update_toolbar_labels(); int ptt_update(void *data); -void lock_cb(GtkWidget *widget, gpointer data); - +int mox_update(void *data); +void tune_cb(GtkWidget *widget, gpointer data); void sim_mox_cb(GtkWidget *widget, gpointer data); void sim_s1_pressed_cb(GtkWidget *widget, gpointer data); void sim_s1_released_cb(GtkWidget *widget, gpointer data); void sim_s2_pressed_cb(GtkWidget *widget, gpointer data); void sim_s2_released_cb(GtkWidget *widget, gpointer data); -void sim_s3_cb(GtkWidget *widget, gpointer data); -void sim_s4_cb(GtkWidget *widget, gpointer data); -void sim_s5_cb(GtkWidget *widget, gpointer data); -void sim_s6_cb(GtkWidget *widget, gpointer data); +void sim_s3_pressed_cb(GtkWidget *widget, gpointer data); +void sim_s3_released_cb(GtkWidget *widget, gpointer data); +void sim_s4_pressed_cb(GtkWidget *widget, gpointer data); +void sim_s4_released_cb(GtkWidget *widget, gpointer data); +void sim_s5_pressed_cb(GtkWidget *widget, gpointer data); +void sim_s5_released_cb(GtkWidget *widget, gpointer data); +void sim_s6_pressed_cb(GtkWidget *widget, gpointer data); +void sim_s6_released_cb(GtkWidget *widget, gpointer data); void sim_function_cb(GtkWidget *widget, gpointer data); GtkWidget *toolbar_init(int my_width, int my_height, GtkWidget* parent); diff --git a/transmitter.c b/transmitter.c new file mode 100644 index 0000000..f4a7812 --- /dev/null +++ b/transmitter.c @@ -0,0 +1,626 @@ +/* Copyright (C) +* 2017 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#include +#include +#include +#include + +#include + +#include "alex.h" +#include "band.h" +#include "bandstack.h" +#include "channel.h" +#include "main.h" +#include "meter.h" +#include "mode.h" +#include "property.h" +#include "radio.h" +#include "vfo.h" +#include "meter.h" +#include "tx_panadapter.h" +#include "waterfall.h" +#include "transmitter.h" + +#define min(x,y) (xpanadapter, tx->width, height); +} + +void transmitter_save_state(TRANSMITTER *tx) { + char name[128]; + char value[128]; + + sprintf(name,"transmitter.%d.fps",tx->id); + sprintf(value,"%d",tx->fps); + setProperty(name,value); + sprintf(name,"transmitter.%d.filter_low",tx->id); + sprintf(value,"%d",tx->filter_low); + setProperty(name,value); + sprintf(name,"transmitter.%d.filter_high",tx->id); + sprintf(value,"%d",tx->filter_high); + setProperty(name,value); + sprintf(name,"transmitter.%d.alex_antenna",tx->id); + sprintf(value,"%d",tx->alex_antenna); + setProperty(name,value); + + sprintf(name,"transmitter.%d.local_microphone",tx->id); + sprintf(value,"%d",tx->local_microphone); + setProperty(name,value); + sprintf(name,"transmitter.%d.input_device",tx->id); + sprintf(value,"%d",tx->input_device); + setProperty(name,value); + +} + +void transmitter_restore_state(TRANSMITTER *tx) { + char name[128]; + char *value; + + sprintf(name,"transmitter.%d.fps",tx->id); + value=getProperty(name); + if(value) tx->fps=atoi(value); + sprintf(name,"transmitter.%d.filter_low",tx->id); + value=getProperty(name); + if(value) tx->filter_low=atoi(value); + sprintf(name,"transmitter.%d.filter_high",tx->id); + value=getProperty(name); + if(value) tx->filter_high=atoi(value); + sprintf(name,"transmitter.%d.alex_antenna",tx->id); + value=getProperty(name); + if(value) tx->alex_antenna=atoi(value); + + sprintf(name,"transmitter.%d.local_microphone",tx->id); + value=getProperty(name); + if(value) tx->local_microphone=atoi(value); + sprintf(name,"transmitter.%d.input_device",tx->id); + value=getProperty(name); + if(value) tx->input_device=atoi(value); +} + +static gint update_display(gpointer data) { + TRANSMITTER *tx=(TRANSMITTER *)data; + int rc; + double fwd; + double rev; + double exciter; + + if(tx->displaying) { + GetPixels(tx->id,0,tx->pixel_samples,&rc); + if(rc) { + tx_panadapter_update(tx); + } else { +//fprintf(stderr,"tx: update_display: GetPixels: id=%d returned %d\n",tx->id,rc); + } + + double alc=GetTXAMeter(tx->id, alc); + double constant1=3.3; + double constant2=0.095; + + if(protocol==ORIGINAL_PROTOCOL) { + switch(device) { + case DEVICE_METIS: + constant1=3.3; + constant2=0.09; + break; + case DEVICE_HERMES: + constant1=3.3; + constant2=0.095; + break; + case DEVICE_ANGELIA: + constant1=3.3; + constant2=0.095; + break; + case DEVICE_ORION: + constant1=5.0; + constant2=0.108; + break; + case DEVICE_ORION2: + constant1=5.0; + constant2=0.108; + break; + case DEVICE_HERMES_LITE: + break; + } + + int power=alex_forward_power; + if(power==0) { + power=exciter_power; + } + double v1; + v1=((double)power/4095.0)*constant1; + fwd=(v1*v1)/constant2; + + power=exciter_power; + v1=((double)power/4095.0)*constant1; + exciter=(v1*v1)/constant2; + + rev=0.0; + if(alex_forward_power!=0) { + power=alex_reverse_power; + v1=((double)power/4095.0)*constant1; + rev=(v1*v1)/constant2; + } + } else { + switch(device) { + case NEW_DEVICE_ATLAS: + constant1=3.3; + constant2=0.09; + break; + case NEW_DEVICE_HERMES: + constant1=3.3; + constant2=0.09; + break; + case NEW_DEVICE_HERMES2: + constant1=3.3; + constant2=0.095; + break; + case NEW_DEVICE_ANGELIA: + constant1=3.3; + constant2=0.095; + break; + case NEW_DEVICE_ORION: + constant1=5.0; + constant2=0.108; + break; + case NEW_DEVICE_ORION2: + constant1=5.0; + constant2=0.108; + break; + case NEW_DEVICE_HERMES_LITE: + constant1=3.3; + constant2=0.09; + break; + } + + int power=alex_forward_power; + if(power==0) { + power=exciter_power; + } + double v1; + v1=((double)power/4095.0)*constant1; + fwd=(v1*v1)/constant2; + + power=exciter_power; + v1=((double)power/4095.0)*constant1; + exciter=(v1*v1)/constant2; + + rev=0.0; + if(alex_forward_power!=0) { + power=alex_reverse_power; + v1=((double)power/4095.0)*constant1; + rev=(v1*v1)/constant2; + } + } + + meter_update(POWER,fwd,rev,exciter,alc); + + return TRUE; // keep going + } + return FALSE; // no more timer events +} + + +static void init_analyzer(TRANSMITTER *tx) { + int flp[] = {0}; + double keep_time = 0.1; + int n_pixout=1; + int spur_elimination_ffts = 1; + int data_type = 1; + int fft_size = 8192; + int window_type = 4; + double kaiser_pi = 14.0; + int overlap = 2048; + int clip = 0; + int span_clip_l = 0; + int span_clip_h = 0; + int pixels=tx->pixels; + int stitches = 1; + int avm = 0; + double tau = 0.001 * 120.0; + int calibration_data_set = 0; + double span_min_freq = 0.0; + double span_max_freq = 0.0; + + int max_w = fft_size + (int) min(keep_time * (double) tx->fps, keep_time * (double) fft_size * (double) tx->fps); + + overlap = (int)max(0.0, ceil(fft_size - (double)tx->mic_sample_rate / (double)tx->fps)); + + fprintf(stderr,"SetAnalyzer id=%d buffer_size=%d overlap=%d\n",tx->id,tx->output_samples,overlap); + + + SetAnalyzer(tx->id, + n_pixout, + spur_elimination_ffts, //number of LO frequencies = number of ffts used in elimination + data_type, //0 for real input data (I only); 1 for complex input data (I & Q) + flp, //vector with one elt for each LO frequency, 1 if high-side LO, 0 otherwise + fft_size, //size of the fft, i.e., number of input samples + tx->output_samples, //number of samples transferred for each OpenBuffer()/CloseBuffer() + window_type, //integer specifying which window function to use + kaiser_pi, //PiAlpha parameter for Kaiser window + overlap, //number of samples each fft (other than the first) is to re-use from the previous + clip, //number of fft output bins to be clipped from EACH side of each sub-span + span_clip_l, //number of bins to clip from low end of entire span + span_clip_h, //number of bins to clip from high end of entire span + pixels, //number of pixel values to return. may be either <= or > number of bins + stitches, //number of sub-spans to concatenate to form a complete span + calibration_data_set, //identifier of which set of calibration data to use + span_min_freq, //frequency at first pixel value8192 + span_max_freq, //frequency at last pixel value + max_w //max samples to hold in input ring buffers + ); + +} + +#ifdef INCLUDED +void transmitter_change_sample_rate(TRANSMITTER *tx,int sample_rate) { + SetChannelState(tx->id,0,1); + tx->mic_sample_rate=sample_rate; + tx->output_samples=tx->buffer_size/(tx->mic_sample_rate/48000); + free(tx->mic_input_buffer); + tx->mic_input_buffer=malloc(sizeof(double)*2*tx->buffer_size); + init_analyzer(tx); +fprintf(stderr,"transmitter_change_sample_rate: id=%d rate=%d output_samples=%d\n",tx->id, tx->mic_sample_rate, tx->output_samples); + SetChannelState(tx->id,1,0); +} +#endif + +static void create_visual(TRANSMITTER *tx) { + + fprintf(stderr,"transmitter: create_visual: id=%d\n",tx->id); + + tx->panel=gtk_fixed_new(); + gtk_widget_set_size_request (tx->panel, tx->width, tx->height); + + if(tx->display_panadapter) { + tx_panadapter_init(tx,tx->width,tx->height); + gtk_fixed_put(GTK_FIXED(tx->panel),tx->panadapter,0,0); + } + +} + +TRANSMITTER *create_transmitter(int id, int buffer_size, int fft_size, int fps, int width, int height) { + int rc; + + TRANSMITTER *tx=malloc(sizeof(TRANSMITTER)); + tx->id=id; + tx->buffer_size=buffer_size; + tx->fft_size=fft_size; + tx->fps=fps; + if(protocol==ORIGINAL_PROTOCOL) { + tx->mic_sample_rate=48000; +// tx->mic_sample_rate=receiver[0]->sample_rate; + tx->mic_dsp_rate=48000; + tx->iq_output_rate=48000; +// tx->output_samples=tx->buffer_size/(tx->mic_sample_rate/48000); + tx->output_samples=tx->buffer_size; + tx->pixels=width; + } else { + tx->mic_sample_rate=48000; + tx->mic_dsp_rate=48000; + tx->iq_output_rate=192000; + tx->output_samples=tx->buffer_size*4; + tx->pixels=width*4; // to allow 192k to 48k conversion + } + + tx->width=width; + tx->height=height; + tx->display_panadapter=1; + tx->display_waterfall=0; + + tx->panadapter_high=20; + tx->panadapter_low=-80; + + tx->displaying=0; + + tx->alex_antenna=ALEX_TX_ANTENNA_1; + +fprintf(stderr,"create_transmitter: id=%d buffer_size=%d mic_sample_rate=%d mic_dsp_rate=%d iq_output_rate=%d output_samples=%d fps=%d\n",tx->id, tx->buffer_size, tx->mic_sample_rate, tx->mic_dsp_rate, tx->iq_output_rate, tx->output_samples,tx->fps); + + tx->filter_low=tx_filter_low; + tx->filter_high=tx_filter_high; + + transmitter_restore_state(tx); + + if(split) { + tx->mode=vfo[VFO_B].mode; + } else { + tx->mode=vfo[VFO_A].mode; + } + + // allocate buffers +fprintf(stderr,"transmitter: allocate buffers: mic_input_buffer=%d iq_output_buffer=%d pixels=%d\n",tx->buffer_size,tx->output_samples,tx->pixels); + tx->mic_input_buffer=malloc(sizeof(double)*2*tx->buffer_size); + tx->iq_output_buffer=malloc(sizeof(double)*2*tx->output_samples); + tx->samples=0; + tx->pixel_samples=malloc(sizeof(float)*tx->pixels); + + fprintf(stderr,"create_transmitter: OpenChannel id=%d buffer_size=%d fft_size=%d sample_rate=%d dspRate=%d outputRate=%d\n", + tx->id, + tx->buffer_size, + tx->fft_size, + tx->mic_sample_rate, + tx->mic_dsp_rate, + tx->iq_output_rate); + + OpenChannel(tx->id, + tx->buffer_size, + tx->fft_size, + tx->mic_sample_rate, + tx->mic_dsp_rate, + tx->iq_output_rate, + 1, // transmit + 0, // run + 0.010, 0.025, 0.0, 0.010, 0); + + SetTXAMode(tx->id, tx->mode); + tx_set_filter(tx,tx_filter_low,tx_filter_high); + SetTXABandpassWindow(tx->id, 1); + SetTXABandpassRun(tx->id, 1); + + SetTXAFMDeviation(tx->id,(double)deviation); + SetTXAFMEmphPosition(tx->id,pre_emphasize); + + SetTXACFIRRun(tx->id, protocol==NEW_PROTOCOL?1:0); // turned on if new protocol + if(enable_tx_equalizer) { + SetTXAGrphEQ(tx->id, tx_equalizer); + SetTXAEQRun(tx->id, 1); + } else { + SetTXAEQRun(tx->id, 0); + } + SetTXACTCSSRun(tx->id, 0); + SetTXAAMSQRun(tx->id, 0); + SetTXACompressorRun(tx->id, 0); + SetTXAosctrlRun(tx->id, 0); + + SetTXAALCAttack(tx->id, 1); + SetTXAALCDecay(tx->id, 10); + SetTXAALCSt(tx->id, tx_alc); + + SetTXALevelerAttack(tx->id, 1); + SetTXALevelerDecay(tx->id, 500); + SetTXALevelerTop(tx->id, 5.0); + SetTXALevelerSt(tx->id, tx_leveler); + + SetTXAPreGenMode(tx->id, 0); + SetTXAPreGenToneMag(tx->id, 0.0); + SetTXAPreGenToneFreq(tx->id, 0.0); + SetTXAPreGenRun(tx->id, 0); + + SetTXAPostGenMode(tx->id, 0); + SetTXAPostGenToneMag(tx->id, tone_level); + SetTXAPostGenToneFreq(tx->id, 0.0); + SetTXAPostGenRun(tx->id, 0); + + double gain=pow(10.0, mic_gain / 20.0); + SetTXAPanelGain1(tx->id,gain); + SetTXAPanelRun(tx->id, 1); + + XCreateAnalyzer(tx->id, &rc, 262144, 1, 1, ""); + if (rc != 0) { + fprintf(stderr, "XCreateAnalyzer id=%d failed: %d\n",tx->id,rc); + } else { + init_analyzer(tx); + } + + create_visual(tx); + + return tx; +} + +void tx_set_mode(TRANSMITTER* tx,int mode) { + if(tx!=NULL) { + tx->mode=mode; + SetTXAMode(tx->id, tx->mode); + tx_set_filter(tx,tx_filter_low,tx_filter_high); + } +} + +void tx_set_filter(TRANSMITTER *tx,int low,int high) { + int mode; + if(split) { + mode=vfo[1].mode; + } else { + mode=vfo[0].mode; + } + switch(mode) { + case modeLSB: + case modeCWL: + case modeDIGL: + tx->filter_low=-high; + tx->filter_high=-low; + break; + case modeUSB: + case modeCWU: + case modeDIGU: + tx->filter_low=low; + tx->filter_high=high; + break; + case modeDSB: + case modeAM: + case modeSAM: + tx->filter_low=-high; + tx->filter_high=high; + break; + case modeFMN: + if(deviation==2500) { + tx->filter_low=-4000; + tx->filter_high=4000; + } else { + tx->filter_low=-8000; + tx->filter_high=8000; + } + break; + case modeDRM: + tx->filter_low=7000; + tx->filter_high=17000; + break; + } + + double fl=tx->filter_low; + double fh=tx->filter_high; + + if(split) { + fl+=vfo[VFO_B].offset; + fh+=vfo[VFO_B].offset; + } else { + fl+=vfo[VFO_A].offset; + fh+=vfo[VFO_A].offset; + } + SetTXABandpassFreqs(tx->id, fl,fh); +} + +void tx_set_pre_emphasize(TRANSMITTER *tx,int state) { + SetTXAFMEmphPosition(tx->id,state); +} + +static void full_tx_buffer(TRANSMITTER *tx) { + long isample; + long qsample; + double gain; + int j; + int error; + int mode; + + switch(protocol) { + case ORIGINAL_PROTOCOL: + gain=32767.0; // 16 bit + break; + case NEW_PROTOCOL: + gain=8388607.0; // 24 bit + break; + } + + if(vox_enabled || vox_setting) { + if(split) { + mode=vfo[1].mode; + } else { + mode=vfo[0].mode; + } + switch(mode) { + case modeLSB: + case modeUSB: + case modeDSB: + case modeFMN: + case modeAM: + case modeSAM: +#ifdef FREEDV + case modeFREEDV: +#endif + update_vox(tx); + break; + } + } + + fexchange0(tx->id, tx->mic_input_buffer, tx->iq_output_buffer, &error); + if(error!=0) { + fprintf(stderr,"full_tx_buffer: id=%d fexchange0: error=%d\n",tx->id,error); + } + + if(tx->displaying) { + Spectrum0(1, tx->id, 0, 0, tx->iq_output_buffer); + } + +if(isTransmitting()) { +#ifdef FREEDV + int mode; + if(split) { + mode=vfo[VFO_B].mode; + } else { + mode=vfo[VFO_A].mode; + } + + if(mode==modeFREEDV) { + gain=8388607.0; + } +#endif + + if(radio->device==NEW_DEVICE_ATLAS && atlas_penelope) { + if(tune) { + gain=gain*tune_drive; + } else { + gain=gain*(double)drive; + } + } + + for(j=0;joutput_samples;j++) { + isample=(long)(tx->iq_output_buffer[j*2]*gain); + qsample=(long)(tx->iq_output_buffer[(j*2)+1]*gain); + switch(protocol) { + case ORIGINAL_PROTOCOL: + old_protocol_iq_samples(isample,qsample); + break; + case NEW_PROTOCOL: + new_protocol_iq_samples(isample,qsample); + break; + } + } + } + +} + +void add_mic_sample(TRANSMITTER *tx,short mic_sample) { + double mic_sample_double; + int mode; + long sample; + + if(split) { + mode=vfo[1].mode; + } else { + mode=vfo[0].mode; + } + + switch(mode) { +#ifdef FREEDV + case modeFREEDV: + break; +#endif + default: + if(mode==modeCWL || mode==modeCWU || tune) { + mic_sample_double=0.0; + } else { + sample=mic_sample<<16; + mic_sample_double=(1.0 / 2147483648.0) * (double)(sample); + } +//fprintf(stderr,"add_mic_sample: id=%d sample=%f (%d,%ld)\n",tx->id,mic_sample_double,mic_sample,sample); + tx->mic_input_buffer[tx->samples*2]=mic_sample_double; + tx->mic_input_buffer[(tx->samples*2)+1]=mic_sample_double; + tx->samples++; + if(tx->samples==tx->buffer_size) { + full_tx_buffer(tx); + tx->samples=0; + } + break; + } +} + +void tx_set_displaying(TRANSMITTER *tx,int state) { + tx->displaying=state; + if(state) { +fprintf(stderr,"start tx display update timer: %d\n", 1000/tx->fps); + tx->update_timer_id=gdk_threads_add_timeout_full(G_PRIORITY_HIGH_IDLE,1000/tx->fps, update_display, tx, NULL); + } +} + diff --git a/transmitter.h b/transmitter.h new file mode 100644 index 0000000..fec966d --- /dev/null +++ b/transmitter.h @@ -0,0 +1,86 @@ +/* Copyright (C) +* 2017 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#ifndef _TRANSMITTER_H +#define _TRANSMITTER_H + +#include + +#define AUDIO_BUFFER_SIZE 260 + +typedef struct _transmitter { + int id; + int fps; + int displaying; + int mic_sample_rate; + int mic_dsp_rate; + int iq_output_rate; + int buffer_size; + int fft_size; + int pixels; + int samples; + int output_samples; + double *mic_input_buffer; + double *iq_output_buffer; + + float *pixel_samples; + int display_panadapter; + int display_waterfall; + gint update_timer_id; + + int mode; + int filter_low; + int filter_high; + +/* + long long frequency; + long long display_frequency; + long long dds_frequency; + long long dds_offset; +*/ + int alex_antenna; + + int width; + int height; + + GtkWidget *panel; + GtkWidget *panadapter; + + int panadapter_low; + int panadapter_high; + + cairo_surface_t *panadapter_surface; + + int local_microphone; + int input_device; + +} TRANSMITTER; + +extern TRANSMITTER *create_transmitter(int id, int buffer_size, int fft_size, int fps, int width, int height); + +void reconfigure_transmitter(TRANSMITTER *tx,int height); + +extern void tx_set_mode(TRANSMITTER* tx,int m); +extern void tx_set_filter(TRANSMITTER *tx,int low,int high); +extern void tx_set_pre_emphasize(TRANSMITTER *tx,int state); + +extern void add_mic_sample(TRANSMITTER *tx,short mic_sample); + +extern void transmitter_save_state(TRANSMITTER *tx); +#endif diff --git a/tx_menu.c b/tx_menu.c new file mode 100644 index 0000000..e6bdfd3 --- /dev/null +++ b/tx_menu.c @@ -0,0 +1,223 @@ +/* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#include +#include +#include + +#include "audio.h" +#include "new_menu.h" +#include "radio.h" +#include "sliders.h" +#include "transmitter.h" + +static GtkWidget *parent_window=NULL; + +static GtkWidget *dialog=NULL; + +static GtkWidget *last_filter; + +static GtkWidget *linein_b; +static GtkWidget *micboost_b; + +static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { + if(dialog!=NULL) { + gtk_widget_destroy(dialog); + dialog=NULL; + sub_menu=NULL; + } + return TRUE; +} + +static void tx_spin_low_cb (GtkWidget *widget, gpointer data) { + tx_filter_low=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); + tx_set_filter(transmitter,tx_filter_low,tx_filter_high); +} + +static void tx_spin_high_cb (GtkWidget *widget, gpointer data) { + tx_filter_high=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); + tx_set_filter(transmitter,tx_filter_low,tx_filter_high); +} + +static void micboost_cb(GtkWidget *widget, gpointer data) { + mic_boost=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)); +} + +static void linein_cb(GtkWidget *widget, gpointer data) { + mic_linein=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)); + g_idle_add(linein_changed,NULL); +} + +static void local_microphone_cb(GtkWidget *widget, gpointer data) { + if(gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) { + if(audio_open_input()==0) { + transmitter->local_microphone=1; + gtk_widget_hide(linein_b); + gtk_widget_hide(micboost_b); + } else { + transmitter->local_microphone=0; + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE); + gtk_widget_show(linein_b); + gtk_widget_show(micboost_b); + } + } else { + if(transmitter->local_microphone) { + transmitter->local_microphone=0; + audio_close_input(); + gtk_widget_show(linein_b); + gtk_widget_show(micboost_b); + } + } +} + +static void local_input_changed_cb(GtkWidget *widget, gpointer data) { + transmitter->input_device=(int)(long)data; + if(transmitter->local_microphone) { + audio_close_input(); + if(audio_open_input()==0) { + transmitter->local_microphone=1; + } else { + transmitter->local_microphone=0; + } + } +} + +static gboolean emp_cb (GtkWidget *widget, gpointer data) { + pre_emphasize=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)); + tx_set_pre_emphasize(transmitter,pre_emphasize); +} + +void tx_menu(GtkWidget *parent) { + GtkWidget *b; + int i; + + parent_window=parent; + + dialog=gtk_dialog_new(); + gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window)); + gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE); + + GdkRGBA color; + color.red = 1.0; + color.green = 1.0; + color.blue = 1.0; + color.alpha = 1.0; + gtk_widget_override_background_color(dialog,GTK_STATE_FLAG_NORMAL,&color); + + GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + + GtkWidget *grid=gtk_grid_new(); + + gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE); + gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE); + gtk_grid_set_column_spacing (GTK_GRID(grid),5); + gtk_grid_set_row_spacing (GTK_GRID(grid),5); + + int row=0; + int col=0; + + 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,col,row,1,1); + + col++; + + GtkWidget *label=gtk_label_new("Transmit"); + gtk_grid_attach(GTK_GRID(grid),label,col,row,1,1); + + row++; + col=0; + + + label=gtk_label_new("Filter: "); + gtk_grid_attach(GTK_GRID(grid),label,col,row,1,1); + + col++; + + GtkWidget *tx_spin_low=gtk_spin_button_new_with_range(0.0,8000.0,1.0); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(tx_spin_low),(double)tx_filter_low); + gtk_grid_attach(GTK_GRID(grid),tx_spin_low,col,row,1,1); + g_signal_connect(tx_spin_low,"value-changed",G_CALLBACK(tx_spin_low_cb),NULL); + + col++; + + GtkWidget *tx_spin_high=gtk_spin_button_new_with_range(0.0,8000.0,1.0); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(tx_spin_high),(double)tx_filter_high); + gtk_grid_attach(GTK_GRID(grid),tx_spin_high,col,row,1,1); + g_signal_connect(tx_spin_high,"value-changed",G_CALLBACK(tx_spin_high_cb),NULL); + + row++; + col=0; + + + if(protocol==ORIGINAL_PROTOCOL || protocol==NEW_PROTOCOL) { + linein_b=gtk_check_button_new_with_label("Mic Line In (ACC connector)"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (linein_b), mic_linein); + gtk_grid_attach(GTK_GRID(grid),linein_b,col,++row,3,1); + g_signal_connect(linein_b,"toggled",G_CALLBACK(linein_cb),NULL); + + micboost_b=gtk_check_button_new_with_label("Mic Boost (radio only)"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (micboost_b), mic_boost); + gtk_grid_attach(GTK_GRID(grid),micboost_b,col,++row,3,1); + g_signal_connect(micboost_b,"toggled",G_CALLBACK(micboost_cb),NULL); + + } + + if(n_input_devices>0) { + GtkWidget *local_microphone_b=gtk_check_button_new_with_label("Local Microphone Input"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (local_microphone_b), transmitter->local_microphone); + gtk_widget_show(local_microphone_b); + gtk_grid_attach(GTK_GRID(grid),local_microphone_b,col,++row,3,1); + g_signal_connect(local_microphone_b,"toggled",G_CALLBACK(local_microphone_cb),NULL); + + if(transmitter->input_device==-1) transmitter->input_device=0; + + for(i=0;iinput_device==i); + gtk_widget_show(input); + gtk_grid_attach(GTK_GRID(grid),input,col,++row,3,1); + g_signal_connect(input,"pressed",G_CALLBACK(local_input_changed_cb),(gpointer *)i); + } + } + + row++; + col=0; + + GtkWidget *emp_b=gtk_check_button_new_with_label("FM TX Pre-emphasize before limiting"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (emp_b), pre_emphasize); + gtk_widget_show(emp_b); + gtk_grid_attach(GTK_GRID(grid),emp_b,col,row,3,1); + g_signal_connect(emp_b,"toggled",G_CALLBACK(emp_cb),NULL); + + gtk_container_add(GTK_CONTAINER(content),grid); + + sub_menu=dialog; + + gtk_widget_show_all(dialog); + + if(transmitter->local_microphone && (protocol==ORIGINAL_PROTOCOL || protocol==NEW_PROTOCOL)) { + gtk_widget_hide(linein_b); + gtk_widget_hide(micboost_b); + } + +} diff --git a/tx_menu.h b/tx_menu.h new file mode 100644 index 0000000..40408c6 --- /dev/null +++ b/tx_menu.h @@ -0,0 +1,18 @@ +/* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +void tx_menu(GtkWidget *parent); diff --git a/tx_panadapter.c b/tx_panadapter.c new file mode 100644 index 0000000..0ec9fcf --- /dev/null +++ b/tx_panadapter.c @@ -0,0 +1,420 @@ +/* Copyright (C) +* 2015 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "agc.h" +#include "band.h" +#include "channel.h" +#include "discovered.h" +#include "radio.h" +#include "receiver.h" +#include "transmitter.h" +#include "tx_panadapter.h" +#include "vfo.h" +#include "mode.h" +#ifdef FREEDV +#include "freedv.h" +#endif +#include "gpio.h" + + +static gint last_x; +static gboolean has_moved=FALSE; +static gboolean pressed=FALSE; + +static gfloat hz_per_pixel; +static gfloat filter_left; +static gfloat filter_right; + + +/* Create a new surface of the appropriate size to store our scribbles */ +static gboolean +panadapter_configure_event_cb (GtkWidget *widget, + GdkEventConfigure *event, + gpointer data) +{ + TRANSMITTER *tx=(TRANSMITTER *)data; + int display_width=gtk_widget_get_allocated_width (tx->panadapter); + int display_height=gtk_widget_get_allocated_height (tx->panadapter); + + if (tx->panadapter_surface) + cairo_surface_destroy (tx->panadapter_surface); + + tx->panadapter_surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget), + CAIRO_CONTENT_COLOR, + display_width, + display_height); + + cairo_t *cr=cairo_create(tx->panadapter_surface); + cairo_set_source_rgb(cr, 0, 0, 0); + cairo_paint(cr); + cairo_destroy(cr); + return TRUE; +} + +/* Redraw the screen from the surface. Note that the ::draw + * signal receives a ready-to-be-used cairo_t that is already + * clipped to only draw the exposed areas of the widget + */ +static gboolean +panadapter_draw_cb (GtkWidget *widget, + cairo_t *cr, + gpointer data) +{ + TRANSMITTER *tx=(TRANSMITTER *)data; + if(tx->panadapter_surface) { + cairo_set_source_surface (cr, tx->panadapter_surface, 0, 0); + cairo_paint (cr); + } + return TRUE; +} + +static gboolean +panadapter_button_press_event_cb (GtkWidget *widget, + GdkEventButton *event, + gpointer data) +{ + int x=(int)event->x; + if (event->button == 1) { + last_x=(int)event->x; + has_moved=FALSE; + pressed=TRUE; + } + return TRUE; +} + +static gboolean +panadapter_button_release_event_cb (GtkWidget *widget, + GdkEventButton *event, + gpointer data) +{ + TRANSMITTER *tx=(TRANSMITTER *)data; + int display_width=gtk_widget_get_allocated_width (tx->panadapter); + int display_height=gtk_widget_get_allocated_height (tx->panadapter); + + if(pressed) { + int x=(int)event->x; + if (event->button == 1) { + if(has_moved) { + // drag + vfo_move((long long)((float)(x-last_x)*hz_per_pixel)); + } else { + // move to this frequency + vfo_move_to((long long)((float)(x-(display_width/2))*hz_per_pixel)); + } + last_x=x; + pressed=FALSE; + } + } + return TRUE; +} + +static gboolean +panadapter_motion_notify_event_cb (GtkWidget *widget, + GdkEventMotion *event, + gpointer data) +{ + int x, y; + GdkModifierType state; + gdk_window_get_device_position (event->window, + event->device, + &x, + &y, + &state); + if((state & GDK_BUTTON1_MASK == GDK_BUTTON1_MASK) || pressed) { + int moved=last_x-x; + vfo_move((long long)((float)moved*hz_per_pixel)); + last_x=x; + has_moved=TRUE; + } + + return TRUE; +} + +static gboolean +panadapter_scroll_event_cb (GtkWidget *widget, + GdkEventScroll *event, + gpointer data) +{ + if(event->direction==GDK_SCROLL_UP) { + vfo_move(step); + } else { + vfo_move(-step); + } +} + +void tx_panadapter_update(TRANSMITTER *tx) { + int i; + int result; + float *samples; + float saved_max; + float saved_min; + gfloat saved_hz_per_pixel; + cairo_text_extents_t extents; + + int display_width=gtk_widget_get_allocated_width (tx->panadapter); + int display_height=gtk_widget_get_allocated_height (tx->panadapter); + + samples=tx->pixel_samples; + //hz_per_pixel=(double)tx->output_rate/(double)display_width; + hz_per_pixel=48000.0/(double)display_width; + + //clear_panadater_surface(); + cairo_t *cr; + cr = cairo_create (tx->panadapter_surface); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_paint (cr); + + // filter + cairo_set_source_rgb (cr, 0.25, 0.25, 0.25); + filter_left=(double)display_width/2.0+((double)tx->filter_low/hz_per_pixel); + filter_right=(double)display_width/2.0+((double)tx->filter_high/hz_per_pixel); + cairo_rectangle(cr, filter_left, 0.0, filter_right-filter_left, (double)display_height); + cairo_fill(cr); + + // plot the levels + int V = (int)(tx->panadapter_high - tx->panadapter_low); + int numSteps = V / 20; + for (i = 1; i < numSteps; i++) { + int num = tx->panadapter_high - i * 20; + int y = (int)floor((tx->panadapter_high - num) * display_height / V); + cairo_set_source_rgb (cr, 0, 1, 1); + cairo_set_line_width(cr, 1.0); + cairo_move_to(cr,0.0,(double)y); + cairo_line_to(cr,(double)display_width,(double)y); + + cairo_set_source_rgb (cr, 0, 1, 1); + cairo_select_font_face(cr, "FreeMono", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); + cairo_set_font_size(cr, 12); + char v[32]; + sprintf(v,"%d dBm",num); + cairo_move_to(cr, 1, (double)y); + cairo_show_text(cr, v); + cairo_stroke(cr); + } + + // plot frequency markers + long long f; + long long divisor=20000; + long long half=24000LL; //(long long)(tx->output_rate/2); + long long frequency; + if(split) { + frequency=vfo[VFO_B].frequency+vfo[VFO_B].offset; + } else { + frequency=vfo[VFO_A].frequency+vfo[VFO_A].offset; + } + divisor=5000LL; +/* + switch(tx->output_rate) { + case 48000: + divisor=5000L; + break; + case 96000: + case 100000: + divisor=10000L; + break; + case 192000: + divisor=20000L; + break; + case 384000: + divisor=25000L; + break; + case 768000: + divisor=50000L; + break; + case 1048576: + case 1536000: + case 2097152: + divisor=100000L; + break; + } +*/ +//fprintf(stderr,"tx_panadapter_update: frequency=%lld divisor=%lld split=%d\n",frequency,divisor,split); + for(i=0;i 0) { + if ((f % divisor) < (long) hz_per_pixel) { + cairo_set_source_rgb (cr, 0, 1, 1); + cairo_set_line_width(cr, 1.0); + cairo_move_to(cr,(double)i,10.0); + cairo_line_to(cr,(double)i,(double)display_height); + + cairo_set_source_rgb (cr, 0, 1, 1); + cairo_select_font_face(cr, "FreeMono", + CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_BOLD); + cairo_set_font_size(cr, 12); + char v[32]; + sprintf(v,"%0lld.%03lld",f/1000000,(f%1000000)/1000); + //cairo_move_to(cr, (double)i, (double)(display_height-10)); + cairo_text_extents(cr, v, &extents); + cairo_move_to(cr, (double)i-(extents.width/2.0), 10.0); + cairo_show_text(cr, v); + } + } + } + cairo_stroke(cr); + + // band edges + long long min_display=frequency-half; + long long max_display=frequency+half; + int b; + if(split) { + b=vfo[1].band; + } else { + b=vfo[0].band; + } + BAND *band=band_get_band(b); + if(band->frequencyMin!=0LL) { + cairo_set_source_rgb (cr, 1, 0, 0); + cairo_set_line_width(cr, 2.0); + if((min_displayfrequencyMin)&&(max_display>band->frequencyMin)) { + i=(band->frequencyMin-min_display)/(long long)hz_per_pixel; + cairo_move_to(cr,(double)i,0.0); + cairo_line_to(cr,(double)i,(double)display_height); + cairo_stroke(cr); + } + if((min_displayfrequencyMax)&&(max_display>band->frequencyMax)) { + i=(band->frequencyMax-min_display)/(long long)hz_per_pixel; + cairo_move_to(cr,(double)i,0.0); + cairo_line_to(cr,(double)i,(double)display_height); + cairo_stroke(cr); + } + } + + // cursor + cairo_set_source_rgb (cr, 1, 0, 0); + cairo_set_line_width(cr, 1.0); +//fprintf(stderr,"cursor: x=%f\n",(double)(display_width/2.0)+(vfo[tx->id].offset/hz_per_pixel)); + cairo_move_to(cr,(double)(display_width/2.0)+(vfo[tx->id].offset/hz_per_pixel),0.0); + cairo_line_to(cr,(double)(display_width/2.0)+(vfo[tx->id].offset/hz_per_pixel),(double)display_height); + cairo_stroke(cr); + + // signal + double s1,s2; + samples[0]=-200.0; + samples[display_width-1]=-200.0; + + int offset=0; + + if(protocol==NEW_PROTOCOL) { + offset=1200; + } + s1=(double)samples[0+offset]+(double)get_attenuation(); + s1 = floor((tx->panadapter_high - s1) + * (double) display_height + / (tx->panadapter_high - tx->panadapter_low)); + cairo_move_to(cr, 0.0, s1); + for(i=1;ipanadapter_high - s2) + * (double) display_height + / (tx->panadapter_high - tx->panadapter_low)); + cairo_line_to(cr, (double)i, s2); + } + + if(display_filled) { + cairo_close_path (cr); + cairo_set_source_rgba(cr, 1, 1, 1,0.5); + cairo_fill_preserve (cr); + } + cairo_set_source_rgb(cr, 1, 1, 1); + cairo_set_line_width(cr, 1.0); + cairo_stroke(cr); + +#ifdef FREEDV + int mode; + mode=tx->mode; + if(mode==modeFREEDV) { + cairo_set_source_rgb(cr, 1, 0, 0); + cairo_set_font_size(cr, 16); + cairo_text_extents(cr, freedv_text_data, &extents); + cairo_move_to(cr, (double)display_width/2.0-(extents.width/2.0),(double)display_height-2.0); + cairo_show_text(cr, freedv_text_data); + } +#endif + +#ifdef GPIO + cairo_set_source_rgb(cr,1,1,0); + cairo_set_font_size(cr,12); + if(ENABLE_E1_ENCODER) { + cairo_move_to(cr, display_width-100,30); + cairo_show_text(cr, encoder_string[e1_encoder_action]); + } + + if(ENABLE_E2_ENCODER) { + cairo_move_to(cr, display_width-100,50); + cairo_show_text(cr, encoder_string[e2_encoder_action]); + } + + if(ENABLE_E3_ENCODER) { + cairo_move_to(cr, display_width-100,70); + cairo_show_text(cr, encoder_string[e3_encoder_action]); + } +#endif + + cairo_destroy (cr); + gtk_widget_queue_draw (tx->panadapter); + +} + +void tx_panadapter_init(TRANSMITTER *tx, int width,int height) { + + int display_width=width; + int display_height=height; + + tx->panadapter_surface=NULL; + tx->panadapter=gtk_drawing_area_new (); + gtk_widget_set_size_request (tx->panadapter, width, height); + + /* Signals used to handle the backing surface */ + g_signal_connect (tx->panadapter, "draw", + G_CALLBACK (panadapter_draw_cb), tx); + g_signal_connect (tx->panadapter,"configure-event", + G_CALLBACK (panadapter_configure_event_cb), tx); + + /* Event signals */ + g_signal_connect (tx->panadapter, "motion-notify-event", + G_CALLBACK (panadapter_motion_notify_event_cb), tx); + g_signal_connect (tx->panadapter, "button-press-event", + G_CALLBACK (panadapter_button_press_event_cb), tx); + g_signal_connect (tx->panadapter, "button-release-event", + G_CALLBACK (panadapter_button_release_event_cb), tx); + g_signal_connect(tx->panadapter,"scroll_event", + G_CALLBACK(panadapter_scroll_event_cb),tx); + + /* Ask to receive events the drawing area doesn't normally + * subscribe to. In particular, we need to ask for the + * button press and motion notify events that want to handle. + */ + gtk_widget_set_events (tx->panadapter, gtk_widget_get_events (tx->panadapter) + | GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK + | GDK_BUTTON1_MOTION_MASK + | GDK_SCROLL_MASK + | GDK_POINTER_MOTION_MASK + | GDK_POINTER_MOTION_HINT_MASK); + +} diff --git a/tx_panadapter.h b/tx_panadapter.h new file mode 100644 index 0000000..dfa8071 --- /dev/null +++ b/tx_panadapter.h @@ -0,0 +1,28 @@ +/* Copyright (C) +* 2015 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#ifndef _PANADAPTER_H +#define _PANADAPTER_H + +void tx_panadapter_update(TRANSMITTER *tx); + +void tx_panadapter_init(TRANSMITTER *tx,int width,int height); + + +#endif diff --git a/update.h b/update.h index ef4a5ed..444a7ab 100644 --- a/update.h +++ b/update.h @@ -1,4 +1,4 @@ -char new_version[]; +extern char new_version[]; extern int check_update(); extern int load_update(); diff --git a/vfo.c b/vfo.c index 5e4ffda..5bc7397 100644 --- a/vfo.c +++ b/vfo.c @@ -41,19 +41,21 @@ #include "band.h" #include "frequency.h" #include "new_protocol.h" +#include "property.h" #include "radio.h" +#include "receiver.h" #include "vfo.h" #include "channel.h" #include "toolbar.h" #include "wdsp.h" -#include "wdsp_init.h" #include "new_menu.h" +#include "rigctl.h" static GtkWidget *parent_window; static int my_width; static int my_height; -static GtkWidget *vfo; +static GtkWidget *vfo_panel; static cairo_surface_t *vfo_surface = NULL; int steps[]={1,10,25,50,100,250,500,1000,2500,5000,6250,9000,10000,12500,15000,20000,25000,30000,50000,100000,0}; @@ -62,57 +64,399 @@ char *step_labels[]={"1Hz","10Hz","25Hz","50Hz","100Hz","250Hz","500Hz","1kHz"," static GtkWidget* menu=NULL; static GtkWidget* band_menu=NULL; + +static void vfo_save_bandstack() { + BANDSTACK *bandstack=bandstack_get_bandstack(vfo[0].band); + BANDSTACK_ENTRY *entry=&bandstack->entry[vfo[0].bandstack]; + entry->frequency=vfo[0].frequency; + entry->mode=vfo[0].mode; + entry->filter=vfo[0].filter; +} + +void vfo_save_state() { + int i; + char name[80]; + char value[80]; + + vfo_save_bandstack(); + + for(i=0;iid; + + if(id==0) { + vfo_save_bandstack(); + } + if(b==vfo[id].band) { + // same band selected - step to the next band stack + bandstack=bandstack_get_bandstack(b); + vfo[id].bandstack++; + if(vfo[id].bandstack>=bandstack->entries) { + vfo[id].bandstack=0; + } + } else { + // new band - get band stack entry + bandstack=bandstack_get_bandstack(b); + vfo[id].bandstack=bandstack->current_entry; + } + + BAND *band=band_get_band(b); + BANDSTACK_ENTRY *entry=&bandstack->entry[vfo[id].bandstack]; + vfo[id].band=b; + vfo[id].frequency=entry->frequency; + vfo[id].mode=entry->mode; + vfo[id].filter=entry->filter; + vfo[id].lo=band->frequencyLO; + + switch(id) { + case 0: + bandstack->current_entry=vfo[id].bandstack; + receiver_vfo_changed(receiver[id]); + BAND *band=band_get_band(vfo[id].band); + set_alex_rx_antenna(band->alexRxAntenna); + set_alex_tx_antenna(band->alexTxAntenna); + set_alex_attenuation(band->alexAttenuation); + receiver_vfo_changed(receiver[0]); + break; + case 1: + if(receivers==2) { + receiver_vfo_changed(receiver[1]); + } + break; + } + + if(split) { + tx_set_mode(transmitter,vfo[VFO_B].mode); + } else { + tx_set_mode(transmitter,vfo[VFO_A].mode); + } + calcDriveLevel(); + calcTuneDriveLevel(); + vfo_update(NULL); +} + +void vfo_bandstack_changed(int b) { + int id=active_receiver->id; + if(id==0) { + vfo_save_bandstack(); + } + vfo[id].bandstack=b; + + BANDSTACK *bandstack=bandstack_get_bandstack(vfo[id].band); + BANDSTACK_ENTRY *entry=&bandstack->entry[vfo[id].bandstack]; + vfo[id].frequency=entry->frequency; + vfo[id].mode=entry->mode; + vfo[id].filter=entry->filter; + + switch(id) { + case 0: + bandstack->current_entry=vfo[id].bandstack; + receiver_vfo_changed(receiver[id]); + BAND *band=band_get_band(vfo[id].band); + set_alex_rx_antenna(band->alexRxAntenna); + set_alex_tx_antenna(band->alexTxAntenna); + set_alex_attenuation(band->alexAttenuation); + receiver_vfo_changed(receiver[0]); + break; + case 1: + if(receivers==2) { + receiver_vfo_changed(receiver[1]); + } + break; + } + + if(split) { + tx_set_mode(transmitter,vfo[VFO_B].mode); + } else { + tx_set_mode(transmitter,vfo[VFO_A].mode); + } + calcDriveLevel(); + calcTuneDriveLevel(); + vfo_update(NULL); + +} + +void vfo_mode_changed(int m) { + int id=active_receiver->id; + vfo[id].mode=m; + switch(id) { + case 0: + receiver_mode_changed(receiver[0]); + receiver_filter_changed(receiver[0]); + break; + case 1: + if(receivers==2) { + receiver_mode_changed(receiver[1]); + receiver_filter_changed(receiver[1]); + } + break; + } + if(split) { + tx_set_mode(transmitter,vfo[VFO_B].mode); + } else { + tx_set_mode(transmitter,vfo[VFO_A].mode); + } + + vfo_update(NULL); +} + +void vfo_filter_changed(int f) { + int id=active_receiver->id; + vfo[id].filter=f; + switch(id) { + case 0: + receiver_filter_changed(receiver[0]); + break; + case 1: + if(receivers==2) { + receiver_filter_changed(receiver[1]); + } + break; + } + + vfo_update(NULL); +} + +void vfo_a_to_b() { + vfo[VFO_B].band=vfo[VFO_A].band; + vfo[VFO_B].bandstack=vfo[VFO_A].bandstack; + vfo[VFO_B].frequency=vfo[VFO_A].frequency; + vfo[VFO_B].mode=vfo[VFO_A].mode; + vfo[VFO_B].filter=vfo[VFO_A].filter; + vfo[VFO_B].filter=vfo[VFO_A].filter; + vfo[VFO_B].lo=vfo[VFO_A].lo; + vfo[VFO_B].offset=vfo[VFO_A].offset; + vfo[VFO_B].rit=vfo[VFO_A].rit; + + if(receivers==2) { + receiver_vfo_changed(receiver[1]); + } + if(split) { + tx_set_mode(transmitter,vfo[VFO_B].mode); + } + vfo_update(NULL); +} + +void vfo_b_to_a() { + vfo[VFO_A].band=vfo[VFO_B].band; + vfo[VFO_A].bandstack=vfo[VFO_B].bandstack; + vfo[VFO_A].frequency=vfo[VFO_B].frequency; + vfo[VFO_A].mode=vfo[VFO_B].mode; + vfo[VFO_A].filter=vfo[VFO_B].filter; + vfo[VFO_A].lo=vfo[VFO_B].lo; + vfo[VFO_A].offset=vfo[VFO_B].offset; + vfo[VFO_A].rit=vfo[VFO_B].rit; + receiver_vfo_changed(receiver[0]); + if(!split) { + tx_set_mode(transmitter,vfo[VFO_B].mode); + } + vfo_update(NULL); +} + +void vfo_a_swap_b() { + int temp_band; + int temp_bandstack; + long long temp_frequency; + int temp_mode; + int temp_filter; + int temp_lo; + int temp_offset; + int temp_rit; + + temp_band=vfo[VFO_A].band; + temp_bandstack=vfo[VFO_A].bandstack; + temp_frequency=vfo[VFO_A].frequency; + temp_mode=vfo[VFO_A].mode; + temp_filter=vfo[VFO_A].filter; + temp_lo=vfo[VFO_A].lo; + temp_offset=vfo[VFO_A].offset; + temp_rit=vfo[VFO_A].rit; + + vfo[VFO_A].band=vfo[VFO_B].band; + vfo[VFO_A].bandstack=vfo[VFO_B].bandstack; + vfo[VFO_A].frequency=vfo[VFO_B].frequency; + vfo[VFO_A].mode=vfo[VFO_B].mode; + vfo[VFO_A].filter=vfo[VFO_B].filter; + vfo[VFO_A].lo=vfo[VFO_B].lo; + vfo[VFO_A].offset=vfo[VFO_B].offset; + vfo[VFO_A].rit=vfo[VFO_B].rit; + + vfo[VFO_B].band=temp_band; + vfo[VFO_B].bandstack=temp_bandstack; + vfo[VFO_B].frequency=temp_frequency; + vfo[VFO_B].mode=temp_mode; + vfo[VFO_B].filter=temp_filter; + vfo[VFO_B].lo=temp_lo; + vfo[VFO_B].offset=temp_offset; + vfo[VFO_B].rit=temp_rit; + + receiver_vfo_changed(receiver[0]); + if(receivers==2) { + receiver_vfo_changed(receiver[1]); + } + if(split) { + tx_set_mode(transmitter,vfo[VFO_B].mode); + } else { + tx_set_mode(transmitter,vfo[VFO_A].mode); + } + vfo_update(NULL); +} + void vfo_step(int steps) { + int id=active_receiver->id; if(!locked) { + if(vfo[id].ctun) { + vfo[id].ctun_frequency=vfo[id].ctun_frequency+(steps*step); + } else { + vfo[id].frequency=vfo[id].frequency+(steps*step); + } + receiver_frequency_changed(active_receiver); +#ifdef INCLUDED BANDSTACK_ENTRY* entry=bandstack_entry_get_current(); - //entry->frequencyA=entry->frequencyA+(steps*step); - //setFrequency(entry->frequencyA); - setFrequency(entry->frequencyA+(steps*step)); + setFrequency(active_receiver->frequency+(steps*step)); +#endif vfo_update(NULL); } } -void vfo_move(int hz) { +void vfo_move(long long hz) { + int id=active_receiver->id; if(!locked) { - BANDSTACK_ENTRY* entry=bandstack_entry_get_current(); - //entry->frequencyA=(entry->frequencyA+hz)/step*step; - //setFrequency(entry->frequencyA); - + switch(protocol) { #ifdef LIMESDR - if(protocol==LIMESDR_PROTOCOL) - setFrequency((entry->frequencyA+ddsOffset-hz)/step*step); - else + case LIMESDR_PROTOCOL: + break; #endif - if(ctun) { - setFrequency((entry->frequencyA+ddsOffset-hz)/step*step); - } else { - setFrequency((entry->frequencyA+ddsOffset+hz)/step*step); - } + default: + vfo[id].frequency=((vfo[id].frequency+hz)/step)*step; + break; + } + receiver_frequency_changed(active_receiver); vfo_update(NULL); } } -void vfo_move_to(int hz) { +void vfo_move_to(long long hz) { + int id=active_receiver->id; if(!locked) { + switch(protocol) { +#ifdef LIMESDR + case LIMESDR_PROTOCOL: + break; +#endif + default: + vfo[id].frequency=(vfo[id].frequency+hz)/step*step; + if(vfo[id].mode==modeCWL) { + vfo[id].frequency+=cw_keyer_sidetone_frequency; + } else if(vfo[id].mode==modeCWU) { + vfo[id].frequency-=cw_keyer_sidetone_frequency; + } + break; + } + receiver_vfo_changed(active_receiver); + +#ifdef INCLUDED + BANDSTACK_ENTRY* entry=bandstack_entry_get_current(); #ifdef LIMESDR if(protocol==LIMESDR_PROTOCOL) { - setFrequency((entry->frequencyA+ddsOffset-hz)/step*step); + setFrequency((entry->frequency+active_receiver->dds_offset-hz)/step*step); } else { #endif - if(ctun) { - setFrequency((entry->frequencyA+hz)/step*step); + if(vfo[id].ctun) { + setFrequency((active_receiver->frequency+hz)/step*step); } else { - long f=(entry->frequencyA+ddsOffset+hz)/step*step; - if(mode==modeCWL) { + long long f=(active_receiver->frequency+active_receiver->dds_offset+hz)/step*step; + if(vfo[active_receiver->id].mode==modeCWL) { f+=cw_keyer_sidetone_frequency; - } else if(mode==modeCWU) { + } else if(vfo[active_receiver->id].mode==modeCWU) { f-=cw_keyer_sidetone_frequency; } setFrequency(f); } #ifdef LIMESDR } +#endif #endif vfo_update(NULL); } @@ -125,27 +469,10 @@ vfo_scroll_event_cb (GtkWidget *widget, { int i; if(event->direction==GDK_SCROLL_UP) { - i=1; - } else { - i=-1; - } - if(event->x>(my_width/2)) { - if(event->x>((my_width/4)*3)) { - // rit - rit+=i; - if(rit>10000) { - rit=1000; - } - if(rit<-1000) { - rit=-1000; - } - } else { - // step - } + vfo_move(step); } else { - // frequency + vfo_move(-step); } - vfo_update(NULL); } @@ -153,9 +480,6 @@ static gboolean vfo_configure_event_cb (GtkWidget *widget, GdkEventConfigure *event, gpointer data) { -fprintf(stderr,"vfo_configure_event_cb: width=%d height=%d\n", - gtk_widget_get_allocated_width (widget), - gtk_widget_get_allocated_height (widget)); if (vfo_surface) cairo_surface_destroy (vfo_surface); @@ -170,10 +494,7 @@ fprintf(stderr,"vfo_configure_event_cb: width=%d height=%d\n", cairo_set_source_rgb (cr, 0, 0, 0); cairo_paint (cr); cairo_destroy(cr); - g_idle_add(vfo_update,NULL); - - /* We've handled the configure event, no need for further processing. */ return TRUE; } @@ -183,15 +504,16 @@ static gboolean vfo_draw_cb (GtkWidget *widget, { cairo_set_source_surface (cr, vfo_surface, 0, 0); cairo_paint (cr); - - return FALSE; + return TRUE; } int vfo_update(void *data) { - BANDSTACK_ENTRY* entry=bandstack_entry_get_current(); - FILTER* band_filters=filters[entry->mode]; - FILTER* band_filter=&band_filters[entry->filter]; + + int id=active_receiver->id; + FILTER* band_filters=filters[vfo[id].mode]; + FILTER* band_filter=&band_filters[vfo[id].filter]; if(vfo_surface) { + char temp_text[32]; cairo_t *cr; cr = cairo_create (vfo_surface); cairo_set_source_rgb (cr, 0, 0, 0); @@ -204,18 +526,40 @@ int vfo_update(void *data) { char version[16]; char text[128]; if(radio->protocol==ORIGINAL_PROTOCOL) { + switch(radio->device) { +#ifdef USBOZY + case DEVICE_OZY: + strcpy(version,""); + break; +#endif + default: + sprintf(version,"%d.%d", + radio->software_version/10, + radio->software_version%10); + break; + } + } else { sprintf(version,"%d.%d", radio->software_version/10, radio->software_version%10); - } else { - sprintf(version,"%d.%d.%d", - radio->software_version/100, - (radio->software_version%100)/10, - radio->software_version%10); } switch(radio->protocol) { case ORIGINAL_PROTOCOL: + switch(radio->device) { +#ifdef USBOZY + case DEVICE_OZY: + sprintf(text,"%s", radio->name); + break; +#endif + default: + sprintf(text,"%s %s %s", + radio->name, + version, + inet_ntoa(radio->info.network.address.sin_addr)); + break; + } + break; case NEW_PROTOCOL: sprintf(text,"%s %s %s", radio->name, @@ -224,126 +568,185 @@ int vfo_update(void *data) { break; #ifdef LIMESDR case LIMESDR_PROTOCOL: - sprintf(text,"%s\n", - radio->name); + sprintf(text,"%s", radio->name); break; #endif } - cairo_set_source_rgb(cr, 0.5, 0.5, 0.5); - cairo_set_font_size(cr, 10); + cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); + cairo_set_font_size(cr, 12); cairo_move_to(cr, 5, 15); cairo_show_text(cr, text); - long long f=entry->frequencyA+ddsOffset; - char sf[32]; - sprintf(sf,"%0lld.%06lld MHz",f/(long long)1000000,f%(long long)1000000); - cairo_set_font_size(cr, 28); - if(isTransmitting()) { + //long long af=active_receiver->frequency+active_receiver->dds_offset; + long long af=vfo[0].frequency+vfo[0].offset; + 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); } else { - cairo_set_source_rgb(cr, 0, 1, 0); + if(active_receiver->id==0) { + cairo_set_source_rgb(cr, 0, 1, 0); + } else { + cairo_set_source_rgb(cr, 0, 0.65, 0); + } } cairo_move_to(cr, 5, 38); - cairo_show_text(cr, sf); - - cairo_set_font_size(cr, 12); + cairo_set_font_size(cr, 22); + cairo_show_text(cr, temp_text); - if(rit==0) { - cairo_set_source_rgb(cr, 0.5, 0.5, 0.5); + //long long bf=frequencyB; + long long bf=vfo[1].frequency+vfo[1].offset; + 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); } else { - cairo_set_source_rgb(cr, 0, 1, 0); + if(active_receiver->id==1) { + cairo_set_source_rgb(cr, 0, 1, 0); + } else { + cairo_set_source_rgb(cr, 0, 0.65, 0); + } } - sprintf(sf,"RIT: %d Hz",rit); - cairo_move_to(cr, (my_width/4)*3, 38); - cairo_show_text(cr, sf); + cairo_move_to(cr, 260, 38); + cairo_show_text(cr, temp_text); - cairo_set_source_rgb(cr, 0, 1, 0); + cairo_set_font_size(cr, 12); - int s=0; - while(steps[s]!=step && steps[s]!=0) { - s++; + if(vfo[id].rit==0) { + cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); + } else { + cairo_set_source_rgb(cr, 1, 1, 0); } - sprintf(sf,"Step %s",step_labels[s]); - cairo_move_to(cr, my_width/2, 15); - cairo_show_text(cr, sf); - - cairo_move_to(cr, (my_width/4)*3, 15); - cairo_show_text(cr, getFrequencyInfo(f)); + sprintf(temp_text,"RIT: %d Hz",vfo[id].rit); + cairo_move_to(cr, 5, 50); + cairo_set_font_size(cr, 12); + cairo_show_text(cr, temp_text); + cairo_move_to(cr, 210, 15); if(locked) { - cairo_set_source_rgb(cr, 1, 0, 0); - cairo_move_to(cr, 10, 50); - cairo_show_text(cr, "Locked"); - } - - if(function) { - cairo_set_source_rgb(cr, 1, 0.5, 0); - cairo_move_to(cr, 70, 50); - cairo_show_text(cr, "Function"); + cairo_set_source_rgb(cr, 1, 0, 0); + } else { + cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); } - + cairo_show_text(cr, "Locked"); + cairo_set_source_rgb(cr, 1, 1, 0); - cairo_move_to(cr, 130, 50); - cairo_show_text(cr, mode_string[entry->mode]); - - cairo_move_to(cr, 190, 50); - if(mode==modeFMN) { + cairo_move_to(cr, 100, 50); + if(vfo[id].mode==modeFMN) { if(deviation==2500) { - cairo_show_text(cr, "8k"); + sprintf(temp_text,"%s 8k",mode_string[vfo[id].mode]); } else { - cairo_show_text(cr, "16k"); + sprintf(temp_text,"%s 16k",mode_string[vfo[id].mode]); } } else { - cairo_show_text(cr, band_filter->title); + sprintf(temp_text,"%s %s",mode_string[vfo[id].mode],band_filter->title); } + cairo_show_text(cr, temp_text); - cairo_move_to(cr, 250, 50); - if(nr) { - cairo_show_text(cr, "NR"); - } - if(nr2) { - cairo_show_text(cr, "NR2"); - } - if(nb) { - cairo_show_text(cr, "NB"); + cairo_move_to(cr, 170, 50); + if(active_receiver->nr) { + cairo_set_source_rgb(cr, 1.0, 1.0, 0.0); + } else { + cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); } - if(nb2) { - cairo_show_text(cr, "NB2"); + cairo_show_text(cr, "NR"); + + cairo_move_to(cr, 200, 50); + if(active_receiver->nr2) { + cairo_set_source_rgb(cr, 1.0, 1.0, 0.0); + } else { + cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); } - if(anf) { - cairo_show_text(cr, "ANF"); + cairo_show_text(cr, "NR2"); + + cairo_move_to(cr, 230, 50); + if(active_receiver->anf) { + cairo_set_source_rgb(cr, 1.0, 1.0, 0.0); + } else { + cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); } - if(snb) { - cairo_show_text(cr, "SNB"); + cairo_show_text(cr, "ANF"); + + cairo_move_to(cr, 260, 50); + if(active_receiver->snb) { + 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, "SNB"); - cairo_move_to(cr, 310, 50); - switch(agc) { + cairo_move_to(cr, 290, 50); + switch(active_receiver->agc) { case AGC_OFF: + cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); cairo_show_text(cr, "AGC OFF"); break; case AGC_LONG: + cairo_set_source_rgb(cr, 1, 1, 0); cairo_show_text(cr, "AGC LONG"); break; case AGC_SLOW: + cairo_set_source_rgb(cr, 1, 1, 0); cairo_show_text(cr, "AGC SLOW"); break; case AGC_MEDIUM: + cairo_set_source_rgb(cr, 1, 1, 0); cairo_show_text(cr, "AGC MEDIUM"); break; case AGC_FAST: + cairo_set_source_rgb(cr, 1, 1, 0); cairo_show_text(cr, "AGC FAST"); break; } + int s=0; + while(steps[s]!=step && steps[s]!=0) { + s++; + } + sprintf(temp_text,"Step %s",step_labels[s]); + cairo_move_to(cr, 375, 50); + cairo_set_source_rgb(cr, 1, 1, 0); + cairo_show_text(cr, temp_text); + + char *info=getFrequencyInfo(af); +/* + cairo_move_to(cr, (my_width/4)*3, 50); + cairo_show_text(cr, getFrequencyInfo(af)); +*/ - cairo_move_to(cr, 400, 50); - if(ctun) { - cairo_show_text(cr, "CTUN"); + cairo_move_to(cr, 460, 50); + if(vfo[id].ctun) { + cairo_set_source_rgb(cr, 1, 1, 0); + } else { + cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); + } + cairo_show_text(cr, "CTUN"); + + cairo_move_to(cr, 500, 50); + if(cat_control>0) { + cairo_set_source_rgb(cr, 1, 1, 0); + } else { + cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); + } + cairo_show_text(cr, "CAT"); + + cairo_move_to(cr, 270, 15); + if(split) { + cairo_set_source_rgb(cr, 1, 0, 0); + } else { + cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); + } + cairo_show_text(cr, "Split"); + + cairo_move_to(cr, 310, 15); + if(vfo[id].mode==modeCWL || vfo[id].mode==modeCWU) { + cairo_set_source_rgb(cr, 1, 1, 0); + } else { + cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); } + sprintf(temp_text,"CW %d wpm, sidetone %d Hz",cw_keyer_speed,cw_keyer_sidetone_frequency); + cairo_show_text(cr, temp_text); cairo_destroy (cr); - gtk_widget_queue_draw (vfo); + gtk_widget_queue_draw (vfo_panel); } else { fprintf(stderr,"vfo_update: no surface!\n"); } @@ -365,92 +768,44 @@ vfo_press_event_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { - +/* if((int)event->x < (my_width/4)) { - lock_cb(NULL,NULL); + //lock_cb(NULL,NULL); } else if((int)event->x < (my_width/2) && (int)event->x > (my_width/4)) { start_freqent(); } else { start_step(); -/* - GtkWidget *dialog=gtk_dialog_new_with_buttons("Step",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); - - GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog)); - GtkWidget *grid=gtk_grid_new(); - - gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE); - gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE); - - GtkWidget *step_rb=NULL; - int i=0; - while(steps[i]!=0) { - if(i==0) { - step_rb=gtk_radio_button_new_with_label(NULL,step_labels[i]); - } else { - step_rb=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(step_rb),step_labels[i]); - } - gtk_widget_override_font(step_rb, pango_font_description_from_string("FreeMono 18")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (step_rb), steps[i]==step); - gtk_widget_show(step_rb); - gtk_grid_attach(GTK_GRID(grid),step_rb,i%5,i/5,1,1); - g_signal_connect(step_rb,"pressed",G_CALLBACK(vfo_step_select_cb),(gpointer *)i); - i++; - } - - gtk_container_add(GTK_CONTAINER(content),grid); - - GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Close",GTK_RESPONSE_OK); - gtk_widget_override_font(close_button, pango_font_description_from_string("FreeMono 18")); - gtk_widget_show_all(dialog); - - g_signal_connect_swapped (dialog, - "response", - G_CALLBACK (gtk_widget_destroy), - dialog); - - int result=gtk_dialog_run(GTK_DIALOG(dialog)); -*/ } +*/ + start_vfo(); return TRUE; } GtkWidget* vfo_init(int width,int height,GtkWidget *parent) { + int i; fprintf(stderr,"vfo_init: width=%d height=%d\n", width, height); + parent_window=parent; my_width=width; my_height=height; - vfo = gtk_drawing_area_new (); - gtk_widget_set_size_request (vfo, width, height); + vfo_panel = gtk_drawing_area_new (); + gtk_widget_set_size_request (vfo_panel, width, height); - /* Signals used to handle the backing surface */ - g_signal_connect (vfo, "draw", - G_CALLBACK (vfo_draw_cb), NULL); - g_signal_connect (vfo,"configure-event", + g_signal_connect (vfo_panel,"configure-event", G_CALLBACK (vfo_configure_event_cb), NULL); + g_signal_connect (vfo_panel, "draw", + G_CALLBACK (vfo_draw_cb), NULL); /* Event signals */ - g_signal_connect (vfo, "button-press-event", + g_signal_connect (vfo_panel, "button-press-event", G_CALLBACK (vfo_press_event_cb), NULL); - g_signal_connect(vfo,"scroll_event", + g_signal_connect(vfo_panel,"scroll_event", G_CALLBACK(vfo_scroll_event_cb),NULL); - gtk_widget_set_events (vfo, gtk_widget_get_events (vfo) + gtk_widget_set_events (vfo_panel, gtk_widget_get_events (vfo_panel) | GDK_BUTTON_PRESS_MASK | GDK_SCROLL_MASK); -fprintf(stderr,"vfo_init: set Frequency,Mode,Filter\n"); - BAND *band=band_get_current_band(); - BANDSTACK_ENTRY* entry=bandstack_entry_get_current(); - setFrequency(entry->frequencyA); - setMode(entry->mode); - FILTER* band_filters=filters[entry->mode]; - FILTER* band_filter=&band_filters[entry->filter]; - setFilter(band_filter->low,band_filter->high); - - set_alex_rx_antenna(band->alexRxAntenna); - set_alex_tx_antenna(band->alexTxAntenna); - set_alex_attenuation(band->alexAttenuation); - - return vfo; + return vfo_panel; } diff --git a/vfo.h b/vfo.h index edfb49b..dc13f0f 100644 --- a/vfo.h +++ b/vfo.h @@ -20,12 +20,48 @@ #ifndef _VFO_H #define _VFO_H + +enum { + VFO_A=0, + VFO_B, + MAX_VFOS +}; + +struct _vfo { + int band; + int bandstack; + long long frequency; + int mode; + int filter; + + int ctun; + long long ctun_frequency; + long long rit; + + long long lo; + long long offset; + +} vfo[MAX_VFOS]; + + extern int steps[]; extern char *step_labels[]; extern GtkWidget* vfo_init(int width,int height,GtkWidget *parent); extern void vfo_step(int steps); -extern void vfo_move(int hz); +extern void vfo_move(long long hz); +extern void vfo_move_to(long long hz); extern int vfo_update(void*); +extern void set_frequency(); + +extern void vfo_save_state(); +extern void vfo_restore_state(); +extern void vfo_band_changed(int b); +extern void vfo_bandstack_changed(int b); +extern void vfo_mode_changed(int m); +extern void vfo_filter_changed(int f); +extern void vfo_a_to_b(); +extern void vfo_b_to_a(); +extern void vfo_a_swap_b(); #endif diff --git a/vfo_menu.c b/vfo_menu.c new file mode 100644 index 0000000..a9dfc35 --- /dev/null +++ b/vfo_menu.c @@ -0,0 +1,256 @@ +/* Copyright (C) +* 2016 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#include +#include +#include +#include + +#include "new_menu.h" +#include "band.h" +#include "filter.h" +#include "mode.h" +#include "radio.h" +#include "receiver.h" +#include "vfo.h" + +static GtkWidget *parent_window=NULL; +static GtkWidget *dialog=NULL; +static GtkWidget *label; + +#define BUF_SIZE 88 + +static char *btn_labels[] = {"1","2","3", + "4","5","6", + "7","8","9", + ".","0","BS", + "HZ","KZ","MZ" + ,"CL" + }; + +static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { + if(dialog!=NULL) { + gtk_widget_destroy(dialog); + dialog=NULL; + sub_menu=NULL; + } + return TRUE; +} + +static gboolean freqent_select_cb (GtkWidget *widget, gpointer data) { + char *str = (char *) data; + const char *labelText; + char output[BUF_SIZE], buffer[BUF_SIZE]; + int len; + double mult; + long long f; + static int set = 0; + + if (set) { + set = 0; + strcpy (buffer, "0"); + sprintf(output, "%s", buffer); + gtk_label_set_markup (GTK_LABEL (label), output); + len = 1; + } else { + labelText = gtk_label_get_text (GTK_LABEL (label)); + strcpy (buffer, labelText); + len = strlen (buffer); + } + + if (isdigit (str[0]) || str[0] == '.') { + + buffer[len] = (gchar) str[0]; + buffer[len+1] = (gchar) 0; + + len = (buffer[0] == '0') ? 1 : 0; + + sprintf(output, "%s", buffer+len); + gtk_label_set_markup (GTK_LABEL (label), output); + } else { + + if (strcmp (str, "BS") == 0) { + /* --- Remove the last character on it. --- */ + if (len > 0) buffer[len-1] = (gchar) 0; + + /* --- Remove digit from field. --- */ + sprintf(output, "%s", buffer); + gtk_label_set_markup (GTK_LABEL (label), output); + + /* --- clear? --- */ + } else if (strcmp (str, "CL") == 0) { + strcpy (buffer, "0"); + sprintf(output, "%s", buffer); + gtk_label_set_markup (GTK_LABEL (label), output); + } else if (str[1] == 'Z') { + switch(str[0]) { + case 'M': + mult = 10000000.0; + break; + case 'K': + mult = 10000.0; + break; + default : + mult = 10.0; + } + f = ((long long)(atof(buffer)*mult)+5)/10; + sprintf(output, "%lld", f); + gtk_label_set_markup (GTK_LABEL (label), output); + int b=get_band_from_frequency(f); + if(b<0) { + fprintf(stderr,"get_band_from_frequency: failed for f=%lld\n",f); + b=bandGen; + } + if(b!=band_get_current()) { + BAND *band=band_set_current(b); + BANDSTACK_ENTRY *entry=bandstack_entry_get_current(); + //setMode(entry->mode); + set_mode(active_receiver,entry->mode); + FILTER* band_filters=filters[entry->mode]; + FILTER* band_filter=&band_filters[entry->filter]; + //setFilter(band_filter->low,band_filter->high); + set_filter(active_receiver,band_filter->low,band_filter->high); + if(active_receiver->id==0) { + set_alex_rx_antenna(band->alexRxAntenna); + set_alex_tx_antenna(band->alexTxAntenna); + set_alex_attenuation(band->alexAttenuation); + } + } + setFrequency(f); + vfo_update(NULL); + + set = 1; + } + } + vfo_update(NULL); +} + +static void rit_cb(GtkComboBox *widget,gpointer data) { + switch(gtk_combo_box_get_active(widget)) { + case 0: + rit_increment=1; + break; + case 1: + rit_increment=10; + break; + case 2: + rit_increment=100; + break; + } + vfo_update(NULL); +} + +static void vfo_cb(GtkComboBox *widget,gpointer data) { + step=steps[gtk_combo_box_get_active(widget)]; + vfo_update(NULL); +} + +static GtkWidget *last_mode; + +void vfo_menu(GtkWidget *parent) { + int i; + + parent_window=parent; + + dialog=gtk_dialog_new(); + gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window)); + gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE); + + GdkRGBA color; + color.red = 1.0; + color.green = 1.0; + color.blue = 1.0; + color.alpha = 1.0; + gtk_widget_override_background_color(dialog,GTK_STATE_FLAG_NORMAL,&color); + + GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + + GtkWidget *grid=gtk_grid_new(); + + gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE); + gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE); + gtk_grid_set_column_spacing (GTK_GRID(grid),4); + gtk_grid_set_row_spacing (GTK_GRID(grid),4); + + 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); + + char rx_id[32]; + sprintf(rx_id,"RX %d VFO %s",active_receiver->id,active_receiver->id==0?"A":"B"); + GtkWidget *rx_label=gtk_label_new(rx_id); + gtk_grid_attach(GTK_GRID(grid),rx_label,1,0,1,1); + + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), "0"); + gtk_misc_set_alignment (GTK_MISC (label), 1, .5); + gtk_grid_attach(GTK_GRID(grid),label,0,1,3,1); + + GtkWidget *step_rb=NULL; + for (i=0; i<16; i++) { + GtkWidget *b=gtk_button_new_with_label(btn_labels[i]); + set_button_text_color(b,"black"); + gtk_widget_show(b); + gtk_grid_attach(GTK_GRID(grid),b,i%3,2+(i/3),1,1); + g_signal_connect(b,"pressed",G_CALLBACK(freqent_select_cb),(gpointer *)btn_labels[i]); + } + + GtkWidget *rit_label=gtk_label_new("RIT step: "); + gtk_grid_attach(GTK_GRID(grid),rit_label,3,1,1,1); + + GtkWidget *rit_b=gtk_combo_box_text_new(); + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(rit_b),NULL,"1 Hz"); + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(rit_b),NULL,"10 Hz"); + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(rit_b),NULL,"100 Hz"); + switch(rit_increment) { + case 1: + gtk_combo_box_set_active(GTK_COMBO_BOX(rit_b), 0); + break; + case 10: + gtk_combo_box_set_active(GTK_COMBO_BOX(rit_b), 1); + break; + case 100: + gtk_combo_box_set_active(GTK_COMBO_BOX(rit_b), 2); + break; + } + g_signal_connect(rit_b,"changed",G_CALLBACK(rit_cb),NULL); + gtk_grid_attach(GTK_GRID(grid),rit_b,3,2,1,1); + + GtkWidget *vfo_label=gtk_label_new("VFO step: "); + gtk_grid_attach(GTK_GRID(grid),vfo_label,3,3,1,1); + + GtkWidget *vfo_b=gtk_combo_box_text_new(); + i=0; + while(steps[i]!=0) { + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(vfo_b),NULL,step_labels[i]); + if(steps[i]==step) { + gtk_combo_box_set_active (GTK_COMBO_BOX(vfo_b), i); + } + i++; + } + g_signal_connect(vfo_b,"changed",G_CALLBACK(vfo_cb),NULL); + gtk_grid_attach(GTK_GRID(grid),vfo_b,3,4,1,1); + + gtk_container_add(GTK_CONTAINER(content),grid); + + sub_menu=dialog; + + gtk_widget_show_all(dialog); + +} diff --git a/vfo_menu.h b/vfo_menu.h new file mode 100644 index 0000000..798da2d --- /dev/null +++ b/vfo_menu.h @@ -0,0 +1,20 @@ +/* Copyright (C) +* 2016 - John Melton, G0ORX/N6LYT +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +extern void vfo_menu(GtkWidget *parent); diff --git a/vox.c b/vox.c index 734f210..287b1cd 100644 --- a/vox.c +++ b/vox.c @@ -20,6 +20,7 @@ #include #include "radio.h" +#include "transmitter.h" #include "vox.h" #include "vfo.h" @@ -35,17 +36,18 @@ static int vox_timeout_cb(gpointer data) { double vox_get_peak() { - return peak*10.0; + double result=peak; + return result; } -void update_vox(double *in,int length) { +void update_vox(TRANSMITTER *tx) { // assumes in is interleaved left and right channel with length samples int previous_vox=vox; int i; double sample; peak=0.0; - for(i=0;ibuffer_size;i++) { + sample=tx->mic_input_buffer[i*2]; if(sample<0.0) { sample=-sample; } @@ -53,22 +55,25 @@ void update_vox(double *in,int length) { peak=sample; } } - double threshold=vox_threshold; - if(mic_boost && !local_microphone) { - threshold=vox_threshold*vox_gain; - } -fprintf(stderr,"update_vox: peak=%f threshold=%f\n",peak,threshold); - if(peak>threshold) { - if(previous_vox) { - g_source_remove(vox_timeout); - } else { - setVox(1); +//fprintf(stderr,"update_vox: id=%d peak=%f\n",tx->id,peak); + + if(vox_enabled) { + double threshold=vox_threshold; + +//fprintf(stderr,"update_vox: peak=%f threshold=%f\n",peak,threshold); + + if(peak>threshold) { + if(previous_vox) { + g_source_remove(vox_timeout); + } else { + setVox(1); + } + vox_timeout=g_timeout_add((int)vox_hang,vox_timeout_cb,NULL); + } + if(vox!=previous_vox) { + g_idle_add(vfo_update,NULL); } - vox_timeout=g_timeout_add((int)vox_hang,vox_timeout_cb,NULL); - } - if(vox!=previous_vox) { - g_idle_add(vfo_update,NULL); } } diff --git a/vox.h b/vox.h index b5d5d40..34bd48e 100644 --- a/vox.h +++ b/vox.h @@ -17,6 +17,6 @@ * */ -extern void update_vox(double *in,int length); +extern void update_vox(TRANSMITTER *tx); extern void vox_cancel(); extern double vox_get_peak(); diff --git a/vox_menu.c b/vox_menu.c index 65bee6a..1d2d516 100644 --- a/vox_menu.c +++ b/vox_menu.c @@ -24,9 +24,10 @@ #include #include "new_menu.h" +#include "radio.h" +#include "transmitter.h" #include "vox_menu.h" #include "vox.h" -#include "radio.h" static GtkWidget *parent_window=NULL; @@ -34,11 +35,12 @@ static GtkWidget *dialog=NULL; static GtkWidget *level; -static pthread_t level_thread_id; +GThread *level_thread_id; static int run_level=0; static double peak=0.0; static int level_update(void *data) { +//fprintf(stderr,"vox peak=%f\n",peak); gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(level),peak); return 0; } @@ -63,28 +65,20 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat static void start_level_thread() { int rc; run_level=1; - rc=pthread_create(&level_thread_id,NULL,level_thread,NULL); - if(rc != 0) { - fprintf(stderr,"vox_menu: pthread_create failed on level_thread: rc=%d\n", rc); - run_level=0; + level_thread_id = g_thread_new( "VOX level", level_thread, NULL); + if(!level_thread_id ) { + fprintf(stderr,"g_thread_new failed on level_thread\n"); } + fprintf(stderr, "level_thread: id=%p\n",level_thread_id); } static void destroy_cb(GtkWidget *widget, gpointer data) { run_level=0; -} - -static void vox_cb(GtkWidget *widget, gpointer data) { - vox_enabled=vox_enabled==1?0:1; - if(vox_enabled) { - start_level_thread(); - } else { - run_level=0; - } + vox_setting=0; } static void vox_value_changed_cb(GtkWidget *widget, gpointer data) { - vox_threshold=gtk_range_get_value(GTK_RANGE(widget))/10000.0; + vox_threshold=gtk_range_get_value(GTK_RANGE(widget))/1000.0; } static void vox_gain_value_changed_cb(GtkWidget *widget, gpointer data) { @@ -124,28 +118,16 @@ void vox_menu(GtkWidget *parent) { g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL); gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1); - GtkWidget *vox_b=gtk_check_button_new_with_label("VOX Enable"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (vox_b), vox_enabled); - gtk_widget_show(vox_b); - gtk_grid_attach(GTK_GRID(grid),vox_b,0,1,1,1); - g_signal_connect(vox_b,"toggled",G_CALLBACK(vox_cb),NULL); + GtkWidget *level_label=gtk_label_new("Mic Level:"); + gtk_misc_set_alignment (GTK_MISC(level_label), 0, 0); + gtk_widget_show(level_label); + gtk_grid_attach(GTK_GRID(grid),level_label,0,1,1,1); level=gtk_progress_bar_new(); + gtk_widget_set_size_request (level, 300, 25); gtk_widget_show(level); gtk_grid_attach(GTK_GRID(grid),level,1,1,1,1); -/* - // try to set progress bar to red - GtkStyleContext *style_context; - GtkCssProvider *provider = gtk_css_provider_new (); - gchar tmp[64]; - style_context = gtk_widget_get_style_context(level); - gtk_style_context_add_provider(style_context, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - g_snprintf(tmp, sizeof tmp, "progressbar.trough.progress { background-color: %s; }", "red"); - gtk_css_provider_load_from_data(GTK_CSS_PROVIDER(provider), tmp, -1, NULL); - g_object_unref (provider); -*/ - GtkWidget *threshold_label=gtk_label_new("VOX Threshold:"); gtk_misc_set_alignment (GTK_MISC(threshold_label), 0, 0); gtk_widget_show(threshold_label); @@ -153,23 +135,11 @@ void vox_menu(GtkWidget *parent) { GtkWidget *vox_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0,1000.0,1.0); gtk_widget_set_size_request (vox_scale, 300, 25); - gtk_range_set_value(GTK_RANGE(vox_scale),vox_threshold*10000.0); + gtk_range_set_value(GTK_RANGE(vox_scale),vox_threshold*1000.0); gtk_widget_show(vox_scale); gtk_grid_attach(GTK_GRID(grid),vox_scale,1,2,1,1); g_signal_connect(G_OBJECT(vox_scale),"value_changed",G_CALLBACK(vox_value_changed_cb),NULL); -/* - GtkWidget *gain_label=gtk_label_new("VOX Gain:"); - gtk_misc_set_alignment (GTK_MISC(gain_label), 0, 0); - gtk_widget_show(gain_label); - gtk_grid_attach(GTK_GRID(grid),gain_label,0,3,1,1); - - GtkWidget *gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,1.0,10.0,1.0); - gtk_range_set_value(GTK_RANGE(gain_scale),vox_gain*10000.0); - gtk_widget_show(gain_scale); - gtk_grid_attach(GTK_GRID(grid),gain_scale,1,3,1,1); - g_signal_connect(G_OBJECT(gain_scale),"value_changed",G_CALLBACK(vox_gain_value_changed_cb),NULL); -*/ GtkWidget *hang_label=gtk_label_new("VOX Hang (ms):"); gtk_misc_set_alignment (GTK_MISC(hang_label), 0, 0); gtk_widget_show(hang_label); @@ -186,9 +156,10 @@ void vox_menu(GtkWidget *parent) { gtk_widget_show_all(dialog); - if(vox_enabled) { - start_level_thread(); + if(!vox_enabled) { + vox_setting=1; } + start_level_thread(); } diff --git a/vox_menu.h b/vox_menu.h index af6606e..8dfc38d 100644 --- a/vox_menu.h +++ b/vox_menu.h @@ -18,3 +18,5 @@ */ void vox_menu(GtkWidget *parent); +gboolean vox_cb (GtkWidget *widget, GdkEventButton *event, gpointer data); + diff --git a/waterfall.c b/waterfall.c index b127dc6..3af56d4 100644 --- a/waterfall.c +++ b/waterfall.c @@ -28,8 +28,6 @@ #include "vfo.h" #include "waterfall.h" -static GtkWidget *waterfall; -static GdkPixbuf *pixbuf = NULL; static int colorLowR=0; // black static int colorLowG=0; @@ -51,11 +49,13 @@ static gboolean pressed=FALSE; static gfloat hz_per_pixel; +/* #define BANDS 7 static long long frequency[BANDS]; static gint mode[BANDS]; static gint band=4; +*/ static int display_width; static int display_height; @@ -66,11 +66,12 @@ waterfall_configure_event_cb (GtkWidget *widget, GdkEventConfigure *event, gpointer data) { + RECEIVER *rx=(RECEIVER *)data; display_width=gtk_widget_get_allocated_width (widget); display_height=gtk_widget_get_allocated_height (widget); - pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, display_width, display_height); + rx->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, display_width, display_height); - char *pixels = gdk_pixbuf_get_pixels (pixbuf); + char *pixels = gdk_pixbuf_get_pixels (rx->pixbuf); memset(pixels, 0, display_width*display_height*3); @@ -86,7 +87,8 @@ waterfall_draw_cb (GtkWidget *widget, cairo_t *cr, gpointer data) { - gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0); + RECEIVER *rx=(RECEIVER *)data; + gdk_cairo_set_source_pixbuf (cr, rx->pixbuf, 0, 0); cairo_paint (cr); return TRUE; } @@ -96,13 +98,7 @@ waterfall_button_press_event_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { - int x=(int)event->x; - if (event->button == 1) { - last_x=(int)event->x; - has_moved=FALSE; - pressed=TRUE; - } - return TRUE; + return receiver_button_press_event(widget,event,data); } static gboolean @@ -110,42 +106,14 @@ waterfall_button_release_event_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { - if(pressed) { - int x=(int)event->x; - if (event->button == 1) { - if(has_moved) { - // drag - vfo_move((int)((float)(x-last_x)*hz_per_pixel)); - } else { - // move to this frequency - vfo_move_to((int)((float)(x-(display_width/2))*hz_per_pixel)); - } - last_x=x; - pressed=FALSE; - } - } - return TRUE; + return receiver_button_release_event(widget,event,data); } static gboolean waterfall_motion_notify_event_cb (GtkWidget *widget, GdkEventMotion *event, gpointer data) { - int x, y; - GdkModifierType state; - gdk_window_get_device_position (event->window, - event->device, - &x, - &y, - &state); - if((state & GDK_BUTTON1_MASK == GDK_BUTTON1_MASK) || pressed) { - int moved=last_x-x; - vfo_move((int)((float)moved*hz_per_pixel)); - last_x=x; - has_moved=TRUE; - } - - return TRUE; + return receiver_motion_notify_event(widget,event,data); } static gboolean @@ -153,26 +121,21 @@ waterfall_scroll_event_cb (GtkWidget *widget, GdkEventScroll *event, gpointer data) { - if(event->direction==GDK_SCROLL_UP) { - vfo_move(step); - } else { - vfo_move(-step); - } + return receiver_scroll_event(widget,event,data); } -void waterfall_update(float *data) { +void waterfall_update(RECEIVER *rx) { int i; - hz_per_pixel=(double)getSampleRate()/(double)display_width; - - if(pixbuf) { - char *pixels = gdk_pixbuf_get_pixels (pixbuf); + float *samples; + if(rx->pixbuf) { + char *pixels = gdk_pixbuf_get_pixels (rx->pixbuf); - int width=gdk_pixbuf_get_width(pixbuf); - int height=gdk_pixbuf_get_height(pixbuf); - int rowstride=gdk_pixbuf_get_rowstride(pixbuf); - int channels=gdk_pixbuf_get_n_channels(pixbuf); + int width=gdk_pixbuf_get_width(rx->pixbuf); + int height=gdk_pixbuf_get_height(rx->pixbuf); + int rowstride=gdk_pixbuf_get_rowstride(rx->pixbuf); + int channels=gdk_pixbuf_get_n_channels(rx->pixbuf); memmove(&pixels[rowstride],pixels,(height-1)*rowstride); @@ -180,20 +143,21 @@ void waterfall_update(float *data) { int average=0; char *p; p=pixels; + samples=rx->pixel_samples; for(i=0;iwaterfall_low) { *p++=colorLowR; *p++=colorLowG; *p++=colorLowB; - } else if(sample>(float)waterfall_high) { + } else if(sample>(float)rx->waterfall_high) { *p++=colorHighR; *p++=colorHighG; *p++=colorHighB; } else { - float range=(float)waterfall_high-(float)waterfall_low; - float offset=sample-(float)waterfall_low; + float range=(float)rx->waterfall_high-(float)rx->waterfall_low; + float offset=sample-(float)rx->waterfall_low; float percent=offset/range; if(percent<(2.0f/9.0f)) { float local_percent = percent / (2.0f/9.0f); @@ -236,47 +200,52 @@ void waterfall_update(float *data) { } - if(waterfall_automatic) { - waterfall_low=average/display_width; - waterfall_high=waterfall_low+50; + if(rx->waterfall_automatic) { + rx->waterfall_low=average/display_width; + rx->waterfall_high=rx->waterfall_low+50; } - gtk_widget_queue_draw (waterfall); + gtk_widget_queue_draw (rx->waterfall); } } -GtkWidget* waterfall_init(int width,int height) { +void waterfall_init(RECEIVER *rx,int width,int height) { display_width=width; display_height=height; - hz_per_pixel=(double)getSampleRate()/(double)display_width; + rx->pixbuf=NULL; + rx->waterfall_low=waterfall_low; + rx->waterfall_high=waterfall_high; + rx->waterfall_automatic=waterfall_automatic; + + hz_per_pixel=(double)rx->sample_rate/(double)display_width; //waterfall_frame = gtk_frame_new (NULL); - waterfall = gtk_drawing_area_new (); - gtk_widget_set_size_request (waterfall, width, height); + rx->waterfall = gtk_drawing_area_new (); + gtk_widget_set_size_request (rx->waterfall, width, height); /* Signals used to handle the backing surface */ - g_signal_connect (waterfall, "draw", - G_CALLBACK (waterfall_draw_cb), NULL); - g_signal_connect (waterfall,"configure-event", - G_CALLBACK (waterfall_configure_event_cb), NULL); + g_signal_connect (rx->waterfall, "draw", + G_CALLBACK (waterfall_draw_cb), rx); + g_signal_connect (rx->waterfall,"configure-event", + G_CALLBACK (waterfall_configure_event_cb), rx); /* Event signals */ - g_signal_connect (waterfall, "motion-notify-event", - G_CALLBACK (waterfall_motion_notify_event_cb), NULL); - g_signal_connect (waterfall, "button-press-event", - G_CALLBACK (waterfall_button_press_event_cb), NULL); - g_signal_connect (waterfall, "button-release-event", - G_CALLBACK (waterfall_button_release_event_cb), NULL); - g_signal_connect(waterfall,"scroll_event", - G_CALLBACK(waterfall_scroll_event_cb),NULL); + g_signal_connect (rx->waterfall, "motion-notify-event", + G_CALLBACK (waterfall_motion_notify_event_cb), rx); + g_signal_connect (rx->waterfall, "button-press-event", + G_CALLBACK (waterfall_button_press_event_cb), rx); + g_signal_connect (rx->waterfall, "button-release-event", + G_CALLBACK (waterfall_button_release_event_cb), rx); + g_signal_connect(rx->waterfall,"scroll_event", + G_CALLBACK(waterfall_scroll_event_cb),rx); /* Ask to receive events the drawing area doesn't normally * subscribe to. In particular, we need to ask for the * button press and motion notify events that want to handle. */ - gtk_widget_set_events (waterfall, gtk_widget_get_events (waterfall) + gtk_widget_set_events (rx->waterfall, gtk_widget_get_events (rx->waterfall) | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON1_MOTION_MASK @@ -284,5 +253,4 @@ GtkWidget* waterfall_init(int width,int height) { | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); - return waterfall; } diff --git a/waterfall.h b/waterfall.h index 6278c38..3d41f52 100644 --- a/waterfall.h +++ b/waterfall.h @@ -20,7 +20,7 @@ #ifndef _WATERFALL_H #define _WATERFALL_H -void waterfall_update(float *data); -GtkWidget* waterfall_init(int width,int height); +extern void waterfall_update(RECEIVER *rx); +extern void waterfall_init(RECEIVER *rx,int width,int height); #endif diff --git a/wdsp_init.c b/wdsp_init.c index 6fafe3c..cdeec08 100644 --- a/wdsp_init.c +++ b/wdsp_init.c @@ -64,9 +64,9 @@ static int receiver; static int running=0; -static int buffer_size=BUFFER_SIZE; -static int tx_buffer_size=BUFFER_SIZE; -static int fft_size=4096; +//static int buffer_size=BUFFER_SIZE; +//static int tx_buffer_size=BUFFER_SIZE; +static int tx_buffer_size; static int dspRate=48000; static int outputRate=48000; static int dvOutputRate=8000; @@ -84,20 +84,20 @@ static void calc_tx_buffer_size() { if(protocol==ORIGINAL_PROTOCOL) { switch(sample_rate) { case 48000: - tx_buffer_size=BUFFER_SIZE; + tx_buffer_size=buffer_size; break; case 96000: - tx_buffer_size=BUFFER_SIZE/2; + tx_buffer_size=buffer_size/2; break; case 192000: - tx_buffer_size=BUFFER_SIZE/4; + tx_buffer_size=buffer_size/4; break; case 384000: - tx_buffer_size=BUFFER_SIZE/8; + tx_buffer_size=buffer_size/8; break; } } else { - tx_buffer_size=BUFFER_SIZE; // input always 192K + tx_buffer_size=buffer_size; // input always 192K } } @@ -253,7 +253,7 @@ static void setupRX(int rx) { } // setup for diversity - create_divEXT(0,0,2,BUFFER_SIZE); + create_divEXT(0,0,2,buffer_size); SetEXTDIVRotate(0, 2, &i_rotate, &q_rotate); SetEXTDIVRun(0,diversity_enabled); } @@ -458,7 +458,10 @@ static void initAnalyzer(int channel,int buffer_size) { int max_w = fft_size + (int) MIN(KEEP_TIME * (double) SPECTRUM_UPDATES_PER_SECOND, KEEP_TIME * (double) fft_size * (double) SPECTRUM_UPDATES_PER_SECOND); - fprintf(stderr,"SetAnalyzer channel=%d buffer_size=%d\n",channel,buffer_size); + overlap = (int)max(0.0, ceil(fft_size - (double)sample_rate / (double)SPECTRUM_UPDATES_PER_SECOND)); + + fprintf(stderr,"SetAnalyzer channel=%d buffer_size=%d overlap=%d\n",channel,buffer_size,overlap); + #ifdef PSK if(channel==CHANNEL_PSK) { data_type=0; diff --git a/wdsp_init.h b/wdsp_init.h deleted file mode 100644 index a61b170..0000000 --- a/wdsp_init.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (C) -* 2015 - John Melton, G0ORX/N6LYT -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -*/ - -#ifndef _WDSP_INIT_H -#define _WDSP_INIT_H - -extern void wdsp_set_input_rate(double rate); -extern void wdsp_set_offset(long long offset); -extern void setMode(int m); -extern int getMode(); -extern void setFilter(int low,int high); -extern int getFilterLow(); -extern int getFilterHigh(); -extern void wdsp_init(int rx,int pixels,int protocol); -extern void wdsp_new_sample_rate(int rate); -extern void wdsp_set_agc(int rx, int agc); -extern void wdsp_set_deviation(double deviation); -extern void wdsp_set_pre_emphasize(int state); -#endif diff --git a/xvtr_menu.c b/xvtr_menu.c index 6a25125..2736864 100644 --- a/xvtr_menu.c +++ b/xvtr_menu.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "new_menu.h" @@ -59,10 +60,10 @@ static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat lof=gtk_entry_get_text(GTK_ENTRY(lo_frequency[i])); xvtr->frequencyLO=atoll(lof); xvtr->disablePA=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(disable_pa[i])); - entry->frequencyA=xvtr->frequencyMin; - entry->frequencyB=xvtr->frequencyMin; + entry->frequency=xvtr->frequencyMin; entry->mode=modeUSB; entry->filter=filterF6; +fprintf(stderr,"min=%s:%lld max=%s:%lld lo=%s:%lld\n",minf,xvtr->frequencyMin,maxf,xvtr->frequencyMax,lof,xvtr->frequencyLO); } else { xvtr->frequencyMin=0; xvtr->frequencyMax=0;