first redesigned code for selective repeat arq

This commit is contained in:
DJ2LS 2023-04-25 15:46:17 +02:00
parent 6e9119cc3c
commit 2a1ffef439
5 changed files with 261 additions and 141 deletions

View file

@ -483,7 +483,7 @@ window.addEventListener("DOMContentLoaded", () => {
command: "msg",
dxcallsign: dxcallsign,
mode: 255,
frames: 1,
frames: 5,
data: data_with_attachment,
checksum: file_checksum,
uuid: uuid,
@ -1443,7 +1443,7 @@ update_chat = function (obj) {
command: "msg",
dxcallsign: doc.dxcallsign,
mode: 255,
frames: 1,
frames: 5,
data: data_with_attachment,
checksum: doc.checksum,
uuid: doc.uuid,

View file

@ -119,6 +119,9 @@ if api is None or "api" not in locals():
api.freedv_open.argype = [ctypes.c_int] # type: ignore
api.freedv_open.restype = ctypes.c_void_p
api.freedv_set_sync.argype = [ctypes.c_void_p, ctypes.c_int] # type: ignore
api.freedv_set_sync.restype = ctypes.c_void_p
api.freedv_open_advanced.argtype = [ctypes.c_int, ctypes.c_void_p] # type: ignore
api.freedv_open_advanced.restype = ctypes.c_void_p

View file

@ -85,6 +85,8 @@ class DATA:
# Flag to indicate if we received an request for repeater frames
self.rpt_request_received = False
self.rpt_request_buffer = [] # requested frames, saved in a list
self.burst_rpt_counter = 0
self.rx_start_of_transmission = 0 # time of transmission start
# 3 bytes for the BOF Beginning of File indicator in a data frame
@ -95,6 +97,8 @@ class DATA:
self.tx_n_max_retries_per_burst = 40
self.rx_n_max_retries_per_burst = 40
self.n_retries_per_burst = 0
self.rx_n_frame_of_burst = 0
self.rx_n_frames_per_burst = 0
# Flag to indicate if we recevied a low bandwidth mode channel opener
self.received_LOW_BANDWIDTH_MODE = False
@ -125,12 +129,12 @@ class DATA:
FREEDV_MODE.datac1.value,
]
# List for minimum SNR operating level for the corresponding mode in self.mode_list
self.snr_list_high_bw = [-10, 0, 3]
self.snr_list_high_bw = [-10, 0-1, 3-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
# TODO: Adjust these times
self.time_list_high_bw = [6+5, 7, 8]
self.time_list_high_bw = [6+5, 7, 10]
# -------------- AVAILABLE MODES END-----------
# Mode list for selecting between low bandwidth ( 500Hz ) and modes with higher bandwidth
@ -455,6 +459,8 @@ class DATA:
:param repeat_delay: Delay time before sending repeat frame, defaults to 0
:type repeat_delay: int, optional
"""
print(frame_to_tx[0])
print(frame_to_tx)
frame_type = FR_TYPE(int.from_bytes(frame_to_tx[0][:1], byteorder="big")).name
self.log.debug("[TNC] enqueue_frame_for_tx", c2_mode=FREEDV_MODE(c2_mode).name, data=frame_to_tx, type=frame_type)
@ -550,34 +556,28 @@ class DATA:
while static.CHANNEL_BUSY and time.time() < channel_busy_timeout and not self.check_if_mode_fits_to_busy_slot():
threading.Event().wait(0.01)
# reset burst timeout in case we had to wait too long
self.burst_last_received = time.time() + channel_busy_timeout + 8
# Transmit frame
# TODO: Do we have to send , self.send_ident_frame(False) ?
# self.enqueue_frame_for_tx([ack_frame, self.send_ident_frame(False)], c2_mode=FREEDV_MODE.sig1.value, copies=3, repeat_delay=0)
self.enqueue_frame_for_tx([ack_frame], c2_mode=FREEDV_MODE.sig1.value, copies=3, repeat_delay=0)
# reset burst timeout in case we had to wait too long
self.burst_last_received = time.time()
def send_retransmit_request_frame(self, freedv) -> None:
def send_retransmit_request_frame(self) -> None:
# check where a None is in our burst buffer and do frame+1, because lists start at 0
# FIXME: Check to see if there's a `frame - 1` in the receive portion. Remove both if there is.
print(static.RX_BURST_BUFFER)
missing_frames = [
frame + 1
for frame, element in enumerate(static.RX_BURST_BUFFER)
if element is None
]
# set n frames per burst to modem
# this is an idea, so it's not getting lost....
# we need to work on this
codec2.api.freedv_set_frames_per_burst(freedv, len(missing_frames))
# TODO: Trim `missing_frames` bytesarray to [7:13] (6) frames, if it's larger.
# TODO: Instead of using int we could use a binary flag
# then create a repeat frame
rpt_frame = bytearray(self.length_sig1_frame)
rpt_frame[:1] = bytes([FR_TYPE.FR_REPEAT.value])
rpt_frame[1:2] = self.session_id
rpt_frame[2:2+len(missing_frames)] = missing_frames
self.log.info("[TNC] ARQ | RX | Requesting", frames=missing_frames)
# Transmit frame
@ -623,7 +623,7 @@ class DATA:
nack_frame[3:4] = bytes([int(self.speed_level)])
# wait while timeout not reached and our busy state is busy
channel_busy_timeout = time.time() + 5
channel_busy_timeout = time.time() + 5 + 5
while static.CHANNEL_BUSY and time.time() < channel_busy_timeout and not self.check_if_mode_fits_to_busy_slot():
threading.Event().wait(0.01)
@ -686,22 +686,19 @@ class DATA:
# Extract some important data from the frame
# Get sequence number of burst frame
rx_n_frame_of_burst = int.from_bytes(bytes(data_in[:1]), "big") - 10
self.rx_n_frame_of_burst = int.from_bytes(bytes(data_in[:1]), "big") - 10
# Get number of bursts from received frame
rx_n_frames_per_burst = int.from_bytes(bytes(data_in[1:2]), "big")
self.rx_n_frames_per_burst = int.from_bytes(bytes(data_in[1:2]), "big")
# The RX burst buffer needs to have a fixed length filled with "None".
# We need this later for counting the "Nones" to detect missing data.
# Check if burst buffer has expected length else create it
if len(static.RX_BURST_BUFFER) != rx_n_frames_per_burst:
static.RX_BURST_BUFFER = [None] * rx_n_frames_per_burst
if len(static.RX_BURST_BUFFER) != self.rx_n_frames_per_burst:
static.RX_BURST_BUFFER = [None] * self.rx_n_frames_per_burst
# Append data to rx burst buffer
# [frame_type][n_frames_per_burst][CRC24][CRC24]
# static.RX_BURST_BUFFER[rx_n_frame_of_burst] = data_in[8:] # type: ignore
static.RX_BURST_BUFFER[rx_n_frame_of_burst] = data_in[3:] # type: ignore
static.RX_BURST_BUFFER[self.rx_n_frame_of_burst] = data_in[self.arq_burst_header_size:] # type: ignore
self.log.debug("[TNC] static.RX_BURST_BUFFER", buffer=static.RX_BURST_BUFFER)
static.DXGRID = b'------'
helpers.add_to_heard_stations(
@ -723,6 +720,9 @@ class DATA:
# static.RX_FRAME_BUFFER += static.RX_BURST_BUFFER[i]
temp_burst_buffer += bytes(value) # type: ignore
# free up burst buffer
static.RX_BURST_BUFFER = []
# TODO: Needs to be removed as soon as mode error is fixed
# catch possible modem error which leads into false byteorder
# modem possibly decodes too late - data then is pushed to buffer
@ -736,12 +736,15 @@ class DATA:
"[TNC] ARQ | RX | wrong byteorder received - dropping data"
)
# we need to run a return here, so we are not sending an ACK
return
#return
except Exception as e:
self.log.warning(
"[TNC] ARQ | RX | wrong byteorder check failed", e=e
)
self.log.debug("[TNC] temp_burst_buffer", buffer=temp_burst_buffer)
self.log.debug("[TNC] static.RX_FRAME_BUFFER", buffer=static.RX_FRAME_BUFFER)
# if frame buffer ends not with the current frame, we are going to append new data
# if data already exists, we received the frame correctly,
# but the ACK frame didn't receive its destination (ISS)
@ -749,7 +752,6 @@ class DATA:
self.log.info(
"[TNC] ARQ | RX | Frame already received - sending ACK again"
)
static.RX_BURST_BUFFER = []
else:
# Here we are going to search for our data in the last received bytes.
@ -759,7 +761,7 @@ class DATA:
# temp_burst_buffer --> new data
# search_area --> area where we want to search
search_area = self.arq_burst_last_payload
search_area = self.arq_burst_last_payload * self.rx_n_frames_per_burst
search_position = len(static.RX_FRAME_BUFFER) - search_area
# if search position < 0, then search position = 0
@ -801,9 +803,13 @@ class DATA:
self.arq_calculate_speed_level(snr)
self.data_channel_last_received = int(time.time()) + 6 + 6
# Create and send ACK frame
self.log.info("[TNC] ARQ | RX | SENDING ACK", finished=static.ARQ_SECONDS_UNTIL_FINISH,
bytesperminute=static.ARQ_BYTES_PER_MINUTE)
while static.IS_CODEC2_TRAFFIC:
print("waiting.....")
self.send_burst_ack_frame(snr)
# Reset n retries per burst counter
@ -829,27 +835,40 @@ class DATA:
irs=helpers.bool_to_string(self.is_IRS)
)
elif rx_n_frame_of_burst == rx_n_frames_per_burst - 1:
# We have "Nones" in our rx buffer,
# Check if we received last frame of burst - this is an indicator for missed frames.
# With this way of doing this, we always MUST receive the last
# frame of a burst otherwise the entire burst is lost
# TODO: See if a timeout on the send side with re-transmit last burst would help.
self.log.debug(
"[TNC] all frames in burst received:",
frame=rx_n_frame_of_burst,
frames=rx_n_frames_per_burst,
)
self.send_retransmit_request_frame(freedv)
self.calculate_transfer_rate_rx(
self.rx_start_of_transmission, len(static.RX_FRAME_BUFFER)
)
#elif self.rx_n_frame_of_burst == self.rx_n_frames_per_burst:
# # We have "Nones" in our rx buffer,
# # Check if we received last frame of burst - this is an indicator for missed frames.
# # With this way of doing this, we always MUST receive the last
# # frame of a burst otherwise the entire burst is lost
# # TODO: See if a timeout on the send side with re-transmit last burst would help.
# self.log.debug(
# "[TNC] last frames of burst received:",
# frame=self.rx_n_frame_of_burst,
# frames=self.rx_n_frames_per_burst,
#
# )
# self.calculate_transfer_rate_rx(
# self.rx_start_of_transmission, len(static.RX_FRAME_BUFFER)
# )
#elif self.rx_n_frame_of_burst not in [self.rx_n_frames_per_burst - 1]:
# self.log.info(
# "[TNC] data_handler: received burst",
# frame=self.rx_n_frame_of_burst + 1,
# frames=self.rx_n_frames_per_burst,
# )
#else:
# self.log.error(
# "[TNC] data_handler: Should not reach this point...",
# frame=self.rx_n_frame_of_burst + 1,
# frames=self.rx_n_frames_per_burst,
# )
else:
self.log.error(
"[TNC] data_handler: Should not reach this point...",
frame=rx_n_frame_of_burst,
frames=rx_n_frames_per_burst,
self.log.warning(
"[TNC] data_handler: missing data in burst buffer...",
frame=self.rx_n_frame_of_burst + 1,
frames=self.rx_n_frames_per_burst
)
# We have a BOF and EOF flag in our data. If we received both we received our frame.
@ -1220,50 +1239,72 @@ class DATA:
# Append data frames with n_frames_per_burst to tempbuffer
# TODO: this part needs a complete rewrite!
# n_frames_per_burst = 1 is working
arqheader = bytearray()
# arqheader[:1] = bytes([FR_TYPE.BURST_01.value + i])
arqheader[:1] = bytes([FR_TYPE.BURST_01.value])
arqheader[1:2] = bytes([n_frames_per_burst])
arqheader[2:3] = self.session_id
# check for maximum frames per burst for remaining data
n_frames_per_burst = 1
max_n_frames_per_burst = 1
print(payload_per_frame)
print(len(data_out[bufferposition:]))
# only check for buffer position if at least one NACK received
self.log.info("[TNC] ----- data buffer position:", iss_buffer_pos=bufferposition, irs_bufferposition=self.irs_buffer_position)
if self.frame_nack_counter > 0 and self.irs_buffer_position != bufferposition:
self.log.error("[TNC] ----- data buffer offset:", iss_buffer_pos=bufferposition, irs_bufferposition=self.irs_buffer_position)
# only adjust buffer position for experimental versions
if 'exp' in static.VERSION:
self.log.warning("[TNC] ----- data adjustment disabled!")
# bufferposition = self.irs_buffer_position
bufferposition_end = bufferposition + payload_per_frame - len(arqheader)
# Normal condition
if bufferposition_end <= len(data_out):
frame = data_out[bufferposition:bufferposition_end]
frame = arqheader + frame
# Pad the last bytes of a frame
if max_n_frames_per_burst > 1:
while (payload_per_frame * n_frames_per_burst) % len(data_out[bufferposition:]) == (payload_per_frame * n_frames_per_burst):
print((payload_per_frame * n_frames_per_burst) % len(data_out))
n_frames_per_burst += 1
if n_frames_per_burst == max_n_frames_per_burst:
break
else:
extended_data_out = data_out[bufferposition:]
extended_data_out += bytes([0]) * (
payload_per_frame - len(extended_data_out) - len(arqheader)
n_frames_per_burst = 1
self.log.info("[TNC] calculated frames_per_burst:", n=n_frames_per_burst)
tempbuffer = []
self.rpt_request_buffer = []
for n_frame in range(0,n_frames_per_burst):
arqheader = bytearray()
arqheader[:1] = bytes([FR_TYPE.BURST_01.value + n_frame])
#####arqheader[:1] = bytes([FR_TYPE.BURST_01.value])
arqheader[1:2] = bytes([n_frames_per_burst])
arqheader[2:3] = self.session_id
# only check for buffer position if at least one NACK received
self.log.info("[TNC] ----- data buffer position:", iss_buffer_pos=bufferposition, irs_bufferposition=self.irs_buffer_position)
if self.frame_nack_counter > 0 and self.irs_buffer_position != bufferposition:
self.log.error("[TNC] ----- data buffer offset:", iss_buffer_pos=bufferposition, irs_bufferposition=self.irs_buffer_position)
# only adjust buffer position for experimental versions
if 'exp' in static.VERSION:
self.log.warning("[TNC] ----- data adjustment disabled!")
# bufferposition = self.irs_buffer_position
bufferposition_end = bufferposition + payload_per_frame - len(arqheader)
# Normal condition
if bufferposition_end <= len(data_out):
frame = data_out[bufferposition:bufferposition_end]
frame = arqheader + frame
# Pad the last bytes of a frame
else:
extended_data_out = data_out[bufferposition:]
extended_data_out += bytes([0]) * (
payload_per_frame - len(extended_data_out) - len(arqheader)
)
frame = arqheader + extended_data_out
######tempbuffer = frame # [frame]
tempbuffer.append(frame)
# add data to our repeat request buffer for easy access if we received a request
self.rpt_request_buffer.append(frame)
# set new buffer position
bufferposition = bufferposition_end
self.log.debug("[TNC] tempbuffer:", tempbuffer=tempbuffer)
self.log.info(
"[TNC] ARQ | TX | FRAMES",
mode=FREEDV_MODE(data_mode).name,
fpb=n_frames_per_burst,
retry=self.tx_n_retry_of_burst,
)
frame = arqheader + extended_data_out
tempbuffer = [frame]
self.log.debug("[TNC] tempbuffer:", tempbuffer=tempbuffer)
self.log.info(
"[TNC] ARQ | TX | FRAMES",
mode=FREEDV_MODE(data_mode).name,
fpb=n_frames_per_burst,
retry=self.tx_n_retry_of_burst,
)
for t_buf_item in tempbuffer:
self.enqueue_frame_for_tx([t_buf_item], c2_mode=data_mode)
self.enqueue_frame_for_tx(tempbuffer, c2_mode=data_mode)
# After transmission finished, wait for an ACK or RPT frame
while (
@ -1564,16 +1605,35 @@ class DATA:
static.HAMLIB_FREQUENCY,
)
self.rpt_request_received = True
self.log.info("[TNC] ARQ REPEAT RECEIVED")
#self.rpt_request_received = True
# Update data_channel timestamp
self.data_channel_last_received = int(time.time())
self.rpt_request_buffer = []
#self.rpt_request_buffer = []
missing_area = bytes(data_in[3:12]) # 1:9
missing_area = bytes(data_in[2:12]) # 1:9
missing_area = missing_area.strip(b"\x00")
print(missing_area)
print(self.rpt_request_buffer)
for i in range(0, 6, 2):
if not missing_area[i: i + 2].endswith(b"\x00\x00"):
self.rpt_request_buffer.insert(0, missing_area[i: i + 2])
tempbuffer = []
for i in range(0, len(missing_area)):
print(missing_area[i])
missing_frames = missing_area[i] -1
# print(self.rpt_request_buffer[missing_frames])
tempbuffer.append(self.rpt_request_buffer[missing_frames])
self.log.info("[TNC] SENDING REPEAT....")
data_mode = self.mode_list[self.speed_level]
print(tempbuffer)
self.enqueue_frame_for_tx(tempbuffer, c2_mode=data_mode)
#for i in range(0, 6, 2):
# if not missing_area[i: i + 2].endswith(b"\x00\x00"):
# self.rpt_request_buffer.insert(0, missing_area[i: i + 2])
############################################################################################################
# ARQ SESSION HANDLER
@ -2317,7 +2377,7 @@ class DATA:
# Reset data_channel/burst timestamps
self.data_channel_last_received = int(time.time())
self.burst_last_received = int(time.time() + 6) # we might need some more time so lets increase this
self.burst_last_received = int(time.time() + 10) # we might need some more time so lets increase this
# Set ARQ State AFTER resetting timeouts
# this avoids timeouts starting too early
@ -2366,7 +2426,7 @@ class DATA:
# Reset data_channel/burst timestamps once again for avoiding running into timeout
self.data_channel_last_received = int(time.time())
self.burst_last_received = int(time.time() + 6) # we might need some more time so lets increase this
self.burst_last_received = int(time.time() + 10) # we might need some more time so lets increase this
def arq_received_channel_is_open(self, data_in: bytes) -> None:
"""
@ -3063,11 +3123,14 @@ class DATA:
self.rx_frame_eof_received = False
self.burst_ack = False
self.rpt_request_received = False
self.burst_rpt_counter = 0
self.data_frame_ack_received = False
static.RX_BURST_BUFFER = []
static.RX_FRAME_BUFFER = b""
self.burst_ack_snr = 0
self.arq_burst_last_payload = 0
self.rx_n_frame_of_burst = 0
self.rx_n_frames_per_burst = 0
# reset modem receiving state to reduce cpu load
modem.RECEIVE_SIG0 = True
@ -3203,12 +3266,19 @@ class DATA:
modem_error_state = modem.get_modem_error_state()
# We want to reach this state only if connected ( == return above not called )
timeout = self.burst_last_received + self.time_list[self.speed_level]
if self.rx_n_frames_per_burst > 1:
frames_left = static.RX_BURST_BUFFER.count(None)
else:
frames_left = 1
print(frames_left)
timeout = self.burst_last_received + (self.time_list[self.speed_level] * frames_left)
print(timeout - time.time())
if timeout <= time.time() or modem_error_state:
print("timeout----------------")
print(time.time() - timeout)
print(time.time() - (self.burst_last_received + self.time_list[self.speed_level]))
print(time.time() - (self.burst_last_received + self.time_list[self.speed_level] * frames_left))
#if time.time() > (self.burst_last_received + (6 * (self.rx_n_frames_per_burst - self.rx_n_frame_of_burst))):
# print("burst timeout reached...")
print("-----------------------")
self.log.warning(
@ -3219,27 +3289,35 @@ class DATA:
modem_error_state=modem_error_state
)
# reset self.burst_last_received
self.burst_last_received = time.time() + self.time_list[self.speed_level]
print(f"frames_per_burst {self.rx_n_frame_of_burst} / {self.rx_n_frames_per_burst}")
if self.rx_n_frames_per_burst > 1 and self.burst_rpt_counter < 100 and None in [static.RX_BURST_BUFFER]:
# reset self.burst_last_received
self.burst_last_received = time.time() + self.time_list[self.speed_level]
self.burst_rpt_counter += 1
self.send_retransmit_request_frame()
else:
# reduce speed level if nack counter increased
self.frame_received_counter = 0
self.burst_nack_counter += 1
if self.burst_nack_counter >= 2:
self.burst_nack_counter = 0
self.speed_level = max(self.speed_level - 1, 0)
static.ARQ_SPEED_LEVEL = self.speed_level
# reset self.burst_last_received
self.burst_last_received = time.time() + self.time_list[self.speed_level]
# Update modes we are listening to
self.set_listening_modes(True, True, self.mode_list[self.speed_level])
# reduce speed level if nack counter increased
self.frame_received_counter = 0
self.burst_nack_counter += 1
if self.burst_nack_counter >= 2:
self.burst_nack_counter = 0
self.speed_level = max(self.speed_level - 1, 0)
static.ARQ_SPEED_LEVEL = self.speed_level
# Why not pass `snr` or `static.SNR`?
self.send_burst_nack_frame_watchdog(0)
# Update modes we are listening to
self.set_listening_modes(True, True, self.mode_list[self.speed_level])
# Update data_channel timestamp
# TODO: Disabled this one for testing.
# self.data_channel_last_received = time.time()
self.n_retries_per_burst += 1
# Why not pass `snr` or `static.SNR`?
self.send_burst_nack_frame_watchdog(0)
# Update data_channel timestamp
# TODO: Disabled this one for testing.
# self.data_channel_last_received = time.time()
self.n_retries_per_burst += 1
else:
# print((self.data_channel_last_received + self.time_list[self.speed_level])-time.time())
pass
@ -3374,6 +3452,7 @@ class DATA:
)
else:
return False
def save_data_to_folder(self,
transmission_uuid,
timestamp,

View file

@ -23,6 +23,7 @@ import numpy as np
import sock
import sounddevice as sd
import static
from static import FRAME_TYPE
import structlog
import ujson as json
import tci
@ -518,6 +519,7 @@ class RF:
frames:
"""
self.reset_data_sync()
if mode == codec2.FREEDV_MODE.datac0.value:
freedv = self.freedv_datac0_tx
@ -586,18 +588,20 @@ class RF:
)
for _ in range(repeats):
# codec2 fsk preamble may be broken -
# at least it sounds like that, so we are disabling it for testing
if self.MODE not in [
codec2.FREEDV_MODE.fsk_ldpc_0.value,
codec2.FREEDV_MODE.fsk_ldpc_1.value,
]:
# Write preamble to txbuffer
codec2.api.freedv_rawdatapreambletx(freedv, mod_out_preamble)
txbuffer += bytes(mod_out_preamble)
# Create modulaton for all frames in the list
# Create modulation for all frames in the list
for frame in frames:
# Write preamble to txbuffer
# codec2 fsk preamble may be broken -
# at least it sounds like that, so we are disabling it for testing
if self.MODE not in [
codec2.FREEDV_MODE.fsk_ldpc_0.value,
codec2.FREEDV_MODE.fsk_ldpc_1.value,
]:
# Write preamble to txbuffer
codec2.api.freedv_rawdatapreambletx(freedv, mod_out_preamble)
txbuffer += bytes(mod_out_preamble)
# Create buffer for data
# Use this if CRC16 checksum is required (DATAc1-3)
buffer = bytearray(payload_bytes_per_frame)
@ -621,16 +625,16 @@ class RF:
codec2.api.freedv_rawdatatx(freedv, mod_out, data)
txbuffer += bytes(mod_out)
# codec2 fsk postamble may be broken -
# at least it sounds like that, so we are disabling it for testing
if self.MODE not in [
codec2.FREEDV_MODE.fsk_ldpc_0.value,
codec2.FREEDV_MODE.fsk_ldpc_1.value,
]:
# Write postamble to txbuffer
codec2.api.freedv_rawdatapostambletx(freedv, mod_out_postamble)
# Append postamble to txbuffer
txbuffer += bytes(mod_out_postamble)
# codec2 fsk postamble may be broken -
# at least it sounds like that, so we are disabling it for testing
if self.MODE not in [
codec2.FREEDV_MODE.fsk_ldpc_0.value,
codec2.FREEDV_MODE.fsk_ldpc_1.value,
]:
# Write postamble to txbuffer
codec2.api.freedv_rawdatapostambletx(freedv, mod_out_postamble)
# Append postamble to txbuffer
txbuffer += bytes(mod_out_postamble)
# Add delay to end of frames
samples_delay = int(self.MODEM_SAMPLE_RATE * (repeat_delay / 1000)) # type: ignore
@ -806,15 +810,31 @@ class RF:
audiobuffer.pop(nin)
nin = codec2.api.freedv_nin(freedv)
if nbytes == bytes_per_frame:
# process commands only if static.LISTEN = True
if static.LISTEN:
self.log.debug(
"[MDM] [demod_audio] Pushing received data to received_queue", nbytes=nbytes
)
self.modem_received_queue.put([bytes_out, freedv, bytes_per_frame])
self.get_scatter(freedv)
self.calculate_snr(freedv)
state_buffer = []
# ignore data channel opener frames for avoiding toggle states
# use case: opener already received, but ack got lost and we are receiving
# an opener again
if mode_name in ["sig1-datac13"] and int.from_bytes(bytes(bytes_out[:1]), "big") in [
FRAME_TYPE.ARQ_SESSION_OPEN.value,
FRAME_TYPE.ARQ_DC_OPEN_W.value,
FRAME_TYPE.ARQ_DC_OPEN_ACK_W.value,
FRAME_TYPE.ARQ_DC_OPEN_N.value,
FRAME_TYPE.ARQ_DC_OPEN_ACK_N.value
]:
print("dropp")
else:
self.log.debug(
"[MDM] [demod_audio] Pushing received data to received_queue", nbytes=nbytes
)
self.modem_received_queue.put([bytes_out, freedv, bytes_per_frame])
self.get_scatter(freedv)
self.calculate_snr(freedv)
state_buffer = []
else:
self.log.warning(
"[MDM] [demod_audio] received frame but ignored processing",
@ -1269,11 +1289,26 @@ class RF:
frames_per_burst = min(frames_per_burst, 1)
frames_per_burst = max(frames_per_burst, 5)
frames_per_burst = 1
codec2.api.freedv_set_frames_per_burst(self.dat0_datac1_freedv, frames_per_burst)
codec2.api.freedv_set_frames_per_burst(self.dat0_datac3_freedv, frames_per_burst)
codec2.api.freedv_set_frames_per_burst(self.dat0_datac4_freedv, frames_per_burst)
codec2.api.freedv_set_frames_per_burst(self.fsk_ldpc_freedv_0, frames_per_burst)
def reset_data_sync(self) -> None:
"""
reset sync state for data modes
:param frames_per_burst: Number of frames per burst requested
:type frames_per_burst: int
"""
codec2.api.freedv_set_sync(self.dat0_datac1_freedv, 0)
codec2.api.freedv_set_sync(self.dat0_datac3_freedv, 0)
codec2.api.freedv_set_sync(self.dat0_datac4_freedv, 0)
codec2.api.freedv_set_sync(self.fsk_ldpc_freedv_0, 0)
def open_codec2_instance(mode: int) -> ctypes.c_void_p:
"""

View file

@ -147,6 +147,9 @@ class FRAME_TYPE(Enum):
"""Lookup for frame types"""
BURST_01 = 10
BURST_02 = 11
BURST_03 = 12
BURST_04 = 13
# ...
BURST_51 = 50
BURST_ACK = 60