From: John Melton G0ORX Date: Sat, 5 Oct 2019 12:25:26 +0000 (+0100) Subject: Added SoapySDR support for Receive X-Git-Url: https://git.rkrishnan.org/pf/content/en/seg/(%5B%5E?a=commitdiff_plain;h=6ac8af8bad3defb161a7f7a771ed93370b25335f;p=pihpsdr.git Added SoapySDR support for Receive --- diff --git a/Makefile b/Makefile index a6e660f..9884a92 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,11 @@ 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 CONTROLLER2 (Also include GPIO and I2C) +#CONTROLLER2_INCLUDE=CONTROLLER2 + # uncomment the line below to include GPIO -#GPIO_INCLUDE=GPIO +GPIO_INCLUDE=GPIO # uncomment the line below to include MCP23017 I2C #I2C_INCLUDE=I2C @@ -19,7 +22,7 @@ GIT_VERSION := $(shell git describe --abbrev=0 --tags) #FREEDV_INCLUDE=FREEDV # uncomment the line below to include Pure Signal support -#PURESIGNAL_INCLUDE=PURESIGNAL +PURESIGNAL_INCLUDE=PURESIGNAL # uncomment the line to below include support for sx1509 i2c expander #SX1509_INCLUDE=sx1509 @@ -52,6 +55,10 @@ LINK=gcc # uncomment the line below for various debug facilities #DEBUG_OPTION=-D DEBUG +ifeq ($(CONTROLLER2_INCLUDE),CONTROLLER2) +CONTROLLER2_OPTIONS=-D CONTROLLER2 +endif + ifeq ($(MIDI_INCLUDE),MIDI) MIDI_OPTIONS=-D MIDI MIDI_SOURCES= alsa_midi.c midi2.c midi3.c @@ -94,8 +101,6 @@ USBOZY_OBJS= \ ozyio.o endif -# uncomment the line below for LimeSDR (uncomment line below) -#LIMESDR_INCLUDE=LIMESDR # uncomment the line below when Radioberry radio cape is plugged in (for now use emulator and old protocol) #RADIOBERRY_INCLUDE=RADIOBERRY @@ -103,18 +108,21 @@ ifeq ($(RADIOBERRY_INCLUDE),RADIOBERRY) RADIOBERRY_OPTIONS=-D RADIOBERRY endif -ifeq ($(LIMESDR_INCLUDE),LIMESDR) -LIMESDR_OPTIONS=-D LIMESDR +# uncomment the line below for SoapySDR +SOAPYSDR_INCLUDE=SOAPYSDR + +ifeq ($(SOAPYSDR_INCLUDE),SOAPYSDR) +SOAPYSDR_OPTIONS=-D SOAPYSDR SOAPYSDRLIBS=-lSoapySDR -LIMESDR_SOURCES= \ -lime_discovery.c \ -lime_protocol.c -LIMESDR_HEADERS= \ -lime_discovery.h \ -lime_protocol.h -LIMESDR_OBJS= \ -lime_discovery.o \ -lime_protocol.o +SOAPYSDR_SOURCES= \ +soapy_discovery.c \ +soapy_protocol.c +SOAPYSDR_HEADERS= \ +soapy_discovery.h \ +soapy_protocol.h +SOAPYSDR_OBJS= \ +soapy_discovery.o \ +soapy_protocol.o endif @@ -159,13 +167,16 @@ ifeq ($(GPIO_INCLUDE),GPIO) GPIO_LIBS=-lwiringPi GPIO_SOURCES= \ gpio.c \ - encoder_menu.c + encoder_menu.c \ + switch_menu.c GPIO_HEADERS= \ gpio.h \ - encoder_menu.h + encoder_menu.h \ + switch_menu.h GPIO_OBJS= \ gpio.o \ - encoder_menu.o + encoder_menu.o \ + switch_menu.o endif ifeq ($(I2C_INCLUDE),I2C) @@ -210,8 +221,9 @@ AUDIO_LIBS=-lasound #AUDIO_LIBS=-lsoundio OPTIONS=-g -Wno-deprecated-declarations $(MIDI_OPTIONS) $(PURESIGNAL_OPTIONS) $(REMOTE_OPTIONS) $(USBOZY_OPTIONS) \ - $(I2C_OPTIONS) $(GPIO_OPTIONS) $(LIMESDR_OPTIONS) $(FREEDV_OPTIONS) $(LOCALCW_OPTIONS) $(RADIOBERRY_OPTIONS) \ + $(I2C_OPTIONS) $(GPIO_OPTIONS) $(SOAPYSDR_OPTIONS) $(FREEDV_OPTIONS) $(LOCALCW_OPTIONS) $(RADIOBERRY_OPTIONS) \ $(PI_SDR_OPTIONS) $(PSK_OPTIONS) $(STEMLAB_OPTIONS) \ + $(CONTROLLER2_OPTIONS) \ -D GIT_DATE='"$(GIT_DATE)"' -D GIT_VERSION='"$(GIT_VERSION)"' $(DEBUG_OPTION) -O3 LIBS=-lrt -lm -lwdsp -lpthread $(AUDIO_LIBS) $(USBOZY_LIBS) $(PSKLIBS) $(GTKLIBS) $(GPIO_LIBS) $(SOAPYSDRLIBS) $(FREEDVLIBS) $(STEMLAB_LIBS) $(MIDI_LIBS) @@ -431,17 +443,17 @@ ext.o \ error_handler.o \ cwramp.o -$(PROGRAM): $(OBJS) $(REMOTE_OBJS) $(USBOZY_OBJS) $(LIMESDR_OBJS) $(FREEDV_OBJS) \ +$(PROGRAM): $(OBJS) $(REMOTE_OBJS) $(USBOZY_OBJS) $(SOAPYSDR_OBJS) $(FREEDV_OBJS) \ $(LOCALCW_OBJS) $(I2C_OBJS) $(GPIO_OBJS) $(PSK_OBJS) $(PURESIGNAL_OBJS) \ $(MIDI_OBJS) $(STEMLAB_OBJS) $(LINK) -o $(PROGRAM) $(OBJS) $(REMOTE_OBJS) $(USBOZY_OBJS) $(I2C_OBJS) $(GPIO_OBJS) \ - $(LIMESDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(PSK_OBJS) $(PURESIGNAL_OBJS) \ + $(SOAPYSDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(PSK_OBJS) $(PURESIGNAL_OBJS) \ $(MIDI_OBJS) $(STEMLAB_OBJS) $(LIBS) -all: prebuild $(PROGRAM) $(HEADERS) $(REMOTE_HEADERS) $(USBOZY_HEADERS) $(LIMESDR_HEADERS) \ +all: prebuild $(PROGRAM) $(HEADERS) $(REMOTE_HEADERS) $(USBOZY_HEADERS) $(SOAPYSDR_HEADERS) \ $(FREEDV_HEADERS) $(LOCALCW_HEADERS) $(I2C_HEADERS) $(GPIO_HEADERS) $(PSK_HEADERS) \ $(PURESIGNAL_HEADERS) $(MIDI_HEADERS) $(STEMLAB_HEADERS) $(SOURCES) $(REMOTE_SOURCES) \ - $(USBOZY_SOURCES) $(LIMESDR_SOURCES) $(FREEDV_SOURCES) $(I2C_SOURCES) $(GPIO_SOURCES) \ + $(USBOZY_SOURCES) $(SOAPYSDR_SOURCES) $(FREEDV_SOURCES) $(I2C_SOURCES) $(GPIO_SOURCES) \ $(PSK_SOURCES) $(PURESIGNAL_SOURCES) $(MIDI_SOURCES)$(STEMLAB_SOURCES) prebuild: diff --git a/about_menu.c b/about_menu.c index 4cd0a12..b64c3b8 100644 --- a/about_menu.c +++ b/about_menu.c @@ -109,6 +109,8 @@ void about_menu(GtkWidget *parent) { lines++; sprintf(text,"%s\n Ken Hopper, N9VV, Testing and Documentation",text); lines++; + sprintf(text,"%s\n Christoph v. Wüllen, DL1YCF, Pure Signal, Diversity, MIDI",text); + lines++; lines++; sprintf(text,"%s\n\nBuild date: %s", text, build_date); @@ -117,7 +119,7 @@ void about_menu(GtkWidget *parent) { sprintf(text,"%s\nBuild version: %s", text, version); lines++; - sprintf(text,"%s\n\nWDSP v%d.%02d", text, GetWDSPVersion()/100, GetWDSPVersion()%100); + sprintf(text,"%s\nWDSP version: %d.%02d", text, GetWDSPVersion()/100, GetWDSPVersion()%100); lines++; sprintf(text,"%s\n\nDevice: %s Protocol %s v%d.%d",text,radio->name,radio->protocol==ORIGINAL_PROTOCOL?"1":"2",radio->software_version/10,radio->software_version%10); diff --git a/adc.h b/adc.h new file mode 100644 index 0000000..3585f0c --- /dev/null +++ b/adc.h @@ -0,0 +1,72 @@ +/* Copyright (C) +* 2018 - 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 ADC_H +#define ADC_H + +enum { + AUTOMATIC=0, + MANUAL +}; + +enum { + BYPASS=0, + HPF_1_5, + HPF_6_5, + HPF_9_5, + HPF_13, + HPF_20 +}; + +enum { + LPF_160=0, + LPF_80, + LPF_60_40, + LPF_30_20, + LPF_17_15, + LPF_12_10, + LPF_6 +}; + +enum { + ANTENNA_1=0, + ANTENNA_2, + ANTENNA_3, + ANTENNA_XVTR, + ANTENNA_EXT1, + ANTENNA_EXT2 +}; + +typedef struct _adc { + gint filters; + gint hpf; + gint lpf; + gint antenna; + gboolean dither; + gboolean random; + gboolean preamp; + gint attenuation; + gboolean enable_step_attenuation; +#ifdef SOAPYSDR + gint *rx_gain; + gboolean agc; +#endif +} ADC; + +#endif diff --git a/agc.h b/agc.h index 2fcb04f..7b8ed04 100644 --- a/agc.h +++ b/agc.h @@ -25,5 +25,6 @@ #define AGC_SLOW 2 #define AGC_MEDIUM 3 #define AGC_FAST 4 +#define AGC_LAST AGC_FAST #endif diff --git a/ant_menu.c b/ant_menu.c index 3ea8d9b..291e71e 100644 --- a/ant_menu.c +++ b/ant_menu.c @@ -28,11 +28,17 @@ #include "ant_menu.h" #include "band.h" #include "radio.h" +#include "new_protocol.h" +#ifdef SOAPYSDR +#include "soapy_protocol.h" +#endif + static GtkWidget *parent_window=NULL; static GtkWidget *menu_b=NULL; static GtkWidget *dialog=NULL; static GtkWidget *grid=NULL; +static GtkWidget *adc0_antenna_combo_box; static void cleanup() { if(dialog!=NULL) { @@ -62,6 +68,18 @@ static void rx_ant_cb(GtkWidget *widget, gpointer data) { } } +static void adc0_antenna_cb(GtkComboBox *widget,gpointer data) { + ADC *adc=(ADC *)data; + adc->antenna=gtk_combo_box_get_active(widget); + if(radio->protocol==NEW_PROTOCOL) { + schedule_high_priority(); +#ifdef SOAPYSDR + } else if(radio->device==SOAPYSDR_USB_DEVICE) { + soapy_protocol_set_rx_antenna(receiver[0],adc[0].antenna); +#endif + } +} + static void rx_lime_ant_cb(GtkWidget *widget, gpointer data) { int ant=((uintptr_t)data)&0xF; BAND *band=band_get_current_band(); @@ -277,14 +295,21 @@ void ant_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 *hf_rb=gtk_radio_button_new_with_label(NULL,"HF"); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hf_rb),TRUE); - g_signal_connect(hf_rb,"toggled",G_CALLBACK(hf_rb_cb),NULL); - gtk_grid_attach(GTK_GRID(grid),hf_rb,1,0,1,1); +#ifdef SOAPYSDR + if(radio->device!=SOAPYSDR_USB_DEVICE) { +#endif + GtkWidget *hf_rb=gtk_radio_button_new_with_label(NULL,"HF"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hf_rb),TRUE); + g_signal_connect(hf_rb,"toggled",G_CALLBACK(hf_rb_cb),NULL); + gtk_grid_attach(GTK_GRID(grid),hf_rb,1,0,1,1); + + GtkWidget *xvtr_rb=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(hf_rb),"XVTR"); + g_signal_connect(xvtr_rb,"toggled",G_CALLBACK(xvtr_rb_cb),NULL); + gtk_grid_attach(GTK_GRID(grid),xvtr_rb,2,0,1,1); - GtkWidget *xvtr_rb=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(hf_rb),"XVTR"); - g_signal_connect(xvtr_rb,"toggled",G_CALLBACK(xvtr_rb_cb),NULL); - gtk_grid_attach(GTK_GRID(grid),xvtr_rb,2,0,1,1); +#ifdef SOAPYSDR + } +#endif if ((protocol == NEW_PROTOCOL && (device == NEW_DEVICE_HERMES || device == NEW_DEVICE_ANGELIA || device == NEW_DEVICE_ORION)) || (protocol == ORIGINAL_PROTOCOL && (device == DEVICE_HERMES || device == DEVICE_ANGELIA || device == DEVICE_ORION))) { @@ -360,37 +385,27 @@ void ant_menu(GtkWidget *parent) { show_hf(); } -#ifdef LIMESDR - if(protocol==LIMESDR_PROTOCOL) { - BAND *band=band_get_current_band(); - - GtkWidget *rx1_none=gtk_radio_button_new_with_label(NULL,"RX 1: NONE"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx1_none), band->alexRxAntenna==0); - gtk_widget_show(rx1_none); - gtk_grid_attach(GTK_GRID(grid),rx1_none,0,1,1,1); - g_signal_connect(rx1_none,"pressed",G_CALLBACK(rx_lime_ant_cb),(gpointer)(long)0); - - GtkWidget *rx1_lnah=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(rx1_none),"RX1: LNAH"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx1_lnah), band->alexRxAntenna==1); - gtk_widget_show(rx1_lnah); - gtk_grid_attach(GTK_GRID(grid),rx1_lnah,0,2,1,1); - g_signal_connect(rx1_lnah,"pressed",G_CALLBACK(rx_lime_ant_cb),(gpointer)(long)+1); - - GtkWidget *rx1_lnal=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(rx1_lnah),"RX1: LNAL"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx1_lnal), band->alexRxAntenna==2); - gtk_widget_show(rx1_lnal); - gtk_grid_attach(GTK_GRID(grid),rx1_lnal,0,3,1,1); - g_signal_connect(rx1_lnal,"pressed",G_CALLBACK(rx_lime_ant_cb),(gpointer)(long)2); - - GtkWidget *rx1_lnaw=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(rx1_lnal),"RX1: LNAW"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx1_lnaw), band->alexRxAntenna==3); - gtk_widget_show(rx1_lnaw); - gtk_grid_attach(GTK_GRID(grid),rx1_lnaw,0,4,1,1); - g_signal_connect(rx1_lnaw,"pressed",G_CALLBACK(rx_lime_ant_cb),(gpointer)(long)3); +#ifdef SOAPYSDR + if(radio->device==SOAPYSDR_USB_DEVICE) { + int i; + +g_print("rx_antennas=%d\n",radio->info.soapy.rx_antennas); + if(radio->info.soapy.rx_antennas>0) { + GtkWidget *antenna_label=gtk_label_new("RX Antenna:"); + gtk_grid_attach(GTK_GRID(grid),antenna_label,0,1,1,1); + adc0_antenna_combo_box=gtk_combo_box_text_new(); + + for(i=0;iinfo.soapy.rx_antennas;i++) { + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(adc0_antenna_combo_box),NULL,radio->info.soapy.rx_antenna[i]); + } + + gtk_combo_box_set_active(GTK_COMBO_BOX(adc0_antenna_combo_box),adc[0].antenna); + g_signal_connect(adc0_antenna_combo_box,"changed",G_CALLBACK(adc0_antenna_cb),&adc[0]); + gtk_grid_attach(GTK_GRID(grid),adc0_antenna_combo_box,1,1,1,1); + } } #endif - gtk_container_add(GTK_CONTAINER(content),grid); sub_menu=dialog; diff --git a/audio.c b/audio.c index 4c98c8d..2d8e541 100644 --- a/audio.c +++ b/audio.c @@ -36,15 +36,19 @@ #include -#include "new_protocol.h" -#include "old_protocol.h" #include "radio.h" #include "receiver.h" +#include "transmitter.h" #include "audio.h" #include "mode.h" +#include "new_protocol.h" +#include "old_protocol.h" +#ifdef SOAPYSDR +#include "soapy_protocol.h" +#endif int audio = 0; -int audio_buffer_size = 256; // samples (both left and right) +long 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; @@ -313,7 +317,7 @@ void audio_close_input() { // int cw_audio_write(double sample){ snd_pcm_sframes_t delay; - int error; + long rc; long trim; short shortsample; @@ -330,24 +334,23 @@ int cw_audio_write(double sample){ 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; +*/ + if ((rc = snd_pcm_writei (rx->playback_handle, rx->playback_buffer, audio_buffer_size-trim)) != audio_buffer_size-trim) { + if(rc<0) { + if(rc==-EPIPE) { + if ((rc = snd_pcm_prepare (rx->playback_handle)) < 0) { + fprintf (stderr, "audio_write: cannot prepare audio interface for use %d (%s)\n", rc, snd_strerror (rc)); + return -1; + } else { + // ignore short write + } } } } @@ -363,7 +366,7 @@ int cw_audio_write(double sample){ // int audio_write(RECEIVER *rx,short left_sample,short right_sample) { snd_pcm_sframes_t delay; - int error; + long rc; long trim; int mode=transmitter->mode; // @@ -374,7 +377,12 @@ int audio_write(RECEIVER *rx,short left_sample,short right_sample) { // If *not* doing CW, the stream continues because we might wish // to listen to this rx while transmitting. // - if (rx == active_receiver && isTransmitting() && (mode==modeCWU || mode==modeCWL)) return 0; + + if (rx == active_receiver && isTransmitting() && (mode==modeCWU || mode==modeCWL)) { + fprintf(stderr,"returning from audio_write\n"); + rx->playback_offset=0; + return 0; + } if(rx->playback_handle!=NULL && rx->playback_buffer!=NULL) { rx->playback_buffer[rx->playback_offset++]=right_sample; @@ -386,24 +394,28 @@ int audio_write(RECEIVER *rx,short left_sample,short right_sample) { 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); +fprintf(stderr,"audio delay=%ld trim=%ld audio_buffer_size=%d\n",delay,trim,audio_buffer_size); + if(trim>=audio_buffer_size) { + rx->playback_offset=0; + return 0; + } } } - - 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; +*/ + if ((rc = snd_pcm_writei (rx->playback_handle, rx->playback_buffer, audio_buffer_size-trim)) != audio_buffer_size-trim) { + if(rc<0) { + if(rc==-EPIPE) { + if ((rc = snd_pcm_prepare (rx->playback_handle)) < 0) { + fprintf (stderr, "audio_write: cannot prepare audio interface for use %d (%s)\n", rc, snd_strerror (rc)); + rx->playback_offset=0; + return -1; + } + } else { + // ignore short write } } } @@ -441,6 +453,11 @@ fprintf(stderr,"mic_read_thread: mic_buffer_size=%d\n",mic_buffer_size); case NEW_PROTOCOL: new_protocol_process_local_mic(mic_buffer,1); break; +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: + soapy_protocol_process_local_mic(mic_buffer); + break; +#endif default: break; } diff --git a/band.c b/band.c index 85d88b1..bc54e68 100644 --- a/band.c +++ b/band.c @@ -122,7 +122,7 @@ BANDSTACK_ENTRY bandstack_entries6[] = {50125000LL,modeUSB,filterF5,200,2800,200,2800}, {50200000LL,modeUSB,filterF5,200,2800,200,2800}}; -#ifdef LIMESDR +#ifdef SOAPYSDR BANDSTACK_ENTRY bandstack_entries70[] = {{70010000LL,modeCWU,filterF6,200,2800,200,2800}, {70200000LL,modeUSB,filterF5,200,2800,200,2800}, @@ -198,7 +198,7 @@ BANDSTACK bandstack15={3,1,bandstack_entries15}; BANDSTACK bandstack12={3,1,bandstack_entries12}; BANDSTACK bandstack10={3,1,bandstack_entries10}; BANDSTACK bandstack6={3,1,bandstack_entries6}; -#ifdef LIMESDR +#ifdef SOAPYSDR BANDSTACK bandstack70={3,1,bandstack_entries70}; BANDSTACK bandstack144={6,1,bandstack_entries144}; BANDSTACK bandstack220={3,1,bandstack_entries220}; @@ -276,7 +276,7 @@ BAND bands[BANDS+XVTRS] = {"12",&bandstack12,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,24890000LL,24990000LL,0LL,0LL,0}, {"10",&bandstack10,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,28000000LL,29700000LL,0LL,0LL,0}, {"6",&bandstack6,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,50000000LL,54000000LL,0LL,0LL,0}, -#ifdef LIMESDR +#ifdef SOAPYSDR {"70",&bandstack70,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,0LL,0LL,0LL,0LL,0}, {"144",&bandstack144,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,144000000LL,148000000LL,0LL,0LL,0}, {"220",&bandstack144,0,0,0,0,0,ALEX_ATTENUATION_0dB,53.0,222000000LL,224980000LL,0LL,0LL,0}, diff --git a/band.h b/band.h index 937b7c1..8e1762e 100644 --- a/band.h +++ b/band.h @@ -34,7 +34,7 @@ #define band12 8 #define band10 9 #define band6 10 -#ifdef LIMESDR +#ifdef SOAPYSDR #define band70 11 #define band220 13 #define band430 14 @@ -76,6 +76,8 @@ struct _BAND { long long frequencyMax; long long frequencyLO; long long errorLO; + long long txFrequencyLO; + long long txErrorLO; int disablePA; }; diff --git a/band_menu.c b/band_menu.c index f1433d1..c89cefd 100644 --- a/band_menu.c +++ b/band_menu.c @@ -103,8 +103,8 @@ void band_menu(GtkWidget *parent) { gtk_grid_attach(GTK_GRID(grid),close_b,0,0,1,1); for(i=0;i=band70 && i<=band3400) { continue; } diff --git a/configure.c b/configure.c index f8fbd93..9ac48f1 100644 --- a/configure.c +++ b/configure.c @@ -44,12 +44,6 @@ 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; @@ -62,6 +56,20 @@ static GtkWidget *E3_a; static GtkWidget *E3_b_label; static GtkWidget *E3_b; static GtkWidget *b_enable_E3_pullup; +static GtkWidget *b_enable_E4_encoder; +static GtkWidget *E4_a_label; +static GtkWidget *E4_a; +static GtkWidget *E4_b_label; +static GtkWidget *E4_b; +static GtkWidget *b_enable_E4_pullup; +#ifdef CONTROLLER2 +static GtkWidget *b_enable_E5_encoder; +static GtkWidget *E5_a_label; +static GtkWidget *E5_a; +static GtkWidget *E5_b_label; +static GtkWidget *E5_b; +static GtkWidget *b_enable_E5_pullup; +#endif static GtkWidget *b_enable_mox; static GtkWidget *mox_label; static GtkWidget *mox; @@ -113,11 +121,6 @@ static gboolean save_cb (GtkWidget *widget, GdkEventButton *event, gpointer data 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)); @@ -128,6 +131,13 @@ static gboolean save_cb (GtkWidget *widget, GdkEventButton *event, gpointer data 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_E4_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E4_encoder))?1:0; + E4_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E4_a)); + E4_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E4_b)); + ENABLE_E4_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E4_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)); @@ -151,6 +161,7 @@ static gboolean save_cb (GtkWidget *widget, GdkEventButton *event, gpointer data 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 ENABLE_CW_BUTTONS=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_cwlr))?1:0; CW_ACTIVE_LOW=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_cw_active_low))?1:0; @@ -213,37 +224,6 @@ void configure_gpio(GtkWidget *parent) { gtk_grid_attach(GTK_GRID(grid),b_enable_vfo_pullup,5,y,1,1); - y++; - - 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); - - 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); - - 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); - - 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); - - 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); - - 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++; b_enable_E2_encoder=gtk_check_button_new_with_label("Enable E2"); @@ -306,8 +286,70 @@ void configure_gpio(GtkWidget *parent) { gtk_grid_attach(GTK_GRID(grid),b_enable_E3_pullup,5,y,1,1); + y++; + b_enable_E4_encoder=gtk_check_button_new_with_label("Enable E4"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_E4_encoder), ENABLE_E4_ENCODER); + gtk_widget_show(b_enable_E4_encoder); + gtk_grid_attach(GTK_GRID(grid),b_enable_E4_encoder,0,y,1,1); + + E4_a_label=gtk_label_new("GPIO A:"); + gtk_widget_show(E4_a_label); + gtk_grid_attach(GTK_GRID(grid),E4_a_label,1,y,1,1); + + E4_a=gtk_spin_button_new_with_range (0.0,100.0,1.0); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(E4_a),E4_ENCODER_A); + gtk_widget_show(E4_a); + gtk_grid_attach(GTK_GRID(grid),E4_a,2,y,1,1); + + E4_b_label=gtk_label_new("GPIO B:"); + gtk_widget_show(E4_b_label); + gtk_grid_attach(GTK_GRID(grid),E4_b_label,3,y,1,1); + + E4_b=gtk_spin_button_new_with_range (0.0,100.0,1.0); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(E4_b),E4_ENCODER_B); + gtk_widget_show(E4_b); + gtk_grid_attach(GTK_GRID(grid),E4_b,4,y,1,1); + + b_enable_E4_pullup=gtk_check_button_new_with_label("Enable Pull-up"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_E4_pullup), ENABLE_E4_PULLUP); + gtk_widget_show(b_enable_E4_pullup); + gtk_grid_attach(GTK_GRID(grid),b_enable_E4_pullup,5,y,1,1); + +#ifdef CONTROLLER2 + y++; + b_enable_E5_encoder=gtk_check_button_new_with_label("Enable E5"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_E5_encoder), ENABLE_E5_ENCODER); + gtk_widget_show(b_enable_E5_encoder); + gtk_grid_attach(GTK_GRID(grid),b_enable_E5_encoder,0,y,1,1); + + E5_a_label=gtk_label_new("GPIO A:"); + gtk_widget_show(E5_a_label); + gtk_grid_attach(GTK_GRID(grid),E5_a_label,1,y,1,1); + + E5_a=gtk_spin_button_new_with_range (0.0,100.0,1.0); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(E5_a),E5_ENCODER_A); + gtk_widget_show(E5_a); + gtk_grid_attach(GTK_GRID(grid),E5_a,2,y,1,1); + + E5_b_label=gtk_label_new("GPIO B:"); + gtk_widget_show(E5_b_label); + gtk_grid_attach(GTK_GRID(grid),E5_b_label,3,y,1,1); + + E5_b=gtk_spin_button_new_with_range (0.0,100.0,1.0); + gtk_spin_button_set_value (GTK_SPIN_BUTTON(E5_b),E5_ENCODER_B); + gtk_widget_show(E5_b); + gtk_grid_attach(GTK_GRID(grid),E5_b,4,y,1,1); + + b_enable_E5_pullup=gtk_check_button_new_with_label("Enable Pull-up"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_E5_pullup), ENABLE_E5_PULLUP); + gtk_widget_show(b_enable_E5_pullup); + gtk_grid_attach(GTK_GRID(grid),b_enable_E5_pullup,5,y,1,1); + +#endif +#ifndef CONTROLLER2 + y++; 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); @@ -337,6 +379,7 @@ void configure_gpio(GtkWidget *parent) { 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); +#endif #ifdef LOCALCW // With LOCALCW, the menu got too long (does not fit on the screen) @@ -360,6 +403,7 @@ void configure_gpio(GtkWidget *parent) { y++; +#ifndef CONTROLLER2 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); @@ -373,6 +417,7 @@ void configure_gpio(GtkWidget *parent) { 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); +#endif #ifdef LOCALCW cwr_label=gtk_label_new("CWR GPIO:"); @@ -392,6 +437,7 @@ void configure_gpio(GtkWidget *parent) { y++; +#ifndef CONTROLLER2 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); @@ -405,6 +451,7 @@ void configure_gpio(GtkWidget *parent) { 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); +#endif #ifdef LOCALCW cws_label=gtk_label_new(" SideTone GPIO:"); @@ -423,6 +470,7 @@ void configure_gpio(GtkWidget *parent) { #endif y++; +#ifndef CONTROLLER2 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); @@ -484,6 +532,7 @@ void configure_gpio(GtkWidget *parent) { gtk_spin_button_set_value (GTK_SPIN_BUTTON(function),FUNCTION_BUTTON); gtk_widget_show(function); gtk_grid_attach(GTK_GRID(grid),function,2,y,1,1); +#endif y++; diff --git a/discovered.c b/discovered.c index 513f255..15e8248 100644 --- a/discovered.c +++ b/discovered.c @@ -17,6 +17,7 @@ * */ +#include #include "discovered.h" int selected_device=0; diff --git a/discovered.h b/discovered.h index 7c14ec0..3309f88 100644 --- a/discovered.h +++ b/discovered.h @@ -21,7 +21,7 @@ #define _DISCOVERED_H #include -#ifdef LIMESDR +#ifdef SOAPYSDR #include #endif @@ -51,8 +51,8 @@ #define NEW_DEVICE_ORION2 5 #define NEW_DEVICE_HERMES_LITE 6 -#ifdef LIMESDR -#define LIMESDR_USB_DEVICE 0 +#ifdef SOAPYSDR +#define SOAPYSDR_USB_DEVICE 0 #endif #define STATE_AVAILABLE 2 @@ -60,8 +60,8 @@ #define ORIGINAL_PROTOCOL 0 #define NEW_PROTOCOL 1 -#ifdef LIMESDR -#define LIMESDR_PROTOCOL 2 +#ifdef SOAPYSDR +#define SOAPYSDR_PROTOCOL 2 #endif #ifdef REMOTE @@ -90,6 +90,11 @@ struct _DISCOVERED { char name[64]; int software_version; int status; + int supported_receivers; + int supported_transmitters; + int adcs; + double frequency_min; + double frequency_max; union { struct network { unsigned char mac_address[6]; @@ -100,9 +105,24 @@ struct _DISCOVERED { struct sockaddr_in interface_netmask; char interface_name[64]; } network; -#ifdef LIMESDR +#ifdef SOAPYSDR struct soapy { - SoapySDRKwargs *args; + int rtlsdr_count; + int sample_rate; + size_t rx_channels; + size_t rx_gains; + char **rx_gain; + SoapySDRRange *rx_range; + gboolean rx_has_automatic_gain; + gboolean rx_has_automatic_dc_offset_correction; + size_t rx_antennas; + char **rx_antenna; + size_t tx_channels; + size_t tx_gains; + char **tx_gain; + SoapySDRRange *tx_range; + size_t tx_antennas; + char **tx_antenna; } soapy; #endif } info; diff --git a/discovery.c b/discovery.c index 5de6a0a..5252bdd 100644 --- a/discovery.c +++ b/discovery.c @@ -31,6 +31,9 @@ #include "discovered.h" #include "old_discovery.h" #include "new_discovery.h" +#ifdef SOAPYSDR +#include "soapy_discovery.h" +#endif #include "main.h" #include "radio.h" #ifdef USBOZY @@ -180,9 +183,9 @@ void discovery() { status_text("Protocol 2 ... Discovering Devices"); new_discovery(); -#ifdef LIMESDR - status_text("LimeSDR ... Discovering Devices"); - lime_discovery(); +#ifdef SOAPYSDR + status_text("SoapySDR ... Discovering Devices"); + soapy_discovery(); #endif status_text("Discovery"); @@ -293,10 +296,10 @@ fprintf(stderr,"%p Protocol=%d name=%s\n",d,d->protocol,d->name); } #endif break; -#ifdef LIMESDR - case LIMESDR_PROTOCOL: - sprintf(text,"%s", - d->name); +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: + sprintf(text,"%s SOAPY_SDR v%d.%d.%d USB", + d->name,d->software_version/100,(d->software_version%100)/10,d->software_version%10); break; #endif #ifdef STEMLAB_DISCOVERY @@ -334,11 +337,17 @@ fprintf(stderr,"%p Protocol=%d name=%s\n",d,d->protocol,d->name); 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 SOAPYSDR + if(d->device!=SOAPYSDR_USB_DEVICE) { +#endif + // 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 SOAPYSDR } +#endif #ifdef STEMLAB_DISCOVERY if (d->protocol == STEMLAB_PROTOCOL) { diff --git a/display_menu.c b/display_menu.c index d9a5276..6efbe0a 100644 --- a/display_menu.c +++ b/display_menu.c @@ -86,6 +86,10 @@ static void panadapter_low_value_changed_cb(GtkWidget *widget, gpointer data) { active_receiver->panadapter_low=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); } +static void panadapter_step_value_changed_cb(GtkWidget *widget, gpointer data) { + active_receiver->panadapter_step=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); +} + static void waterfall_high_value_changed_cb(GtkWidget *widget, gpointer data) { active_receiver->waterfall_high=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); } @@ -113,12 +117,12 @@ static void display_sliders_cb(GtkWidget *widget, gpointer data) { reconfigure_radio(); } -/* + static void display_toolbar_cb(GtkWidget *widget, gpointer data) { display_toolbar=display_toolbar==1?0:1; reconfigure_radio(); } -*/ + void display_menu(GtkWidget *parent) { int i; @@ -145,193 +149,269 @@ void display_menu(GtkWidget *parent) { //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE); //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE); + int col=0; + int row=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,0,0,1,1); + gtk_grid_attach(GTK_GRID(grid),close_b,col,row,1,1); + + row++; + col=0; GtkWidget *filled_b=gtk_check_button_new_with_label("Fill Panadapter"); //gtk_widget_override_font(filled_b, pango_font_description_from_string("Arial 18")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (filled_b), display_filled); gtk_widget_show(filled_b); - gtk_grid_attach(GTK_GRID(grid),filled_b,0,1,1,1); + gtk_grid_attach(GTK_GRID(grid),filled_b,col,row,1,1); g_signal_connect(filled_b,"toggled",G_CALLBACK(filled_cb),NULL); + row++; + col=0; + GtkWidget *frames_per_second_label=gtk_label_new("Frames Per Second: "); //gtk_widget_override_font(frames_per_second_label, pango_font_description_from_string("Arial 18")); gtk_widget_show(frames_per_second_label); - gtk_grid_attach(GTK_GRID(grid),frames_per_second_label,0,2,1,1); + gtk_grid_attach(GTK_GRID(grid),frames_per_second_label,col,row,1,1); + + col++; GtkWidget *frames_per_second_r=gtk_spin_button_new_with_range(1.0,100.0,1.0); //gtk_widget_override_font(frames_per_second_r, pango_font_description_from_string("Arial 18")); gtk_spin_button_set_value(GTK_SPIN_BUTTON(frames_per_second_r),(double)updates_per_second); gtk_widget_show(frames_per_second_r); - gtk_grid_attach(GTK_GRID(grid),frames_per_second_r,1,2,1,1); + gtk_grid_attach(GTK_GRID(grid),frames_per_second_r,col,row,1,1); g_signal_connect(frames_per_second_r,"value_changed",G_CALLBACK(frames_per_second_value_changed_cb),NULL); + row++; + col=0; GtkWidget *panadapter_high_label=gtk_label_new("Panadapter High: "); //gtk_widget_override_font(panadapter_high_label, pango_font_description_from_string("Arial 18")); gtk_widget_show(panadapter_high_label); - gtk_grid_attach(GTK_GRID(grid),panadapter_high_label,0,3,1,1); + gtk_grid_attach(GTK_GRID(grid),panadapter_high_label,col,row,1,1); + + col++; 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)active_receiver->panadapter_high); gtk_widget_show(panadapter_high_r); - gtk_grid_attach(GTK_GRID(grid),panadapter_high_r,1,3,1,1); + gtk_grid_attach(GTK_GRID(grid),panadapter_high_r,col,row,1,1); g_signal_connect(panadapter_high_r,"value_changed",G_CALLBACK(panadapter_high_value_changed_cb),NULL); + row++; + col=0; + GtkWidget *panadapter_low_label=gtk_label_new("Panadapter Low: "); //gtk_widget_override_font(panadapter_low_label, pango_font_description_from_string("Arial 18")); gtk_widget_show(panadapter_low_label); - gtk_grid_attach(GTK_GRID(grid),panadapter_low_label,0,4,1,1); + gtk_grid_attach(GTK_GRID(grid),panadapter_low_label,col,row,1,1); + + col++; 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)active_receiver->panadapter_low); gtk_widget_show(panadapter_low_r); - gtk_grid_attach(GTK_GRID(grid),panadapter_low_r,1,4,1,1); + gtk_grid_attach(GTK_GRID(grid),panadapter_low_r,col,row,1,1); g_signal_connect(panadapter_low_r,"value_changed",G_CALLBACK(panadapter_low_value_changed_cb),NULL); + row++; + col=0; + + GtkWidget *panadapter_step_label=gtk_label_new("Panadapter Step: "); + //gtk_widget_override_font(panadapter_step_label, pango_font_description_from_string("Arial 18")); + gtk_widget_show(panadapter_step_label); + gtk_grid_attach(GTK_GRID(grid),panadapter_step_label,col,row,1,1); + + col++; + + GtkWidget *panadapter_step_r=gtk_spin_button_new_with_range(1.0,20.0,1.0); + //gtk_widget_override_font(panadapter_step_r, pango_font_description_from_string("Arial 18")); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(panadapter_step_r),(double)active_receiver->panadapter_step); + gtk_widget_show(panadapter_step_r); + gtk_grid_attach(GTK_GRID(grid),panadapter_step_r,col,row,1,1); + g_signal_connect(panadapter_step_r,"value_changed",G_CALLBACK(panadapter_step_value_changed_cb),NULL); + + row++; + col=0; + GtkWidget *waterfall_automatic_label=gtk_label_new("Waterfall Automatic: "); //gtk_widget_override_font(waterfall_automatic_label, pango_font_description_from_string("Arial 18")); gtk_widget_show(waterfall_automatic_label); - gtk_grid_attach(GTK_GRID(grid),waterfall_automatic_label,0,5,1,1); + gtk_grid_attach(GTK_GRID(grid),waterfall_automatic_label,col,row,1,1); + + col++; 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), active_receiver->waterfall_automatic); gtk_widget_show(waterfall_automatic_b); - gtk_grid_attach(GTK_GRID(grid),waterfall_automatic_b,1,5,1,1); + gtk_grid_attach(GTK_GRID(grid),waterfall_automatic_b,col,row,1,1); g_signal_connect(waterfall_automatic_b,"toggled",G_CALLBACK(waterfall_automatic_cb),NULL); + row++; + col=0; + GtkWidget *waterfall_high_label=gtk_label_new("Waterfall High: "); //gtk_widget_override_font(waterfall_high_label, pango_font_description_from_string("Arial 18")); gtk_widget_show(waterfall_high_label); - gtk_grid_attach(GTK_GRID(grid),waterfall_high_label,0,6,1,1); + gtk_grid_attach(GTK_GRID(grid),waterfall_high_label,col,row,1,1); + + col++; 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)active_receiver->waterfall_high); gtk_widget_show(waterfall_high_r); - gtk_grid_attach(GTK_GRID(grid),waterfall_high_r,1,6,1,1); + gtk_grid_attach(GTK_GRID(grid),waterfall_high_r,col,row,1,1); g_signal_connect(waterfall_high_r,"value_changed",G_CALLBACK(waterfall_high_value_changed_cb),NULL); + row++; + col=0; + GtkWidget *waterfall_low_label=gtk_label_new("Waterfall Low: "); //gtk_widget_override_font(waterfall_low_label, pango_font_description_from_string("Arial 18")); gtk_widget_show(waterfall_low_label); - gtk_grid_attach(GTK_GRID(grid),waterfall_low_label,0,7,1,1); + gtk_grid_attach(GTK_GRID(grid),waterfall_low_label,col,row,1,1); + + col++; 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)active_receiver->waterfall_low); gtk_widget_show(waterfall_low_r); - gtk_grid_attach(GTK_GRID(grid),waterfall_low_r,1,7,1,1); + gtk_grid_attach(GTK_GRID(grid),waterfall_low_r,col,row,1,1); g_signal_connect(waterfall_low_r,"value_changed",G_CALLBACK(waterfall_low_value_changed_cb),NULL); + col=2; + row=1; + GtkWidget *detector_mode_label=gtk_label_new("Detector: "); //gtk_widget_override_font(detector_mode_label, pango_font_description_from_string("Arial 18")); gtk_widget_show(detector_mode_label); - gtk_grid_attach(GTK_GRID(grid),detector_mode_label,2,1,1,1); + gtk_grid_attach(GTK_GRID(grid),detector_mode_label,col,row,1,1); + + row++; GtkWidget *detector_mode_peak=gtk_radio_button_new_with_label(NULL,"Peak"); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (detector_mode_peak), display_detector_mode==DETECTOR_MODE_PEAK); gtk_widget_show(detector_mode_peak); - gtk_grid_attach(GTK_GRID(grid),detector_mode_peak,2,2,1,1); + gtk_grid_attach(GTK_GRID(grid),detector_mode_peak,col,row,1,1); g_signal_connect(detector_mode_peak,"pressed",G_CALLBACK(detector_mode_cb),(gpointer *)DETECTOR_MODE_PEAK); + row++; + GtkWidget *detector_mode_rosenfell=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(detector_mode_peak),"Rosenfell"); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (detector_mode_rosenfell), display_detector_mode==DETECTOR_MODE_ROSENFELL); gtk_widget_show(detector_mode_rosenfell); - gtk_grid_attach(GTK_GRID(grid),detector_mode_rosenfell,2,3,1,1); + gtk_grid_attach(GTK_GRID(grid),detector_mode_rosenfell,col,row,1,1); g_signal_connect(detector_mode_rosenfell,"pressed",G_CALLBACK(detector_mode_cb),(gpointer *)DETECTOR_MODE_ROSENFELL); + row++; + GtkWidget *detector_mode_average=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(detector_mode_rosenfell),"Average"); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (detector_mode_average), display_detector_mode==DETECTOR_MODE_AVERAGE); gtk_widget_show(detector_mode_average); - gtk_grid_attach(GTK_GRID(grid),detector_mode_average,2,4,1,1); + gtk_grid_attach(GTK_GRID(grid),detector_mode_average,col,row,1,1); g_signal_connect(detector_mode_average,"pressed",G_CALLBACK(detector_mode_cb),(gpointer *)DETECTOR_MODE_AVERAGE); - GtkWidget *detector_mode_sample=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(detector_mode_average),"Sample"); + row++; + + GtkWidget *detector_mode_sample=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(detector_mode_average),"Sample"); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (detector_mode_sample), display_detector_mode==DETECTOR_MODE_SAMPLE); gtk_widget_show(detector_mode_sample); - gtk_grid_attach(GTK_GRID(grid),detector_mode_sample,2,5,1,1); + gtk_grid_attach(GTK_GRID(grid),detector_mode_sample,col,row,1,1); g_signal_connect(detector_mode_sample,"pressed",G_CALLBACK(detector_mode_cb),(gpointer *)DETECTOR_MODE_SAMPLE); + col=3; + row=1; GtkWidget *average_mode_label=gtk_label_new("Averaging: "); //gtk_widget_override_font(average_mode_label, pango_font_description_from_string("Arial 18")); gtk_widget_show(average_mode_label); - gtk_grid_attach(GTK_GRID(grid),average_mode_label,3,1,1,1); + gtk_grid_attach(GTK_GRID(grid),average_mode_label,col,row,1,1); + + row++; GtkWidget *average_mode_none=gtk_radio_button_new_with_label(NULL,"None"); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (average_mode_none), display_detector_mode==AVERAGE_MODE_NONE); gtk_widget_show(average_mode_none); - gtk_grid_attach(GTK_GRID(grid),average_mode_none,3,2,1,1); + gtk_grid_attach(GTK_GRID(grid),average_mode_none,col,row,1,1); g_signal_connect(average_mode_none,"pressed",G_CALLBACK(average_mode_cb),(gpointer *)AVERAGE_MODE_NONE); + row++; + GtkWidget *average_mode_recursive=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(average_mode_none),"Recursive"); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (average_mode_recursive), display_average_mode==AVERAGE_MODE_RECURSIVE); gtk_widget_show(average_mode_recursive); - gtk_grid_attach(GTK_GRID(grid),average_mode_recursive,3,3,1,1); + gtk_grid_attach(GTK_GRID(grid),average_mode_recursive,col,row,1,1); g_signal_connect(average_mode_recursive,"pressed",G_CALLBACK(average_mode_cb),(gpointer *)AVERAGE_MODE_RECURSIVE); + row++; + GtkWidget *average_mode_time_window=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(average_mode_recursive),"Time Window"); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (average_mode_time_window), display_average_mode==AVERAGE_MODE_TIME_WINDOW); gtk_widget_show(average_mode_time_window); - gtk_grid_attach(GTK_GRID(grid),average_mode_time_window,3,4,1,1); + gtk_grid_attach(GTK_GRID(grid),average_mode_time_window,col,row,1,1); g_signal_connect(average_mode_time_window,"pressed",G_CALLBACK(average_mode_cb),(gpointer *)AVERAGE_MODE_TIME_WINDOW); + row++; + GtkWidget *average_mode_log_recursive=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(average_mode_time_window),"Log Recursive"); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (average_mode_log_recursive), display_average_mode==AVERAGE_MODE_LOG_RECURSIVE); gtk_widget_show(average_mode_log_recursive); - gtk_grid_attach(GTK_GRID(grid),average_mode_log_recursive,3,5,1,1); + gtk_grid_attach(GTK_GRID(grid),average_mode_log_recursive,col,row,1,1); g_signal_connect(average_mode_log_recursive,"pressed",G_CALLBACK(average_mode_cb),(gpointer *)AVERAGE_MODE_LOG_RECURSIVE); + row++; GtkWidget *time_label=gtk_label_new("Time (ms): "); //gtk_widget_override_font(average_mode_label, pango_font_description_from_string("Arial 18")); gtk_widget_show(time_label); - gtk_grid_attach(GTK_GRID(grid),time_label,3,6,1,1); + gtk_grid_attach(GTK_GRID(grid),time_label,col,row,1,1); + + col++; GtkWidget *time_r=gtk_spin_button_new_with_range(1.0,9999.0,1.0); gtk_spin_button_set_value(GTK_SPIN_BUTTON(time_r),(double)display_average_time); gtk_widget_show(time_r); - gtk_grid_attach(GTK_GRID(grid),time_r,4,6,1,1); + gtk_grid_attach(GTK_GRID(grid),time_r,col,row,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); -*/ + row++; + row++; + row++; + col=1; + 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), active_receiver->display_waterfall); gtk_widget_show(b_display_waterfall); - gtk_grid_attach(GTK_GRID(grid),b_display_waterfall,1,8,1,1); + gtk_grid_attach(GTK_GRID(grid),b_display_waterfall,col,row,1,1); g_signal_connect(b_display_waterfall,"toggled",G_CALLBACK(display_waterfall_cb),(gpointer *)NULL); + col++; + GtkWidget *b_display_sliders=gtk_check_button_new_with_label("Display Sliders"); //gtk_widget_override_font(b_display_sliders, pango_font_description_from_string("Arial 18")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_display_sliders), display_sliders); gtk_widget_show(b_display_sliders); - gtk_grid_attach(GTK_GRID(grid),b_display_sliders,2,8,1,1); + gtk_grid_attach(GTK_GRID(grid),b_display_sliders,col,row,1,1); g_signal_connect(b_display_sliders,"toggled",G_CALLBACK(display_sliders_cb),(gpointer *)NULL); -/* + col++; + 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); + gtk_grid_attach(GTK_GRID(grid),b_display_toolbar,col,row,1,1); g_signal_connect(b_display_toolbar,"toggled",G_CALLBACK(display_toolbar_cb),(gpointer *)NULL); -*/ + gtk_container_add(GTK_CONTAINER(content),grid); sub_menu=dialog; diff --git a/diversity_menu.c b/diversity_menu.c index 4e084f1..f3df140 100644 --- a/diversity_menu.c +++ b/diversity_menu.c @@ -28,12 +28,15 @@ #include "diversity_menu.h" #include "radio.h" #include "new_protocol.h" +#include "sliders.h" #include static GtkWidget *parent_window=NULL; static GtkWidget *dialog=NULL; +static GtkWidget *gain_scale=NULL; +static GtkWidget *phase_scale=NULL; static GtkWidget *level; @@ -42,6 +45,8 @@ static void cleanup() { gtk_widget_destroy(dialog); dialog=NULL; sub_menu=NULL; + gain_scale=NULL; + phase_scale=NULL; } } @@ -68,24 +73,56 @@ static void diversity_cb(GtkWidget *widget, gpointer data) { // The DIVERSITY rotation parameters must be re-calculated // each time the gain or the phase changes. // -static void gain_value_changed_cb(GtkWidget *widget, gpointer data) { +static void set_gain(double gain) { double amplitude,arg; - div_gain=gtk_range_get_value(GTK_RANGE(widget)); + div_gain=gain; amplitude=pow(10.0, 0.05*div_gain); arg=div_phase*0.017453292519943295769236907684886; div_cos=amplitude*cos(arg); div_sin=amplitude*sin(arg); } -static void phase_value_changed_cb(GtkWidget *widget, gpointer data) { +static void gain_value_changed_cb(GtkWidget *widget, gpointer data) { + set_gain(gtk_range_get_value(GTK_RANGE(widget))); +} + +void update_diversity_gain(double increment) { + double g=div_gain+(increment/10); + if(g<-12.0) g=-12.0; + if(g>12.0) g=12.0; + if(gain_scale!=NULL) { + gtk_range_set_value(GTK_RANGE(gain_scale),div_gain); + } else { + show_diversity_gain(); + } + set_gain(g); +} + +static void set_phase(double phase) { double amplitude,arg; - div_phase=gtk_range_get_value(GTK_RANGE(widget)); + div_phase=phase; amplitude=pow(10.0, 0.05*div_gain); arg=div_phase*0.017453292519943295769236907684886; div_cos=amplitude*cos(arg); div_sin=amplitude*sin(arg); } +static void phase_value_changed_cb(GtkWidget *widget, gpointer data) { + set_phase(gtk_range_get_value(GTK_RANGE(widget))); +} + +void update_diversity_phase(double increment) { + double p=div_phase+increment; + if(p<0.0) p=360.0; + if(p>360.0) p=0.0; + if(phase_scale!=NULL) { + gtk_range_set_value(GTK_RANGE(phase_scale),div_phase); + } else { + show_diversity_phase(); + } + set_phase(p); +} + void diversity_menu(GtkWidget *parent) { int i; @@ -119,32 +156,32 @@ void diversity_menu(GtkWidget *parent) { GtkWidget *diversity_b=gtk_check_button_new_with_label("Diversity Enable"); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (diversity_b), diversity_enabled); gtk_widget_show(diversity_b); - gtk_grid_attach(GTK_GRID(grid),diversity_b,0,1,1,1); + gtk_grid_attach(GTK_GRID(grid),diversity_b,1,0,1,1); g_signal_connect(diversity_b,"toggled",G_CALLBACK(diversity_cb),NULL); GtkWidget *gain_label=gtk_label_new("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,2,1,1); + gtk_grid_attach(GTK_GRID(grid),gain_label,0,1,1,1); - GtkWidget *gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,-12.0,+12.0,0.1); + gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,-12.0,+12.0,0.1); gtk_widget_set_size_request (gain_scale, 300, 25); gtk_range_set_value(GTK_RANGE(gain_scale),div_gain); gtk_widget_show(gain_scale); - gtk_grid_attach(GTK_GRID(grid),gain_scale,1,2,1,1); + gtk_grid_attach(GTK_GRID(grid),gain_scale,1,1,1,1); g_signal_connect(G_OBJECT(gain_scale),"value_changed",G_CALLBACK(gain_value_changed_cb),NULL); GtkWidget *phase_label=gtk_label_new("Phase:"); gtk_misc_set_alignment (GTK_MISC(phase_label), 0, 0); gtk_widget_show(phase_label); - gtk_grid_attach(GTK_GRID(grid),phase_label,0,3,1,1); + gtk_grid_attach(GTK_GRID(grid),phase_label,0,2,1,1); - GtkWidget *phase_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0,360.0,1.0); + phase_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0,360.0,1.0); gtk_widget_set_size_request (phase_scale, 300, 25); gtk_range_set_value(GTK_RANGE(phase_scale),div_phase); gtk_widget_show(phase_scale); - gtk_grid_attach(GTK_GRID(grid),phase_scale,1,3,1,1); + gtk_grid_attach(GTK_GRID(grid),phase_scale,1,2,1,1); g_signal_connect(G_OBJECT(phase_scale),"value_changed",G_CALLBACK(phase_value_changed_cb),NULL); diff --git a/diversity_menu.h b/diversity_menu.h index 2530dae..b71588f 100644 --- a/diversity_menu.h +++ b/diversity_menu.h @@ -18,3 +18,5 @@ */ extern void diversity_menu(GtkWidget *parent); +extern void update_diversity_gain(double increment); +extern void update_diversity_phase(double increment); diff --git a/encoder_menu.c b/encoder_menu.c index e3d5af0..83d89ba 100644 --- a/encoder_menu.c +++ b/encoder_menu.c @@ -32,18 +32,25 @@ #include "vfo.h" #include "button_text.h" #include "gpio.h" +#ifdef CONTROLLER2 +#include "i2c.h" +#endif static GtkWidget *parent_window=NULL; static GtkWidget *dialog=NULL; -static GtkWidget *b_af_gain; -static GtkWidget *b_agc_gain; +static GtkWidget *b_af_gain_rx1; +static GtkWidget *b_af_gain_rx2; +static GtkWidget *b_agc_gain_rx1; +static GtkWidget *b_agc_gain_rx2; 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_rit_rx1; +static GtkWidget *b_rit_rx2; +static GtkWidget *b_xit; static GtkWidget *b_cw_speed; static GtkWidget *b_cw_frequency; static GtkWidget *b_panadapter_high; @@ -51,12 +58,62 @@ static GtkWidget *b_panadapter_low; static GtkWidget *b_squelch; static GtkWidget *b_compression; +#ifdef CONTROLLER2 +static GtkWidget *b_top_af_gain_rx1; +static GtkWidget *b_top_af_gain_rx2; +static GtkWidget *b_top_agc_gain_rx1; +static GtkWidget *b_top_agc_gain_rx2; +static GtkWidget *b_top_attenuation; +static GtkWidget *b_top_mic_gain; +static GtkWidget *b_top_drive; +static GtkWidget *b_top_tune_drive; +static GtkWidget *b_top_rit_rx1; +static GtkWidget *b_top_rit_rx2; +static GtkWidget *b_top_xit; +static GtkWidget *b_top_cw_speed; +static GtkWidget *b_top_cw_frequency; +static GtkWidget *b_top_panadapter_high; +static GtkWidget *b_top_panadapter_low; +static GtkWidget *b_top_squelch; +static GtkWidget *b_top_compression; +#endif + +enum { + ENC2, +#ifdef CONTROLLER2 + ENC2_TOP, +#endif + ENC2_SW, + ENC3, +#ifdef CONTROLLER2 + ENC3_TOP, +#endif + ENC3_SW, + ENC4, +#ifdef CONTROLLER2 + ENC4_TOP, +#endif + ENC4_SW, +#ifdef CONTROLLER2 + ENC5, + ENC5_TOP, + ENC5_SW, +#endif +}; + +typedef struct _choice { + int id; + int action; + GtkWidget *button; +} CHOICE; + static int encoder; static void cleanup() { if(dialog!=NULL) { gtk_widget_destroy(dialog); dialog=NULL; + active_menu=NO_MENU; sub_menu=NULL; } } @@ -71,60 +128,132 @@ static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_d return FALSE; } -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-1; - } - } if(pos<0) { - e1_encoder_action++; - if(e1_encoder_action>=ENCODER_LAST) { - e1_encoder_action=0; - } - } - action=e1_encoder_action; +static void enc_select_cb(GtkWidget *widget,gpointer data) { + CHOICE *choice=(CHOICE *)data; + switch(choice->id) { + case ENC2: + e2_encoder_action=choice->action; break; - case 2: - if(pos>0) { - e2_encoder_action--; - if(e2_encoder_action<0) { - e2_encoder_action=ENCODER_LAST-1; - } - } if(pos<0) { - e2_encoder_action++; - if(e2_encoder_action>=ENCODER_LAST) { - e2_encoder_action=0; - } - } - action=e2_encoder_action; +#ifdef CONTROLLER2 + case ENC2_TOP: + e2_top_encoder_action=choice->action; break; - case 3: - if(pos>0) { - e3_encoder_action--; - if(e3_encoder_action<0) { - e3_encoder_action=ENCODER_LAST-1; - } - } if(pos<0) { - e3_encoder_action++; - if(e3_encoder_action>=ENCODER_LAST) { - e3_encoder_action=0; - } - } - action=e3_encoder_action; +#endif + case ENC3: + e3_encoder_action=choice->action; + break; +#ifdef CONTROLLER2 + case ENC3_TOP: + e3_top_encoder_action=choice->action; + break; +#endif + case ENC4: + e4_encoder_action=choice->action; + break; +#ifdef CONTROLLER2 + case ENC4_TOP: + e4_top_encoder_action=choice->action; + break; +#endif +#ifdef CONTROLLER2 + case ENC5: + e5_encoder_action=choice->action; + break; + case ENC5_TOP: + e5_top_encoder_action=choice->action; + break; +#endif + } + gtk_button_set_label(GTK_BUTTON(choice->button),encoder_string[choice->action]); +} + +static gboolean enc_cb(GtkWidget *widget, GdkEvent *event, gpointer data) { + int enc=GPOINTER_TO_INT(data); + int i; + + GtkWidget *menu=gtk_menu_new(); + for(i=0;iid=enc; + choice->action=i; + choice->button=widget; + g_signal_connect(menu_item,"activate",G_CALLBACK(enc_select_cb),choice); + gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); + } + gtk_widget_show_all(menu); +#if GTK_CHECK_VERSION(3,22,0) + gtk_menu_popup_at_pointer(GTK_MENU(menu),(GdkEvent *)event); +// the following line of code is to work around the problem of the popup menu not having scroll bars. + gtk_menu_reposition(GTK_MENU(menu)); +#else + gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,0,gtk_get_current_event_time()); +#endif + + return TRUE; +} + +static void sw_select_cb(GtkWidget *widget,gpointer data) { + CHOICE *choice=(CHOICE *)data; + switch(choice->id) { + case ENC2_SW: + e2_sw_action=choice->action; + break; + case ENC3_SW: + e3_sw_action=choice->action; + break; + case ENC4_SW: + e4_sw_action=choice->action; + break; +#ifdef CONTROLLER2 + case ENC5_SW: + e5_sw_action=choice->action; break; +#endif } + gtk_button_set_label(GTK_BUTTON(choice->button),sw_string[choice->action]); +} + +static gboolean sw_cb(GtkWidget *widget, GdkEvent *event, gpointer data) { + int sw=GPOINTER_TO_INT(data); + int i; + GtkWidget *menu=gtk_menu_new(); + for(i=0;iid=sw; + choice->action=i; + choice->button=widget; + g_signal_connect(menu_item,"activate",G_CALLBACK(sw_select_cb),choice); + gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); + } + gtk_widget_show_all(menu); +#if GTK_CHECK_VERSION(3,22,0) + gtk_menu_popup_at_pointer(GTK_MENU(menu),(GdkEvent *)event); +// the following line of code is to work around the problem of the popup menu not having scroll bars. + gtk_menu_reposition(GTK_MENU(menu)); +#else + gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,0,gtk_get_current_event_time()); +#endif + + return TRUE; +} + +GtkWidget* getRadioButton(int action) { + GtkWidget* button; switch(action) { - case ENCODER_AF_GAIN: - button=b_af_gain; + case ENCODER_AF_GAIN_RX1: + button=b_af_gain_rx1; + break; + case ENCODER_AF_GAIN_RX2: + button=b_af_gain_rx2; + break; + case ENCODER_AGC_GAIN_RX1: + button=b_agc_gain_rx1; break; - case ENCODER_AGC_GAIN: - button=b_agc_gain; + case ENCODER_AGC_GAIN_RX2: + button=b_agc_gain_rx2; break; case ENCODER_ATTENUATION: button=b_attenuation; @@ -140,8 +269,11 @@ void encoder_select(int pos) { button=b_tune_drive; break; */ - case ENCODER_RIT: - button=b_rit; + case ENCODER_RIT_RX1: + button=b_rit_rx1; + break; + case ENCODER_RIT_RX2: + button=b_rit_rx2; break; case ENCODER_CW_SPEED: button=b_cw_speed; @@ -162,25 +294,493 @@ void encoder_select(int pos) { button=b_compression; break; } + return button; +} + +#ifdef CONTROLLER2 +GtkWidget* getTopRadioButton(int action) { + GtkWidget* button; + switch(action) { + case ENCODER_AF_GAIN_RX1: + button=b_top_af_gain_rx1; + break; + case ENCODER_AF_GAIN_RX2: + button=b_top_af_gain_rx2; + break; + case ENCODER_AGC_GAIN_RX1: + button=b_top_agc_gain_rx1; + break; + case ENCODER_AGC_GAIN_RX2: + button=b_top_agc_gain_rx2; + break; + case ENCODER_ATTENUATION: + button=b_top_attenuation; + break; + case ENCODER_MIC_GAIN: + button=b_top_mic_gain; + break; + case ENCODER_DRIVE: + button=b_top_drive; + break; +/* + case ENCODER_TUNE_DRIVE: + button=b_top_tune_drive; + break; +*/ + case ENCODER_RIT_RX1: + button=b_top_rit_rx1; + break; + case ENCODER_RIT_RX2: + button=b_top_rit_rx2; + break; + case ENCODER_CW_SPEED: + button=b_top_cw_speed; + break; + case ENCODER_CW_FREQUENCY: + button=b_top_cw_frequency; + break; + case ENCODER_PANADAPTER_HIGH: + button=b_top_panadapter_high; + break; + case ENCODER_PANADAPTER_LOW: + button=b_top_panadapter_low; + break; + case ENCODER_SQUELCH: + button=b_top_squelch; + break; + case ENCODER_COMP: + button=b_top_compression; + break; + } + return button; +} +#endif + + +static gboolean select_cb (GtkWidget *widget, gpointer data) { + GtkWidget *button; + int action; + + switch(encoder) { + case 2: + action=e2_encoder_action; + break; + case 3: + action=e3_encoder_action; + break; + case 4: + action=e4_encoder_action; + break; + case 5: + action=e5_encoder_action; + break; + } + button=getRadioButton(action); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); +} +#ifdef CONTROLLER2 +static gboolean top_select_cb (GtkWidget *widget, gpointer data) { + GtkWidget *button; + int action; + + switch(encoder) { + case 2: + action=e2_top_encoder_action; + break; + case 3: + action=e3_top_encoder_action; + break; + case 4: + action=e4_top_encoder_action; + break; + case 5: + action=e5_top_encoder_action; + break; + } + button=getTopRadioButton(action); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); } +#endif -static gboolean action_select_cb (GtkWidget *widget, gpointer data) { - int action=(int)data; +void encoder_select(int pos) { + int action; + GtkWidget *button; switch(encoder) { - case 1: - e1_encoder_action=action; + case 2: + if(pos>0) { + e2_encoder_action--; + if(e2_encoder_action<0) { + e2_encoder_action=ENCODER_ACTIONS-1; + } + } if(pos<0) { + e2_encoder_action++; + if(e2_encoder_action>=ENCODER_ACTIONS) { + 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_ACTIONS-1; + } + } if(pos<0) { + e3_encoder_action++; + if(e3_encoder_action>=ENCODER_ACTIONS) { + e3_encoder_action=0; + } + } + action=e3_encoder_action; + break; + case 4: + if(pos>0) { + e4_encoder_action--; + if(e4_encoder_action<0) { + e4_encoder_action=ENCODER_ACTIONS-1; + } + } if(pos<0) { + e4_encoder_action++; + if(e4_encoder_action>=ENCODER_ACTIONS) { + e4_encoder_action=0; + } + } + action=e4_encoder_action; + break; + } + + button=getRadioButton(action); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); + +} + +#ifdef CONTROLLER2 +void top_encoder_select(int pos) { + int action; + GtkWidget *button; + switch(encoder) { case 2: - e2_encoder_action=action; + if(pos>0) { + e2_top_encoder_action--; + if(e2_top_encoder_action<0) { + e2_top_encoder_action=ENCODER_ACTIONS-1; + } + } if(pos<0) { + e2_top_encoder_action++; + if(e2_top_encoder_action>=ENCODER_ACTIONS) { + e2_top_encoder_action=0; + } + } + action=e2_top_encoder_action; break; case 3: - e3_encoder_action=action; + if(pos>0) { + e3_top_encoder_action--; + if(e3_top_encoder_action<0) { + e3_top_encoder_action=ENCODER_ACTIONS-1; + } + } if(pos<0) { + e3_top_encoder_action++; + if(e3_top_encoder_action>=ENCODER_ACTIONS) { + e3_top_encoder_action=0; + } + } + action=e3_top_encoder_action; + break; + case 4: + if(pos>0) { + e4_top_encoder_action--; + if(e4_top_encoder_action<0) { + e4_top_encoder_action=ENCODER_ACTIONS-1; + } + } if(pos<0) { + e4_top_encoder_action++; + if(e4_top_encoder_action>=ENCODER_ACTIONS) { + e4_top_encoder_action=0; + } + } + action=e4_top_encoder_action; + break; + case 5: + if(pos>0) { + e5_top_encoder_action--; + if(e5_top_encoder_action<0) { + e5_top_encoder_action=ENCODER_ACTIONS-1; + } + } if(pos<0) { + e5_top_encoder_action++; + if(e5_top_encoder_action>=ENCODER_ACTIONS) { + e5_top_encoder_action=0; + } + } + action=e5_top_encoder_action; break; } + + button=getTopRadioButton(action); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); + +} +#endif + + static gboolean action_select_cb (GtkWidget *widget, gpointer data) { + int action=(int)data; + switch(encoder) { + case 2: + e2_encoder_action=action; + break; + case 3: + e3_encoder_action=action; + break; + case 4: + e4_encoder_action=action; + break; + case 5: + e5_encoder_action=action; + break; + } + } + +#ifdef CONTROLLER2 + static gboolean top_action_select_cb (GtkWidget *widget, gpointer data) { + int action=(int)data; + switch(encoder) { + case 2: + e2_top_encoder_action=action; + break; + case 3: + e3_top_encoder_action=action; + break; + case 4: + e4_top_encoder_action=action; + break; + case 5: + e5_top_encoder_action=action; + break; + } + } +#endif + + static gboolean enc2_cb(GtkWidget *widget, gpointer data) { + int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget)); + e2_encoder_action=i; + return TRUE; + } + + static gboolean enc2_sw_cb(GtkWidget *widget, gpointer data) { + int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget)); + e2_sw_action=i; + return TRUE; + } + + static gboolean enc3_cb(GtkWidget *widget, gpointer data) { + int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget)); + e3_encoder_action=i; + return TRUE; + } + + static gboolean enc3_sw_cb(GtkWidget *widget, gpointer data) { + int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget)); + e3_sw_action=i; + return TRUE; + } + + static gboolean enc4_cb(GtkWidget *widget, gpointer data) { + int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget)); + e4_encoder_action=i; + return TRUE; + } + + static gboolean enc4_sw_cb(GtkWidget *widget, gpointer data) { + int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget)); + e4_sw_action=i; + return TRUE; + } + +#ifdef CONTROLLER2 + static gboolean enc2_top_cb(GtkWidget *widget, gpointer data) { + int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget)); + e2_top_encoder_action=i; + return TRUE; + } + + static gboolean enc3_top_cb(GtkWidget *widget, gpointer data) { + int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget)); + e3_top_encoder_action=i; + return TRUE; + } + + static gboolean enc4_top_cb(GtkWidget *widget, gpointer data) { + int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget)); + e4_top_encoder_action=i; + return TRUE; + } + + static gboolean enc5_cb(GtkWidget *widget, gpointer data) { + int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget)); + e5_encoder_action=i; + return TRUE; + } + static gboolean enc5_sw_cb(GtkWidget *widget, gpointer data) { + int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget)); + e5_sw_action=i; + return TRUE; + } + + + static gboolean enc5_top_cb(GtkWidget *widget, gpointer data) { + int i=gtk_combo_box_get_active (GTK_COMBO_BOX(widget)); + e5_top_encoder_action=i; + return TRUE; + } +#endif + +void encoder_menu(GtkWidget *parent) { + int row=0; + int col=0; + int i; + + dialog=gtk_dialog_new(); + gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window)); + //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE); + char title[32]; + sprintf(title,"piHPSDR - Encoder Actions:"); + gtk_window_set_title(GTK_WINDOW(dialog),title); + g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), 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); + 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,col,row,1,1); + + row++; + col=1; +#ifdef CONTROLLER2 + GtkWidget *label_bottom=gtk_label_new("Bottom"); + gtk_grid_attach(GTK_GRID(grid),label_bottom,col,row,1,1); + col++; + GtkWidget *label_top=gtk_label_new("Top"); + gtk_grid_attach(GTK_GRID(grid),label_top,col,row,1,1); + col++; +#else + GtkWidget *label_encoder=gtk_label_new("Encoder"); + gtk_grid_attach(GTK_GRID(grid),label_encoder,col,row,1,1); + col++; +#endif + GtkWidget *label_switch=gtk_label_new("Switch"); + gtk_grid_attach(GTK_GRID(grid),label_switch,col,row,1,1); + col++; + + row++; + col=0; + + GtkWidget *enc2_title=gtk_label_new("ENC2: "); + gtk_grid_attach(GTK_GRID(grid),enc2_title,col,row,1,1); + col++; + + GtkWidget *enc2=gtk_button_new_with_label(encoder_string[e2_encoder_action]); + gtk_grid_attach(GTK_GRID(grid),enc2,col,row,1,1); + g_signal_connect(enc2,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC2)); + col++; + +#ifdef CONTROLLER2 + GtkWidget *enc2_top=gtk_button_new_with_label(encoder_string[e2_top_encoder_action]); + gtk_grid_attach(GTK_GRID(grid),enc2_top,col,row,1,1); + g_signal_connect(enc2_top,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC2_TOP)); + col++; +#endif + + GtkWidget *enc2_sw=gtk_button_new_with_label(sw_string[e2_sw_action]); + gtk_grid_attach(GTK_GRID(grid),enc2_sw,col,row,1,1); + g_signal_connect(enc2_sw,"button_press_event",G_CALLBACK(sw_cb),GINT_TO_POINTER(ENC2_SW)); + + row++; + col=0; + + GtkWidget *enc3_title=gtk_label_new("ENC3: "); + gtk_grid_attach(GTK_GRID(grid),enc3_title,col,row,1,1); + col++; + + GtkWidget *enc3=gtk_button_new_with_label(encoder_string[e3_encoder_action]); + gtk_grid_attach(GTK_GRID(grid),enc3,col,row,1,1); + g_signal_connect(enc3,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC3)); + col++; + +#ifdef CONTROLLER2 + GtkWidget *enc3_top=gtk_button_new_with_label(encoder_string[e3_top_encoder_action]); + gtk_grid_attach(GTK_GRID(grid),enc3_top,col,row,1,1); + g_signal_connect(enc3_top,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC3_TOP)); + col++; +#endif + + GtkWidget *enc3_sw=gtk_button_new_with_label(sw_string[e3_sw_action]); + gtk_grid_attach(GTK_GRID(grid),enc3_sw,col,row,1,1); + g_signal_connect(enc3_sw,"button_press_event",G_CALLBACK(sw_cb),GINT_TO_POINTER(ENC3_SW)); + + row++; + col=0; + + GtkWidget *enc4_title=gtk_label_new("ENC4: "); + gtk_grid_attach(GTK_GRID(grid),enc4_title,col,row,1,1); + col++; + + GtkWidget *enc4=gtk_button_new_with_label(encoder_string[e4_encoder_action]); + gtk_grid_attach(GTK_GRID(grid),enc4,col,row,1,1); + g_signal_connect(enc4,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC4)); + col++; + +#ifdef CONTROLLER2 + GtkWidget *enc4_top=gtk_button_new_with_label(encoder_string[e4_top_encoder_action]); + gtk_grid_attach(GTK_GRID(grid),enc4_top,col,row,1,1); + g_signal_connect(enc4_top,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC4_TOP)); + col++; +#endif + + GtkWidget *enc4_sw=gtk_button_new_with_label(sw_string[e4_sw_action]); + gtk_grid_attach(GTK_GRID(grid),enc4_sw,col,row,1,1); + g_signal_connect(enc4_sw,"button_press_event",G_CALLBACK(sw_cb),GINT_TO_POINTER(ENC4_SW)); + + row++; + col=0; + +#ifdef CONTROLLER2 + GtkWidget *enc5_title=gtk_label_new("ENC5: "); + gtk_grid_attach(GTK_GRID(grid),enc5_title,col,row,1,1); + col++; + + GtkWidget *enc5=gtk_button_new_with_label(encoder_string[e5_encoder_action]); + gtk_grid_attach(GTK_GRID(grid),enc5,col,row,1,1); + g_signal_connect(enc5,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC5)); + col++; + + GtkWidget *enc5_top=gtk_button_new_with_label(encoder_string[e5_top_encoder_action]); + gtk_grid_attach(GTK_GRID(grid),enc5_top,col,row,1,1); + g_signal_connect(enc5_top,"button_press_event",G_CALLBACK(enc_cb),GINT_TO_POINTER(ENC5_TOP)); + col++; + + GtkWidget *enc5_sw=gtk_button_new_with_label(sw_string[e5_sw_action]); + gtk_grid_attach(GTK_GRID(grid),enc5_sw,col,row,1,1); + g_signal_connect(enc5_sw,"button_press_event",G_CALLBACK(sw_cb),GINT_TO_POINTER(ENC5_SW)); +#endif + + gtk_container_add(GTK_CONTAINER(content),grid); + + sub_menu=dialog; + + gtk_widget_show_all(dialog); } +/* void encoder_menu(GtkWidget *parent,int e) { GtkWidget *b; int i; @@ -189,17 +789,42 @@ void encoder_menu(GtkWidget *parent,int e) { encoder=e; int encoder_action; +#ifdef CONTROLLER2 + int top_encoder_action; +#endif 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; + case 4: + encoder_action=e4_encoder_action; + break; +#ifdef CONTROLLER2 + case 5: + encoder_action=e5_encoder_action; + break; +#endif } +#ifdef CONTROLLER2 + switch(encoder) { + case 2: + top_encoder_action=e2_top_encoder_action; + break; + case 3: + top_encoder_action=e3_top_encoder_action; + break; + case 4: + top_encoder_action=e4_top_encoder_action; + break; + case 5: + top_encoder_action=e5_top_encoder_action; + break; + } +#endif + parent_window=parent; dialog=gtk_dialog_new(); @@ -236,25 +861,49 @@ void encoder_menu(GtkWidget *parent,int e) { row++; col=0; - 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,col,row,2,1); - g_signal_connect(b_af_gain,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_AF_GAIN); +#ifdef CONTROLLER2 + GtkWidget *bottom_title=gtk_label_new("Bottom"); + gtk_grid_attach(GTK_GRID(grid),bottom_title,col,row,4,1); + + row++; + col=0; +#endif + + b_af_gain_rx1=gtk_radio_button_new_with_label(NULL,"AF Gain RX1"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_af_gain_rx1), encoder_action==ENCODER_AF_GAIN_RX1); + gtk_widget_show(b_af_gain_rx1); + gtk_grid_attach(GTK_GRID(grid),b_af_gain_rx1,col,row,2,1); + g_signal_connect(b_af_gain_rx1,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_AF_GAIN_RX1); row++; - 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,col,row,2,1); - g_signal_connect(b_agc_gain,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_AGC_GAIN); + b_af_gain_rx2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_af_gain_rx1),"AF Gain RX2"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_af_gain_rx2), encoder_action==ENCODER_AF_GAIN_RX2); + gtk_widget_show(b_af_gain_rx2); + gtk_grid_attach(GTK_GRID(grid),b_af_gain_rx2,col,row,2,1); + g_signal_connect(b_af_gain_rx2,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_AF_GAIN_RX2); + + row++; + + b_agc_gain_rx1=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_af_gain_rx2),"AGC Gain RX1"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_agc_gain_rx1), encoder_action==ENCODER_AGC_GAIN_RX1); + gtk_widget_show(b_agc_gain_rx1); + gtk_grid_attach(GTK_GRID(grid),b_agc_gain_rx1,col,row,2,1); + g_signal_connect(b_agc_gain_rx1,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_AGC_GAIN_RX1); + + row++; + + b_agc_gain_rx2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_agc_gain_rx1),"AGC Gain RX2"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_agc_gain_rx2), encoder_action==ENCODER_AGC_GAIN_RX2); + gtk_widget_show(b_agc_gain_rx2); + gtk_grid_attach(GTK_GRID(grid),b_agc_gain_rx2,col,row,2,1); + g_signal_connect(b_agc_gain_rx2,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_AGC_GAIN_RX2); row++; #ifdef RADIOBERRY - b_attenuation=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_agc_gain),"RX GAIN"); + b_attenuation=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_agc_gain_rx2),"RX GAIN"); #else - b_attenuation=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_agc_gain),"Attenuation"); + b_attenuation=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_agc_gain_rx2),"Attenuation"); #endif gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_attenuation), encoder_action==ENCODER_ATTENUATION); gtk_widget_show(b_attenuation); @@ -277,18 +926,32 @@ void encoder_menu(GtkWidget *parent,int e) { gtk_grid_attach(GTK_GRID(grid),b_drive,col,row,2,1); g_signal_connect(b_drive,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_DRIVE); + b_xit=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_drive),"XIT"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_xit), encoder_action==ENCODER_XIT); + gtk_widget_show(b_xit); + gtk_grid_attach(GTK_GRID(grid),b_xit,col,row,2,1); + g_signal_connect(b_xit,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_XIT); + + col++; + row=1; + + b_rit_rx1=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_drive),"RIT RX1"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_rit_rx1), encoder_action==ENCODER_RIT_RX1); + gtk_widget_show(b_rit_rx1); + gtk_grid_attach(GTK_GRID(grid),b_rit_rx1,col,row,2,1); + g_signal_connect(b_rit_rx1,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_RIT_RX1); + row++; - b_rit=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_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,col,row,2,1); - g_signal_connect(b_rit,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_RIT); + b_rit_rx2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_rit_rx1),"RIT RX2"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_rit_rx2), encoder_action==ENCODER_RIT_RX2); + gtk_widget_show(b_rit_rx2); + gtk_grid_attach(GTK_GRID(grid),b_rit_rx2,col,row,2,1); + g_signal_connect(b_rit_rx2,"pressed",G_CALLBACK(action_select_cb),(gpointer *)ENCODER_RIT_RX2); - col=2; - row=1; + row++; - b_cw_speed=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_rit),"CW Speed"); + b_cw_speed=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_rit_rx2),"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,col,row,2,1); @@ -341,3 +1004,4 @@ void encoder_menu(GtkWidget *parent,int e) { gtk_widget_show_all(dialog); } +*/ diff --git a/encoder_menu.h b/encoder_menu.h index 8b45595..3f42272 100644 --- a/encoder_menu.h +++ b/encoder_menu.h @@ -20,7 +20,7 @@ #ifndef _ENCODER_MENU_H #define _ENCODER_MENU_H -extern void encoder_menu(GtkWidget *parent,int e); +extern void encoder_menu(GtkWidget *parent); extern void encoder_select(int pos); #endif diff --git a/exit_menu.c b/exit_menu.c index 3f09a72..a671a10 100644 --- a/exit_menu.c +++ b/exit_menu.c @@ -27,6 +27,9 @@ #include "radio.h" #include "new_protocol.h" #include "old_protocol.h" +#ifdef SOAPYSDR +#include "soapy_protocol.h" +#endif #ifdef GPIO #include "gpio.h" #endif @@ -66,9 +69,9 @@ static gboolean exit_cb (GtkWidget *widget, GdkEventButton *event, gpointer data case NEW_PROTOCOL: new_protocol_stop(); break; -#ifdef LIMESDR - case LIMESDR_PROTOCOL: - lime_protocol_stop(); +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: + soapy_protocol_stop(); break; #endif } @@ -87,9 +90,9 @@ static gboolean reboot_cb (GtkWidget *widget, GdkEventButton *event, gpointer da case NEW_PROTOCOL: new_protocol_stop(); break; -#ifdef LIMESDR - case LIMESDR_PROTOCOL: - lime_protocol_stop(); +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: + soapy_protocol_stop(); break; #endif } @@ -109,9 +112,9 @@ static gboolean shutdown_cb (GtkWidget *widget, GdkEventButton *event, gpointer case NEW_PROTOCOL: new_protocol_stop(); break; -#ifdef LIMESDR - case LIMESDR_PROTOCOL: - lime_protocol_stop(); +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: + soapy_protocol_stop(); break; #endif } diff --git a/ext.c b/ext.c index 1379c5c..e8e02ba 100644 --- a/ext.c +++ b/ext.c @@ -27,13 +27,19 @@ #include "sliders.h" #include "toolbar.h" #include "band_menu.h" +#include "diversity_menu.h" #include "vfo.h" #include "radio.h" #include "new_menu.h" +#include "new_protocol.h" #ifdef PURESIGNAL #include "ps_menu.h" #endif +#include "agc.h" +#include "filter.h" #include "band.h" +#include "bandstack.h" +#include "wdsp.h" // The following calls functions can be called usig g_idle_add @@ -96,6 +102,11 @@ int ext_band_update(void *data) { return 0; } +int ext_bandstack_update(void *data) { + start_bandstack(); + return 0; +} + int ext_mode_update(void *data) { start_mode(); return 0; @@ -106,28 +117,38 @@ int ext_filter_update(void *data) { return 0; } +int ext_frequency_update(void *data) { + start_vfo(); + return 0; +} + +int ext_memory_update(void *data) { + start_store(); + return 0; +} + int ext_noise_update(void *data) { start_noise(); return 0; } int ext_mox_update(void *data) { - mox_update((int)(uintptr_t)data); + mox_update(GPOINTER_TO_INT(data)); return 0; } int ext_tune_update(void *data) { - tune_update((int)(uintptr_t)data); + tune_update(GPOINTER_TO_INT(data)); return 0; } int ext_vox_changed(void *data) { - vox_changed((int)(uintptr_t)data); + vox_changed(GPOINTER_TO_INT(data)); return 0; } int ext_update_agc_gain(void *data) { - update_agc_gain(*(double *)data); + update_agc_gain(GPOINTER_TO_INT(data)); free(data); return 0; } @@ -143,12 +164,12 @@ int ext_calc_drive_level(void *data) { } int ext_vfo_band_changed(void *data) { - vfo_band_changed((int)(uintptr_t)data); + vfo_band_changed(GPOINTER_TO_INT(data)); return 0; } int ext_radio_change_sample_rate(void *data) { - radio_change_sample_rate((int)(uintptr_t)data); + radio_change_sample_rate(GPOINTER_TO_INT(data)); return 0; } @@ -185,7 +206,7 @@ int ext_set_mic_gain(void * data) { int ext_set_agc_gain(void *data) { double d=*(double *)data; - set_agc_gain(d); + set_agc_gain(active_receiver->id,d); free(data); return 0; } @@ -223,7 +244,7 @@ int ext_update_att_preamp(void *data) { } int ext_set_alex_attenuation(void *data) { - int val=(int)(uintptr_t)data; + int val=GPOINTER_TO_INT(data); set_alex_attenuation(val); return 0; } @@ -234,3 +255,239 @@ int ext_set_attenuation_value(void *data) { free(data); return 0; } + + +#ifdef PURESIGNAL +int ext_ps_update(void *data) { + if(transmitter->puresignal==0) { + tx_set_ps(transmitter,1); + } else { + tx_set_ps(transmitter,0); + } + return 0; +} +#endif + +int ext_two_tone(void *data) { + int state=transmitter->twotone?0:1; + tx_set_twotone(transmitter,state); + return 0; +} + +int ext_nr_update(void *data) { + if(active_receiver->nr==0 && active_receiver->nr2==0) { + active_receiver->nr=1; + active_receiver->nr2=0; + mode_settings[vfo[active_receiver->id].mode].nr=1; + mode_settings[vfo[active_receiver->id].mode].nr2=0; + } else if(active_receiver->nr==1 && active_receiver->nr2==0) { + active_receiver->nr=0; + active_receiver->nr2=1; + mode_settings[vfo[active_receiver->id].mode].nr=0; + mode_settings[vfo[active_receiver->id].mode].nr2=1; + } else if(active_receiver->nr==0 && active_receiver->nr2==1) { + active_receiver->nr=0; + active_receiver->nr2=0; + mode_settings[vfo[active_receiver->id].mode].nr=0; + mode_settings[vfo[active_receiver->id].mode].nr2=0; + } + SetRXAANRRun(active_receiver->id, active_receiver->nr); + SetRXAEMNRRun(active_receiver->id, active_receiver->nr2); + vfo_update(); + return 0; +} + +int ext_nb_update(void *data) { + if(active_receiver->nb==0 && active_receiver->nb2==0) { + active_receiver->nb=1; + active_receiver->nb2=0; + mode_settings[vfo[active_receiver->id].mode].nb=1; + mode_settings[vfo[active_receiver->id].mode].nb2=0; + } else if(active_receiver->nb==1 && active_receiver->nb2==0) { + active_receiver->nb=0; + active_receiver->nb2=1; + mode_settings[vfo[active_receiver->id].mode].nb=0; + mode_settings[vfo[active_receiver->id].mode].nb2=1; + } else if(active_receiver->nb==0 && active_receiver->nb2==1) { + active_receiver->nb=0; + active_receiver->nb2=0; + mode_settings[vfo[active_receiver->id].mode].nb=0; + mode_settings[vfo[active_receiver->id].mode].nb2=0; + } + SetEXTANBRun(active_receiver->id, active_receiver->nb); + SetEXTNOBRun(active_receiver->id, active_receiver->nb2); + vfo_update(); + return 0; +} + +int ext_snb_update(void *data) { + if(active_receiver->snb==0) { + active_receiver->snb=1; + mode_settings[vfo[active_receiver->id].mode].snb=1; + } else { + active_receiver->snb=0; + mode_settings[vfo[active_receiver->id].mode].snb=0; + } + SetRXASNBARun(active_receiver->id, active_receiver->snb); + vfo_update(); + return 0; +} + +int ext_band_plus(void *data) { + int id=active_receiver->id; + int b=vfo[id].band; + b++; + if(b>=BANDS) b=0; + vfo_band_changed(b); + return 0; +} + + +int ext_band_minus(void *data) { + int id=active_receiver->id; + int b=vfo[id].band; + b--; + if(b<0) b=BANDS-1; + vfo_band_changed(b); + return 0; +} + +int ext_bandstack_plus(void *data) { + BAND *band=band_get_band(vfo[active_receiver->id].band); + BANDSTACK *bandstack=band->bandstack; + int b=vfo[active_receiver->id].bandstack+1; + if(b>=bandstack->entries) b=0; + vfo_bandstack_changed(b); + return 0; +} + +int ext_bandstack_minus(void *data) { + BAND *band=band_get_band(vfo[active_receiver->id].band); + BANDSTACK *bandstack=band->bandstack; + int b=vfo[active_receiver->id].bandstack-1; + if(b<0) b=bandstack->entries-1;; + vfo_bandstack_changed(b); + return 0; +} + +int ext_lock_update(void *data) { + locked=locked==1?0:1; + vfo_update(); + return 0; +} + +int ext_rit_update(void *data) { + vfo[active_receiver->id].rit_enabled=vfo[active_receiver->id].rit_enabled==1?0:1; + if(protocol==NEW_PROTOCOL) { + schedule_high_priority(); + } + vfo_update(); + return 0; +} + +int ext_rit_clear(void *data) { + vfo[active_receiver->id].rit=0; + vfo_update(); + return 0; +} + +int ext_xit_update(void *data) { + return 0; +} + +int ext_xit_clear(void *data) { + return 0; +} + +int ext_filter_plus(void *data) { + int f=vfo[active_receiver->id].filter-1; + if(f<0) f=FILTERS-1; + vfo_filter_changed(f); + return 0; +} + +int ext_filter_minus(void *data) { + int f=vfo[active_receiver->id].filter+1; + if(f>=FILTERS) f=0; + vfo_filter_changed(f); + return 0; +} + +int ext_mode_plus(void *data) { + int mode=vfo[active_receiver->id].mode; + mode++; + if(mode>=MODES) mode=0; + vfo_mode_changed(mode); + return 0; +} + +int ext_mode_minus(void *data) { + int mode=vfo[active_receiver->id].mode; + mode--; + if(mode<0) mode=MODES-1; + vfo_mode_changed(mode); + return 0; +} + +int ext_ctun_update(void *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(); + return 0; +} + +int ext_agc_update(void *data) { + active_receiver->agc++; + if(active_receiver->agc>+AGC_LAST) { + active_receiver->agc=0; + } + set_agc(active_receiver, active_receiver->agc); + vfo_update(); + return 0; +} + +int ext_split_update(void *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(); + return 0; +} + +int ext_start_rx(void *data) { + start_rx(); + return 0; +} + +int ext_diversity_update(void *data) { + int menu=GPOINTER_TO_INT(data); + if(menu) { + start_diversity(); + } else { + diversity_enabled=diversity_enabled==1?0:1; + if (protocol == NEW_PROTOCOL) { + schedule_high_priority(); + schedule_receive_specific(); + } + vfo_update(); + } + return 0; +} + +int ext_function_update(void *data) { + function++; + if(function>MAX_FUNCTION) { + function=0; + } + update_toolbar_labels(); + vfo_update(); +} + diff --git a/ext.h b/ext.h index 97ab829..ac99555 100644 --- a/ext.h +++ b/ext.h @@ -28,6 +28,7 @@ extern int ext_vfo_update(void *data); extern int ext_set_frequency(void *data); extern int ext_vfo_filter_changed(void *data); extern int ext_band_update(void *data); +extern int ext_bandstack_update(void *data); extern int ext_mox_update(void *data); extern int ext_tune_update(void *data); extern int ext_linein_changed(void *data); @@ -39,6 +40,32 @@ extern int ext_calc_drive_level(void *data); extern int ext_vfo_band_changed(void *data); extern int ext_radio_change_sample_rate(void *data); +extern int ext_ps_update(void *data); +extern int ext_two_tone(void *data); +extern int ext_nr_update(void *data); +extern int ext_nb_update(void *data); +extern int ext_snb_update(void *data); +extern int ext_band_plus(void *data); +extern int ext_band_minus(void *data); +extern int ext_bandstack_plus(void *data); +extern int ext_bandstack_minus(void *data); +extern int ext_a_to_b(void *data); +extern int ext_lock_update(void *data); +extern int ext_rit_update(void *data); +extern int ext_rit_clear(void *data); +extern int ext_xit_update(void *data); +extern int ext_xit_clear(void *data); +extern int ext_filter_plus(void *data); +extern int ext_filter_minus(void *data); +extern int ext_mode_plus(void *data); +extern int ext_mode_minus(void *data); +extern int ext_b_to_a(void *data); +extern int ext_a_swap_b(void *data); +extern int ext_ctun_update(void *data); +extern int ext_agc_update(void *data); +extern int ext_split_update(void *data); + + extern int ext_cw_setup(); extern int ext_cw_key(void *data); @@ -50,6 +77,10 @@ extern int ext_mode_update(void *data); extern int ext_filter_update(void *data); extern int ext_noise_update(void *data); +extern int ext_frequency_update(void *data); +extern int ext_memory_update(void *data); +extern int ext_function_update(void *data); + #ifdef PURESIGNAL extern int ext_tx_set_ps(void *data); #endif @@ -67,3 +98,6 @@ int ext_update_att_preamp(void *data); int ext_set_alex_attenuation(void *data); int ext_set_attenuation_value(void *data); int ext_set_compression(void *data); + +int ext_start_rx(void *data); +int ext_diversity_update(void *data); diff --git a/filter.c b/filter.c index 86c1ad8..28043af 100644 --- a/filter.c +++ b/filter.c @@ -20,7 +20,11 @@ #include #include +#include "sliders.h" #include "filter.h" +#include "receiver.h" +#include "vfo.h" +#include "radio.h" #include "property.h" FILTER filterLSB[FILTERS]={ @@ -431,3 +435,26 @@ void filterRestoreState() { } +void filter_width_changed(int rx,int increment) { + int id=receiver[rx]->id; + FILTER *mode_filters=filters[vfo[id].mode]; + FILTER *filter=&mode_filters[vfo[id].filter]; + +fprintf(stderr,"filter_width_changed: rx=%d mode=%d filter=%d increment=%d\n",rx,vfo[id].mode,vfo[id].filter,increment); + + if(vfo[id].filter==filterVar1 || vfo[id].filter==filterVar2) { + filter->high=filter->high+increment; +fprintf(stderr,"filter->low=%d filter->high=%d\n",filter->low,filter->high); + if(vfo[id].mode==modeCWL || vfo[id].mode==modeCWU) { + filter->low=filter->high; + } + vfo_filter_changed(vfo[id].filter); + int width=filter->high-filter->low; + if(vfo[id].mode==modeCWL || vfo[id].mode==modeCWU) { + width=filter->high; + } else { + if(width<0) width=filter->low-filter->high; + } + set_filter_width(id,width); + } +} diff --git a/filter.h b/filter.h index ea95003..1e1b463 100644 --- a/filter.h +++ b/filter.h @@ -59,4 +59,5 @@ FILTER *filters[MODES]; void filterSaveState(); void filterRestoreState(); +void filter_width_changed(int rx,int increment); #endif diff --git a/frequency.c b/frequency.c index d69fe76..53d6dff 100644 --- a/frequency.c +++ b/frequency.c @@ -326,39 +326,7 @@ struct frequency_info frequencyInfo[]= { 1296800000LL, 1296999999LL, "23CM Experimental Beacons", NOBAND, TRUE }, { 1297000000LL, 1300000000LL, "23CM Digital Modes", NOBAND, TRUE }, - { 2300000000LL, 2302999999LL, "2.3GHz High Data Rate", NOBAND, TRUE }, - { 2303000000LL, 2303499999LL, "2.3GHz Packet", NOBAND, TRUE }, - { 2303500000LL, 2303800000LL, "2.3GHz TTY Packet", NOBAND, TRUE }, - { 2303800001LL, 2303899999LL, "2.3GHz General", NOBAND, TRUE }, - { 2303900000LL, 2303900000LL, "2.3GHz Packet/TTY/CW/EME", NOBAND, TRUE }, - { 2303900001LL, 2304099999LL, "2.3GHz CW/EME", NOBAND, TRUE }, - { 2304100000LL, 2304100000LL, "2.3GHz Calling Frequency", NOBAND, TRUE }, - { 2304100001LL, 2304199999LL, "2.3GHz CW/EME/SSB", NOBAND, TRUE }, - { 2304200000LL, 2304299999LL, "2.3GHz SSB/SSTV/FAX/Packet AM/Amtor",NOBAND, TRUE }, - { 2304300000LL, 2304319999LL, "2.3GHz Propagation Beacon Network", NOBAND, TRUE }, - { 2304320000LL, 2304399999LL, "2.3GHz General Propagation Beacons", NOBAND, TRUE }, - { 2304400000LL, 2304499999LL, "2.3GHz SSB/SSTV/ACSSB/FAX/Packet AM",NOBAND, TRUE }, - { 2304500000LL, 2304699999LL, "2.3GHz X-Band Translator Input", NOBAND, TRUE }, - { 2304700000LL, 2304899999LL, "2.3GHz X-Band Translator Output", NOBAND, TRUE }, - { 2304900000LL, 2304999999LL, "2.3GHz Experimental Beacons", NOBAND, TRUE }, - { 2305000000LL, 2305199999LL, "2.3GHz FM Simplex", NOBAND, TRUE }, - { 2305200000LL, 2305200000LL, "2.3GHz FM Simplex Calling", NOBAND, TRUE }, - { 2305200001LL, 2305999999LL, "2.3GHz FM Simplex", NOBAND, TRUE }, - { 2306000000LL, 2308999999LL, "2.3GHz FM Repeaters", NOBAND, TRUE }, - { 2309000000LL, 2310000000LL, "2.3GHz Control/Aux Links", NOBAND, TRUE }, - { 2390000000LL, 2395999999LL, "2.3GHz Fast-Scan TV", NOBAND, TRUE }, - { 2396000000LL, 2398999999LL, "2.3GHz High Rate Data", NOBAND, TRUE }, - { 2399000000LL, 2399499999LL, "2.3GHz Packet", NOBAND, TRUE }, - { 2399500000LL, 2399999999LL, "2.3GHz Control/Aux Links", NOBAND, TRUE }, - { 2400000000LL, 2402999999LL, "2.4GHz Satellite", NOBAND, TRUE }, - { 2403000000LL, 2407999999LL, "2.4GHz Satellite High-Rate Data", NOBAND, TRUE }, - { 2408000000LL, 2409999999LL, "2.4GHz Satellite", NOBAND, TRUE }, - { 2410000000LL, 2412999999LL, "2.4GHz FM Repeaters", NOBAND, TRUE }, - { 2413000000LL, 2417999999LL, "2.4GHz High-Rate Data", NOBAND, TRUE }, - { 2418000000LL, 2429999999LL, "2.4GHz Fast-Scan TV", NOBAND, TRUE }, - { 2430000000LL, 2432999999LL, "2.4GHz Satellite", NOBAND, TRUE }, - { 2433000000LL, 2437999999LL, "2.4GHz Sat High-Rate Data", NOBAND, TRUE }, - { 2438000000LL, 2450000000LL, "2.4GHz Wideband FM/FSTV/FMTV", NOBAND, TRUE }, + { 2300000000LL, 2449999999LL, "13cm", NOBAND, TRUE }, { 3456000000LL, 3456099999LL, "3.4GHz General", NOBAND, TRUE }, { 3456100000LL, 3456100000LL, "3.4GHz Calling Frequency", NOBAND, TRUE }, @@ -370,9 +338,7 @@ struct frequency_info frequencyInfo[]= { 5760100001LL, 5760299999LL, "5.7GHz General", NOBAND, TRUE }, { 5760300000LL, 5760400000LL, "5.7GHz Propagation Beacons", NOBAND, TRUE }, - {10368000000LL, 10368099999LL, "10GHz General", NOBAND, TRUE }, - {10368100000LL, 10368100000LL, "10GHz Calling Frequency", NOBAND, TRUE }, - {10368100001LL, 10368400000LL, "10GHz General", NOBAND, TRUE }, + {10000000000LL, 10499999999LL, "10GHz", NOBAND, TRUE }, {24192000000LL, 24192099999LL, "24GHz General", NOBAND, TRUE }, {24192100000LL, 24192100000LL, "24GHz Calling Frequency", NOBAND, TRUE }, diff --git a/general_menu.c b/general_menu.c index 9168544..01e173f 100644 --- a/general_menu.c +++ b/general_menu.c @@ -269,8 +269,8 @@ void general_menu(GtkWidget *parent) { } -#ifdef LIMESDR - if(protocol==LIMESDR_PROTOCOL) { +#ifdef SOAPYSDR + if(protocol==SOAPYSDR_PROTOCOL) { GtkWidget *sample_rate_1M=gtk_radio_button_new_with_label(NULL,"1000000"); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_1M), sample_rate==1000000); gtk_grid_attach(GTK_GRID(grid),sample_rate_1M,0,2,1,1); diff --git a/gpio.c b/gpio.c index dccc90f..a69196b 100644 --- a/gpio.c +++ b/gpio.c @@ -50,6 +50,7 @@ #endif #include "new_menu.h" #include "encoder_menu.h" +#include "diversity_menu.h" #include "gpio.h" #ifdef CONTROLLER2 #include "i2c.h" @@ -76,31 +77,39 @@ int VFO_ENCODER_B=0; #ifdef VFO_HAS_FUNCTION int VFO_FUNCTION=12; #endif -int ENABLE_E1_ENCODER=1; -int ENABLE_E1_PULLUP=0; -int E1_ENCODER_A=28; -int E1_ENCODER_B=25; -int E1_FUNCTION=3; int ENABLE_E2_ENCODER=1; -int ENABLE_E2_PULLUP=0; -int E2_ENCODER_A=7; -int E2_ENCODER_B=29; -int E2_FUNCTION=2; +int ENABLE_E2_PULLUP=1; +int E2_ENCODER_A=21; +int E2_ENCODER_B=22; +int E2_TOP_ENCODER_A=25; +int E2_TOP_ENCODER_B=28; +int E2_FUNCTION=3; int ENABLE_E3_ENCODER=1; -int ENABLE_E3_PULLUP=0; -int E3_ENCODER_A=27; -int E3_ENCODER_B=24; -int E3_FUNCTION=4; +int ENABLE_E3_PULLUP=1; +int E3_ENCODER_A=13; +int E3_ENCODER_B=11; +int E3_TOP_ENCODER_A=29; +int E3_TOP_ENCODER_B=7; +int E3_FUNCTION=2; int ENABLE_E4_ENCODER=1; -int ENABLE_E4_PULLUP=0; -int E4_ENCODER_A=6; -int E4_ENCODER_B=10; -int E4_FUNCTION=5; +int ENABLE_E4_PULLUP=1; +int E4_ENCODER_A=14; +int E4_ENCODER_B=12; +int E4_TOP_ENCODER_A=24; +int E4_TOP_ENCODER_B=27; +int E4_FUNCTION=4; +int ENABLE_E5_ENCODER=1; +int ENABLE_E5_PULLUP=1; +int E5_ENCODER_A=23; +int E5_ENCODER_B=26; +int E5_TOP_ENCODER_A=10; +int E5_TOP_ENCODER_B=6; +int E5_FUNCTION=5; -int ENABLE_E1_BUTTON=1; int ENABLE_E2_BUTTON=1; int ENABLE_E3_BUTTON=1; int ENABLE_E4_BUTTON=1; +int ENABLE_E5_BUTTON=1; int I2C_INTERRUPT=16; @@ -110,21 +119,21 @@ int ENABLE_VFO_ENCODER=1; int ENABLE_VFO_PULLUP=1; int VFO_ENCODER_A=1; int VFO_ENCODER_B=0; -int ENABLE_E1_ENCODER=1; -int ENABLE_E1_PULLUP=0; -int E1_ENCODER_A=28; -int E1_ENCODER_B=25; -int E1_FUNCTION=6; int ENABLE_E2_ENCODER=1; int ENABLE_E2_PULLUP=0; -int E2_ENCODER_A=27; -int E2_ENCODER_B=24; -int E2_FUNCTION=10; +int E2_ENCODER_A=28; +int E2_ENCODER_B=25; +int E2_FUNCTION=6; int ENABLE_E3_ENCODER=1; int ENABLE_E3_PULLUP=0; -int E3_ENCODER_A=7; -int E3_ENCODER_B=29; -int E3_FUNCTION=11; +int E3_ENCODER_A=27; +int E3_ENCODER_B=24; +int E3_FUNCTION=10; +int ENABLE_E4_ENCODER=1; +int ENABLE_E4_PULLUP=0; +int E4_ENCODER_A=7; +int E4_ENCODER_B=29; +int E4_FUNCTION=11; int ENABLE_S1_BUTTON=1; int S1_BUTTON=23; int ENABLE_S2_BUTTON=1; @@ -141,9 +150,9 @@ int ENABLE_MOX_BUTTON=1; int MOX_BUTTON=2; int ENABLE_FUNCTION_BUTTON=1; int FUNCTION_BUTTON=3; -int ENABLE_E1_BUTTON=1; int ENABLE_E2_BUTTON=1; int ENABLE_E3_BUTTON=1; +int ENABLE_E4_BUTTON=1; #endif #ifdef LOCALCW @@ -155,24 +164,43 @@ int ENABLE_CW_BUTTONS=1; int CW_ACTIVE_LOW=1; #endif -static volatile int vfoEncoderPos; -static volatile int vfo_A; -static volatile int vfo_B; -static volatile int vfoFunction; -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; +int vfoEncoderPos; +int vfoFunction; + #ifdef CONTROLLER2 -static volatile int e4EncoderPos; -static volatile int e4Function; -int e4_encoder_action=ENCODER_MIC_GAIN; +int e2EncoderPos; +int e2_sw_action=MENU_BAND; +int e2_encoder_action=ENCODER_AF_GAIN_RX2; +int e3EncoderPos; +int e3_sw_action=MENU_MODE; +int e3_encoder_action=ENCODER_AGC_GAIN_RX2; +int e4EncoderPos; +int e4_sw_action=MENU_FILTER; +int e4_encoder_action=ENCODER_IF_WIDTH_RX2; +int e2_top_encoder_action=ENCODER_AF_GAIN_RX1; +int e3_top_encoder_action=ENCODER_AGC_GAIN_RX1; +int e4_top_encoder_action=ENCODER_IF_WIDTH_RX1; +int e2TopEncoderPos; +int e3TopEncoderPos; +int e4TopEncoderPos; + +int e5_encoder_action=ENCODER_DRIVE; +int e5_top_encoder_action=ENCODER_TUNE_DRIVE; +int e5EncoderPos; +int e5TopEncoderPos; +int e5_sw_action=MENU_FREQUENCY; +#else +int e2EncoderPos; +int e2_sw_action=RIT; +int e2_encoder_action=ENCODER_AF_GAIN_RX1; +int e3EncoderPos; +int e3_sw_action=AGC; +int e3_encoder_action=ENCODER_AGC_GAIN_RX1; +int e4EncoderPos; +int e4_sw_action=BAND_PLUS; +int e4_encoder_action=ENCODER_DRIVE; #endif + static volatile int function_state; static volatile int band_state; static volatile int bandstack_state; @@ -187,16 +215,6 @@ static gpointer rotary_encoder_thread(gpointer data); 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; -#ifdef CONTROLLER2 -static int e4_function=0; -static int previous_e4_function=0; -#endif static int band_button=0; static int previous_band_button=0; static int bandstack_button=0; @@ -214,25 +232,76 @@ static int previous_mox_button=0; static int running=0; -char *encoder_string[] = { -"AF GAIN", -"AGC GAIN", -#ifdef RADIOBERRY - "RX-GAIN", -#else - "ATTENUATION", +char *encoder_string[ENCODER_ACTIONS] = { + "AF GAIN RX1", + "RF GAIN RX1", + "AF GAIN RX2", + "RF GAIN RX2", + "AGC GAIN RX1", + "AGC GAIN RX2", + "IF WIDTH RX1", + "IF WIDTH RX2", + "ATTENUATION", + "MIC GAIN", + "DRIVE", + "TUNE DRIVE", + "RIT RX1", + "RIT RX2", + "XIT", + "CW SPEED", + "CW FREQUENCY", + "PANADAPTER HIGH", + "PANADAPTER LOW", + "SQUELCH", + "COMP", + "DIVERSITY GAIN", + "DIVERSITY PHASE"}; + +char *sw_string[SWITCH_ACTIONS] = { + "NO ACTION", + "TUNE", + "MOX", + "PS", + "TWO TONE", + "NR", + "NB", + "SNB", + "RIT", + "RIT Clear", + "XIT", + "XIT Clear", + "BAND PLUS", + "BAND MINUS", + "BANDSTACK PLUS", + "BANDSTACK MINUS", + "MODE PLUS", + "MODE MINUS", + "FILTER PLUS", + "FILTER MINUS", + "A TO B", + "B TO A", + "A SWAP B", + "LOCK", + "CTUN", + "AGC", + "SPLIT", + "DIVERSITY", + "BAND MENU", + "BANDSTACK MENU", + "MODE MENU", + "FILTER MENU", + "FREQUENCY MENU", + "MEMORY MENU", + "DIVERSITY MENU", +#ifndef CONTROLLER2 + "FUNCTION", #endif -"MIC GAIN", -"DRIVE", -"RIT", -"CW SPEED", -"CW FREQUENCY", -"PANADAPTER HIGH", -"PANADAPTER LOW", -"SQUELCH", -"COMP" }; +#ifdef CONTROLLER2 +int sw_action[SWITCHES] = {TUNE,MOX,PS,TWO_TONE,NR,A_TO_B,B_TO_A,MODE_MINUS,BAND_MINUS,MODE_PLUS,BAND_PLUS,XIT,NB,SNB,LOCK,CTUN}; +#endif + static int mox_pressed(void *data) { if(running) sim_mox_cb(NULL,NULL); return 0; @@ -324,26 +393,126 @@ static int vfo_function_released(void *data) { } static int e_function_pressed(void *data) { - int encoder=(int)data; - start_encoder(encoder); + int action=(int)data; +fprintf(stderr,"e_function_pressed: %d\n",action); + switch(action) { + case TUNE: + g_idle_add(ext_tune_update,NULL); + break; + case MOX: + g_idle_add(ext_mox_update,NULL); + break; + case PS: + g_idle_add(ext_ps_update,NULL); + break; + case TWO_TONE: + g_idle_add(ext_two_tone,NULL); + break; + case NR: + g_idle_add(ext_nr_update,NULL); + break; + case NB: + g_idle_add(ext_nb_update,NULL); + break; + case SNB: + g_idle_add(ext_snb_update,NULL); + break; + case RIT: + g_idle_add(ext_rit_update,NULL); + break; + case RIT_CLEAR: + g_idle_add(ext_rit_clear,NULL); + break; + case XIT: + g_idle_add(ext_xit_update,NULL); + break; + case XIT_CLEAR: + g_idle_add(ext_xit_clear,NULL); + break; + case BAND_PLUS: + g_idle_add(ext_band_plus,NULL); + break; + case BAND_MINUS: + g_idle_add(ext_band_minus,NULL); + break; + case BANDSTACK_PLUS: + g_idle_add(ext_bandstack_plus,NULL); + break; + case BANDSTACK_MINUS: + g_idle_add(ext_bandstack_minus,NULL); + break; + case MODE_PLUS: + g_idle_add(ext_mode_plus,NULL); + break; + case MODE_MINUS: + g_idle_add(ext_mode_minus,NULL); + break; + case FILTER_PLUS: + g_idle_add(ext_filter_plus,NULL); + break; + case FILTER_MINUS: + g_idle_add(ext_filter_minus,NULL); + break; + case A_TO_B: + g_idle_add(ext_vfo_a_to_b,NULL); + break; + case B_TO_A: + g_idle_add(ext_vfo_b_to_a,NULL); + break; + case A_SWAP_B: + g_idle_add(ext_vfo_a_swap_b,NULL); + break; + case LOCK: + g_idle_add(ext_lock_update,NULL); + break; + case CTUN: + g_idle_add(ext_ctun_update,NULL); + break; + case AGC: + g_idle_add(ext_agc_update,NULL); + break; + case SPLIT: + g_idle_add(ext_split_update,NULL); + break; + case DIVERSITY: + g_idle_add(ext_diversity_update,GINT_TO_POINTER(0)); + break; + case MENU_BAND: + g_idle_add(ext_band_update,NULL); + break; + case MENU_BANDSTACK: + g_idle_add(ext_bandstack_update,NULL); + break; + case MENU_MODE: + g_idle_add(ext_mode_update,NULL); + break; + case MENU_FILTER: + g_idle_add(ext_filter_update,NULL); + break; + case MENU_FREQUENCY: + g_idle_add(ext_frequency_update,NULL); + break; + case MENU_MEMORY: + g_idle_add(ext_memory_update,NULL); + break; + case MENU_DIVERSITY: + g_idle_add(ext_diversity_update,GINT_TO_POINTER(1)); + break; +#ifndef CONTROLLER2 + case FUNCTION: + g_idle_add(ext_function_update,NULL); + break; +#endif + } return 0; } -static unsigned long e1debounce=0; - -static void e1FunctionAlert() { - int level=digitalRead(E1_FUNCTION); - if(level==0) { - if(running) g_idle_add(e_function_pressed,(gpointer)1); - } -} - static unsigned long e2debounce=0; static void e2FunctionAlert() { int level=digitalRead(E2_FUNCTION); if(level==0) { - if(running) g_idle_add(e_function_pressed,(gpointer)2); + if(running) g_idle_add(e_function_pressed,(gpointer)e2_sw_action); } } @@ -352,17 +521,26 @@ static unsigned long e3debounce=0; static void e3FunctionAlert() { int level=digitalRead(E3_FUNCTION); if(level==0) { - if(running) g_idle_add(e_function_pressed,(gpointer)3); + if(running) g_idle_add(e_function_pressed,(gpointer)e3_sw_action); } } -#ifdef CONTROLLER2 static unsigned long e4debounce=0; static void e4FunctionAlert() { int level=digitalRead(E4_FUNCTION); if(level==0) { - if(running) g_idle_add(e_function_pressed,(gpointer)4); + if(running) g_idle_add(e_function_pressed,(gpointer)e4_sw_action); + } +} + +#ifdef CONTROLLER2 +static unsigned long e5debounce=0; + +static void e5FunctionAlert() { + int level=digitalRead(E5_FUNCTION); + if(level==0) { + if(running) g_idle_add(e_function_pressed,(gpointer)e5_sw_action); } } #endif @@ -600,8 +778,22 @@ static void vfoFunctionAlert() { #endif static void vfoEncoderInt(int A_or_B) { - int switch_A=digitalRead(VFO_ENCODER_A); - int switch_B=digitalRead(VFO_ENCODER_B); + static int vfoA=1, vfoB=1; + int levelA=digitalRead(VFO_ENCODER_A); + int levelB=digitalRead(VFO_ENCODER_B); + + if(levelA!=vfoA) { + if(levelA==levelB) ++vfoEncoderPos; + if(levelA!=levelB) --vfoEncoderPos; + vfoA=levelA; + } +/* + if(levelA!=e2CurrentA) { + if(levelA==levelB) ++e2EncoderPos; + if(levelA!=levelB) --e2EncoderPos; + e2CurrentA=levelA; + } + if(vfo_A==switch_A && vfo_B==switch_B) { return; // same as last } @@ -614,6 +806,7 @@ static void vfoEncoderInt(int A_or_B) { vfoEncoderPos++; } } +*/ } static void vfoEncoderA() { @@ -624,65 +817,49 @@ static void vfoEncoderB() { vfoEncoderInt(VFO_ENCODER_B); } -static void e1EncoderInterrupt(int gpio) { - static int e1CurrentA=1, e1CurrentB=1; - - int levelA=digitalRead(E1_ENCODER_A); - int levelB=digitalRead(E1_ENCODER_B); - - if(e1CurrentA==levelA && e1CurrentB==levelB) { - return; - } +static void e2EncoderInterrupt(int gpio) { + static int e2CurrentA=1, e2CurrentB=1; - e1CurrentA=levelA; - e1CurrentB=levelB; + int levelA=digitalRead(E2_ENCODER_A); + int levelB=digitalRead(E2_ENCODER_B); - if(levelA && levelB) { - if(gpio==E1_ENCODER_B) { - --e1EncoderPos; - } else { - ++e1EncoderPos; - } + if(levelA!=e2CurrentA) { + if(levelA==levelB) ++e2EncoderPos; + if(levelA!=levelB) --e2EncoderPos; + e2CurrentA=levelA; } } -static void e1EncoderA() { - e1EncoderInterrupt(E1_ENCODER_A); +static void e2EncoderA() { + e2EncoderInterrupt(E2_ENCODER_A); } -static void e1EncoderB() { - e1EncoderInterrupt(E1_ENCODER_B); +static void e2EncoderB() { + e2EncoderInterrupt(E2_ENCODER_B); } -static void e2EncoderInterrupt(int gpio) { - static int e2CurrentA=1, e2CurrentB=1; - - int levelA=digitalRead(E2_ENCODER_A); - int levelB=digitalRead(E2_ENCODER_B); - - if(e2CurrentA==levelA && e2CurrentB==levelB) { - return; - } +#ifdef CONTROLLER2 +static void e2TopEncoderInterrupt(int gpio) { + static int e2TopCurrentA=1, e2TopCurrentB=1; - e2CurrentA=levelA; - e2CurrentB=levelB; + int levelA=digitalRead(E2_TOP_ENCODER_A); + int levelB=digitalRead(E2_TOP_ENCODER_B); - if(levelA && levelB) { - if(gpio==E2_ENCODER_B) { - --e2EncoderPos; - } else { - ++e2EncoderPos; - } + if(levelA!=e2TopCurrentA) { + if(levelA==levelB) ++e2TopEncoderPos; + if(levelA!=levelB) --e2TopEncoderPos; + e2TopCurrentA=levelA; } } -static void e2EncoderA() { - e2EncoderInterrupt(E2_ENCODER_A); +static void e2TopEncoderA() { + e2TopEncoderInterrupt(E2_TOP_ENCODER_A); } -static void e2EncoderB() { - e2EncoderInterrupt(E2_ENCODER_B); +static void e2TopEncoderB() { + e2TopEncoderInterrupt(E2_TOP_ENCODER_B); } +#endif static void e3EncoderInterrupt(int gpio) { static int e3CurrentA=1, e3CurrentB=1; @@ -690,19 +867,10 @@ static void e3EncoderInterrupt(int gpio) { int levelA=digitalRead(E3_ENCODER_A); int levelB=digitalRead(E3_ENCODER_B); - if(e3CurrentA==levelA && e3CurrentB==levelB) { - return; - } - - e3CurrentA=levelA; - e3CurrentB=levelB; - - if(levelA && levelB) { - if(gpio==E3_ENCODER_B) { - --e3EncoderPos; - } else { - ++e3EncoderPos; - } + if(levelA!=e3CurrentA) { + if(levelA==levelB) ++e3EncoderPos; + if(levelA!=levelB) --e3EncoderPos; + e3CurrentA=levelA; } } @@ -715,25 +883,39 @@ static void e3EncoderB() { } #ifdef CONTROLLER2 +static void e3TopEncoderInterrupt(int gpio) { + static int e3TopCurrentA=1, e3TopCurrentB=1; + + int levelA=digitalRead(E3_TOP_ENCODER_A); + int levelB=digitalRead(E3_TOP_ENCODER_B); + + + if(levelA!=e3TopCurrentA) { + if(levelA==levelB) ++e3TopEncoderPos; + if(levelA!=levelB) --e3TopEncoderPos; + e3TopCurrentA=levelA; + } +} + +static void e3TopEncoderA() { + e3TopEncoderInterrupt(E3_TOP_ENCODER_A); +} + +static void e3TopEncoderB() { + e3TopEncoderInterrupt(E3_TOP_ENCODER_B); +} +#endif + static void e4EncoderInterrupt(int gpio) { static int e4CurrentA=1, e4CurrentB=1; int levelA=digitalRead(E4_ENCODER_A); int levelB=digitalRead(E4_ENCODER_B); - if(e4CurrentA==levelA && e4CurrentB==levelB) { - return; - } - - e4CurrentA=levelA; - e4CurrentB=levelB; - - if(levelA && levelB) { - if(gpio==E4_ENCODER_B) { - --e4EncoderPos; - } else { - ++e4EncoderPos; - } + if(levelA!=e4CurrentA) { + if(levelA==levelB) ++e4EncoderPos; + if(levelA!=levelB) --e4EncoderPos; + e4CurrentA=levelA; } } @@ -744,6 +926,75 @@ static void e4EncoderA() { static void e4EncoderB() { e4EncoderInterrupt(E4_ENCODER_B); } + +#ifdef CONTROLLER2 +static void e4TopEncoderInterrupt(int gpio) { + static int e4TopCurrentA=1, e4TopCurrentB=1; + + int levelA=digitalRead(E4_TOP_ENCODER_A); + int levelB=digitalRead(E4_TOP_ENCODER_B); + + if(levelA!=e4TopCurrentA) { + if(levelA==levelB) ++e4TopEncoderPos; + if(levelA!=levelB) --e4TopEncoderPos; + e4TopCurrentA=levelA; + } +} + +static void e4TopEncoderA() { + e4TopEncoderInterrupt(E4_TOP_ENCODER_A); +} + +static void e4TopEncoderB() { + e4TopEncoderInterrupt(E4_TOP_ENCODER_B); +} +#endif + + +#ifdef CONTROLLER2 +static void e5EncoderInterrupt(int gpio) { + static int e5CurrentA=1, e5CurrentB=1; + + int levelA=digitalRead(E5_ENCODER_A); + int levelB=digitalRead(E5_ENCODER_B); + + + if(levelA!=e5CurrentA) { + if(levelA==levelB) ++e5EncoderPos; + if(levelA!=levelB) --e5EncoderPos; + e5CurrentA=levelA; + } +} + +static void e5EncoderA() { + e5EncoderInterrupt(E5_ENCODER_A); +} + +static void e5EncoderB() { + e5EncoderInterrupt(E5_ENCODER_B); +} + +static void e5TopEncoderInterrupt(int gpio) { + static int e5TopCurrentA=1, e5TopCurrentB=1; + + int levelA=digitalRead(E5_TOP_ENCODER_A); + int levelB=digitalRead(E5_TOP_ENCODER_B); + + if(levelA!=e5TopCurrentA) { + if(levelA==levelB) ++e5TopEncoderPos; + if(levelA!=levelB) --e5TopEncoderPos; + e5TopCurrentA=levelA; + } +} + +static void e5TopEncoderA() { + e5TopEncoderInterrupt(E5_TOP_ENCODER_A); +} + +static void e5TopEncoderB() { + e5TopEncoderInterrupt(E5_TOP_ENCODER_B); +} + #endif #ifdef CONTROLLER2 @@ -755,8 +1006,50 @@ static void pI2CInterrupt() { } #endif +void gpio_restore_actions() { + char* value; + char name[80]; + int i; + + value=getProperty("e2_encoder_action"); + if(value) e2_encoder_action=atoi(value); + value=getProperty("e2_sw_action"); + if(value) e2_sw_action=atoi(value); + value=getProperty("e3_encoder_action"); + if(value) e3_encoder_action=atoi(value); + value=getProperty("e3_sw_action"); + if(value) e3_sw_action=atoi(value); + value=getProperty("e4_encoder_action"); + if(value) e4_encoder_action=atoi(value); + value=getProperty("e4_sw_action"); + if(value) e4_sw_action=atoi(value); +#ifdef CONTROLLER2 + value=getProperty("e2_top_encoder_action"); + if(value) e2_top_encoder_action=atoi(value); + value=getProperty("e3_top_encoder_action"); + if(value) e3_top_encoder_action=atoi(value); + value=getProperty("e4_top_encoder_action"); + if(value) e4_top_encoder_action=atoi(value); + value=getProperty("e5_encoder_action"); + if(value) e5_encoder_action=atoi(value); + value=getProperty("e5_top_encoder_action"); + if(value) e5_top_encoder_action=atoi(value); + value=getProperty("e5_sw_action"); + if(value) e5_sw_action=atoi(value); + for(i=0;ivolume; + case ENCODER_AF_GAIN_RX1: + value=receiver[0]->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); + set_af_gain(0,value); + break; + case ENCODER_AF_GAIN_RX2: + value=receiver[1]->volume; + value+=(double)pos/100.0; + if(value<0.0) { + value=0.0; + } else if(value>1.0) { + value=1.0; + } + set_af_gain(1,value); + break; + case ENCODER_AGC_GAIN_RX1: + value=receiver[0]->agc_gain; + value+=(double)pos; + if(value<-20.0) { + value=-20.0; + } else if(value>120.0) { + value=120.0; + } + set_agc_gain(0,value); break; - case ENCODER_AGC_GAIN: - value=active_receiver->agc_gain; + case ENCODER_AGC_GAIN_RX2: + value=receiver[1]->agc_gain; value+=(double)pos; if(value<-20.0) { value=-20.0; } else if(value>120.0) { value=120.0; } - set_agc_gain(value); + set_agc_gain(1,value); + break; + case ENCODER_IF_WIDTH_RX1: + filter_width_changed(0,pos); + break; + case ENCODER_IF_WIDTH_RX2: + filter_width_changed(1,pos); break; case ENCODER_ATTENUATION: value=(double)adc_attenuation[active_receiver->adc]; @@ -1333,7 +1750,6 @@ static void encoder_changed(int action,int pos) { break; case ENCODER_MIC_GAIN: value=mic_gain; - //gain+=(double)pos/100.0; value+=(double)pos; if(value<-10.0) { value=-10.0; @@ -1352,15 +1768,29 @@ static void encoder_changed(int action,int pos) { } set_drive(value); break; - case ENCODER_RIT: - value=(double)vfo[active_receiver->id].rit; + case ENCODER_RIT_RX1: + value=(double)vfo[receiver[0]->id].rit; value+=(double)(pos*rit_increment); if(value<-1000.0) { value=-1000.0; } else if(value>1000.0) { value=1000.0; } - vfo[active_receiver->id].rit=(int)value; + vfo[receiver[0]->id].rit=(int)value; + if(protocol==NEW_PROTOCOL) { + schedule_high_priority(); + } + g_idle_add(ext_vfo_update,NULL); + break; + case ENCODER_RIT_RX2: + value=(double)vfo[receiver[1]->id].rit; + value+=(double)(pos*rit_increment); + if(value<-1000.0) { + value=-1000.0; + } else if(value>1000.0) { + value=1000.0; + } + vfo[receiver[1]->id].rit=(int)value; if(protocol==NEW_PROTOCOL) { schedule_high_priority(); } @@ -1420,49 +1850,99 @@ static void encoder_changed(int action,int pos) { transmitter->compressor_level=(int)value; set_compression(transmitter); break; + case ENCODER_DIVERSITY_GAIN: + update_diversity_gain((double)pos); + break; + case ENCODER_DIVERSITY_PHASE: + update_diversity_phase((double)pos); + break; } } -static int e1_encoder_changed(void *data) { +static int e2_encoder_changed(void *data) { int pos=(int)data; - if(active_menu==E1_MENU) { + if(active_menu==E2_MENU) { encoder_select(pos); } else { - encoder_changed(e1_encoder_action,pos); + encoder_changed(e2_encoder_action,pos); } //free(data); return 0; } -static int e2_encoder_changed(void *data) { +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 e4_encoder_changed(void *data) { + int pos=(int)data; + if(active_menu==E4_MENU) { + encoder_select(pos); + } else { + encoder_changed(e4_encoder_action,pos); + } + //free(data); + return 0; +} + +#ifdef CONTROLLER2 +static int e2_top_encoder_changed(void *data) { int pos=(int)data; if(active_menu==E2_MENU) { encoder_select(pos); } else { - encoder_changed(e2_encoder_action,pos); + encoder_changed(e2_top_encoder_action,pos); } //free(data); return 0; } -static int e3_encoder_changed(void *data) { +static int e3_top_encoder_changed(void *data) { int pos=(int)data; if(active_menu==E3_MENU) { encoder_select(pos); } else { - encoder_changed(e3_encoder_action,pos); + encoder_changed(e3_top_encoder_action,pos); } //free(data); return 0; } -#ifdef CONTROLLER2 -static int e4_encoder_changed(void *data) { +static int e4_top_encoder_changed(void *data) { int pos=(int)data; if(active_menu==E4_MENU) { encoder_select(pos); } else { - encoder_changed(e4_encoder_action,pos); + encoder_changed(e4_top_encoder_action,pos); + } + //free(data); + return 0; +} + +static int e5_encoder_changed(void *data) { + int pos=(int)data; + if(active_menu==E5_MENU) { + encoder_select(pos); + } else { + encoder_changed(e5_encoder_action,pos); + } + //free(data); + return 0; +} + +static int e5_top_encoder_changed(void *data) { + int pos=(int)data; + if(active_menu==E5_MENU) { + encoder_select(pos); + } else { + encoder_changed(e5_top_encoder_action,pos); } //free(data); return 0; @@ -1482,11 +1962,6 @@ static gpointer rotary_encoder_thread(gpointer data) { g_idle_add(vfo_encoder_changed,(gpointer)pos); } - pos=e1_encoder_get_pos(); - if(pos!=0) { - g_idle_add(e1_encoder_changed,(gpointer)pos); - } - pos=e2_encoder_get_pos(); if(pos!=0) { g_idle_add(e2_encoder_changed,(gpointer)pos); @@ -1497,11 +1972,36 @@ static gpointer rotary_encoder_thread(gpointer data) { g_idle_add(e3_encoder_changed,(gpointer)pos); } -#ifdef CONTROLLER2 pos=e4_encoder_get_pos(); if(pos!=0) { g_idle_add(e4_encoder_changed,(gpointer)pos); } + +#ifdef CONTROLLER2 + pos=e2_top_encoder_get_pos(); + if(pos!=0) { + g_idle_add(e2_top_encoder_changed,(gpointer)pos); + } + + pos=e3_top_encoder_get_pos(); + if(pos!=0) { + g_idle_add(e3_top_encoder_changed,(gpointer)pos); + } + + pos=e4_top_encoder_get_pos(); + if(pos!=0) { + g_idle_add(e4_top_encoder_changed,(gpointer)pos); + } + + pos=e5_encoder_get_pos(); + if(pos!=0) { + g_idle_add(e5_encoder_changed,(gpointer)pos); + } + + pos=e5_top_encoder_get_pos(); + if(pos!=0) { + g_idle_add(e5_top_encoder_changed,(gpointer)pos); + } #endif #ifdef sx1509 diff --git a/gpio.h b/gpio.h index e2253f3..6757545 100644 --- a/gpio.h +++ b/gpio.h @@ -21,30 +21,131 @@ #define _GPIO_H enum { - ENCODER_AF_GAIN=0, - ENCODER_AGC_GAIN, + ENCODER_AF_GAIN_RX1=0, + ENCODER_RF_GAIN_RX1, + ENCODER_AF_GAIN_RX2, + ENCODER_RF_GAIN_RX2, + ENCODER_AGC_GAIN_RX1, + ENCODER_AGC_GAIN_RX2, + ENCODER_IF_WIDTH_RX1, + ENCODER_IF_WIDTH_RX2, ENCODER_ATTENUATION, ENCODER_MIC_GAIN, ENCODER_DRIVE, -// ENCODER_TUNE_DRIVE, - ENCODER_RIT, + ENCODER_TUNE_DRIVE, + ENCODER_RIT_RX1, + ENCODER_RIT_RX2, + ENCODER_XIT, ENCODER_CW_SPEED, ENCODER_CW_FREQUENCY, ENCODER_PANADAPTER_HIGH, ENCODER_PANADAPTER_LOW, ENCODER_SQUELCH, ENCODER_COMP, - ENCODER_LAST + ENCODER_DIVERSITY_GAIN, + ENCODER_DIVERSITY_PHASE, + ENCODER_ACTIONS }; +extern char *encoder_string[ENCODER_ACTIONS]; + +enum { + NO_ACTION=0, + TUNE, + MOX, + PS, + TWO_TONE, + NR, + NB, + SNB, + RIT, + RIT_CLEAR, + XIT, + XIT_CLEAR, + BAND_PLUS, + BAND_MINUS, + BANDSTACK_PLUS, + BANDSTACK_MINUS, + MODE_PLUS, + MODE_MINUS, + FILTER_PLUS, + FILTER_MINUS, + A_TO_B, + B_TO_A, + A_SWAP_B, + LOCK, + CTUN, + AGC, + SPLIT, + DIVERSITY, + MENU_BAND, + MENU_BANDSTACK, + MENU_MODE, + MENU_FILTER, + MENU_FREQUENCY, + MENU_MEMORY, + MENU_DIVERSITY, + FUNCTION, + SWITCH_ACTIONS +}; + +extern char *sw_string[SWITCH_ACTIONS]; + + +#ifndef CONTROLLER2 +#define SWITCHES 8 +enum { + SW1=0, + SW2, + SW3, + SW4, + SW5, + SW6, + SW7, + SW8 +}; +#else +#define SWITCHES 16 +enum { + SW2=0, + SW3, + SW4, + SW5, + SW6, + SW7, + SW8, + SW9, + SW10, + SW11, + SW12, + SW13, + SW14, + SW15, + SW16, + SW17 +}; + +#endif + +extern int sw_action[SWITCHES]; extern int settle_time; -extern char *encoder_string[ENCODER_LAST]; -extern int e1_encoder_action; extern int e2_encoder_action; extern int e3_encoder_action; +extern int e4_encoder_action; +extern int e5_encoder_action; + +extern int e2_top_encoder_action; +extern int e3_top_encoder_action; +extern int e4_top_encoder_action; +extern int e5_top_encoder_action; + +extern int e2_sw_action; +extern int e3_sw_action; +extern int e4_sw_action; +extern int e5_sw_action; extern int ENABLE_VFO_ENCODER; extern int ENABLE_VFO_PULLUP; @@ -52,10 +153,6 @@ extern int VFO_ENCODER_A; extern int VFO_ENCODER_B; extern int VFO_ENCODER_A_PIN; extern int VFO_ENCODER_B_PIN; -extern int ENABLE_E1_ENCODER; -extern int ENABLE_E1_PULLUP; -extern int E1_ENCODER_A; -extern int E1_ENCODER_B; extern int ENABLE_E2_ENCODER; extern int ENABLE_E2_PULLUP; extern int E2_ENCODER_A; @@ -64,6 +161,16 @@ extern int ENABLE_E3_ENCODER; extern int ENABLE_E3_PULLUP; extern int E3_ENCODER_A; extern int E3_ENCODER_B; +extern int ENABLE_E4_ENCODER; +extern int ENABLE_E4_PULLUP; +extern int E4_ENCODER_A; +extern int E4_ENCODER_B; +#ifdef CONTROLLER2 +extern int ENABLE_E5_ENCODER; +extern int ENABLE_E5_PULLUP; +extern int E5_ENCODER_A; +extern int E5_ENCODER_B; +#endif extern int ENABLE_S1_BUTTON; extern int S1_BUTTON; extern int ENABLE_S2_BUTTON; @@ -93,8 +200,10 @@ int gpio_right_cw_key(); int gpio_cw_sidetone_enabled(); #endif +void gpio_restore_actions(); void gpio_restore_state(); void gpio_save_state(); +void gpio_save_actions(); int gpio_init(); void gpio_close(); int vfo_encoder_get_pos(); diff --git a/i2c.c b/i2c.c index fac927a..e6d6a24 100644 --- a/i2c.c +++ b/i2c.c @@ -9,6 +9,7 @@ #include #include "i2c.h" +#include "gpio.h" #include "band.h" #include "band_menu.h" #include "bandstack.h" @@ -21,6 +22,23 @@ #define ADDRESS_1 0X20 #define ADDRESS_2 0X23 +#define SW_2 0X8000 +#define SW_3 0X4000 +#define SW_4 0X2000 +#define SW_5 0X1000 +#define SW_6 0X0008 +#define SW_7 0X0004 +#define SW_8 0X0002 +#define SW_9 0X0001 +#define SW_10 0X0010 +#define SW_11 0X0020 +#define SW_12 0X0040 +#define SW_13 0X0080 +#define SW_14 0X0800 +#define SW_15 0X0400 +#define SW_16 0X0200 +#define SW_17 0X0100 + static int write_byte_data(unsigned char addr,unsigned char reg, unsigned char data) { int fd; int rc; @@ -109,56 +127,144 @@ void i2c_interrupt() { flags=read_word_data(ADDRESS_1,0x0E); if(flags) { ints=read_word_data(ADDRESS_1,0x10); - fprintf(stderr,"i2c_interrupt: flags=%04X,ints=%04X\n",flags,ints); if(ints) { + int i=-1; switch(ints) { - case 0x0001: - g_idle_add(ext_mox_update,NULL); + case SW_2: + i=SW2; + break; + case SW_3: + i=SW3; + break; + case SW_4: + i=SW4; + break; + case SW_5: + i=SW5; + break; + case SW_6: + i=SW6; + break; + case SW_7: + i=SW7; + break; + case SW_8: + i=SW8; + break; + case SW_9: + i=SW9; + break; + case SW_10: + i=SW10; + break; + case SW_11: + i=SW11; + break; + case SW_12: + i=SW12; + break; + case SW_13: + i=SW13; + break; + case SW_14: + i=SW14; + break; + case SW_15: + i=SW15; + break; + case SW_16: + i=SW16; + break; + case SW_17: + i=SW17; + break; + } + switch(sw_action[i]) { + case TUNE: + { + int tune=getTune(); + if(tune==0) tune=1; else tune=0; + g_idle_add(ext_tune_update,GINT_TO_POINTER(tune)); + } + break; + case MOX: + { + int mox=getMox(); + if(mox==0) mox=1; else mox=0; + g_idle_add(ext_mox_update,GINT_TO_POINTER(mox)); + } + break; + case PS: + g_idle_add(ext_ps_update,NULL); + break; + case TWO_TONE: + g_idle_add(ext_two_tone,NULL); + break; + case NR: + g_idle_add(ext_nr_update,NULL); + break; + case NB: + g_idle_add(ext_nb_update,NULL); + break; + case SNB: + g_idle_add(ext_snb_update,NULL); + break; + case RIT: + g_idle_add(ext_rit_update,NULL); + break; + case RIT_CLEAR: + g_idle_add(ext_rit_clear,NULL); + break; + case XIT: + g_idle_add(ext_xit_update,NULL); + break; + case XIT_CLEAR: + g_idle_add(ext_xit_clear,NULL); break; - case 0x0002: - g_idle_add(ext_tune_update,NULL); + case BAND_PLUS: + g_idle_add(ext_band_plus,NULL); break; - case 0x0004: - g_idle_add(ext_band_update,NULL); + case BAND_MINUS: + g_idle_add(ext_band_minus,NULL); break; - case 0x0008: - g_idle_add(ext_band_update,(void *)band40); + case BANDSTACK_PLUS: + g_idle_add(ext_bandstack_plus,NULL); break; - case 0x0010: - g_idle_add(ext_band_update,(void *)band30); + case BANDSTACK_MINUS: + g_idle_add(ext_bandstack_minus,NULL); break; - case 0x0020: - g_idle_add(ext_band_update,(void *)band20); + case MODE_PLUS: + g_idle_add(ext_mode_plus,NULL); break; - case 0x0040: - g_idle_add(ext_band_update,(void *)band17); + case MODE_MINUS: + g_idle_add(ext_mode_minus,NULL); break; - case 0x0080: - g_idle_add(ext_band_update,(void *)band15); + case FILTER_PLUS: + g_idle_add(ext_filter_plus,NULL); break; - case 0x0100: - g_idle_add(ext_band_update,(void *)band12); + case FILTER_MINUS: + g_idle_add(ext_filter_minus,NULL); break; - case 0x0200: - g_idle_add(ext_band_update,(void *)band10); + case A_TO_B: + g_idle_add(ext_vfo_a_to_b,NULL); break; - case 0x0400: - g_idle_add(ext_band_update,(void *)band6); + case B_TO_A: + g_idle_add(ext_vfo_b_to_a,NULL); break; - case 0x0800: - g_idle_add(ext_band_update,(void *)bandGen); + case A_SWAP_B: + g_idle_add(ext_vfo_a_swap_b,NULL); break; - case 0x1000: - g_idle_add(ext_band_update,(void *)band12); + case LOCK: + g_idle_add(ext_lock_update,NULL); break; - case 0x2000: - g_idle_add(ext_band_update,(void *)band10); + case CTUN: + g_idle_add(ext_ctun_update,NULL); break; - case 0x4000: - g_idle_add(ext_band_update,(void *)band6); + case AGC: + g_idle_add(ext_agc_update,NULL); break; - case 0x8000: - g_idle_add(ext_band_update,(void *)bandGen); + case SPLIT: + g_idle_add(ext_split_update,NULL); break; } } diff --git a/i2c.h b/i2c.h index e06808d..3271c26 100644 --- a/i2c.h +++ b/i2c.h @@ -1,3 +1,2 @@ - -void i2c_init(); -void i2c_interrupt(); +extern void i2c_init(); +extern void i2c_interrupt(); diff --git a/lime_discovery.c b/lime_discovery.c deleted file mode 100644 index 86979bb..0000000 --- a/lime_discovery.c +++ /dev/null @@ -1,85 +0,0 @@ -#include -#include -#include -#include "discovered.h" -#include "lime_discovery.h" - -void lime_discovery() { - SoapySDRKwargs args; - size_t length; - int i; - args.size=0; - SoapySDRKwargs *devs=SoapySDRDevice_enumerate(&args, &length); - -fprintf(stderr,"lime_discovery: length=%ld devs->size=%ld\n",length,devs->size); - - for(i=0;isize;i++) { -fprintf(stderr,"lime_discovery:device key=%s val=%s\n",devs->keys[i], devs->vals[i]); - if(strcmp(devs->keys[i],"name")==0) { - discovered[devices].protocol=LIMESDR_PROTOCOL; - discovered[devices].device=LIMESDR_USB_DEVICE; - strcpy(discovered[devices].name,devs->vals[i]); - discovered[devices].status=STATE_AVAILABLE; - discovered[devices].info.soapy.args=devs; - devices++; - } - } - -/* - SoapySDRDevice *device=SoapySDRDevice_make(devs); - if(device==NULL) { - fprintf(stderr,"SoapySDRDevice_make failed: %s\n",SoapySDRDevice_lastError()); - return; - } - - SoapySDRKwargs info=SoapySDRDevice_getHardwareInfo(device); - int version=0; - for(i=0;i -#include -#include -#include - -//#define TIMING -#ifdef TIMING -#include -#endif - -#include "audio.h" -#include "channel.h" -#include "discovered.h" -#include "lime_protocol.h" -#include "radio.h" -#include "receiver.h" -#include "SoapySDR/Constants.h" -#include "SoapySDR/Device.h" - -static double bandwidth=3000000.0; - -static size_t lime_receiver; -static SoapySDRDevice *lime_device; -static SoapySDRStream *stream; -static int lime_sample_rate; -static int display_width; -static int lime_buffer_size=BUFFER_SIZE; -static int outputsamples; -static int lime_fft_size=4096; -static int dspRate=48000; -static int outputRate=48000; -static float *buffer; -static int max_samples; - -static long long saved_frequency=0LL; -static int saved_antenna=-1; - -//static double iqinputbuffer[BUFFER_SIZE*2]; -static double audiooutputbuffer[BUFFER_SIZE*2]; -static int samples=0; - -static GThread *receive_thread_id; -static gpointer receive_thread(gpointer data); - -static int actual_rate; -#ifdef RESAMPLE -static void *resampler; -static double resamples[1024*2]; -static double resampled[1024*2]; -#endif - -#ifdef TIMING -static int rate_samples; -#endif - -static int running; - -void lime_protocol_change_sample_rate(int rate) { -} - -void lime_protocol_init(int rx,int pixels,int sample_rate) { - SoapySDRKwargs args; - int rc; - -fprintf(stderr,"lime_protocol_init: lime_receiver=%d pixels=%d sample_rate=%d\n",rx,pixels,sample_rate); - - lime_receiver=(size_t)rx; - display_width=pixels; - lime_sample_rate=sample_rate; - - outputsamples=BUFFER_SIZE/(sample_rate/48000); -/* - switch(sample_rate) { - case 48000: - outputsamples=BUFFER_SIZE; - break; - case 96000: - outputsamples=BUFFER_SIZE/2; - break; - case 192000: - outputsamples=BUFFER_SIZE/4; - break; - case 384000: - outputsamples=BUFFER_SIZE/8; - break; - case 768000: - outputsamples=BUFFER_SIZE/16; - break; - case 1536000: - outputsamples=BUFFER_SIZE/32; - break; - } -*/ - - - - - args.size=0; - - // initialize the radio -fprintf(stderr,"lime_protocol: receive_thread: SoapySDRDevice_make\n"); - lime_device=SoapySDRDevice_make(radio->info.soapy.args); - if(lime_device==NULL) { - fprintf(stderr,"lime_protocol: SoapySDRDevice_make failed: %s\n",SoapySDRDevice_lastError()); - _exit(-1); - } - -fprintf(stderr,"lime_protocol: set antenna to NONE\n"); - lime_protocol_set_antenna(0); - -fprintf(stderr,"lime_protocol: setting samplerate=%f\n",(double)sample_rate); - rc=SoapySDRDevice_setSampleRate(lime_device,SOAPY_SDR_RX,lime_receiver,(double)sample_rate); - if(rc!=0) { - fprintf(stderr,"lime_protocol: SoapySDRDevice_setSampleRate(%f) failed: %s\n",(double)sample_rate,SoapySDRDevice_lastError()); - } - - actual_rate=(int)SoapySDRDevice_getSampleRate(lime_device, SOAPY_SDR_RX, lime_receiver); -fprintf(stderr,"lime_protocol: actual samplerate= %d\n",actual_rate); -#ifdef RESAMPLE -if(sample_rate==768000 && actual_rate==767999) { - actual_rate=768000; - fprintf(stderr,"lime_protocol: forced actual_rate\n"); -} -#endif - -fprintf(stderr,"lime_protocol: setting bandwidth =%f\n",bandwidth); - rc=SoapySDRDevice_setBandwidth(lime_device,SOAPY_SDR_RX,lime_receiver,bandwidth); - if(rc!=0) { - fprintf(stderr,"lime_protocol: SoapySDRDevice_setBandwidth(%f) failed: %s\n",bandwidth,SoapySDRDevice_lastError()); - } - -if(saved_frequency!=0LL) { -fprintf(stderr,"lime_protocol: setting save_frequency: %lld\n",saved_frequency); - lime_protocol_set_frequency(saved_frequency); -} - -/* -fprintf(stderr,"lime_protocol: set baseband frequency\n"); - rc=SoapySDRDevice_setFrequencyComponent(lime_device,SOAPY_SDR_RX,lime_receiver,"BB",0.0,&args); - if(rc!=0) { - fprintf(stderr,"lime_protocol: SoapySDRDevice_setFrequencyComponent(BB) failed: %s\n",SoapySDRDevice_lastError()); - } -*/ - -fprintf(stderr,"setting antennal to LNAL\n"); - lime_protocol_set_antenna(2); - -fprintf(stderr,"setting Gain LNA=30.0\n"); - rc=SoapySDRDevice_setGainElement(lime_device,SOAPY_SDR_RX,lime_receiver,"LNA",30.0); - if(rc!=0) { - fprintf(stderr,"lime_protocol: SoapySDRDevice_setGain LNA failed: %s\n",SoapySDRDevice_lastError()); - } -fprintf(stderr,"setting Gain PGA=19.0\n"); - rc=SoapySDRDevice_setGainElement(lime_device,SOAPY_SDR_RX,lime_receiver,"PGA",19.0); - if(rc!=0) { - fprintf(stderr,"lime_protocol: SoapySDRDevice_setGain PGA failed: %s\n",SoapySDRDevice_lastError()); - } -fprintf(stderr,"setting Gain TIA=12.0\n"); - rc=SoapySDRDevice_setGainElement(lime_device,SOAPY_SDR_RX,lime_receiver,"TIA",12.0); - if(rc!=0) { - fprintf(stderr,"lime_protocol: SoapySDRDevice_setGain TIA failed: %s\n",SoapySDRDevice_lastError()); - } - -fprintf(stderr,"lime_protocol: receive_thread: SoapySDRDevice_setupStream\n"); - size_t channels=(size_t)lime_receiver; - rc=SoapySDRDevice_setupStream(lime_device,&stream,SOAPY_SDR_RX,"CF32",&channels,1,&args); - if(rc!=0) { - fprintf(stderr,"lime_protocol: SoapySDRDevice_setupStream failed: %s\n",SoapySDRDevice_lastError()); - _exit(-1); - } - - max_samples=SoapySDRDevice_getStreamMTU(lime_device,stream); -fprintf(stderr,"max_samples=%d\n",max_samples); - - buffer=(float *)malloc(max_samples*sizeof(float)*2); - -#ifdef RESAMPLE - if(actual_rate!=sample_rate) { -fprintf(stderr,"lime_protocol: creating resampler from %d to %d\n",actual_rate,sample_rate); - resampler=create_resample (1, max_samples, resamples, resampled, actual_rate, sample_rate, 0.0, 0, 1.0); - } -#endif - - rc=SoapySDRDevice_activateStream(lime_device, stream, 0, 0LL, 0); - if(rc!=0) { - fprintf(stderr,"lime_protocol: SoapySDRDevice_activateStream failed: %s\n",SoapySDRDevice_lastError()); - _exit(-1); - } - - - if(saved_antenna!=-1) { -fprintf(stderr,"lime_protocol: setting save_antenna: %d\n",saved_antenna); - lime_protocol_set_antenna(saved_antenna); - } - - if(saved_frequency!=0LL) { -fprintf(stderr,"lime_protocol: setting save_frequency: %lld\n",saved_frequency); - lime_protocol_set_frequency(saved_frequency); - } - -fprintf(stderr,"lime_protocol_init: audio_open_output\n"); - if(audio_open_output(receiver[0])!=0) { - receiver[0]->local_audio=false; - fprintf(stderr,"audio_open_output failed\n"); - } - -fprintf(stderr,"lime_protocol_init: create receive_thread\n"); - receive_thread_id = g_thread_new( "lime protocol", receive_thread, NULL); - if( ! receive_thread_id ) - { - fprintf(stderr,"g_thread_new failed for receive_thread\n"); - exit( -1 ); - } - fprintf(stderr, "receive_thread: id=%p\n",receive_thread_id); -} - -static void *receive_thread(void *arg) { - float isample; - float qsample; - int outsamples; - int elements; - int flags=0; - long long timeNs=0; - long timeoutUs=10000L; - int i; -#ifdef TIMING - struct timeval tv; - long start_time, end_time; - rate_samples=0; - gettimeofday(&tv, NULL); start_time=tv.tv_usec + 1000000 * tv.tv_sec; -#endif - running=1; -fprintf(stderr,"lime_protocol: receive_thread\n"); - while(running) { - elements=SoapySDRDevice_readStream(lime_device,stream,(void *)&buffer,max_samples,&flags,&timeNs,timeoutUs); -//fprintf(stderr,"read %d elements\n",elements); -#ifdef RESAMPLE - if(actual_rate!=lime_sample_rate) { - for(i=0;i #include +#include #include "discovered.h" #include "new_protocol.h" diff --git a/old_protocol.c b/old_protocol.c index c38f135..5a8981a 100644 --- a/old_protocol.c +++ b/old_protocol.c @@ -643,7 +643,11 @@ static int second_receiver_channel() { // return the channel number of the second receiver // #ifdef PURESIGNAL - return 2; + if(device==DEVICE_HERMES_LITE) { + return 1; + } else { + return 2; + } #else return 1; #endif @@ -671,9 +675,15 @@ static long long channel_freq(int chan) { switch (chan) { #ifdef PURESIGNAL case 0: - case 1: vfonum=receiver[0]->id; break; + case 1: + if(device==DEVICE_HERMES_LITE) { + vfonum=receiver[1]->id; + } else { + vfonum=receiver[0]->id; + } + break; case 2: case 3: case 4: diff --git a/property.c b/property.c index 08f74af..beba9a5 100644 --- a/property.c +++ b/property.c @@ -83,7 +83,7 @@ void saveProperties(char* filename) { char line[512]; char version[32]; - //fprintf(stderr,"saveProperties: %s\n",filename); + fprintf(stderr,"saveProperties: %s\n",filename); if(!f) { fprintf(stderr,"can't open %s\n",filename); diff --git a/radio.c b/radio.c index 6d82af4..47c6fde 100644 --- a/radio.c +++ b/radio.c @@ -29,6 +29,7 @@ #include +#include "adc.h" #include "audio.h" #include "discovered.h" //#include "discovery.h" @@ -46,8 +47,8 @@ #include "new_protocol.h" #include "old_protocol.h" #include "store.h" -#ifdef LIMESDR -#include "lime_protocol.h" +#ifdef SOAPYSDR +#include "soapy_protocol.h" #endif #ifdef FREEDV #include "freedv.h" @@ -122,6 +123,9 @@ int region=REGION_OTHER; int echo=0; +int radio_sample_rate; +gboolean iqswap; + static gint save_timer_id; DISCOVERED *radio=NULL; @@ -175,6 +179,7 @@ int waterfall_high=-100; int waterfall_low=-150; int display_sliders=1; +int display_toolbar=1; //double volume=0.2; double mic_gain=0.0; @@ -391,6 +396,7 @@ void start_radio() { #endif char text[256]; + //for(i=0;iprotocol) { case ORIGINAL_PROTOCOL: @@ -410,24 +416,92 @@ void start_radio() { //} + char p[32]; + char version[32]; + char mac[32]; + char ip[32]; + char iface[32]; + + switch(radio->protocol) { + case ORIGINAL_PROTOCOL: + strcpy(p,"Protocol 1"); + sprintf(version,"v%d.%d)", + radio->software_version/10, + radio->software_version%10); + sprintf(mac,"%02X:%02X:%02X:%02X:%02X:%02X", + 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]); + sprintf(ip,"%s", inet_ntoa(radio->info.network.address.sin_addr)); + sprintf(iface,"%s", radio->info.network.interface_name); + break; + case NEW_PROTOCOL: + strcpy(p,"Protocol 2"); + sprintf(version,"v%d.%d)", + radio->software_version/10, + radio->software_version%10); + sprintf(mac,"%02X:%02X:%02X:%02X:%02X:%02X", + 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]); + sprintf(ip,"%s", inet_ntoa(radio->info.network.address.sin_addr)); + sprintf(iface,"%s", radio->info.network.interface_name); + break; +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: + strcpy(p,"SoapySDR"); + sprintf(version,"v%d.%d.%d)", + radio->software_version/100, + (radio->software_version%100)/10, + radio->software_version%10); + strcpy(mac,""); + strcpy(ip,""); + strcpy(iface,""); + break; +#endif + } + + switch(protocol) { + case ORIGINAL_PROTOCOL: + case NEW_PROTOCOL: +#ifdef USBOZY + if(radio->device==DEVICE_OZY) { + sprintf(text,"%s (%s) on USB /dev/ozy\n", radio->name, p); + } else { +#endif + sprintf(text,"Starting %s (%s %s)", + radio->name, + p, + version); +#ifdef USBOZY + } +#endif + break; +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: + sprintf(text,"Starting %s (%s %s)", + radio->name, + "SoapySDR", + version); + break; +#endif + } status_text(text); - sprintf(text,"piHPSDR: %s (%s v%d.%d) %s (%02X:%02X:%02X:%02X:%02X:%02X) on %s", + sprintf(text,"piHPSDR: %s (%s %s) %s (%s) on %s", radio->name, - radio->protocol==ORIGINAL_PROTOCOL?"Protocol 1":"Protocol 2", - radio->software_version/10, - radio->software_version%10, - inet_ntoa(radio->info.network.address.sin_addr), - 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], - radio->info.network.interface_name); - -//fprintf(stderr,"title: length=%d\n", (int)strlen(text)); + p, + version, + ip, + mac, + iface); gtk_window_set_title (GTK_WINDOW (top_window), text); @@ -454,9 +528,9 @@ void start_radio() { break; } break; -#ifdef LIMESDR - case LIMESDR_PROTOCOL: - sprintf(property_path,"limesdr.props"); +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: + sprintf(property_path,"%s.props",radio->name); break; #endif } @@ -518,16 +592,104 @@ void start_radio() { break; } break; +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: + if(strcmp(radio->name,"lime")==0) { + n_adc=2; + } else { + n_adc=1; + } + break; +#endif default: break; } + iqswap=0; + +#ifdef SOAPYSDR + if(radio->device==SOAPYSDR_USB_DEVICE) { + iqswap=1; + } + receivers=1; +#endif + adc_attenuation[0]=0; adc_attenuation[1]=0; rx_gain_slider[0] = 0; rx_gain_slider[1] = 0; + adc[0].antenna=ANTENNA_1; + adc[0].filters=AUTOMATIC; + adc[0].hpf=HPF_13; + adc[0].lpf=LPF_30_20; + adc[0].dither=FALSE; + adc[0].random=FALSE; + adc[0].preamp=FALSE; + adc[0].attenuation=0; +#ifdef SOAPYSDR + adc[0].antenna=1; // LNAH + if(radio->device==SOAPYSDR_USB_DEVICE) { + adc[0].rx_gain=malloc(radio->info.soapy.rx_gains*sizeof(gint)); + for (size_t i = 0; i < radio->info.soapy.rx_gains; i++) { + adc[0].rx_gain[i]=0; + } + adc[0].agc=FALSE; +/* + if(r->can_transmit) { + r->dac[0].antenna=1; + r->dac[0].tx_gain=malloc(r->discovered->info.soapy.tx_gains*sizeof(gint)); + for (size_t i = 0; i < r->discovered->info.soapy.tx_gains; i++) { + r->dac[0].tx_gain[i]=0; + } + } +*/ + } +#endif + + adc[1].antenna=ANTENNA_1; + adc[1].filters=AUTOMATIC; + adc[1].hpf=HPF_9_5; + adc[1].lpf=LPF_60_40; + adc[1].dither=FALSE; + adc[1].random=FALSE; + adc[1].preamp=FALSE; + adc[1].attenuation=0; +#ifdef SOAPYSDR + adc[1].antenna=3; // LNAW + if(radio->device==SOAPYSDR_USB_DEVICE) { + adc[1].rx_gain=malloc(radio->info.soapy.rx_gains*sizeof(gint)); + for (size_t i = 0; i < radio->info.soapy.rx_gains; i++) { + adc[1].rx_gain[i]=0; + } + adc[1].agc=FALSE; + +/* + if(r->can_transmit) { + r->dac[1].tx_gain=malloc(r->discovered->info.soapy.tx_gains*sizeof(gint)); + for (size_t i = 0; i < r->discovered->info.soapy.tx_gains; i++) { + r->dac[1].tx_gain[i]=0; + } + } +*/ + } + + radio_sample_rate=radio->info.soapy.sample_rate; +#endif + //fprintf(stderr,"meter_calibration=%f display_calibration=%f\n", meter_calibration, display_calibration); + +#ifdef CONTROLLER2 + display_sliders=0; + display_toolbar=1; +#else + display_sliders=1; + display_toolbar=1; +#endif + +#ifdef GPIO + gpio_restore_state(); +#endif radioRestoreState(); @@ -537,8 +699,19 @@ void start_radio() { // Change setting to reasonable value then. // // - if (protocol == ORIGINAL_PROTOCOL && buffer_size > 2048) buffer_size=2048; - if (protocol == NEW_PROTOCOL && buffer_size > 512) buffer_size= 512; + switch (protocol) { + case ORIGINAL_PROTOCOL: + if (buffer_size > 2048) buffer_size=2048; + break; + case NEW_PROTOCOL: + if (buffer_size > 512) buffer_size=512; + break; +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: + if (buffer_size > 2048) buffer_size=2048; + break; +#endif + } radio_change_region(region); @@ -572,10 +745,13 @@ void start_radio() { y+=MENU_HEIGHT; - int rx_height=display_height-VFO_HEIGHT-TOOLBAR_HEIGHT; + int rx_height=display_height-VFO_HEIGHT; if(display_sliders) { rx_height-=SLIDERS_HEIGHT; } + if(display_toolbar) { + rx_height-=TOOLBAR_HEIGHT; + } int tx_height=rx_height; rx_height=rx_height/RECEIVERS; @@ -639,9 +815,9 @@ void start_radio() { case NEW_PROTOCOL: new_protocol_init(display_width); break; -#ifdef LIMESDR - case LIMESDR_PROTOCOL: - lime_protocol_init(0,display_width,receiver[0]->sample_rate); +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: + soapy_protocol_init(0,false); break; #endif } @@ -660,9 +836,11 @@ void start_radio() { } - toolbar = toolbar_init(display_width,TOOLBAR_HEIGHT,top_window); - gtk_fixed_put(GTK_FIXED(fixed),toolbar,0,y); - y+=TOOLBAR_HEIGHT; + if(display_toolbar) { + toolbar = toolbar_init(display_width,TOOLBAR_HEIGHT,top_window); + gtk_fixed_put(GTK_FIXED(fixed),toolbar,0,y); + y+=TOOLBAR_HEIGHT; + } // // Now, if there should only one receiver be displayed @@ -686,7 +864,7 @@ void start_radio() { // save every 30 seconds - save_timer_id=gdk_threads_add_timeout(30000, save_cb, NULL); + //save_timer_id=gdk_threads_add_timeout(30000, save_cb, NULL); #ifdef PSK if(vfo[active_receiver->id].mode==modePSK) { @@ -710,6 +888,33 @@ void start_radio() { schedule_high_priority(); } +#ifdef SOAPYSDR + if(protocol==SOAPYSDR_PROTOCOL) { + RECEIVER *rx=receiver[0]; + soapy_protocol_create_receiver(rx); + + + soapy_protocol_set_rx_antenna(rx,adc[0].antenna); + for(int i=0;iinfo.soapy.rx_gains;i++) { + soapy_protocol_set_gain(rx,radio->info.soapy.rx_gain[i],adc[0].rx_gain[i]); + } + soapy_protocol_set_rx_frequency(rx,VFO_A); + soapy_protocol_set_automatic_gain(rx,adc[0].agc); + for(int i=0;iinfo.soapy.rx_gains;i++) { + soapy_protocol_set_gain(rx,radio->info.soapy.rx_gain[i],adc[0].rx_gain[i]); + } + soapy_protocol_start_receiver(rx); +/* + if(r->can_transmit) { + if(r->transmitter!=NULL && r->transmitter->rx==rx) { + soapy_protocol_set_tx_antenna(r->transmitter,1); + soapy_protocol_set_tx_frequency(r->transmitter); + } + } +*/ + } +#endif + g_idle_add(ext_vfo_update,(gpointer)NULL); gdk_window_set_cursor(gtk_widget_get_window(top_window),gdk_cursor_new(GDK_ARROW)); @@ -766,9 +971,9 @@ void radio_change_sample_rate(int rate) { tx_set_ps_sample_rate(transmitter,rate); } break; -#ifdef LIMESDR - case LIMESDR_PROTOCOL: - lime_protocol_change_sample_rate(rate); +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: + soapy_protocol_change_sample_rate(receiver[0],rate); break; #endif } @@ -857,9 +1062,20 @@ void setMox(int state) { mox=state; } vox=0; - if(protocol==NEW_PROTOCOL) { + switch(protocol) { + case NEW_PROTOCOL: schedule_high_priority(); schedule_receive_specific(); + break; +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: + if(transmitter!=NULL) { + soapy_protocol_set_tx_frequency(transmitter); + } + break; +#endif + default: + break; } } @@ -878,6 +1094,42 @@ void vox_changed(int state) { } } +void frequency_changed(RECEIVER *rx) { +//fprintf(stderr,"frequency_changed: channel=%d frequency=%ld lo=%ld error=%ld ctun=%d offset=%ld\n",rx->channel,rx->frequency_a,rx->lo_a,rx->error_a,rx->ctun,rx->offset); + if(vfo[0].ctun) { + SetRXAShiftFreq(rx->id, (double)vfo[0].offset); + RXANBPSetShiftFrequency(rx->id, (double)vfo[0].offset); +#ifdef SOAPYSDR + if(radio->protocol==SOAPYSDR_PROTOCOL) { +/* + if(radio->can_transmit) { + if(radio->transmitter!=NULL && radio->transmitter->rx==rx) { + //soapy_protocol_set_tx_frequency(radio->transmitter); + } + } +*/ + } +#endif + } else { + double f=(double)(vfo[0].frequency-vfo[0].lo); + if(radio->protocol==NEW_PROTOCOL) { + schedule_high_priority(); +#ifdef SOAPYSDR + } else if(radio->protocol==SOAPYSDR_PROTOCOL) { + soapy_protocol_set_rx_frequency(rx,VFO_A); +/* + if(radio->can_transmit) { + if(radio->transmitter!=NULL && radio->transmitter->rx==rx) { + soapy_protocol_set_tx_frequency(radio->transmitter); + } + } +*/ +#endif + } + vfo[0].band=get_band_from_frequency(vfo[0].frequency); + } +} + void setTune(int state) { int i; @@ -1002,6 +1254,9 @@ void setFrequency(long long f) { switch(protocol) { case NEW_PROTOCOL: case ORIGINAL_PROTOCOL: +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: +#endif 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); @@ -1015,20 +1270,6 @@ void setFrequency(long long f) { vfo[v].frequency=f; } break; -#ifdef LIMESDR - case LIMESDR_PROTOCOL: - { -fprintf(stderr,"setFrequency: %lld\n",f); - 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; - vfo[v].offset=f-vfo[v].frequency; - set_offset(active_receiver,vfo[v].offset); - return; - } - break; -#endif } switch(protocol) { @@ -1037,11 +1278,12 @@ fprintf(stderr,"setFrequency: %lld\n",f); break; case ORIGINAL_PROTOCOL: break; -#ifdef LIMESDR - case LIMESDR_PROTOCOL: - lime_protocol_set_frequency(f); - vfo[v].offset=0; - set_offset(active_receiver,vfo[v].offset); +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: + if(!vfo[v].ctun) { + soapy_protocol_set_rx_frequency(active_receiver,v); + vfo[v].offset=0; + } break; #endif } @@ -1112,9 +1354,9 @@ void set_attenuation(int value) { case NEW_PROTOCOL: schedule_high_priority(); break; -#ifdef LIMESDR - case LIMESDR_PROTOCOL: - lime_protocol_set_attenuation(value); +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: + //soapy_protocol_set_attenuation(value); break; #endif } @@ -1127,9 +1369,9 @@ void set_alex_rx_antenna(int v) { schedule_high_priority(); } } -#ifdef LIMESDR - if(protocol==LIMESDR_PROTOCOL) { - lime_protocol_set_antenna(v);; +#ifdef SOAPYSDR + if(protocol==SOAPYSDR_PROTOCOL) { + soapy_protocol_set_rx_antenna(active_receiver,v); } #endif } @@ -1160,14 +1402,17 @@ void set_alex_attenuation(int v) { } void radioRestoreState() { + char name[80]; char *value; fprintf(stderr,"radioRestoreState: %s\n",property_path); +fprintf(stderr,"sem_wait\n"); #ifdef __APPLE__ sem_wait(property_sem); #else sem_wait(&property_sem); #endif +fprintf(stderr,"sem_wait: returner\n"); loadProperties(property_path); value=getProperty("new_pa_board"); @@ -1206,10 +1451,8 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path); if(value) panadapter_low=atoi(value); value=getProperty("display_sliders"); if(value) display_sliders=atoi(value); -/* value=getProperty("display_toolbar"); if(value) display_toolbar=atoi(value); -*/ value=getProperty("waterfall_high"); if(value) waterfall_high=atoi(value); value=getProperty("waterfall_low"); @@ -1335,23 +1578,20 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path); value=getProperty("tone_level"); if(value) tone_level=atof(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); + value=getProperty("iqswap"); + if(value) iqswap=atoi(value); + filterRestoreState(); bandRestoreState(); memRestoreState(); vfo_restore_state(); modesettings_restore_state(); +#ifdef GPIO + gpio_restore_actions(); +#endif #ifdef FREEDV freedv_restore_state(); #endif @@ -1368,8 +1608,34 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path); value=getProperty("rx1_gain_slider"); if(value) rx_gain_slider[0]=atoi(value); value=getProperty("rx2_gain_slider"); - if(value) rx_gain_slider[1]=atoi(value); + if(value) rx_gain_slider[1]=atoi(value); + +#ifdef SOAPYSDR + if(radio->device==SOAPYSDR_USB_DEVICE) { + for(int i=0;iinfo.soapy.rx_gains;i++) { + sprintf(name,"radio.adc[0].rx_gain.%s",radio->info.soapy.rx_gain[i]) ; + value=getProperty(name); + if(value!=NULL) adc[0].rx_gain[i]=atoi(value); + } + value=getProperty("radio.adc[0].agc"); + if(value!=NULL) adc[0].agc=atoi(value); + value=getProperty("radio.adc[0].antenna"); + if(value!=NULL) adc[0].antenna=atoi(value); + +/* + if(radio->can_transmit) { + for(int i=0;iinfo.soapy.tx_gains;i++) { + sprintf(name,"radio.dac[0].tx_gain.%s",radio->info.soapy.tx_gain[i]); + value=getProperty(name); + if(value!=NULL) dac[0].tx_gain[i]=atoi(value); + } + } +*/ + } +#endif + +fprintf(stderr,"sem_post\n"); #ifdef __APPLE__ sem_post(property_sem); #else @@ -1379,13 +1645,17 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path); void radioSaveState() { int i; + char name[80]; char value[80]; +fprintf(stderr,"radioSaveState: %s\n",property_path); +fprintf(stderr,"sem_wait\n"); #ifdef __APPLE__ sem_wait(property_sem); #else sem_wait(&property_sem); #endif +fprintf(stderr,"sem_wait: returned\n"); sprintf(value,"%d",new_pa_board); setProperty("new_pa_board",value); sprintf(value,"%d",region); @@ -1416,6 +1686,8 @@ void radioSaveState() { setProperty("panadapter_low",value); sprintf(value,"%d",display_sliders); setProperty("display_sliders",value); + sprintf(value,"%d",display_toolbar); + setProperty("display_toolbar",value); sprintf(value,"%d",waterfall_high); setProperty("waterfall_high",value); sprintf(value,"%d",waterfall_low); @@ -1531,24 +1803,69 @@ void radioSaveState() { sprintf(value,"%f",tone_level); setProperty("tone_level",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 - sprintf(value,"%d",adc_attenuation[0]); setProperty("adc_0_attenuation",value); sprintf(value,"%d",adc_attenuation[1]); setProperty("adc_1_attenuation",value); - sprintf(value,"%d",rx_gain_slider[0]); + sprintf(value,"%d",rx_gain_slider[0]); setProperty("rx1_gain_slider",value); sprintf(value,"%d",rx_gain_slider[1]); setProperty("rx2_gain_slider",value); + +#ifdef SOAPYSDR + if(radio->device==SOAPYSDR_USB_DEVICE) { + for(int i=0;iinfo.soapy.rx_gains;i++) { + sprintf(name,"radio.adc[0].rx_gain.%s",radio->info.soapy.rx_gain[i]); + sprintf(value,"%d", adc[0].rx_gain[i]); + setProperty(name,value); + } + sprintf(name,"radio.adc[0].agc"); + sprintf(value,"%d", soapy_protocol_get_automatic_gain(receiver[0])); + setProperty(name,value); + sprintf(name,"radio.adc[0].antenna"); + sprintf(value,"%d", adc[0].antenna); + setProperty(name,value); + +/* + if(radio->can_transmit) { + for(int i=0;idiscovered->info.soapy.tx_gains;i++) { + sprintf(name,"radio.dac[0].tx_gain.%s",radio->discovered->info.soapy.tx_gain[i]); + sprintf(value,"%d", radio->dac[0].tx_gain[i]); + setProperty(name,value); + } + } +*/ + for(int i=0;iinfo.soapy.rx_gains;i++) { + sprintf(name,"radio.adc[1].rx_gain.%s",radio->info.soapy.rx_gain[i]); + sprintf(value,"%d", adc[1].rx_gain[i]); + setProperty(name,value); + } + sprintf(name,"radio.adc[1].agc"); + sprintf(value,"%d", soapy_protocol_get_automatic_gain(receiver[1])); + setProperty(name,value); + sprintf(name,"radio.adc[1].antenna"); + sprintf(value,"%d", adc[1].antenna); + setProperty(name,value); + +/* + if(radio->can_transmit) { + for(int i=0;idiscovered->info.soapy.tx_gains;i++) { + sprintf(name,"radio.dac[1].tx_gain.%s",radio->discovered->info.soapy.tx_gain[i]); + sprintf(value,"%d", radio->dac[1].tx_gain[i]); + setProperty(name,value); + } + } +*/ + } +#endif + + + sprintf(value,"%d",receivers); + setProperty("receivers",value); + + sprintf(value,"%d",iqswap); + setProperty("iqswap",value); vfo_save_state(); modesettings_save_state(); @@ -1571,12 +1888,17 @@ void radioSaveState() { bandSaveState(); memSaveState(); +#ifdef GPIO + gpio_save_actions(); +#endif + sprintf(value,"%d",rigctl_enable); setProperty("rigctl_enable",value); sprintf(value,"%d",rigctl_port_base); setProperty("rigctl_port_base",value); saveProperties(property_path); +fprintf(stderr,"sem_post\n"); #ifdef __APPLE__ sem_post(property_sem); #else diff --git a/radio.h b/radio.h index f1898ae..f10902e 100644 --- a/radio.h +++ b/radio.h @@ -20,6 +20,7 @@ #ifndef _RADIO_H #define _RADIO_H +#include "adc.h" #include "discovered.h" #include "receiver.h" #include "transmitter.h" @@ -88,6 +89,9 @@ extern TRANSMITTER *transmitter; extern int echo; +extern int radio_sample_rate; +extern gboolean iqswap; + #define MAX_BUFFER_SIZE 2048 extern int buffer_size; @@ -146,7 +150,7 @@ extern int mic_ptt_tip_bias_ring; int receivers; -int adc[2]; +ADC adc[2]; int adc_attenuation[2]; int rx_gain_slider[2]; @@ -265,6 +269,7 @@ extern int getMox(); extern void setTune(int state); extern int getTune(); extern void vox_changed(int state); +extern void frequency_changed(RECEIVER *rx); extern double getDrive(); extern void setDrive(double d); extern void calcDriveLevel(); diff --git a/radio_menu.c b/radio_menu.c index 9d40fdb..4f6b87f 100644 --- a/radio_menu.c +++ b/radio_menu.c @@ -26,6 +26,7 @@ #include "new_menu.h" #include "radio_menu.h" +#include "adc.h" #include "band.h" #include "filter.h" #include "radio.h" @@ -33,6 +34,9 @@ #include "sliders.h" #include "new_protocol.h" #include "old_protocol.h" +#ifdef SOAPYSDR +#include "soapy_protocol.h" +#endif #include "gpio.h" static GtkWidget *parent_window=NULL; @@ -59,6 +63,46 @@ static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_d return FALSE; } +#ifdef SOAPYSDR +static void gain_value_changed_cb(GtkWidget *widget, gpointer data) { + ADC *adc=(ADC *)data; + int gain; + if(radio->device==SOAPYSDR_USB_DEVICE) { + gain=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); + soapy_protocol_set_gain(receiver[0],(char *)gtk_widget_get_name(widget),gain); + for(int i=0;iinfo.soapy.rx_gains;i++) { + if(strcmp(radio->info.soapy.rx_gain[i],(char *)gtk_widget_get_name(widget))==0) { + adc[0].rx_gain[i]=gain; + break; + } + } + } +} + +static void agc_changed_cb(GtkWidget *widget, gpointer data) { + ADC *adc=(ADC *)data; + gboolean agc=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + soapy_protocol_set_automatic_gain(receiver[0],agc); +} + +/* +static void dac0_gain_value_changed_cb(GtkWidget *widget, gpointer data) { + DAC *dac=(DAC *)data; + int gain; + if(radio->device==SOAPYSDR_USB_DEVICE) { + gain=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); + soapy_protocol_set_tx_gain(radio->transmitter,(char *)gtk_widget_get_name(widget),gain); + for(int i=0;idiscovered->info.soapy.tx_gains;i++) { + if(strcmp(radio->discovered->info.soapy.tx_gain[i],(char *)gtk_widget_get_name(widget))==0) { + radio->dac[0].tx_gain[i]=gain; + break; + } + } + } +} +*/ +#endif + 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)); } @@ -94,6 +138,11 @@ static void bias_cb(GtkWidget *widget, gpointer data) { mic_bias_enabled=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); } +static void iqswap_cb(GtkWidget *widget, gpointer data) { + iqswap=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); +} + + static void load_filters(void) { if(protocol==NEW_PROTOCOL) { filter_board_changed(); @@ -280,25 +329,25 @@ void radio_menu(GtkWidget *parent) { } break; -#ifdef LIMESDR - case LIMESDR_PROTOCOL: +#ifdef SOAPYSDR + case SOAPYSDR_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); + char rate[16]; + sprintf(rate,"%d",radio->info.soapy.sample_rate); + + GtkWidget *sample_rate=gtk_radio_button_new_with_label(NULL,rate); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate), radio->info.soapy.sample_rate); + gtk_grid_attach(GTK_GRID(grid),sample_rate,x,2,1,1); + g_signal_connect(sample_rate,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)radio->info.soapy.sample_rate); + x++; } break; #endif + } @@ -387,6 +436,11 @@ void radio_menu(GtkWidget *parent) { 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); + GtkWidget *iqswap_b=gtk_check_button_new_with_label("Swap IQ"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (iqswap_b), iqswap); + gtk_grid_attach(GTK_GRID(grid),iqswap_b,x,4,1,1); + g_signal_connect(iqswap_b,"toggled",G_CALLBACK(iqswap_cb),NULL); + x++; #ifdef USBOZY @@ -429,6 +483,43 @@ void radio_menu(GtkWidget *parent) { g_signal_connect(pene_tx_b,"toggled",G_CALLBACK(penelopetx_cb),NULL); } +#ifdef SOAPYSDR + if(radio->device==SOAPYSDR_USB_DEVICE) { + int i; + if(radio->info.soapy.rx_gains>0) { + x++; + GtkWidget *gain=gtk_label_new("Gains:"); + gtk_grid_attach(GTK_GRID(grid),gain,0,x,1,1); + x++; + } + + if(radio->info.soapy.rx_has_automatic_gain) { + GtkWidget *agc=gtk_check_button_new_with_label("Hardware AGC: "); + gtk_grid_attach(GTK_GRID(grid),agc,1,x,1,1); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(agc),adc[0].agc); + g_signal_connect(agc,"toggled",G_CALLBACK(agc_changed_cb),&adc[0]); + x++; + } + + for(i=0;iinfo.soapy.rx_gains;i++) { + GtkWidget *gain_label=gtk_label_new(radio->info.soapy.rx_gain[i]); + gtk_grid_attach(GTK_GRID(grid),gain_label,0,x,1,1); + SoapySDRRange range=radio->info.soapy.rx_range[i]; + if(range.step==0.0) { + range.step=1.0; + } + GtkWidget *gain_b=gtk_spin_button_new_with_range(range.minimum,range.maximum,range.step); + gtk_widget_set_name (gain_b, radio->info.soapy.rx_gain[i]); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(gain_b),(double)adc[0].rx_gain[i]); + gtk_grid_attach(GTK_GRID(grid),gain_b,1,x,1,1); + g_signal_connect(gain_b,"value_changed",G_CALLBACK(gain_value_changed_cb),&adc[0]); + x++; + } + + } +#endif + + gtk_container_add(GTK_CONTAINER(content),grid); sub_menu=dialog; diff --git a/receiver.c b/receiver.c index 41a8664..694bff9 100644 --- a/receiver.c +++ b/receiver.c @@ -34,11 +34,6 @@ #include "main.h" #include "meter.h" #include "mode.h" -#include "new_protocol.h" -#include "old_protocol.h" -#ifdef LIME_PROTOOCL -#include "lime_protocol.h" -#endif #include "property.h" #include "radio.h" #include "receiver.h" @@ -48,6 +43,11 @@ #include "rx_panadapter.h" #include "sliders.h" #include "waterfall.h" +#include "new_protocol.h" +#include "old_protocol.h" +#ifdef SOAPYSDR +#include "soapy_protocol.h" +#endif #ifdef FREEDV #include "freedv.h" #endif @@ -85,6 +85,8 @@ gboolean receiver_button_press_event(GtkWidget *widget, GdkEventButton *event, g last_x=(int)event->x; has_moved=FALSE; pressed=TRUE; + } else if(event->button==3) { + g_idle_add(ext_start_rx,NULL); } } else { making_active=TRUE; @@ -100,6 +102,9 @@ gboolean receiver_button_release_event(GtkWidget *widget, GdkEventButton *event, g_idle_add(menu_active_receiver_changed,NULL); g_idle_add(ext_vfo_update,NULL); g_idle_add(sliders_active_receiver_changed,NULL); + if(event->button==3) { + g_idle_add(ext_start_rx,NULL); + } } else { int display_width=gtk_widget_get_allocated_width (rx->panadapter); int display_height=gtk_widget_get_allocated_height (rx->panadapter); @@ -133,12 +138,13 @@ gboolean receiver_motion_notify_event(GtkWidget *widget, GdkEventMotion *event, &x, &y, &state); - if(state & GDK_BUTTON1_MASK) { + // G0ORX: removed test as with it unable to drag screen + //if(state & GDK_BUTTON1_MASK) { int moved=last_x-x; vfo_move((long long)((float)moved*rx->hz_per_pixel)); last_x=x; has_moved=TRUE; - } + //} } return TRUE; @@ -198,6 +204,9 @@ void receiver_save_state(RECEIVER *rx) { sprintf(name,"receiver.%d.panadapter_high",rx->id); sprintf(value,"%d",rx->panadapter_high); setProperty(name,value); + sprintf(name,"receiver.%d.panadapter_step",rx->id); + sprintf(value,"%d",rx->panadapter_step); + setProperty(name,value); sprintf(name,"receiver.%d.display_waterfall",rx->id); sprintf(value,"%d",rx->display_waterfall); setProperty(name,value); @@ -367,6 +376,9 @@ fprintf(stderr,"receiver_restore_state: id=%d\n",rx->id); sprintf(name,"receiver.%d.panadapter_high",rx->id); value=getProperty(name); if(value) rx->panadapter_high=atoi(value); + sprintf(name,"receiver.%d.panadapter_step",rx->id); + value=getProperty(name); + if(value) rx->panadapter_step=atoi(value); sprintf(name,"receiver.%d.display_waterfall",rx->id); value=getProperty(name); if(value) rx->display_waterfall=atoi(value); @@ -444,6 +456,11 @@ fprintf(stderr,"receiver_restore_state: id=%d\n",rx->id); if(value) rx->audio_channel=atoi(value); sprintf(name,"receiver.%d.local_audio",rx->id); value=getProperty(name); +if(value) { + fprintf(stderr,"%s=%s\n",name,value); +} else { + fprintf(stderr,"%s=NULL\n",name); +} if(value) rx->local_audio=atoi(value); sprintf(name,"receiver.%d.mute_when_not_active",rx->id); value=getProperty(name); @@ -800,6 +817,7 @@ fprintf(stderr,"create_pure_signal_receiver: id=%d buffer_size=%d\n",id,buffer_s rx->panadapter_high=-40; rx->panadapter_low=-140; + rx->panadapter_step=20; rx->volume=0.0; @@ -894,7 +912,25 @@ fprintf(stderr,"create_receiver: id=%d buffer_size=%d fft_size=%d pixels=%d fps= } } fprintf(stderr,"create_receiver: id=%d default adc=%d\n",rx->id, rx->adc); - rx->sample_rate=48000; +#ifdef SOAPYSDR + if(radio->device==SOAPYSDR_USB_DEVICE) { +/* + if(strcmp(radio->name,"lime")==0) { + rx->sample_rate=384000; + } else if(strcmp(radio->name,"rtlsdr")==0) { + rx->sample_rate=384000; + } else { + rx->sample_rate=384000; + } +*/ + rx->sample_rate=radio->info.soapy.sample_rate; + rx->resample_step=1; + } else { +#endif + rx->sample_rate=48000; +#ifdef SOAPYSDR + } +#endif rx->buffer_size=buffer_size; rx->fft_size=fft_size; rx->pixels=pixels; @@ -979,6 +1015,9 @@ fprintf(stderr,"create_receiver: id=%d default adc=%d\n",rx->id, rx->adc); receiver_restore_state(rx); + rx->resample_step=radio->info.soapy.sample_rate/rx->sample_rate; + +fprintf(stderr,"create_receiver (after restore): rx=%p id=%d local_audio=%d\n",rx,rx->id,rx->local_audio); int scale=rx->sample_rate/48000; rx->output_samples=rx->buffer_size/scale; rx->audio_output_buffer=malloc(sizeof(double)*2*rx->output_samples); @@ -1078,6 +1117,7 @@ fprintf(stderr,"RXASetMP %d\n",rx->low_latency); create_visual(rx); +fprintf(stderr,"create_receiver: rx=%p id=%d local_audio=%d\n",rx,rx->id,rx->local_audio); if(rx->local_audio) { audio_open_output(rx); } @@ -1135,6 +1175,14 @@ void receiver_change_sample_rate(RECEIVER *rx,int sample_rate) { SetInputSamplerate(rx->id, sample_rate); SetEXTANBSamplerate (rx->id, sample_rate); SetEXTNOBSamplerate (rx->id, sample_rate); + +#ifdef SOAPYSDR + if(protocol==SOAPYSDR_PROTOCOL) { + rx->resample_step=radio_sample_rate/rx->sample_rate; +g_print("receiver_change_sample_rate: resample_step=%d\n",rx->resample_step); + } +#endif + SetChannelState(rx->id,1,0); 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); @@ -1146,8 +1194,17 @@ void receiver_frequency_changed(RECEIVER *rx) { 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 + } else { + switch(protocol) { + case NEW_PROTOCOL: + schedule_high_priority(); // send new frequency + break; +#if SOAPYSDR + case SOAPYSDR_PROTOCOL: + soapy_protocol_set_rx_frequency(rx,id); + break; +#endif + } } } @@ -1232,8 +1289,8 @@ static void process_freedv_rx_buffer(RECEIVER *rx) { case NEW_PROTOCOL: new_protocol_audio_samples(rx,left_audio_sample,right_audio_sample); break; -#ifdef LIMESDR - case LIMESDR_PROTOCOL: +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: break; #endif } @@ -1310,8 +1367,8 @@ static void process_rx_buffer(RECEIVER *rx) { } } break; -#ifdef LIMESDR - case LIMESDR_PROTOCOL: +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: break; #endif } @@ -1352,7 +1409,7 @@ void full_rx_buffer(RECEIVER *rx) { 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); + //fprintf(stderr,"full_rx_buffer: id=%d fexchange0: error=%d\n",rx->id,error); } if(rx->displaying) { diff --git a/receiver.h b/receiver.h index 0327a99..0464c63 100644 --- a/receiver.h +++ b/receiver.h @@ -39,6 +39,7 @@ typedef enum _audio_t audio_t; typedef struct _receiver { int id; + int ddc; int adc; double volume; @@ -99,6 +100,7 @@ typedef struct _receiver { int panadapter_low; int panadapter_high; + int panadapter_step; int waterfall_low; int waterfall_high; @@ -128,6 +130,9 @@ typedef struct _receiver { int mute_radio; + gdouble *buffer; + int resample_step; + #ifdef FREEDV GMutex freedv_mutex; int freedv; diff --git a/release/pihpsdr-v1.2.3.tar b/release/pihpsdr-v1.2.3.tar index 2628abf..e92fc2a 100644 Binary files a/release/pihpsdr-v1.2.3.tar and b/release/pihpsdr-v1.2.3.tar differ diff --git a/release/pihpsdr.tar b/release/pihpsdr.tar index 2628abf..ab8bf75 100644 Binary files a/release/pihpsdr.tar and b/release/pihpsdr.tar differ diff --git a/release/pihpsdr/install.sh b/release/pihpsdr/install.sh index e44c896..757fd4b 100755 --- a/release/pihpsdr/install.sh +++ b/release/pihpsdr/install.sh @@ -33,11 +33,17 @@ fi cp pihpsdr.desktop ~/.local/share/applications echo "removing old versions of shared libraries" sudo rm -rf /usr/local/lib/libwdsp.so -sudo rm -rf /usr/local/lib/libcodec2.* echo "installing pihpsdr" sudo cp pihpsdr /usr/local/bin echo "installing shared libraries" sudo cp libwdsp.so /usr/local/lib -sudo cp libcodec2.so.0.7 /usr/local/lib -cd /usr/local/lib; sudo ln -s libcodec2.so.0.7 libcodec2.so +sudo cp libLimeSuite.so.19.04.1 /usr/local/lib +sudo cp libSoapySDR.so.0.8.0 /usr/local/lib +sudo cp -R SoapySDR /usr/local/lib +cd /usr/local/lib +sudo ln -s libLimeSuite.so.19.04.1 libLimeSuite.so.19.04-1 +sudo ln -s libLimeSuite.so.19.04-1 libLimeSuite.so +sudo ln -s libSoapySDR.so.0.8.0 libSoapySDR.so.0.8 +sudo ln -s libSoapySDR.so.0.8 libLimeSuite.so +sudo apt-get install librtlsdr-dev sudo ldconfig diff --git a/release/pihpsdr/libSoapySDR.so.0.5-1 b/release/pihpsdr/libSoapySDR.so.0.5-1 deleted file mode 100755 index 3c0232f..0000000 Binary files a/release/pihpsdr/libSoapySDR.so.0.5-1 and /dev/null differ diff --git a/release/pihpsdr/libcodec2.so.0.7 b/release/pihpsdr/libcodec2.so.0.7 deleted file mode 100755 index 5038f4f..0000000 Binary files a/release/pihpsdr/libcodec2.so.0.7 and /dev/null differ diff --git a/release/pihpsdr/libpsk.so b/release/pihpsdr/libpsk.so deleted file mode 100755 index 0ace61f..0000000 Binary files a/release/pihpsdr/libpsk.so and /dev/null differ diff --git a/release/pihpsdr/libwdsp.so b/release/pihpsdr/libwdsp.so index 744bf4b..a020b79 100755 Binary files a/release/pihpsdr/libwdsp.so and b/release/pihpsdr/libwdsp.so differ diff --git a/release/pihpsdr/pihpsdr b/release/pihpsdr/pihpsdr index 51696e9..b741cd2 100755 Binary files a/release/pihpsdr/pihpsdr and b/release/pihpsdr/pihpsdr differ diff --git a/rigctl.c b/rigctl.c index ee19965..54b61ba 100644 --- a/rigctl.c +++ b/rigctl.c @@ -1181,7 +1181,7 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) { fprintf(stderr,"RIGCTL: BD - current band=%d\n",cur_band); #endif if(cur_band == 0) { - #ifdef LIMESDR + #ifdef SOAPYSDR cur_band = band472; #else cur_band = band6; diff --git a/rx_menu.c b/rx_menu.c index 66d262c..eec1927 100644 --- a/rx_menu.c +++ b/rx_menu.c @@ -225,25 +225,30 @@ void rx_menu(GtkWidget *parent) { x++; break; -#ifdef LIMESDR - case LIMESDR_PROTOCOL: +#ifdef SOAPYSDR + case SOAPYSDR_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); + char rate[16]; + sprintf(rate,"%d",radio->info.soapy.sample_rate); + GtkWidget *sample_rate=gtk_radio_button_new_with_label(NULL,rate); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate), radio->info.soapy.sample_rate); + gtk_grid_attach(GTK_GRID(grid),sample_rate,x,2,1,1); + g_signal_connect(sample_rate,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)radio->info.soapy.sample_rate); + + if(radio->info.soapy.sample_rate>384000) { + GtkWidget *sample_rate_384K=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(sample_rate),"384000"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sample_rate_384K), active_receiver->sample_rate==384000); + gtk_grid_attach(GTK_GRID(grid),sample_rate_384K,x,3,1,1); + g_signal_connect(sample_rate_384K,"pressed",G_CALLBACK(sample_rate_cb),(gpointer *)384000); + } } x++; break; #endif + } // diff --git a/rx_panadapter.c b/rx_panadapter.c index 52a2eb8..ad36311 100644 --- a/rx_panadapter.c +++ b/rx_panadapter.c @@ -223,7 +223,7 @@ void rx_panadapter_update(RECEIVER *rx) { // filter - cairo_set_source_rgba (cr, 0.25, 0.25, 0.25, 0.75); + cairo_set_source_rgba (cr, 0.75, 0.75, 0.00, 0.75); filter_left =-cwshift+(double)display_width/2.0+(((double)rx->filter_low+vfo[rx->id].offset)/rx->hz_per_pixel); filter_right=-cwshift+(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); @@ -260,7 +260,7 @@ void rx_panadapter_update(RECEIVER *rx) { char v[32]; for(i=rx->panadapter_high;i>=rx->panadapter_low;i--) { - int mod=abs(i)%20; + int mod=abs(i)%rx->panadapter_step; if(mod==0) { double y = (double)(rx->panadapter_high-i)*dbm_per_line; cairo_move_to(cr,0.0,y); @@ -327,7 +327,7 @@ void rx_panadapter_update(RECEIVER *rx) { // band edges if(band->frequencyMin!=0LL) { cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); - cairo_set_line_width(cr, 2.0); + cairo_set_line_width(cr, 1.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); @@ -458,26 +458,28 @@ void rx_panadapter_update(RECEIVER *rx) { } #endif -#ifdef GPIO +#ifdef GPIO +#ifndef CONTROLLER2 if(active) { cairo_set_source_rgb(cr,1.0,1.0,0.0); cairo_set_font_size(cr,16); - if(ENABLE_E1_ENCODER) { + if(ENABLE_E2_ENCODER) { cairo_move_to(cr, display_width-150,30); - cairo_show_text(cr, encoder_string[e1_encoder_action]); + cairo_show_text(cr, encoder_string[e2_encoder_action]); } - if(ENABLE_E2_ENCODER) { + if(ENABLE_E3_ENCODER) { cairo_move_to(cr, display_width-150,50); - cairo_show_text(cr, encoder_string[e2_encoder_action]); + cairo_show_text(cr, encoder_string[e3_encoder_action]); } - if(ENABLE_E3_ENCODER) { + if(ENABLE_E4_ENCODER) { cairo_move_to(cr, display_width-150,70); - cairo_show_text(cr, encoder_string[e3_encoder_action]); + cairo_show_text(cr, encoder_string[e4_encoder_action]); } } #endif +#endif cairo_destroy (cr); diff --git a/sliders.c b/sliders.c index f95fdee..b9b0901 100644 --- a/sliders.c +++ b/sliders.c @@ -69,6 +69,9 @@ static GtkWidget *sliders; #define ATTENUATION 6 #define SQUELCH 7 #define COMP 8 +#define FILTER_WIDTH 9 +#define DIVERSITY_GAIN 10 +#define DIVERSITY_PHASE 11 static gint scale_timer; static int scale_status=NONE; @@ -93,6 +96,9 @@ static GtkWidget *comp_label; static GtkWidget *comp_scale; static GtkWidget *comp_enable; static GtkWidget *dummy_label; +static GtkWidget *filter_width_scale; +static GtkWidget *diversity_gain_scale; +static GtkWidget *diversity_phase_scale; static GdkRGBA white; static GdkRGBA gray; @@ -275,11 +281,11 @@ static void agcgain_value_changed_cb(GtkWidget *widget, gpointer data) { SetRXAAGCTop(active_receiver->id, active_receiver->agc_gain); } -void set_agc_gain(double value) { - active_receiver->agc_gain=value; - SetRXAAGCTop(active_receiver->id, active_receiver->agc_gain); +void set_agc_gain(int rx,double value) { + receiver[rx]->agc_gain=value; + SetRXAAGCTop(receiver[rx]->id, receiver[rx]->agc_gain); if(display_sliders) { - gtk_range_set_value (GTK_RANGE(agc_scale),active_receiver->agc_gain); + gtk_range_set_value (GTK_RANGE(agc_scale),receiver[rx]->agc_gain); } else { if(scale_status!=AGC_GAIN) { if(scale_status!=NONE) { @@ -294,7 +300,7 @@ void set_agc_gain(double value) { 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),active_receiver->agc_gain); + gtk_range_set_value (GTK_RANGE(agc_scale),receiver[rx]->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); @@ -302,14 +308,14 @@ 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),active_receiver->agc_gain); + gtk_range_set_value (GTK_RANGE(agc_scale),receiver[rx]->agc_gain); scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL); } } } void update_agc_gain(double gain) { - set_agc_gain(gain); + set_agc_gain(active_receiver->id,gain); } static void afgain_value_changed_cb(GtkWidget *widget, gpointer data) { @@ -324,14 +330,14 @@ static void afgain_value_changed_cb(GtkWidget *widget, gpointer data) { } void update_af_gain() { - set_af_gain(active_receiver->volume); + set_af_gain(active_receiver->id,active_receiver->volume); } -void set_af_gain(double value) { - active_receiver->volume=value; - SetRXAPanelGain1 (active_receiver->id, active_receiver->volume); +void set_af_gain(int rx,double value) { + receiver[rx]->volume=value; + SetRXAPanelGain1 (receiver[rx]->id, receiver[rx]->volume); if(display_sliders) { - gtk_range_set_value (GTK_RANGE(af_gain_scale),active_receiver->volume*100.0); + gtk_range_set_value (GTK_RANGE(af_gain_scale),receiver[rx]->volume*100.0); } else { if(scale_status!=AF_GAIN) { if(scale_status!=NONE) { @@ -346,7 +352,7 @@ void set_af_gain(double value) { 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),active_receiver->volume*100.0); + gtk_range_set_value (GTK_RANGE(af_gain_scale),receiver[rx]->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); @@ -354,12 +360,40 @@ 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),active_receiver->volume*100.0); + gtk_range_set_value (GTK_RANGE(af_gain_scale),receiver[rx]->volume*100.0); scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL); } } } +void set_filter_width(int rx,int width) { + if(scale_status!=FILTER_WIDTH) { + if(scale_status!=NONE) { + g_source_remove(scale_timer); + gtk_widget_destroy(scale_dialog); + scale_status=NONE; + } + } + if(scale_status==NONE) { + scale_status=FILTER_WIDTH; + scale_dialog=gtk_dialog_new_with_buttons("Filter Width (Hz)",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); + GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog)); + filter_width_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 4000.0, 1.00); + gtk_widget_set_size_request (filter_width_scale, 400, 30); + gtk_range_set_value (GTK_RANGE(filter_width_scale),(double)width); + gtk_widget_show(filter_width_scale); + gtk_container_add(GTK_CONTAINER(content),filter_width_scale); + scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL); + //gtk_widget_show_all(scale_dialog); + int result=gtk_dialog_run(GTK_DIALOG(scale_dialog)); + } else { + g_source_remove(scale_timer); + gtk_range_set_value (GTK_RANGE(filter_width_scale),(double)width); + scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL); + } +} + + static void micgain_value_changed_cb(GtkWidget *widget, gpointer data) { if(mic_linein) { linein_gain=(int)gtk_range_get_value(GTK_RANGE(widget)); @@ -583,6 +617,61 @@ void set_compression(TRANSMITTER* tx) { g_idle_add(ext_vfo_update, NULL); } +void show_diversity_gain() { + if(scale_status!=DIVERSITY_GAIN) { + if(scale_status!=NONE) { + g_source_remove(scale_timer); + gtk_widget_destroy(scale_dialog); + scale_status=NONE; + } + } + if(scale_status==NONE) { + scale_status=DIVERSITY_GAIN; + scale_dialog=gtk_dialog_new_with_buttons("Diversity Gain",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); + GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog)); + diversity_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,-12.0, 12.0, 0.1); + gtk_widget_set_size_request (diversity_gain_scale, 400, 30); + gtk_range_set_value (GTK_RANGE(diversity_gain_scale),div_gain); + gtk_widget_show(diversity_gain_scale); + gtk_container_add(GTK_CONTAINER(content),diversity_gain_scale); + scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL); + //gtk_widget_show_all(scale_dialog); + int result=gtk_dialog_run(GTK_DIALOG(scale_dialog)); + } else { + g_source_remove(scale_timer); + gtk_range_set_value (GTK_RANGE(diversity_gain_scale),div_gain); + scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL); + } +} + +void show_diversity_phase() { + if(scale_status!=DIVERSITY_PHASE) { + if(scale_status!=NONE) { + g_source_remove(scale_timer); + gtk_widget_destroy(scale_dialog); + scale_status=NONE; + } + } + if(scale_status==NONE) { + scale_status=DIVERSITY_PHASE; + scale_dialog=gtk_dialog_new_with_buttons("Diversity Phase",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); + GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog)); + diversity_phase_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 360.0, 1.0); + gtk_widget_set_size_request (diversity_phase_scale, 400, 30); + gtk_range_set_value (GTK_RANGE(diversity_phase_scale),div_phase); + gtk_widget_show(diversity_phase_scale); + gtk_container_add(GTK_CONTAINER(content),diversity_phase_scale); + scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL); + //gtk_widget_show_all(scale_dialog); + int result=gtk_dialog_run(GTK_DIALOG(scale_dialog)); + } else { + g_source_remove(scale_timer); + gtk_range_set_value (GTK_RANGE(diversity_phase_scale),div_phase); + scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL); + } +} + + GtkWidget *sliders_init(int my_width, int my_height) { width=my_width; height=my_height; diff --git a/sliders.h b/sliders.h index a33ac7f..32fef86 100644 --- a/sliders.h +++ b/sliders.h @@ -1,8 +1,6 @@ /* 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. * @@ -32,13 +30,15 @@ extern void update_agc_gain(double gain); extern void update_af_gain(); extern int update_mic_gain(void *); extern int update_drive(void *); +extern int update_tune_drive(void *); -extern void set_agc_gain(double value); -extern void set_af_gain(double value); +extern void set_agc_gain(int rx,double value); +extern void set_af_gain(int rx,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 void set_filter_width(int rx,int width); extern GtkWidget *sliders_init(int my_width, int my_height); extern void sliders_update(); @@ -46,4 +46,7 @@ extern void sliders_update(); extern void set_squelch(); extern void set_compression(TRANSMITTER *tx); +extern void show_diversity_gain(); +extern void show_diversity_phase(); + #endif diff --git a/soapy_discovery.c b/soapy_discovery.c new file mode 100644 index 0000000..54c64fd --- /dev/null +++ b/soapy_discovery.c @@ -0,0 +1,244 @@ +/* Copyright (C) +* 2019 - 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 "discovered.h" +#include "soapy_discovery.h" + +static int rtlsdr_count=0; + +static void get_info(char *driver) { + size_t rx_rates_length, tx_rates_length, rx_gains_length, tx_gains_length, ranges_length, rx_antennas_length, tx_antennas_length, rx_bandwidth_length, tx_bandwidth_length; + int i; + SoapySDRKwargs args={}; + int version=0; + int rtlsdr_val=0; + + fprintf(stderr,"soapy_discovery: get_info: %s\n", driver); + + SoapySDRKwargs_set(&args, "driver", driver); + if(strcmp(driver,"rtlsdr")==0) { + char count[16]; + sprintf(count,"%d",rtlsdr_count); + SoapySDRKwargs_set(&args, "rtl", count); + rtlsdr_val=rtlsdr_count; + rtlsdr_count++; + } + SoapySDRDevice *sdr = SoapySDRDevice_make(&args); + SoapySDRKwargs_clear(&args); + version=0; + + char *driverkey=SoapySDRDevice_getDriverKey(sdr); + fprintf(stderr,"DriverKey=%s\n",driverkey); + + char *hardwarekey=SoapySDRDevice_getHardwareKey(sdr); + fprintf(stderr,"HardwareKey=%s\n",hardwarekey); + + SoapySDRKwargs info=SoapySDRDevice_getHardwareInfo(sdr); + for(i=0;i %f (%f),", rx_rates[i].minimum, rx_rates[i].maximum, rx_rates[i].minimum/48000.0); + if(sample_rate==0) { + if(rx_rates[i].minimum==rx_rates[i].maximum) { + if(((int)rx_rates[i].minimum%48000)==0) { + sample_rate=(int)rx_rates[i].minimum; + } + } else { + if((384000.0>=rx_rates[i].minimum) && (384000<=(int)rx_rates[i].maximum)) { + sample_rate=384000; + } +/* + if((768000.0>=rx_rates[i].minimum) && (768000<=(int)rx_rates[i].maximum)) { + sample_rate=768000; + } +*/ + } + } + } + fprintf(stderr,"\n"); + free(rx_rates); + fprintf(stderr,"sample_rate selected %d\n",sample_rate); + + SoapySDRRange *tx_rates=SoapySDRDevice_getSampleRateRange(sdr, SOAPY_SDR_TX, 1, &tx_rates_length); + fprintf(stderr,"Tx sample rates: "); + for (size_t i = 0; i < tx_rates_length; i++) { + fprintf(stderr,"%f -> %f (%f),", tx_rates[i].minimum, tx_rates[i].maximum, tx_rates[i].minimum/48000.0); + } + fprintf(stderr,"\n"); + free(tx_rates); + + double *bandwidths=SoapySDRDevice_listBandwidths(sdr, SOAPY_SDR_RX, 0, &rx_bandwidth_length); + fprintf(stderr,"Rx bandwidths: "); + for (size_t i = 0; i < rx_bandwidth_length; i++) { + fprintf(stderr,"%f, ", bandwidths[i]); + } + fprintf(stderr,"\n"); + free(bandwidths); + + bandwidths=SoapySDRDevice_listBandwidths(sdr, SOAPY_SDR_TX, 0, &tx_bandwidth_length); + fprintf(stderr,"Tx bandwidths: "); + for (size_t i = 0; i < tx_bandwidth_length; i++) { + fprintf(stderr,"%f, ", bandwidths[i]); + } + fprintf(stderr,"\n"); + free(bandwidths); + + double bandwidth=SoapySDRDevice_getBandwidth(sdr, SOAPY_SDR_RX, 0); + fprintf(stderr,"RX0: bandwidth=%f\n",bandwidth); + + bandwidth=SoapySDRDevice_getBandwidth(sdr, SOAPY_SDR_TX, 0); + fprintf(stderr,"TX0: bandwidth=%f\n",bandwidth); + + SoapySDRRange *ranges = SoapySDRDevice_getFrequencyRange(sdr, SOAPY_SDR_RX, 0, &ranges_length); + fprintf(stderr,"Rx freq ranges: "); + for (size_t i = 0; i < ranges_length; i++) fprintf(stderr,"[%f Hz -> %f Hz step=%f], ", ranges[i].minimum, ranges[i].maximum,ranges[i].step); + fprintf(stderr,"\n"); + + char** rx_antennas = SoapySDRDevice_listAntennas(sdr, SOAPY_SDR_RX, 0, &rx_antennas_length); + fprintf(stderr, "Rx antennas: "); + for (size_t i = 0; i < rx_antennas_length; i++) fprintf(stderr, "%s, ", rx_antennas[i]); + fprintf(stderr,"\n"); + + char** tx_antennas = SoapySDRDevice_listAntennas(sdr, SOAPY_SDR_TX, 0, &tx_antennas_length); + fprintf(stderr, "Tx antennas: "); + for (size_t i = 0; i < tx_antennas_length; i++) fprintf(stderr, "%s, ", tx_antennas[i]); + fprintf(stderr,"\n"); + + char **rx_gains = SoapySDRDevice_listGains(sdr, SOAPY_SDR_RX, 0, &rx_gains_length); + + gboolean has_automatic_gain=SoapySDRDevice_hasGainMode(sdr, SOAPY_SDR_RX, 0); + fprintf(stderr,"has_automaic_gain=%d\n",has_automatic_gain); + + gboolean has_automatic_dc_offset_correction=SoapySDRDevice_hasDCOffsetMode(sdr, SOAPY_SDR_RX, 0); + fprintf(stderr,"has_automaic_dc_offset_correction=%d\n",has_automatic_dc_offset_correction); + + char **tx_gains = SoapySDRDevice_listGains(sdr, SOAPY_SDR_TX, 1, &tx_gains_length); + + size_t formats_length; + char **formats = SoapySDRDevice_getStreamFormats(sdr,SOAPY_SDR_RX,0,&formats_length); + fprintf(stderr, "Rx formats: "); + for (size_t i = 0; i < formats_length; i++) fprintf(stderr, "%s, ", formats[i]); + fprintf(stderr,"\n"); + + fprintf(stderr,"float=%lu double=%lu\n",sizeof(float),sizeof(double)); + + if(devices %f step=%f\n",rx_range.minimum,rx_range.maximum,rx_range.step); + discovered[devices].info.soapy.rx_range[i]=rx_range; + } + discovered[devices].info.soapy.rx_has_automatic_gain=has_automatic_gain; + discovered[devices].info.soapy.rx_has_automatic_dc_offset_correction=has_automatic_dc_offset_correction; + discovered[devices].info.soapy.rx_antennas=rx_antennas_length; + discovered[devices].info.soapy.rx_antenna=rx_antennas; + + discovered[devices].info.soapy.tx_channels=tx_channels; + discovered[devices].info.soapy.tx_gains=tx_gains_length; + discovered[devices].info.soapy.tx_gain=tx_gains; + discovered[devices].info.soapy.tx_range=malloc(tx_gains_length*sizeof(SoapySDRRange)); +fprintf(stderr,"Tx gains: \n"); + for (size_t i = 0; i < tx_gains_length; i++) { + fprintf(stderr,"%s ", tx_gains[i]); + SoapySDRRange tx_range=SoapySDRDevice_getGainElementRange(sdr, SOAPY_SDR_TX, 1, tx_gains[i]); + fprintf(stderr,"%f -> %f step=%f\n",tx_range.minimum,tx_range.maximum,tx_range.step); + discovered[devices].info.soapy.tx_range[i]=tx_range; + } + discovered[devices].info.soapy.tx_antennas=tx_antennas_length; + discovered[devices].info.soapy.tx_antenna=tx_antennas; + devices++; + } + + + free(ranges); + +} + +void soapy_discovery() { + size_t length; + int i,j; + SoapySDRKwargs args={}; + +fprintf(stderr,"soapy_discovery\n"); + SoapySDRKwargs *results = SoapySDRDevice_enumerate(NULL, &length); +fprintf(stderr,"soapy_discovery: length=%d\n",length); + for (i = 0; i < length; i++) { + for (size_t j = 0; j < results[i].size; j++) { + if(strcmp(results[i].keys[j],"driver")==0 && strcmp(results[i].vals[j],"audio")!=0) { + get_info(results[i].vals[j]); + } + } + } + SoapySDRKwargsList_clear(results, length); +} diff --git a/soapy_discovery.h b/soapy_discovery.h new file mode 100644 index 0000000..65df402 --- /dev/null +++ b/soapy_discovery.h @@ -0,0 +1,25 @@ +/* Copyright (C) +* 2019 - 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 _SOAPY_DISCOVERY_H +#define _SOAPY_DISCOVERY_H + +void soapy_discovery(); + +#endif diff --git a/soapy_protocol.c b/soapy_protocol.c new file mode 100644 index 0000000..2255dcb --- /dev/null +++ b/soapy_protocol.c @@ -0,0 +1,482 @@ +/* Copyright (C) +* 2019 - 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 "SoapySDR/Constants.h" +#include "SoapySDR/Device.h" +#include "SoapySDR/Formats.h" +#include "SoapySDR/Version.h" + +//#define TIMING +#ifdef TIMING +#include +#endif + +#include "band.h" +#include "channel.h" +#include "discovered.h" +#include "mode.h" +#include "filter.h" +#include "receiver.h" +#include "transmitter.h" +//#include "wideband.h" +//#include "adc.h" +//#include "dac.h" +#include "radio.h" +#include "main.h" +//#include "protocol1.h" +#include "soapy_protocol.h" +#include "audio.h" +#include "signal.h" +#include "vfo.h" +#ifdef FREEDV +#include "freedv.h" +#endif +#ifdef PSK +#include "psk.h" +#endif +#include "ext.h" +#include "error_handler.h" + +static double bandwidth=2500000.0; + +static SoapySDRDevice *soapy_device; +static SoapySDRStream *rx_stream; +static SoapySDRStream *tx_stream; +static int soapy_rx_sample_rate; +static int soapy_tx_sample_rate; +static int max_samples; + +static int samples=0; + +static GThread *receive_thread_id; +static gpointer receive_thread(gpointer data); + +static int actual_rate; + +#ifdef TIMING +static int rate_samples; +#endif + +static gboolean running; + +static int mic_sample_divisor=1; + + +static int max_tx_samples; +static float *output_buffer; +static int output_buffer_index; + +SoapySDRDevice *get_soapy_device() { + return soapy_device; +} + +void soapy_protocol_set_mic_sample_rate(int rate) { + mic_sample_divisor=rate/48000; +} + +void soapy_protocol_change_sample_rate(RECEIVER *rx,int rate) { +} + +void soapy_protocol_create_receiver(RECEIVER *rx) { + int rc; + + soapy_rx_sample_rate=rx->sample_rate; + +fprintf(stderr,"soapy_protocol_create_receiver: setting samplerate=%f adc=%d\n",(double)soapy_rx_sample_rate,rx->adc); + rc=SoapySDRDevice_setSampleRate(soapy_device,SOAPY_SDR_RX,rx->adc,(double)soapy_rx_sample_rate); + if(rc!=0) { + fprintf(stderr,"soapy_protocol_create_receiver: SoapySDRDevice_setSampleRate(%f) failed: %s\n",(double)soapy_rx_sample_rate,SoapySDR_errToStr(rc)); + } + + size_t channel=rx->adc; +#if defined(SOAPY_SDR_API_VERSION) && (SOAPY_SDR_API_VERSION < 0x00080000) +fprintf(stderr,"soapy_protocol_create_receiver: SoapySDRDevice_setupStream(version<0x00080000): channel=%ld\n",channel); + rc=SoapySDRDevice_setupStream(soapy_device,&rx_stream,SOAPY_SDR_RX,SOAPY_SDR_CF32,&channel,1,NULL); + if(rc!=0) { + fprintf(stderr,"soapy_protocol_create_receiver: SoapySDRDevice_setupStream (RX) failed: %s\n",SoapySDR_errToStr(rc)); + _exit(-1); + } +#else +fprintf(stderr,"soapy_protocol_create_receiver: SoapySDRDevice_setupStream(version>=0x00080000): channel=%ld\n",channel); + rx_stream=SoapySDRDevice_setupStream(soapy_device,SOAPY_SDR_RX,SOAPY_SDR_CF32,&channel,1,NULL); + if(rx_stream==NULL) { + fprintf(stderr,"soapy_protocol_create_receiver: SoapySDRDevice_setupStream (RX) failed (rx_stream is NULL)\n"); + _exit(-1); + } +#endif + + + max_samples=SoapySDRDevice_getStreamMTU(soapy_device,rx_stream); + if(max_samples>(2*rx->fft_size)) { + max_samples=2*rx->fft_size; + } + rx->buffer=g_new(double,max_samples*2); + +fprintf(stderr,"soapy_protocol_create_receiver: max_samples=%d buffer=%p\n",max_samples,rx->buffer); + +} + +void soapy_protocol_start_receiver(RECEIVER *rx) { + int rc; + +fprintf(stderr,"soapy_protocol_start_receiver: activate_stream\n"); + rc=SoapySDRDevice_activateStream(soapy_device, rx_stream, 0, 0LL, 0); + if(rc!=0) { + fprintf(stderr,"soapy_protocol_start_receiver: SoapySDRDevice_activateStream failed: %s\n",SoapySDR_errToStr(rc)); + _exit(-1); + } + +fprintf(stderr,"soapy_protocol_start_receiver: create receive_thread\n"); + receive_thread_id = g_thread_new( "rx_thread", receive_thread, rx); + if( ! receive_thread_id ) + { + fprintf(stderr,"g_thread_new failed for receive_thread\n"); + exit( -1 ); + } + fprintf(stderr, "receive_thread: id=%p\n",receive_thread_id); +} + +void soapy_protocol_create_transmitter(TRANSMITTER *tx) { + int rc; + + soapy_tx_sample_rate=tx->iq_output_rate; + +fprintf(stderr,"soapy_protocol_create_transmitter: setting samplerate=%f\n",(double)soapy_tx_sample_rate); + rc=SoapySDRDevice_setSampleRate(soapy_device,SOAPY_SDR_TX,8,(double)soapy_tx_sample_rate); + if(rc!=0) { + fprintf(stderr,"soapy_protocol_configure_transmitter: SoapySDRDevice_setSampleRate(%f) failed: %s\n",(double)soapy_tx_sample_rate,SoapySDR_errToStr(rc)); + } + + size_t channel=0; +fprintf(stderr,"soapy_protocol_create_transmitter: SoapySDRDevice_setupStream: channel=%ld\n",channel); +#if defined(SOAPY_SDR_API_VERSION) && (SOAPY_SDR_API_VERSION < 0x00080000) + rc=SoapySDRDevice_setupStream(soapy_device,&tx_stream,SOAPY_SDR_TX,SOAPY_SDR_CF32,&channel,1,NULL); + if(rc!=0) { + fprintf(stderr,"soapy_protocol_create_transmitter: SoapySDRDevice_setupStream (RX) failed: %s\n",SoapySDR_errToStr(rc)); + _exit(-1); + } +#else + tx_stream=SoapySDRDevice_setupStream(soapy_device,SOAPY_SDR_TX,SOAPY_SDR_CF32,&channel,1,NULL); + if(tx_stream==NULL) { + fprintf(stderr,"soapy_protocol_create_transmitter: SoapySDRDevice_setupStream (TX) failed: %s\n",SoapySDR_errToStr(rc)); + _exit(-1); + } +#endif + + max_tx_samples=SoapySDRDevice_getStreamMTU(soapy_device,tx_stream); + if(max_tx_samples>(2*tx->fft_size)) { + max_tx_samples=2*tx->fft_size; + } +fprintf(stderr,"soapy_protocol_create_transmitter: max_tx_samples=%d\n",max_tx_samples); + output_buffer=(float *)malloc(max_tx_samples*sizeof(float)*2); + +} + +void soapy_protocol_start_transmitter(TRANSMITTER *tx) { + int rc; + +fprintf(stderr,"soapy_protocol_start_transmitter: activateStream\n"); + rc=SoapySDRDevice_activateStream(soapy_device, tx_stream, 0, 0LL, 0); + if(rc!=0) { + fprintf(stderr,"soapy_protocol_start_transmitter: SoapySDRDevice_activateStream failed: %s\n",SoapySDR_errToStr(rc)); + _exit(-1); + } +} + +void soapy_protocol_stop_transmitter(TRANSMITTER *tx) { + int rc; + +fprintf(stderr,"soapy_protocol_stop_transmitter: deactivateStream\n"); + rc=SoapySDRDevice_deactivateStream(soapy_device, tx_stream, 0, 0LL); + if(rc!=0) { + fprintf(stderr,"soapy_protocol_stop_transmitter: SoapySDRDevice_deactivateStream failed: %s\n",SoapySDR_errToStr(rc)); + _exit(-1); + } +} + +void soapy_protocol_init(int rx,gboolean hf) { + SoapySDRKwargs args={}; + int rc; + int i; + +fprintf(stderr,"soapy_protocol_init: rx=%d hf=%d\n",rx,hf); + + // initialize the radio +fprintf(stderr,"soapy_protocol_init: SoapySDRDevice_make\n"); + SoapySDRKwargs_set(&args, "driver", radio->name); + if(strcmp(radio->name,"rtlsdr")==0) { + char id[16]; + sprintf(id,"%d",radio->info.soapy.rtlsdr_count); + SoapySDRKwargs_set(&args, "rtl", id); + + if(hf) { + SoapySDRKwargs_set(&args, "direct_samp", "2"); + } else { + SoapySDRKwargs_set(&args, "direct_samp", "0"); + } + } + soapy_device=SoapySDRDevice_make(&args); + if(soapy_device==NULL) { + fprintf(stderr,"soapy_protocol: SoapySDRDevice_make failed: %s\n",SoapySDRDevice_lastError()); + _exit(-1); + } + SoapySDRKwargs_clear(&args); + +} + +static void *receive_thread(void *arg) { + double isample; + double qsample; + int elements; + int flags=0; + long long timeNs=0; + long timeoutUs=100000L; + int i; +#ifdef TIMING + struct timeval tv; + long start_time, end_time; + rate_samples=0; + gettimeofday(&tv, NULL); start_time=tv.tv_usec + 1000000 * tv.tv_sec; +#endif + RECEIVER *rx=(RECEIVER *)arg; + float *buffer=g_new(float,max_samples*2); + void *buffs[]={buffer}; + running=TRUE; +fprintf(stderr,"soapy_protocol: receive_thread\n"); + while(running) { + elements=SoapySDRDevice_readStream(soapy_device,rx_stream,buffs,max_samples,&flags,&timeNs,timeoutUs); + if(elements<0) { + fprintf(stderr,"soapy_protocol_receive_thread: SoapySDRDevice_readStream failed: %s max_samples=%d\n",SoapySDR_errToStr(elements),max_samples); + } + for(i=0;ibuffer[i*2]=(double)buffer[i*2]; + rx->buffer[(i*2)+1]=(double)buffer[(i*2)+1]; + } +/* + if(rx->resampler!=NULL) { + int out_elements=xresample(rx->resampler); +g_print("resampler: elements in=%d out=%d\n",elements,out_elements); + for(i=0;iresampled_buffer[i*2]; + isample=rx->resampled_buffer[(i*2)+1]; + } else { + isample=rx->resampled_buffer[i*2]; + qsample=rx->resampled_buffer[(i*2)+1]; + } + add_iq_samples(rx,isample,qsample); + } +*/ + if(rx->sample_rate!=radio_sample_rate) { + for(int i=0;iresample_step) { +/* + isample=0.0; + qsample=0.0; + for(int j=0;jresample_step;j++) { + isample+=rx->buffer[(i+j)*2]; + qsample+=rx->buffer[((i+j)*2)+1]; + } + if(iqswap) { + add_iq_samples(rx,qsample/(double)rx->resample_step,isample/(double)rx->resample_step); + } else { + add_iq_samples(rx,isample/(double)rx->resample_step,qsample/(double)rx->resample_step); + } +*/ + isample=rx->buffer[i*2]; + qsample=rx->buffer[(i*2)+1]; + if(iqswap) { + add_iq_samples(rx,qsample,isample); + } else { + add_iq_samples(rx,isample,qsample); + } + } + } else { + for(i=0;ibuffer[i*2]; + qsample=rx->buffer[(i*2)+1]; + if(iqswap) { + add_iq_samples(rx,qsample,isample); + } else { + add_iq_samples(rx,isample,qsample); + } +#ifdef TIMING + rate_samples++; + if(rate_samples>=rx->sample_rate) { + gettimeofday(&tv, NULL); end_time=tv.tv_usec + 1000000 * tv.tv_sec; + fprintf(stderr,"%d samples in %ld usec\n",rx->sample_rate,end_time-start_time); + rate_samples=0; + start_time=end_time; + } +#endif + } + } + } + +fprintf(stderr,"soapy_protocol: receive_thread: SoapySDRDevice_deactivateStream\n"); + SoapySDRDevice_deactivateStream(soapy_device,rx_stream,0,0LL); +fprintf(stderr,"soapy_protocol: receive_thread: SoapySDRDevice_closeStream\n"); + SoapySDRDevice_closeStream(soapy_device,rx_stream); +fprintf(stderr,"soapy_protocol: receive_thread: SoapySDRDevice_unmake\n"); + SoapySDRDevice_unmake(soapy_device); + //_exit(0); +} + +void soapy_protocol_process_local_mic(unsigned char *buffer) { + int b; + int i; + short sample; + +// always 48000 samples per second + b=0; + for(i=0;i<720;i++) { + sample=(short)(buffer[i]*32767.0); +#ifdef FREEDV + if(active_receiver->freedv) { + add_freedv_mic_sample(transmitter,sample); + } else { +#endif + add_mic_sample(transmitter,sample); +#ifdef FREEDV + } +#endif + } +} + +void soapy_protocol_iq_samples(float isample,float qsample) { + const void *tx_buffs[]={output_buffer}; + int flags=0; + long long timeNs=0; + long timeoutUs=100000L; + if(isTransmitting(radio)) { + output_buffer[output_buffer_index++]=isample; + output_buffer[output_buffer_index++]=qsample; + if(output_buffer_index>=max_tx_samples) { +// write the buffer + int elements=SoapySDRDevice_writeStream(soapy_device,tx_stream,tx_buffs,max_tx_samples,&flags,timeNs,timeoutUs); + if(elements!=max_tx_samples) { + g_print("soapy_protocol_iq_samples: writeStream returned %d for %d elements\n",elements,max_tx_samples); + } + output_buffer_index=0; + } + } +} + + + +void soapy_protocol_stop() { +fprintf(stderr,"soapy_protocol_stop\n"); + running=FALSE; +} + +void soapy_protocol_set_rx_frequency(RECEIVER *rx,int v) { + int rc; + + if(soapy_device!=NULL) { + double f=(double)(vfo[v].frequency-vfo[v].lo); +//g_print("soapy_protocol_set_rx_frequency: %f (%f %f)\n",f,(double)vfo[v].frequency,(double)vfo[v].lo); + rc=SoapySDRDevice_setFrequency(soapy_device,SOAPY_SDR_RX,rx->adc,f,NULL); + if(rc!=0) { + fprintf(stderr,"soapy_protocol: SoapySDRDevice_setFrequency(RX) failed: %s\n",SoapySDR_errToStr(rc)); + } + } +} + +void soapy_protocol_set_tx_frequency(TRANSMITTER *tx) { + int v=active_receiver->id; + int rc; + double f; + + if(soapy_device!=NULL) { + //f=(double)(vfo[v].frequency+vfo[v].ctun_frequency-vfo[v].lo_tx); + if(vfo[v].ctun) { + f=(double)(vfo[v].ctun_frequency-vfo[v].lo_tx); + } else { + f=(double)(vfo[v].frequency-vfo[v].lo_tx); + } +//g_print("soapy_protocol_set_tx_frequency: %f\n",f); + rc=SoapySDRDevice_setFrequency(soapy_device,SOAPY_SDR_TX,active_receiver->adc,f,NULL); + if(rc!=0) { + fprintf(stderr,"soapy_protocol: SoapySDRDevice_setFrequency(TX) failed: %s\n",SoapySDR_errToStr(rc)); + } + } +} + +void soapy_protocol_set_rx_antenna(RECEIVER *rx,int ant) { + int rc; + if(soapy_device!=NULL) { +// fprintf(stderr,"soapy_protocol: set_rx_antenna: %s\n",radio->info.soapy.rx_antenna[ant]); + rc=SoapySDRDevice_setAntenna(soapy_device,SOAPY_SDR_RX,rx->adc,radio->info.soapy.rx_antenna[ant]); + if(rc!=0) { + fprintf(stderr,"soapy_protocol: SoapySDRDevice_setAntenna RX failed: %s\n",SoapySDR_errToStr(rc)); + } + } +} + +void soapy_protocol_set_tx_antenna(TRANSMITTER *tx,int ant) { + int rc; + if(soapy_device!=NULL) { +// fprintf(stderr,"soapy_protocol: set_tx_antenna: %s\n",radio->info.soapy.tx_antenna[ant]); + rc=SoapySDRDevice_setAntenna(soapy_device,SOAPY_SDR_TX,active_receiver->adc,radio->info.soapy.tx_antenna[ant]); + if(rc!=0) { + fprintf(stderr,"soapy_protocol: SoapySDRDevice_setAntenna TX failed: %s\n",SoapySDR_errToStr(rc)); + } + } +} + +void soapy_protocol_set_gain(RECEIVER *rx,char *name,int gain) { + int rc; +//fprintf(stderr,"soapy_protocol_set_gain: adc=%d %s=%d\n",rx->adc,name,gain); + rc=SoapySDRDevice_setGainElement(soapy_device,SOAPY_SDR_RX,rx->adc,name,(double)gain); + if(rc!=0) { + fprintf(stderr,"soapy_protocol: SoapySDRDevice_setGain %s failed: %s\n",name,SoapySDR_errToStr(rc)); + } +} + +void soapy_protocol_set_tx_gain(TRANSMITTER *tx,char *name,int gain) { + int rc; + rc=SoapySDRDevice_setGainElement(soapy_device,SOAPY_SDR_TX,tx->dac,name,(double)gain); + if(rc!=0) { + fprintf(stderr,"soapy_protocol: SoapySDRDevice_setGain %s failed: %s\n",name,SoapySDR_errToStr(rc)); + } +} + +int soapy_protocol_get_gain(RECEIVER *rx,char *name) { + double gain; + gain=SoapySDRDevice_getGainElement(soapy_device,SOAPY_SDR_RX,rx->adc,name); + return (int)gain; +} + +gboolean soapy_protocol_get_automatic_gain(RECEIVER *rx) { + gboolean mode=SoapySDRDevice_getGainMode(soapy_device, SOAPY_SDR_RX, rx->adc); + return mode; +} + +void soapy_protocol_set_automatic_gain(RECEIVER *rx,gboolean mode) { + int rc; + rc=SoapySDRDevice_setGainMode(soapy_device, SOAPY_SDR_RX, rx->adc,mode); + if(rc!=0) { + + fprintf(stderr,"soapy_protocol: SoapySDRDevice_getGainMode failed: %s\n", SoapySDR_errToStr(rc)); + } +} diff --git a/soapy_protocol.h b/soapy_protocol.h new file mode 100644 index 0000000..3db9d17 --- /dev/null +++ b/soapy_protocol.h @@ -0,0 +1,49 @@ +/* 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 _SOAPY_PROTOCOL_H +#define _SOAPY_PROTOCOL_H + +#define BUFFER_SIZE 1024 + +SoapySDRDevice *get_soapy_device(); + +void soapy_protocol_create_receiver(RECEIVER *rx); +void soapy_protocol_start_receiver(RECEIVER *rx); + +void soapy_protocol_init(int rx,gboolean hf); +void soapy_protocol_stop(); +void soapy_protocol_set_rx_frequency(RECEIVER *rx,int v); +void soapy_protocol_set_rx_antenna(RECEIVER *rx,int ant); +void soapy_protocol_set_lna_gain(RECEIVER *rx,int gain); +void soapy_protocol_set_gain(RECEIVER *rx,char *name,int gain); +int soapy_protocol_get_gain(RECEIVER *rx,char *name); +void soapy_protocol_change_sample_rate(RECEIVER *rx,int rate); +gboolean soapy_protocol_get_automatic_gain(RECEIVER *rx); +void soapy_protocol_set_automatic_gain(RECEIVER *rx,gboolean mode); +void soapy_protocol_create_transmitter(TRANSMITTER *tx); +void soapy_protocol_start_transmitter(TRANSMITTER *tx); +void soapy_protocol_stop_transmitter(TRANSMITTER *tx); +void soapy_protocol_set_tx_frequency(TRANSMITTER *tx); +void soapy_protocol_set_tx_antenna(TRANSMITTER *tx,int ant); +void soapy_protocol_set_tx_gain(TRANSMITTER *tx,char *name,int gain); +void soapy_protocol_process_local_mic(unsigned char *buffer); +void soapy_protocol_iq_samples(float isample,float qsample); +void soapy_protocol_set_mic_sample_rate(int rate); +#endif diff --git a/switch_menu.c b/switch_menu.c new file mode 100644 index 0000000..fd5a40c --- /dev/null +++ b/switch_menu.c @@ -0,0 +1,395 @@ +/* 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. +* +*/ + +#ifdef CONTROLLER2 +#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" +#ifdef CONTROLLER2 +#include "i2c.h" +#endif + +typedef struct _choice { + int sw; + int action; + GtkWidget *button; +} CHOICE; + +static GtkWidget *parent_window=NULL; + +static GtkWidget *dialog=NULL; + + +static void cleanup() { + if(dialog!=NULL) { + gtk_widget_destroy(dialog); + dialog=NULL; + active_menu=NO_MENU; + sub_menu=NULL; + } +} + +static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { + cleanup(); + return TRUE; +} + +static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) { + cleanup(); + return FALSE; +} + + +static void sw_select_cb(GtkWidget *widget, gpointer data) { + char text[128]; + CHOICE *choice=(CHOICE *)data; + sw_action[choice->sw]=choice->action; + GtkWidget *label=gtk_bin_get_child(GTK_BIN(choice->button)); + sprintf(text,"%s",sw_string[choice->action]); + gtk_label_set_markup (GTK_LABEL(label), text); +} + +static gboolean sw_cb(GtkWidget *widget, GdkEvent *event, gpointer data) { + int sw=GPOINTER_TO_INT(data); + int i; + + GtkWidget *menu=gtk_menu_new(); + for(i=0;isw=sw; + choice->action=i; + choice->button=widget; + g_signal_connect(menu_item,"activate",G_CALLBACK(sw_select_cb),choice); + gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); +fprintf(stderr,"%d=%s\n",i,sw_string[i]); + } + gtk_widget_show_all(menu); +#if GTK_CHECK_VERSION(3,22,0) + gtk_menu_popup_at_pointer(GTK_MENU(menu),(GdkEvent *)event); +// the following line of code is to work around the problem of the popup menu not having scroll bars. + gtk_menu_reposition(GTK_MENU(menu)); +#else + gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,0,gtk_get_current_event_time()); +#endif + return TRUE; +} + +void switch_menu(GtkWidget *parent) { + int row=0; + int col=0; + int i; + char label[32]; + + dialog=gtk_dialog_new(); + gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window)); + //gtk_window_set_decorated(GTK_WINDOW(dialog),FALSE); + char title[32]; + sprintf(title,"piHPSDR - Encoder Actions:"); + gtk_window_set_title(GTK_WINDOW(dialog),title); + g_signal_connect (dialog, "delete_event", G_CALLBACK (delete_event), NULL); + + GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + + GtkWidget *grid=gtk_grid_new(); + + gtk_grid_set_column_homogeneous(GTK_GRID(grid),FALSE); + gtk_grid_set_row_homogeneous(GTK_GRID(grid),FALSE); + gtk_grid_set_column_spacing (GTK_GRID(grid),2); + gtk_grid_set_row_spacing (GTK_GRID(grid),2); + + GtkWidget *close_b=gtk_button_new_with_label("Close"); + GtkWidget *close_label=gtk_bin_get_child(GTK_BIN(close_b)); + sprintf(label,"Close"); + gtk_label_set_markup (GTK_LABEL(close_label), label); + g_signal_connect (close_b, "pressed", G_CALLBACK(close_cb), NULL); + gtk_grid_attach(GTK_GRID(grid),close_b,col,row,1,1); + + row++; + col=0; + +#ifndef CONTROLLER2 + + GtkWidget *sw7_title=gtk_label_new("SW7: "); + gtk_grid_attach(GTK_GRID(grid),sw7_title,col,row,1,1); + col++; + + GtkWidget *sw7_combo_box=gtk_combo_box_text_new(); + for(i=0;i%s",sw_string[sw_action[SW13]]); + gtk_label_set_markup (GTK_LABEL(sw13_label), label); + gtk_grid_attach(GTK_GRID(grid),sw13,col,row,1,1); + g_signal_connect (sw13, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW13)); + row++; + col=7; + + GtkWidget *sw12=gtk_button_new_with_label(sw_string[sw_action[SW12]]); + GtkWidget *sw12_label=gtk_bin_get_child(GTK_BIN(sw12)); + sprintf(label,"%s",sw_string[sw_action[SW12]]); + gtk_label_set_markup (GTK_LABEL(sw12_label), label); + gtk_grid_attach(GTK_GRID(grid),sw12,col,row,1,1); + g_signal_connect (sw12, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW12)); + col++; + + GtkWidget *sw11=gtk_button_new_with_label(sw_string[sw_action[SW11]]); + GtkWidget *sw11_label=gtk_bin_get_child(GTK_BIN(sw11)); + sprintf(label,"%s",sw_string[sw_action[SW11]]); + gtk_label_set_markup (GTK_LABEL(sw11_label), label); + gtk_grid_attach(GTK_GRID(grid),sw11,col,row,1,1); + g_signal_connect (sw11, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW11)); + row++; + col=7; + + GtkWidget *sw10=gtk_button_new_with_label(sw_string[sw_action[SW10]]); + GtkWidget *sw10_label=gtk_bin_get_child(GTK_BIN(sw10)); + sprintf(label,"%s",sw_string[sw_action[SW10]]); + gtk_label_set_markup (GTK_LABEL(sw10_label), label); + gtk_grid_attach(GTK_GRID(grid),sw10,col,row,1,1); + g_signal_connect (sw10, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW10)); + col++; + + GtkWidget *sw9=gtk_button_new_with_label(sw_string[sw_action[SW9]]); + GtkWidget *sw9_label=gtk_bin_get_child(GTK_BIN(sw9)); + sprintf(label,"%s",sw_string[sw_action[SW9]]); + gtk_label_set_markup (GTK_LABEL(sw9_label), label); + gtk_grid_attach(GTK_GRID(grid),sw9,col,row,1,1); + g_signal_connect (sw9, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW9)); + row++; + col=7; + + GtkWidget *sw7=gtk_button_new_with_label(sw_string[sw_action[SW7]]); + GtkWidget *sw7_label=gtk_bin_get_child(GTK_BIN(sw7)); + sprintf(label,"%s",sw_string[sw_action[SW7]]); + gtk_label_set_markup (GTK_LABEL(sw7_label), label); + gtk_grid_attach(GTK_GRID(grid),sw7,col,row,1,1); + g_signal_connect (sw7, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW7)); + col++; + + GtkWidget *sw8=gtk_button_new_with_label(sw_string[sw_action[SW8]]); + GtkWidget *sw8_label=gtk_bin_get_child(GTK_BIN(sw8)); + sprintf(label,"%s",sw_string[sw_action[SW8]]); + gtk_label_set_markup (GTK_LABEL(sw8_label), label); + gtk_grid_attach(GTK_GRID(grid),sw8,col,row,1,1); + g_signal_connect (sw8, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW8)); + row++; + col=7; + + GtkWidget *sw16=gtk_button_new_with_label(sw_string[sw_action[SW16]]); + GtkWidget *sw16_label=gtk_bin_get_child(GTK_BIN(sw16)); + sprintf(label,"%s",sw_string[sw_action[SW16]]); + gtk_label_set_markup (GTK_LABEL(sw16_label), label); + gtk_grid_attach(GTK_GRID(grid),sw16,col,row,1,1); + g_signal_connect (sw16, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW16)); + col++; + + GtkWidget *sw17=gtk_button_new_with_label(sw_string[sw_action[SW17]]); + GtkWidget *sw17_label=gtk_bin_get_child(GTK_BIN(sw17)); + sprintf(label,"%s",sw_string[sw_action[SW17]]); + gtk_label_set_markup (GTK_LABEL(sw17_label), label); + gtk_grid_attach(GTK_GRID(grid),sw17,col,row,1,1); + g_signal_connect (sw17, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW17)); + row++; + col=0; + + GtkWidget *sw2=gtk_button_new_with_label(sw_string[sw_action[SW2]]); + GtkWidget *sw2_label=gtk_bin_get_child(GTK_BIN(sw2)); + sprintf(label,"%s",sw_string[sw_action[SW2]]); + gtk_label_set_markup (GTK_LABEL(sw2_label), label); + gtk_grid_attach(GTK_GRID(grid),sw2,col,row,1,1); + g_signal_connect (sw2, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW2)); + col++; + + GtkWidget *sw3=gtk_button_new_with_label(sw_string[sw_action[SW3]]); + GtkWidget *sw3_label=gtk_bin_get_child(GTK_BIN(sw3)); + sprintf(label,"%s",sw_string[sw_action[SW3]]); + gtk_label_set_markup (GTK_LABEL(sw3_label), label); + gtk_grid_attach(GTK_GRID(grid),sw3,col,row,1,1); + g_signal_connect (sw3, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW3)); + col++; + + GtkWidget *sw4=gtk_button_new_with_label(sw_string[sw_action[SW4]]); + GtkWidget *sw4_label=gtk_bin_get_child(GTK_BIN(sw4)); + sprintf(label,"%s",sw_string[sw_action[SW4]]); + gtk_label_set_markup (GTK_LABEL(sw4_label), label); + gtk_grid_attach(GTK_GRID(grid),sw4,col,row,1,1); + g_signal_connect (sw4, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW4)); + col++; + + GtkWidget *sw5=gtk_button_new_with_label(sw_string[sw_action[SW5]]); + GtkWidget *sw5_label=gtk_bin_get_child(GTK_BIN(sw5)); + sprintf(label,"%s",sw_string[sw_action[SW5]]); + gtk_label_set_markup (GTK_LABEL(sw5_label), label); + gtk_grid_attach(GTK_GRID(grid),sw5,col,row,1,1); + g_signal_connect (sw5, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW5)); + col++; + + GtkWidget *sw6=gtk_button_new_with_label(sw_string[sw_action[SW6]]); + GtkWidget *sw6_label=gtk_bin_get_child(GTK_BIN(sw6)); + sprintf(label,"%s",sw_string[sw_action[SW6]]); + gtk_label_set_markup (GTK_LABEL(sw6_label), label); + gtk_grid_attach(GTK_GRID(grid),sw6,col,row,1,1); + g_signal_connect (sw6, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW6)); + col++; + + GtkWidget *sw14=gtk_button_new_with_label(sw_string[sw_action[SW14]]); + GtkWidget *sw14_label=gtk_bin_get_child(GTK_BIN(sw14)); + sprintf(label,"%s",sw_string[sw_action[SW14]]); + gtk_label_set_markup (GTK_LABEL(sw14_label), label); + gtk_grid_attach(GTK_GRID(grid),sw14,col,row,1,1); + g_signal_connect (sw14, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW14)); + col++; + + GtkWidget *sw15=gtk_button_new_with_label(sw_string[sw_action[SW15]]); + GtkWidget *sw15_label=gtk_bin_get_child(GTK_BIN(sw15)); + sprintf(label,"%s",sw_string[sw_action[SW15]]); + gtk_label_set_markup (GTK_LABEL(sw15_label), label); + gtk_grid_attach(GTK_GRID(grid),sw15,col,row,1,1); + g_signal_connect (sw15, "button_press_event", G_CALLBACK(sw_cb), GINT_TO_POINTER(SW15)); + col++; + + + +#endif + + gtk_container_add(GTK_CONTAINER(content),grid); + + sub_menu=dialog; + + gtk_widget_show_all(dialog); +} +#endif diff --git a/switch_menu.h b/switch_menu.h new file mode 100644 index 0000000..487b77b --- /dev/null +++ b/switch_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 _SWITCH_MENU_H +#define _SWITCH_MENU_H + +extern void switch_menu(GtkWidget *parent); + +extern void switch_select(int pos); +#endif diff --git a/toolbar.c b/toolbar.c index 4337118..395db8e 100644 --- a/toolbar.c +++ b/toolbar.c @@ -48,7 +48,6 @@ #include "button_text.h" #include "ext.h" -#define MAX_FUNCTION 3 int function=0; static int width; @@ -351,6 +350,7 @@ void mox_cb(GtkWidget *widget, gpointer data) { } void mox_update(int state) { +fprintf(stderr,"mox_update: state=%d\n",state); if(getTune()==1) { setTune(0); } diff --git a/toolbar.h b/toolbar.h index 38b2487..19b1adf 100644 --- a/toolbar.h +++ b/toolbar.h @@ -20,6 +20,8 @@ #ifndef _TOOLBAR_H #define _TOOLBAR_H +#define MAX_FUNCTION 3 + extern int function; diff --git a/transmitter.h b/transmitter.h index 0defd5f..3886824 100644 --- a/transmitter.h +++ b/transmitter.h @@ -26,6 +26,7 @@ typedef struct _transmitter { int id; + int dac; int fps; int displaying; int mic_sample_rate; diff --git a/tx_panadapter.c b/tx_panadapter.c index e9690f7..209bbc1 100644 --- a/tx_panadapter.c +++ b/tx_panadapter.c @@ -349,23 +349,25 @@ void tx_panadapter_update(TRANSMITTER *tx) { #endif #ifdef GPIO +#ifndef CONTROLLER2 cairo_set_source_rgb(cr,1.0,1.0,0.0); cairo_set_font_size(cr,16); - if(ENABLE_E1_ENCODER) { + if(ENABLE_E2_ENCODER) { cairo_move_to(cr, display_width-150,30); - cairo_show_text(cr, encoder_string[e1_encoder_action]); + cairo_show_text(cr, encoder_string[e2_encoder_action]); } - if(ENABLE_E2_ENCODER) { + if(ENABLE_E3_ENCODER) { cairo_move_to(cr, display_width-150,50); - cairo_show_text(cr, encoder_string[e2_encoder_action]); + cairo_show_text(cr, encoder_string[e3_encoder_action]); } - if(ENABLE_E3_ENCODER) { + if(ENABLE_E4_ENCODER) { cairo_move_to(cr, display_width-150,70); - cairo_show_text(cr, encoder_string[e3_encoder_action]); + cairo_show_text(cr, encoder_string[e4_encoder_action]); } #endif +#endif #ifdef PURESIGNAL if(tx->puresignal) { diff --git a/version.c b/version.c index ea57553..2b9e706 100644 --- a/version.c +++ b/version.c @@ -20,4 +20,8 @@ char build_date[]=GIT_DATE; char build_version[]=GIT_VERSION; -char version[]=GIT_VERSION; +#ifdef CONTROLLER2 +char version[]="2.0.0 (Controller2)"; +#else +char version[]="2.0.0"; +#endif diff --git a/vfo.c b/vfo.c index 01075cc..0664f8e 100644 --- a/vfo.c +++ b/vfo.c @@ -173,6 +173,9 @@ void vfo_save_state() { sprintf(name,"vfo.%d.lo",i); sprintf(value,"%lld",vfo[i].lo); setProperty(name,value); + sprintf(name,"vfo.%d.lo_tx",i); + sprintf(value,"%lld",vfo[i].lo_tx); + setProperty(name,value); sprintf(name,"vfo.%d.ctun_frequency",i); sprintf(value,"%lld",vfo[i].ctun_frequency); setProperty(name,value); @@ -236,7 +239,9 @@ void vfo_restore_state() { sprintf(name,"vfo.%d.filter",i); value=getProperty(name); if(value) vfo[i].filter=atoi(value); - + sprintf(name,"vfo.%d.lo_tx",i); + value=getProperty(name); + if(value) vfo[i].lo_tx=atoll(value); } } @@ -279,6 +284,8 @@ void vfo_band_changed(int b) { vfo[id].mode=entry->mode; vfo[id].filter=entry->filter; vfo[id].lo=band->frequencyLO+band->errorLO; + vfo[id].lo_tx=band->txFrequencyLO+band->txErrorLO; + switch(id) { case 0: @@ -537,11 +544,13 @@ void vfo_move(long long hz) { int id=active_receiver->id; if(!locked) { switch(protocol) { -#ifdef LIMESDR - case LIMESDR_PROTOCOL: +/* +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: vfo[id].ctun_frequency=((vfo[id].ctun_frequency-hz)/step)*step; break; #endif +*/ default: if(vfo[id].ctun) { vfo[id].ctun_frequency=((vfo[id].ctun_frequency-hz)/step)*step; @@ -559,11 +568,13 @@ void vfo_move_to(long long hz) { int id=active_receiver->id; if(!locked) { switch(protocol) { -#ifdef LIMESDR - case LIMESDR_PROTOCOL: +/* +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: vfo[id].ctun_frequency=(vfo[id].frequency+hz)/step*step; break; #endif +*/ default: if(vfo[id].ctun) { vfo[id].ctun_frequency=(vfo[id].frequency+hz)/step*step; @@ -588,8 +599,8 @@ void vfo_move_to(long long hz) { BANDSTACK_ENTRY* entry=bandstack_entry_get_current(); -#ifdef LIMESDR - if(protocol==LIMESDR_PROTOCOL) { +#ifdef SOAPYSDR + if(protocol==SOAPYSDR_PROTOCOL) { setFrequency((entry->frequency+active_receiver->dds_offset-hz)/step*step); } else { #endif @@ -604,7 +615,7 @@ void vfo_move_to(long long hz) { } setFrequency(f); } -#ifdef LIMESDR +#ifdef SOAPYSDR } #endif #endif @@ -789,7 +800,7 @@ void vfo_update() { cairo_show_text(cr, "NR2"); } else { cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); - cairo_show_text(cr, "NR2"); + cairo_show_text(cr, "NR"); } cairo_move_to(cr, 210, 50); @@ -846,6 +857,14 @@ void vfo_update() { cairo_show_text(cr, "CMPR OFF"); } + cairo_move_to(cr, 500, 50); + if(diversity_enabled) { + 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, "DIV"); + int s=0; while(steps[s]!=step && steps[s]!=0) { s++; diff --git a/vfo.h b/vfo.h index 081da64..c221885 100644 --- a/vfo.h +++ b/vfo.h @@ -42,6 +42,7 @@ struct _vfo { long long lo; long long offset; + long long lo_tx; } vfo[MAX_VFOS]; diff --git a/xvtr_menu.c b/xvtr_menu.c index 962d583..d825818 100644 --- a/xvtr_menu.c +++ b/xvtr_menu.c @@ -39,6 +39,8 @@ static GtkWidget *min_frequency[BANDS+XVTRS]; static GtkWidget *max_frequency[BANDS+XVTRS]; static GtkWidget *lo_frequency[BANDS+XVTRS]; static GtkWidget *lo_error[BANDS+XVTRS]; +static GtkWidget *tx_lo_frequency[BANDS+XVTRS]; +static GtkWidget *tx_lo_error[BANDS+XVTRS]; static GtkWidget *disable_pa[BANDS+XVTRS]; static void save_xvtr () { @@ -50,6 +52,8 @@ static void save_xvtr () { const char *maxf; const char *lof; const char *loerr; + const char *txlof; + const char *txloerr; for(i=BANDS;ibandstack; @@ -57,17 +61,21 @@ static void save_xvtr () { strcpy(xvtr->title,t); if(strlen(t)!=0) { minf=gtk_entry_get_text(GTK_ENTRY(min_frequency[i])); - xvtr->frequencyMin=atoll(minf)*1000000; + xvtr->frequencyMin=(long long)(atof(minf)*1000000.0); maxf=gtk_entry_get_text(GTK_ENTRY(max_frequency[i])); - xvtr->frequencyMax=atoll(maxf)*1000000; + xvtr->frequencyMax=(long long)(atof(maxf)*1000000.0); lof=gtk_entry_get_text(GTK_ENTRY(lo_frequency[i])); - xvtr->frequencyLO=atoll(lof)*1000000; + xvtr->frequencyLO=(long long)(atof(lof)*1000000.0); loerr=gtk_entry_get_text(GTK_ENTRY(lo_error[i])); xvtr->errorLO=atoll(loerr); + txlof=gtk_entry_get_text(GTK_ENTRY(tx_lo_frequency[i])); + xvtr->txFrequencyLO=(long long)(atof(txlof)*1000000.0); + txloerr=gtk_entry_get_text(GTK_ENTRY(tx_lo_error[i])); + xvtr->txErrorLO=atoll(txloerr); xvtr->disablePA=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(disable_pa[i])); for(b=0;bentries;b++) { BANDSTACK_ENTRY *entry=&bandstack->entry[b]; - entry->frequency=xvtr->frequencyMin; + entry->frequency=xvtr->frequencyMin+((xvtr->frequencyMax-xvtr->frequencyMin)/2); entry->mode=modeUSB; entry->filter=filterF6; } @@ -84,6 +92,96 @@ fprintf(stderr,"min=%s:%lld max=%s:%lld lo=%s:%lld\n",minf,xvtr->frequencyMin,ma } } +void update_receiver(int band,gboolean error) { + int i; + RECEIVER *rx=active_receiver; + gboolean saved_ctun; +g_print("update_receiver: band=%d error=%d\n",band,error); + if(vfo[0].band==band) { + BAND *xvtr=band_get_band(band); +g_print("update_receiver: found band: %s\n",xvtr->title); + vfo[0].lo=xvtr->frequencyLO+xvtr->errorLO; + vfo[0].lo_tx=xvtr->txFrequencyLO+xvtr->txErrorLO; + saved_ctun=vfo[0].ctun; + if(saved_ctun) { + vfo[0].ctun=FALSE; + } + frequency_changed(rx); + if(saved_ctun) { + vfo[0].ctun=TRUE; + } + +/* + if(radio->transmitter!=NULL) { + if(radio->transmitter->rx==rx) { + update_tx_panadapter(radio); + } + } +*/ + } +} + +void min_frequency_cb(GtkEditable *editable,gpointer user_data) { + int band=GPOINTER_TO_INT(user_data); + BAND *xvtr=band_get_band(band); + const char* minf=gtk_entry_get_text(GTK_ENTRY(min_frequency[band])); + xvtr->frequencyMin=(long long)(atof(minf)*1000000.0); + update_receiver(band,FALSE); +} + +void max_frequency_cb(GtkEditable *editable,gpointer user_data) { + int band=GPOINTER_TO_INT(user_data); + BAND *xvtr=band_get_band(band); + const char* maxf=gtk_entry_get_text(GTK_ENTRY(max_frequency[band])); + xvtr->frequencyMin=(long long)(atof(maxf)*1000000.0); + update_receiver(band,FALSE); +} + +void lo_frequency_cb(GtkEditable *editable,gpointer user_data) { + int band=GPOINTER_TO_INT(user_data); + BAND *xvtr=band_get_band(band); + const char* lof=gtk_entry_get_text(GTK_ENTRY(lo_frequency[band])); + xvtr->frequencyLO=(long long)(atof(lof)*1000000.0); + update_receiver(band,FALSE); +} + +void lo_error_cb(GtkEditable *editable,gpointer user_data) { +g_print("lo_error_cb\n"); + int band=GPOINTER_TO_INT(user_data); + BAND *xvtr=band_get_band(band); + const char* errorf=gtk_entry_get_text(GTK_ENTRY(lo_error[band])); + xvtr->errorLO=atoll(errorf); + update_receiver(band,TRUE); +} + +void lo_error_update(RECEIVER *rx,long long offset) { +g_print("lo_error_update: band=%d\n",vfo[0].band); + BAND *xvtr=band_get_band(vfo[0].band); + if(dialog!=NULL) { + char temp[32]; + sprintf(temp,"%lld",xvtr->errorLO); + gtk_entry_set_text(GTK_ENTRY(lo_error[vfo[0].band]),temp); + } + xvtr->errorLO=xvtr->errorLO+offset; + update_receiver(vfo[0].band,TRUE); +} + +void tx_lo_frequency_cb(GtkEditable *editable,gpointer user_data) { + int band=GPOINTER_TO_INT(user_data); + BAND *xvtr=band_get_band(band); + const char* lof=gtk_entry_get_text(GTK_ENTRY(tx_lo_frequency[band])); + xvtr->txFrequencyLO=(long long)(atof(lof)*1000000.0); + update_receiver(band,FALSE); +} + +void tx_lo_error_cb(GtkEditable *editable,gpointer user_data) { + int band=GPOINTER_TO_INT(user_data); + BAND *xvtr=band_get_band(band); + const char* errorf=gtk_entry_get_text(GTK_ENTRY(tx_lo_error[band])); + xvtr->txErrorLO=atoll(errorf); + update_receiver(band,TRUE); +} + static void cleanup() { save_xvtr(); if(dialog!=NULL) { @@ -137,16 +235,20 @@ fprintf(stderr,"xvtr_menu\n"); GtkWidget *label=gtk_label_new("Title"); gtk_grid_attach(GTK_GRID(grid),label,0,1,1,1); - label=gtk_label_new("Min Frequency(MHz)"); + label=gtk_label_new("Min Freq(MHz)"); gtk_grid_attach(GTK_GRID(grid),label,1,1,1,1); - label=gtk_label_new("Max Frequency(MHz)"); + label=gtk_label_new("Max Freq(MHz)"); gtk_grid_attach(GTK_GRID(grid),label,2,1,1,1); - label=gtk_label_new("LO Frequency(MHz)"); + label=gtk_label_new("LO Freq(MHz)"); gtk_grid_attach(GTK_GRID(grid),label,3,1,1,1); - label=gtk_label_new("LO Error(Hz)"); + label=gtk_label_new("LO Err(Hz)"); gtk_grid_attach(GTK_GRID(grid),label,4,1,1,1); - label=gtk_label_new("Disable PA"); + label=gtk_label_new("TX LO Freq(MHz)"); gtk_grid_attach(GTK_GRID(grid),label,5,1,1,1); + label=gtk_label_new("TX LO Err(Hz)"); + gtk_grid_attach(GTK_GRID(grid),label,6,1,1,1); + label=gtk_label_new("Disable PA"); + gtk_grid_attach(GTK_GRID(grid),label,7,1,1,1); for(i=BANDS;ifrequencyMin/1000000LL); + sprintf(f,"%5.3f",(double)xvtr->frequencyMin/1000000.0); gtk_entry_set_text(GTK_ENTRY(min_frequency[i]),f); gtk_grid_attach(GTK_GRID(grid),min_frequency[i],1,i+2,1,1); + g_signal_connect(min_frequency[i],"changed",G_CALLBACK(min_frequency_cb),GINT_TO_POINTER(i)); max_frequency[i]=gtk_entry_new(); gtk_entry_set_width_chars(GTK_ENTRY(max_frequency[i]),7); - sprintf(f,"%lld",xvtr->frequencyMax/1000000LL); + sprintf(f,"%5.3f",(double)xvtr->frequencyMax/1000000.0); gtk_entry_set_text(GTK_ENTRY(max_frequency[i]),f); gtk_grid_attach(GTK_GRID(grid),max_frequency[i],2,i+2,1,1); + g_signal_connect(max_frequency[i],"changed",G_CALLBACK(max_frequency_cb),GINT_TO_POINTER(i)); lo_frequency[i]=gtk_entry_new(); gtk_entry_set_width_chars(GTK_ENTRY(lo_frequency[i]),7); - sprintf(f,"%lld",xvtr->frequencyLO/1000000LL); + sprintf(f,"%5.3f",(double)xvtr->frequencyLO/1000000.0); gtk_entry_set_text(GTK_ENTRY(lo_frequency[i]),f); gtk_grid_attach(GTK_GRID(grid),lo_frequency[i],3,i+2,1,1); + g_signal_connect(lo_frequency[i],"changed",G_CALLBACK(lo_frequency_cb),GINT_TO_POINTER(i)); lo_error[i]=gtk_entry_new(); gtk_entry_set_width_chars(GTK_ENTRY(lo_error[i]),9); sprintf(f,"%lld",xvtr->errorLO); gtk_entry_set_text(GTK_ENTRY(lo_error[i]),f); gtk_grid_attach(GTK_GRID(grid),lo_error[i],4,i+2,1,1); + g_signal_connect(lo_error[i],"changed",G_CALLBACK(lo_error_cb),GINT_TO_POINTER(i)); + + tx_lo_frequency[i]=gtk_entry_new(); + gtk_entry_set_width_chars(GTK_ENTRY(tx_lo_frequency[i]),7); + sprintf(f,"%5.3f",(double)xvtr->txFrequencyLO/1000000.0); + gtk_entry_set_text(GTK_ENTRY(tx_lo_frequency[i]),f); + gtk_grid_attach(GTK_GRID(grid),tx_lo_frequency[i],5,i+2,1,1); + g_signal_connect(tx_lo_frequency[i],"changed",G_CALLBACK(tx_lo_frequency_cb),GINT_TO_POINTER(i)); + + tx_lo_error[i]=gtk_entry_new(); + gtk_entry_set_width_chars(GTK_ENTRY(tx_lo_error[i]),9); + sprintf(f,"%lld",xvtr->txErrorLO); + gtk_entry_set_text(GTK_ENTRY(tx_lo_error[i]),f); + gtk_grid_attach(GTK_GRID(grid),tx_lo_error[i],6,i+2,1,1); + g_signal_connect(tx_lo_error[i],"changed",G_CALLBACK(tx_lo_error_cb),GINT_TO_POINTER(i)); disable_pa[i]=gtk_check_button_new(); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(disable_pa[i]),xvtr->disablePA); - gtk_grid_attach(GTK_GRID(grid),disable_pa[i],5,i+2,1,1); + gtk_grid_attach(GTK_GRID(grid),disable_pa[i],7,i+2,1,1); }