diff --git a/modem/arq_session.py b/modem/arq_session.py index 5c1dfcfb..ca2694ea 100644 --- a/modem/arq_session.py +++ b/modem/arq_session.py @@ -6,11 +6,24 @@ from modem_frametypes import FRAME_TYPE class ARQSession(): - MODE_BY_SPEED = [ - codec2.FREEDV_MODE.datac4, - codec2.FREEDV_MODE.datac3, - codec2.FREEDV_MODE.datac1, - ] + SPEED_LEVEL_DICT = { + 0: { + 'mode': codec2.FREEDV_MODE.datac4, + 'min_snr': -10, + 'duration_per_frame': 5.17, + }, + 1: { + 'mode': codec2.FREEDV_MODE.datac3, + 'min_snr': 0, + 'duration_per_frame': 3.19, + }, + 2: { + 'mode': codec2.FREEDV_MODE.datac1, + 'min_snr': 3, + 'duration_per_frame': 4.18, + }, + } + def __init__(self, config: dict, tx_frame_queue: queue.Queue, dxcall: str): self.logger = structlog.get_logger(type(self).__name__) @@ -36,7 +49,7 @@ class ARQSession(): logger(msg) def get_mode_by_speed_level(self, speed_level): - return self.MODE_BY_SPEED[speed_level] + return self.SPEED_LEVEL_DICT[speed_level]["mode"] def transmit_frame(self, frame: bytearray): self.log("Transmitting frame") @@ -55,7 +68,7 @@ class ARQSession(): def get_data_payload_size(self): return self.frame_factory.get_available_data_payload_for_mode( FRAME_TYPE.ARQ_BURST_FRAME, - self.MODE_BY_SPEED[self.speed_level] + self.SPEED_LEVEL_DICT[self.speed_level]["mode"] ) def set_details(self, snr, frequency_offset): diff --git a/modem/arq_session_irs.py b/modem/arq_session_irs.py index 5542658f..3df6f5af 100644 --- a/modem/arq_session_irs.py +++ b/modem/arq_session_irs.py @@ -52,6 +52,8 @@ class ARQSessionIRS(arq_session.ARQSession): self.received_bytes = 0 self.received_crc = None + self.transmitted_acks = 0 + def set_modem_decode_modes(self, modes): pass @@ -65,6 +67,13 @@ class ARQSessionIRS(arq_session.ARQSession): self.transmit_frame(frame) self.log(f"Waiting {timeout} seconds...") if not self.event_frame_received.wait(timeout): + # use case: data burst got lost, we want to send a NACK with updated speed level + if self.state in [self.STATE_BURST_REPLY_SENT, self.STATE_INFO_ACK_SENT]: + self.transmitted_acks = 0 + self.calibrate_speed_settings() + self.send_burst_nack() + return + self.log("Timeout waiting for ISS. Session failed.") self.set_state(self.STATE_FAILED) @@ -94,6 +103,12 @@ class ARQSessionIRS(arq_session.ARQSession): self.launch_transmit_and_wait(info_ack, self.TIMEOUT_CONNECT) self.set_state(self.STATE_INFO_ACK_SENT) + def send_burst_nack(self): + self.calibrate_speed_settings() + 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) + + def process_incoming_data(self, frame): if frame['offset'] != self.received_bytes: self.logger.info(f"Discarding data frame due to wrong offset", frame=self.frame_received) @@ -116,12 +131,14 @@ class ARQSessionIRS(arq_session.ARQSession): def receive_data(self, burst_frame): self.process_incoming_data(burst_frame) - + self.calibrate_speed_settings() ack = self.frame_factory.build_arq_burst_ack( self.id, self.received_bytes, self.speed_level, self.frames_per_burst, self.snr[0]) if not self.all_data_received(): + # increase ack counter + self.transmitted_acks += 1 self.transmit_and_wait(ack) self.set_state(self.STATE_BURST_REPLY_SENT) return @@ -136,17 +153,12 @@ class ARQSessionIRS(arq_session.ARQSession): self.set_state(self.STATE_FAILED) def calibrate_speed_settings(self): - return - - # decrement speed level after the 2nd retry - if self.RETRIES_TRANSFER - self.retries >= 2: - self.speed -= 1 - self.speed = max(self.speed, 0) - return + # if we have two ACKS, then consider increasing speed level + if self.transmitted_acks >= 2: + self.transmitted_acks = 0 + new_speed_level = min(self.speed_level + 1, len(self.SPEED_LEVEL_DICT) - 1) - # increment speed level after 2 successfully sent bursts and fitting snr - # TODO + # check first if the next mode supports the actual snr + if self.snr >= self.SPEED_LEVEL_DICT[new_speed_level]["min_snr"]: + self.speed_level = new_speed_level - - self.speed = self.speed - self.frames_per_burst = self.frames_per_burst diff --git a/modem/arq_session_iss.py b/modem/arq_session_iss.py index 72fda0f6..fdb6580d 100644 --- a/modem/arq_session_iss.py +++ b/modem/arq_session_iss.py @@ -105,7 +105,7 @@ class ARQSessionISS(arq_session.ARQSession): offset = self.confirmed_bytes payload = self.data[offset : offset + payload_size] data_frame = self.frame_factory.build_arq_burst_frame( - self.MODE_BY_SPEED[self.speed_level], + self.SPEED_LEVEL_DICT[self.speed_level]["mode"], self.id, self.confirmed_bytes, payload) burst.append(data_frame)