From: John Melton G0ORX Date: Thu, 7 Nov 2019 16:20:53 +0000 (+0000) Subject: Changed audio to use audio device name. Added XIT. Added Duplex. Addes SAT and RSAT... X-Git-Url: https://git.rkrishnan.org/pf/content/en/seg/(%5B%5E?a=commitdiff_plain;h=36c04deb44584b607f14e22e3787b68e3064086d;p=pihpsdr.git Changed audio to use audio device name. Added XIT. Added Duplex. Addes SAT and RSAT modes. --- diff --git a/ant_menu.c b/ant_menu.c index d7ac9f7..a23c6bb 100644 --- a/ant_menu.c +++ b/ant_menu.c @@ -88,7 +88,7 @@ static void dac0_antenna_cb(GtkComboBox *widget,gpointer data) { schedule_high_priority(); #ifdef SOAPYSDR } else if(radio->device==SOAPYSDR_USB_DEVICE) { - soapy_protocol_set_tx_antenna(transmitter,dac[0].antenna); + soapy_protocol_set_tx_antenna(transmitter,dac->antenna); #endif } } diff --git a/audio.c b/audio.c index c54facb..a942201 100644 --- a/audio.c +++ b/audio.c @@ -66,7 +66,7 @@ static snd_pcm_t *record_handle=NULL; //static unsigned char *audio_buffer=NULL; //static int audio_offset=0; -static unsigned char *mic_buffer=NULL; +static float *mic_buffer=NULL; static GThread *mic_read_thread_id; @@ -74,13 +74,11 @@ static int running=FALSE; static void *mic_read_thread(void *arg); -char *input_devices[32]; -int n_input_devices=0; -//int n_selected_input_device=-1; -char *output_devices[32]; -int n_output_devices=0; -//int n_selected_output_device=-1; +int n_input_devices; +AUDIO_DEVICE input_devices[MAX_AUDIO_DEVICES]; +int n_output_devices; +AUDIO_DEVICE output_devices[MAX_AUDIO_DEVICES]; int audio_open_output(RECEIVER *rx) { int err; @@ -88,22 +86,21 @@ int audio_open_output(RECEIVER *rx) { int rate=48000; int dir=0; - -fprintf(stderr,"audio_open_output: rx=%d audio_device=%d\n",rx->id,rx->audio_device); - if(rx->audio_device<0 || rx->audio_device>=n_output_devices) { - rx->audio_device=-1; + if(rx->audio_name==NULL) { + rx->local_audio=0; return -1; } +fprintf(stderr,"audio_open_output: rx=%d %s\n",rx->id,rx->audio_name); + int i; - char hw[64]; - char *selected=output_devices[rx->audio_device]; + char hw[128]; -fprintf(stderr,"audio_open_output: selected=%d:%s\n",rx->audio_device,selected); +fprintf(stderr,"audio_open_output: selected=%s\n",rx->audio_name); i=0; - while(selected[i]!=' ') { - hw[i]=selected[i]; + while(rx->audio_name[i]!=' ') { + hw[i]=rx->audio_name[i]; i++; } hw[i]='\0'; @@ -182,16 +179,14 @@ int audio_open_input() { int rate=48000; int dir=0; -fprintf(stderr,"audio_open_input: %d\n",transmitter->input_device); - if(transmitter->input_device<0 || transmitter->input_device>=n_input_devices) { - transmitter->input_device=0; + if(transmitter->microphone_name==NULL) { + transmitter->local_microphone=0; return -1; } +fprintf(stderr,"audio_open_input: %s\n",transmitter->microphone_name); int i; char hw[64]; - char *selected=input_devices[transmitter->input_device]; - fprintf(stderr,"audio_open_input: selected=%d:%s\n",transmitter->input_device,selected); switch(protocol) { case ORIGINAL_PROTOCOL: @@ -211,12 +206,13 @@ fprintf(stderr,"audio_open_input: %d\n",transmitter->input_device); fprintf(stderr,"audio_open_input: mic_buffer_size=%d\n",mic_buffer_size); i=0; - while(selected[i]!=' ') { - hw[i]=selected[i]; + while(transmitter->microphone_name[i]!=' ') { + hw[i]=transmitter->microphone_name[i]; i++; } hw[i]='\0'; + fprintf(stderr,"audio_open_input: hw=%s\n",hw); if ((err = snd_pcm_open (&record_handle, hw, SND_PCM_STREAM_CAPTURE, 0)) < 0) { @@ -247,7 +243,7 @@ fprintf(stderr,"audio_open_input: %d\n",transmitter->input_device); return -1; } - if ((err = snd_pcm_hw_params_set_format (record_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { + if ((err = snd_pcm_hw_params_set_format (record_handle, hw_params, SND_PCM_FORMAT_FLOAT_LE)) < 0) { fprintf (stderr, "audio_open_input: cannot set sample format (%s)\n", snd_strerror (err)); audio_close_input(); @@ -277,7 +273,8 @@ fprintf(stderr,"audio_open_input: %d\n",transmitter->input_device); snd_pcm_hw_params_free (hw_params); - mic_buffer=(unsigned char *)malloc(MIC_BUFFER_SIZE); + mic_buffer=g_new0(float,mic_buffer_size); + running=TRUE; mic_read_thread_id = g_thread_new( "local mic", mic_read_thread, NULL); @@ -456,14 +453,14 @@ fprintf(stderr,"mic_read_thread: mic_buffer_size=%d\n",mic_buffer_size); // process the mic input switch(protocol) { case ORIGINAL_PROTOCOL: - old_protocol_process_local_mic(mic_buffer,1); + old_protocol_process_local_mic(mic_buffer); break; case NEW_PROTOCOL: - new_protocol_process_local_mic(mic_buffer,1); + new_protocol_process_local_mic(mic_buffer); break; #ifdef SOAPYSDR case SOAPYSDR_PROTOCOL: - soapy_protocol_process_local_mic(mic_buffer,1); + soapy_protocol_process_local_mic(mic_buffer); break; #endif default: @@ -486,16 +483,11 @@ void audio_get_cards() { fprintf(stderr,"audio_get_cards\n"); - for(i=0;i= 0 && card >= 0) { int err = 0; snd_ctl_t *handle; @@ -519,24 +511,36 @@ fprintf(stderr,"audio_get_cards\n"); // input devices snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE); if ((err = snd_ctl_pcm_info(handle, pcminfo)) == 0) { - device_id=malloc(64); - snprintf(device_id, 64, "plughw:%d,%d %s", card, dev, snd_ctl_card_info_get_name(info)); - input_devices[n_input_devices++]=device_id; + device_id=malloc(128); + snprintf(device_id, 128, "plughw:%d,%d %s", card, dev, snd_ctl_card_info_get_name(info)); + if(n_input_devices #include +#include "main.h" #include "new_menu.h" #include "exit_menu.h" +#include "discovery.h" #include "radio.h" #include "new_protocol.h" #include "old_protocol.h" @@ -48,6 +50,33 @@ static void cleanup() { } } +static gboolean discovery_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { + cleanup(); +#ifdef GPIO + gpio_close(); +#endif + switch(protocol) { + case ORIGINAL_PROTOCOL: + old_protocol_stop(); + break; + case NEW_PROTOCOL: + new_protocol_stop(); + break; +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: + soapy_protocol_stop(); + break; +#endif + } + radioSaveState(); + radio_stop(); + gtk_container_remove(GTK_CONTAINER(top_window), fixed); + gtk_widget_destroy(fixed); + gtk_container_add(GTK_CONTAINER(top_window), grid); + discovery(); + return TRUE; +} + static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { cleanup(); return TRUE; @@ -76,6 +105,7 @@ static gboolean exit_cb (GtkWidget *widget, GdkEventButton *event, gpointer data #endif } radioSaveState(); + _exit(0); } @@ -152,17 +182,21 @@ void exit_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 *discovery_b=gtk_button_new_with_label("Discovery"); + g_signal_connect (discovery_b, "pressed", G_CALLBACK(discovery_cb), NULL); + gtk_grid_attach(GTK_GRID(grid),discovery_b,0,1,1,1); + GtkWidget *exit_b=gtk_button_new_with_label("Exit"); g_signal_connect (exit_b, "pressed", G_CALLBACK(exit_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),exit_b,0,1,1,1); + gtk_grid_attach(GTK_GRID(grid),exit_b,1,1,1,1); GtkWidget *reboot_b=gtk_button_new_with_label("Reboot"); g_signal_connect (reboot_b, "pressed", G_CALLBACK(reboot_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),reboot_b,1,1,1,1); + gtk_grid_attach(GTK_GRID(grid),reboot_b,2,1,1,1); GtkWidget *shutdown_b=gtk_button_new_with_label("Shutdown"); g_signal_connect (shutdown_b, "pressed", G_CALLBACK(shutdown_cb), NULL); - gtk_grid_attach(GTK_GRID(grid),shutdown_b,2,1,1,1); + gtk_grid_attach(GTK_GRID(grid),shutdown_b,3,1,1,1); gtk_container_add(GTK_CONTAINER(content),grid); diff --git a/ext.c b/ext.c index ca80aeb..155f4e5 100644 --- a/ext.c +++ b/ext.c @@ -458,10 +458,21 @@ int ext_rit_clear(void *data) { } int ext_xit_update(void *data) { + if(can_transmit) { + transmitter->xit_enabled=transmitter->xit_enabled==1?0:1; + if(protocol==NEW_PROTOCOL) { + schedule_high_priority(); + } + } + vfo_update(); return 0; } int ext_xit_clear(void *data) { + if(can_transmit) { + transmitter->xit=0; + vfo_update(); + } return 0; } @@ -550,6 +561,17 @@ int ext_diversity_update(void *data) { return 0; } +int ext_sat_update(void *data) { + int mode=GPOINTER_TO_INT(data); + if(sat_mode==mode) { + sat_mode=SAT_NONE; + } else { + sat_mode=mode; + } + vfo_update(); + return 0; +} + int ext_function_update(void *data) { function++; if(function>MAX_FUNCTION) { diff --git a/ext.h b/ext.h index a4a259d..115d05e 100644 --- a/ext.h +++ b/ext.h @@ -102,3 +102,4 @@ int ext_set_compression(void *data); int ext_start_rx(void *data); int ext_diversity_update(void *data); +int ext_sat_update(void *data); diff --git a/gpio.c b/gpio.c index 2f17b94..e9e18dc 100644 --- a/gpio.c +++ b/gpio.c @@ -337,6 +337,8 @@ char *sw_string[SWITCH_ACTIONS] = { "AGC", "SPLIT", "DIVERSITY", + "SAT", + "RSAT", "BAND MENU", "BANDSTACK MENU", "MODE MENU", @@ -448,18 +450,18 @@ static int e_function_pressed(void *data) { fprintf(stderr,"e_function_pressed: %d\n",action); switch(action) { case TUNE: - g_idle_add(ext_tune_update,NULL); + if(can_transmit) g_idle_add(ext_tune_update,NULL); break; case MOX: - g_idle_add(ext_mox_update,NULL); + if(can_transmit) g_idle_add(ext_mox_update,NULL); break; case PS: #ifdef PURESIGNAL - g_idle_add(ext_ps_update,NULL); + if(can_transmit) g_idle_add(ext_ps_update,NULL); #endif break; case TWO_TONE: - g_idle_add(ext_two_tone,NULL); + if(can_transmit) g_idle_add(ext_two_tone,NULL); break; case NR: g_idle_add(ext_nr_update,NULL); @@ -477,10 +479,10 @@ fprintf(stderr,"e_function_pressed: %d\n",action); g_idle_add(ext_rit_clear,NULL); break; case XIT: - g_idle_add(ext_xit_update,NULL); + if(can_transmit) g_idle_add(ext_xit_update,NULL); break; case XIT_CLEAR: - g_idle_add(ext_xit_clear,NULL); + if(can_transmit) g_idle_add(ext_xit_clear,NULL); break; case BAND_PLUS: g_idle_add(ext_band_plus,NULL); @@ -525,11 +527,17 @@ fprintf(stderr,"e_function_pressed: %d\n",action); g_idle_add(ext_agc_update,NULL); break; case SPLIT: - g_idle_add(ext_split_update,NULL); + if(can_transmit) g_idle_add(ext_split_update,NULL); break; case DIVERSITY: g_idle_add(ext_diversity_update,GINT_TO_POINTER(0)); break; + case SAT: + if(can_transmit) g_idle_add(ext_sat_update,GINT_TO_POINTER(SAT_MODE)); + break; + case RSAT: + if(can_transmit) g_idle_add(ext_sat_update,GINT_TO_POINTER(RSAT_MODE)); + break; case MENU_BAND: g_idle_add(ext_band_update,NULL); break; @@ -1716,6 +1724,26 @@ static void encoder_changed(int action,int pos) { } set_af_gain(1,value); break; + case ENCODER_RF_GAIN_RX1: + value=receiver[0]->rf_gain; + value+=(double)pos; + if(value<0.0) { + value=0.0; + } else if(value>100.0) { + value=100.0; + } + set_rf_gain(0,value); + break; + case ENCODER_RF_GAIN_RX2: + value=receiver[1]->rf_gain; + value+=(double)pos; + if(value<0.0) { + value=0.0; + } else if(value>71.0) { + value=71.0; + } + set_rf_gain(1,value); + break; case ENCODER_AGC_GAIN_RX1: value=receiver[0]->agc_gain; value+=(double)pos; @@ -1761,8 +1789,8 @@ static void encoder_changed(int action,int pos) { case ENCODER_MIC_GAIN: value=mic_gain; value+=(double)pos; - if(value<-10.0) { - value=-10.0; + if(value<-12.0) { + value=-12.0; } else if(value>50.0) { value=50.0; } @@ -1781,10 +1809,10 @@ static void encoder_changed(int action,int pos) { 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; + if(value<-10000.0) { + value=-10000.0; + } else if(value>10000.0) { + value=10000.0; } vfo[receiver[0]->id].rit=(int)value; if(protocol==NEW_PROTOCOL) { @@ -1795,10 +1823,10 @@ static void encoder_changed(int action,int pos) { 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; + if(value<-10000.0) { + value=-10000.0; + } else if(value>10000.0) { + value=10000.0; } vfo[receiver[1]->id].rit=(int)value; if(protocol==NEW_PROTOCOL) { @@ -1806,6 +1834,20 @@ static void encoder_changed(int action,int pos) { } g_idle_add(ext_vfo_update,NULL); break; + case ENCODER_XIT: + value=(double)transmitter->xit; + value+=(double)(pos*rit_increment); + if(value<-10000.0) { + value=-10000.0; + } else if(value>10000.0) { + value=10000.0; + } + transmitter->xit=(int)value; + if(protocol==NEW_PROTOCOL) { + schedule_high_priority(); + } + g_idle_add(ext_vfo_update,NULL); + break; case ENCODER_CW_SPEED: value=(double)cw_keyer_speed; value+=(double)pos; diff --git a/gpio.h b/gpio.h index 2d82536..ca99052 100644 --- a/gpio.h +++ b/gpio.h @@ -78,6 +78,8 @@ enum { AGC, SPLIT, DIVERSITY, + SAT, + RSAT, MENU_BAND, MENU_BANDSTACK, MENU_MODE, diff --git a/i2c.c b/i2c.c index d299a61..d9333ad 100644 --- a/i2c.c +++ b/i2c.c @@ -185,26 +185,26 @@ void i2c_interrupt() { //g_print("i1c_interrupt: sw=%d action=%d\n",i,sw_action[i]); 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)); + if(can_transmit) { + 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)); + if(can_transmit) { + int mox=getMox(); + if(mox==0) mox=1; else mox=0; + g_idle_add(ext_mox_update,GINT_TO_POINTER(mox)); } break; case PS: #ifdef PURESIGNAL - g_idle_add(ext_ps_update,NULL); + if(can_transmit) g_idle_add(ext_ps_update,NULL); #endif break; case TWO_TONE: - g_idle_add(ext_two_tone,NULL); + if(can_transmit) g_idle_add(ext_two_tone,NULL); break; case NR: g_idle_add(ext_nr_update,NULL); @@ -222,10 +222,10 @@ void i2c_interrupt() { g_idle_add(ext_rit_clear,NULL); break; case XIT: - g_idle_add(ext_xit_update,NULL); + if(can_transmit) g_idle_add(ext_xit_update,NULL); break; case XIT_CLEAR: - g_idle_add(ext_xit_clear,NULL); + if(can_transmit) g_idle_add(ext_xit_clear,NULL); break; case BAND_PLUS: g_idle_add(ext_band_plus,NULL); @@ -270,7 +270,37 @@ void i2c_interrupt() { g_idle_add(ext_agc_update,NULL); break; case SPLIT: - g_idle_add(ext_split_update,NULL); + if(can_transmit) g_idle_add(ext_split_update,NULL); + break; + case DIVERSITY: + g_idle_add(ext_diversity_update,GINT_TO_POINTER(0)); + break; + case SAT: + if(can_transmit) g_idle_add(ext_sat_update,GINT_TO_POINTER(SAT_MODE)); + break; + case RSAT: + if(can_transmit) g_idle_add(ext_sat_update,GINT_TO_POINTER(RSAT_MODE)); + 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; } } diff --git a/midi3.c b/midi3.c index efa5361..2a2fd05 100644 --- a/midi3.c +++ b/midi3.c @@ -240,19 +240,21 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) { break; case COMPRESS: // Use values in the range 0 ... 20 - if (type == MIDI_WHEEL) { - dnew=transmitter->compressor_level + val; - if (dnew > 20.0) dnew=20.0; - if (dnew < 0 ) dnew=0; - } else if (type == MIDI_KNOB){ + if(can_transmit) { + if (type == MIDI_WHEEL) { + dnew=transmitter->compressor_level + val; + if (dnew > 20.0) dnew=20.0; + if (dnew < 0 ) dnew=0; + } else if (type == MIDI_KNOB){ dnew=(20.0*val)/100.0; - } else { + } else { break; - } - transmitter->compressor_level=dnew; - if (dnew < 0.5) transmitter->compressor=0; - if (dnew > 0.5) transmitter->compressor=1; - g_idle_add(ext_set_compression, NULL); + } + transmitter->compressor_level=dnew; + if (dnew < 0.5) transmitter->compressor=0; + if (dnew > 0.5) transmitter->compressor=1; + g_idle_add(ext_set_compression, NULL); + } break; case MIDI_NB: // cycle through NoiseBlanker settings @@ -284,8 +286,10 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) { break; case VOX: // toggle VOX - vox_enabled = !vox_enabled; - g_idle_add(ext_vfo_update, NULL); + if(can_transmit) { + vox_enabled = !vox_enabled; + g_idle_add(ext_vfo_update, NULL); + } break; case MIDI_CTUN: // toggle CTUN @@ -303,20 +307,24 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) { case MIDI_PS: #ifdef PURESIGNAL // toggle PURESIGNAL - new=!(transmitter->puresignal); - g_idle_add(ext_tx_set_ps,GINT_TO_POINTER(new)); + if(can_transmit) { + new=!(transmitter->puresignal); + g_idle_add(ext_tx_set_ps,GINT_TO_POINTER(new)); + } #endif break; case MIDI_SPLIT: // toggle split mode - if(!split) { + if(can_transmit) { + if(!split) { split=1; tx_set_mode(transmitter,vfo[VFO_B].mode); - } else { + } else { split=0; tx_set_mode(transmitter,vfo[VFO_A].mode); - } - g_idle_add(ext_vfo_update, NULL); + } + g_idle_add(ext_vfo_update, NULL); + } break; case VFO_A2B: g_idle_add(ext_vfo_a_to_b, NULL); diff --git a/new_protocol.c b/new_protocol.c index 178513b..bd020c5 100644 --- a/new_protocol.c +++ b/new_protocol.c @@ -727,6 +727,9 @@ static void new_protocol_high_priority() { // txFrequency=vfo[txvfo].frequency-vfo[txvfo].lo+vfo[txvfo].offset; + if(transmitter->xit_enabled) { + txFrequency+=transmitter->xit; + } if (!cw_is_on_vfo_freq) { if(txmode==modeCWU) { @@ -1841,20 +1844,12 @@ static void process_mic_data(int bytes) { } } -void new_protocol_process_local_mic(unsigned char *buffer,int le) { - int b; +void new_protocol_process_local_mic(float *buffer) { int i; short sample; - b=0; for(i=0;ifreedv) { add_freedv_mic_sample(transmitter,sample); diff --git a/new_protocol.h b/new_protocol.h index fe900b3..82875c5 100644 --- a/new_protocol.h +++ b/new_protocol.h @@ -88,7 +88,7 @@ extern int getMox(); extern void setTune(int state); extern int getTune(); -extern void new_protocol_process_local_mic(unsigned char *buffer,int le); +extern void new_protocol_process_local_mic(float *buffer); extern void new_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right_audio_sample); extern void new_protocol_iq_samples(int isample,int qsample); extern void new_protocol_flush_iq_samples(); diff --git a/old_protocol.c b/old_protocol.c index 98b3ccc..b4701df 100644 --- a/old_protocol.c +++ b/old_protocol.c @@ -735,6 +735,9 @@ static long long channel_freq(int chan) { } } freq=vfo[vfonum].frequency-vfo[vfonum].lo+vfo[vfonum].offset; + if(transmitter->xit_enabled) { + freq+=transmitter->xit; + } if (!cw_is_on_vfo_freq) { if(vfo[vfonum].mode==modeCWU) { freq+=(long long)cw_keyer_sidetone_frequency; @@ -1044,23 +1047,15 @@ void old_protocol_iq_samples(int isample,int qsample) { } -void old_protocol_process_local_mic(unsigned char *buffer,int le) { - int b; +void old_protocol_process_local_mic(float *buffer) { int i; short sample; // always 48000 samples per second - b=0; for(i=0;i<720;i++) { // avoid pointer increments in logical-or constructs, as the sequence // is undefined - if(le) { - sample = (short) (buffer[b++]&0xFF); - sample |= (short) (buffer[b++]<<8); - } else { - sample = (short)(buffer[b++]<<8); - sample |= (short) (buffer[b++]&0xFF); - } + sample = (short) (buffer[i]*32767.0); #ifdef FREEDV if(active_receiver->freedv) { add_freedv_mic_sample(transmitter,sample); diff --git a/old_protocol.h b/old_protocol.h index c7cf63c..bda0ab2 100644 --- a/old_protocol.h +++ b/old_protocol.h @@ -26,7 +26,7 @@ extern void old_protocol_run(); extern void old_protocol_init(int rx,int pixels,int rate); extern void old_protocol_set_mic_sample_rate(int rate); -extern void old_protocol_process_local_mic(unsigned char *buffer,int le); +extern void old_protocol_process_local_mic(float *buffer); extern void old_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right_audio_sample); extern void old_protocol_iq_samples(int isample,int qsample); extern void old_protocol_iq_samples_with_sidetone(int isample,int qsample,int side); diff --git a/radio.c b/radio.c index faa0ee7..fb63857 100644 --- a/radio.c +++ b/radio.c @@ -97,7 +97,7 @@ #define FREEDV_WATERFALL_HEIGHT (105) #endif -static GtkWidget *fixed; +GtkWidget *fixed; static GtkWidget *vfo_panel; static GtkWidget *meter; static GtkWidget *menu; @@ -120,6 +120,8 @@ static GtkWidget *encoders; static cairo_surface_t *encoders_surface = NULL; #endif +gint sat_mode; + int region=REGION_OTHER; int echo=0; @@ -317,6 +319,21 @@ double display_calibration=0.0; int can_transmit=0; +gboolean duplex=FALSE; + +void radio_stop() { + if(can_transmit) { +g_print("radio_stop: TX: CloseChannel: %d\n",transmitter->id); + CloseChannel(transmitter->id); + } + set_displaying(receiver[0],0); +g_print("radio_stop: RX0: CloseChannel: %d\n",receiver[0]->id); + CloseChannel(receiver[0]->id); + set_displaying(receiver[1],0); +g_print("radio_stop: RX1: CloseChannel: %d\n",receiver[1]->id); + CloseChannel(receiver[1]->id); +} + void reconfigure_radio() { int i; int y; @@ -750,6 +767,7 @@ void start_radio() { y=0; fixed=gtk_fixed_new(); + g_object_ref(grid); // so it does not get deleted gtk_container_remove(GTK_CONTAINER(top_window),grid); gtk_container_add(GTK_CONTAINER(top_window), fixed); @@ -787,7 +805,6 @@ void start_radio() { int tx_height=rx_height; rx_height=rx_height/RECEIVERS; - // // To be on the safe side, we create ALL receiver panels here // If upon startup, we only should display one panel, we do the switch below @@ -811,7 +828,7 @@ void start_radio() { //fprintf(stderr,"Create transmitter\n"); if(can_transmit) { - transmitter=create_transmitter(CHANNEL_TX, buffer_size, fft_size, updates_per_second, display_width, tx_height); + transmitter=create_transmitter(CHANNEL_TX, buffer_size, fft_size, updates_per_second, display_width/2, tx_height/2); transmitter->x=0; transmitter->y=VFO_HEIGHT; @@ -821,6 +838,7 @@ void start_radio() { receiver[PS_RX_FEEDBACK]=create_pure_signal_receiver(PS_RX_FEEDBACK, buffer_size,protocol==ORIGINAL_PROTOCOL?active_receiver->sample_rate:192000,display_width); SetPSHWPeak(transmitter->id, protocol==ORIGINAL_PROTOCOL? 0.4067 : 0.2899); #endif + } #ifdef AUDIO_WATERFALL @@ -923,20 +941,27 @@ void start_radio() { if(can_transmit) { soapy_protocol_create_transmitter(transmitter); soapy_protocol_set_tx_antenna(transmitter,dac[0].antenna); +/* for(int i=0;iinfo.soapy.tx_gains;i++) { - soapy_protocol_set_tx_gain(transmitter,radio->info.soapy.tx_gain[i],dac[0].tx_gain[i]); + soapy_protocol_set_tx_gain_element(transmitter,radio->info.soapy.tx_gain[i],dac[0].tx_gain[i]); } +*/ + soapy_protocol_set_tx_gain(transmitter,transmitter->drive); soapy_protocol_set_tx_frequency(transmitter); + soapy_protocol_start_transmitter(transmitter); } 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_gain_element(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_set_gain_element(rx,radio->info.soapy.rx_gain[i],adc[0].rx_gain[i]); } if(vfo[0].ctun) { @@ -944,6 +969,9 @@ void start_radio() { } soapy_protocol_start_receiver(rx); +//g_print("radio: set rf_gain=%f\n",rx->rf_gain); + soapy_protocol_set_gain(rx,rx->rf_gain); + } #endif @@ -1014,6 +1042,7 @@ void radio_change_sample_rate(int rate) { static void rxtx(int state) { int i; + g_print("rxtx: state=%d duplex=%d\n",state,duplex); if(state) { // switch to tx #ifdef FREEDV @@ -1029,20 +1058,22 @@ static void rxtx(int state) { tx_feedback->samples=0; #endif - for(i=0;iid,0,1); - set_displaying(receiver[i],0); - g_object_ref((gpointer)receiver[i]->panel); - g_object_ref((gpointer)receiver[i]->panadapter); - if(receiver[i]->waterfall!=NULL) { - g_object_ref((gpointer)receiver[i]->waterfall); + if(!duplex) { + for(i=0;iid,0,1); + set_displaying(receiver[i],0); + g_object_ref((gpointer)receiver[i]->panel); + g_object_ref((gpointer)receiver[i]->panadapter); + if(receiver[i]->waterfall!=NULL) { + g_object_ref((gpointer)receiver[i]->waterfall); + } + gtk_container_remove(GTK_CONTAINER(fixed),receiver[i]->panel); } - gtk_container_remove(GTK_CONTAINER(fixed),receiver[i]->panel); } //#ifdef FREEDV // if(active_receiver->freedv) { @@ -1050,10 +1081,26 @@ static void rxtx(int state) { // } //#endif gtk_fixed_put(GTK_FIXED(fixed),transmitter->panel,transmitter->x,transmitter->y); + SetChannelState(transmitter->id,1,0); tx_set_displaying(transmitter,1); + switch(protocol) { +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: + soapy_protocol_set_tx_frequency(transmitter); + //soapy_protocol_start_transmitter(transmitter); + break; +#endif + } } else { // switch to rx + switch(protocol) { +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: + //soapy_protocol_stop_transmitter(transmitter); + break; +#endif + } SetChannelState(transmitter->id,0,1); tx_set_displaying(transmitter,0); g_object_ref((gpointer)transmitter->panel); @@ -1064,10 +1111,12 @@ static void rxtx(int state) { // gtk_widget_hide(audio_waterfall); // } //#endif - for(i=0;ipanel,receiver[i]->x,receiver[i]->y); - SetChannelState(receiver[i]->id,1,0); - set_displaying(receiver[i],1); + if(!duplex) { + for(i=0;ipanel,receiver[i]->x,receiver[i]->y); + SetChannelState(receiver[i]->id,1,0); + set_displaying(receiver[i],1); + } } //#ifdef FREEDV // if(active_receiver->freedv) { @@ -1084,6 +1133,7 @@ static void rxtx(int state) { } void setMox(int state) { +g_print("setMox: %d\n",state); if(!can_transmit) return; vox_cancel(); // remove time-out if(mox!=state) { @@ -1100,18 +1150,6 @@ void setMox(int state) { schedule_high_priority(); schedule_receive_specific(); break; -#ifdef SOAPYSDR - case SOAPYSDR_PROTOCOL: - if(transmitter!=NULL) { - if(mox) { - soapy_protocol_set_tx_frequency(transmitter); - soapy_protocol_start_transmitter(transmitter); - } else { - soapy_protocol_stop_transmitter(transmitter); - } - } - break; -#endif default: break; } @@ -1204,16 +1242,18 @@ void setTune(int state) { //schedule_general(); } if(state) { - for(i=0;iid,0,1); - set_displaying(receiver[i],0); - if(protocol==NEW_PROTOCOL) { - schedule_high_priority(); + if(!duplex) { + for(i=0;iid,0,1); + set_displaying(receiver[i],0); + if(protocol==NEW_PROTOCOL) { + schedule_high_priority(); + } } } @@ -1372,7 +1412,18 @@ void calcDriveLevel() { void setDrive(double value) { transmitter->drive=value; - calcDriveLevel(); + switch(protocol) { + case ORIGINAL_PROTOCOL: + case NEW_PROTOCOL: + calcDriveLevel(); + break; +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: + soapy_protocol_set_tx_gain(transmitter,transmitter->drive); + + break; +#endif + } } double getTuneDrive() { @@ -1652,6 +1703,13 @@ fprintf(stderr,"sem_wait: returner\n"); value=getProperty("rx2_gain_slider"); if(value) rx_gain_slider[1]=atoi(value); + value=getProperty("split"); + if(value) split=atoi(value); + value=getProperty("duplex"); + if(value) duplex=atoi(value); + value=getProperty("sat_mode"); + if(value) sat_mode=atoi(value); + #ifdef SOAPYSDR if(radio->device==SOAPYSDR_USB_DEVICE) { for(int i=0;iinfo.soapy.rx_gains;i++) { @@ -1664,6 +1722,8 @@ fprintf(stderr,"sem_wait: returner\n"); value=getProperty("radio.adc[0].antenna"); if(value!=NULL) adc[0].antenna=atoi(value); + value=getProperty("radio.dac[0].antenna"); + if(value!=NULL) dac[0].antenna=atoi(value); 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); @@ -1867,6 +1927,10 @@ fprintf(stderr,"sem_wait: returned\n"); sprintf(value,"%d", adc[0].antenna); setProperty(name,value); + sprintf(name,"radio.dac[0].antenna"); + sprintf(value,"%d", dac[0].antenna); + setProperty(name,value); + for(int i=0;iinfo.soapy.tx_gains;i++) { sprintf(name,"radio.dac[0].tx_gain.%s",radio->info.soapy.tx_gain[i]); sprintf(value,"%d", dac[0].tx_gain[i]); @@ -1885,6 +1949,10 @@ fprintf(stderr,"sem_wait: returned\n"); sprintf(value,"%d", adc[1].antenna); setProperty(name,value); + sprintf(name,"radio.dac[1].antenna"); + sprintf(value,"%d", dac[1].antenna); + setProperty(name,value); + for(int i=0;iinfo.soapy.tx_gains;i++) { sprintf(name,"radio.dac[1].tx_gain.%s",radio->info.soapy.tx_gain[i]); sprintf(value,"%d", dac[1].tx_gain[i]); @@ -1915,6 +1983,14 @@ fprintf(stderr,"sem_wait: returned\n"); if(can_transmit) { transmitter_save_state(transmitter); } + + sprintf(value,"%d",duplex); + setProperty("duplex",value); + sprintf(value,"%d",split); + setProperty("split",value); + sprintf(value,"%d",sat_mode); + setProperty("sat_mode",value); + #ifdef FREEDV freedv_save_state(); #endif diff --git a/radio.h b/radio.h index 7f1a46b..de3c11e 100644 --- a/radio.h +++ b/radio.h @@ -48,6 +48,8 @@ extern DISCOVERED *radio; +extern GtkWidget *fixed; + extern char property_path[]; #define NONE 0 @@ -88,6 +90,14 @@ extern TRANSMITTER *transmitter; #define KEYER_MODE_A 1 #define KEYER_MODE_B 2 +enum { + SAT_NONE, + SAT_MODE, + RSAT_MODE +}; + +extern gint sat_mode; + extern int echo; extern int radio_sample_rate; @@ -159,9 +169,10 @@ int rx_gain_slider[2]; int locked; extern long long step; -//extern int rit; extern int rit_increment; +extern gboolean duplex; + extern int lt2208Dither; extern int lt2208Random; extern int attenuation; @@ -264,6 +275,7 @@ extern double display_calibration; extern int can_transmit; +extern void radio_stop(); extern void reconfigure_radio(); extern void start_radio(); //extern void init_radio(); diff --git a/radio_menu.c b/radio_menu.c index 62840fe..163aa4b 100644 --- a/radio_menu.c +++ b/radio_menu.c @@ -38,12 +38,15 @@ #include "soapy_protocol.h" #endif #include "gpio.h" +#include "vfo.h" static GtkWidget *parent_window=NULL; - static GtkWidget *menu_b=NULL; - static GtkWidget *dialog=NULL; +static GtkWidget *rx_gains[3]; +static GtkWidget *tx_gains[2]; +static GtkWidget *sat_b; +static GtkWidget *rsat_b; static void cleanup() { if(dialog!=NULL) { @@ -64,18 +67,47 @@ static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_d } #ifdef SOAPYSDR +static void rf_gain_value_changed_cb(GtkWidget *widget, gpointer data) { + ADC *adc=(ADC *)data; + active_receiver->rf_gain=gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget)); + + if(radio->device==SOAPYSDR_USB_DEVICE) { + soapy_protocol_set_gain(receiver[0],active_receiver->rf_gain); + } + + for(int i=0;iinfo.soapy.rx_gains;i++) { + int value=soapy_protocol_get_gain_element(active_receiver,radio->info.soapy.rx_gain[i]); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(rx_gains[i]),(double)value); + } +} + static void rx_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); + soapy_protocol_set_gain_element(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 drive_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(transmitter,(double)gain); + for(int i=0;iinfo.soapy.tx_gains;i++) { + int value=soapy_protocol_get_tx_gain_element(transmitter,radio->info.soapy.tx_gain[i]); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(tx_gains[i]),(double)value); + } } } @@ -84,7 +116,7 @@ static void tx_gain_value_changed_cb(GtkWidget *widget, gpointer 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(transmitter,(char *)gtk_widget_get_name(widget),gain); + soapy_protocol_set_tx_gain_element(transmitter,(char *)gtk_widget_get_name(widget),gain); for(int i=0;iinfo.soapy.tx_gains;i++) { if(strcmp(radio->info.soapy.tx_gain[i],(char *)gtk_widget_get_name(widget))==0) { dac[0].tx_gain[i]=gain; @@ -107,7 +139,7 @@ static void dac0_gain_value_changed_cb(GtkWidget *widget, gpointer 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); + soapy_protocol_set_tx_gain_element(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; @@ -158,6 +190,35 @@ static void iqswap_cb(GtkWidget *widget, gpointer data) { iqswap=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); } +static void split_cb(GtkWidget *widget, gpointer data) { + split=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + vfo_update(); +} + +static void duplex_cb(GtkWidget *widget, gpointer data) { + duplex=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + vfo_update(); +} + +static void sat_cb(GtkWidget *widget, gpointer data) { + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rsat_b), FALSE); + sat_mode=SAT_MODE; + } else { + sat_mode=SAT_NONE; + } + vfo_update(); +} + +static void rsat_cb(GtkWidget *widget, gpointer data) { + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sat_b), FALSE); + sat_mode=RSAT_MODE; + } else { + sat_mode=SAT_NONE; + } + vfo_update(); +} static void load_filters(void) { if(protocol==NEW_PROTOCOL) { @@ -290,6 +351,8 @@ void radio_menu(GtkWidget *parent) { gtk_grid_attach(GTK_GRID(grid),region_combo,col,row,1,1); g_signal_connect(region_combo,"changed",G_CALLBACK(region_cb),NULL); + col++; + row++; col=0; @@ -468,7 +531,7 @@ void radio_menu(GtkWidget *parent) { row=1; - GtkWidget *rit_label=gtk_label_new("RIT step (Hz): "); + GtkWidget *rit_label=gtk_label_new("R/XIT step (Hz): "); gtk_grid_attach(GTK_GRID(grid),rit_label,col,row,1,1); row++; @@ -564,9 +627,40 @@ void radio_menu(GtkWidget *parent) { if(row>temp_row) temp_row=row; } -#ifdef SOAPYSDR row=temp_row; col=0; + + GtkWidget *split_b=gtk_check_button_new_with_label("Split"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (split_b), split); + gtk_grid_attach(GTK_GRID(grid),split_b,col,row,1,1); + g_signal_connect(split_b,"toggled",G_CALLBACK(split_cb),NULL); + + col++; + + GtkWidget *duplex_b=gtk_check_button_new_with_label("Duplex"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (duplex_b), duplex); + gtk_grid_attach(GTK_GRID(grid),duplex_b,col,row,1,1); + g_signal_connect(duplex_b,"toggled",G_CALLBACK(duplex_cb),NULL); + + col++; + + sat_b=gtk_check_button_new_with_label("SAT"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sat_b), sat_mode==SAT_MODE); + gtk_grid_attach(GTK_GRID(grid),sat_b,col,row,1,1); + g_signal_connect(sat_b,"toggled",G_CALLBACK(sat_cb),NULL); + + col++; + + rsat_b=gtk_check_button_new_with_label("RSAT"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rsat_b), sat_mode==RSAT_MODE); + gtk_grid_attach(GTK_GRID(grid),rsat_b,col,row,1,1); + g_signal_connect(rsat_b,"toggled",G_CALLBACK(rsat_cb),NULL); + + row++; + if(row>temp_row) temp_row=row; + +#ifdef SOAPYSDR + col=0; if(radio->device==SOAPYSDR_USB_DEVICE) { int i; if(radio->info.soapy.rx_gains>0) { @@ -594,6 +688,7 @@ void radio_menu(GtkWidget *parent) { } + //rx_gains=g_new(GtkWidget*,radio->info.soapy.rx_gains); for(i=0;iinfo.soapy.rx_gains;i++) { col=0; GtkWidget *rx_gain_label=gtk_label_new(radio->info.soapy.rx_gain[i]); @@ -603,18 +698,35 @@ void radio_menu(GtkWidget *parent) { if(range.step==0.0) { range.step=1.0; } - GtkWidget *rx_gain_b=gtk_spin_button_new_with_range(range.minimum,range.maximum,range.step); - gtk_widget_set_name (rx_gain_b, radio->info.soapy.rx_gain[i]); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(rx_gain_b),(double)adc[0].rx_gain[i]); - gtk_grid_attach(GTK_GRID(grid),rx_gain_b,col,row,1,1); - g_signal_connect(rx_gain_b,"value_changed",G_CALLBACK(rx_gain_value_changed_cb),&adc[0]); - col++; + rx_gains[i]=gtk_spin_button_new_with_range(range.minimum,range.maximum,range.step); + gtk_widget_set_name (rx_gains[i], radio->info.soapy.rx_gain[i]); + int value=soapy_protocol_get_gain_element(active_receiver,radio->info.soapy.rx_gain[i]); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(rx_gains[i]),(double)value); + //gtk_spin_button_set_value(GTK_SPIN_BUTTON(rx_gains[i]),(double)adc[0].rx_gain[i]); + gtk_grid_attach(GTK_GRID(grid),rx_gains[i],col,row,1,1); + g_signal_connect(rx_gains[i],"value_changed",G_CALLBACK(rx_gain_value_changed_cb),&adc[0]); + + gtk_widget_set_sensitive(rx_gains[i], FALSE); + row++; } + // used single gain control - LimeSDR works out best setting for the 3 rx gains + col=0; + GtkWidget *rf_gain_label=gtk_label_new("RF Gain"); + gtk_grid_attach(GTK_GRID(grid),rf_gain_label,col,row,1,1); + col++; + GtkWidget *rf_gain_b=gtk_spin_button_new_with_range(0.0,60.0,1.0); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(rf_gain_b),active_receiver->rf_gain); + gtk_grid_attach(GTK_GRID(grid),rf_gain_b,col,row,1,1); + g_signal_connect(rf_gain_b,"value_changed",G_CALLBACK(rf_gain_value_changed_cb),&adc[0]); + col++; + row++; + row=temp_row; if(can_transmit) { + //tx_gains=g_new(GtkWidget*,radio->info.soapy.tx_gains); for(i=0;iinfo.soapy.tx_gains;i++) { col=2; GtkWidget *tx_gain_label=gtk_label_new(radio->info.soapy.tx_gain[i]); @@ -624,15 +736,29 @@ void radio_menu(GtkWidget *parent) { if(range.step==0.0) { range.step=1.0; } - GtkWidget *tx_gain_b=gtk_spin_button_new_with_range(range.minimum,range.maximum,range.step); - gtk_widget_set_name (tx_gain_b, radio->info.soapy.tx_gain[i]); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(tx_gain_b),(double)dac[0].tx_gain[i]); - gtk_grid_attach(GTK_GRID(grid),tx_gain_b,col,row,1,1); - g_signal_connect(tx_gain_b,"value_changed",G_CALLBACK(tx_gain_value_changed_cb),&dac[0]); + tx_gains[i]=gtk_spin_button_new_with_range(range.minimum,range.maximum,range.step); + gtk_widget_set_name (tx_gains[i], radio->info.soapy.tx_gain[i]); + int value=soapy_protocol_get_tx_gain_element(transmitter,radio->info.soapy.tx_gain[i]); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(tx_gains[i]),(double)value); + //gtk_spin_button_set_value(GTK_SPIN_BUTTON(tx_gains[i]),(double)dac[0].tx_gain[i]); + gtk_grid_attach(GTK_GRID(grid),tx_gains[i],col,row,1,1); + g_signal_connect(tx_gains[i],"value_changed",G_CALLBACK(tx_gain_value_changed_cb),&dac[0]); + + gtk_widget_set_sensitive(tx_gains[i], FALSE); + row++; } - } + // used single gain control - LimeSDR works out best setting for the 3 rx gains + col=2; + GtkWidget *tx_gain_label=gtk_label_new("TX Gain"); + gtk_grid_attach(GTK_GRID(grid),tx_gain_label,col,row,1,1); + col++; + tx_gains[i]=gtk_spin_button_new_with_range(0.0,100.0,1.0); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(tx_gains[i]),transmitter->drive); + gtk_grid_attach(GTK_GRID(grid),tx_gains[i],col,row,1,1); + g_signal_connect(tx_gains[i],"value_changed",G_CALLBACK(drive_gain_value_changed_cb),&adc[0]); + } } #endif diff --git a/receiver.c b/receiver.c index 411e385..4f4be81 100644 --- a/receiver.c +++ b/receiver.c @@ -116,7 +116,7 @@ gboolean receiver_button_release_event(GtkWidget *widget, GdkEventButton *event, vfo_move((long long)((float)(x-last_x)*rx->hz_per_pixel)); } else { // move to this frequency - vfo_move_to((long long)((float)(x-(display_width/2))*rx->hz_per_pixel)); + vfo_move_to((long long)((float)x*rx->hz_per_pixel)); } last_x=x; pressed=FALSE; @@ -140,7 +140,8 @@ gboolean receiver_motion_notify_event(GtkWidget *widget, GdkEventMotion *event, &state); // G0ORX: removed test as with it unable to drag screen //if(state & GDK_BUTTON1_MASK) { - int moved=last_x-x; + //int moved=last_x-x; + int moved=x-last_x; vfo_move((long long)((float)moved*rx->hz_per_pixel)); last_x=x; has_moved=TRUE; @@ -152,17 +153,9 @@ gboolean receiver_motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gboolean receiver_scroll_event(GtkWidget *widget, GdkEventScroll *event, gpointer data) { if(event->direction==GDK_SCROLL_UP) { - if(vfo[active_receiver->id].ctun) { - vfo_move(-step); - } else { - vfo_move(step); - } + vfo_move(step); } else { - if(vfo[active_receiver->id].ctun) { - vfo_move(step); - } else { - vfo_move(-step); - } + vfo_move(-step); } return TRUE; } @@ -226,6 +219,9 @@ void receiver_save_state(RECEIVER *rx) { sprintf(name,"receiver.%d.volume",rx->id); sprintf(value,"%f",rx->volume); setProperty(name,value); + sprintf(name,"receiver.%d.rf_gain",rx->id); + sprintf(value,"%f",rx->rf_gain); + setProperty(name,value); sprintf(name,"receiver.%d.agc",rx->id); sprintf(value,"%d",rx->agc); setProperty(name,value); @@ -285,6 +281,11 @@ void receiver_save_state(RECEIVER *rx) { sprintf(name,"receiver.%d.local_audio",rx->id); sprintf(value,"%d",rx->local_audio); setProperty(name,value); + if(rx->audio_name!=NULL) { + sprintf(name,"receiver.%d.audio_name",rx->id); + sprintf(value,"%s",rx->audio_name); + setProperty(name,value); + } sprintf(name,"receiver.%d.mute_when_not_active",rx->id); sprintf(value,"%d",rx->mute_when_not_active); setProperty(name,value); @@ -398,6 +399,9 @@ fprintf(stderr,"receiver_restore_state: id=%d\n",rx->id); sprintf(name,"receiver.%d.volume",rx->id); value=getProperty(name); if(value) rx->volume=atof(value); + sprintf(name,"receiver.%d.rf_gain",rx->id); + value=getProperty(name); + if(value) rx->rf_gain=atof(value); sprintf(name,"receiver.%d.agc",rx->id); value=getProperty(name); if(value) rx->agc=atoi(value); @@ -457,6 +461,12 @@ fprintf(stderr,"receiver_restore_state: id=%d\n",rx->id); sprintf(name,"receiver.%d.local_audio",rx->id); value=getProperty(name); if(value) rx->local_audio=atoi(value); + sprintf(name,"receiver.%d.audio_name",rx->id); + value=getProperty(name); + if(value) { + rx->audio_name=g_new(gchar,strlen(value)+1); + strcpy(rx->audio_name,value); + } sprintf(name,"receiver.%d.mute_when_not_active",rx->id); value=getProperty(name); if(value) rx->mute_when_not_active=atoi(value); @@ -594,6 +604,10 @@ void set_displaying(RECEIVER *rx,int state) { rx->displaying=state; if(state) { rx->update_timer_id=gdk_threads_add_timeout_full(G_PRIORITY_HIGH_IDLE,1000/rx->fps, update_display, rx, NULL); + } else { + if(rx->update_timer_id!=-1) { + rx->update_timer_id=-1; + } } } @@ -814,7 +828,8 @@ fprintf(stderr,"create_pure_signal_receiver: id=%d buffer_size=%d\n",id,buffer_s rx->panadapter_low=-140; rx->panadapter_step=20; - rx->volume=0.0; + rx->volume=5.0; + rx->rf_gain=50.0; rx->squelch_enable=0; rx->squelch=0; @@ -846,6 +861,7 @@ fprintf(stderr,"create_pure_signal_receiver: id=%d buffer_size=%d\n",id,buffer_s rx->playback_handle=NULL; rx->playback_buffer=NULL; rx->local_audio=0; + rx->audio_name=NULL; rx->mute_when_not_active=0; rx->audio_channel=STEREO; rx->audio_device=-1; @@ -930,6 +946,7 @@ fprintf(stderr,"create_receiver: id=%d default adc=%d\n",rx->id, rx->adc); rx->fft_size=fft_size; rx->pixels=pixels; rx->fps=fps; + rx->update_timer_id=-1; // rx->dds_offset=0; @@ -986,6 +1003,7 @@ fprintf(stderr,"create_receiver: id=%d default adc=%d\n",rx->id, rx->adc); rx->playback_handle=NULL; rx->local_audio=0; + rx->audio_name=NULL; rx->mute_when_not_active=0; rx->audio_channel=STEREO; rx->audio_device=-1; @@ -1312,7 +1330,7 @@ static void process_rx_buffer(RECEIVER *rx) { short right_audio_sample; int i; for(i=0;ioutput_samples;i++) { - if(isTransmitting()) { + if(isTransmitting() && !duplex) { left_audio_sample=0; right_audio_sample=0; } else { diff --git a/receiver.h b/receiver.h index 8a98c2a..f201bfb 100644 --- a/receiver.h +++ b/receiver.h @@ -43,6 +43,8 @@ typedef struct _receiver { gint adc; gdouble volume; + gdouble rf_gain; + gint agc; gdouble agc_gain; gdouble agc_slope; @@ -110,6 +112,7 @@ typedef struct _receiver { gint local_audio; gint mute_when_not_active; gint audio_device; + gchar *audio_name; #ifdef PORTAUDIO PaStream *playback_handle; gfloat *playback_buffer; diff --git a/release/pihpsdr-controller1.v2.0.1-beta.tar b/release/pihpsdr-controller1.v2.0.1-beta.tar new file mode 100644 index 0000000..c9b2335 Binary files /dev/null and b/release/pihpsdr-controller1.v2.0.1-beta.tar differ diff --git a/release/pihpsdr-controller2-v1.v2.0.1-beta.tar b/release/pihpsdr-controller2-v1.v2.0.1-beta.tar new file mode 100644 index 0000000..42c5970 Binary files /dev/null and b/release/pihpsdr-controller2-v1.v2.0.1-beta.tar differ diff --git a/release/pihpsdr-controller2-v2.v2.0.1-beta.tar b/release/pihpsdr-controller2-v2.v2.0.1-beta.tar new file mode 100644 index 0000000..6e1c279 Binary files /dev/null and b/release/pihpsdr-controller2-v2.v2.0.1-beta.tar differ diff --git a/release/pihpsdr-nocontroller.v2.0.1-beta.tar b/release/pihpsdr-nocontroller.v2.0.1-beta.tar new file mode 100644 index 0000000..d40f2cb Binary files /dev/null and b/release/pihpsdr-nocontroller.v2.0.1-beta.tar differ diff --git a/release/pihpsdr/pihpsdr b/release/pihpsdr/pihpsdr index 0ee5bab..c22bfb8 100755 Binary files a/release/pihpsdr/pihpsdr and b/release/pihpsdr/pihpsdr differ diff --git a/rx_menu.c b/rx_menu.c index 24db9fc..f986b51 100644 --- a/rx_menu.c +++ b/rx_menu.c @@ -35,10 +35,10 @@ #include "new_protocol.h" static GtkWidget *parent_window=NULL; - static GtkWidget *menu_b=NULL; - static GtkWidget *dialog=NULL; +static GtkWidget *local_audio_b=NULL; +static GtkWidget *output=NULL; static void cleanup() { if(dialog!=NULL) { @@ -96,6 +96,12 @@ static void adc_cb(GtkWidget *widget, gpointer data) { static void local_audio_cb(GtkWidget *widget, gpointer data) { fprintf(stderr,"local_audio_cb: rx=%d\n",active_receiver->id); + + if(active_receiver->audio_name==NULL) { + int i=gtk_combo_box_get_active(GTK_COMBO_BOX(output)); + active_receiver->audio_name=g_new(gchar,strlen(output_devices[i].name)+1); + strcpy(active_receiver->audio_name,output_devices[i].name); + } if(gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) { if(audio_open_output(active_receiver)==0) { active_receiver->local_audio=1; @@ -126,21 +132,30 @@ static void mute_radio_cb(GtkWidget *widget, gpointer data) { // call audo_close_output with old device, audio_open_output with new one // static void local_output_changed_cb(GtkWidget *widget, gpointer data) { - int newdev = (int)(long)data; - fprintf(stderr,"local_output_changed rx=%d from %d to %d\n",active_receiver->id,active_receiver->audio_device,newdev); + int i = GPOINTER_TO_INT(data); + fprintf(stderr,"local_output_changed rx=%d %s\n",active_receiver->id,output_devices[i].name); if(active_receiver->local_audio) { audio_close_output(active_receiver); // audio_close with OLD device - active_receiver->audio_device=newdev; // update rx to NEW device - if(audio_open_output(active_receiver)==0) { // audio_open with NEW device - active_receiver->local_audio=1; - } else { + } + + if(active_receiver->audio_name!=NULL) { + g_free(active_receiver->audio_name); + active_receiver->audio_name=NULL; + } + + if(i>=0) { + active_receiver->audio_name=g_new(gchar,strlen(output_devices[i].name)+1); + strcpy(active_receiver->audio_name,output_devices[i].name); + //active_receiver->audio_device=output_devices[i].index; // update rx to NEW device + } + + if(active_receiver->local_audio) { + if(audio_open_output(active_receiver)<0) { // audio_open with NEW device active_receiver->local_audio=0; + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (local_audio_b),FALSE); } - fprintf(stderr,"local_output_changed rx=%d local_audio=%d\n",active_receiver->id,active_receiver->local_audio); - } else { - // If not (currently) using local audio, just change dev num - active_receiver->audio_device=newdev; } + fprintf(stderr,"local_output_changed rx=%d local_audio=%d\n",active_receiver->id,active_receiver->local_audio); } static void audio_channel_cb(GtkWidget *widget, gpointer data) { @@ -316,7 +331,7 @@ void rx_menu(GtkWidget *parent) { int row=0; if(n_output_devices>0) { - GtkWidget *local_audio_b=gtk_check_button_new_with_label("Local Audio Output"); + local_audio_b=gtk_check_button_new_with_label("Local Audio Output"); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (local_audio_b), active_receiver->local_audio); gtk_widget_show(local_audio_b); gtk_grid_attach(GTK_GRID(grid),local_audio_b,x,++row,1,1); @@ -324,13 +339,17 @@ void rx_menu(GtkWidget *parent) { if(active_receiver->audio_device==-1) active_receiver->audio_device=0; - GtkWidget *output=NULL; + output=NULL; for(i=0;iaudio_device==i); + output=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(output),output_devices[i].description); + if(active_receiver->audio_name!=NULL) { + if(strcmp(active_receiver->audio_name,output_devices[i].description)==0) { + gtk_combo_box_set_active(GTK_COMBO_BOX(output),i); + } + } gtk_widget_show(output); gtk_grid_attach(GTK_GRID(grid),output,x,++row,1,1); - g_signal_connect(output,"pressed",G_CALLBACK(local_output_changed_cb),(gpointer)(long)i); + g_signal_connect(output,"pressed",G_CALLBACK(local_output_changed_cb),GINT_TO_POINTER(i)); } row=0; diff --git a/rx_panadapter.c b/rx_panadapter.c index 7ba22ac..37e24bd 100644 --- a/rx_panadapter.c +++ b/rx_panadapter.c @@ -387,6 +387,11 @@ void rx_panadapter_update(RECEIVER *rx) { samples[display_width-1]=-200.0; s1=(double)samples[0]+(double)adc_attenuation[rx->adc]; if (filter_board == ALEX && rx->adc == 0) s1 += (double)(10*rx->alex_attenuation); +#ifdef SOAPYSDR + if(protocol==SOAPYSDR_PROTOCOL) { + s1-=rx->rf_gain; + } +#endif s1 = floor((rx->panadapter_high - s1) * (double) display_height @@ -395,6 +400,11 @@ void rx_panadapter_update(RECEIVER *rx) { for(i=1;iadc]; if (filter_board == ALEX && rx->adc == 0) s2 += (double)(10*rx->alex_attenuation); +#ifdef SOAPYSDR + if(protocol==SOAPYSDR_PROTOCOL) { + s2-=rx->rf_gain; + } +#endif s2 = floor((rx->panadapter_high - s2) * (double) display_height / (rx->panadapter_high - rx->panadapter_low)); diff --git a/sliders.c b/sliders.c index f6ffca5..71e6311 100644 --- a/sliders.c +++ b/sliders.c @@ -44,6 +44,9 @@ #include "band.h" #include "discovered.h" #include "new_protocol.h" +#ifdef SOAPYSDR +#include "soapy_protocol.h" +#endif #include "vfo.h" #include "alex.h" #include "agc.h" @@ -62,22 +65,25 @@ static GtkWidget *sliders; #define NONE 0 #define AF_GAIN 1 -#define MIC_GAIN 2 -#define LINEIN_GAIN 3 -#define AGC_GAIN 4 -#define DRIVE 5 -#define ATTENUATION 6 -#define SQUELCH 7 -#define COMP 8 -#define FILTER_WIDTH 9 -#define DIVERSITY_GAIN 10 -#define DIVERSITY_PHASE 11 +#define RF_GAIN 2 +#define MIC_GAIN 3 +#define LINEIN_GAIN 4 +#define AGC_GAIN 5 +#define DRIVE 6 +#define ATTENUATION 7 +#define SQUELCH 8 +#define COMP 9 +#define FILTER_WIDTH 10 +#define DIVERSITY_GAIN 11 +#define DIVERSITY_PHASE 12 static gint scale_timer; static int scale_status=NONE; static GtkWidget *scale_dialog; static GtkWidget *af_gain_label; static GtkWidget *af_gain_scale; +static GtkWidget *rf_gain_label; +static GtkWidget *rf_gain_scale; static GtkWidget *agc_gain_label; static GtkWidget *agc_scale; static GtkWidget *attenuation_label; @@ -111,8 +117,8 @@ void sliders_update() { gtk_range_set_range(GTK_RANGE(mic_gain_scale),0.0,31.0); gtk_range_set_value (GTK_RANGE(mic_gain_scale),linein_gain); } else { - gtk_label_set_text(GTK_LABEL(mic_gain_label),"Mic (dB):"); - gtk_range_set_range(GTK_RANGE(mic_gain_scale),-10.0,50.0); + gtk_label_set_text(GTK_LABEL(mic_gain_label),"Mic:"); + gtk_range_set_range(GTK_RANGE(mic_gain_scale),-12.0,50.0); gtk_range_set_value (GTK_RANGE(mic_gain_scale),mic_gain); } } @@ -368,6 +374,56 @@ void set_af_gain(int rx,double value) { } } +static void rf_gain_value_changed_cb(GtkWidget *widget, gpointer data) { + active_receiver->rf_gain=gtk_range_get_value(GTK_RANGE(af_gain_scale)); +#ifdef SOAPYSDR + if(protocol=SOAPYSDR_PROTOCOL) { + soapy_protocol_set_gain(active_receiver,active_receiver->rf_gain); + } +#endif +} + +void update_rf_gain() { + set_rf_gain(active_receiver->id,active_receiver->rf_gain); +} + +void set_rf_gain(int rx,double value) { + receiver[rx]->rf_gain=value; +#ifdef SOAPYSDR + if(protocol==SOAPYSDR_PROTOCOL) { + soapy_protocol_set_gain(active_receiver,active_receiver->rf_gain); + } +#endif + if(display_sliders) { + gtk_range_set_value (GTK_RANGE(rf_gain_scale),receiver[rx]->rf_gain); + } else { + if(scale_status!=RF_GAIN) { + if(scale_status!=NONE) { + g_source_remove(scale_timer); + gtk_widget_destroy(scale_dialog); + scale_status=NONE; + } + } + if(scale_status==NONE) { + scale_status=RF_GAIN; + scale_dialog=gtk_dialog_new_with_buttons("RF Gain",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); + GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog)); + rf_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 100.0, 1.00); + gtk_widget_set_size_request (rf_gain_scale, 400, 30); + gtk_range_set_value (GTK_RANGE(rf_gain_scale),receiver[rx]->rf_gain); + gtk_widget_show(rf_gain_scale); + gtk_container_add(GTK_CONTAINER(content),rf_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(rf_gain_scale),receiver[rx]->rf_gain); + 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) { @@ -401,16 +457,14 @@ static void micgain_value_changed_cb(GtkWidget *widget, gpointer data) { linein_gain=(int)gtk_range_get_value(GTK_RANGE(widget)); } else { mic_gain=gtk_range_get_value(GTK_RANGE(widget)); - double gain=pow(10.0, mic_gain / 20.0); - SetTXAPanelGain1(transmitter->id,gain); + SetTXAPanelGain1(transmitter->id,pow(10.0, mic_gain/20.0)); } } void set_mic_gain(double value) { if(can_transmit) { mic_gain=value; - double gain=pow(10.0, mic_gain / 20.0); - SetTXAPanelGain1(transmitter->id,gain); + SetTXAPanelGain1(transmitter->id,pow(10.0, mic_gain/20.0)); if(display_sliders) { gtk_range_set_value (GTK_RANGE(mic_gain_scale),mic_gain); } else { @@ -423,9 +477,9 @@ void set_mic_gain(double value) { } if(scale_status==NONE) { scale_status=MIC_GAIN; - scale_dialog=gtk_dialog_new_with_buttons("Mic Gain (dB)",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); + scale_dialog=gtk_dialog_new_with_buttons("Mic Gain",GTK_WINDOW(top_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL); GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog)); - mic_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,-10.0, 50.0, 1.00); + mic_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,-12.0, 50.0, 1.00); gtk_widget_set_size_request (mic_gain_scale, 400, 30); gtk_range_set_value (GTK_RANGE(mic_gain_scale),mic_gain); gtk_widget_show(mic_gain_scale); @@ -759,11 +813,11 @@ fprintf(stderr,"sliders_init: width=%d height=%d\n", width,height); if(can_transmit) { - mic_gain_label=gtk_label_new(mic_linein?"Linein:":"Mic (dB):"); + mic_gain_label=gtk_label_new(mic_linein?"Linein:":"Mic:"); gtk_widget_override_font(mic_gain_label, pango_font_description_from_string("Sans 10")); gtk_grid_attach(GTK_GRID(sliders),mic_gain_label,0,1,1,1); - mic_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,mic_linein?0.0:-10.0,mic_linein?31.0:50.0, 1.0); + mic_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,mic_linein?0.0:1.0,mic_linein?31.0:100.0, 1.0); gtk_widget_override_font(mic_gain_scale, pango_font_description_from_string("Sans 10")); gtk_range_set_value (GTK_RANGE(mic_gain_scale),mic_linein?linein_gain:mic_gain); gtk_grid_attach(GTK_GRID(sliders),mic_gain_scale,1,1,2,1); diff --git a/sliders.h b/sliders.h index 32fef86..bf93e7a 100644 --- a/sliders.h +++ b/sliders.h @@ -34,6 +34,7 @@ extern int update_tune_drive(void *); extern void set_agc_gain(int rx,double value); extern void set_af_gain(int rx,double value); +extern void set_rf_gain(int rx,double value); extern void set_mic_gain(double value); extern void set_drive(double drive); //extern void set_tune(double tune); diff --git a/soapy_protocol.c b/soapy_protocol.c index a556300..fdbaa41 100644 --- a/soapy_protocol.c +++ b/soapy_protocol.c @@ -64,7 +64,6 @@ 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; @@ -163,12 +162,11 @@ fprintf(stderr,"soapy_protocol_start_receiver: create receive_thread\n"); 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,tx->dac,(double)soapy_tx_sample_rate); +fprintf(stderr,"soapy_protocol_create_transmitter: setting samplerate=%f\n",(double)tx->iq_output_rate); + rc=SoapySDRDevice_setSampleRate(soapy_device,SOAPY_SDR_TX,tx->dac,(double)tx->iq_output_rate); if(rc!=0) { - fprintf(stderr,"soapy_protocol_configure_transmitter: SoapySDRDevice_setSampleRate(%f) failed: %s\n",(double)soapy_tx_sample_rate,SoapySDR_errToStr(rc)); + fprintf(stderr,"soapy_protocol_configure_transmitter: SoapySDRDevice_setSampleRate(%f) failed: %s\n",(double)tx->iq_output_rate,SoapySDR_errToStr(rc)); } size_t channel=tx->dac; @@ -354,21 +352,13 @@ fprintf(stderr,"soapy_protocol: receive_thread: SoapySDRDevice_unmake\n"); //_exit(0); } -void soapy_protocol_process_local_mic(unsigned char *buffer,int le) { - int b; +void soapy_protocol_process_local_mic(float *buffer) { int i; short sample; // always 48000 samples per second - b=0; for(i=0;i<720;i++) { - if(le) { - sample = (short) (buffer[b++]&0xFF); - sample |= (short) (buffer[b++]<<8); - } else { - sample = (short)(buffer[b++]<<8); - sample |= (short) (buffer[b++]&0xFF); - } + sample=(short)(buffer[i]*32767.0); #ifdef FREEDV if(active_receiver->freedv) { add_freedv_mic_sample(transmitter,sample); @@ -386,11 +376,12 @@ void soapy_protocol_iq_samples(float isample,float qsample) { int flags=0; long long timeNs=0; long timeoutUs=100000L; - if(isTransmitting(radio)) { + if(isTransmitting()) { output_buffer[output_buffer_index++]=isample; output_buffer[output_buffer_index++]=qsample; if(output_buffer_index>=max_tx_samples) { // write the buffer +//g_print("soapy_protocol_iq_samples: writeStream\n"); 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); @@ -421,10 +412,14 @@ void soapy_protocol_set_rx_frequency(RECEIVER *rx,int v) { } void soapy_protocol_set_tx_frequency(TRANSMITTER *tx) { - int v=active_receiver->id; + int v; int rc; double f; + v=active_receiver->id; + if(split) { + v=active_receiver->id==0?1:0; + } if(soapy_device!=NULL) { //f=(double)(vfo[v].frequency+vfo[v].ctun_frequency-vfo[v].lo_tx); if(vfo[v].ctun) { @@ -432,6 +427,12 @@ void soapy_protocol_set_tx_frequency(TRANSMITTER *tx) { } else { f=(double)(vfo[v].frequency-vfo[v].lo_tx); } + + if(transmitter->xit_enabled) { + f+=(double)(transmitter->xit); + } + + g_print("soapy_protocol_set_tx_frequency: %f\n",f); rc=SoapySDRDevice_setFrequency(soapy_device,SOAPY_SDR_TX,tx->dac,f,NULL); if(rc!=0) { @@ -462,29 +463,52 @@ void soapy_protocol_set_tx_antenna(TRANSMITTER *tx,int ant) { } } -void soapy_protocol_set_gain(RECEIVER *rx,char *name,int gain) { +void soapy_protocol_set_gain(RECEIVER *rx,double gain) { + int rc; +//fprintf(stderr,"soapy_protocol_set_gain: adc=%d gain=%f\n",gain); + rc=SoapySDRDevice_setGain(soapy_device,SOAPY_SDR_RX,rx->adc,gain); + if(rc!=0) { + fprintf(stderr,"soapy_protocol: SoapySDRDevice_setGain failed: %s\n",SoapySDR_errToStr(rc)); + } +} + +void soapy_protocol_set_gain_element(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)); + fprintf(stderr,"soapy_protocol: SoapySDRDevice_setGainElement %s failed: %s\n",name,SoapySDR_errToStr(rc)); + } +} + +void soapy_protocol_set_tx_gain(TRANSMITTER *tx,int gain) { + int rc; + rc=SoapySDRDevice_setGain(soapy_device,SOAPY_SDR_TX,tx->dac,(double)gain); + if(rc!=0) { + fprintf(stderr,"soapy_protocol: SoapySDRDevice_setGain failed: %s\n",SoapySDR_errToStr(rc)); } } -void soapy_protocol_set_tx_gain(TRANSMITTER *tx,char *name,int gain) { +void soapy_protocol_set_tx_gain_element(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)); + fprintf(stderr,"soapy_protocol: SoapySDRDevice_setGainElement %s failed: %s\n",name,SoapySDR_errToStr(rc)); } } -int soapy_protocol_get_gain(RECEIVER *rx,char *name) { +int soapy_protocol_get_gain_element(RECEIVER *rx,char *name) { double gain; gain=SoapySDRDevice_getGainElement(soapy_device,SOAPY_SDR_RX,rx->adc,name); return (int)gain; } +int soapy_protocol_get_tx_gain_element(TRANSMITTER *tx,char *name) { + double gain; + gain=SoapySDRDevice_getGainElement(soapy_device,SOAPY_SDR_TX,tx->dac,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; diff --git a/soapy_protocol.h b/soapy_protocol.h index 39e6c96..22b80a6 100644 --- a/soapy_protocol.h +++ b/soapy_protocol.h @@ -32,8 +32,9 @@ 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_set_gain(RECEIVER *rx,double gain); +void soapy_protocol_set_gain_element(RECEIVER *rx,char *name,int gain); +int soapy_protocol_get_gain_element(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); @@ -42,8 +43,10 @@ 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,int le); +void soapy_protocol_set_tx_gain(TRANSMITTER *tx,int gain); +void soapy_protocol_set_tx_gain_element(TRANSMITTER *tx,char *name,int gain); +int soapy_protocol_get_tx_gain_element(TRANSMITTER *tx,char *name); +void soapy_protocol_process_local_mic(float *buffer); void soapy_protocol_iq_samples(float isample,float qsample); void soapy_protocol_set_mic_sample_rate(int rate); #endif diff --git a/toolbar.c b/toolbar.c index fa210e1..4dbc037 100644 --- a/toolbar.c +++ b/toolbar.c @@ -78,12 +78,26 @@ static GdkRGBA gray; static gint rit_plus_timer=-1; static gint rit_minus_timer=-1; +static gint xit_plus_timer=-1; +static gint xit_minus_timer=-1; static gboolean rit_timer_cb(gpointer data) { int i=GPOINTER_TO_INT(data); vfo[active_receiver->id].rit+=(i*rit_increment); - if(vfo[active_receiver->id].rit>1000) vfo[active_receiver->id].rit=1000; - if(vfo[active_receiver->id].rit<-1000) vfo[active_receiver->id].rit=-1000; + if(vfo[active_receiver->id].rit>10000) vfo[active_receiver->id].rit=10000; + if(vfo[active_receiver->id].rit<-10000) vfo[active_receiver->id].rit=-10000; + if(protocol==NEW_PROTOCOL) { + schedule_high_priority(); + } + g_idle_add(ext_vfo_update,NULL); + return TRUE; +} + +static gboolean xit_timer_cb(gpointer data) { + int i=GPOINTER_TO_INT(data); + transmitter->xit+=(i*rit_increment); + if(transmitter->xit>10000) transmitter->xit=10000; + if(transmitter->xit<-10000) transmitter->xit=-10000; if(protocol==NEW_PROTOCOL) { schedule_high_priority(); } @@ -94,7 +108,11 @@ static gboolean rit_timer_cb(gpointer data) { void update_toolbar_labels() { switch(function) { case 0: - gtk_button_set_label(GTK_BUTTON(sim_mox),"Mox"); + if(can_transmit) { + gtk_button_set_label(GTK_BUTTON(sim_mox),"Mox"); + } else { + gtk_button_set_label(GTK_BUTTON(sim_mox),""); + } gtk_button_set_label(GTK_BUTTON(sim_s1),"Band"); gtk_button_set_label(GTK_BUTTON(sim_s2),"BStack"); gtk_button_set_label(GTK_BUTTON(sim_s3),"Mode"); @@ -104,38 +122,86 @@ void update_toolbar_labels() { set_button_text_color(sim_s1,"black"); set_button_text_color(sim_s2,"black"); break; - case 1: - gtk_button_set_label(GTK_BUTTON(sim_mox),"Mox"); + if(can_transmit) { + gtk_button_set_label(GTK_BUTTON(sim_mox),"Mox"); + } else { + gtk_button_set_label(GTK_BUTTON(sim_mox),""); + } gtk_button_set_label(GTK_BUTTON(sim_s1),"Lock"); gtk_button_set_label(GTK_BUTTON(sim_s2),"CTUN"); gtk_button_set_label(GTK_BUTTON(sim_s3),"A>B"); gtk_button_set_label(GTK_BUTTON(sim_s4),"AB"); - gtk_button_set_label(GTK_BUTTON(sim_s6),"Split"); + if(can_transmit) { + gtk_button_set_label(GTK_BUTTON(sim_s6),"Split"); + } else { + gtk_button_set_label(GTK_BUTTON(sim_s6),""); + } break; case 2: - gtk_button_set_label(GTK_BUTTON(sim_mox),"Mox"); + if(can_transmit) { + gtk_button_set_label(GTK_BUTTON(sim_mox),"Mox"); + } else { + gtk_button_set_label(GTK_BUTTON(sim_mox),""); + } gtk_button_set_label(GTK_BUTTON(sim_s1),"Freq"); gtk_button_set_label(GTK_BUTTON(sim_s2),"Mem"); - //gtk_button_set_label(GTK_BUTTON(sim_s3),"Vox"); gtk_button_set_label(GTK_BUTTON(sim_s3),"RIT"); - gtk_button_set_label(GTK_BUTTON(sim_s4),"RIT+"); gtk_button_set_label(GTK_BUTTON(sim_s5),"RIT-"); gtk_button_set_label(GTK_BUTTON(sim_s6),"RIT CL"); - if(full_tune) { - set_button_text_color(sim_s1,"red"); + break; + case 3: + if(can_transmit) { + gtk_button_set_label(GTK_BUTTON(sim_mox),"Mox"); + } else { + gtk_button_set_label(GTK_BUTTON(sim_mox),""); } - if(memory_tune) { - set_button_text_color(sim_s2,"red"); + gtk_button_set_label(GTK_BUTTON(sim_s1),"Freq"); + gtk_button_set_label(GTK_BUTTON(sim_s2),"Mem"); + if(can_transmit) { + gtk_button_set_label(GTK_BUTTON(sim_s3),"XIT"); + gtk_button_set_label(GTK_BUTTON(sim_s4),"XIT+"); + gtk_button_set_label(GTK_BUTTON(sim_s5),"XIT-"); + gtk_button_set_label(GTK_BUTTON(sim_s6),"XIT CL"); + } else { + gtk_button_set_label(GTK_BUTTON(sim_s3),""); + gtk_button_set_label(GTK_BUTTON(sim_s4),""); + gtk_button_set_label(GTK_BUTTON(sim_s5),""); + gtk_button_set_label(GTK_BUTTON(sim_s6),""); } break; - case 3: - gtk_button_set_label(GTK_BUTTON(sim_mox),"Tune"); - if(OCtune!=0 && OCfull_tune_time!=0) { - gtk_button_set_label(GTK_BUTTON(sim_s1),"Full"); + case 4: + if(can_transmit) { + gtk_button_set_label(GTK_BUTTON(sim_mox),"Mox"); } else { + gtk_button_set_label(GTK_BUTTON(sim_mox),""); + } + gtk_button_set_label(GTK_BUTTON(sim_s1),"Freq"); + if(can_transmit) { + gtk_button_set_label(GTK_BUTTON(sim_s2),"Split"); + gtk_button_set_label(GTK_BUTTON(sim_s3),"Duplex"); + gtk_button_set_label(GTK_BUTTON(sim_s4),"SAT"); + gtk_button_set_label(GTK_BUTTON(sim_s5),"RSAT"); + } else { + gtk_button_set_label(GTK_BUTTON(sim_s2),""); + gtk_button_set_label(GTK_BUTTON(sim_s3),""); + gtk_button_set_label(GTK_BUTTON(sim_s4),""); + gtk_button_set_label(GTK_BUTTON(sim_s5),""); + } + gtk_button_set_label(GTK_BUTTON(sim_s6),""); + break; + case 5: + if(can_transmit) { + gtk_button_set_label(GTK_BUTTON(sim_mox),"Tune"); + if(OCtune!=0 && OCfull_tune_time!=0) { + gtk_button_set_label(GTK_BUTTON(sim_s1),"Full"); + } else { + gtk_button_set_label(GTK_BUTTON(sim_s1),""); + } + } else { + gtk_button_set_label(GTK_BUTTON(sim_mox),""); gtk_button_set_label(GTK_BUTTON(sim_s1),""); } if(OCtune!=0 && OCmemory_tune_time!=0) { @@ -146,7 +212,11 @@ void update_toolbar_labels() { gtk_button_set_label(GTK_BUTTON(sim_s3),"Band"); gtk_button_set_label(GTK_BUTTON(sim_s4),"Mode"); gtk_button_set_label(GTK_BUTTON(sim_s5),"Filter"); - gtk_button_set_label(GTK_BUTTON(sim_s6),"Mox"); + if(can_transmit) { + gtk_button_set_label(GTK_BUTTON(sim_s6),"Mox"); + } else { + gtk_button_set_label(GTK_BUTTON(sim_s6),""); + } if(full_tune) { set_button_text_color(sim_s1,"red"); } @@ -210,13 +280,44 @@ static void aswapb_cb (GtkWidget *widget, gpointer data) { } static void split_cb (GtkWidget *widget, gpointer data) { - split=split==1?0:1; - if(split) { - tx_set_mode(transmitter,vfo[VFO_B].mode); - } else { - tx_set_mode(transmitter,vfo[VFO_A].mode); + if(can_transmit) { + split=split==1?0:1; + if(split) { + tx_set_mode(transmitter,vfo[VFO_B].mode); + } else { + tx_set_mode(transmitter,vfo[VFO_A].mode); + } + g_idle_add(ext_vfo_update,NULL); + } +} + +static void duplex_cb (GtkWidget *widget, gpointer data) { + if(can_transmit) { + duplex=duplex==1?0:1; + g_idle_add(ext_vfo_update,NULL); + } +} + +static void sat_cb (GtkWidget *widget, gpointer data) { + if(can_transmit) { + if(sat_mode==SAT_MODE) { + sat_mode=SAT_NONE; + } else { + sat_mode=SAT_MODE; + } + g_idle_add(ext_vfo_update,NULL); + } +} + +static void rsat_cb (GtkWidget *widget, gpointer data) { + if(can_transmit) { + if(sat_mode==RSAT_MODE) { + sat_mode=SAT_NONE; + } else { + sat_mode=RSAT_MODE; + } + g_idle_add(ext_vfo_update,NULL); } - g_idle_add(ext_vfo_update,NULL); } static void rit_enable_cb(GtkWidget *widget, gpointer data) { @@ -230,8 +331,8 @@ static void rit_enable_cb(GtkWidget *widget, gpointer data) { static void rit_cb(GtkWidget *widget, gpointer data) { int i=GPOINTER_TO_INT(data); vfo[active_receiver->id].rit+=i*rit_increment; - if(vfo[active_receiver->id].rit>1000) vfo[active_receiver->id].rit=1000; - if(vfo[active_receiver->id].rit<-1000) vfo[active_receiver->id].rit=-1000; + if(vfo[active_receiver->id].rit>10000) vfo[active_receiver->id].rit=10000; + if(vfo[active_receiver->id].rit<-10000) vfo[active_receiver->id].rit=-10000; if(protocol==NEW_PROTOCOL) { schedule_high_priority(); } @@ -248,6 +349,41 @@ static void rit_clear_cb(GtkWidget *widget, gpointer data) { g_idle_add(ext_vfo_update,NULL); } +static void xit_enable_cb(GtkWidget *widget, gpointer data) { + if(can_transmit) { + transmitter->xit_enabled=transmitter->xit_enabled==1?0:1; + if(protocol==NEW_PROTOCOL) { + schedule_high_priority(); + } + g_idle_add(ext_vfo_update,NULL); + } +} + +static void xit_cb(GtkWidget *widget, gpointer data) { + if(can_transmit) { + int i=GPOINTER_TO_INT(data); + transmitter->xit+=i*rit_increment; + if(transmitter->xit>10000) transmitter->xit=10000; + if(transmitter->xit<-10000) transmitter->xit=-10000; + if(protocol==NEW_PROTOCOL) { + schedule_high_priority(); + } + g_idle_add(ext_vfo_update,NULL); + if(i<0) { + xit_minus_timer=g_timeout_add(200,xit_timer_cb,(gpointer)(long)i); + } else { + xit_plus_timer=g_timeout_add(200,xit_timer_cb,(gpointer)(long)i); + } + } +} + +static void xit_clear_cb(GtkWidget *widget, gpointer data) { + if(can_transmit) { + transmitter->xit=0; + g_idle_add(ext_vfo_update,NULL); + } +} + static void freq_cb(GtkWidget *widget, gpointer data) { start_vfo(); } @@ -409,6 +545,12 @@ void sim_s1_pressed_cb(GtkWidget *widget, gpointer data) { freq_cb(widget,data); break; case 3: + freq_cb(widget,data); + break; + case 4: + freq_cb(widget,data); + break; + case 5: full_tune=full_tune==1?0:1; if(full_tune) { set_button_text_color(sim_s2,"black"); @@ -430,6 +572,10 @@ void sim_s1_released_cb(GtkWidget *widget, gpointer data) { break; case 3: break; + case 4: + break; + case 5: + break; } } @@ -445,6 +591,12 @@ void sim_s2_pressed_cb(GtkWidget *widget, gpointer data) { mem_cb(widget,data); break; case 3: + mem_cb(widget,data); + break; + case 4: + split_cb(widget,data); + break; + case 5: memory_tune=memory_tune==1?0:1; if(memory_tune) { set_button_text_color(sim_s1,"black"); @@ -466,6 +618,10 @@ void sim_s2_released_cb(GtkWidget *widget, gpointer data) { break; case 3: break; + case 4: + break; + case 5: + break; } } @@ -480,10 +636,15 @@ void sim_s3_pressed_cb(GtkWidget *widget, gpointer data) { atob_cb(widget,data); break; case 2: - //vox_cb(widget,data); rit_enable_cb(widget,data); break; case 3: + xit_enable_cb(widget,data); + break; + case 4: + duplex_cb(widget,data); + break; + case 5: band_cb(widget,data); break; } @@ -499,6 +660,10 @@ void sim_s3_released_cb(GtkWidget *widget, gpointer data) { break; case 3: break; + case 4: + break; + case 5: + break; } } @@ -517,6 +682,14 @@ void sim_s4_pressed_cb(GtkWidget *widget, gpointer data) { } break; case 3: + if(xit_minus_timer==-1 && xit_plus_timer==-1) { + xit_cb(widget,(void *)1); + } + break; + case 4: + sat_cb(widget,data); + break; + case 5: mode_cb(widget,data); break; } @@ -535,6 +708,14 @@ void sim_s4_released_cb(GtkWidget *widget, gpointer data) { } break; case 3: + if(xit_plus_timer!=-1) { + g_source_remove(xit_plus_timer); + xit_plus_timer=-1; + } + break; + case 4: + break; + case 5: break; } } @@ -554,6 +735,14 @@ void sim_s5_pressed_cb(GtkWidget *widget, gpointer data) { } break; case 3: + if(xit_minus_timer==-1 && xit_plus_timer==-1) { + xit_cb(widget,(void *)-1); + } + break; + case 4: + rsat_cb(widget,data); + break; + case 5: filter_cb(widget,data); break; } @@ -572,6 +761,14 @@ void sim_s5_released_cb(GtkWidget *widget, gpointer data) { } break; case 3: + if(xit_minus_timer!=-1) { + g_source_remove(xit_minus_timer); + xit_minus_timer=-1; + } + break; + case 4: + break; + case 5: break; } } @@ -588,6 +785,11 @@ void sim_s6_pressed_cb(GtkWidget *widget, gpointer data) { rit_clear_cb(widget,NULL); break; case 3: + xit_clear_cb(widget,NULL); + break; + case 4: + break; + case 5: break; } } @@ -601,7 +803,10 @@ void sim_s6_released_cb(GtkWidget *widget, gpointer data) { case 2: break; case 3: - mox_cb((GtkWidget *)NULL, (gpointer)NULL); + break; + case 4: + break; + case 5: break; } } @@ -611,9 +816,11 @@ void sim_mox_cb(GtkWidget *widget, gpointer data) { case 0: case 1: case 2: + case 3: + case 4: mox_cb((GtkWidget *)NULL, (gpointer)NULL); break; - case 3: + case 5: tune_cb((GtkWidget *)NULL, (gpointer)NULL); break; } diff --git a/toolbar.h b/toolbar.h index 19b1adf..5a1b887 100644 --- a/toolbar.h +++ b/toolbar.h @@ -20,7 +20,7 @@ #ifndef _TOOLBAR_H #define _TOOLBAR_H -#define MAX_FUNCTION 3 +#define MAX_FUNCTION 5 extern int function; diff --git a/transmitter.c b/transmitter.c index a79f5a7..7a44d4f 100644 --- a/transmitter.c +++ b/transmitter.c @@ -169,10 +169,11 @@ void transmitter_save_state(TRANSMITTER *tx) { sprintf(name,"transmitter.%d.local_microphone",tx->id); sprintf(value,"%d",tx->local_microphone); setProperty(name,value); - sprintf(name,"transmitter.%d.input_device",tx->id); - sprintf(value,"%d",tx->input_device); - setProperty(name,value); - + if(tx->microphone_name!=NULL) { + sprintf(name,"transmitter.%d.microphone_name",tx->id); + sprintf(value,"%s",tx->microphone_name); + setProperty(name,value); + } sprintf(name,"transmitter.%d.low_latency",tx->id); sprintf(value,"%d",tx->low_latency); setProperty(name,value); @@ -230,6 +231,12 @@ void transmitter_save_state(TRANSMITTER *tx) { sprintf(name,"transmitter.%d.compressor_level",tx->id); sprintf(value,"%f",tx->compressor_level); setProperty(name,value); + sprintf(name,"transmitter.%d.xit_enabled",tx->id); + sprintf(value,"%d",tx->xit_enabled); + setProperty(name,value); + sprintf(name,"transmitter.%d.xit",tx->id); + sprintf(value,"%lld",tx->xit); + setProperty(name,value); } void transmitter_restore_state(TRANSMITTER *tx) { @@ -259,9 +266,12 @@ void transmitter_restore_state(TRANSMITTER *tx) { sprintf(name,"transmitter.%d.local_microphone",tx->id); value=getProperty(name); if(value) tx->local_microphone=atoi(value); - sprintf(name,"transmitter.%d.input_device",tx->id); + sprintf(name,"transmitter.%d.microphone_name",tx->id); value=getProperty(name); - if(value) tx->input_device=atoi(value); + if(value) { + tx->microphone_name=g_new(gchar,strlen(value)+1); + strcpy(tx->microphone_name,value); + } sprintf(name,"transmitter.%d.low_latency",tx->id); value=getProperty(name); if(value) tx->low_latency=atoi(value); @@ -317,6 +327,12 @@ void transmitter_restore_state(TRANSMITTER *tx) { sprintf(name,"transmitter.%d.compressor_level",tx->id); value=getProperty(name); if(value) tx->compressor_level=atof(value); + sprintf(name,"transmitter.%d.xit_enabled",tx->id); + value=getProperty(name); + if(value) tx->xit_enabled=atoi(value); + sprintf(name,"transmitter.%d.xit",tx->id); + value=getProperty(name); + if(value) tx->xit=atoll(value); } static gboolean update_display(gpointer data) { @@ -574,9 +590,15 @@ TRANSMITTER *create_transmitter(int id, int buffer_size, int fft_size, int fps, tx->mic_sample_rate=48000; tx->mic_dsp_rate=96000; tx->iq_output_rate=radio_sample_rate; - tx->buffer_size=1024; - tx->output_samples=1024*(tx->iq_output_rate/tx->mic_sample_rate); - tx->pixels=width*8; // to allow 384k to 24k conversion + tx->output_samples=tx->buffer_size*(tx->iq_output_rate/tx->mic_sample_rate); + tx->pixels=width*(tx->iq_output_rate/tx->mic_sample_rate); +/* + tx->mic_sample_rate=48000; + tx->mic_dsp_rate=48000; + tx->iq_output_rate=48000; + tx->output_samples=tx->buffer_size; + tx->pixels=width; // to allow 48k to 24k conversion +*/ break; #endif @@ -594,7 +616,7 @@ TRANSMITTER *create_transmitter(int id, int buffer_size, int fft_size, int fps, tx->alex_antenna=ALEX_TX_ANTENNA_1; -fprintf(stderr,"create_transmitter: id=%d buffer_size=%d mic_sample_rate=%d mic_dsp_rate=%d iq_output_rate=%d output_samples=%d fps=%d\n",tx->id, tx->buffer_size, tx->mic_sample_rate, tx->mic_dsp_rate, tx->iq_output_rate, tx->output_samples,tx->fps); +fprintf(stderr,"create_transmitter: id=%d buffer_size=%d mic_sample_rate=%d mic_dsp_rate=%d iq_output_rate=%d output_samples=%d fps=%d width=%d height=%d\n",tx->id, tx->buffer_size, tx->mic_sample_rate, tx->mic_dsp_rate, tx->iq_output_rate, tx->output_samples,tx->fps,tx->width,tx->height); tx->filter_low=tx_filter_low; tx->filter_high=tx_filter_high; @@ -629,6 +651,10 @@ fprintf(stderr,"create_transmitter: id=%d buffer_size=%d mic_sample_rate=%d mic_ tx->compressor_level=0.0; tx->local_microphone=0; + tx->microphone_name=NULL; + + tx->xit_enabled=FALSE; + tx->xit=0LL; transmitter_restore_state(tx); @@ -716,8 +742,7 @@ fprintf(stderr,"transmitter: allocate buffers: mic_input_buffer=%p iq_output_buf SetTXAPostGenToneFreq(tx->id, 0.0); SetTXAPostGenRun(tx->id, 0); - double gain=pow(10.0, mic_gain / 20.0); - SetTXAPanelGain1(tx->id,gain); + SetTXAPanelGain1(tx->id,pow(10.0, mic_gain/20.0)); SetTXAPanelRun(tx->id, 1); SetTXAFMDeviation(tx->id, (double)tx->deviation); @@ -755,7 +780,9 @@ void tx_set_filter(TRANSMITTER *tx,int low,int high) { } else { mode=vfo[0].mode; } -//fprintf(stderr,"tx_set_filter: tx=%p mode=%d low=%d high=%d\n",tx,mode,low,high); + +fprintf(stderr,"tx_set_filter: tx=%p mode=%s low=%d high=%d\n",tx,mode_string[mode],low,high); + switch(mode) { case modeLSB: case modeCWL: @@ -793,6 +820,7 @@ void tx_set_filter(TRANSMITTER *tx,int low,int high) { double fl=tx->filter_low; double fh=tx->filter_high; +/* if(split) { fl+=vfo[VFO_B].offset; fh+=vfo[VFO_B].offset; @@ -800,6 +828,7 @@ void tx_set_filter(TRANSMITTER *tx,int low,int high) { fl+=vfo[VFO_A].offset; fh+=vfo[VFO_A].offset; } +*/ SetTXABandpassFreqs(tx->id, fl,fh); } @@ -958,8 +987,14 @@ static void full_tx_buffer(TRANSMITTER *tx) { // Original code without pulse shaping and without side tone // for(j=0;joutput_samples;j++) { - double is=tx->iq_output_buffer[j*2]; - double qs=tx->iq_output_buffer[(j*2)+1]; + double is,qs; + if(iqswap) { + qs=tx->iq_output_buffer[j*2]; + qs=tx->iq_output_buffer[(j*2)+1]; + } else { + is=tx->iq_output_buffer[j*2]; + qs=tx->iq_output_buffer[(j*2)+1]; + } isample=is>=0.0?(long)floor(is*gain+0.5):(long)ceil(is*gain-0.5); qsample=qs>=0.0?(long)floor(qs*gain+0.5):(long)ceil(qs*gain-0.5); switch(protocol) { @@ -971,7 +1006,7 @@ static void full_tx_buffer(TRANSMITTER *tx) { break; #ifdef SOAPYSDR case SOAPYSDR_PROTOCOL: - soapy_protocol_iq_samples((float)tx->iq_output_buffer[j*2],(float)tx->iq_output_buffer[(j*2)+1]); + soapy_protocol_iq_samples((float)isample,(float)qsample); break; #endif } diff --git a/transmitter.h b/transmitter.h index 3886824..83c15a3 100644 --- a/transmitter.h +++ b/transmitter.h @@ -49,12 +49,6 @@ typedef struct _transmitter { int filter_low; int filter_high; -/* - long long frequency; - long long display_frequency; - long long dds_frequency; - long long dds_offset; -*/ int alex_antenna; int width; @@ -69,7 +63,7 @@ typedef struct _transmitter { cairo_surface_t *panadapter_surface; int local_microphone; - int input_device; + gchar *microphone_name; int out_of_band; gint out_of_band_timer_id; @@ -111,6 +105,9 @@ typedef struct _transmitter { double rev; double alc; + gint xit_enabled; + long long xit; + int x; int y; diff --git a/tx_menu.c b/tx_menu.c index 760eb10..2528754 100644 --- a/tx_menu.c +++ b/tx_menu.c @@ -27,11 +27,9 @@ #include "ext.h" static GtkWidget *parent_window=NULL; - static GtkWidget *dialog=NULL; - static GtkWidget *last_filter; - +static GtkWidget *input; static GtkWidget *micin_b=NULL; static GtkWidget *linein_b=NULL; static GtkWidget *micboost_b=NULL; @@ -114,6 +112,11 @@ static void tune_percent_cb (GtkWidget *widget, gpointer data) { static void local_microphone_cb(GtkWidget *widget, gpointer data) { if(gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) { + if(transmitter->microphone_name==NULL) { + int i=gtk_combo_box_get_active(GTK_COMBO_BOX(input)); + transmitter->microphone_name=g_new(gchar,strlen(input_devices[i].name)+1); + strcpy(transmitter->microphone_name,input_devices[i].name); + } if(audio_open_input()==0) { transmitter->local_microphone=1; if(micin_b!=NULL) gtk_widget_hide(micin_b); @@ -148,12 +151,20 @@ static void linein_changed(GtkWidget *widget, gpointer data) { } static void local_input_changed_cb(GtkWidget *widget, gpointer data) { - transmitter->input_device=(int)(long)data; + int i=GPOINTER_TO_INT(data); if(transmitter->local_microphone) { audio_close_input(); - if(audio_open_input()==0) { - transmitter->local_microphone=1; - } else { + } + + if(transmitter->microphone_name!=NULL) { + g_free(transmitter->microphone_name); + } + + transmitter->microphone_name=g_new(gchar,strlen(input_devices[i].name)+1); + strcpy(transmitter->microphone_name,input_devices[i].name); + + if(transmitter->local_microphone) { + if(audio_open_input()<0) { transmitter->local_microphone=0; } } @@ -233,22 +244,24 @@ void tx_menu(GtkWidget *parent) { row++; col=0; - GtkWidget *comp_enable=gtk_check_button_new_with_label("Compression (dB):"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (comp_enable), transmitter->compressor); - gtk_grid_attach(GTK_GRID(grid),comp_enable,col,row,1,1); - g_signal_connect(comp_enable,"toggled",G_CALLBACK(comp_enable_cb),NULL); + } - col++; - GtkWidget *comp=gtk_spin_button_new_with_range(0.0,20.0,1.0); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(comp),(double)transmitter->compressor_level); - gtk_grid_attach(GTK_GRID(grid),comp,col,row,1,1); - g_signal_connect(comp,"value-changed",G_CALLBACK(comp_cb),NULL); + GtkWidget *comp_enable=gtk_check_button_new_with_label("Compression (dB):"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (comp_enable), transmitter->compressor); + gtk_grid_attach(GTK_GRID(grid),comp_enable,col,row,1,1); + g_signal_connect(comp_enable,"toggled",G_CALLBACK(comp_enable_cb),NULL); - row++; - col=0; + col++; + + GtkWidget *comp=gtk_spin_button_new_with_range(0.0,20.0,1.0); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(comp),(double)transmitter->compressor_level); + gtk_grid_attach(GTK_GRID(grid),comp,col,row,1,1); + g_signal_connect(comp,"value-changed",G_CALLBACK(comp_cb),NULL); + + row++; + col=0; - } if(n_input_devices>0) { GtkWidget *local_microphone_b=gtk_check_button_new_with_label("Local Microphone Input"); @@ -257,14 +270,14 @@ void tx_menu(GtkWidget *parent) { gtk_grid_attach(GTK_GRID(grid),local_microphone_b,col,row++,2,1); g_signal_connect(local_microphone_b,"toggled",G_CALLBACK(local_microphone_cb),NULL); - if(transmitter->input_device==-1) { - transmitter->input_device=0; - } - - GtkWidget *input=NULL; + input=NULL; for(i=0;iinput_device==i); + input=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(input),input_devices[i].description); + if(transmitter->microphone_name!=NULL) { + if(strcmp(transmitter->microphone_name,input_devices[i].description)==0) { + gtk_combo_box_set_active(GTK_COMBO_BOX(input),i); + } + } gtk_widget_show(input); gtk_grid_attach(GTK_GRID(grid),input,col,row++,2,1); g_signal_connect(input,"pressed",G_CALLBACK(local_input_changed_cb),(gpointer)(long)i); @@ -325,7 +338,7 @@ void tx_menu(GtkWidget *parent) { col++; - GtkWidget *panadapter_low_r=gtk_spin_button_new_with_range(-220.0,100.0,1.0); + GtkWidget *panadapter_low_r=gtk_spin_button_new_with_range(-400.0,100.0,1.0); gtk_spin_button_set_value(GTK_SPIN_BUTTON(panadapter_low_r),(double)transmitter->panadapter_low); gtk_widget_show(panadapter_low_r); gtk_grid_attach(GTK_GRID(grid),panadapter_low_r,col,row,1,1); diff --git a/tx_panadapter.c b/tx_panadapter.c index efa8a84..e78ea10 100644 --- a/tx_panadapter.c +++ b/tx_panadapter.c @@ -62,6 +62,7 @@ tx_panadapter_configure_event_cb (GtkWidget *widget, int display_width=gtk_widget_get_allocated_width (tx->panadapter); int display_height=gtk_widget_get_allocated_height (tx->panadapter); +g_print("tx_panadapter_configure_event_cb: width=%d height=%d\n",display_width,display_height); if (tx->panadapter_surface) cairo_surface_destroy (tx->panadapter_surface); @@ -251,7 +252,12 @@ void tx_panadapter_update(TRANSMITTER *tx) { //long long half=12000LL; //(long long)(tx->output_rate/2); long long half=24000LL; //(long long)(tx->output_rate/2); long long frequency; - frequency=vfo[id].frequency+vfo[id].offset; + //frequency=vfo[id].frequency+vfo[id].offset; + if(vfo[id].ctun) { + frequency=vfo[id].ctun_frequency-vfo[id].lo_tx; + } else { + frequency=vfo[id].frequency-vfo[id].lo_tx; + } double vfofreq=(double)display_width * 0.5; if (!cw_is_on_vfo_freq) { if(vfo[id].mode==modeCWU) { @@ -315,8 +321,10 @@ void tx_panadapter_update(TRANSMITTER *tx) { cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); cairo_set_line_width(cr, 1.0); //fprintf(stderr,"cursor: x=%f\n",(double)(display_width/2.0)+(vfo[tx->id].offset/hz_per_pixel)); - cairo_move_to(cr,vfofreq+(vfo[id].offset/hz_per_pixel),0.0); - cairo_line_to(cr,vfofreq+(vfo[id].offset/hz_per_pixel),(double)display_height); + //cairo_move_to(cr,vfofreq+(vfo[id].offset/hz_per_pixel),0.0); + //cairo_line_to(cr,vfofreq+(vfo[id].offset/hz_per_pixel),(double)display_height); + cairo_move_to(cr,vfofreq,0.0); + cairo_line_to(cr,vfofreq,(double)display_height); cairo_stroke(cr); // signal @@ -328,13 +336,16 @@ void tx_panadapter_update(TRANSMITTER *tx) { switch(protocol) { case ORIGINAL_PROTOCOL: - //offset=(tx->pixels/4)*1; offset=0; break; case NEW_PROTOCOL: - //offset=(tx->pixels/16)*7; offset=(tx->pixels/8)*3; break; +#ifdef SOAPYSDR + case SOAPYSDR_PROTOCOL: + offset=(tx->pixels/16)*7; + break; +#endif } s1=(double)samples[0+offset]; diff --git a/version.c b/version.c index 06ccee0..b81b88f 100644 --- a/version.c +++ b/version.c @@ -21,11 +21,11 @@ char build_date[]=GIT_DATE; char build_version[]=GIT_VERSION; #if defined (CONTROLLER2_V1) -char version[]="2.0.0 (Controller2 V1)"; +char version[]="2.0.1 (Controller2 V1)"; #elif defined (CONTROLLER2_V2) -char version[]="2.0.0 (Controller2 V2)"; +char version[]="2.0.1 (Controller2 V2)"; #elif defined (GPIO) -char version[]="2.0.0 (Controller1)"; +char version[]="2.0.1 (Controller1)"; #else -char version[]="2.0.0"; +char version[]="2.0.1"; #endif diff --git a/vfo.c b/vfo.c index 006c4e4..9097885 100644 --- a/vfo.c +++ b/vfo.c @@ -291,6 +291,8 @@ void vfo_band_changed(int b) { vfo[id].lo=band->frequencyLO+band->errorLO; vfo[id].lo_tx=band->txFrequencyLO+band->txErrorLO; + // turn off ctun + vfo[id].ctun=0; switch(id) { case 0: @@ -550,6 +552,29 @@ void vfo_step(int steps) { } else { vfo[id].frequency=vfo[id].frequency+(steps*step); } + + int sid=id==0?1:0; + switch(sat_mode) { + case SAT_NONE: + break; + case SAT_MODE: + // A and B increment and decrement together + if(vfo[sid].ctun) { + vfo[sid].ctun_frequency=vfo[sid].ctun_frequency+(steps*step); + } else { + vfo[sid].frequency=vfo[sid].frequency+(steps*step); + } + break; + case RSAT_MODE: + // A increments and B decrements or A decrments and B increments + if(vfo[sid].ctun) { + vfo[sid].ctun_frequency=vfo[sid].ctun_frequency-(steps*step); + } else { + vfo[sid].frequency=vfo[sid].frequency-(steps*step); + } + break; + } + receiver_frequency_changed(active_receiver); #ifdef INCLUDED BANDSTACK_ENTRY* entry=bandstack_entry_get_current(); @@ -561,20 +586,31 @@ void vfo_step(int steps) { void vfo_move(long long hz) { int id=active_receiver->id; +g_print("vfo_move: id=%d hz=%lld\n",id,hz); if(!locked) { - switch(protocol) { -/* -#ifdef SOAPYSDR - case SOAPYSDR_PROTOCOL: - vfo[id].ctun_frequency=((vfo[id].ctun_frequency-hz)/step)*step; + if(vfo[id].ctun) { + vfo[id].ctun_frequency=((vfo[id].ctun_frequency+hz)/step)*step; + } else { + vfo[id].frequency=((vfo[id].frequency+hz)/step)*step; + } + int sid=id==0?1:0; + switch(sat_mode) { + case SAT_NONE: break; -#endif -*/ - default: - if(vfo[id].ctun) { - vfo[id].ctun_frequency=((vfo[id].ctun_frequency-hz)/step)*step; + case SAT_MODE: + // A and B increment and decrement together + if(vfo[sid].ctun) { + vfo[sid].ctun_frequency=((vfo[sid].ctun_frequency+hz)/step)*step; } else { - vfo[id].frequency=((vfo[id].frequency+hz)/step)*step; + vfo[sid].frequency=((vfo[sid].frequency+hz)/step)*step; + } + break; + case RSAT_MODE: + // A increments and B decrements or A decrments and B increments + if(vfo[sid].ctun) { + vfo[sid].ctun_frequency=((vfo[sid].ctun_frequency-hz)/step)*step; + } else { + vfo[sid].frequency=((vfo[sid].frequency-hz)/step)*step; } break; } @@ -584,27 +620,64 @@ void vfo_move(long long hz) { } void vfo_move_to(long long hz) { + // hz is the offset from the min frequency int id=active_receiver->id; + long long offset=(hz/step)*step; + long long half=(long long)(active_receiver->sample_rate/2); + long long f=vfo[id].frequency-half+offset; + long long diff; + +g_print("vfo_move_to: id=%d hz=%lld f=%lld\n",id,hz,f); + if(!locked) { - switch(protocol) { - default: - if(vfo[id].ctun) { - vfo[id].ctun_frequency=(vfo[id].frequency+hz)/step*step; - if(vfo[id].mode==modeCWL) { - vfo[id].ctun_frequency+=cw_keyer_sidetone_frequency; - } else if(vfo[id].mode==modeCWU) { - vfo[id].ctun_frequency-=cw_keyer_sidetone_frequency; - } + if(vfo[id].ctun) { + diff=f-vfo[id].ctun_frequency; + vfo[id].ctun_frequency=f; + if(vfo[id].mode==modeCWL) { + vfo[id].ctun_frequency+=cw_keyer_sidetone_frequency; + } else if(vfo[id].mode==modeCWU) { + vfo[id].ctun_frequency-=cw_keyer_sidetone_frequency; + } +g_print("vfo_move_to: vfo=%d ctun_frequency=%lld diff=%lld\n",id,vfo[id].ctun_frequency,diff); + } else { + diff=f-vfo[id].frequency; + vfo[id].frequency=f; + if(vfo[id].mode==modeCWL) { + vfo[id].frequency+=cw_keyer_sidetone_frequency; + } else if(vfo[id].mode==modeCWU) { + vfo[id].frequency-=cw_keyer_sidetone_frequency; + } +g_print("vfo_move_to: vfo=%d frequency=%lld diff==%%ld\n",id,vfo[id].frequency,diff); + } + + int sid=id==0?1:0; + switch(sat_mode) { + case SAT_NONE: + break; + case SAT_MODE: + f=vfo[sid].frequency-half+offset; + // A and B increment and decrement together + if(vfo[sid].ctun) { + vfo[sid].ctun_frequency+=diff; +g_print("vfo_move_to: SAT vfo=%d ctun_frequency=%lld\n",sid,vfo[sid].ctun_frequency); } else { - vfo[id].frequency=(vfo[id].frequency+hz)/step*step; - if(vfo[id].mode==modeCWL) { - vfo[id].frequency+=cw_keyer_sidetone_frequency; - } else if(vfo[id].mode==modeCWU) { - vfo[id].frequency-=cw_keyer_sidetone_frequency; - } + vfo[sid].frequency+=diff; +g_print("vfo_move_to: SAT vfo=%d frequency=%lld\n",sid,vfo[sid].frequency); + } + break; + case RSAT_MODE: + f=vfo[sid].frequency+half-offset; + // A increments and B decrements or A decrements and B increments + if(vfo[sid].ctun) { + vfo[sid].ctun_frequency-=diff; +g_print("vfo_move_to: RSAT vfo=%d ctun_frequency=%lld\n",sid,vfo[sid].ctun_frequency); + } else { + vfo[sid].frequency-=diff; +g_print("vfo_move_to: RSAT vfo=%d frequency=%lld\n",sid,vfo[sid].frequency); } break; } + receiver_vfo_changed(active_receiver); #ifdef INCLUDED @@ -745,7 +818,21 @@ void vfo_update() { // id == 1, split == 1 : TX freq = VFO_A - long long af=vfo[0].frequency+vfo[0].offset; + long long af; + if(isTransmitting() && !split) { + if(vfo[0].ctun) { + af=(double)(vfo[0].ctun_frequency-vfo[0].lo_tx); + } else { + af=(double)(vfo[0].frequency-vfo[0].lo_tx); + } + } else { + if(vfo[0].ctun) { + af=(double)(vfo[0].ctun_frequency); + } else { + af=(double)(vfo[0].frequency); + } + } + sprintf(temp_text,"VFO A: %0lld.%06lld",af/(long long)1000000,af%(long long)1000000); if(isTransmitting() && ((id == 0 && !split) || (id == 1 && split))) { if (transmitter->out_of_band) sprintf(temp_text,"VFO A: Out of band"); @@ -762,7 +849,20 @@ void vfo_update() { cairo_show_text(cr, temp_text); - long long bf=vfo[1].frequency+vfo[1].offset; + long long bf; + if(isTransmitting() && split) { + if(vfo[1].ctun) { + bf=(double)(vfo[1].ctun_frequency-vfo[1].lo_tx); + } else { + bf=(double)(vfo[1].frequency-vfo[1].lo_tx); + } + } else { + if(vfo[1].ctun) { + bf=(double)(vfo[1].ctun_frequency); + } else { + bf=(double)(vfo[1].frequency); + } + } sprintf(temp_text,"VFO B: %0lld.%06lld",bf/(long long)1000000,bf%(long long)1000000); if(isTransmitting() && ((id == 0 && split) || (id == 1 && !split))) { if (transmitter->out_of_band) sprintf(temp_text,"VFO B: Out of band"); @@ -774,23 +874,50 @@ void vfo_update() { cairo_set_source_rgb(cr, 0.0, 0.65, 0.0); } } - cairo_move_to(cr, 260, 38); + cairo_move_to(cr, 270, 38); cairo_show_text(cr, temp_text); +#ifdef PURESIGNAL + if(can_transmit) { + cairo_move_to(cr, 180, 15); + if(transmitter->puresignal) { + cairo_set_source_rgb(cr, 1.0, 1.0, 0.0); + } else { + cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); + } + cairo_set_font_size(cr, 12); + cairo_show_text(cr, "PS"); + } +#endif + + if(vfo[id].rit_enabled==0) { cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); } else { - cairo_set_source_rgb(cr, 1.0, 1.0, 0.0); + cairo_set_source_rgb(cr, 0.0, 1.0, 0.0); } - sprintf(temp_text,"RIT: %lld Hz",vfo[id].rit); + sprintf(temp_text,"RIT: %lldHz",vfo[id].rit); cairo_move_to(cr, 210, 15); cairo_set_font_size(cr, 12); cairo_show_text(cr, temp_text); + + if(can_transmit) { + if(transmitter->xit_enabled==0) { + cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); + } else { + cairo_set_source_rgb(cr, 1.0, 0.0, 0.0); + } + sprintf(temp_text,"XIT: %lldHz",transmitter->xit); + cairo_move_to(cr, 310, 15); + cairo_set_font_size(cr, 12); + cairo_show_text(cr, temp_text); + } + // NB and NB2 are mutually exclusive, therefore // they are put to the same place in order to save // some space - cairo_move_to(cr, 150, 50); + cairo_move_to(cr, 155, 50); if(active_receiver->nb) { cairo_set_source_rgb(cr, 1.0, 1.0, 0.0); cairo_show_text(cr, "NB"); @@ -831,7 +958,8 @@ void vfo_update() { } cairo_show_text(cr, "SNB"); - cairo_move_to(cr, 300, 50); + //cairo_move_to(cr, 300, 50); + cairo_move_to(cr, 270, 50); switch(active_receiver->agc) { case AGC_OFF: cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); @@ -860,7 +988,8 @@ void vfo_update() { // we should display the compressor (level) // if(can_transmit) { - cairo_move_to(cr, 400, 50); + //cairo_move_to(cr, 400, 50); + cairo_move_to(cr, 330, 50); if (transmitter->compressor) { sprintf(temp_text,"CMPR %d dB",(int) transmitter->compressor_level); cairo_set_source_rgb(cr, 1.0, 1.0, 0.0); @@ -884,7 +1013,8 @@ void vfo_update() { s++; } sprintf(temp_text,"Step %s",step_labels[s]); - cairo_move_to(cr, 300, 15); + //cairo_move_to(cr, 300, 15); + cairo_move_to(cr, 400, 15); cairo_set_source_rgb(cr, 1.0, 1.0, 0.0); cairo_show_text(cr, temp_text); @@ -894,7 +1024,8 @@ void vfo_update() { cairo_show_text(cr, getFrequencyInfo(af)); */ - cairo_move_to(cr, 400, 15); + //cairo_move_to(cr, 400, 15); + cairo_move_to(cr, 430, 50); if(vfo[id].ctun) { cairo_set_source_rgb(cr, 1.0, 1.0, 0.0); } else { @@ -902,7 +1033,8 @@ void vfo_update() { } cairo_show_text(cr, "CTUN"); - cairo_move_to(cr, 450, 15); + //cairo_move_to(cr, 450, 15); + cairo_move_to(cr, 470, 50); if(cat_control>0) { cairo_set_source_rgb(cr, 1.0, 1.0, 0.0); } else { @@ -934,19 +1066,28 @@ void vfo_update() { } cairo_show_text(cr, "Split"); -#ifdef PURESIGNAL - if(can_transmit) { - cairo_move_to(cr, 105, 50); - if(transmitter->puresignal) { - 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, "PS"); + cairo_move_to(cr, 95, 50); + if(sat_mode!=SAT_NONE) { + cairo_set_source_rgb(cr, 1.0, 0.0, 0.0); + } else { + cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); + } + if(sat_mode==SAT_NONE || sat_mode==SAT_MODE) { + cairo_show_text(cr, "SAT"); + } else { + cairo_show_text(cr, "RSAT"); } -#endif + if(duplex) { + cairo_set_source_rgb(cr, 1.0, 0.0, 0.0); + } else { + cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); + } + sprintf(temp_text,"DUP"); + cairo_move_to(cr, 130, 50); + cairo_set_font_size(cr, 12); + cairo_show_text(cr, temp_text); cairo_destroy (cr); gtk_widget_queue_draw (vfo_panel); diff --git a/vfo.h b/vfo.h index c221885..310e35c 100644 --- a/vfo.h +++ b/vfo.h @@ -37,6 +37,7 @@ struct _vfo { int ctun; long long ctun_frequency; + int rit_enabled; long long rit; diff --git a/vfo_menu.c b/vfo_menu.c index 0e5b1da..3f5da0d 100644 --- a/vfo_menu.c +++ b/vfo_menu.c @@ -325,10 +325,12 @@ void vfo_menu(GtkWidget *parent) { #endif #ifdef PURESIGNAL - GtkWidget *enable_ps=gtk_check_button_new_with_label("Enable Pure Signal"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (enable_ps), transmitter->puresignal); - gtk_grid_attach(GTK_GRID(grid),enable_ps,3,7,1,1); - g_signal_connect(enable_ps,"toggled",G_CALLBACK(enable_ps_cb),NULL); + if(can_transmit) { + GtkWidget *enable_ps=gtk_check_button_new_with_label("Enable Pure Signal"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (enable_ps), transmitter->puresignal); + gtk_grid_attach(GTK_GRID(grid),enable_ps,3,7,1,1); + g_signal_connect(enable_ps,"toggled",G_CALLBACK(enable_ps_cb),NULL); + } #endif gtk_container_add(GTK_CONTAINER(content),grid); diff --git a/xvtr_menu.c b/xvtr_menu.c index d825818..5d5534a 100644 --- a/xvtr_menu.c +++ b/xvtr_menu.c @@ -96,10 +96,10 @@ 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); +//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); +//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;