diff --git a/modem/arq_session.py b/modem/arq_session.py index 75334d6a..4b259cd6 100644 --- a/modem/arq_session.py +++ b/modem/arq_session.py @@ -44,6 +44,8 @@ class ARQSession(): self.modem = modem self.speed_level = 0 + self.previous_speed_level = 0 + self.frames_per_burst = 1 self.frame_factory = data_frame_factory.DataFrameFactory(self.config) @@ -97,7 +99,6 @@ class ARQSession(): received_data, type_byte = getattr(self, action_name)(frame) if isinstance(received_data, bytearray) and isinstance(type_byte, int): self.arq_data_type_handler.dispatch(type_byte, received_data) - return self.log(f"Ignoring unknown transition from state {self.state.name} with frame {frame['frame_type']}") diff --git a/modem/arq_session_irs.py b/modem/arq_session_irs.py index 9141d50f..52dd8fa4 100644 --- a/modem/arq_session_irs.py +++ b/modem/arq_session_irs.py @@ -76,8 +76,6 @@ class ARQSessionIRS(arq_session.ARQSession): self.received_bytes = 0 self.received_crc = None - self.speed_level = 0 - self.abort = False def all_data_received(self): @@ -160,16 +158,14 @@ class ARQSessionIRS(arq_session.ARQSession): self.process_incoming_data(burst_frame) if not self.all_data_received(): - downshift, upshift = self.calibrate_speed_settings() + self.calibrate_speed_settings(burst_frame=burst_frame) ack = self.frame_factory.build_arq_burst_ack( self.id, self.received_bytes, self.speed_level, self.frames_per_burst, self.snr[0], - flag_abort=self.abort, - flag_upshift=upshift, - flag_downshift=downshift + flag_abort=self.abort ) self.set_state(IRS_State.BURST_REPLY_SENT) @@ -204,53 +200,46 @@ class ARQSessionIRS(arq_session.ARQSession): flag_checksum=False) self.transmit_frame(ack, mode=FREEDV_MODE.signalling) self.log("CRC fail at the end of transmission!") - self.transmission_failed() + return self.transmission_failed() + + def calibrate_speed_settings(self, burst_frame=None): + if burst_frame: + received_speed_level = burst_frame['speed_level'] + else: + received_speed_level = 0 - def calibrate_speed_settings(self): latest_snr = self.snr[-1] if self.snr else -10 appropriate_speed_level = self.get_appropriate_speed_level(latest_snr) modes_to_decode = {} - # Log the latest SNR, current, and appropriate speed levels for clarity + # Log the latest SNR, current, appropriate speed levels, and the previous speed level self.log( - f"Latest SNR: {latest_snr}, Current Speed Level: {self.speed_level}, Appropriate Speed Level: {appropriate_speed_level}", + f"Latest SNR: {latest_snr}, Current Speed Level: {self.speed_level}, Appropriate Speed Level: {appropriate_speed_level}, Previous Speed Level: {self.previous_speed_level}", isWarning=True) - # Initialize shift flags - upshift = False - downshift = False - - # Determine if we need to shift + # Adjust the speed level by one step towards the appropriate level, if needed if appropriate_speed_level > self.speed_level and self.speed_level < len(self.SPEED_LEVEL_DICT) - 1: - # Upshift by one level, but remember to listen on the current level as well in case of loosing ACK - previous_speed_level = self.speed_level - self.speed_level += 1 - upshift = True - self.log(f"Upshifting. New speed level: {self.speed_level}", isWarning=True) + if received_speed_level == self.speed_level: + self.speed_level += 1 elif appropriate_speed_level < self.speed_level and self.speed_level > 0: - # Downshift by one level, but remember to listen on the current level as well in case of loosing ACK - previous_speed_level = self.speed_level - self.speed_level -= 1 - downshift = True - self.log(f"Downshifting. New speed level: {self.speed_level}", isWarning=True) - else: - # No shift needed, set previous to current for correct mode decoding setup - previous_speed_level = self.speed_level + if received_speed_level == self.speed_level: + self.speed_level -= 1 - # Decode the current mode + # Always decode the current mode current_mode = self.get_mode_by_speed_level(self.speed_level).value modes_to_decode[current_mode] = True - # Additionally, decode the previous speed level mode if it has changed - if upshift or downshift: - previous_mode = self.get_mode_by_speed_level(previous_speed_level).value + # Decode the previous speed level mode + if self.previous_speed_level != self.speed_level: + previous_mode = self.get_mode_by_speed_level(self.previous_speed_level).value modes_to_decode[previous_mode] = True + self.previous_speed_level = self.speed_level # Update the previous speed level - self.log(f"Modes to Decode: {modes_to_decode.keys()}", isWarning=True) - # Apply the new decode mode based on the updated speed level + self.log(f"Modes to Decode: {list(modes_to_decode.keys())}", isWarning=True) + # Apply the new decode mode based on the updated and previous speed levels self.modem.demodulator.set_decode_mode(modes_to_decode) - return downshift, upshift + return self.speed_level def abort_transmission(self): self.log(f"Aborting transmission... setting abort flag") diff --git a/modem/arq_session_iss.py b/modem/arq_session_iss.py index 1f1d34b1..8308067d 100644 --- a/modem/arq_session_iss.py +++ b/modem/arq_session_iss.py @@ -68,8 +68,6 @@ class ARQSessionISS(arq_session.ARQSession): self.frame_factory = data_frame_factory.DataFrameFactory(self.config) - self.speed_level = 0 - def generate_id(self): while True: random_int = random.randint(1,255) @@ -113,21 +111,34 @@ class ARQSessionISS(arq_session.ARQSession): # Log the received frame for debugging self.log(f"Received frame: {frame}", isWarning=True) - # Safely extract upshift and downshift flags with default to False if not present - upshift = frame['flag'].get('UPSHIFT', False) - downshift = frame['flag'].get('DOWNSHIFT', False) - - # Check for UPSHIFT frame and ensure speed level does not exceed max limit - if upshift and not downshift and self.speed_level < len(self.SPEED_LEVEL_DICT) - 1: - self.speed_level += 1 - self.log(f"Upshifting. New speed level: {self.speed_level}") - - # Check for DOWNSHIFT frame and ensure speed level does not go below 0 - elif downshift and not upshift and self.speed_level > 0: - self.speed_level -= 1 - self.log(f"Downshifting. New speed level: {self.speed_level}") + # Extract the speed_level directly from the frame + if 'speed_level' in frame: + new_speed_level = frame['speed_level'] + # Ensure the new speed level is within the allowable range + if 0 <= new_speed_level < len(self.SPEED_LEVEL_DICT): + # Log the speed level change if it's different from the current speed level + if new_speed_level != self.speed_level: + self.log(f"Changing speed level from {self.speed_level} to {new_speed_level}", isWarning=True) + self.previous_speed_level = self.speed_level # Store the current speed level as previous + self.speed_level = new_speed_level # Update the current speed level + else: + self.log("Received speed level is the same as the current speed level.", isWarning=True) + else: + self.log(f"Received speed level {new_speed_level} is out of allowable range.", isWarning=True) + else: + self.log("No speed level specified in the received frame.", isWarning=True) + # Apply the new decode mode based on the updated speed level, including the previous speed level + modes_to_decode = { + self.get_mode_by_speed_level(self.speed_level).value: True, + } + # Include the previous speed level mode if it's different from the current + if hasattr(self, 'previous_speed_level') and self.previous_speed_level != self.speed_level: + modes_to_decode[self.get_mode_by_speed_level(self.previous_speed_level).value] = True + self.log(f"Modes to Decode: {list(modes_to_decode.keys())}", isWarning=True) + # Apply the new decode mode based on the current and previous speed levels + self.modem.demodulator.set_decode_mode(modes_to_decode) def send_info(self, irs_frame): # check if we received an abort flag @@ -174,7 +185,7 @@ class ARQSessionISS(arq_session.ARQSession): payload = self.data[offset : offset + payload_size] data_frame = self.frame_factory.build_arq_burst_frame( self.SPEED_LEVEL_DICT[self.speed_level]["mode"], - self.id, self.confirmed_bytes, payload) + self.id, self.confirmed_bytes, payload, self.speed_level) burst.append(data_frame) self.launch_twr(burst, self.TIMEOUT_TRANSFER, self.RETRIES_CONNECT, mode='auto') self.set_state(ISS_State.BURST_SENT) diff --git a/modem/data_frame_factory.py b/modem/data_frame_factory.py index 894e2d1c..3fb4c9fb 100644 --- a/modem/data_frame_factory.py +++ b/modem/data_frame_factory.py @@ -15,8 +15,6 @@ class DataFrameFactory: 'FINAL': 0, # Bit-position for indicating the FINAL state 'ABORT': 1, # Bit-position for indicating the ABORT request 'CHECKSUM': 2, # Bit-position for indicating the CHECKSUM is correct or not - 'DOWNSHIFT': 3, # Bit-position for indicating a requested ARQ DOWNSHIFT - 'UPSHIFT': 4, # Bit-position for indicating a requested ARQ UPSHIFT } def __init__(self, config): @@ -146,6 +144,7 @@ class DataFrameFactory: self.template_list[FR_TYPE.ARQ_BURST_FRAME.value] = { "frame_length": None, "session_id": 1, + "speed_level": 1, "offset": 4, "data": "dynamic", } @@ -396,9 +395,10 @@ class DataFrameFactory: } return self.construct(FR_TYPE.ARQ_SESSION_INFO_ACK, payload) - def build_arq_burst_frame(self, freedv_mode: codec2.FREEDV_MODE, session_id: int, offset: int, data: bytes): + def build_arq_burst_frame(self, freedv_mode: codec2.FREEDV_MODE, session_id: int, offset: int, data: bytes, speed_level: int): payload = { "session_id": session_id.to_bytes(1, 'big'), + "speed_level": speed_level.to_bytes(4, 'big'), "offset": offset.to_bytes(4, 'big'), "data": data, } @@ -406,7 +406,7 @@ class DataFrameFactory: return frame def build_arq_burst_ack(self, session_id: bytes, offset, speed_level: int, - frames_per_burst: int, snr: int, flag_final=False, flag_checksum=False, flag_abort=False, flag_downshift=False, flag_upshift=False): + frames_per_burst: int, snr: int, flag_final=False, flag_checksum=False, flag_abort=False): flag = 0b00000000 if flag_final: flag = helpers.set_flag(flag, 'FINAL', True, self.ARQ_FLAGS) @@ -417,14 +417,6 @@ class DataFrameFactory: if flag_abort: flag = helpers.set_flag(flag, 'ABORT', True, self.ARQ_FLAGS) - if flag_downshift: - flag = helpers.set_flag(flag, 'DOWNSHIFT', True, self.ARQ_FLAGS) - flag = helpers.set_flag(flag, 'UPSHIFT', False, self.ARQ_FLAGS) - - if flag_upshift: - flag = helpers.set_flag(flag, 'DOWNSHIFT', False, self.ARQ_FLAGS) - flag = helpers.set_flag(flag, 'UPSHIFT', True, self.ARQ_FLAGS) - payload = { "session_id": session_id.to_bytes(1, 'big'), "offset": offset.to_bytes(4, 'big'),