WIP ARQ - cleanup and modem fix

This commit is contained in:
DJ2LS 2023-12-15 14:41:11 +01:00
parent 16f37677d5
commit c4dbe0caef
5 changed files with 32 additions and 82 deletions

View file

@ -51,10 +51,13 @@ class ARQSession():
def get_mode_by_speed_level(self, speed_level): def get_mode_by_speed_level(self, speed_level):
return self.SPEED_LEVEL_DICT[speed_level]["mode"] return self.SPEED_LEVEL_DICT[speed_level]["mode"]
def transmit_frame(self, frame: bytearray): def transmit_frame(self, frame: bytearray, mode = False):
self.log("Transmitting frame") self.log("Transmitting frame")
if not mode:
self.get_mode_by_speed_level(self.speed_level)
modem_queue_item = { modem_queue_item = {
'mode': self.get_mode_by_speed_level(self.speed_level), 'mode': mode,
'repeat': 1, 'repeat': 1,
'repeat_delay': 1, 'repeat_delay': 1,
'frame': frame, 'frame': frame,

View file

@ -4,6 +4,8 @@ import queue
import arq_session import arq_session
import helpers import helpers
from modem_frametypes import FRAME_TYPE from modem_frametypes import FRAME_TYPE
from codec2 import FREEDV_MODE
class ARQSessionIRS(arq_session.ARQSession): class ARQSessionIRS(arq_session.ARQSession):
@ -77,9 +79,9 @@ class ARQSessionIRS(arq_session.ARQSession):
self.log("Timeout waiting for ISS. Session failed.") self.log("Timeout waiting for ISS. Session failed.")
self.set_state(self.STATE_FAILED) self.set_state(self.STATE_FAILED)
def launch_transmit_and_wait(self, frame, timeout): def launch_transmit_and_wait(self, frame, timeout, mode):
thread_wait = threading.Thread(target = self.transmit_and_wait, thread_wait = threading.Thread(target = self.transmit_and_wait,
args = [frame, timeout]) args = [frame, timeout, mode])
thread_wait.start() thread_wait.start()
def send_open_ack(self, open_frame): def send_open_ack(self, open_frame):
@ -88,7 +90,7 @@ class ARQSessionIRS(arq_session.ARQSession):
self.dxcall, self.dxcall,
self.version, self.version,
self.snr[0]) self.snr[0])
self.launch_transmit_and_wait(ack_frame, self.TIMEOUT_CONNECT) self.launch_transmit_and_wait(ack_frame, self.TIMEOUT_CONNECT, mode=FREEDV_MODE.datac13)
self.set_state(self.STATE_OPEN_ACK_SENT) self.set_state(self.STATE_OPEN_ACK_SENT)
def send_info_ack(self, info_frame): def send_info_ack(self, info_frame):
@ -97,10 +99,11 @@ class ARQSessionIRS(arq_session.ARQSession):
self.total_crc = info_frame['total_crc'] self.total_crc = info_frame['total_crc']
self.dx_snr.append(info_frame['snr']) self.dx_snr.append(info_frame['snr'])
self.calibrate_speed_settings()
info_ack = self.frame_factory.build_arq_session_info_ack( info_ack = self.frame_factory.build_arq_session_info_ack(
self.id, self.total_crc, self.snr[0], self.id, self.total_crc, self.snr[0],
self.speed_level, self.frames_per_burst) self.speed_level, self.frames_per_burst)
self.launch_transmit_and_wait(info_ack, self.TIMEOUT_CONNECT) self.launch_transmit_and_wait(info_ack, self.TIMEOUT_CONNECT, mode=FREEDV_MODE.datac13)
self.set_state(self.STATE_INFO_ACK_SENT) self.set_state(self.STATE_INFO_ACK_SENT)
def send_burst_nack(self): def send_burst_nack(self):
@ -108,7 +111,6 @@ class ARQSessionIRS(arq_session.ARQSession):
nack = self.frame_factory.build_arq_burst_ack(self.id, self.received_bytes, self.speed_level, self.frames_per_burst, self.snr[0]) nack = self.frame_factory.build_arq_burst_ack(self.id, self.received_bytes, self.speed_level, self.frames_per_burst, self.snr[0])
self.transmit_and_wait(nack) self.transmit_and_wait(nack)
def process_incoming_data(self, frame): def process_incoming_data(self, frame):
if frame['offset'] != self.received_bytes: if frame['offset'] != self.received_bytes:
self.logger.info(f"Discarding data frame due to wrong offset", frame=self.frame_received) self.logger.info(f"Discarding data frame due to wrong offset", frame=self.frame_received)

