From 36d717636c664431d77ac36ba482046780e04bac Mon Sep 17 00:00:00 2001 From: "James C. Ahlstrom" Date: Wed, 20 Mar 2024 12:28:39 -0400 Subject: [PATCH] Quisk version 4.2.30 --- CHANGELOG.txt | 7 +++++++ __init__.py | 2 +- configure.py | 2 +- is_key_down.c | 1 + quisk.c | 15 ++++++++++++++- quisk.py | 3 ++- quisk_conf_defaults.py | 11 +++++++++++ setup.py | 2 +- 8 files changed, 38 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 4019024..fe9fba3 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,10 @@ +Quisk Version 4.2.30 March 2024 +================================ +A new option "Tx-Rx silence msec" on the Timing configuration screen controls how long +to suppress Rx audio when switching from Tx to Rx. The previous fixed time was 50 msec. + +The SSB squelch control now works on CW too. Please test. + Quisk Version 4.2.29 January 2024 ================================== This version updates the FreeDV library files and program logic. I added a "Monitor" diff --git a/__init__.py b/__init__.py index ee518f2..7dfa8f1 100644 --- a/__init__.py +++ b/__init__.py @@ -1,2 +1,2 @@ -#Quisk version 4.2.29 +#Quisk version 4.2.30 from .quisk import main diff --git a/configure.py b/configure.py index c38f215..0f72bff 100644 --- a/configure.py +++ b/configure.py @@ -2005,7 +2005,7 @@ def OnChange2(self, ctrl, value): if self.radio_name == Settings[1]: # changed for current radio if name in ('hot_key_ptt_toggle', 'hot_key_ptt_if_hidden', 'keyupDelay', 'cwTone', 'pulse_audio_verbose_output', 'start_cw_delay', 'start_ssb_delay', 'maximum_tx_secs', 'quisk_serial_cts', 'quisk_serial_dsr', - 'hot_key_ptt1', 'hot_key_ptt2', 'midi_ptt_toggle'): + 'hot_key_ptt1', 'hot_key_ptt2', 'midi_ptt_toggle', 'TxRxSilenceMsec'): setattr(conf, name, x) application.ImmediateChange(name) elif name[0:4] in ('lin_', 'win_'): diff --git a/is_key_down.c b/is_key_down.c index 76eddd9..5262911 100644 --- a/is_key_down.c +++ b/is_key_down.c @@ -168,6 +168,7 @@ static void modem_status(void) #include #include +#include #include static int fdComm = -1; // File descriptor to read the serial port diff --git a/quisk.c b/quisk.c index 27bb362..fe503e1 100644 --- a/quisk.c +++ b/quisk.c @@ -181,6 +181,7 @@ int quisk_sidetoneFreq; // frequency in hertz for the sidetone int quisk_start_cw_delay = 15; // milliseconds to delay output on CW key down int quisk_start_ssb_delay = 100; // milliseconds to discard output on SSB etc. key down static int maximum_tx_secs; // Failsafe timeout for Tx in seconds +static int TxRxSilenceMsec = 50; // Play silence in msec on Tx to Rx static int key_is_down = 0; // internal key state up or down static double agcReleaseGain=80; // AGC maximum gain @@ -1921,6 +1922,10 @@ static int quisk_process_demodulate(complex double * cSamples, double * dsamples } if(bank == 0) dAutoNotch(dsamples, nSamples, rit_freq, quisk_filter_srate); + if (ssb_squelch_enabled) { + ssb_squelch(dsamples, nSamples, quisk_filter_srate, MeasureSquelch + bank); + d_delay(dsamples, nSamples, bank, SQUELCH_FFT_SIZE); + } nSamples = quisk_dInterpolate(dsamples, nSamples, &Storage[bank].filtAudio12p2, 2); nSamples = quisk_dInterp2HB45(dsamples, nSamples, &Storage[bank].HalfBand6); nSamples = quisk_dInterp2HB45(dsamples, nSamples, &Storage[bank].HalfBand7); @@ -1940,6 +1945,10 @@ static int quisk_process_demodulate(complex double * cSamples, double * dsamples } if(bank == 0) dAutoNotch(dsamples, nSamples, rit_freq, quisk_filter_srate); + if (ssb_squelch_enabled) { + ssb_squelch(dsamples, nSamples, quisk_filter_srate, MeasureSquelch + bank); + d_delay(dsamples, nSamples, bank, SQUELCH_FFT_SIZE); + } nSamples = quisk_dInterpolate(dsamples, nSamples, &Storage[bank].filtAudio12p2, 2); nSamples = quisk_dInterp2HB45(dsamples, nSamples, &Storage[bank].HalfBand6); nSamples = quisk_dInterp2HB45(dsamples, nSamples, &Storage[bank].HalfBand7); @@ -2458,7 +2467,7 @@ int quisk_process_samples(complex double * cSamples, int nSamples) quisk_sound_state.sample_rate; nout = (int)dOutCounter; // number of samples to output dOutCounter -= nout; - playSilence = (int)(quisk_sound_state.playback_rate * 50e-3); // Play silence after sidetone ends, number of samples + playSilence = (int)(quisk_sound_state.playback_rate * 1E-3 * TxRxSilenceMsec); // Play silence after sidetone ends, number of samples keyupEnvelope = 0; if (quisk_active_sidetone == 2 && QUISK_CWKEY_DOWN) { // Play sidetone instead of radio for CW if (! sidetoneIsOn) { // turn on sidetone @@ -4694,6 +4703,9 @@ static PyObject * ImmediateChange(PyObject * self, PyObject * args) // called fr else if ( ! strcmp(name, "maximum_tx_secs")) { maximum_tx_secs = QuiskGetConfigInt(name, 0); } + else if ( ! strcmp(name, "TxRxSilenceMsec")) { + TxRxSilenceMsec = QuiskGetConfigInt(name, 50); + } Py_INCREF (Py_None); return Py_None; } @@ -5851,6 +5863,7 @@ static PyObject * record_app(PyObject * self, PyObject * args) quisk_start_cw_delay = QuiskGetConfigInt("start_cw_delay", 15); quisk_start_ssb_delay = QuiskGetConfigInt("start_ssb_delay", 100); maximum_tx_secs = QuiskGetConfigInt("maximum_tx_secs", 0); + TxRxSilenceMsec = QuiskGetConfigInt("TxRxSilenceMsec", 50); quisk_sound_state.sample_rate = rate; fft_sample_rate = rate; is_little_endian = 1; // Test machine byte order diff --git a/quisk.py b/quisk.py index 47ba4e7..960bcd6 100644 --- a/quisk.py +++ b/quisk.py @@ -3762,7 +3762,8 @@ def OnInit(self): # Find the data width from a list of preferred sizes; it is the width of returned graph data. # The graph_width is the width of data_width that is displayed. if conf.window_width > 0: - wFrame, h = frame.GetClientSize().Get() # client window width + #wFrame, h = frame.GetClientSize().Get() # client window width + wFrame = conf.window_width - 15 # Thanks to Nick Abramenko, RA3PKJ graph = GraphScreen(frame, self.width//2, self.width//2, None) # make a GraphScreen to calculate borders self.graph_width = wFrame - (graph.width - graph.graph_width) # less graph borders equals actual graph_width graph.Destroy() diff --git a/quisk_conf_defaults.py b/quisk_conf_defaults.py index 28fd206..f5cabc7 100644 --- a/quisk_conf_defaults.py +++ b/quisk_conf_defaults.py @@ -419,6 +419,8 @@ ## hermes_antenna_tuner Antenna tuner, text choice # This option only applies to the Hermes Lite 2. Set this to None if you don't have a tuner. # Set this to "Tune" to control the Icom AH-4 compatible ATU attached to the Hermes Lite 2 end plate. +# Note that this option only applies to the HL2 end plate, not the IO board. +# A tuner attached to the IO board is controlled from a button on the last line of the screen. # Then when the Spot button is pressed with a positive power, a tune request is sent to the ATU. # If the Spot button is pressed with a zero power level, the tuner is set to bypass mode. # Changes are immediate (no need to restart). @@ -1646,6 +1648,15 @@ # Changes are immediate (no need to restart). maximum_tx_secs = 0 +## TxRxSilenceMsec Tx-Rx silence msec, integer +# When changing from transmit to receive a radio may receive either noise or the end of the transmission. +# This may be returned as received audio, and can be heard as a loud pop. +# This parameter plays silence for the specified number of milliseconds when changing from transmit to receive. +# Make it long enough to zero out the pop, but not too much longer. +# It is ignored when in full duplex mode. +# Changes are immediate (no need to restart). +TxRxSilenceMsec = 50 + ## keyupDelay Keyup delay msecs, integer # This is the key hang time for semi-breakin CW. It is the time in milliseconds # from the last CW key release until changing to receive. diff --git a/setup.py b/setup.py index 4b04e72..d5870be 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ # You must define the version here. A title string including # the version will be written to __init__.py and read by quisk.py. -Version = '4.2.29' +Version = '4.2.30' fp = open("__init__.py", "w") # write title string fp.write("#Quisk version %s\n" % Version)