mode cleanup and sone arq related improvements to new modes

This commit is contained in:
DJ2LS 2023-04-21 14:13:00 +02:00
parent 7f9e048dcd
commit df78e11bc3
3 changed files with 37 additions and 114 deletions

View file

@ -154,15 +154,6 @@ api.freedv_get_n_max_modem_samples.restype = ctypes.c_int
api.FREEDV_FS_8000 = 8000 # type: ignore 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 # -------------------------------- FSK LDPC MODE SETTINGS

View file

@ -105,10 +105,10 @@ class DATA:
# List of codec2 modes to use in "low bandwidth" mode. # List of codec2 modes to use in "low bandwidth" mode.
self.mode_list_low_bw = [ 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 # 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 # List for time to wait for corresponding mode in seconds
self.time_list_low_bw = [6] self.time_list_low_bw = [6]
@ -116,15 +116,17 @@ class DATA:
# List of codec2 modes to use in "high bandwidth" mode. # List of codec2 modes to use in "high bandwidth" mode.
self.mode_list_high_bw = [ self.mode_list_high_bw = [
FREEDV_MODE.datac4.value,
FREEDV_MODE.datac3.value, FREEDV_MODE.datac3.value,
FREEDV_MODE.datac1.value, FREEDV_MODE.datac1.value,
] ]
# List for minimum SNR operating level for the corresponding mode in self.mode_list # 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 # List for time to wait for corresponding mode in seconds
# test with 6,7 --> caused sometimes a frame timeout if ack frame takes longer # test with 6,7 --> caused sometimes a frame timeout if ack frame takes longer
# TODO: Need to check why ACK frames needs more time # 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----------- # -------------- AVAILABLE MODES END-----------
# Mode list for selecting between low bandwidth ( 500Hz ) and modes with higher bandwidth # 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 :param frame_to_tx: Frame data to send
:type frame_to_tx: list of bytearrays :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 :type c2_mode: int, optional
:param copies: Number of frame copies to send, defaults to 1 :param copies: Number of frame copies to send, defaults to 1
:type copies: int, optional :type copies: int, optional
@ -2779,6 +2781,7 @@ class DATA:
dxcallsign dxcallsign
""" """
# TODO: Update this to datac13
# Sleep a random amount of time before responding to make it more likely to be # 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 # 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 # duration, plus overhead. Set the wait interval to be random between 0 and 2s

View file

@ -44,9 +44,6 @@ RECEIVE_DATAC4 = False
# state buffer # state buffer
# TODO: Remove datac0
#SIG0_DATAC0_STATE = []
#SIG1_DATAC0_STATE = []
SIG0_DATAC13_STATE = [] SIG0_DATAC13_STATE = []
SIG1_DATAC13_STATE = [] SIG1_DATAC13_STATE = []
@ -87,9 +84,7 @@ class RF:
# Make sure our resampler will work # Make sure our resampler will work
assert (self.AUDIO_SAMPLE_RATE_RX / self.MODEM_SAMPLE_RATE) == codec2.api.FDMDV_OS_48 # type: ignore 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 # init codec2 resampler
# TODO: Need to change the entire modem module to integrate codec2 module
self.c_lib = codec2.api
self.resampler = codec2.resampler() self.resampler = codec2.resampler()
self.modem_transmit_queue = MODEM_TRANSMIT_QUEUE self.modem_transmit_queue = MODEM_TRANSMIT_QUEUE
@ -106,27 +101,6 @@ class RF:
# Open codec2 instances # 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 # DATAC13
# SIGNALLING MODE 0 - Used for Connecting - Payload 14 Bytes # SIGNALLING MODE 0 - Used for Connecting - Payload 14 Bytes
self.sig0_datac13_freedv, \ self.sig0_datac13_freedv, \
@ -134,7 +108,7 @@ class RF:
self.sig0_datac13_bytes_out, \ self.sig0_datac13_bytes_out, \
self.sig0_datac13_buffer, \ self.sig0_datac13_buffer, \
self.sig0_datac13_nin = \ 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 # DATAC13
# SIGNALLING MODE 1 - Used for ACK/NACK - Payload 5 Bytes # SIGNALLING MODE 1 - Used for ACK/NACK - Payload 5 Bytes
@ -143,7 +117,7 @@ class RF:
self.sig1_datac13_bytes_out, \ self.sig1_datac13_bytes_out, \
self.sig1_datac13_buffer, \ self.sig1_datac13_buffer, \
self.sig1_datac13_nin = \ 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 # DATAC1
self.dat0_datac1_freedv, \ self.dat0_datac1_freedv, \
@ -151,7 +125,7 @@ class RF:
self.dat0_datac1_bytes_out, \ self.dat0_datac1_bytes_out, \
self.dat0_datac1_buffer, \ self.dat0_datac1_buffer, \
self.dat0_datac1_nin = \ 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 # DATAC3
self.dat0_datac3_freedv, \ self.dat0_datac3_freedv, \
@ -159,7 +133,7 @@ class RF:
self.dat0_datac3_bytes_out, \ self.dat0_datac3_bytes_out, \
self.dat0_datac3_buffer, \ self.dat0_datac3_buffer, \
self.dat0_datac3_nin = \ 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 # DATAC4
self.dat0_datac4_freedv, \ self.dat0_datac4_freedv, \
@ -167,7 +141,7 @@ class RF:
self.dat0_datac4_bytes_out, \ self.dat0_datac4_bytes_out, \
self.dat0_datac4_buffer, \ self.dat0_datac4_buffer, \
self.dat0_datac4_nin = \ 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 # FSK LDPC - 0
@ -177,7 +151,7 @@ class RF:
self.fsk_ldpc_buffer_0, \ self.fsk_ldpc_buffer_0, \
self.fsk_ldpc_nin_0 = \ self.fsk_ldpc_nin_0 = \
self.init_codec2_mode( self.init_codec2_mode(
codec2.api.FREEDV_MODE_FSK_LDPC, codec2.FREEDV_MODE.fsk_ldpc.value,
codec2.api.FREEDV_MODE_FSK_LDPC_0_ADV codec2.api.FREEDV_MODE_FSK_LDPC_0_ADV
) )
@ -192,17 +166,16 @@ class RF:
codec2.api.FREEDV_MODE_FSK_LDPC_1_ADV codec2.api.FREEDV_MODE_FSK_LDPC_1_ADV
) )
# INIT TX MODES # INIT TX MODES - here we need all modes.
# TODO: Use enum from codec2
self.freedv_datac0_tx = open_codec2_instance(codec2.FREEDV_MODE.datac0.value) 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_datac1_tx = open_codec2_instance(codec2.FREEDV_MODE.datac1.value)
self.freedv_datac3_tx = open_codec2_instance(codec2.FREEDV_MODE.datac3.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_datac4_tx = open_codec2_instance(codec2.FREEDV_MODE.datac4.value)
self.freedv_datac13_tx = open_codec2_instance(codec2.FREEDV_MODE.datac13.value) self.freedv_datac13_tx = open_codec2_instance(codec2.FREEDV_MODE.datac13.value)
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)
self.freedv_ldpc0_tx = open_codec2_instance(200) # --------------------------------------------CREATE PORTAUDIO INSTANCE
self.freedv_ldpc1_tx = open_codec2_instance(201)
# --------------------------------------------CREATE PYAUDIO INSTANCE
if not TESTMODE and not static.AUDIO_ENABLE_TCI: if not TESTMODE and not static.AUDIO_ENABLE_TCI:
try: try:
self.stream = sd.RawStream( self.stream = sd.RawStream(
@ -289,14 +262,7 @@ class RF:
# --------------------------------------------INIT AND OPEN HAMLIB # --------------------------------------------INIT AND OPEN HAMLIB
# Check how we want to control the radio # Check how we want to control the radio
# TODO: deprecated feature - we can remove this possibly if static.HAMLIB_RADIOCONTROL == "rigctld":
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":
import rigctld as rig import rigctld as rig
elif static.AUDIO_ENABLE_TCI: elif static.AUDIO_ENABLE_TCI:
self.radio = self.tci_module self.radio = self.tci_module
@ -329,15 +295,15 @@ class RF:
audio_thread_fsk_ldpc1.start() audio_thread_fsk_ldpc1.start()
else: 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 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 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( audio_thread_dat0_datac1 = threading.Thread(
target=self.audio_dat0_datac1, name="AUDIO_THREAD DATAC1", daemon=True target=self.audio_dat0_datac1, name="AUDIO_THREAD DATAC1", daemon=True
@ -406,8 +372,8 @@ class RF:
length_x = len(x) length_x = len(x)
for data_buffer, receive in [ for data_buffer, receive in [
(self.sig0_datac0_buffer, RECEIVE_SIG0), (self.sig0_datac13_buffer, RECEIVE_SIG0),
(self.sig1_datac0_buffer, RECEIVE_SIG1), (self.sig1_datac13_buffer, RECEIVE_SIG1),
(self.dat0_datac1_buffer, RECEIVE_DATAC1), (self.dat0_datac1_buffer, RECEIVE_DATAC1),
(self.dat0_datac3_buffer, RECEIVE_DATAC3), (self.dat0_datac3_buffer, RECEIVE_DATAC3),
(self.dat0_datac4_buffer, RECEIVE_DATAC4), (self.dat0_datac4_buffer, RECEIVE_DATAC4),
@ -440,8 +406,8 @@ class RF:
length_x = len(x) length_x = len(x)
for data_buffer, receive in [ for data_buffer, receive in [
(self.sig0_datac0_buffer, RECEIVE_SIG0), (self.sig0_datac13_buffer, RECEIVE_SIG0),
(self.sig1_datac0_buffer, RECEIVE_SIG1), (self.sig1_datac13_buffer, RECEIVE_SIG1),
(self.dat0_datac1_buffer, RECEIVE_DATAC1), (self.dat0_datac1_buffer, RECEIVE_DATAC1),
(self.dat0_datac3_buffer, RECEIVE_DATAC3), (self.dat0_datac3_buffer, RECEIVE_DATAC3),
(self.dat0_datac4_buffer, RECEIVE_DATAC4), (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: if mode == codec2.FREEDV_MODE.datac0.value:
freedv = self.freedv_datac0_tx freedv = self.freedv_datac0_tx
elif mode == codec2.FREEDV_MODE.datac1.value: elif mode == codec2.FREEDV_MODE.datac1.value:
@ -892,7 +848,7 @@ class RF:
) )
# set tuning range # set tuning range
self.c_lib.freedv_set_tuning_range( codec2.api.freedv_set_tuning_range(
c2instance, c2instance,
ctypes.c_float(static.TUNING_RANGE_FMIN), ctypes.c_float(static.TUNING_RANGE_FMIN),
ctypes.c_float(static.TUNING_RANGE_FMAX), ctypes.c_float(static.TUNING_RANGE_FMAX),
@ -917,48 +873,22 @@ class RF:
# Additional Datac0-specific information - these are not referenced anywhere else. # 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_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_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_freedv
# ) # )
# self.sig0_datac0_n_tx_preamble_modem_samples = ( # 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.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 values
return c2instance, bytes_per_frame, bytes_out, audio_buffer, nin 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: def audio_sig0_datac13(self) -> None:
"""Receive data encoded with datac13 - 0""" """Receive data encoded with datac13 - 0"""
self.sig0_datac13_nin = self.demodulate_audio( self.sig0_datac13_nin = self.demodulate_audio(
@ -1081,7 +1011,7 @@ class RF:
:rtype: float :rtype: float
""" """
modemStats = codec2.MODEMSTATS() 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) offset = round(modemStats.foff) * (-1)
static.FREQ_OFFSET = offset static.FREQ_OFFSET = offset
return offset return offset
@ -1099,7 +1029,7 @@ class RF:
modemStats = codec2.MODEMSTATS() modemStats = codec2.MODEMSTATS()
ctypes.cast( 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, ctypes.c_void_p,
) )
@ -1142,7 +1072,7 @@ class RF:
modem_stats_snr = ctypes.c_float() modem_stats_snr = ctypes.c_float()
modem_stats_sync = ctypes.c_int() 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) freedv, ctypes.byref(modem_stats_sync), ctypes.byref(modem_stats_snr)
) )
modem_stats_snr = modem_stats_snr.value modem_stats_snr = modem_stats_snr.value
@ -1249,7 +1179,6 @@ class RF:
if rms_counter > 50: if rms_counter > 50:
d = np.frombuffer(self.fft_data, np.int16).astype(np.float32) d = np.frombuffer(self.fft_data, np.int16).astype(np.float32)
# calculate RMS and then dBFS # 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 # https://dsp.stackexchange.com/questions/8785/how-to-compute-dbfs
# try except for avoiding runtime errors by division/0 # try except for avoiding runtime errors by division/0
try: try: