From a035bb13f22e9f5e1dac9e5089a58e12b0ae45d0 Mon Sep 17 00:00:00 2001 From: John Melton - G0ORX/N6LYT Date: Mon, 13 Feb 2017 09:37:30 +0000 Subject: [PATCH] New version to support 2 receivers --- Makefile | 138 +- agc_menu.c | 21 +- ant_menu.c | 12 +- audio.c | 187 +- audio.h | 12 +- audio_menu.c | 4 +- band.c | 179 +- band.h | 19 +- band_menu.c | 42 +- band_menu.h | 1 + bandstack.h | 3 +- bandstack_menu.c | 35 +- configure.c | 561 ++++-- cw_menu.c | 8 +- discovered.h | 7 + discovery.c | 263 +++ discovery.h | 20 + display_menu.c | 64 +- dsp_menu.c | 43 +- encoder_menu.c | 289 +++ encoder_menu.h | 26 + equalizer_menu.c | 8 +- filter.c | 249 ++- filter.h | 11 +- filter_menu.c | 128 +- filter_menu.h | 1 + fm_menu.c | 4 +- freqent_menu.c | 23 +- general_menu.c | 82 +- gpio.c | 733 ++++--- gpio.h | 23 + gpio_mraa.c | 6 +- i2c.c | 258 +++ i2c.h | 2 + libusbio.c | 99 + libusbio.h | 19 + main.c | 928 +-------- main.h | 28 +- meter.c | 22 +- meter.h | 2 + meter_menu.c | 2 +- mode.c | 1 + mode.h | 3 +- mode_menu.c | 19 +- new_discovery.c | 28 +- new_menu.c | 303 +-- new_menu.h | 39 +- new_protocol.c | 872 ++++---- new_protocol.h | 12 +- noise_menu.c | 119 +- oc_menu.c | 22 +- old_discovery.c | 28 +- old_protocol.c | 847 ++++---- old_protocol.h | 15 +- ozyio.c | 707 +++++++ ozyio.h | 86 + pa_menu.c | 11 +- panadapter.c | 490 ----- property.c | 15 +- property.h | 2 +- psk.c | 1 - psk_waterfall.c | 9 +- psk_waterfall.h | 2 +- radio.c | 818 +++++--- radio.h | 71 +- radio_menu.c | 407 ++++ radio_menu.h | 20 + receiver.c | 1029 ++++++++++ receiver.h | 147 +- rigctl.c | 3288 +++++++++++++++++-------------- rigctl.h | 5 +- rit.c | 28 +- rx_menu.c | 333 ++++ rx_menu.h | 20 + rx_panadapter.c | 410 ++++ panadapter.h => rx_panadapter.h | 4 +- sliders.c | 85 +- sliders.h | 17 +- soundio.c | 477 +++++ soundio.h | 39 + splash.c | 41 +- splash.h | 3 +- store.c | 140 ++ wdsp_init.h => store.h | 38 +- store_menu.c | 140 ++ store_menu.h | 20 + toolbar.c | 1103 +++-------- toolbar.h | 17 +- transmitter.c | 626 ++++++ transmitter.h | 86 + tx_menu.c | 223 +++ tx_menu.h | 18 + tx_panadapter.c | 420 ++++ tx_panadapter.h | 28 + update.h | 2 +- vfo.c | 737 +++++-- vfo.h | 38 +- vfo_menu.c | 256 +++ vfo_menu.h | 20 + vox.c | 41 +- vox.h | 2 +- vox_menu.c | 67 +- vox_menu.h | 2 + waterfall.c | 134 +- waterfall.h | 4 +- wdsp_init.c | 23 +- xvtr_menu.c | 5 +- 107 files changed, 12972 insertions(+), 6653 deletions(-) create mode 100644 discovery.c create mode 100644 discovery.h create mode 100644 encoder_menu.c create mode 100644 encoder_menu.h create mode 100644 i2c.c create mode 100644 i2c.h create mode 100644 libusbio.c create mode 100644 libusbio.h create mode 100644 ozyio.c create mode 100644 ozyio.h delete mode 100644 panadapter.c create mode 100644 radio_menu.c create mode 100644 radio_menu.h create mode 100644 receiver.c create mode 100644 rx_menu.c create mode 100644 rx_menu.h create mode 100644 rx_panadapter.c rename panadapter.h => rx_panadapter.h (88%) create mode 100644 soundio.c create mode 100644 soundio.h create mode 100644 store.c rename wdsp_init.h => store.h (59%) create mode 100644 store_menu.c create mode 100644 store_menu.h create mode 100644 transmitter.c create mode 100644 transmitter.h create mode 100644 tx_menu.c create mode 100644 tx_menu.h create mode 100644 tx_panadapter.c create mode 100644 tx_panadapter.h create mode 100644 vfo_menu.c create mode 100644 vfo_menu.h diff --git a/Makefile b/Makefile index 773c00b0..78ab4d5f 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 1c88fcbf..1f8485c6 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 de36b4c1..9cef5032 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 0b3ae131..d7fa469b 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 57ad396c..e8a56f41 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 2045be87..2826dcec 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 980d94fb..c3fa969d 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 5f99de71..36532946 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 b4d8c2d7..d55ceff8 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 f7b5a14f..f77fc1a4 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 9e8b30e5..2950b6c1 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 4dc5f3c2..001ea453 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 c882cd4d..688d7ea6 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 b1e263c4..176d1ec5 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 28b41e0e..d4f6322c 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 00000000..3fc509de --- /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 00000000..74600f02 --- /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 1030325d..027e0e49 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 1878d793..690a90e4 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 00000000..f2dabf7f --- /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 00000000..8b455959 --- /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 c474baa4..f2c7582e 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 84492adf..63d959c5 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 8c91cfe8..ea950032 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 9b9b0dcf..f0aa0050 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 fbc39bef..057532ab 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 00d1d6cd..d3d88479 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 0b34ff0f..987de813 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 f3757df6..da5bb154 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 95869242..d3ec3034 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 cb8fcf32..fb60859d 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 45c8f9c4..8b054aef 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 00000000..d33dbec1 --- /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 00000000..14ec8860 --- /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 00000000..0f52c6bf --- /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 00000000..eb3660b8 --- /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 c0fd576e..d340d05e 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 ba49d5ba..49a76c91 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 f95b790d..426d1c09 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 44df1014..868dc6ca 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 bccabdc0..e43361d4 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 7bb8cd0f..37bd12b8 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 e2839d27..ec688105 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 0784302d..de525c60 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 b8a21cab..110d3ebf 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 6be6ec20..9734c42e 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 3caac573..ea221797 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 75972ef3..fa48079d 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 52837592..81ff5c0b 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 b85aa389..73fc5677 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 58cbd41e..bccd0424 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 c38f5545..45107ee8 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 00000000..c71121e2 --- /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 00000000..b643cfe8 --- /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 00882fcc..67cb6e64 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 181c5474..00000000 --- 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 883025b5..3fb103af 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 a3905e5e..a2b8280c 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 5572b9f7..ba03e505 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 abdf8aea..648ef343 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 4698dd72..e4a55d56 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 90089611..0c41d568 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 00000000..8e62c11d --- /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 00000000..9cd8b93a --- /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 00000000..cbec540e --- /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 1d91a7e9..75e36a78 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 b1f76092..90b76dd2 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 2d3ec1a6..51e59ed3 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 da598f92..e9091b62 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 00000000..3d1318dc --- /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 00000000..52066146 --- /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 00000000..45f956de --- /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/panadapter.h b/rx_panadapter.h similarity index 88% rename from panadapter.h rename to rx_panadapter.h index 61717d08..3481d8a1 100644 --- a/panadapter.h +++ b/rx_panadapter.h @@ -20,9 +20,9 @@ #ifndef _PANADAPTER_H #define _PANADAPTER_H -void panadapter_update(float* data,int tx); +void rx_panadapter_update(RECEIVER* rx); -GtkWidget* panadapter_init(int width,int height); +void rx_panadapter_init(RECEIVER *rx,int width,int height); #endif diff --git a/sliders.c b/sliders.c index d33cf947..4b029046 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 1601753b..17aa9271 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 00000000..622d54ae --- /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 00000000..ee4dcfed --- /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 9dded3e1..0520d5b1 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 8c6e1ad0..ada65a92 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 00000000..0b6bb47d --- /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(); -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/store_menu.c b/store_menu.c new file mode 100644 index 00000000..a91cadaa --- /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 54cbf332..203b6068 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 00000000..f4a78122 --- /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 00000000..fec966d3 --- /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 00000000..e6bdfd3b --- /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 00000000..40408c6c --- /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 00000000..0ec9fcf5 --- /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 00000000..dfa8071c --- /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 ef4a5ed6..444a7ab5 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 5e4ffda8..5bc73974 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 edfb49b1..dc13f0f5 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 00000000..a9dfc359 --- /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 00000000..798da2dc --- /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 734f2105..287b1cde 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 b5d5d40e..34bd48e2 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 65bee6ad..1d2d5167 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 af6606e0..8dfc38d2 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 b127dc6a..3af56d42 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 6278c38d..3d41f52b 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 6fafe3c9..cdeec089 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/xvtr_menu.c b/xvtr_menu.c index 6a251251..27368647 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;