some more frame porting

This commit is contained in:
DJ2LS 2023-11-30 20:35:07 +01:00
parent ca1257bab7
commit 02062e3e18
7 changed files with 130 additions and 92 deletions

View file

@ -99,9 +99,9 @@ class DataFrameFactory:
}
def _load_arq_templates(self):
# same structure for narrow and wide types
arq_dc_open_ack = {
arq_dc_open = {
"frame_length": self.LENGTH_SIG0_FRAME,
"destination_crc": 3,
"origin_crc": 3,
@ -109,9 +109,22 @@ class DataFrameFactory:
"session_id": 1,
}
# arq connect frames
self.template_list[FR_TYPE.ARQ_DC_OPEN_N.value] = arq_dc_open
self.template_list[FR_TYPE.ARQ_DC_OPEN_W.value] = arq_dc_open
# same structure for narrow and wide types
arq_dc_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_DC_OPEN_ACK_N.value] = arq_dc_open_ack
self.template_list[FR_TYPE.ARQ_DC_OPEN_ACK_W.value] = arq_dc_open_ack
# arq burst ack
self.template_list[FR_TYPE.BURST_ACK.value] = {
"frame_length": self.LENGTH_SIG1_FRAME,
@ -288,9 +301,36 @@ class DataFrameFactory:
"session_id": session_id.to_bytes(1, 'big'),
}
channel_type = FR_TYPE.ARQ_DC_OPEN_W if isWideband else FR_TYPE.ARQ_DC_OPEN_N
return self.construct(channel_type, payload)
def build_arq_connect_ack(self, isWideband, session_id, speed_level,arq_protocol_version):
#connection_frame = bytearray(self.length_sig0_frame)
#connection_frame[:1] = frametype
#connection_frame[1:2] = self.session_id
#connection_frame[8:9] = bytes([self.speed_level])
#connection_frame[13:14] = bytes([self.arq_protocol_version])
payload = {
"session_id": session_id.to_bytes(1, 'big'),
"speed_level": bytes([speed_level]),
"arq_protocol_version": bytes([arq_protocol_version]),
}
channel_type = FR_TYPE.ARQ_DC_OPEN_ACK_W if isWideband else FR_TYPE.ARQ_DC_OPEN_ACK_N
return self.construct(channel_type, payload)
def build_arq_session_connect(self, isWideband, destination, session_id):
payload = {
"destination_crc": helpers.get_crc_24(destination),
"origin_crc": helpers.get_crc_24(self.myfullcall),
"origin": helpers.callsign_to_bytes(self.myfullcall),
"session_id": session_id.to_bytes(1, 'big'),
}
return self.construct(FR_TYPE.ARQ_SESSION_OPEN, payload)
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])

View file

