From 62605ef757d6256180edabbf01a8832787825f4b Mon Sep 17 00:00:00 2001 From: c vw Date: Thu, 15 Dec 2022 18:10:03 +0100 Subject: [PATCH] Some "brain-storming" on setting a new frequency --- radio.c | 52 ++++----------------------------- radio.h | 4 +-- receiver.c | 70 +++++++++++++++++++++++++++++++++------------ receiver.h | 1 + vfo.c | 84 +++++++++++++++++++++++++++++++++++++++++++++--------- vfo.h | 9 +++--- 6 files changed, 132 insertions(+), 88 deletions(-) diff --git a/radio.c b/radio.c index 6c9193a..2537c36 100644 --- a/radio.c +++ b/radio.c @@ -1368,7 +1368,7 @@ void start_radio() { soapy_protocol_set_gain(rx); if(vfo[0].ctun) { - setFrequency(vfo[0].ctun_frequency); + receiver_set_frequency(rx,vfo[0].ctun_frequency); } soapy_protocol_start_receiver(rx); @@ -1845,52 +1845,6 @@ int isTransmitting() { return mox | vox | tune; } -void setFrequency(long long f) { - int v=active_receiver->id; - vfo[v].band=get_band_from_frequency(f); - - if(vfo[v].ctun) { - // - // If new frequency is within "window", change the CTUN frequency and - // update the offset. If it is outside, deactivate CTUN and fall - // through - // - long long minf=vfo[v].frequency-(long long)(active_receiver->sample_rate/2); - long long maxf=vfo[v].frequency+(long long)(active_receiver->sample_rate/2); - if(f > minf && f < maxf) { - vfo[v].ctun_frequency=f; - vfo[v].offset=f-vfo[v].frequency; - set_offset(active_receiver,vfo[v].offset); - return; - } - vfo[v].ctun=0; - vfo[v].ctun_frequency=0; - vfo[v].offset=0; - set_offset(active_receiver,vfo[v].offset); - } - vfo[v].frequency=f; - - switch(protocol) { - case NEW_PROTOCOL: - schedule_high_priority(); - break; - case ORIGINAL_PROTOCOL: - break; -#ifdef SOAPYSDR - case SOAPYSDR_PROTOCOL: - if(!vfo[v].ctun) { - soapy_protocol_set_rx_frequency(active_receiver,v); - vfo[v].offset=0; - } - break; -#endif - } -} - -long long getFrequency() { - return vfo[active_receiver->id].frequency; -} - double getDrive() { return transmitter->drive; } @@ -2041,6 +1995,10 @@ void set_alex_attenuation(int v) { } } +void radio_split_toggle() { + radio_set_split(!split); +} + void radio_set_split(int val) { // // "split" *must only* be set through this interface, diff --git a/radio.h b/radio.h index af7647b..3e6294a 100644 --- a/radio.h +++ b/radio.h @@ -338,6 +338,7 @@ extern void radio_change_receivers(int r); extern void radio_change_sample_rate(int rate); extern void set_alex_antennas(void); extern void tx_vfo_changed(void); +extern void radio_split_toggle(); extern void radio_set_split(int v); extern void setMox(int state); extern int getMox(void); @@ -360,9 +361,6 @@ extern void set_alex_attenuation(int v); extern int isTransmitting(void); -extern void setFrequency(long long f); -extern long long getFrequency(void); - extern void radioRestoreState(void); extern void radioSaveState(void); diff --git a/receiver.c b/receiver.c index 8fa9175..d043d89 100644 --- a/receiver.c +++ b/receiver.c @@ -1322,20 +1322,46 @@ g_print("%s: id=%d rate=%d scale=%d buffer_size=%d output_samples=%d\n",__FUNCTI g_print("%s: id=%d rate=%d buffer_size=%d output_samples=%d\n",__FUNCTION__,rx->id, rx->sample_rate, rx->buffer_size, rx->output_samples); } +void receiver_set_frequency(RECEIVER *rx, long long f) { + int id=rx->id; + + // + // update VFO, and let receiver_frequency_changed do the rest + // + vfo[id].band=get_band_from_frequency(f); + if(vfo[id].ctun) { + vfo[id].ctun_frequency=f; + } else { + vfo[id].frequency=f; + } + receiver_frequency_changed(rx); +} + void receiver_frequency_changed(RECEIVER *rx) { int id=rx->id; if(vfo[id].ctun) { + int ctun_ok=1; + long long frequency=vfo[id].frequency; + long long half=(long long)rx->sample_rate/2LL; + long long rx_low=vfo[id].ctun_frequency+rx->filter_low; + long long rx_high=vfo[id].ctun_frequency+rx->filter_high; + if (rx_low < frequency - half || rx_high > frequency+half) { + // + // Perhaps this is paranoia, but a "legal" VFO might turn + // into an "illegal" when when reducing the sample rate, + // thus narrowing the CTUN window + // + g_print("%s: CTUN freq out of range\n", __FUNCTION__); + vfo[id].frequency=vfo[id].ctun_frequency; + ctun_ok=0; + } if(rx->zoom>1) { // // Adjust PAN if new filter width has moved out of // current display range // - long long frequency=vfo[id].frequency; - long long half=(long long)rx->sample_rate/2LL; - long long rx_low=vfo[id].ctun_frequency+rx->filter_low; - long long rx_high=vfo[id].ctun_frequency+rx->filter_high; long long min_display=frequency-half+(long long)((double)rx->pan*rx->hz_per_pixel); long long max_display=min_display+(long long)((double)rx->width*rx->hz_per_pixel); if(rx_low<=min_display) { @@ -1350,28 +1376,31 @@ void receiver_frequency_changed(RECEIVER *rx) { } // - // The (HPSDR) frequency does not change in CTUN, - // so simply compute new offset and tell WDSP about it + // Compute new offset and tell WDSP about it // vfo[id].offset=vfo[id].ctun_frequency-vfo[id].frequency; if(vfo[id].rit_enabled) { vfo[id].offset+=vfo[id].rit; } set_offset(rx,vfo[id].offset); - } else { - switch(protocol) { - case ORIGINAL_PROTOCOL: - // P1 does this automatically - break; - case NEW_PROTOCOL: - schedule_high_priority(); // send new frequency - break; + // + // If we have changed the CTUN center frequency, + // we cannot return but must tell the radio about it + // + if (ctun_ok) return; + } + switch(protocol) { + case ORIGINAL_PROTOCOL: + // P1 does this automatically + break; + case NEW_PROTOCOL: + schedule_high_priority(); // send new frequency + break; #if SOAPYSDR - case SOAPYSDR_PROTOCOL: - soapy_protocol_set_rx_frequency(rx,id); - break; + case SOAPYSDR_PROTOCOL: + soapy_protocol_set_rx_frequency(rx,id); + break; #endif - } } } @@ -1390,9 +1419,12 @@ void receiver_mode_changed(RECEIVER *rx) { } void receiver_vfo_changed(RECEIVER *rx) { + // + // Called when the VFO controlling rx has changed, + // e.g. after a "swap VFO" action + // receiver_frequency_changed(rx); receiver_mode_changed(rx); - //receiver_filter_changed(rx); } static void process_rx_buffer(RECEIVER *rx) { diff --git a/receiver.h b/receiver.h index 41d580c..c596b7d 100644 --- a/receiver.h +++ b/receiver.h @@ -180,6 +180,7 @@ extern RECEIVER *create_pure_signal_receiver(int id, int buffer_size,int sample_ extern RECEIVER *create_receiver(int id, int buffer_size, int fft_size, int pixels, int fps, int width, int height); extern void receiver_change_sample_rate(RECEIVER *rx,int sample_rate); extern void receiver_change_adc(RECEIVER *rx,int adc); +extern void receiver_set_frequency(RECEIVER *rx, long long frequency); extern void receiver_frequency_changed(RECEIVER *rx); extern void receiver_mode_changed(RECEIVER *rx); extern void receiver_filter_changed(RECEIVER *rx); diff --git a/vfo.c b/vfo.c index 79d948f..ea7c726 100644 --- a/vfo.c +++ b/vfo.c @@ -1533,22 +1533,78 @@ void vfo_set_frequency(int v,long long f) { if (b != vfo[v].band) { vfo_band_changed(v, b); } - if(active_receiver->id==v) { - setFrequency(f); - } else { - // change VFO frequency of the non-active receiver - vfo[v].frequency=f; - if (vfo[v].ctun) { - vfo[v].ctun=FALSE; - vfo[v].offset=0; - vfo[v].ctun_frequency=vfo[v].frequency; - } + if (v == VFO_A) receiver_set_frequency(receiver[0], f); + if (v == VFO_B) { + // + // If there is only one receiver, there is no RX running that + // is controlled by VFO_B, so just update the frequency of the + // VFO without telling WDSP about it. + // If VFO_B controls a (running) receiver, do the "full job". + // if (receivers == 2) { - // VFO v controls a running WDSP receiver, - // need to "manually change" it. - // DO NOT DO IT HERE. Better add a "RECEIVER *rx" argument - // to setFrequency in radio.c + receiver_set_frequency(receiver[1], f); + } else { + vfo[v].frequency=f; + if (vfo[v].ctun) { + vfo[v].ctun=FALSE; + vfo[v].offset=0; + vfo[v].ctun_frequency=vfo[v].frequency; + } } } g_idle_add(ext_vfo_update, NULL); } + +// +// Set CTUN state of a VFO +// +void vfo_ctun_update(int id,int state) { + long long f; + if (vfo[id].ctun == state) return; // no-op if no change + vfo[id].ctun=state; + if(vfo[id].ctun) { + // CTUN turned OFF->ON + vfo[id].ctun_frequency=vfo[id].frequency; + vfo[id].offset=0; + if (id < receivers) receiver_set_frequency(receiver[id],vfo[id].ctun_frequency); + } else { + // CTUN turned ON->OFF: keep frequency + vfo[id].frequency=vfo[id].ctun_frequency; + vfo[id].offset=0; + if (id < receivers) receiver_set_frequency(receiver[id],vfo[id].ctun_frequency); + } +} + +// +// helper function for numerically entering a new VFO frequency +// +void num_pad(int val) { + // + // The numpad may be difficult to use since the frequency has to be given in Hz + // TODO: add a multiplier button like "kHz" + // TODO: display the current "entered_frequency" somewhere + // (not all of us are good in typing blind) + // + RECEIVER *rx=active_receiver; + if(!vfo[rx->id].entering_frequency) { + vfo[rx->id].entered_frequency=0; + vfo[rx->id].entering_frequency=TRUE; + } + switch(val) { + case -1: // clear + vfo[rx->id].entered_frequency=0; + vfo[rx->id].entering_frequency=FALSE; + break; + case -2: // enter + if(vfo[rx->id].entered_frequency!=0) { + receiver_set_frequency(rx, vfo[rx->id].entered_frequency); + g_idle_add(ext_vfo_update, NULL); + } + vfo[rx->id].entering_frequency=FALSE; + break; + default: + vfo[rx->id].entered_frequency=(vfo[rx->id].entered_frequency*10)+val; + break; + } +} + diff --git a/vfo.h b/vfo.h index 859eab7..76ed8d6 100644 --- a/vfo.h +++ b/vfo.h @@ -74,11 +74,6 @@ struct _mode_settings { extern struct _mode_settings mode_settings[]; -typedef struct _set_frequency { - int vfo; - long long frequency; -} SET_FREQUENCY; - #define STEPS 15 extern char *step_labels[]; @@ -118,4 +113,8 @@ extern void vfo_rit_clear(int rx); extern void vfo_rit(int rx,int i); extern void vfo_set_frequency(int vfo, long long f); +extern void vfo_ctun_update(int id, int state); + +extern void num_pad(int val); + #endif -- 2.45.2