View file

@ -52,12 +52,12 @@ class ARQSessionISS(arq_session.ARQSession):
def generate_id(self): def generate_id(self):
return random.randint(1,255) return random.randint(1,255)
def transmit_wait_and_retry(self, frame_or_burst, timeout, retries): def transmit_wait_and_retry(self, frame_or_burst, timeout, retries, mode):
while retries > 0: while retries > 0:
if isinstance(frame_or_burst, list): burst = frame_or_burst if isinstance(frame_or_burst, list): burst = frame_or_burst
else: burst = [frame_or_burst] else: burst = [frame_or_burst]
for f in burst: for f in burst:
self.transmit_frame(f) self.transmit_frame(f, mode)
self.log(f"Waiting {timeout} seconds...") self.log(f"Waiting {timeout} seconds...")
if self.event_frame_received.wait(timeout): if self.event_frame_received.wait(timeout):
return return
@ -66,13 +66,13 @@ class ARQSessionISS(arq_session.ARQSession):
self.set_state(self.STATE_FAILED) self.set_state(self.STATE_FAILED)
self.log("Session failed") self.log("Session failed")
def launch_twr(self, frame_or_burst, timeout, retries): def launch_twr(self, frame_or_burst, timeout, retries, mode):
twr = threading.Thread(target = self.transmit_wait_and_retry, args=[frame_or_burst, timeout, retries]) twr = threading.Thread(target = self.transmit_wait_and_retry, args=[frame_or_burst, timeout, retries, mode])
twr.start() twr.start()
def start(self): def start(self):
session_open_frame = self.frame_factory.build_arq_session_open(self.dxcall, self.id) session_open_frame = self.frame_factory.build_arq_session_open(self.dxcall, self.id)
self.launch_twr(session_open_frame, self.TIMEOUT_CONNECT_ACK, self.RETRIES_CONNECT) self.launch_twr(session_open_frame, self.TIMEOUT_CONNECT_ACK, self.RETRIES_CONNECT, mode=FREEDV_MODE.datac13)
self.set_state(self.STATE_OPEN_SENT) self.set_state(self.STATE_OPEN_SENT)
def set_speed_and_frames_per_burst(self, frame): def set_speed_and_frames_per_burst(self, frame):

View file

@ -7,7 +7,8 @@ from arq_session_iss import ARQSessionISS
class ARQRawCommand(TxCommand): class ARQRawCommand(TxCommand):
def set_params_from_api(self, apiParams): def set_params_from_api(self, apiParams):
self.dxcall = apiParams['dxcall'] print(apiParams)
self.dxcall = apiParams['dxcallsign']
if not api_validations.validate_freedata_callsign(self.dxcall): if not api_validations.validate_freedata_callsign(self.dxcall):
self.dxcall = f"{self.dxcall}-0" self.dxcall = f"{self.dxcall}-0"

View file

