mirror of
https://github.com/DJ2LS/FreeDATA
synced 2024-05-14 08:04:33 +00:00
gear shifting test
This commit is contained in:
parent
836f4b99d8
commit
22f0226600
8 changed files with 102 additions and 44 deletions
|
@ -127,4 +127,13 @@ class ARQSession():
|
||||||
'total_bytes': total_bytes,
|
'total_bytes': total_bytes,
|
||||||
'duration': duration,
|
'duration': duration,
|
||||||
'bytes_per_minute': bytes_per_minute
|
'bytes_per_minute': bytes_per_minute
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def get_appropriate_speed_level(self, snr):
|
||||||
|
# Start with the lowest speed level as default
|
||||||
|
# In case of a not fitting SNR, we return the lowest speed level
|
||||||
|
appropriate_speed_level = min(self.SPEED_LEVEL_DICT.keys())
|
||||||
|
for level, details in self.SPEED_LEVEL_DICT.items():
|
||||||
|
if snr >= details['min_snr'] and level > appropriate_speed_level:
|
||||||
|
appropriate_speed_level = level
|
||||||
|
return appropriate_speed_level
|
|
@ -76,13 +76,10 @@ class ARQSessionIRS(arq_session.ARQSession):
|
||||||
self.received_bytes = 0
|
self.received_bytes = 0
|
||||||
self.received_crc = None
|
self.received_crc = None
|
||||||
|
|
||||||
self.transmitted_acks = 0
|
self.speed_level = 0
|
||||||
|
|
||||||
self.abort = False
|
self.abort = False
|
||||||
|
|
||||||
def set_decode_mode(self):
|
|
||||||
self.modem.demodulator.set_decode_mode(self.get_mode_by_speed_level(self.speed_level))
|
|
||||||
|
|
||||||
def all_data_received(self):
|
def all_data_received(self):
|
||||||
return self.total_length == self.received_bytes
|
return self.total_length == self.received_bytes
|
||||||
|
|
||||||
|
@ -127,9 +124,6 @@ class ARQSessionIRS(arq_session.ARQSession):
|
||||||
self.log(f"New transfer of {self.total_length} bytes")
|
self.log(f"New transfer of {self.total_length} bytes")
|
||||||
self.event_manager.send_arq_session_new(False, self.id, self.dxcall, self.total_length, self.state.name)
|
self.event_manager.send_arq_session_new(False, self.id, self.dxcall, self.total_length, self.state.name)
|
||||||
|
|
||||||
self.calibrate_speed_settings()
|
|
||||||
self.set_decode_mode()
|
|
||||||
|
|
||||||
info_ack = self.frame_factory.build_arq_session_info_ack(
|
info_ack = self.frame_factory.build_arq_session_info_ack(
|
||||||
self.id, self.total_crc, self.snr[0],
|
self.id, self.total_crc, self.snr[0],
|
||||||
self.speed_level, self.frames_per_burst, flag_abort=self.abort)
|
self.speed_level, self.frames_per_burst, flag_abort=self.abort)
|
||||||
|
@ -163,17 +157,20 @@ class ARQSessionIRS(arq_session.ARQSession):
|
||||||
|
|
||||||
def receive_data(self, burst_frame):
|
def receive_data(self, burst_frame):
|
||||||
self.process_incoming_data(burst_frame)
|
self.process_incoming_data(burst_frame)
|
||||||
self.calibrate_speed_settings()
|
|
||||||
|
|
||||||
if not self.all_data_received():
|
if not self.all_data_received():
|
||||||
|
downshift, upshift = self.calibrate_speed_settings()
|
||||||
ack = self.frame_factory.build_arq_burst_ack(
|
ack = self.frame_factory.build_arq_burst_ack(
|
||||||
self.id, self.received_bytes,
|
self.id,
|
||||||
self.speed_level, self.frames_per_burst, self.snr[0], flag_abort=self.abort)
|
self.received_bytes,
|
||||||
|
self.speed_level,
|
||||||
|
self.frames_per_burst,
|
||||||
|
self.snr[0],
|
||||||
|
flag_abort=self.abort,
|
||||||
|
flag_upshift=upshift,
|
||||||
|
flag_downshift=downshift
|
||||||
|
)
|
||||||
|
|
||||||
self.set_decode_mode()
|
|
||||||
|
|
||||||
# increase ack counter
|
|
||||||
# self.transmitted_acks += 1
|
|
||||||
self.set_state(IRS_State.BURST_REPLY_SENT)
|
self.set_state(IRS_State.BURST_REPLY_SENT)
|
||||||
self.launch_transmit_and_wait(ack, self.TIMEOUT_DATA, mode=FREEDV_MODE.signalling)
|
self.launch_transmit_and_wait(ack, self.TIMEOUT_DATA, mode=FREEDV_MODE.signalling)
|
||||||
return None, None
|
return None, None
|
||||||
|
@ -209,16 +206,46 @@ class ARQSessionIRS(arq_session.ARQSession):
|
||||||
self.transmission_failed()
|
self.transmission_failed()
|
||||||
|
|
||||||
def calibrate_speed_settings(self):
|
def calibrate_speed_settings(self):
|
||||||
self.speed_level = 0 # for now stay at lowest speed level
|
latest_snr = self.snr[-1] if self.snr else -10
|
||||||
return
|
appropriate_speed_level = self.get_appropriate_speed_level(latest_snr)
|
||||||
# if we have two ACKS, then consider increasing speed level
|
modes_to_decode = {}
|
||||||
if self.transmitted_acks >= 2:
|
|
||||||
self.transmitted_acks = 0
|
|
||||||
new_speed_level = min(self.speed_level + 1, len(self.SPEED_LEVEL_DICT) - 1)
|
|
||||||
|
|
||||||
# check first if the next mode supports the actual snr
|
# Log the latest SNR, current, and appropriate speed levels for clarity
|
||||||
if self.snr[0] >= self.SPEED_LEVEL_DICT[new_speed_level]["min_snr"]:
|
self.log(
|
||||||
self.speed_level = new_speed_level
|
f"Latest SNR: {latest_snr}, Current Speed Level: {self.speed_level}, Appropriate Speed Level: {appropriate_speed_level}",
|
||||||
|
isWarning=True)
|
||||||
|
|
||||||
|
# Always decode the current mode
|
||||||
|
current_mode = self.get_mode_by_speed_level(self.speed_level).value
|
||||||
|
modes_to_decode[current_mode] = True
|
||||||
|
|
||||||
|
# Initialize shift flags
|
||||||
|
upshift = False
|
||||||
|
downshift = False
|
||||||
|
|
||||||
|
# Check if a shift is needed
|
||||||
|
if appropriate_speed_level != self.speed_level:
|
||||||
|
# Determine the direction of the shift
|
||||||
|
upshift = appropriate_speed_level > self.speed_level
|
||||||
|
downshift = appropriate_speed_level < self.speed_level
|
||||||
|
|
||||||
|
# Update the speed level
|
||||||
|
self.speed_level = appropriate_speed_level
|
||||||
|
self.log(f"Updated Speed Level: {self.speed_level}", isWarning=True)
|
||||||
|
|
||||||
|
# Determine additional modes based on the direction of the shift
|
||||||
|
if upshift and self.speed_level < len(self.SPEED_LEVEL_DICT) - 1:
|
||||||
|
next_mode = self.get_mode_by_speed_level(self.speed_level).value
|
||||||
|
modes_to_decode[next_mode] = True
|
||||||
|
elif downshift and self.speed_level > 0:
|
||||||
|
prev_mode = self.get_mode_by_speed_level(self.speed_level).value
|
||||||
|
modes_to_decode[prev_mode] = True
|
||||||
|
|
||||||
|
self.log(f"Modes to Decode: {modes_to_decode}", isWarning=True)
|
||||||
|
# Apply the new decode mode based on the updated speed level
|
||||||
|
self.modem.demodulator.set_decode_mode(modes_to_decode)
|
||||||
|
|
||||||
|
return downshift, upshift
|
||||||
|
|
||||||
def abort_transmission(self):
|
def abort_transmission(self):
|
||||||
self.log(f"Aborting transmission... setting abort flag")
|
self.log(f"Aborting transmission... setting abort flag")
|
||||||
|
|
|
@ -105,11 +105,25 @@ class ARQSessionISS(arq_session.ARQSession):
|
||||||
self.launch_twr(session_open_frame, self.TIMEOUT_CONNECT_ACK, self.RETRIES_CONNECT, mode=FREEDV_MODE.signalling)
|
self.launch_twr(session_open_frame, self.TIMEOUT_CONNECT_ACK, self.RETRIES_CONNECT, mode=FREEDV_MODE.signalling)
|
||||||
self.set_state(ISS_State.OPEN_SENT)
|
self.set_state(ISS_State.OPEN_SENT)
|
||||||
|
|
||||||
def set_speed_and_frames_per_burst(self, frame):
|
def update_speed_level(self, frame):
|
||||||
self.speed_level = frame['speed_level']
|
self.log("---------------------------------------------------------", isWarning=True)
|
||||||
self.log(f"Speed level set to {self.speed_level}")
|
|
||||||
self.frames_per_burst = frame['frames_per_burst']
|
# Log the received frame for debugging
|
||||||
self.log(f"Frames per burst set to {self.frames_per_burst}")
|
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}")
|
||||||
|
|
||||||
def send_info(self, irs_frame):
|
def send_info(self, irs_frame):
|
||||||
# check if we received an abort flag
|
# check if we received an abort flag
|
||||||
|
@ -128,7 +142,7 @@ class ARQSessionISS(arq_session.ARQSession):
|
||||||
|
|
||||||
def send_data(self, irs_frame):
|
def send_data(self, irs_frame):
|
||||||
|
|
||||||
self.set_speed_and_frames_per_burst(irs_frame)
|
self.update_speed_level(irs_frame)
|
||||||
|
|
||||||
if 'offset' in irs_frame:
|
if 'offset' in irs_frame:
|
||||||
self.confirmed_bytes = irs_frame['offset']
|
self.confirmed_bytes = irs_frame['offset']
|
||||||
|
|
|
@ -15,6 +15,8 @@ class DataFrameFactory:
|
||||||
'FINAL': 0, # Bit-position for indicating the FINAL state
|
'FINAL': 0, # Bit-position for indicating the FINAL state
|
||||||
'ABORT': 1, # Bit-position for indicating the ABORT request
|
'ABORT': 1, # Bit-position for indicating the ABORT request
|
||||||
'CHECKSUM': 2, # Bit-position for indicating the CHECKSUM is correct or not
|
'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):
|
def __init__(self, config):
|
||||||
|
@ -404,7 +406,7 @@ class DataFrameFactory:
|
||||||
return frame
|
return frame
|
||||||
|
|
||||||
def build_arq_burst_ack(self, session_id: bytes, offset, speed_level: int,
|
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):
|
frames_per_burst: int, snr: int, flag_final=False, flag_checksum=False, flag_abort=False, flag_downshift=False, flag_upshift=False):
|
||||||
flag = 0b00000000
|
flag = 0b00000000
|
||||||
if flag_final:
|
if flag_final:
|
||||||
flag = helpers.set_flag(flag, 'FINAL', True, self.ARQ_FLAGS)
|
flag = helpers.set_flag(flag, 'FINAL', True, self.ARQ_FLAGS)
|
||||||
|
@ -415,6 +417,13 @@ class DataFrameFactory:
|
||||||
if flag_abort:
|
if flag_abort:
|
||||||
flag = helpers.set_flag(flag, 'ABORT', True, self.ARQ_FLAGS)
|
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 = {
|
payload = {
|
||||||
"session_id": session_id.to_bytes(1, 'big'),
|
"session_id": session_id.to_bytes(1, 'big'),
|
||||||
|
|
|
@ -382,15 +382,15 @@ class Demodulator():
|
||||||
for mode in self.MODE_DICT:
|
for mode in self.MODE_DICT:
|
||||||
codec2.api.freedv_set_sync(self.MODE_DICT[mode]["instance"], 0)
|
codec2.api.freedv_set_sync(self.MODE_DICT[mode]["instance"], 0)
|
||||||
|
|
||||||
def set_decode_mode(self, mode):
|
def set_decode_mode(self, modes_to_decode):
|
||||||
|
# Reset all modes to not decode
|
||||||
|
for m in self.MODE_DICT:
|
||||||
|
self.MODE_DICT[m]["decode"] = False
|
||||||
|
|
||||||
for m in self.MODE_DICT: self.MODE_DICT[m]["decode"] = False
|
# Enable specified modes
|
||||||
|
for mode, decode in modes_to_decode.items():
|
||||||
|
if mode in self.MODE_DICT:
|
||||||
|
self.MODE_DICT[mode]["decode"] = decode
|
||||||
|
|
||||||
# signalling is always true
|
enabled_modes = [mode.name for mode, details in self.MODE_DICT.items() if details["decode"]]
|
||||||
self.MODE_DICT[codec2.FREEDV_MODE.signalling.value]["decode"] = True
|
self.log.info(f"[MDM] [demod_audio] Enabled decode modes: {', '.join(enabled_modes)}")
|
||||||
|
|
||||||
# Enable mode based on speed_level
|
|
||||||
self.MODE_DICT[mode.value]["decode"] = True
|
|
||||||
self.log.info(f"[MDM] [demod_audio] set data mode: {mode.name}")
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
|
@ -91,7 +91,6 @@ class FrameHandler():
|
||||||
def add_to_heard_stations(self):
|
def add_to_heard_stations(self):
|
||||||
frame = self.details['frame']
|
frame = self.details['frame']
|
||||||
|
|
||||||
print(frame)
|
|
||||||
if 'origin' not in frame:
|
if 'origin' not in frame:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ app = Flask(__name__)
|
||||||
CORS(app)
|
CORS(app)
|
||||||
CORS(app, resources={r"/*": {"origins": "*"}})
|
CORS(app, resources={r"/*": {"origins": "*"}})
|
||||||
sock = Sock(app)
|
sock = Sock(app)
|
||||||
MODEM_VERSION = "0.13.7-alpha"
|
MODEM_VERSION = "0.14.0-alpha-exp"
|
||||||
|
|
||||||
# set config file to use
|
# set config file to use
|
||||||
def set_config():
|
def set_config():
|
||||||
|
|
|
@ -144,7 +144,7 @@ class TestARQSession(unittest.TestCase):
|
||||||
self.waitAndCloseChannels()
|
self.waitAndCloseChannels()
|
||||||
del cmd
|
del cmd
|
||||||
|
|
||||||
def DisabledtestARQSessionLargePayload(self):
|
def testARQSessionLargePayload(self):
|
||||||
# set Packet Error Rate (PER) / frame loss probability
|
# set Packet Error Rate (PER) / frame loss probability
|
||||||
self.loss_probability = 0
|
self.loss_probability = 0
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue