ARQ WIP - channel busy detection

This commit is contained in:
DJ2LS 2023-12-30 21:47:16 +01:00
parent ca46949653
commit 7549e34d45
7 changed files with 42 additions and 40 deletions

View file

@ -50,6 +50,9 @@ class ARQSessionIRS(arq_session.ARQSession):
FRAME_TYPE.ARQ_BURST_FRAME.value: 'receive_data',
FRAME_TYPE.ARQ_STOP.value: 'send_stop_ack'
},
IRS_State.ABORTED: {
FRAME_TYPE.ARQ_STOP.value: 'send_stop_ack'
},
}
def __init__(self, config: dict, modem, dxcall: str, session_id: int):

View file

@ -24,14 +24,14 @@ class ARQSessionISS(arq_session.ARQSession):
# DJ2LS: 3 seconds seems to be too small for radios with a too slow PTT toggle time
# DJ2LS: 3.5 seconds is working well WITHOUT a channel busy detection delay
TIMEOUT_CONNECT_ACK = 3.5
TIMEOUT_TRANSFER = 3.5
TIMEOUT_STOP_ACK = 3.5
TIMEOUT_CHANNEL_BUSY = 2
TIMEOUT_CONNECT_ACK = 3.5 + TIMEOUT_CHANNEL_BUSY
TIMEOUT_TRANSFER = 3.5 + TIMEOUT_CHANNEL_BUSY
TIMEOUT_STOP_ACK = 3.5 + TIMEOUT_CHANNEL_BUSY
STATE_TRANSITION = {
ISS_State.OPEN_SENT: {
FRAME_TYPE.ARQ_SESSION_OPEN_ACK.value: 'send_info',
},
ISS_State.INFO_SENT: {
FRAME_TYPE.ARQ_SESSION_OPEN_ACK.value: 'send_info',
@ -167,8 +167,6 @@ class ARQSessionISS(arq_session.ARQSession):
self.event_frame_received.set()
# start with abort sequence
# TODO: We have to wait some time here for avoiding collisions with actual transmissions...
# This could be done by the channel busy detection, for example, if part of def transmit() in modem.py
self.send_stop()
def send_stop(self):

View file

@ -8,6 +8,7 @@ import sounddevice as sd
import structlog
import numpy as np
import queue
import threading
atexit.register(sd._terminate)
@ -313,19 +314,17 @@ def calculate_fft(data, fft_queue, states) -> None:
if addDelay:
# Limit delay counter to a maximum of 200. The higher this value,
# the longer we will wait until releasing state
states.set("channel_busy", True)
states.set_channel_busy_condition_traffic(True)
CHANNEL_BUSY_DELAY = min(CHANNEL_BUSY_DELAY + 10, 200)
else:
# Decrement channel busy counter if no signal has been detected.
CHANNEL_BUSY_DELAY = max(CHANNEL_BUSY_DELAY - 1, 0)
# When our channel busy counter reaches 0, toggle state to False
if CHANNEL_BUSY_DELAY == 0:
states.set("channel_busy", False)
# erase queue if greater than 10
if fft_queue.qsize() >= 10:
states.set_channel_busy_condition_traffic(False)
# erase queue if greater than 3
if fft_queue.qsize() >= 1:
fft_queue = queue.Queue()
fft_queue.put(dfftlist[:315]) # 315 --> bandwidth 3200
except Exception as err:
print(f"[MDM] calculate_fft: Exception: {err}")
print("[MDM] Setting fft=0")
fft_queue.put([0])

View file

@ -101,7 +101,7 @@ for file in files:
#log.info("[C2 ] Libcodec2 loaded", path=file)
break
except OSError as err:
log.warning("[C2 ] Error: Libcodec2 found but not loaded", path=file, e=err)
log.info("[C2 ] Error: Libcodec2 found but not loaded", path=file, e=err)
# Quit module if codec2 cant be loaded
if api is None or "api" not in locals():

View file

@ -37,7 +37,7 @@ class Demodulator():
self.AUDIO_FRAMES_PER_BUFFER_RX = 4800
self.buffer_overflow_counter = [0, 0, 0, 0, 0, 0, 0, 0]
self.is_codec2_traffic_counter = 0
self.is_codec2_traffic_cooldown = 20
self.is_codec2_traffic_cooldown = 10
self.audio_received_queue = audio_rx_q
self.modem_received_queue = modem_rx_q
@ -224,25 +224,18 @@ class Demodulator():
if rx_status not in [0]:
# we need to disable this if in testmode as its causing problems with FIFO it seems
self.states.set("is_codec2_traffic", True)
self.is_codec2_traffic_counter = self.is_codec2_traffic_cooldown
if not self.states.channel_busy:
self.log.debug("[MDM] Setting channel_busy since codec2 data detected")
self.states.set("channel_busy", True)
#self.channel_busy_delay += 10
self.log.debug(
"[MDM] [demod_audio] modem state", mode=mode_name, rx_status=rx_status,
sync_flag=codec2.api.rx_sync_flags_to_text[rx_status]
)
else:
self.states.set("is_codec2_traffic", False)
# decrement codec traffic counter for making state smoother
if self.is_codec2_traffic_counter > 0:
self.is_codec2_traffic_counter -= 1
self.states.set("is_codec2_traffic", True)
self.states.set_channel_busy_condition_codec2(True)
else:
self.states.set("is_codec2_traffic", False)
self.states.set_channel_busy_condition_codec2(False)
if rx_status == 10:
state_buffer.append(rx_status)

View file

@ -221,7 +221,7 @@ class RF:
alc_level=str(self.radio_alc))
def transmit(
self, mode, repeats: int, repeat_delay: int, frames: bytearray
self, mode, repeats: int, repeat_delay: int, frames: bytearray, timeout_channel_busy=5
) -> bool:
"""
@ -256,8 +256,7 @@ class RF:
# Wait for some other thread that might be transmitting
self.states.waitForTransmission()
self.states.setTransmitting(True)
# if we're transmitting FreeDATA signals, reset channel busy state
self.states.set("channel_busy", False)
self.states.channel_busy_event.wait(timeout_channel_busy)
start_of_transmission = time.time()
# TODO Moved ptt toggle some steps before audio is ready for testing
@ -307,7 +306,6 @@ class RF:
# transmit audio
self.transmit_audio(txbuffer_out)
self.states.set("channel_busy", False)
self.radio.set_ptt(False)
self.event_manager.send_ptt_change(False)
self.states.setTransmitting(False)

View file

@ -13,9 +13,11 @@ class StateManager:
# modem related states
# not every state is needed to publish, yet
# TODO can we reduce them?
self.channel_busy = False
self.channel_busy_slot = [False, False, False, False, False]
self.is_codec2_traffic = False
self.channel_busy_event = threading.Event()
self.channel_busy_condition_traffic = threading.Event()
self.channel_busy_condition_codec2 = threading.Event()
self.is_modem_running = False
self.is_modem_busy = False
self.is_beacon_running = False
@ -35,16 +37,6 @@ class StateManager:
self.arq_iss_sessions = {}
self.arq_irs_sessions = {}
self.arq_session_state = 'disconnected'
self.arq_speed_level = 0
self.arq_total_bytes = 0
self.arq_bits_per_second = 0
self.arq_bytes_per_minute = 0
self.arq_transmission_percent = 0
self.arq_compression_factor = 0
self.arq_speed_list = []
self.arq_seconds_until_timeout = 0
self.mesh_routing_table = []
@ -89,7 +81,6 @@ class StateManager:
return {
"freedata-message": msgtype,
"channel_busy": self.channel_busy,
"is_codec2_traffic": self.is_codec2_traffic,
"is_modem_running": self.is_modem_running,
"is_beacon_running": self.is_beacon_running,
"radio_status": self.radio_status,
@ -162,3 +153,23 @@ class StateManager:
self.activities_list[activity_id] = activity_data
self.sendStateUpdate()
def calculate_channel_busy_state(self):
if self.channel_busy_condition_traffic.is_set() and self.channel_busy_condition_codec2.is_set():
self.channel_busy_event.set()
else:
self.channel_busy_event = threading.Event()
def set_channel_busy_condition_traffic(self, busy):
if not busy:
self.channel_busy_condition_traffic.set()
else:
self.channel_busy_condition_traffic = threading.Event()
self.calculate_channel_busy_state()
def set_channel_busy_condition_codec2(self, traffic):
if not traffic:
self.channel_busy_condition_codec2.set()
else:
self.channel_busy_condition_codec2 = threading.Event()
self.calculate_channel_busy_state()