@ -329,13 +329,14 @@ class IRS(ARQ):
frametype = bytes([FR_TYPE.ARQ_DC_OPEN_ACK_W.value])
self.log.debug("[Modem] Responding with high bandwidth mode")
connection_frame = bytearray(self.length_sig0_frame)
connection_frame[:1] = frametype
connection_frame[1:2] = self.session_id
connection_frame[8:9] = bytes([self.speed_level])
connection_frame[13:14] = bytes([self.arq_protocol_version])
self.enqueue_frame_for_tx([connection_frame], c2_mode=FREEDV_MODE.sig0.value, copies=1, repeat_delay=0)
connection_ack_frame = self.frame_factory.build_arq_connect_ack(
session_id=self.session_id,
speed_level=self.speed_level,
arq_protocol_version=self.arq_protocol_version
)
self.enqueue_frame_for_tx([connection_ack_frame], c2_mode=FREEDV_MODE.sig0.value, copies=1, repeat_delay=0)
self.event_manager.send_custom_event(
freedata="modem-message",

View file

@ -626,83 +626,6 @@ class ISS(ARQ):
)
return False
def open_session(self) -> bool:
"""
Create and send the frame to request a connection.
Returns:
True if the session was opened successfully
False if the session open request failed
"""
self.IS_ARQ_SESSION_MASTER = True
self.states.set("arq_session_state", "connecting")
# create a random session id
self.session_id = np.random.bytes(1)
connection_frame = bytearray(self.length_sig0_frame)
connection_frame[:1] = bytes([FR_TYPE.ARQ_SESSION_OPEN.value])
connection_frame[1:2] = self.session_id
connection_frame[2:5] = self.dxcallsign_crc
connection_frame[5:8] = self.mycallsign_crc
connection_frame[8:14] = helpers.callsign_to_bytes(self.mycallsign)
while not self.states.is_arq_session:
threading.Event().wait(0.01)
for attempt in range(self.session_connect_max_retries):
self.log.info(
"[Modem] SESSION ["
+ str(self.mycallsign, "UTF-8")
+ "]>>?<<["
+ str(self.dxcallsign, "UTF-8")
+ "]",
a=f"{str(attempt + 1)}/{str(self.session_connect_max_retries)}",
state=self.states.arq_session_state,
)
self.event_manager.send_custom_event(
freedata="modem-message",
arq="session",
status="connecting",
attempt=attempt + 1,
maxattempts=self.session_connect_max_retries,
mycallsign=str(self.mycallsign, 'UTF-8'),
dxcallsign=str(self.dxcallsign, 'UTF-8'),
)
self.enqueue_frame_for_tx([connection_frame], c2_mode=FREEDV_MODE.sig0.value, copies=1, repeat_delay=0)
# Wait for a time, looking to see if `self.states.is_arq_session`
# indicates we've received a positive response from the far station.
timeout = time.time() + 3
while time.time() < timeout:
threading.Event().wait(0.01)
# Stop waiting if data channel is opened
if self.states.is_arq_session:
return True
# Stop waiting and interrupt if data channel is getting closed while opening
if self.states.arq_session_state == "disconnecting":
# disabled this session close as its called twice
# self.close_session()
return False
# Session connect timeout, send close_session frame to
# attempt to clean up the far-side, if it received the
# open_session frame and can still hear us.
if not self.states.is_arq_session:
self.close_session()
return False
# Given the while condition, it will only exit when `self.states.is_arq_session` is True
self.event_manager.send_custom_event(
freedata="modem-message",
arq="session",
status="connected",
mycallsign=str(self.mycallsign, 'UTF-8'),
dxcallsign=str(self.dxcallsign, 'UTF-8'),
)
return True
def open_dc_and_transmit(
self,
@ -838,13 +761,11 @@ class ISS(ARQ):
frametype = bytes([FR_TYPE.ARQ_DC_OPEN_W.value])
self.log.debug("[Modem] Requesting high bandwidth mode")
connection_frame = bytearray(self.length_sig0_frame)
connection_frame[:1] = frametype
connection_frame[1:4] = self.dxcallsign_crc
connection_frame[4:7] = self.mycallsign_crc
connection_frame[7:13] = helpers.callsign_to_bytes(mycallsign)
connection_frame[13:14] = self.session_id
# build connection frame
connection_frame = self.frame_factory.build_arq_connect(
session_id=self.session_id,
destination_crc=self.dxcallsign_crc,
)
for attempt in range(self.data_channel_max_retries):
self.event_manager.send_custom_event(

View file

@ -169,6 +169,82 @@ class SESSION(ARQ):
MODEM_TRANSMIT_QUEUE.put(["morse", 1, 0, self.mycallsign])
self.arq_cleanup()
def open_session(self) -> bool:
"""
Create and send the frame to request a connection.
Returns:
True if the session was opened successfully
False if the session open request failed
"""
self.IS_ARQ_SESSION_MASTER = True
self.states.set("arq_session_state", "connecting")
# create a random session id
self.session_id = np.random.bytes(1)
# build connection frame
connection_frame = self.frame_factory.build_arq_session_connect(
session_id=self.session_id,
destination_crc=self.dxcallsign_crc,
)
while not self.states.is_arq_session:
threading.Event().wait(0.01)
for attempt in range(self.session_connect_max_retries):
self.log.info(
"[Modem] SESSION ["
+ str(self.mycallsign, "UTF-8")
+ "]>>?<<["
+ str(self.dxcallsign, "UTF-8")
+ "]",
a=f"{str(attempt + 1)}/{str(self.session_connect_max_retries)}",
state=self.states.arq_session_state,
)
self.event_manager.send_custom_event(
freedata="modem-message",
arq="session",
status="connecting",
attempt=attempt + 1,
maxattempts=self.session_connect_max_retries,
mycallsign=str(self.mycallsign, 'UTF-8'),
dxcallsign=str(self.dxcallsign, 'UTF-8'),
)
self.enqueue_frame_for_tx([connection_frame], c2_mode=FREEDV_MODE.sig0.value, copies=1, repeat_delay=0)
# Wait for a time, looking to see if `self.states.is_arq_session`
# indicates we've received a positive response from the far station.
timeout = time.time() + 3
while time.time() < timeout:
threading.Event().wait(0.01)
# Stop waiting if data channel is opened
if self.states.is_arq_session:
return True
# Stop waiting and interrupt if data channel is getting closed while opening
if self.states.arq_session_state == "disconnecting":
# disabled this session close as its called twice
# self.close_session()
return False
# Session connect timeout, send close_session frame to
# attempt to clean up the far-side, if it received the
# open_session frame and can still hear us.
if not self.states.is_arq_session:
self.close_session()
return False
# Given the while condition, it will only exit when `self.states.is_arq_session` is True
self.event_manager.send_custom_event(
freedata="modem-message",
arq="session",
status="connected",
mycallsign=str(self.mycallsign, 'UTF-8'),
dxcallsign=str(self.dxcallsign, 'UTF-8'),
)
return True
def received_session_opener(self, data_in: bytes, snr) -> None:
"""
Received a session open request packet.