From 5842519e2a7f5aa53ad5f70572f132179a02c800 Mon Sep 17 00:00:00 2001 From: DJ2LS Date: Fri, 8 Dec 2023 11:42:38 +0100 Subject: [PATCH] WIP adding arq data frame --- modem/arq_session_iss.py | 16 +++++++---- modem/data_frame_factory.py | 56 +++++++++++++++++++++++++++++-------- modem/modem_frametypes.py | 10 +++---- 3 files changed, 59 insertions(+), 23 deletions(-) diff --git a/modem/arq_session_iss.py b/modem/arq_session_iss.py index 6620137e..544d5457 100644 --- a/modem/arq_session_iss.py +++ b/modem/arq_session_iss.py @@ -74,17 +74,21 @@ class ARQSessionISS(arq_session.ARQSession): # Sends the full payload in multiple frames def send_data(self): + # Todo make this n frames per burst stuff part of the protocol again + # hard coding n frames per burst to 1 for now. + n_frames_per_burst = 1 + n_frame = 1 + offset = 0 while offset < len(self.data): max_size = self.get_payload_size(self.speed_level) end_offset = min(len(self.data), max_size) frame_payload = self.data[offset:end_offset] - # TODO build_arq_session_connect is wrong frame. It seems we need to create the correct function for this - #data_frame = self.frame_factory.build_arq_session_connect(self.speed_level, self.dxcall, frame_payload) - #self.set_state(self.STATE_SENDING) - #if not self.send_arq(data_frame): - # return False - #offset = end_offset + 1 + data_frame = self.frame_factory.build_arq_data_frame(self.id, n_frames_per_burst, max_size, n_frame, frame_payload) + self.set_state(self.STATE_SENDING) + if not self.send_arq(data_frame): + return False + offset = end_offset + 1 # Send part of the payload using ARQ def send_arq(self, frame): diff --git a/modem/data_frame_factory.py b/modem/data_frame_factory.py index 62349245..365206b5 100644 --- a/modem/data_frame_factory.py +++ b/modem/data_frame_factory.py @@ -101,7 +101,7 @@ class DataFrameFactory: def _load_arq_templates(self): # same structure for narrow and wide types - arq_dc_open = { + arq_session_open = { "frame_length": self.LENGTH_SIG0_FRAME, "destination_crc": 3, "origin_crc": 3, @@ -109,22 +109,32 @@ class DataFrameFactory: "session_id": 1, } # arq connect frames - self.template_list[FR_TYPE.ARQ_SESSION_OPEN_N.value] = arq_dc_open - self.template_list[FR_TYPE.ARQ_SESSION_OPEN_W.value] = arq_dc_open + self.template_list[FR_TYPE.ARQ_SESSION_OPEN_N.value] = arq_session_open + self.template_list[FR_TYPE.ARQ_SESSION_OPEN_W.value] = arq_session_open # same structure for narrow and wide types - arq_dc_open_ack = { + arq_session_open_ack = { "frame_length": self.LENGTH_SIG0_FRAME, "session_id": 1, "speed_level": 1, "arq_protocol_version": 1 } # arq connect ack frames - self.template_list[FR_TYPE.ARQ_SESSION_OPEN_ACK_N.value] = arq_dc_open_ack - self.template_list[FR_TYPE.ARQ_SESSION_OPEN_ACK_W.value] = arq_dc_open_ack + self.template_list[FR_TYPE.ARQ_SESSION_OPEN_ACK_N.value] = arq_session_open_ack + self.template_list[FR_TYPE.ARQ_SESSION_OPEN_ACK_W.value] = arq_session_open_ack + # arq data frame + # register n frames + for n_frame in range(0,50): + self.template_list[FR_TYPE.BURST_01.value + n_frame] = { + "frame_length": "dynamic", + "n_frames_per_burst": 1, + "session_id": 1, + "payload": "dynamic", + } + # arq burst ack self.template_list[FR_TYPE.BURST_ACK.value] = { "frame_length": self.LENGTH_SIG1_FRAME, @@ -163,10 +173,20 @@ class DataFrameFactory: } - def construct(self, frametype, content): - frame_template = self.template_list[frametype.value] - frame_length = frame_template["frame_length"] - frame = bytearray(frame_length) + def construct(self, frametype, content, frame_length=LENGTH_SIG1_FRAME): + # frame_length: can be set manually for data frames, whose length can be dynamic regarding corresponding mode + + # data bursts have a frame type range of 01-50 + if frametype in range(1, 50): + frame_template = self.template_list[frametype.value] + frame = bytearray(frame_length) + # override "dynamic" value of payload length + self.template_list[frame_template].payload = frame_length - 3 + + else: + frame_template = self.template_list[frametype.value] + frame_length = frame_template["frame_length"] + frame = bytearray(frame_length) buffer_position = 1 for key, item_length in frame_template.items(): @@ -222,9 +242,11 @@ class DataFrameFactory: :rtype: int """ freedv = codec2.open_instance(mode) - # TODO add close session # get number of bytes per frame for mode - return int(codec2.api.freedv_get_bits_per_modem_frame(freedv) / 8) + bytes_per_frame = int(codec2.api.freedv_get_bits_per_modem_frame(freedv) / 8) + # TODO add close session + return bytes_per_frame + def build_ping(self, destination): payload = { @@ -326,6 +348,16 @@ class DataFrameFactory: channel_type = FR_TYPE.ARQ_SESSION_OPEN_ACK_W if isWideband else FR_TYPE.ARQ_SESSION_OPEN_ACK_N return self.construct(channel_type, payload) + def build_arq_data_frame(self, session_id: bytes, n_frames_per_burst: int, max_size: int, n_frame: int, frame_payload: bytes): + payload = { + "n_frames_per_burst": bytes([n_frames_per_burst]), + "session_id": session_id, + "data": frame_payload + } + + return self.construct(FR_TYPE.FR_TYPE.BURST_01.value + n_frame, payload, frame_length=max_size) + + def build_arq_burst_ack(self, session_id: bytes, snr: int, speed_level: int, len_arq_rx_frame_buffer: int): # ack_frame = bytearray(self.length_sig1_frame) # ack_frame[:1] = bytes([FR_TYPE.BURST_ACK.value]) diff --git a/modem/modem_frametypes.py b/modem/modem_frametypes.py index 728190be..ce315c9e 100644 --- a/modem/modem_frametypes.py +++ b/modem/modem_frametypes.py @@ -7,12 +7,12 @@ from enum import Enum class FRAME_TYPE(Enum): """Lookup for frame types""" - BURST_01 = 10 - BURST_02 = 11 - BURST_03 = 12 - BURST_04 = 13 + BURST_01 = 1 + BURST_02 = 2 + BURST_03 = 3 + BURST_04 = 4 # ... - BURST_51 = 50 + BURST_50 = 50 BURST_ACK = 60 FR_ACK = 61 FR_REPEAT = 62