From df78e11bc37122113683392ba56b5019fd57b719 Mon Sep 17 00:00:00 2001 From: DJ2LS Date: Fri, 21 Apr 2023 14:13:00 +0200 Subject: [PATCH] mode cleanup and sone arq related improvements to new modes --- tnc/codec2.py | 9 ---- tnc/data_handler.py | 13 +++-- tnc/modem.py | 129 ++++++++++---------------------------------- 3 files changed, 37 insertions(+), 114 deletions(-) diff --git a/tnc/codec2.py b/tnc/codec2.py index ad27a6c3..75dd6c64 100644 --- a/tnc/codec2.py +++ b/tnc/codec2.py @@ -154,15 +154,6 @@ api.freedv_get_n_max_modem_samples.restype = ctypes.c_int api.FREEDV_FS_8000 = 8000 # type: ignore -# TODO: do we need this code? Can we change it to just use Enum from above? -api.FREEDV_MODE_DATAC1 = FREEDV_MODE.datac1.value # type: ignore -api.FREEDV_MODE_DATAC3 = FREEDV_MODE.datac3.value # type: ignore -api.FREEDV_MODE_DATAC4 = FREEDV_MODE.datac4.value # type: ignore -# api.FREEDV_MODE_DATAC0 = FREEDV_MODE.datac0.value # type: ignore -api.FREEDV_MODE_DATAC13 = FREEDV_MODE.datac13.value # type: ignore - -api.FREEDV_MODE_FSK_LDPC = FREEDV_MODE.fsk_ldpc.value # type: ignore - # -------------------------------- FSK LDPC MODE SETTINGS diff --git a/tnc/data_handler.py b/tnc/data_handler.py index 64d1ed5e..a4b77bdc 100644 --- a/tnc/data_handler.py +++ b/tnc/data_handler.py @@ -105,10 +105,10 @@ class DATA: # List of codec2 modes to use in "low bandwidth" mode. self.mode_list_low_bw = [ - FREEDV_MODE.datac3.value, + FREEDV_MODE.datac4.value, ] # List for minimum SNR operating level for the corresponding mode in self.mode_list - self.snr_list_low_bw = [0] + self.snr_list_low_bw = [-5] # List for time to wait for corresponding mode in seconds self.time_list_low_bw = [6] @@ -116,15 +116,17 @@ class DATA: # List of codec2 modes to use in "high bandwidth" mode. self.mode_list_high_bw = [ + FREEDV_MODE.datac4.value, FREEDV_MODE.datac3.value, FREEDV_MODE.datac1.value, ] # List for minimum SNR operating level for the corresponding mode in self.mode_list - self.snr_list_high_bw = [0, 3] + self.snr_list_high_bw = [-5, 0, 3] # List for time to wait for corresponding mode in seconds # test with 6,7 --> caused sometimes a frame timeout if ack frame takes longer # TODO: Need to check why ACK frames needs more time - self.time_list_high_bw = [7, 8] + # TODO: Adjust these times + self.time_list_high_bw = [7, 7, 8] # -------------- AVAILABLE MODES END----------- # Mode list for selecting between low bandwidth ( 500Hz ) and modes with higher bandwidth @@ -440,7 +442,7 @@ class DATA: :param frame_to_tx: Frame data to send :type frame_to_tx: list of bytearrays - :param c2_mode: Codec2 mode to use, defaults to 14 (datac0) + :param c2_mode: Codec2 mode to use, defaults to datac13 :type c2_mode: int, optional :param copies: Number of frame copies to send, defaults to 1 :type copies: int, optional @@ -2779,6 +2781,7 @@ class DATA: dxcallsign """ + # TODO: Update this to datac13 # Sleep a random amount of time before responding to make it more likely to be # heard when many stations respond. Each DATAC0 frame is 0.44 sec (440ms) in # duration, plus overhead. Set the wait interval to be random between 0 and 2s diff --git a/tnc/modem.py b/tnc/modem.py index 4137dc5b..d422e9dd 100644 --- a/tnc/modem.py +++ b/tnc/modem.py @@ -44,9 +44,6 @@ RECEIVE_DATAC4 = False # state buffer -# TODO: Remove datac0 -#SIG0_DATAC0_STATE = [] -#SIG1_DATAC0_STATE = [] SIG0_DATAC13_STATE = [] SIG1_DATAC13_STATE = [] @@ -87,9 +84,7 @@ class RF: # Make sure our resampler will work assert (self.AUDIO_SAMPLE_RATE_RX / self.MODEM_SAMPLE_RATE) == codec2.api.FDMDV_OS_48 # type: ignore - # Small hack for initializing codec2 via codec2.py module - # TODO: Need to change the entire modem module to integrate codec2 module - self.c_lib = codec2.api + # init codec2 resampler self.resampler = codec2.resampler() self.modem_transmit_queue = MODEM_TRANSMIT_QUEUE @@ -106,27 +101,6 @@ class RF: # Open codec2 instances - # DATAC0 - # SIGNALLING MODE 0 - Used for Connecting - Payload 14 Bytes - """ - self.sig0_datac0_freedv, \ - self.sig0_datac0_bytes_per_frame, \ - self.sig0_datac0_bytes_out, \ - self.sig0_datac0_buffer, \ - self.sig0_datac0_nin = \ - self.init_codec2_mode(codec2.api.FREEDV_MODE_DATAC0, None) - - # DATAC0 - # SIGNALLING MODE 1 - Used for ACK/NACK - Payload 5 Bytes - self.sig1_datac0_freedv, \ - self.sig1_datac0_bytes_per_frame, \ - self.sig1_datac0_bytes_out, \ - self.sig1_datac0_buffer, \ - self.sig1_datac0_nin = \ - self.init_codec2_mode(codec2.api.FREEDV_MODE_DATAC0, None) - """ - - # DATAC13 # SIGNALLING MODE 0 - Used for Connecting - Payload 14 Bytes self.sig0_datac13_freedv, \ @@ -134,7 +108,7 @@ class RF: self.sig0_datac13_bytes_out, \ self.sig0_datac13_buffer, \ self.sig0_datac13_nin = \ - self.init_codec2_mode(codec2.api.FREEDV_MODE_DATAC13, None) + self.init_codec2_mode(codec2.FREEDV_MODE.datac13.value, None) # DATAC13 # SIGNALLING MODE 1 - Used for ACK/NACK - Payload 5 Bytes @@ -143,7 +117,7 @@ class RF: self.sig1_datac13_bytes_out, \ self.sig1_datac13_buffer, \ self.sig1_datac13_nin = \ - self.init_codec2_mode(codec2.api.FREEDV_MODE_DATAC13, None) + self.init_codec2_mode(codec2.FREEDV_MODE.datac13.value, None) # DATAC1 self.dat0_datac1_freedv, \ @@ -151,7 +125,7 @@ class RF: self.dat0_datac1_bytes_out, \ self.dat0_datac1_buffer, \ self.dat0_datac1_nin = \ - self.init_codec2_mode(codec2.api.FREEDV_MODE_DATAC1, None) + self.init_codec2_mode(codec2.FREEDV_MODE.datac1.value, None) # DATAC3 self.dat0_datac3_freedv, \ @@ -159,7 +133,7 @@ class RF: self.dat0_datac3_bytes_out, \ self.dat0_datac3_buffer, \ self.dat0_datac3_nin = \ - self.init_codec2_mode(codec2.api.FREEDV_MODE_DATAC3, None) + self.init_codec2_mode(codec2.FREEDV_MODE.datac3.value, None) # DATAC4 self.dat0_datac4_freedv, \ @@ -167,7 +141,7 @@ class RF: self.dat0_datac4_bytes_out, \ self.dat0_datac4_buffer, \ self.dat0_datac4_nin = \ - self.init_codec2_mode(codec2.api.FREEDV_MODE_DATAC4, None) + self.init_codec2_mode(codec2.FREEDV_MODE.datac4.value, None) # FSK LDPC - 0 @@ -177,7 +151,7 @@ class RF: self.fsk_ldpc_buffer_0, \ self.fsk_ldpc_nin_0 = \ self.init_codec2_mode( - codec2.api.FREEDV_MODE_FSK_LDPC, + codec2.FREEDV_MODE.fsk_ldpc.value, codec2.api.FREEDV_MODE_FSK_LDPC_0_ADV ) @@ -192,17 +166,16 @@ class RF: codec2.api.FREEDV_MODE_FSK_LDPC_1_ADV ) - # INIT TX MODES - # TODO: Use enum from codec2 + # INIT TX MODES - here we need all modes. self.freedv_datac0_tx = open_codec2_instance(codec2.FREEDV_MODE.datac0.value) self.freedv_datac1_tx = open_codec2_instance(codec2.FREEDV_MODE.datac1.value) self.freedv_datac3_tx = open_codec2_instance(codec2.FREEDV_MODE.datac3.value) self.freedv_datac4_tx = open_codec2_instance(codec2.FREEDV_MODE.datac4.value) self.freedv_datac13_tx = open_codec2_instance(codec2.FREEDV_MODE.datac13.value) - - self.freedv_ldpc0_tx = open_codec2_instance(200) - self.freedv_ldpc1_tx = open_codec2_instance(201) - # --------------------------------------------CREATE PYAUDIO INSTANCE + self.freedv_ldpc0_tx = open_codec2_instance(codec2.FREEDV_MODE.fsk_ldpc_0.value) + self.freedv_ldpc1_tx = open_codec2_instance(codec2.FREEDV_MODE.fsk_ldpc_1.value) + + # --------------------------------------------CREATE PORTAUDIO INSTANCE if not TESTMODE and not static.AUDIO_ENABLE_TCI: try: self.stream = sd.RawStream( @@ -289,14 +262,7 @@ class RF: # --------------------------------------------INIT AND OPEN HAMLIB # Check how we want to control the radio - # TODO: deprecated feature - we can remove this possibly - if static.HAMLIB_RADIOCONTROL == "direct": - print("direct hamlib support deprecated - not usable anymore") - sys.exit(1) - elif static.HAMLIB_RADIOCONTROL == "rigctl": - print("rigctl support deprecated - not usable anymore") - sys.exit(1) - elif static.HAMLIB_RADIOCONTROL == "rigctld": + if static.HAMLIB_RADIOCONTROL == "rigctld": import rigctld as rig elif static.AUDIO_ENABLE_TCI: self.radio = self.tci_module @@ -329,15 +295,15 @@ class RF: audio_thread_fsk_ldpc1.start() else: - audio_thread_sig0_datac0 = threading.Thread( + audio_thread_sig0_datac13 = threading.Thread( target=self.audio_sig0_datac13, name="AUDIO_THREAD DATAC13 - 0", daemon=True ) - audio_thread_sig0_datac0.start() + audio_thread_sig0_datac13.start() - audio_thread_sig1_datac0 = threading.Thread( + audio_thread_sig1_datac13 = threading.Thread( target=self.audio_sig1_datac13, name="AUDIO_THREAD DATAC13 - 1", daemon=True ) - audio_thread_sig1_datac0.start() + audio_thread_sig1_datac13.start() audio_thread_dat0_datac1 = threading.Thread( target=self.audio_dat0_datac1, name="AUDIO_THREAD DATAC1", daemon=True @@ -406,8 +372,8 @@ class RF: length_x = len(x) for data_buffer, receive in [ - (self.sig0_datac0_buffer, RECEIVE_SIG0), - (self.sig1_datac0_buffer, RECEIVE_SIG1), + (self.sig0_datac13_buffer, RECEIVE_SIG0), + (self.sig1_datac13_buffer, RECEIVE_SIG1), (self.dat0_datac1_buffer, RECEIVE_DATAC1), (self.dat0_datac3_buffer, RECEIVE_DATAC3), (self.dat0_datac4_buffer, RECEIVE_DATAC4), @@ -440,8 +406,8 @@ class RF: length_x = len(x) for data_buffer, receive in [ - (self.sig0_datac0_buffer, RECEIVE_SIG0), - (self.sig1_datac0_buffer, RECEIVE_SIG1), + (self.sig0_datac13_buffer, RECEIVE_SIG0), + (self.sig1_datac13_buffer, RECEIVE_SIG1), (self.dat0_datac1_buffer, RECEIVE_DATAC1), (self.dat0_datac3_buffer, RECEIVE_DATAC3), (self.dat0_datac4_buffer, RECEIVE_DATAC4), @@ -548,16 +514,6 @@ class RF: """ - """ - sig0 = 14 - sig1 = 14 - datac0 = 14 - datac1 = 10 - datac3 = 12 - fsk_ldpc = 9 - fsk_ldpc_0 = 200 - fsk_ldpc_1 = 201 - """ if mode == codec2.FREEDV_MODE.datac0.value: freedv = self.freedv_datac0_tx elif mode == codec2.FREEDV_MODE.datac1.value: @@ -892,7 +848,7 @@ class RF: ) # set tuning range - self.c_lib.freedv_set_tuning_range( + codec2.api.freedv_set_tuning_range( c2instance, ctypes.c_float(static.TUNING_RANGE_FMIN), ctypes.c_float(static.TUNING_RANGE_FMAX), @@ -917,48 +873,22 @@ class RF: # Additional Datac0-specific information - these are not referenced anywhere else. # self.sig0_datac0_payload_per_frame = self.sig0_datac0_bytes_per_frame - 2 - # self.sig0_datac0_n_nom_modem_samples = self.c_lib.freedv_get_n_nom_modem_samples( + # self.sig0_datac0_n_nom_modem_samples = codec2.api.freedv_get_n_nom_modem_samples( # self.sig0_datac0_freedv # ) - # self.sig0_datac0_n_tx_modem_samples = self.c_lib.freedv_get_n_tx_modem_samples( + # self.sig0_datac0_n_tx_modem_samples = codec2.api.freedv_get_n_tx_modem_samples( # self.sig0_datac0_freedv # ) # self.sig0_datac0_n_tx_preamble_modem_samples = ( - # self.c_lib.freedv_get_n_tx_preamble_modem_samples(self.sig0_datac0_freedv) + # codec2.api.freedv_get_n_tx_preamble_modem_samples(self.sig0_datac0_freedv) # ) # self.sig0_datac0_n_tx_postamble_modem_samples = ( - # self.c_lib.freedv_get_n_tx_postamble_modem_samples(self.sig0_datac0_freedv) + # codec2.api.freedv_get_n_tx_postamble_modem_samples(self.sig0_datac0_freedv) # ) # return values return c2instance, bytes_per_frame, bytes_out, audio_buffer, nin - # TODO: Remove datac0 - # def audio_sig0_datac0(self) -> None: - # """Receive data encoded with datac0 - 0""" - # self.sig0_datac0_nin = self.demodulate_audio( - # self.sig0_datac0_buffer, - # self.sig0_datac0_nin, - # self.sig0_datac0_freedv, - # self.sig0_datac0_bytes_out, - # self.sig0_datac0_bytes_per_frame, - # SIG0_DATAC0_STATE, - # "sig0-datac0" - # ) - - # def audio_sig1_datac0(self) -> None: - # """Receive data encoded with datac0 - 1""" - # self.sig1_datac0_nin = self.demodulate_audio( - # self.sig1_datac0_buffer, - # self.sig1_datac0_nin, - # self.sig1_datac0_freedv, - # self.sig1_datac0_bytes_out, - # self.sig1_datac0_bytes_per_frame, - # SIG1_DATAC0_STATE, - # "sig1-datac0" - # ) - - def audio_sig0_datac13(self) -> None: """Receive data encoded with datac13 - 0""" self.sig0_datac13_nin = self.demodulate_audio( @@ -1081,7 +1011,7 @@ class RF: :rtype: float """ modemStats = codec2.MODEMSTATS() - self.c_lib.freedv_get_modem_extended_stats(freedv, ctypes.byref(modemStats)) + codec2.api.freedv_get_modem_extended_stats(freedv, ctypes.byref(modemStats)) offset = round(modemStats.foff) * (-1) static.FREQ_OFFSET = offset return offset @@ -1099,7 +1029,7 @@ class RF: modemStats = codec2.MODEMSTATS() ctypes.cast( - self.c_lib.freedv_get_modem_extended_stats(freedv, ctypes.byref(modemStats)), + codec2.api.freedv_get_modem_extended_stats(freedv, ctypes.byref(modemStats)), ctypes.c_void_p, ) @@ -1142,7 +1072,7 @@ class RF: modem_stats_snr = ctypes.c_float() modem_stats_sync = ctypes.c_int() - self.c_lib.freedv_get_modem_stats( + codec2.api.freedv_get_modem_stats( freedv, ctypes.byref(modem_stats_sync), ctypes.byref(modem_stats_snr) ) modem_stats_snr = modem_stats_snr.value @@ -1249,7 +1179,6 @@ class RF: if rms_counter > 50: d = np.frombuffer(self.fft_data, np.int16).astype(np.float32) # calculate RMS and then dBFS - # TODO: Need to change static.AUDIO_RMS to AUDIO_DBFS somewhen # https://dsp.stackexchange.com/questions/8785/how-to-compute-dbfs # try except for avoiding runtime errors by division/0 try: