From 973b19a47ccecfbcaccf3f08a23991ee2e147493 Mon Sep 17 00:00:00 2001 From: Franco Venturi Date: Fri, 7 Aug 2020 17:52:50 -0400 Subject: [PATCH 1/2] add support for SDRplay RSP receivers --- discovered.h | 1 + radio.c | 27 +++++++++++++++++++++++---- radio_info.c | 4 +++- receiver.c | 4 +++- receiver_dialog.c | 2 +- soapy_discovery.c | 23 +++++++++++++++++++++++ soapy_protocol.c | 25 ++++++++++++++++--------- vfo.c | 2 +- 8 files changed, 71 insertions(+), 17 deletions(-) diff --git a/discovered.h b/discovered.h index 5f8001e..883d3a7 100644 --- a/discovered.h +++ b/discovered.h @@ -93,6 +93,7 @@ struct _DISCOVERED { #ifdef SOAPYSDR struct soapy { int rtlsdr_count; + int sdrplay_count; int sample_rate; size_t rx_channels; size_t rx_gains; diff --git a/radio.c b/radio.c index d39bc2d..d5f4c79 100644 --- a/radio.c +++ b/radio.c @@ -592,7 +592,7 @@ void delete_receiver(RECEIVER *rx) { if(radio->discovered->protocol==PROTOCOL_1) { protocol1_stop(); } - if(radio->transmitter->rx==rx) { + if(radio->transmitter!=NULL && radio->transmitter->rx==rx) { radio->transmitter->rx=NULL; } radio->receiver[i]=NULL; @@ -605,7 +605,7 @@ g_print("delete_receiver: receivers now %d\n",radio->receivers); } } - if(radio->transmitter->rx==NULL) { + if(radio->transmitter!=NULL && radio->transmitter->rx==NULL) { if(radio->receivers>0) { for(i=0;idiscovered->supported_receivers;i++) { if(radio->receiver[i]!=NULL) { @@ -789,8 +789,27 @@ g_print("add_receiver: using receiver %d\n",i); r->receiver[i]=create_receiver(i,r->sample_rate); r->receivers++; g_print("add_receiver: receivers now %d\n",r->receivers); - if(r->discovered->protocol==PROTOCOL_2) { - protocol2_start_receiver(r->receiver[i]); + switch(r->discovered->protocol) { + case PROTOCOL_2: + protocol2_start_receiver(r->receiver[i]); + break; +#ifdef SOAPYSDR + case PROTOCOL_SOAPYSDR: + soapy_protocol_create_receiver(r->receiver[i]); + RECEIVER *rx=r->receiver[i]; + int adc=rx->adc; + soapy_protocol_set_rx_antenna(radio->receiver[i],radio->adc[adc].antenna); + double f=(double)(rx->frequency_a-rx->lo_a+rx->error_a); + soapy_protocol_set_rx_frequency(radio->receiver[i]); + soapy_protocol_set_automatic_gain(radio->receiver[i],radio->adc[adc].agc); + for(int i=0;idiscovered->info.soapy.rx_gains;i++) { + soapy_protocol_set_gain(&radio->adc[adc]); + } + soapy_protocol_start_receiver(rx); + break; +#endif + default: + break; } } else { g_print("add_receiver: no receivers available\n"); diff --git a/radio_info.c b/radio_info.c index 8e1397b..3bd5b21 100644 --- a/radio_info.c +++ b/radio_info.c @@ -132,7 +132,9 @@ void update_radio_info(RECEIVER *rx) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(info->temp_b),radio->transmitter->temperature>radio->temperature_alarm_value); } - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(info->swr_b),radio->transmitter->swr>radio->swr_alarm_value); + if (radio->transmitter!=NULL) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(info->swr_b),radio->transmitter->swr>radio->swr_alarm_value); + } #ifdef MIDI gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(info->midi_b),radio->midi_enabled && (radio->receiver[midi_rx]->channel==rx->channel)); diff --git a/receiver.c b/receiver.c index 2245eb3..2956cd7 100644 --- a/receiver.c +++ b/receiver.c @@ -1535,7 +1535,9 @@ g_print("create_receiver: channel=%d frequency_min=%ld frequency_max=%ld\n", cha break; #ifdef SOAPYSDR case PROTOCOL_SOAPYSDR: - if(radio->discovered->supported_receivers>1) { + if(radio->discovered->supported_receivers>1 && +// fv - need to figure how to deal with the Lime Suite + strcmp(radio->discovered->name,"lms7")==0) { rx->adc=2; } else { rx->adc=1; diff --git a/receiver_dialog.c b/receiver_dialog.c index 3214a2e..ec86196 100644 --- a/receiver_dialog.c +++ b/receiver_dialog.c @@ -1308,7 +1308,7 @@ GtkWidget *create_receiver_dialog(RECEIVER *rx) { row++; rx->tx_control_b=gtk_check_button_new_with_label("Use This Receivers Frequency"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx->tx_control_b), radio->transmitter->rx==rx); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rx->tx_control_b), radio->transmitter!=NULL && radio->transmitter->rx==rx); gtk_grid_attach(GTK_GRID(tx_grid),rx->tx_control_b,0,0,1,1); rx->tx_control_signal_id=g_signal_connect(rx->tx_control_b,"toggled",G_CALLBACK(tx_cb),rx); } diff --git a/soapy_discovery.c b/soapy_discovery.c index 5c3b2d5..aff091b 100644 --- a/soapy_discovery.c +++ b/soapy_discovery.c @@ -27,6 +27,7 @@ #include "soapy_discovery.h" static int rtlsdr_count=0; +static int sdrplay_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; @@ -35,6 +36,7 @@ static void get_info(char *driver) { char *version; char *address=NULL; int rtlsdr_val=0; + int sdrplay_val=0; fprintf(stderr,"soapy_discovery: get_info: %s\n", driver); @@ -45,6 +47,12 @@ static void get_info(char *driver) { SoapySDRKwargs_set(&args, "rtl", count); rtlsdr_val=rtlsdr_count; rtlsdr_count++; + } else if(strcmp(driver,"sdrplay")==0) { + char label[16]; + sprintf(label,"SDRplay Dev%d",sdrplay_count); + SoapySDRKwargs_set(&args, "label", label); + sdrplay_val=sdrplay_count; + sdrplay_count++; } SoapySDRDevice *sdr = SoapySDRDevice_make(&args); SoapySDRKwargs_clear(&args); @@ -54,6 +62,9 @@ static void get_info(char *driver) { char *hardwarekey=SoapySDRDevice_getHardwareKey(sdr); fprintf(stderr,"HardwareKey=%s\n",hardwarekey); + if(strcmp(driver,"sdrplay")==0) { + address=hardwarekey; + } SoapySDRKwargs info=SoapySDRDevice_getHardwareInfo(sdr); version=""; @@ -65,6 +76,11 @@ static void get_info(char *driver) { if(strcmp(info.keys[i],"fw_version")==0) { version=info.vals[i]; } + if(strcmp(info.keys[i],"sdrplay_api_api_version")==0) { + /* take just the first 4 characters here */ + info.vals[i][4]='\0'; + version=info.vals[i]; + } if(strcmp(info.keys[i],"ip,ip-addr")==0) { address=info.vals[i]; } @@ -197,8 +213,13 @@ static void get_info(char *driver) { discovered[devices].info.soapy.sample_rate=sample_rate; if(strcmp(driver,"rtlsdr")==0) { discovered[devices].info.soapy.rtlsdr_count=rtlsdr_val; + discovered[devices].info.soapy.sdrplay_count=0; + } else if(strcmp(driver,"sdrplay")==0) { + discovered[devices].info.soapy.rtlsdr_count=0; + discovered[devices].info.soapy.sdrplay_count=sdrplay_val; } else { discovered[devices].info.soapy.rtlsdr_count=0; + discovered[devices].info.soapy.sdrplay_count=0; } discovered[devices].info.soapy.rx_channels=rx_channels; discovered[devices].info.soapy.rx_gains=rx_gains_length; @@ -241,6 +262,8 @@ fprintf(stderr,"Tx gains: \n"); devices++; } + // fv + SoapySDRDevice_unmake(sdr); free(ranges); diff --git a/soapy_protocol.c b/soapy_protocol.c index a22c437..f8b529d 100644 --- a/soapy_protocol.c +++ b/soapy_protocol.c @@ -55,8 +55,9 @@ static double bandwidth=1000000.0; +#define MAX_CHANNELS 2 static SoapySDRDevice *soapy_device; -static SoapySDRStream *rx_stream; +static SoapySDRStream *rx_stream[MAX_CHANNELS]; static SoapySDRStream *tx_stream; static int soapy_rx_sample_rate; static int soapy_tx_sample_rate; @@ -113,21 +114,21 @@ g_print("%s: setting samplerate=%f\n",__FUNCTION__,(double)soapy_rx_sample_rate) size_t channel=rx->adc; g_print("%s: SoapySDRDevice_setupStream: channel=%ld\n",__FUNCTION__,channel); #if defined(SOAPY_SDR_API_VERSION) && (SOAPY_SDR_API_VERSION < 0x00080000) - rc=SoapySDRDevice_setupStream(soapy_device,&rx_stream,SOAPY_SDR_RX,SOAPY_SDR_CF32,&channel,1,NULL); + rc=SoapySDRDevice_setupStream(soapy_device,&rx_stream[channel],SOAPY_SDR_RX,SOAPY_SDR_CF32,&channel,1,NULL); if(rc!=0) { g_print("%s: SoapySDRDevice_setupStream (RX) failed: %s\n",__FUNCTION__,SoapySDR_errToStr(rc)); _exit(-1); } #else - rx_stream=SoapySDRDevice_setupStream(soapy_device,SOAPY_SDR_RX,SOAPY_SDR_CF32,&channel,1,NULL); - if(rx_stream==NULL) { + rx_stream[channel]=SoapySDRDevice_setupStream(soapy_device,SOAPY_SDR_RX,SOAPY_SDR_CF32,&channel,1,NULL); + if(rx_stream[channel]==NULL) { g_print("%s: SoapySDRDevice_setupStream (RX) failed: %s\n",__FUNCTION__,SoapySDR_errToStr(rc)); _exit(-1); } #endif - max_samples=SoapySDRDevice_getStreamMTU(soapy_device,rx_stream); + max_samples=SoapySDRDevice_getStreamMTU(soapy_device,rx_stream[channel]); if(max_samples>(2*rx->fft_size)) { max_samples=2*rx->fft_size; } @@ -139,7 +140,8 @@ void soapy_protocol_start_receiver(RECEIVER *rx) { int rc; g_print("%s: activate_stream\n",__FUNCTION__); - rc=SoapySDRDevice_activateStream(soapy_device, rx_stream, 0, 0LL, 0); + size_t channel=rx->adc; + rc=SoapySDRDevice_activateStream(soapy_device, rx_stream[channel], 0, 0LL, 0); if(rc!=0) { g_print("%s: SoapySDRDevice_activateStream failed: %s\n",__FUNCTION__,SoapySDR_errToStr(rc)); _exit(-1); @@ -236,6 +238,10 @@ g_print("soapy_protocol_init: SoapySDRDevice_make\n"); char id[16]; sprintf(id,"%d",radio->discovered->info.soapy.rtlsdr_count); SoapySDRKwargs_set(&args, "rtl", id); + } else if(strcmp(radio->discovered->name,"sdrplay")==0) { + char label[16]; + sprintf(label,"SDRplay Dev%d",radio->discovered->info.soapy.sdrplay_count); + SoapySDRKwargs_set(&args, "label", label); } soapy_device=SoapySDRDevice_make(&args); if(soapy_device==NULL) { @@ -265,8 +271,9 @@ static void *receive_thread(void *arg) { void *buffs[]={buffer}; running=TRUE; g_print("%s: receive_thread\n",__FUNCTION__); + size_t channel=rx->adc; while(running) { - elements=SoapySDRDevice_readStream(soapy_device,rx_stream,buffs,max_samples,&flags,&timeNs,timeoutUs); + elements=SoapySDRDevice_readStream(soapy_device,rx_stream[channel],buffs,max_samples,&flags,&timeNs,timeoutUs); if(elements<0) { g_print("%s: elements=%d max_samples=%d\n",__FUNCTION__,elements,max_samples); } @@ -335,9 +342,9 @@ g_print("resampler: elements in=%d out=%d\n",elements,out_elements); } g_print("%s: receive_thread: SoapySDRDevice_deactivateStream\n",__FUNCTION__); - SoapySDRDevice_deactivateStream(soapy_device,rx_stream,0,0LL); + SoapySDRDevice_deactivateStream(soapy_device,rx_stream[channel],0,0LL); g_print("%s: receive_thread: SoapySDRDevice_closeStream\n",__FUNCTION__); - SoapySDRDevice_closeStream(soapy_device,rx_stream); + SoapySDRDevice_closeStream(soapy_device,rx_stream[channel]); g_print("%s: receive_thread: SoapySDRDevice_unmake\n",__FUNCTION__); SoapySDRDevice_unmake(soapy_device); _exit(0); diff --git a/vfo.c b/vfo.c index 6454571..01f499a 100644 --- a/vfo.c +++ b/vfo.c @@ -178,7 +178,7 @@ void vfo_aswapb(RECEIVER *rx) { frequency_changed(rx); receiver_mode_changed(rx,rx->mode_a); - if(radio->transmitter->rx==rx) { + if(radio->transmitter!=NULL && radio->transmitter->rx==rx) { if(rx->split!=SPLIT_OFF) { transmitter_set_mode(radio->transmitter,rx->mode_b); } else { From 43c4f184116c06f0c4e99dec68f639ce76850447 Mon Sep 17 00:00:00 2001 From: Franco Venturi Date: Wed, 11 Nov 2020 08:05:45 -0500 Subject: [PATCH 2/2] fix: fix radio->transmitter null pointer in vfo.c --- vfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vfo.c b/vfo.c index 01f499a..e3f3110 100644 --- a/vfo.c +++ b/vfo.c @@ -442,7 +442,7 @@ void mode_cb(GtkWidget *menu_item,gpointer data) { if(choice->rx->split!=SPLIT_OFF) { choice->rx->mode_b=choice->selection; } - if(radio->transmitter->rx==choice->rx) { + if(radio->transmitter!=NULL && radio->transmitter->rx==choice->rx) { if(choice->rx->split!=SPLIT_OFF) { transmitter_set_mode(radio->transmitter,choice->rx->mode_b); } else {