@ -11,7 +11,6 @@ Created on Wed Dec 23 07:04:24 2020
import atexit import atexit
import ctypes import ctypes
import os
import queue import queue
import threading import threading
import time import time
@ -25,13 +24,9 @@ import cw
from queues import RIGCTLD_COMMAND_QUEUE from queues import RIGCTLD_COMMAND_QUEUE
import audio import audio
import event_manager import event_manager
from modem_frametypes import FRAME_TYPE
import beacon import beacon
import demodulator import demodulator
TESTMODE = False
TXCHANNEL = ""
class RF: class RF:
"""Class to encapsulate interactions between the audio device and codec2""" """Class to encapsulate interactions between the audio device and codec2"""
@ -132,16 +127,14 @@ class RF:
def start_modem(self): def start_modem(self):
result = False result = False
if not TESTMODE and self.radiocontrol not in ["tci"]: if self.radiocontrol not in ["tci"]:
result = self.init_audio() result = self.init_audio()
if not result: if not result:
raise RuntimeError("Unable to init audio devices") raise RuntimeError("Unable to init audio devices")
self.demodulator.start(self.stream) self.demodulator.start(self.stream)
elif not TESTMODE:
result = self.init_tci()
else: else:
result = self.init_mkfifo() result = self.init_tci()
if result not in [False]: if result not in [False]:
# init codec2 instances # init codec2 instances
@ -245,34 +238,6 @@ class RF:
daemon=True, daemon=True,
) )
tci_tx_callback_thread.start() tci_tx_callback_thread.start()
def init_mkfifo(self):
class Object:
"""An object for simulating audio stream"""
active = True
self.stream = Object()
# Create mkfifo buffers
try:
os.mkfifo(RXCHANNEL)
os.mkfifo(TXCHANNEL)
except Exception as err:
self.log.info(f"[MDM] init:mkfifo: Exception: {err}")
mkfifo_write_callback_thread = threading.Thread(
target=self.mkfifo_write_callback,
name="MKFIFO WRITE CALLBACK THREAD",
daemon=True,
)
mkfifo_write_callback_thread.start()
self.log.debug("[MDM] Starting mkfifo_read_callback")
mkfifo_read_callback_thread = threading.Thread(
target=self.mkfifo_read_callback,
name="MKFIFO READ CALLBACK THREAD",
daemon=True,
)
mkfifo_read_callback_thread.start()
def mkfifo_write_callback(self) -> None: def mkfifo_write_callback(self) -> None:
"""Support testing by writing the audio data to a pipe.""" """Support testing by writing the audio data to a pipe."""
@ -304,20 +269,16 @@ class RF:
""" """
self.demodulator.reset_data_sync() self.demodulator.reset_data_sync()
if mode == codec2.FREEDV_MODE.datac0.value: # get freedv instance by mode
freedv = self.freedv_datac0_tx mode_transition = {
elif mode == codec2.FREEDV_MODE.datac1.value: codec2.FREEDV_MODE.datac0: self.freedv_datac0_tx,
freedv = self.freedv_datac1_tx codec2.FREEDV_MODE.datac1: self.freedv_datac1_tx,
elif mode == codec2.FREEDV_MODE.datac3.value: codec2.FREEDV_MODE.datac3: self.freedv_datac3_tx,
freedv = self.freedv_datac3_tx codec2.FREEDV_MODE.datac4: self.freedv_datac4_tx,
elif mode == codec2.FREEDV_MODE.datac4.value: codec2.FREEDV_MODE.datac13: self.freedv_datac13_tx,
freedv = self.freedv_datac4_tx }
elif mode == codec2.FREEDV_MODE.datac13.value: if mode in mode_transition:
freedv = self.freedv_datac13_tx freedv = mode_transition[mode]
elif mode == codec2.FREEDV_MODE.fsk_ldpc_0.value:
freedv = self.freedv_ldpc0_tx
elif mode == codec2.FREEDV_MODE.fsk_ldpc_1.value:
freedv = self.freedv_ldpc1_tx
else: else:
return False return False
@ -659,7 +620,7 @@ class RF:
queuesize = self.modem_transmit_queue.qsize() queuesize = self.modem_transmit_queue.qsize()
self.log.debug("[MDM] self.modem_transmit_queue", qsize=queuesize) self.log.debug("[MDM] self.modem_transmit_queue", qsize=queuesize)
tx = self.modem_transmit_queue.get() tx = self.modem_transmit_queue.get()
print(tx)
# TODO Why we is this taking an array instead of a single frame? # TODO Why we is this taking an array instead of a single frame?
if tx['mode'] in ["morse"]: if tx['mode'] in ["morse"]:
self.transmit_morse(tx['repeat'], tx['repeat_delay'], [tx['frame']]) self.transmit_morse(tx['repeat'], tx['repeat_delay'], [tx['frame']])
@ -870,20 +831,3 @@ class RF:
# Set config boolean regarding wheter it should sent FFT data to queue # Set config boolean regarding wheter it should sent FFT data to queue
self.enable_fft_stream = enable self.enable_fft_stream = enable
def get_modem_error_state():
"""
get current state buffer and return True of contains 10
"""
if RECEIVE_DATAC1 and 10 in DAT0_DATAC1_STATE:
DAT0_DATAC1_STATE.clear()
return True
if RECEIVE_DATAC3 and 10 in DAT0_DATAC3_STATE:
DAT0_DATAC3_STATE.clear()
return True
if RECEIVE_DATAC4 and 10 in DAT0_DATAC4_STATE:
DAT0_DATAC4_STATE.clear()
return True
return False