mirror of
https://github.com/DJ2LS/FreeDATA
synced 2024-05-14 08:04:33 +00:00
Merge branch 'develop' of github.com:DJ2LS/FreeDATA into develop
This commit is contained in:
commit
c684cd58e0
3 changed files with 283 additions and 278 deletions
|
@ -23,7 +23,7 @@ import codec2
|
||||||
import helpers
|
import helpers
|
||||||
import modem
|
import modem
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from global_instances import ARQ, HamlibParam, ModemParam, Station, Modem
|
from global_instances import ARQ, Modem
|
||||||
import structlog
|
import structlog
|
||||||
import stats
|
import stats
|
||||||
import ujson as json
|
import ujson as json
|
||||||
|
@ -47,9 +47,17 @@ class DATA:
|
||||||
self.event_queue = event_queue
|
self.event_queue = event_queue
|
||||||
|
|
||||||
self.mycallsign = config['STATION']['mycall']
|
self.mycallsign = config['STATION']['mycall']
|
||||||
self.mygrid = config['STATION']['mygrid']
|
self.mycallsign_crc = b''
|
||||||
|
|
||||||
self.dxcallsign = Station.dxcallsign
|
self.mygrid = config['STATION']['mygrid']
|
||||||
|
self.enable_fsk = config['MODEM']['enable_fsk']
|
||||||
|
|
||||||
|
# TODO we need to pass this information from modem when receiving a burst
|
||||||
|
self.modem_frequency_offset = 0
|
||||||
|
|
||||||
|
self.dxcallsign = b"ZZ9YY-0"
|
||||||
|
self.dxcallsign_crc = b''
|
||||||
|
self.dxgrid = b''
|
||||||
|
|
||||||
self.data_queue_transmit = DATA_QUEUE_TRANSMIT
|
self.data_queue_transmit = DATA_QUEUE_TRANSMIT
|
||||||
self.data_queue_received = DATA_QUEUE_RECEIVED
|
self.data_queue_received = DATA_QUEUE_RECEIVED
|
||||||
|
@ -489,19 +497,14 @@ class DATA:
|
||||||
:param repeat_delay: Delay time before sending repeat frame, defaults to 0
|
:param repeat_delay: Delay time before sending repeat frame, defaults to 0
|
||||||
:type repeat_delay: int, optional
|
:type repeat_delay: int, optional
|
||||||
"""
|
"""
|
||||||
#print(frame_to_tx[0])
|
|
||||||
#print(frame_to_tx)
|
|
||||||
frame_type = FR_TYPE(int.from_bytes(frame_to_tx[0][:1], byteorder="big")).name
|
frame_type = FR_TYPE(int.from_bytes(frame_to_tx[0][:1], byteorder="big")).name
|
||||||
self.log.debug("[Modem] enqueue_frame_for_tx", c2_mode=FREEDV_MODE(c2_mode).name, data=frame_to_tx,
|
self.log.debug("[Modem] enqueue_frame_for_tx", c2_mode=FREEDV_MODE(c2_mode).name, data=frame_to_tx,
|
||||||
type=frame_type)
|
type=frame_type)
|
||||||
|
|
||||||
# Set the TRANSMITTING flag before adding an object to the transmit queue
|
|
||||||
# TODO This is not that nice, we could improve this somehow
|
|
||||||
Modem.transmitting = True
|
|
||||||
modem.MODEM_TRANSMIT_QUEUE.put([c2_mode, copies, repeat_delay, frame_to_tx])
|
modem.MODEM_TRANSMIT_QUEUE.put([c2_mode, copies, repeat_delay, frame_to_tx])
|
||||||
|
|
||||||
# Wait while transmitting
|
# Wait while transmitting
|
||||||
while Modem.transmitting:
|
while self.states.is_transmitting:
|
||||||
threading.Event().wait(0.01)
|
threading.Event().wait(0.01)
|
||||||
|
|
||||||
def send_data_to_socket_queue(self, **jsondata):
|
def send_data_to_socket_queue(self, **jsondata):
|
||||||
|
@ -518,8 +521,8 @@ class DATA:
|
||||||
uuid=self.transmission_uuid,
|
uuid=self.transmission_uuid,
|
||||||
timestamp=timestamp,
|
timestamp=timestamp,
|
||||||
mycallsign=str(self.mycallsign, "UTF-8"),
|
mycallsign=str(self.mycallsign, "UTF-8"),
|
||||||
dxcallsign=str(Station.dxcallsign, "UTF-8"),
|
dxcallsign=str(self.dxcallsign, "UTF-8"),
|
||||||
dxgrid=str(Station.dxgrid, "UTF-8"),
|
dxgrid=str(self.dxgrid, "UTF-8"),
|
||||||
data=base64_data,
|
data=base64_data,
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
|
@ -530,7 +533,7 @@ class DATA:
|
||||||
if "mycallsign" not in jsondata:
|
if "mycallsign" not in jsondata:
|
||||||
jsondata["mycallsign"] = str(self.mycallsign, "UTF-8")
|
jsondata["mycallsign"] = str(self.mycallsign, "UTF-8")
|
||||||
if "dxcallsign" not in jsondata:
|
if "dxcallsign" not in jsondata:
|
||||||
jsondata["dxcallsign"] = str(Station.dxcallsign, "UTF-8")
|
jsondata["dxcallsign"] = str(self.dxcallsign, "UTF-8")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.log.debug("[Modem] error adding callsigns to network message", e=e)
|
self.log.debug("[Modem] error adding callsigns to network message", e=e)
|
||||||
|
|
||||||
|
@ -565,7 +568,7 @@ class DATA:
|
||||||
ack_frame[4:8] = len(ARQ.rx_frame_buffer).to_bytes(4, byteorder="big")
|
ack_frame[4:8] = len(ARQ.rx_frame_buffer).to_bytes(4, byteorder="big")
|
||||||
|
|
||||||
# wait if we have a channel busy condition
|
# wait if we have a channel busy condition
|
||||||
if ModemParam.channel_busy:
|
if self.states.channel_busy:
|
||||||
self.channel_busy_handler()
|
self.channel_busy_handler()
|
||||||
|
|
||||||
# Transmit frame
|
# Transmit frame
|
||||||
|
@ -580,7 +583,7 @@ class DATA:
|
||||||
ack_frame[2:3] = helpers.snr_to_bytes(snr)
|
ack_frame[2:3] = helpers.snr_to_bytes(snr)
|
||||||
|
|
||||||
# wait if we have a channel busy condition
|
# wait if we have a channel busy condition
|
||||||
if ModemParam.channel_busy:
|
if self.states.channel_busy:
|
||||||
self.channel_busy_handler()
|
self.channel_busy_handler()
|
||||||
|
|
||||||
# Transmit frame
|
# Transmit frame
|
||||||
|
@ -620,7 +623,7 @@ class DATA:
|
||||||
# self.enqueue_frame_for_tx([ack_frame, self.send_ident_frame(False)], c2_mode=FREEDV_MODE.sig1.value, copies=3, repeat_delay=0)
|
# self.enqueue_frame_for_tx([ack_frame, self.send_ident_frame(False)], c2_mode=FREEDV_MODE.sig1.value, copies=3, repeat_delay=0)
|
||||||
|
|
||||||
# wait if we have a channel busy condition
|
# wait if we have a channel busy condition
|
||||||
if ModemParam.channel_busy:
|
if self.states.channel_busy:
|
||||||
self.channel_busy_handler()
|
self.channel_busy_handler()
|
||||||
|
|
||||||
self.enqueue_frame_for_tx([nack_frame], c2_mode=FREEDV_MODE.sig1.value, copies=3, repeat_delay=0)
|
self.enqueue_frame_for_tx([nack_frame], c2_mode=FREEDV_MODE.sig1.value, copies=3, repeat_delay=0)
|
||||||
|
@ -647,7 +650,7 @@ class DATA:
|
||||||
nack_frame[5:9] = len(ARQ.rx_frame_buffer).to_bytes(4, byteorder="big")
|
nack_frame[5:9] = len(ARQ.rx_frame_buffer).to_bytes(4, byteorder="big")
|
||||||
|
|
||||||
# wait if we have a channel busy condition
|
# wait if we have a channel busy condition
|
||||||
if ModemParam.channel_busy:
|
if self.states.channel_busy:
|
||||||
self.channel_busy_handler()
|
self.channel_busy_handler()
|
||||||
|
|
||||||
# TRANSMIT NACK FRAME FOR BURST
|
# TRANSMIT NACK FRAME FOR BURST
|
||||||
|
@ -661,10 +664,10 @@ class DATA:
|
||||||
disconnection_frame = bytearray(self.length_sig1_frame)
|
disconnection_frame = bytearray(self.length_sig1_frame)
|
||||||
disconnection_frame[:1] = bytes([FR_TYPE.ARQ_SESSION_CLOSE.value])
|
disconnection_frame[:1] = bytes([FR_TYPE.ARQ_SESSION_CLOSE.value])
|
||||||
disconnection_frame[1:2] = self.session_id
|
disconnection_frame[1:2] = self.session_id
|
||||||
disconnection_frame[2:5] = Station.dxcallsign_crc
|
disconnection_frame[2:5] = self.dxcallsign_crc
|
||||||
|
|
||||||
# wait if we have a channel busy condition
|
# wait if we have a channel busy condition
|
||||||
if ModemParam.channel_busy:
|
if self.states.channel_busy:
|
||||||
self.channel_busy_handler()
|
self.channel_busy_handler()
|
||||||
|
|
||||||
self.enqueue_frame_for_tx([disconnection_frame], c2_mode=FREEDV_MODE.sig0.value, copies=3, repeat_delay=0)
|
self.enqueue_frame_for_tx([disconnection_frame], c2_mode=FREEDV_MODE.sig0.value, copies=3, repeat_delay=0)
|
||||||
|
@ -686,14 +689,14 @@ class DATA:
|
||||||
data_in = bytes(data_in)
|
data_in = bytes(data_in)
|
||||||
|
|
||||||
# only process data if we are in ARQ and BUSY state else return to quit
|
# only process data if we are in ARQ and BUSY state else return to quit
|
||||||
if not self.states.is_arq_state and Modem.modem_state not in ["BUSY"]:
|
if not self.states.is_arq_state and not self.states.is_modem_busy:
|
||||||
self.log.warning("[Modem] wrong modem state - dropping data", is_arq_state=self.states.is_arq_state,
|
self.log.warning("[Modem] wrong modem state - dropping data", is_arq_state=self.states.is_arq_state,
|
||||||
modem_state=Modem.modem_state)
|
modem_state=self.states.is_modem_busy)
|
||||||
return
|
return
|
||||||
|
|
||||||
self.arq_file_transfer = True
|
self.arq_file_transfer = True
|
||||||
|
|
||||||
Modem.modem_state = "BUSY"
|
self.states.set("is_modem_busy", True)
|
||||||
self.states.set("is_arq_state", True)
|
self.states.set("is_arq_state", True)
|
||||||
|
|
||||||
# Update data_channel timestamp
|
# Update data_channel timestamp
|
||||||
|
@ -715,14 +718,14 @@ class DATA:
|
||||||
# Append data to rx burst buffer
|
# Append data to rx burst buffer
|
||||||
ARQ.rx_burst_buffer[self.rx_n_frame_of_burst] = data_in[self.arq_burst_header_size:] # type: ignore
|
ARQ.rx_burst_buffer[self.rx_n_frame_of_burst] = data_in[self.arq_burst_header_size:] # type: ignore
|
||||||
|
|
||||||
Station.dxgrid = b'------'
|
self.dxgrid = b'------'
|
||||||
helpers.add_to_heard_stations(
|
helpers.add_to_heard_stations(
|
||||||
Station.dxcallsign,
|
self.dxcallsign,
|
||||||
Station.dxgrid,
|
self.dxgrid,
|
||||||
"DATA",
|
"DATA",
|
||||||
snr,
|
snr,
|
||||||
ModemParam.frequency_offset,
|
self.modem_frequency_offset,
|
||||||
HamlibParam.hamlib_frequency,
|
self.states.radio_frequency,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check if we received all frames in the burst by checking if burst buffer has no more "Nones"
|
# Check if we received all frames in the burst by checking if burst buffer has no more "Nones"
|
||||||
|
@ -976,10 +979,10 @@ class DATA:
|
||||||
"""
|
"""
|
||||||
mode_name = FREEDV_MODE(self.mode_list[self.speed_level]).name
|
mode_name = FREEDV_MODE(self.mode_list[self.speed_level]).name
|
||||||
mode_slots = FREEDV_MODE_USED_SLOTS[mode_name].value
|
mode_slots = FREEDV_MODE_USED_SLOTS[mode_name].value
|
||||||
if mode_slots in [ModemParam.channel_busy_slot]:
|
if mode_slots in [self.states.channel_busy_slot]:
|
||||||
self.log.warning(
|
self.log.warning(
|
||||||
"[Modem] busy slot detection",
|
"[Modem] busy slot detection",
|
||||||
slots=ModemParam.channel_busy_slot,
|
slots=self.states.channel_busy_slot,
|
||||||
mode_slots=mode_slots,
|
mode_slots=mode_slots,
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
@ -1087,8 +1090,8 @@ class DATA:
|
||||||
[
|
[
|
||||||
self.transmission_uuid,
|
self.transmission_uuid,
|
||||||
timestamp,
|
timestamp,
|
||||||
Station.dxcallsign,
|
self.dxcallsign,
|
||||||
Station.dxgrid,
|
self.dxgrid,
|
||||||
base64_data,
|
base64_data,
|
||||||
signed,
|
signed,
|
||||||
ARQ.arq_compression_factor,
|
ARQ.arq_compression_factor,
|
||||||
|
@ -1109,8 +1112,8 @@ class DATA:
|
||||||
e=e,
|
e=e,
|
||||||
uuid=self.transmission_uuid,
|
uuid=self.transmission_uuid,
|
||||||
timestamp=timestamp,
|
timestamp=timestamp,
|
||||||
dxcall=Station.dxcallsign,
|
dxcall=self.dxcallsign,
|
||||||
dxgrid=Station.dxgrid,
|
dxgrid=self.dxgrid,
|
||||||
data=base64_data
|
data=base64_data
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1120,8 +1123,8 @@ class DATA:
|
||||||
self.transmission_uuid,
|
self.transmission_uuid,
|
||||||
timestamp,
|
timestamp,
|
||||||
self.mycallsign,
|
self.mycallsign,
|
||||||
Station.dxcallsign,
|
self.dxcallsign,
|
||||||
Station.dxgrid,
|
self.dxgrid,
|
||||||
data_frame
|
data_frame
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -1130,8 +1133,8 @@ class DATA:
|
||||||
e=e,
|
e=e,
|
||||||
uuid=self.transmission_uuid,
|
uuid=self.transmission_uuid,
|
||||||
timestamp=timestamp,
|
timestamp=timestamp,
|
||||||
dxcall=Station.dxcallsign,
|
dxcall=self.dxcallsign,
|
||||||
dxgrid=Station.dxgrid,
|
dxgrid=self.dxgrid,
|
||||||
data=base64_data
|
data=base64_data
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1146,8 +1149,8 @@ class DATA:
|
||||||
timestamp=timestamp,
|
timestamp=timestamp,
|
||||||
finished=0,
|
finished=0,
|
||||||
mycallsign=str(self.mycallsign, "UTF-8"),
|
mycallsign=str(self.mycallsign, "UTF-8"),
|
||||||
dxcallsign=str(Station.dxcallsign, "UTF-8"),
|
dxcallsign=str(self.dxcallsign, "UTF-8"),
|
||||||
dxgrid=str(Station.dxgrid, "UTF-8"),
|
dxgrid=str(self.dxgrid, "UTF-8"),
|
||||||
data=base64_data,
|
data=base64_data,
|
||||||
irs=helpers.bool_to_string(self.is_IRS),
|
irs=helpers.bool_to_string(self.is_IRS),
|
||||||
hmac_signed=signed,
|
hmac_signed=signed,
|
||||||
|
@ -1173,7 +1176,7 @@ class DATA:
|
||||||
"[Modem] | RX | DATACHANNEL ["
|
"[Modem] | RX | DATACHANNEL ["
|
||||||
+ str(self.mycallsign, "UTF-8")
|
+ str(self.mycallsign, "UTF-8")
|
||||||
+ "]<< >>["
|
+ "]<< >>["
|
||||||
+ str(Station.dxcallsign, "UTF-8")
|
+ str(self.dxcallsign, "UTF-8")
|
||||||
+ "]",
|
+ "]",
|
||||||
snr=snr,
|
snr=snr,
|
||||||
)
|
)
|
||||||
|
@ -1529,14 +1532,14 @@ class DATA:
|
||||||
"""
|
"""
|
||||||
# Process data only if we are in ARQ and BUSY state
|
# Process data only if we are in ARQ and BUSY state
|
||||||
if self.states.is_arq_state:
|
if self.states.is_arq_state:
|
||||||
Station.dxgrid = b'------'
|
self.dxgrid = b'------'
|
||||||
helpers.add_to_heard_stations(
|
helpers.add_to_heard_stations(
|
||||||
self.dxcallsign,
|
self.dxcallsign,
|
||||||
Station.dxgrid,
|
self.dxgrid,
|
||||||
"DATA",
|
"DATA",
|
||||||
snr,
|
snr,
|
||||||
ModemParam.frequency_offset,
|
self.modem_frequency_offset,
|
||||||
HamlibParam.hamlib_frequency,
|
self.states.radio_frequency,
|
||||||
)
|
)
|
||||||
|
|
||||||
frametype = int.from_bytes(bytes(data_in[:1]), "big")
|
frametype = int.from_bytes(bytes(data_in[:1]), "big")
|
||||||
|
@ -1584,14 +1587,14 @@ class DATA:
|
||||||
"""Received an ACK for a transmitted frame"""
|
"""Received an ACK for a transmitted frame"""
|
||||||
# Process data only if we are in ARQ and BUSY state
|
# Process data only if we are in ARQ and BUSY state
|
||||||
if self.states.is_arq_state:
|
if self.states.is_arq_state:
|
||||||
Station.dxgrid = b'------'
|
self.dxgrid = b'------'
|
||||||
helpers.add_to_heard_stations(
|
helpers.add_to_heard_stations(
|
||||||
Station.dxcallsign,
|
self.dxcallsign,
|
||||||
Station.dxgrid,
|
self.dxgrid,
|
||||||
"DATA",
|
"DATA",
|
||||||
snr,
|
snr,
|
||||||
ModemParam.frequency_offset,
|
self.modem_frequency_offset,
|
||||||
HamlibParam.hamlib_frequency,
|
self.states.radio_frequency,
|
||||||
)
|
)
|
||||||
# Force data loops of Modem to stop and continue with next frame
|
# Force data loops of Modem to stop and continue with next frame
|
||||||
self.data_frame_ack_received = True
|
self.data_frame_ack_received = True
|
||||||
|
@ -1622,14 +1625,14 @@ class DATA:
|
||||||
speed_list=ARQ.speed_list
|
speed_list=ARQ.speed_list
|
||||||
)
|
)
|
||||||
|
|
||||||
Station.dxgrid = b'------'
|
self.dxgrid = b'------'
|
||||||
helpers.add_to_heard_stations(
|
helpers.add_to_heard_stations(
|
||||||
Station.dxcallsign,
|
self.dxcallsign,
|
||||||
Station.dxgrid,
|
self.dxgrid,
|
||||||
"DATA",
|
"DATA",
|
||||||
snr,
|
snr,
|
||||||
ModemParam.frequency_offset,
|
self.modem_frequency_offset,
|
||||||
HamlibParam.hamlib_frequency,
|
self.states.radio_frequency,
|
||||||
)
|
)
|
||||||
self.send_data_to_socket_queue(
|
self.send_data_to_socket_queue(
|
||||||
freedata="modem-message",
|
freedata="modem-message",
|
||||||
|
@ -1659,16 +1662,16 @@ class DATA:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# Only process data if we are in ARQ and BUSY state
|
# Only process data if we are in ARQ and BUSY state
|
||||||
if not self.states.is_arq_state or Modem.modem_state != "BUSY":
|
if not self.states.is_arq_state or not self.states.is_modem_busy:
|
||||||
return
|
return
|
||||||
Station.dxgrid = b'------'
|
self.dxgrid = b'------'
|
||||||
helpers.add_to_heard_stations(
|
helpers.add_to_heard_stations(
|
||||||
Station.dxcallsign,
|
self.dxcallsign,
|
||||||
Station.dxgrid,
|
self.dxgrid,
|
||||||
"DATA",
|
"DATA",
|
||||||
snr,
|
snr,
|
||||||
ModemParam.frequency_offset,
|
self.modem_frequency_offset,
|
||||||
HamlibParam.hamlib_frequency,
|
self.states.radio_frequency,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.log.info("[Modem] ARQ REPEAT RECEIVED")
|
self.log.info("[Modem] ARQ REPEAT RECEIVED")
|
||||||
|
@ -1702,7 +1705,7 @@ class DATA:
|
||||||
############################################################################################################
|
############################################################################################################
|
||||||
def arq_session_handler(self, mycallsign, dxcallsign, attempts) -> bool:
|
def arq_session_handler(self, mycallsign, dxcallsign, attempts) -> bool:
|
||||||
"""
|
"""
|
||||||
Create a session with `Station.dxcallsign` and wait until the session is open.
|
Create a session with `self.dxcallsign` and wait until the session is open.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if the session was opened successfully
|
True if the session was opened successfully
|
||||||
|
@ -1714,8 +1717,8 @@ class DATA:
|
||||||
self.mycallsign = mycallsign
|
self.mycallsign = mycallsign
|
||||||
self.dxcallsign = dxcallsign
|
self.dxcallsign = dxcallsign
|
||||||
|
|
||||||
Station.dxcallsign = self.dxcallsign
|
self.states.set("dxcallsign", self.dxcallsign)
|
||||||
Station.dxcallsign_crc = helpers.get_crc_24(self.dxcallsign)
|
self.dxcallsign_crc = helpers.get_crc_24(self.dxcallsign)
|
||||||
|
|
||||||
self.log.info(
|
self.log.info(
|
||||||
"[Modem] SESSION ["
|
"[Modem] SESSION ["
|
||||||
|
@ -1727,7 +1730,7 @@ class DATA:
|
||||||
)
|
)
|
||||||
|
|
||||||
# wait if we have a channel busy condition
|
# wait if we have a channel busy condition
|
||||||
if ModemParam.channel_busy:
|
if self.states.channel_busy:
|
||||||
self.channel_busy_handler()
|
self.channel_busy_handler()
|
||||||
|
|
||||||
self.open_session()
|
self.open_session()
|
||||||
|
@ -1792,8 +1795,8 @@ class DATA:
|
||||||
connection_frame = bytearray(self.length_sig0_frame)
|
connection_frame = bytearray(self.length_sig0_frame)
|
||||||
connection_frame[:1] = bytes([FR_TYPE.ARQ_SESSION_OPEN.value])
|
connection_frame[:1] = bytes([FR_TYPE.ARQ_SESSION_OPEN.value])
|
||||||
connection_frame[1:2] = self.session_id
|
connection_frame[1:2] = self.session_id
|
||||||
connection_frame[2:5] = Station.dxcallsign_crc
|
connection_frame[2:5] = self.dxcallsign_crc
|
||||||
connection_frame[5:8] = Station.mycallsign_crc
|
connection_frame[5:8] = self.mycallsign_crc
|
||||||
connection_frame[8:14] = helpers.callsign_to_bytes(self.mycallsign)
|
connection_frame[8:14] = helpers.callsign_to_bytes(self.mycallsign)
|
||||||
|
|
||||||
while not ARQ.arq_session:
|
while not ARQ.arq_session:
|
||||||
|
@ -1879,21 +1882,21 @@ class DATA:
|
||||||
self.arq_session_last_received = int(time.time())
|
self.arq_session_last_received = int(time.time())
|
||||||
|
|
||||||
self.session_id = bytes(data_in[1:2])
|
self.session_id = bytes(data_in[1:2])
|
||||||
Station.dxcallsign_crc = bytes(data_in[5:8])
|
self.dxcallsign_crc = bytes(data_in[5:8])
|
||||||
self.dxcallsign = helpers.bytes_to_callsign(bytes(data_in[8:14]))
|
self.dxcallsign = helpers.bytes_to_callsign(bytes(data_in[8:14]))
|
||||||
Station.dxcallsign = self.dxcallsign
|
self.states.set("dxcallsign", self.dxcallsign)
|
||||||
|
|
||||||
# check if callsign ssid override
|
# check if callsign ssid override
|
||||||
valid, mycallsign = helpers.check_callsign(self.mycallsign, data_in[2:5])
|
valid, mycallsign = helpers.check_callsign(self.mycallsign, data_in[2:5])
|
||||||
self.mycallsign = mycallsign
|
self.mycallsign = mycallsign
|
||||||
Station.dxgrid = b'------'
|
self.dxgrid = b'------'
|
||||||
helpers.add_to_heard_stations(
|
helpers.add_to_heard_stations(
|
||||||
Station.dxcallsign,
|
self.dxcallsign,
|
||||||
Station.dxgrid,
|
self.dxgrid,
|
||||||
"DATA",
|
"DATA",
|
||||||
snr,
|
snr,
|
||||||
ModemParam.frequency_offset,
|
self.modem_frequency_offset,
|
||||||
HamlibParam.hamlib_frequency,
|
self.states.radio_frequency,
|
||||||
)
|
)
|
||||||
self.log.info(
|
self.log.info(
|
||||||
"[Modem] SESSION ["
|
"[Modem] SESSION ["
|
||||||
|
@ -1904,7 +1907,7 @@ class DATA:
|
||||||
self.states.arq_session_state,
|
self.states.arq_session_state,
|
||||||
)
|
)
|
||||||
ARQ.arq_session = True
|
ARQ.arq_session = True
|
||||||
Modem.modem_state = "BUSY"
|
self.states.set("is_modem_busy", True)
|
||||||
|
|
||||||
self.send_data_to_socket_queue(
|
self.send_data_to_socket_queue(
|
||||||
freedata="modem-message",
|
freedata="modem-message",
|
||||||
|
@ -1964,14 +1967,14 @@ class DATA:
|
||||||
_valid_session = helpers.check_session_id(self.session_id, bytes(data_in[1:2]))
|
_valid_session = helpers.check_session_id(self.session_id, bytes(data_in[1:2]))
|
||||||
if (_valid_crc or _valid_session) and self.states.arq_session_state not in ["disconnected"]:
|
if (_valid_crc or _valid_session) and self.states.arq_session_state not in ["disconnected"]:
|
||||||
self.states.set("arq_session_state", "disconnected")
|
self.states.set("arq_session_state", "disconnected")
|
||||||
Station.dxgrid = b'------'
|
self.dxgrid = b'------'
|
||||||
helpers.add_to_heard_stations(
|
helpers.add_to_heard_stations(
|
||||||
Station.dxcallsign,
|
self.dxcallsign,
|
||||||
Station.dxgrid,
|
self.dxgrid,
|
||||||
"DATA",
|
"DATA",
|
||||||
snr,
|
snr,
|
||||||
ModemParam.frequency_offset,
|
self.modem_frequency_offset,
|
||||||
HamlibParam.hamlib_frequency,
|
self.states.radio_frequency,
|
||||||
)
|
)
|
||||||
self.log.info(
|
self.log.info(
|
||||||
"[Modem] SESSION ["
|
"[Modem] SESSION ["
|
||||||
|
@ -1997,7 +2000,7 @@ class DATA:
|
||||||
def transmit_session_heartbeat(self) -> None:
|
def transmit_session_heartbeat(self) -> None:
|
||||||
"""Send ARQ sesion heartbeat while connected"""
|
"""Send ARQ sesion heartbeat while connected"""
|
||||||
# ARQ.arq_session = True
|
# ARQ.arq_session = True
|
||||||
# Modem.modem_state = "BUSY"
|
# self.states.set("is_modem_busy", True)
|
||||||
# self.states.set("arq_session_state", "connected")
|
# self.states.set("arq_session_state", "connected")
|
||||||
|
|
||||||
connection_frame = bytearray(self.length_sig0_frame)
|
connection_frame = bytearray(self.length_sig0_frame)
|
||||||
|
@ -2027,14 +2030,14 @@ class DATA:
|
||||||
_valid_session = helpers.check_session_id(self.session_id, bytes(data_in[1:2]))
|
_valid_session = helpers.check_session_id(self.session_id, bytes(data_in[1:2]))
|
||||||
if _valid_crc or _valid_session and self.states.arq_session_state in ["connected", "connecting"]:
|
if _valid_crc or _valid_session and self.states.arq_session_state in ["connected", "connecting"]:
|
||||||
self.log.debug("[Modem] Received session heartbeat")
|
self.log.debug("[Modem] Received session heartbeat")
|
||||||
Station.dxgrid = b'------'
|
self.dxgrid = b'------'
|
||||||
helpers.add_to_heard_stations(
|
helpers.add_to_heard_stations(
|
||||||
self.dxcallsign,
|
self.dxcallsign,
|
||||||
Station.dxgrid,
|
self.dxgrid,
|
||||||
"SESSION-HB",
|
"SESSION-HB",
|
||||||
snr,
|
snr,
|
||||||
ModemParam.frequency_offset,
|
self.modem_frequency_offset,
|
||||||
HamlibParam.hamlib_frequency,
|
self.states.radio_frequency,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.send_data_to_socket_queue(
|
self.send_data_to_socket_queue(
|
||||||
|
@ -2048,7 +2051,7 @@ class DATA:
|
||||||
|
|
||||||
ARQ.arq_session = True
|
ARQ.arq_session = True
|
||||||
self.states.set("arq_session_state", "connected")
|
self.states.set("arq_session_state", "connected")
|
||||||
Modem.modem_state = "BUSY"
|
self.states.set("is_modem_busy", True)
|
||||||
|
|
||||||
# Update the timeout timestamps
|
# Update the timeout timestamps
|
||||||
self.arq_session_last_received = int(time.time())
|
self.arq_session_last_received = int(time.time())
|
||||||
|
@ -2096,14 +2099,12 @@ class DATA:
|
||||||
# overwrite mycallsign in case of different SSID
|
# overwrite mycallsign in case of different SSID
|
||||||
self.mycallsign = mycallsign
|
self.mycallsign = mycallsign
|
||||||
self.dxcallsign = dxcallsign
|
self.dxcallsign = dxcallsign
|
||||||
|
self.dxcallsign_crc = helpers.get_crc_24(self.dxcallsign)
|
||||||
Station.dxcallsign = dxcallsign
|
|
||||||
Station.dxcallsign_crc = helpers.get_crc_24(Station.dxcallsign)
|
|
||||||
|
|
||||||
# override session connection attempts
|
# override session connection attempts
|
||||||
self.data_channel_max_retries = attempts
|
self.data_channel_max_retries = attempts
|
||||||
|
|
||||||
Modem.modem_state = "BUSY"
|
self.states.set("is_modem_busy", True)
|
||||||
self.arq_file_transfer = True
|
self.arq_file_transfer = True
|
||||||
|
|
||||||
self.transmission_uuid = transmission_uuid
|
self.transmission_uuid = transmission_uuid
|
||||||
|
@ -2195,8 +2196,8 @@ class DATA:
|
||||||
|
|
||||||
connection_frame = bytearray(self.length_sig0_frame)
|
connection_frame = bytearray(self.length_sig0_frame)
|
||||||
connection_frame[:1] = frametype
|
connection_frame[:1] = frametype
|
||||||
connection_frame[1:4] = Station.dxcallsign_crc
|
connection_frame[1:4] = self.dxcallsign_crc
|
||||||
connection_frame[4:7] = Station.mycallsign_crc
|
connection_frame[4:7] = self.mycallsign_crc
|
||||||
connection_frame[7:13] = helpers.callsign_to_bytes(mycallsign)
|
connection_frame[7:13] = helpers.callsign_to_bytes(mycallsign)
|
||||||
connection_frame[13:14] = self.session_id
|
connection_frame[13:14] = self.session_id
|
||||||
|
|
||||||
|
@ -2221,7 +2222,7 @@ class DATA:
|
||||||
)
|
)
|
||||||
|
|
||||||
# Let's check if we have a busy channel and if we are not in a running arq session.
|
# Let's check if we have a busy channel and if we are not in a running arq session.
|
||||||
if ModemParam.channel_busy and not self.arq_state_event.is_set() or self.states.is_codec2_traffic:
|
if self.states.channel_busy and not self.arq_state_event.is_set() or self.states.is_codec2_traffic:
|
||||||
self.channel_busy_handler()
|
self.channel_busy_handler()
|
||||||
|
|
||||||
# if channel free, enqueue frame for tx
|
# if channel free, enqueue frame for tx
|
||||||
|
@ -2235,7 +2236,7 @@ class DATA:
|
||||||
|
|
||||||
if self.states.is_arq_state_event.is_set():
|
if self.states.is_arq_state_event.is_set():
|
||||||
return True
|
return True
|
||||||
if Modem.modem_state in ["IDLE"]:
|
if not self.states.is_modem_busy:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# `data_channel_max_retries` attempts have been sent. Aborting attempt & cleaning up
|
# `data_channel_max_retries` attempts have been sent. Aborting attempt & cleaning up
|
||||||
|
@ -2258,7 +2259,7 @@ class DATA:
|
||||||
|
|
||||||
# stop processing if not in arq session, but modem state is busy and we have a different session id
|
# stop processing if not in arq session, but modem state is busy and we have a different session id
|
||||||
# use-case we get a connection request while connecting to another station
|
# use-case we get a connection request while connecting to another station
|
||||||
if not ARQ.arq_session and Modem.modem_state in ["BUSY"] and data_in[13:14] != self.session_id:
|
if not ARQ.arq_session and self.states.is_modem_busy and data_in[13:14] != self.session_id:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.arq_file_transfer = True
|
self.arq_file_transfer = True
|
||||||
|
@ -2276,9 +2277,9 @@ class DATA:
|
||||||
|
|
||||||
self.is_IRS = True
|
self.is_IRS = True
|
||||||
|
|
||||||
Station.dxcallsign_crc = bytes(data_in[4:7])
|
self.dxcallsign_crc = bytes(data_in[4:7])
|
||||||
self.dxcallsign = helpers.bytes_to_callsign(bytes(data_in[7:13]))
|
self.dxcallsign = helpers.bytes_to_callsign(bytes(data_in[7:13]))
|
||||||
Station.dxcallsign = self.dxcallsign
|
self.states.set("dxcallsign", self.dxcallsign)
|
||||||
|
|
||||||
self.send_data_to_socket_queue(
|
self.send_data_to_socket_queue(
|
||||||
freedata="modem-message",
|
freedata="modem-message",
|
||||||
|
@ -2347,14 +2348,14 @@ class DATA:
|
||||||
|
|
||||||
# Update modes we are listening to
|
# Update modes we are listening to
|
||||||
self.set_listening_modes(True, True, self.mode_list[self.speed_level])
|
self.set_listening_modes(True, True, self.mode_list[self.speed_level])
|
||||||
Station.dxgrid = b'------'
|
self.dxgrid = b'------'
|
||||||
helpers.add_to_heard_stations(
|
helpers.add_to_heard_stations(
|
||||||
Station.dxcallsign,
|
self.dxcallsign,
|
||||||
Station.dxgrid,
|
self.dxgrid,
|
||||||
"DATA",
|
"DATA",
|
||||||
snr,
|
snr,
|
||||||
ModemParam.frequency_offset,
|
self.modem_frequency_offset,
|
||||||
HamlibParam.hamlib_frequency,
|
self.states.radio_frequency,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.session_id = data_in[13:14]
|
self.session_id = data_in[13:14]
|
||||||
|
@ -2379,7 +2380,7 @@ class DATA:
|
||||||
# Set ARQ State AFTER resetting timeouts
|
# Set ARQ State AFTER resetting timeouts
|
||||||
# this avoids timeouts starting too early
|
# this avoids timeouts starting too early
|
||||||
self.states.set("is_arq_state", True)
|
self.states.set("is_arq_state", True)
|
||||||
Modem.modem_state = "BUSY"
|
self.states.set("is_modem_busy", True)
|
||||||
|
|
||||||
self.reset_statistics()
|
self.reset_statistics()
|
||||||
|
|
||||||
|
@ -2461,14 +2462,14 @@ class DATA:
|
||||||
self.speed_level = int.from_bytes(bytes(data_in[8:9]), "big")
|
self.speed_level = int.from_bytes(bytes(data_in[8:9]), "big")
|
||||||
self.log.debug("[Modem] speed level selected for given SNR", speed_level=self.speed_level)
|
self.log.debug("[Modem] speed level selected for given SNR", speed_level=self.speed_level)
|
||||||
|
|
||||||
Station.dxgrid = b'------'
|
self.dxgrid = b'------'
|
||||||
helpers.add_to_heard_stations(
|
helpers.add_to_heard_stations(
|
||||||
Station.dxcallsign,
|
self.dxcallsign,
|
||||||
Station.dxgrid,
|
self.dxgrid,
|
||||||
"DATA",
|
"DATA",
|
||||||
snr,
|
snr,
|
||||||
ModemParam.frequency_offset,
|
self.modem_frequency_offset,
|
||||||
HamlibParam.hamlib_frequency,
|
self.states.radio_frequency,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.log.info(
|
self.log.info(
|
||||||
|
@ -2531,8 +2532,8 @@ class DATA:
|
||||||
dxcallsign = helpers.callsign_to_bytes(dxcallsign)
|
dxcallsign = helpers.callsign_to_bytes(dxcallsign)
|
||||||
dxcallsign = helpers.bytes_to_callsign(dxcallsign)
|
dxcallsign = helpers.bytes_to_callsign(dxcallsign)
|
||||||
|
|
||||||
Station.dxcallsign = dxcallsign
|
self.dxcallsign = dxcallsign
|
||||||
Station.dxcallsign_crc = helpers.get_crc_24(Station.dxcallsign)
|
self.dxcallsign_crc = helpers.get_crc_24(self.dxcallsign)
|
||||||
self.send_data_to_socket_queue(
|
self.send_data_to_socket_queue(
|
||||||
freedata="modem-message",
|
freedata="modem-message",
|
||||||
ping="transmitting",
|
ping="transmitting",
|
||||||
|
@ -2549,12 +2550,12 @@ class DATA:
|
||||||
|
|
||||||
ping_frame = bytearray(self.length_sig0_frame)
|
ping_frame = bytearray(self.length_sig0_frame)
|
||||||
ping_frame[:1] = bytes([FR_TYPE.PING.value])
|
ping_frame[:1] = bytes([FR_TYPE.PING.value])
|
||||||
ping_frame[1:4] = Station.dxcallsign_crc
|
ping_frame[1:4] = self.dxcallsign_crc
|
||||||
ping_frame[4:7] = helpers.get_crc_24(mycallsign)
|
ping_frame[4:7] = helpers.get_crc_24(mycallsign)
|
||||||
ping_frame[7:13] = helpers.callsign_to_bytes(mycallsign)
|
ping_frame[7:13] = helpers.callsign_to_bytes(mycallsign)
|
||||||
|
|
||||||
if Modem.enable_fsk:
|
if self.enable_fsk:
|
||||||
self.log.info("[Modem] ENABLE FSK", state=Modem.enable_fsk)
|
self.log.info("[Modem] ENABLE FSK", state=self.enable_fsk)
|
||||||
self.enqueue_frame_for_tx([ping_frame], c2_mode=FREEDV_MODE.fsk_ldpc_0.value)
|
self.enqueue_frame_for_tx([ping_frame], c2_mode=FREEDV_MODE.fsk_ldpc_0.value)
|
||||||
else:
|
else:
|
||||||
self.enqueue_frame_for_tx([ping_frame], c2_mode=FREEDV_MODE.sig0.value)
|
self.enqueue_frame_for_tx([ping_frame], c2_mode=FREEDV_MODE.sig0.value)
|
||||||
|
@ -2577,8 +2578,8 @@ class DATA:
|
||||||
self.log.debug("[Modem] received_ping: ping not for this station.")
|
self.log.debug("[Modem] received_ping: ping not for this station.")
|
||||||
return
|
return
|
||||||
|
|
||||||
Station.dxcallsign_crc = dxcallsign_crc
|
self.dxcallsign_crc = dxcallsign_crc
|
||||||
Station.dxcallsign = dxcallsign
|
self.dxcallsign = dxcallsign
|
||||||
self.log.info(
|
self.log.info(
|
||||||
"[Modem] PING REQ ["
|
"[Modem] PING REQ ["
|
||||||
+ str(mycallsign, "UTF-8")
|
+ str(mycallsign, "UTF-8")
|
||||||
|
@ -2588,14 +2589,14 @@ class DATA:
|
||||||
snr=snr,
|
snr=snr,
|
||||||
)
|
)
|
||||||
|
|
||||||
Station.dxgrid = b'------'
|
self.dxgrid = b'------'
|
||||||
helpers.add_to_heard_stations(
|
helpers.add_to_heard_stations(
|
||||||
dxcallsign,
|
dxcallsign,
|
||||||
Station.dxgrid,
|
self.dxgrid,
|
||||||
"PING",
|
"PING",
|
||||||
snr,
|
snr,
|
||||||
ModemParam.frequency_offset,
|
self.modem_frequency_offset,
|
||||||
HamlibParam.hamlib_frequency,
|
self.states.radio_frequency,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.send_data_to_socket_queue(
|
self.send_data_to_socket_queue(
|
||||||
|
@ -2603,7 +2604,7 @@ class DATA:
|
||||||
ping="received",
|
ping="received",
|
||||||
uuid=str(uuid.uuid4()),
|
uuid=str(uuid.uuid4()),
|
||||||
timestamp=int(time.time()),
|
timestamp=int(time.time()),
|
||||||
dxgrid=str(Station.dxgrid, "UTF-8"),
|
dxgrid=str(self.dxgrid, "UTF-8"),
|
||||||
dxcallsign=str(dxcallsign, "UTF-8"),
|
dxcallsign=str(dxcallsign, "UTF-8"),
|
||||||
mycallsign=str(mycallsign, "UTF-8"),
|
mycallsign=str(mycallsign, "UTF-8"),
|
||||||
snr=str(snr),
|
snr=str(snr),
|
||||||
|
@ -2619,12 +2620,12 @@ class DATA:
|
||||||
"""
|
"""
|
||||||
ping_frame = bytearray(self.length_sig0_frame)
|
ping_frame = bytearray(self.length_sig0_frame)
|
||||||
ping_frame[:1] = bytes([FR_TYPE.PING_ACK.value])
|
ping_frame[:1] = bytes([FR_TYPE.PING_ACK.value])
|
||||||
ping_frame[1:4] = Station.dxcallsign_crc
|
ping_frame[1:4] = self.dxcallsign_crc
|
||||||
ping_frame[4:7] = Station.mycallsign_crc
|
ping_frame[4:7] = self.mycallsign_crc
|
||||||
ping_frame[7:11] = helpers.encode_grid(self.mygrid)
|
ping_frame[7:11] = helpers.encode_grid(self.mygrid)
|
||||||
ping_frame[13:14] = helpers.snr_to_bytes(snr)
|
ping_frame[13:14] = helpers.snr_to_bytes(snr)
|
||||||
|
|
||||||
if Modem.enable_fsk:
|
if self.enable_fsk:
|
||||||
self.enqueue_frame_for_tx([ping_frame], c2_mode=FREEDV_MODE.fsk_ldpc_0.value)
|
self.enqueue_frame_for_tx([ping_frame], c2_mode=FREEDV_MODE.fsk_ldpc_0.value)
|
||||||
else:
|
else:
|
||||||
self.enqueue_frame_for_tx([ping_frame], c2_mode=FREEDV_MODE.sig0.value)
|
self.enqueue_frame_for_tx([ping_frame], c2_mode=FREEDV_MODE.sig0.value)
|
||||||
|
@ -2642,15 +2643,15 @@ class DATA:
|
||||||
_valid, mycallsign = helpers.check_callsign(self.mycallsign, data_in[1:4])
|
_valid, mycallsign = helpers.check_callsign(self.mycallsign, data_in[1:4])
|
||||||
if _valid:
|
if _valid:
|
||||||
|
|
||||||
Station.dxgrid = bytes(helpers.decode_grid(data_in[7:11]), "UTF-8")
|
self.dxgrid = bytes(helpers.decode_grid(data_in[7:11]), "UTF-8")
|
||||||
dxsnr = helpers.snr_from_bytes(data_in[13:14])
|
dxsnr = helpers.snr_from_bytes(data_in[13:14])
|
||||||
self.send_data_to_socket_queue(
|
self.send_data_to_socket_queue(
|
||||||
freedata="modem-message",
|
freedata="modem-message",
|
||||||
ping="acknowledge",
|
ping="acknowledge",
|
||||||
uuid=str(uuid.uuid4()),
|
uuid=str(uuid.uuid4()),
|
||||||
timestamp=int(time.time()),
|
timestamp=int(time.time()),
|
||||||
dxgrid=str(Station.dxgrid, "UTF-8"),
|
dxgrid=str(self.dxgrid, "UTF-8"),
|
||||||
dxcallsign=str(Station.dxcallsign, "UTF-8"),
|
dxcallsign=str(self.dxcallsign, "UTF-8"),
|
||||||
mycallsign=str(mycallsign, "UTF-8"),
|
mycallsign=str(mycallsign, "UTF-8"),
|
||||||
snr=str(snr),
|
snr=str(snr),
|
||||||
dxsnr=str(dxsnr)
|
dxsnr=str(dxsnr)
|
||||||
|
@ -2658,24 +2659,24 @@ class DATA:
|
||||||
# combined_snr = own rx snr / snr on dx side
|
# combined_snr = own rx snr / snr on dx side
|
||||||
combined_snr = f"{snr}/{dxsnr}"
|
combined_snr = f"{snr}/{dxsnr}"
|
||||||
helpers.add_to_heard_stations(
|
helpers.add_to_heard_stations(
|
||||||
Station.dxcallsign,
|
self.dxcallsign,
|
||||||
Station.dxgrid,
|
self.dxgrid,
|
||||||
"PING-ACK",
|
"PING-ACK",
|
||||||
combined_snr,
|
combined_snr,
|
||||||
ModemParam.frequency_offset,
|
self.modem_frequency_offset,
|
||||||
HamlibParam.hamlib_frequency,
|
self.states.radio_frequency,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.log.info(
|
self.log.info(
|
||||||
"[Modem] PING ACK ["
|
"[Modem] PING ACK ["
|
||||||
+ str(mycallsign, "UTF-8")
|
+ str(mycallsign, "UTF-8")
|
||||||
+ "] >|< ["
|
+ "] >|< ["
|
||||||
+ str(Station.dxcallsign, "UTF-8")
|
+ str(self.dxcallsign, "UTF-8")
|
||||||
+ "]",
|
+ "]",
|
||||||
snr=snr,
|
snr=snr,
|
||||||
dxsnr=dxsnr,
|
dxsnr=dxsnr,
|
||||||
)
|
)
|
||||||
Modem.modem_state = "IDLE"
|
self.states.set("is_modem_busy", False)
|
||||||
else:
|
else:
|
||||||
self.log.info(
|
self.log.info(
|
||||||
"[Modem] FOREIGN PING ACK ["
|
"[Modem] FOREIGN PING ACK ["
|
||||||
|
@ -2702,8 +2703,8 @@ class DATA:
|
||||||
|
|
||||||
stop_frame = bytearray(self.length_sig0_frame)
|
stop_frame = bytearray(self.length_sig0_frame)
|
||||||
stop_frame[:1] = bytes([FR_TYPE.ARQ_STOP.value])
|
stop_frame[:1] = bytes([FR_TYPE.ARQ_STOP.value])
|
||||||
stop_frame[1:4] = Station.dxcallsign_crc
|
stop_frame[1:4] = self.dxcallsign_crc
|
||||||
stop_frame[4:7] = Station.mycallsign_crc
|
stop_frame[4:7] = self.mycallsign_crc
|
||||||
# TODO Not sure if we really need the session id when disconnecting
|
# TODO Not sure if we really need the session id when disconnecting
|
||||||
# stop_frame[1:2] = self.session_id
|
# stop_frame[1:2] = self.session_id
|
||||||
stop_frame[7:13] = helpers.callsign_to_bytes(self.mycallsign)
|
stop_frame[7:13] = helpers.callsign_to_bytes(self.mycallsign)
|
||||||
|
@ -2718,7 +2719,7 @@ class DATA:
|
||||||
Received a transmission stop
|
Received a transmission stop
|
||||||
"""
|
"""
|
||||||
self.log.warning("[Modem] Stopping transmission!")
|
self.log.warning("[Modem] Stopping transmission!")
|
||||||
Modem.modem_state = "IDLE"
|
self.states.set("is_modem_busy", False)
|
||||||
self.states.set("is_arq_state", False)
|
self.states.set("is_arq_state", False)
|
||||||
self.send_data_to_socket_queue(
|
self.send_data_to_socket_queue(
|
||||||
freedata="modem-message",
|
freedata="modem-message",
|
||||||
|
@ -2749,8 +2750,8 @@ class DATA:
|
||||||
not ARQ.arq_session
|
not ARQ.arq_session
|
||||||
and not self.arq_file_transfer
|
and not self.arq_file_transfer
|
||||||
and not self.beacon_paused
|
and not self.beacon_paused
|
||||||
#and not ModemParam.channel_busy
|
#and not self.states.channel_busy
|
||||||
and Modem.modem_state not in ["BUSY"]
|
and not self.states.is_modem_busy
|
||||||
and not self.states.is_arq_state
|
and not self.states.is_arq_state
|
||||||
):
|
):
|
||||||
self.send_data_to_socket_queue(
|
self.send_data_to_socket_queue(
|
||||||
|
@ -2768,8 +2769,8 @@ class DATA:
|
||||||
beacon_frame[1:7] = helpers.callsign_to_bytes(self.mycallsign)
|
beacon_frame[1:7] = helpers.callsign_to_bytes(self.mycallsign)
|
||||||
beacon_frame[7:11] = helpers.encode_grid(self.mygrid)
|
beacon_frame[7:11] = helpers.encode_grid(self.mygrid)
|
||||||
|
|
||||||
if Modem.enable_fsk:
|
if self.enable_fsk:
|
||||||
self.log.info("[Modem] ENABLE FSK", state=Modem.enable_fsk)
|
self.log.info("[Modem] ENABLE FSK", state=self.enable_fsk)
|
||||||
self.enqueue_frame_for_tx(
|
self.enqueue_frame_for_tx(
|
||||||
[beacon_frame],
|
[beacon_frame],
|
||||||
c2_mode=FREEDV_MODE.fsk_ldpc_0.value,
|
c2_mode=FREEDV_MODE.fsk_ldpc_0.value,
|
||||||
|
@ -2800,14 +2801,14 @@ class DATA:
|
||||||
"""
|
"""
|
||||||
# here we add the received station to the heard stations buffer
|
# here we add the received station to the heard stations buffer
|
||||||
beacon_callsign = helpers.bytes_to_callsign(bytes(data_in[1:7]))
|
beacon_callsign = helpers.bytes_to_callsign(bytes(data_in[1:7]))
|
||||||
Station.dxgrid = bytes(helpers.decode_grid(data_in[7:11]), "UTF-8")
|
self.dxgrid = bytes(helpers.decode_grid(data_in[7:11]), "UTF-8")
|
||||||
self.send_data_to_socket_queue(
|
self.send_data_to_socket_queue(
|
||||||
freedata="modem-message",
|
freedata="modem-message",
|
||||||
beacon="received",
|
beacon="received",
|
||||||
uuid=str(uuid.uuid4()),
|
uuid=str(uuid.uuid4()),
|
||||||
timestamp=int(time.time()),
|
timestamp=int(time.time()),
|
||||||
dxcallsign=str(beacon_callsign, "UTF-8"),
|
dxcallsign=str(beacon_callsign, "UTF-8"),
|
||||||
dxgrid=str(Station.dxgrid, "UTF-8"),
|
dxgrid=str(self.dxgrid, "UTF-8"),
|
||||||
snr=str(snr),
|
snr=str(snr),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -2815,17 +2816,17 @@ class DATA:
|
||||||
"[Modem] BEACON RCVD ["
|
"[Modem] BEACON RCVD ["
|
||||||
+ str(beacon_callsign, "UTF-8")
|
+ str(beacon_callsign, "UTF-8")
|
||||||
+ "]["
|
+ "]["
|
||||||
+ str(Station.dxgrid, "UTF-8")
|
+ str(self.dxgrid, "UTF-8")
|
||||||
+ "] ",
|
+ "] ",
|
||||||
snr=snr,
|
snr=snr,
|
||||||
)
|
)
|
||||||
helpers.add_to_heard_stations(
|
helpers.add_to_heard_stations(
|
||||||
beacon_callsign,
|
beacon_callsign,
|
||||||
Station.dxgrid,
|
self.dxgrid,
|
||||||
"BEACON",
|
"BEACON",
|
||||||
snr,
|
snr,
|
||||||
ModemParam.frequency_offset,
|
self.modem_frequency_offset,
|
||||||
HamlibParam.hamlib_frequency,
|
self.states.radio_frequency,
|
||||||
)
|
)
|
||||||
|
|
||||||
def transmit_cq(self) -> None:
|
def transmit_cq(self) -> None:
|
||||||
|
@ -2851,8 +2852,8 @@ class DATA:
|
||||||
|
|
||||||
self.log.debug("[Modem] CQ Frame:", data=[cq_frame])
|
self.log.debug("[Modem] CQ Frame:", data=[cq_frame])
|
||||||
|
|
||||||
if Modem.enable_fsk:
|
if self.enable_fsk:
|
||||||
self.log.info("[Modem] ENABLE FSK", state=Modem.enable_fsk)
|
self.log.info("[Modem] ENABLE FSK", state=self.enable_fsk)
|
||||||
self.enqueue_frame_for_tx([cq_frame], c2_mode=FREEDV_MODE.fsk_ldpc_0.value)
|
self.enqueue_frame_for_tx([cq_frame], c2_mode=FREEDV_MODE.fsk_ldpc_0.value)
|
||||||
else:
|
else:
|
||||||
self.enqueue_frame_for_tx([cq_frame], c2_mode=FREEDV_MODE.sig0.value, copies=1, repeat_delay=0)
|
self.enqueue_frame_for_tx([cq_frame], c2_mode=FREEDV_MODE.sig0.value, copies=1, repeat_delay=0)
|
||||||
|
@ -2869,30 +2870,30 @@ class DATA:
|
||||||
# here we add the received station to the heard stations buffer
|
# here we add the received station to the heard stations buffer
|
||||||
dxcallsign = helpers.bytes_to_callsign(bytes(data_in[1:7]))
|
dxcallsign = helpers.bytes_to_callsign(bytes(data_in[1:7]))
|
||||||
self.log.debug("[Modem] received_cq:", dxcallsign=dxcallsign)
|
self.log.debug("[Modem] received_cq:", dxcallsign=dxcallsign)
|
||||||
Station.dxgrid = bytes(helpers.decode_grid(data_in[7:11]), "UTF-8")
|
self.dxgrid = bytes(helpers.decode_grid(data_in[7:11]), "UTF-8")
|
||||||
|
|
||||||
self.send_data_to_socket_queue(
|
self.send_data_to_socket_queue(
|
||||||
freedata="modem-message",
|
freedata="modem-message",
|
||||||
cq="received",
|
cq="received",
|
||||||
mycallsign=str(self.mycallsign, "UTF-8"),
|
mycallsign=str(self.mycallsign, "UTF-8"),
|
||||||
dxcallsign=str(dxcallsign, "UTF-8"),
|
dxcallsign=str(dxcallsign, "UTF-8"),
|
||||||
dxgrid=str(Station.dxgrid, "UTF-8"),
|
dxgrid=str(self.dxgrid, "UTF-8"),
|
||||||
)
|
)
|
||||||
self.log.info(
|
self.log.info(
|
||||||
"[Modem] CQ RCVD ["
|
"[Modem] CQ RCVD ["
|
||||||
+ str(dxcallsign, "UTF-8")
|
+ str(dxcallsign, "UTF-8")
|
||||||
+ "]["
|
+ "]["
|
||||||
+ str(Station.dxgrid, "UTF-8")
|
+ str(self.dxgrid, "UTF-8")
|
||||||
+ "] ",
|
+ "] ",
|
||||||
snr=snr,
|
snr=snr,
|
||||||
)
|
)
|
||||||
helpers.add_to_heard_stations(
|
helpers.add_to_heard_stations(
|
||||||
dxcallsign,
|
dxcallsign,
|
||||||
Station.dxgrid,
|
self.dxgrid,
|
||||||
"CQ CQ CQ",
|
"CQ CQ CQ",
|
||||||
snr,
|
snr,
|
||||||
ModemParam.frequency_offset,
|
self.modem_frequency_offset,
|
||||||
HamlibParam.hamlib_frequency,
|
self.states.radio_frequency,
|
||||||
)
|
)
|
||||||
|
|
||||||
if Modem.respond_to_cq and Modem.respond_to_call:
|
if Modem.respond_to_cq and Modem.respond_to_call:
|
||||||
|
@ -2929,8 +2930,8 @@ class DATA:
|
||||||
qrv_frame[7:11] = helpers.encode_grid(self.mygrid)
|
qrv_frame[7:11] = helpers.encode_grid(self.mygrid)
|
||||||
qrv_frame[11:12] = helpers.snr_to_bytes(snr)
|
qrv_frame[11:12] = helpers.snr_to_bytes(snr)
|
||||||
|
|
||||||
if Modem.enable_fsk:
|
if self.enable_fsk:
|
||||||
self.log.info("[Modem] ENABLE FSK", state=Modem.enable_fsk)
|
self.log.info("[Modem] ENABLE FSK", state=self.enable_fsk)
|
||||||
self.enqueue_frame_for_tx([qrv_frame], c2_mode=FREEDV_MODE.fsk_ldpc_0.value)
|
self.enqueue_frame_for_tx([qrv_frame], c2_mode=FREEDV_MODE.fsk_ldpc_0.value)
|
||||||
else:
|
else:
|
||||||
self.enqueue_frame_for_tx([qrv_frame], c2_mode=FREEDV_MODE.sig0.value, copies=1, repeat_delay=0)
|
self.enqueue_frame_for_tx([qrv_frame], c2_mode=FREEDV_MODE.sig0.value, copies=1, repeat_delay=0)
|
||||||
|
@ -2944,7 +2945,7 @@ class DATA:
|
||||||
"""
|
"""
|
||||||
# here we add the received station to the heard stations buffer
|
# here we add the received station to the heard stations buffer
|
||||||
dxcallsign = helpers.bytes_to_callsign(bytes(data_in[1:7]))
|
dxcallsign = helpers.bytes_to_callsign(bytes(data_in[1:7]))
|
||||||
Station.dxgrid = bytes(helpers.decode_grid(data_in[7:11]), "UTF-8")
|
self.dxgrid = bytes(helpers.decode_grid(data_in[7:11]), "UTF-8")
|
||||||
dxsnr = helpers.snr_from_bytes(data_in[11:12])
|
dxsnr = helpers.snr_from_bytes(data_in[11:12])
|
||||||
|
|
||||||
combined_snr = f"{snr}/{dxsnr}"
|
combined_snr = f"{snr}/{dxsnr}"
|
||||||
|
@ -2953,7 +2954,7 @@ class DATA:
|
||||||
freedata="modem-message",
|
freedata="modem-message",
|
||||||
qrv="received",
|
qrv="received",
|
||||||
dxcallsign=str(dxcallsign, "UTF-8"),
|
dxcallsign=str(dxcallsign, "UTF-8"),
|
||||||
dxgrid=str(Station.dxgrid, "UTF-8"),
|
dxgrid=str(self.dxgrid, "UTF-8"),
|
||||||
snr=str(snr),
|
snr=str(snr),
|
||||||
dxsnr=str(dxsnr)
|
dxsnr=str(dxsnr)
|
||||||
)
|
)
|
||||||
|
@ -2962,18 +2963,18 @@ class DATA:
|
||||||
"[Modem] QRV RCVD ["
|
"[Modem] QRV RCVD ["
|
||||||
+ str(dxcallsign, "UTF-8")
|
+ str(dxcallsign, "UTF-8")
|
||||||
+ "]["
|
+ "]["
|
||||||
+ str(Station.dxgrid, "UTF-8")
|
+ str(self.dxgrid, "UTF-8")
|
||||||
+ "] ",
|
+ "] ",
|
||||||
snr=snr,
|
snr=snr,
|
||||||
dxsnr=dxsnr
|
dxsnr=dxsnr
|
||||||
)
|
)
|
||||||
helpers.add_to_heard_stations(
|
helpers.add_to_heard_stations(
|
||||||
dxcallsign,
|
dxcallsign,
|
||||||
Station.dxgrid,
|
self.dxgrid,
|
||||||
"QRV",
|
"QRV",
|
||||||
combined_snr,
|
combined_snr,
|
||||||
ModemParam.frequency_offset,
|
self.modem_frequency_offset,
|
||||||
HamlibParam.hamlib_frequency,
|
self.states.radio_frequency,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -3017,7 +3018,7 @@ class DATA:
|
||||||
|
|
||||||
# wait while timeout not reached and our busy state is busy
|
# wait while timeout not reached and our busy state is busy
|
||||||
channel_busy_timeout = time.time() + self.channel_busy_timeout
|
channel_busy_timeout = time.time() + self.channel_busy_timeout
|
||||||
while ModemParam.channel_busy and time.time() < channel_busy_timeout and not self.check_if_mode_fits_to_busy_slot():
|
while self.states.channel_busy and time.time() < channel_busy_timeout and not self.check_if_mode_fits_to_busy_slot():
|
||||||
threading.Event().wait(0.01)
|
threading.Event().wait(0.01)
|
||||||
|
|
||||||
# ------------ CALCULATE TRANSFER RATES
|
# ------------ CALCULATE TRANSFER RATES
|
||||||
|
@ -3199,7 +3200,7 @@ class DATA:
|
||||||
|
|
||||||
# we need to keep these values if in ARQ_SESSION
|
# we need to keep these values if in ARQ_SESSION
|
||||||
if not ARQ.arq_session:
|
if not ARQ.arq_session:
|
||||||
Modem.modem_state = "IDLE"
|
self.states.set("is_modem_busy", False)
|
||||||
self.dxcallsign = b"AA0AA-0"
|
self.dxcallsign = b"AA0AA-0"
|
||||||
self.mycallsign = self.mycallsign
|
self.mycallsign = self.mycallsign
|
||||||
self.session_id = bytes(1)
|
self.session_id = bytes(1)
|
||||||
|
@ -3340,7 +3341,7 @@ class DATA:
|
||||||
waiting_time = (self.time_list[self.speed_level] * frames_left) + self.duration_sig0_frame + self.channel_busy_timeout + 1
|
waiting_time = (self.time_list[self.speed_level] * frames_left) + self.duration_sig0_frame + self.channel_busy_timeout + 1
|
||||||
timeout_percent = 100 - (time_left / waiting_time * 100)
|
timeout_percent = 100 - (time_left / waiting_time * 100)
|
||||||
#timeout_percent = 0
|
#timeout_percent = 0
|
||||||
if timeout_percent >= 75 and not self.states.is_codec2_traffic and not Modem.transmitting:
|
if timeout_percent >= 75 and not self.states.is_codec2_traffic and not self.states.is_transmitting:
|
||||||
override = True
|
override = True
|
||||||
else:
|
else:
|
||||||
override = False
|
override = False
|
||||||
|
@ -3351,7 +3352,7 @@ class DATA:
|
||||||
# better wait some more time because data might be important for us
|
# better wait some more time because data might be important for us
|
||||||
# reason for this situation can be delays on IRS and ISS, maybe because both had a busy channel condition.
|
# reason for this situation can be delays on IRS and ISS, maybe because both had a busy channel condition.
|
||||||
# Nevertheless, we need to keep timeouts short for efficiency
|
# Nevertheless, we need to keep timeouts short for efficiency
|
||||||
if timeout <= time.time() or modem_error_state and not self.states.is_codec2_traffic and not Modem.transmitting or override:
|
if timeout <= time.time() or modem_error_state and not self.states.is_codec2_traffic and not self.states.is_transmitting or override:
|
||||||
self.log.warning(
|
self.log.warning(
|
||||||
"[Modem] Burst decoding error or timeout",
|
"[Modem] Burst decoding error or timeout",
|
||||||
attempt=self.n_retries_per_burst,
|
attempt=self.n_retries_per_burst,
|
||||||
|
@ -3413,7 +3414,7 @@ class DATA:
|
||||||
DATA CHANNEL
|
DATA CHANNEL
|
||||||
"""
|
"""
|
||||||
# and not static.ARQ_SEND_KEEP_ALIVE:
|
# and not static.ARQ_SEND_KEEP_ALIVE:
|
||||||
if self.states.is_arq_state and Modem.modem_state == "BUSY":
|
if self.states.is_arq_state and self.states.is_modem_busy:
|
||||||
threading.Event().wait(0.01)
|
threading.Event().wait(0.01)
|
||||||
if (
|
if (
|
||||||
self.data_channel_last_received + self.transmission_timeout
|
self.data_channel_last_received + self.transmission_timeout
|
||||||
|
@ -3435,7 +3436,7 @@ class DATA:
|
||||||
"[Modem] DATA ["
|
"[Modem] DATA ["
|
||||||
+ str(self.mycallsign, "UTF-8")
|
+ str(self.mycallsign, "UTF-8")
|
||||||
+ "]<<T>>["
|
+ "]<<T>>["
|
||||||
+ str(Station.dxcallsign, "UTF-8")
|
+ str(self.dxcallsign, "UTF-8")
|
||||||
+ "]"
|
+ "]"
|
||||||
)
|
)
|
||||||
self.send_data_to_socket_queue(
|
self.send_data_to_socket_queue(
|
||||||
|
@ -3456,7 +3457,7 @@ class DATA:
|
||||||
"""
|
"""
|
||||||
if (
|
if (
|
||||||
ARQ.arq_session
|
ARQ.arq_session
|
||||||
and Modem.modem_state == "BUSY"
|
and self.states.is_modem_busy
|
||||||
and not self.arq_file_transfer
|
and not self.arq_file_transfer
|
||||||
):
|
):
|
||||||
if self.arq_session_last_received + self.arq_session_timeout > time.time():
|
if self.arq_session_last_received + self.arq_session_timeout > time.time():
|
||||||
|
@ -3549,7 +3550,7 @@ class DATA:
|
||||||
|
|
||||||
# send burst only if channel not busy - but without waiting
|
# send burst only if channel not busy - but without waiting
|
||||||
# otherwise burst will be dropped
|
# otherwise burst will be dropped
|
||||||
if not ModemParam.channel_busy and not Modem.transmitting:
|
if not self.states.channel_busy and not self.states.is_transmitting:
|
||||||
self.enqueue_frame_for_tx(
|
self.enqueue_frame_for_tx(
|
||||||
frame_to_tx=[fec_frame], c2_mode=codec2.FREEDV_MODE["sig0"].value
|
frame_to_tx=[fec_frame], c2_mode=codec2.FREEDV_MODE["sig0"].value
|
||||||
)
|
)
|
||||||
|
|
208
modem/modem.py
208
modem/modem.py
|
@ -20,7 +20,6 @@ import codec2
|
||||||
import itertools
|
import itertools
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import sounddevice as sd
|
import sounddevice as sd
|
||||||
from global_instances import HamlibParam, ModemParam, Modem
|
|
||||||
from static import FRAME_TYPE
|
from static import FRAME_TYPE
|
||||||
import structlog
|
import structlog
|
||||||
import tci
|
import tci
|
||||||
|
@ -34,8 +33,6 @@ TESTMODE = False
|
||||||
RXCHANNEL = ""
|
RXCHANNEL = ""
|
||||||
TXCHANNEL = ""
|
TXCHANNEL = ""
|
||||||
|
|
||||||
Modem.transmitting = False
|
|
||||||
|
|
||||||
# Receive only specific modes to reduce CPU load
|
# Receive only specific modes to reduce CPU load
|
||||||
RECEIVE_SIG0 = True
|
RECEIVE_SIG0 = True
|
||||||
RECEIVE_SIG1 = False
|
RECEIVE_SIG1 = False
|
||||||
|
@ -77,12 +74,22 @@ class RF:
|
||||||
self.rx_audio_level = config['AUDIO']['rx_audio_level']
|
self.rx_audio_level = config['AUDIO']['rx_audio_level']
|
||||||
self.tx_audio_level = config['AUDIO']['tx_audio_level']
|
self.tx_audio_level = config['AUDIO']['tx_audio_level']
|
||||||
self.enable_audio_auto_tune = config['AUDIO']['enable_auto_tune']
|
self.enable_audio_auto_tune = config['AUDIO']['enable_auto_tune']
|
||||||
|
self.enable_fsk = config['MODEM']['enable_fsk']
|
||||||
self.enable_fft = config['MODEM']['enable_fft']
|
self.enable_fft = config['MODEM']['enable_fft']
|
||||||
self.enable_scatter = config['MODEM']['enable_scatter']
|
self.enable_scatter = config['MODEM']['enable_scatter']
|
||||||
self.tx_delay = config['MODEM']['tx_delay']
|
self.tx_delay = config['MODEM']['tx_delay']
|
||||||
self.tuning_range_fmin = config['MODEM']['tuning_range_fmin']
|
self.tuning_range_fmin = config['MODEM']['tuning_range_fmin']
|
||||||
self.tuning_range_fmax = config['MODEM']['tuning_range_fmax']
|
self.tuning_range_fmax = config['MODEM']['tuning_range_fmax']
|
||||||
|
|
||||||
|
self.radiocontrol = config['RADIO']['radiocontrol']
|
||||||
|
self.rigctld_ip = config['RADIO']['rigctld_ip']
|
||||||
|
self.rigctld_port = config['RADIO']['rigctld_port']
|
||||||
|
|
||||||
|
|
||||||
|
self.states.set("is_transmitting", False)
|
||||||
|
self.ptt_state = False
|
||||||
|
self.radio_alc = 0.0
|
||||||
|
|
||||||
self.tci_ip = config['TCI']['tci_ip']
|
self.tci_ip = config['TCI']['tci_ip']
|
||||||
self.tci_port = config['TCI']['tci_port']
|
self.tci_port = config['TCI']['tci_port']
|
||||||
|
|
||||||
|
@ -96,7 +103,7 @@ class RF:
|
||||||
|
|
||||||
self.AUDIO_FRAMES_PER_BUFFER_RX = 2400 * 2 # 8192
|
self.AUDIO_FRAMES_PER_BUFFER_RX = 2400 * 2 # 8192
|
||||||
# 8192 Let's do some tests with very small chunks for TX
|
# 8192 Let's do some tests with very small chunks for TX
|
||||||
self.AUDIO_FRAMES_PER_BUFFER_TX = 1200 if HamlibParam.hamlib_radiocontrol in ["tci"] else 2400 * 2
|
self.AUDIO_FRAMES_PER_BUFFER_TX = 1200 if self.radiocontrol in ["tci"] else 2400 * 2
|
||||||
# 8 * (self.AUDIO_SAMPLE_RATE_RX/self.MODEM_SAMPLE_RATE) == 48
|
# 8 * (self.AUDIO_SAMPLE_RATE_RX/self.MODEM_SAMPLE_RATE) == 48
|
||||||
self.AUDIO_CHANNELS = 1
|
self.AUDIO_CHANNELS = 1
|
||||||
self.MODE = 0
|
self.MODE = 0
|
||||||
|
@ -137,14 +144,14 @@ class RF:
|
||||||
threading.Event().wait(0.01)
|
threading.Event().wait(0.01)
|
||||||
|
|
||||||
if len(self.modoutqueue) > 0 and not self.mod_out_locked:
|
if len(self.modoutqueue) > 0 and not self.mod_out_locked:
|
||||||
HamlibParam.ptt_state = self.radio.set_ptt(True)
|
self.radio.set_ptt(True)
|
||||||
self.event_manager.send_ptt_change(True)
|
self.event_manager.send_ptt_change(True)
|
||||||
|
|
||||||
data_out = self.modoutqueue.popleft()
|
data_out = self.modoutqueue.popleft()
|
||||||
self.tci_module.push_audio(data_out)
|
self.tci_module.push_audio(data_out)
|
||||||
|
|
||||||
def start_modem(self):
|
def start_modem(self):
|
||||||
if not TESTMODE and HamlibParam.hamlib_radiocontrol not in ["tci"]:
|
if not TESTMODE and self.radiocontrol not in ["tci"]:
|
||||||
result = self.init_audio()
|
result = self.init_audio()
|
||||||
|
|
||||||
elif not TESTMODE:
|
elif not TESTMODE:
|
||||||
|
@ -304,8 +311,8 @@ class RF:
|
||||||
(self.dat0_datac1_buffer, RECEIVE_DATAC1),
|
(self.dat0_datac1_buffer, RECEIVE_DATAC1),
|
||||||
(self.dat0_datac3_buffer, RECEIVE_DATAC3),
|
(self.dat0_datac3_buffer, RECEIVE_DATAC3),
|
||||||
(self.dat0_datac4_buffer, RECEIVE_DATAC4),
|
(self.dat0_datac4_buffer, RECEIVE_DATAC4),
|
||||||
(self.fsk_ldpc_buffer_0, Modem.enable_fsk),
|
(self.fsk_ldpc_buffer_0, self.enable_fsk),
|
||||||
(self.fsk_ldpc_buffer_1, Modem.enable_fsk),
|
(self.fsk_ldpc_buffer_1, self.enable_fsk),
|
||||||
]:
|
]:
|
||||||
if (
|
if (
|
||||||
not (data_buffer.nbuffer + length_x) > data_buffer.size
|
not (data_buffer.nbuffer + length_x) > data_buffer.size
|
||||||
|
@ -338,8 +345,8 @@ class RF:
|
||||||
(self.dat0_datac1_buffer, RECEIVE_DATAC1),
|
(self.dat0_datac1_buffer, RECEIVE_DATAC1),
|
||||||
(self.dat0_datac3_buffer, RECEIVE_DATAC3),
|
(self.dat0_datac3_buffer, RECEIVE_DATAC3),
|
||||||
(self.dat0_datac4_buffer, RECEIVE_DATAC4),
|
(self.dat0_datac4_buffer, RECEIVE_DATAC4),
|
||||||
(self.fsk_ldpc_buffer_0, Modem.enable_fsk),
|
(self.fsk_ldpc_buffer_0, self.enable_fsk),
|
||||||
(self.fsk_ldpc_buffer_1, Modem.enable_fsk),
|
(self.fsk_ldpc_buffer_1, self.enable_fsk),
|
||||||
]:
|
]:
|
||||||
if (
|
if (
|
||||||
not (data_buffer.nbuffer + length_x) > data_buffer.size
|
not (data_buffer.nbuffer + length_x) > data_buffer.size
|
||||||
|
@ -388,7 +395,7 @@ class RF:
|
||||||
|
|
||||||
# Avoid decoding when transmitting to reduce CPU
|
# Avoid decoding when transmitting to reduce CPU
|
||||||
# TODO Overriding this for testing purposes
|
# TODO Overriding this for testing purposes
|
||||||
# if not Modem.transmitting:
|
# if not self.states.is_transmitting:
|
||||||
length_x = len(x)
|
length_x = len(x)
|
||||||
# Avoid buffer overflow by filling only if buffer for
|
# Avoid buffer overflow by filling only if buffer for
|
||||||
# selected datachannel mode is not full
|
# selected datachannel mode is not full
|
||||||
|
@ -398,26 +405,25 @@ class RF:
|
||||||
(self.dat0_datac1_buffer, RECEIVE_DATAC1, 2),
|
(self.dat0_datac1_buffer, RECEIVE_DATAC1, 2),
|
||||||
(self.dat0_datac3_buffer, RECEIVE_DATAC3, 3),
|
(self.dat0_datac3_buffer, RECEIVE_DATAC3, 3),
|
||||||
(self.dat0_datac4_buffer, RECEIVE_DATAC4, 4),
|
(self.dat0_datac4_buffer, RECEIVE_DATAC4, 4),
|
||||||
(self.fsk_ldpc_buffer_0, Modem.enable_fsk, 5),
|
(self.fsk_ldpc_buffer_0, self.enable_fsk, 5),
|
||||||
(self.fsk_ldpc_buffer_1, Modem.enable_fsk, 6),
|
(self.fsk_ldpc_buffer_1, self.enable_fsk, 6),
|
||||||
]:
|
]:
|
||||||
if (audiobuffer.nbuffer + length_x) > audiobuffer.size:
|
if (audiobuffer.nbuffer + length_x) > audiobuffer.size:
|
||||||
self.buffer_overflow_counter[index] += 1
|
self.buffer_overflow_counter[index] += 1
|
||||||
self.event_manager.send_buffer_overflow(self.buffer_overflow_counter)
|
self.event_manager.send_buffer_overflow(self.buffer_overflow_counter)
|
||||||
elif receive:
|
elif receive:
|
||||||
audiobuffer.push(x)
|
audiobuffer.push(x)
|
||||||
# end of "not Modem.transmitting" if block
|
# end of "not self.states.is_transmitting" if block
|
||||||
|
|
||||||
if not self.modoutqueue or self.mod_out_locked:
|
if not self.modoutqueue or self.mod_out_locked:
|
||||||
data_out48k = np.zeros(frames, dtype=np.int16)
|
data_out48k = np.zeros(frames, dtype=np.int16)
|
||||||
if self.enable_fft:
|
if self.enable_fft:
|
||||||
self.calculate_fft(x)
|
self.calculate_fft(x)
|
||||||
else:
|
else:
|
||||||
if not HamlibParam.ptt_state:
|
# TODO Moved to this place for testing
|
||||||
# TODO Moved to this place for testing
|
# Maybe we can avoid moments of silence before transmitting
|
||||||
# Maybe we can avoid moments of silence before transmitting
|
self.radio.set_ptt(True)
|
||||||
HamlibParam.ptt_state = self.radio.set_ptt(True)
|
self.event_manager.send_ptt_change(True)
|
||||||
self.event_manager.send_ptt_change(True)
|
|
||||||
|
|
||||||
data_out48k = self.modoutqueue.popleft()
|
data_out48k = self.modoutqueue.popleft()
|
||||||
if self.enable_fft:
|
if self.enable_fft:
|
||||||
|
@ -464,14 +470,14 @@ class RF:
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
Modem.transmitting = True
|
self.states.set("is_transmitting", True)
|
||||||
# if we're transmitting FreeDATA signals, reset channel busy state
|
# if we're transmitting FreeDATA signals, reset channel busy state
|
||||||
self.states.set("channel_busy", False)
|
self.states.set("channel_busy", False)
|
||||||
|
|
||||||
start_of_transmission = time.time()
|
start_of_transmission = time.time()
|
||||||
# TODO Moved ptt toggle some steps before audio is ready for testing
|
# TODO Moved ptt toggle some steps before audio is ready for testing
|
||||||
# Toggle ptt early to save some time and send ptt state via socket
|
# Toggle ptt early to save some time and send ptt state via socket
|
||||||
# HamlibParam.ptt_state = self.radio.set_ptt(True)
|
# self.radio.set_ptt(True)
|
||||||
# jsondata = {"ptt": "True"}
|
# jsondata = {"ptt": "True"}
|
||||||
# data_out = json.dumps(jsondata)
|
# data_out = json.dumps(jsondata)
|
||||||
# sock.SOCKET_QUEUE.put(data_out)
|
# sock.SOCKET_QUEUE.put(data_out)
|
||||||
|
@ -573,7 +579,7 @@ class RF:
|
||||||
self.audio_auto_tune()
|
self.audio_auto_tune()
|
||||||
x = set_audio_volume(x, self.tx_audio_level)
|
x = set_audio_volume(x, self.tx_audio_level)
|
||||||
|
|
||||||
if not HamlibParam.hamlib_radiocontrol in ["tci"]:
|
if not self.radiocontrol in ["tci"]:
|
||||||
txbuffer_out = self.resampler.resample8_to_48(x)
|
txbuffer_out = self.resampler.resample8_to_48(x)
|
||||||
else:
|
else:
|
||||||
txbuffer_out = x
|
txbuffer_out = x
|
||||||
|
@ -592,7 +598,7 @@ class RF:
|
||||||
self.mod_out_locked = False
|
self.mod_out_locked = False
|
||||||
|
|
||||||
# we need to wait manually for tci processing
|
# we need to wait manually for tci processing
|
||||||
if HamlibParam.hamlib_radiocontrol in ["tci"]:
|
if self.radiocontrol in ["tci"]:
|
||||||
duration = len(txbuffer_out) / 8000
|
duration = len(txbuffer_out) / 8000
|
||||||
timestamp_to_sleep = time.time() + duration
|
timestamp_to_sleep = time.time() + duration
|
||||||
self.log.debug("[MDM] TCI calculated duration", duration=duration)
|
self.log.debug("[MDM] TCI calculated duration", duration=duration)
|
||||||
|
@ -605,7 +611,7 @@ class RF:
|
||||||
tci_timeout_reached = True
|
tci_timeout_reached = True
|
||||||
|
|
||||||
while self.modoutqueue or not tci_timeout_reached:
|
while self.modoutqueue or not tci_timeout_reached:
|
||||||
if HamlibParam.hamlib_radiocontrol in ["tci"]:
|
if self.radiocontrol in ["tci"]:
|
||||||
if time.time() < timestamp_to_sleep:
|
if time.time() < timestamp_to_sleep:
|
||||||
tci_timeout_reached = False
|
tci_timeout_reached = False
|
||||||
else:
|
else:
|
||||||
|
@ -614,7 +620,7 @@ class RF:
|
||||||
# if we're transmitting FreeDATA signals, reset channel busy state
|
# if we're transmitting FreeDATA signals, reset channel busy state
|
||||||
self.states.set("channel_busy", False)
|
self.states.set("channel_busy", False)
|
||||||
|
|
||||||
HamlibParam.ptt_state = self.radio.set_ptt(False)
|
self.radio.set_ptt(False)
|
||||||
|
|
||||||
# Push ptt state to socket stream
|
# Push ptt state to socket stream
|
||||||
self.event_manager.send_ptt_change(False)
|
self.event_manager.send_ptt_change(False)
|
||||||
|
@ -623,7 +629,7 @@ class RF:
|
||||||
self.mod_out_locked = True
|
self.mod_out_locked = True
|
||||||
|
|
||||||
self.modem_transmit_queue.task_done()
|
self.modem_transmit_queue.task_done()
|
||||||
Modem.transmitting = False
|
self.states.set("is_transmitting", False)
|
||||||
|
|
||||||
end_of_transmission = time.time()
|
end_of_transmission = time.time()
|
||||||
transmission_time = end_of_transmission - start_of_transmission
|
transmission_time = end_of_transmission - start_of_transmission
|
||||||
|
@ -632,34 +638,34 @@ class RF:
|
||||||
def audio_auto_tune(self):
|
def audio_auto_tune(self):
|
||||||
# enable / disable AUDIO TUNE Feature / ALC correction
|
# enable / disable AUDIO TUNE Feature / ALC correction
|
||||||
if self.enable_audio_auto_tune:
|
if self.enable_audio_auto_tune:
|
||||||
if HamlibParam.alc == 0.0:
|
if self.radio_alc == 0.0:
|
||||||
self.tx_audio_level = self.tx_audio_level + 20
|
self.tx_audio_level = self.tx_audio_level + 20
|
||||||
elif 0.0 < HamlibParam.alc <= 0.1:
|
elif 0.0 < self.radio_alc <= 0.1:
|
||||||
print("0.0 < HamlibParam.alc <= 0.1")
|
print("0.0 < self.radio_alc <= 0.1")
|
||||||
self.tx_audio_level = self.tx_audio_level + 2
|
self.tx_audio_level = self.tx_audio_level + 2
|
||||||
self.log.debug("[MDM] AUDIO TUNE", audio_level=str(self.tx_audio_level),
|
self.log.debug("[MDM] AUDIO TUNE", audio_level=str(self.tx_audio_level),
|
||||||
alc_level=str(HamlibParam.alc))
|
alc_level=str(self.radio_alc))
|
||||||
elif 0.1 < HamlibParam.alc < 0.2:
|
elif 0.1 < self.radio_alc < 0.2:
|
||||||
print("0.1 < HamlibParam.alc < 0.2")
|
print("0.1 < self.radio_alc < 0.2")
|
||||||
self.tx_audio_level = self.tx_audio_level
|
self.tx_audio_level = self.tx_audio_level
|
||||||
self.log.debug("[MDM] AUDIO TUNE", audio_level=str(self.tx_audio_level),
|
self.log.debug("[MDM] AUDIO TUNE", audio_level=str(self.tx_audio_level),
|
||||||
alc_level=str(HamlibParam.alc))
|
alc_level=str(self.radio_alc))
|
||||||
elif 0.2 < HamlibParam.alc < 0.99:
|
elif 0.2 < self.radio_alc < 0.99:
|
||||||
print("0.2 < HamlibParam.alc < 0.99")
|
print("0.2 < self.radio_alc < 0.99")
|
||||||
self.tx_audio_level = self.tx_audio_level - 20
|
self.tx_audio_level = self.tx_audio_level - 20
|
||||||
self.log.debug("[MDM] AUDIO TUNE", audio_level=str(self.tx_audio_level),
|
self.log.debug("[MDM] AUDIO TUNE", audio_level=str(self.tx_audio_level),
|
||||||
alc_level=str(HamlibParam.alc))
|
alc_level=str(self.radio_alc))
|
||||||
elif 1.0 >= HamlibParam.alc:
|
elif 1.0 >= self.radio_alc:
|
||||||
print("1.0 >= HamlibParam.alc")
|
print("1.0 >= self.radio_alc")
|
||||||
self.tx_audio_level = self.tx_audio_level - 40
|
self.tx_audio_level = self.tx_audio_level - 40
|
||||||
self.log.debug("[MDM] AUDIO TUNE", audio_level=str(self.tx_audio_level),
|
self.log.debug("[MDM] AUDIO TUNE", audio_level=str(self.tx_audio_level),
|
||||||
alc_level=str(HamlibParam.alc))
|
alc_level=str(self.radio_alc))
|
||||||
else:
|
else:
|
||||||
self.log.debug("[MDM] AUDIO TUNE", audio_level=str(self.tx_audio_level),
|
self.log.debug("[MDM] AUDIO TUNE", audio_level=str(self.tx_audio_level),
|
||||||
alc_level=str(HamlibParam.alc))
|
alc_level=str(self.radio_alc))
|
||||||
|
|
||||||
def transmit_morse(self, repeats, repeat_delay, frames):
|
def transmit_morse(self, repeats, repeat_delay, frames):
|
||||||
Modem.transmitting = True
|
self.states.set("is_transmitting", True)
|
||||||
# if we're transmitting FreeDATA signals, reset channel busy state
|
# if we're transmitting FreeDATA signals, reset channel busy state
|
||||||
self.states.set("channel_busy", False)
|
self.states.set("channel_busy", False)
|
||||||
self.log.debug(
|
self.log.debug(
|
||||||
|
@ -674,7 +680,7 @@ class RF:
|
||||||
self.mod_out_locked = False
|
self.mod_out_locked = False
|
||||||
|
|
||||||
# we need to wait manually for tci processing
|
# we need to wait manually for tci processing
|
||||||
if HamlibParam.hamlib_radiocontrol in ["tci"]:
|
if self.radiocontrol in ["tci"]:
|
||||||
duration = len(txbuffer_out) / 8000
|
duration = len(txbuffer_out) / 8000
|
||||||
timestamp_to_sleep = time.time() + duration
|
timestamp_to_sleep = time.time() + duration
|
||||||
self.log.debug("[MDM] TCI calculated duration", duration=duration)
|
self.log.debug("[MDM] TCI calculated duration", duration=duration)
|
||||||
|
@ -687,7 +693,7 @@ class RF:
|
||||||
tci_timeout_reached = True
|
tci_timeout_reached = True
|
||||||
|
|
||||||
while self.modoutqueue or not tci_timeout_reached:
|
while self.modoutqueue or not tci_timeout_reached:
|
||||||
if HamlibParam.hamlib_radiocontrol in ["tci"]:
|
if self.radiocontrol in ["tci"]:
|
||||||
if time.time() < timestamp_to_sleep:
|
if time.time() < timestamp_to_sleep:
|
||||||
tci_timeout_reached = False
|
tci_timeout_reached = False
|
||||||
else:
|
else:
|
||||||
|
@ -697,7 +703,7 @@ class RF:
|
||||||
# if we're transmitting FreeDATA signals, reset channel busy state
|
# if we're transmitting FreeDATA signals, reset channel busy state
|
||||||
self.states.set("channel_busy", False)
|
self.states.set("channel_busy", False)
|
||||||
|
|
||||||
HamlibParam.ptt_state = self.radio.set_ptt(False)
|
self.radio.set_ptt(False)
|
||||||
|
|
||||||
# Push ptt state to socket stream
|
# Push ptt state to socket stream
|
||||||
self.event_manager.send_ptt_change(False)
|
self.event_manager.send_ptt_change(False)
|
||||||
|
@ -706,7 +712,7 @@ class RF:
|
||||||
self.mod_out_locked = True
|
self.mod_out_locked = True
|
||||||
|
|
||||||
self.modem_transmit_queue.task_done()
|
self.modem_transmit_queue.task_done()
|
||||||
Modem.transmitting = False
|
self.states.set("is_transmitting", False)
|
||||||
threading.Event().set()
|
threading.Event().set()
|
||||||
|
|
||||||
end_of_transmission = time.time()
|
end_of_transmission = time.time()
|
||||||
|
@ -732,7 +738,7 @@ class RF:
|
||||||
|
|
||||||
def init_decoders(self):
|
def init_decoders(self):
|
||||||
|
|
||||||
if Modem.enable_fsk:
|
if self.enable_fsk:
|
||||||
audio_thread_fsk_ldpc0 = threading.Thread(
|
audio_thread_fsk_ldpc0 = threading.Thread(
|
||||||
target=self.audio_fsk_ldpc_0, name="AUDIO_THREAD FSK LDPC0", daemon=True
|
target=self.audio_fsk_ldpc_0, name="AUDIO_THREAD FSK LDPC0", daemon=True
|
||||||
)
|
)
|
||||||
|
@ -849,43 +855,36 @@ class RF:
|
||||||
if nbytes == bytes_per_frame:
|
if nbytes == bytes_per_frame:
|
||||||
print(bytes(bytes_out))
|
print(bytes(bytes_out))
|
||||||
|
|
||||||
# process commands only if Modem.listen = True
|
# ignore data channel opener frames for avoiding toggle states
|
||||||
if Modem.listen:
|
# use case: opener already received, but ack got lost and we are receiving
|
||||||
|
# an opener again
|
||||||
# ignore data channel opener frames for avoiding toggle states
|
if mode_name in ["sig1-datac13"] and int.from_bytes(bytes(bytes_out[:1]), "big") in [
|
||||||
# use case: opener already received, but ack got lost and we are receiving
|
FRAME_TYPE.ARQ_SESSION_OPEN.value,
|
||||||
# an opener again
|
FRAME_TYPE.ARQ_DC_OPEN_W.value,
|
||||||
if mode_name in ["sig1-datac13"] and int.from_bytes(bytes(bytes_out[:1]), "big") in [
|
FRAME_TYPE.ARQ_DC_OPEN_ACK_W.value,
|
||||||
FRAME_TYPE.ARQ_SESSION_OPEN.value,
|
FRAME_TYPE.ARQ_DC_OPEN_N.value,
|
||||||
FRAME_TYPE.ARQ_DC_OPEN_W.value,
|
FRAME_TYPE.ARQ_DC_OPEN_ACK_N.value
|
||||||
FRAME_TYPE.ARQ_DC_OPEN_ACK_W.value,
|
]:
|
||||||
FRAME_TYPE.ARQ_DC_OPEN_N.value,
|
print("dropp")
|
||||||
FRAME_TYPE.ARQ_DC_OPEN_ACK_N.value
|
elif int.from_bytes(bytes(bytes_out[:1]), "big") in [
|
||||||
]:
|
FRAME_TYPE.MESH_BROADCAST.value,
|
||||||
print("dropp")
|
FRAME_TYPE.MESH_SIGNALLING_PING.value,
|
||||||
elif int.from_bytes(bytes(bytes_out[:1]), "big") in [
|
FRAME_TYPE.MESH_SIGNALLING_PING_ACK.value,
|
||||||
FRAME_TYPE.MESH_BROADCAST.value,
|
]:
|
||||||
FRAME_TYPE.MESH_SIGNALLING_PING.value,
|
self.log.debug(
|
||||||
FRAME_TYPE.MESH_SIGNALLING_PING_ACK.value,
|
"[MDM] [demod_audio] moving data to mesh dispatcher", nbytes=nbytes
|
||||||
]:
|
|
||||||
self.log.debug(
|
|
||||||
"[MDM] [demod_audio] moving data to mesh dispatcher", nbytes=nbytes
|
|
||||||
)
|
|
||||||
MESH_RECEIVED_QUEUE.put(bytes(bytes_out))
|
|
||||||
|
|
||||||
else:
|
|
||||||
self.log.debug(
|
|
||||||
"[MDM] [demod_audio] Pushing received data to received_queue", nbytes=nbytes
|
|
||||||
)
|
|
||||||
snr = self.calculate_snr(freedv)
|
|
||||||
self.modem_received_queue.put([bytes_out, freedv, bytes_per_frame, snr])
|
|
||||||
self.get_scatter(freedv)
|
|
||||||
state_buffer = []
|
|
||||||
else:
|
|
||||||
self.log.warning(
|
|
||||||
"[MDM] [demod_audio] received frame but ignored processing",
|
|
||||||
listen=Modem.listen
|
|
||||||
)
|
)
|
||||||
|
MESH_RECEIVED_QUEUE.put(bytes(bytes_out))
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.log.debug(
|
||||||
|
"[MDM] [demod_audio] Pushing received data to received_queue", nbytes=nbytes
|
||||||
|
)
|
||||||
|
snr = self.calculate_snr(freedv)
|
||||||
|
self.modem_received_queue.put([bytes_out, freedv, bytes_per_frame, snr])
|
||||||
|
self.get_scatter(freedv)
|
||||||
|
state_buffer = []
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.log.warning("[MDM] [demod_audio] Stream not active anymore", e=e)
|
self.log.warning("[MDM] [demod_audio] Stream not active anymore", e=e)
|
||||||
|
|
||||||
|
@ -1167,7 +1166,6 @@ class RF:
|
||||||
def get_frequency_offset(self, freedv: ctypes.c_void_p) -> float:
|
def get_frequency_offset(self, freedv: ctypes.c_void_p) -> float:
|
||||||
"""
|
"""
|
||||||
Ask codec2 for the calculated (audio) frequency offset of the received signal.
|
Ask codec2 for the calculated (audio) frequency offset of the received signal.
|
||||||
Side-effect: sets ModemParam.frequency_offset
|
|
||||||
|
|
||||||
:param freedv: codec2 instance to query
|
:param freedv: codec2 instance to query
|
||||||
:type freedv: ctypes.c_void_p
|
:type freedv: ctypes.c_void_p
|
||||||
|
@ -1177,7 +1175,6 @@ class RF:
|
||||||
modemStats = codec2.MODEMSTATS()
|
modemStats = codec2.MODEMSTATS()
|
||||||
codec2.api.freedv_get_modem_extended_stats(freedv, ctypes.byref(modemStats))
|
codec2.api.freedv_get_modem_extended_stats(freedv, ctypes.byref(modemStats))
|
||||||
offset = round(modemStats.foff) * (-1)
|
offset = round(modemStats.foff) * (-1)
|
||||||
ModemParam.frequency_offset = offset
|
|
||||||
return offset
|
return offset
|
||||||
|
|
||||||
def get_scatter(self, freedv: ctypes.c_void_p) -> None:
|
def get_scatter(self, freedv: ctypes.c_void_p) -> None:
|
||||||
|
@ -1225,7 +1222,6 @@ class RF:
|
||||||
"""
|
"""
|
||||||
Ask codec2 for data about the received signal and calculate
|
Ask codec2 for data about the received signal and calculate
|
||||||
the signal-to-noise ratio.
|
the signal-to-noise ratio.
|
||||||
Side effect: sets ModemParam.snr
|
|
||||||
|
|
||||||
:param freedv: codec2 instance to query
|
:param freedv: codec2 instance to query
|
||||||
:type freedv: ctypes.c_void_p
|
:type freedv: ctypes.c_void_p
|
||||||
|
@ -1244,30 +1240,28 @@ class RF:
|
||||||
|
|
||||||
snr = round(modem_stats_snr, 1)
|
snr = round(modem_stats_snr, 1)
|
||||||
self.log.info("[MDM] calculate_snr: ", snr=snr)
|
self.log.info("[MDM] calculate_snr: ", snr=snr)
|
||||||
ModemParam.snr = snr
|
# snr = np.clip(
|
||||||
# ModemParam.snr = np.clip(
|
|
||||||
# snr, -127, 127
|
# snr, -127, 127
|
||||||
# ) # limit to max value of -128/128 as a possible fix of #188
|
# ) # limit to max value of -128/128 as a possible fix of #188
|
||||||
return ModemParam.snr
|
return snr
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
self.log.error(f"[MDM] calculate_snr: Exception: {err}")
|
self.log.error(f"[MDM] calculate_snr: Exception: {err}")
|
||||||
ModemParam.snr = 0
|
return 0
|
||||||
return ModemParam.snr
|
|
||||||
|
|
||||||
def init_rig_control(self):
|
def init_rig_control(self):
|
||||||
# Check how we want to control the radio
|
# Check how we want to control the radio
|
||||||
if HamlibParam.hamlib_radiocontrol == "rigctld":
|
if self.radiocontrol == "rigctld":
|
||||||
import rigctld as rig
|
import rigctld as rig
|
||||||
elif HamlibParam.hamlib_radiocontrol == "tci":
|
elif self.radiocontrol == "tci":
|
||||||
self.radio = self.tci_module
|
self.radio = self.tci_module
|
||||||
else:
|
else:
|
||||||
import rigdummy as rig
|
import rigdummy as rig
|
||||||
|
|
||||||
if not HamlibParam.hamlib_radiocontrol in ["tci"]:
|
if not self.radiocontrol in ["tci"]:
|
||||||
self.radio = rig.radio()
|
self.radio = rig.radio()
|
||||||
self.radio.open_rig(
|
self.radio.open_rig(
|
||||||
rigctld_ip=HamlibParam.hamlib_rigctld_ip,
|
rigctld_ip=self.rigctld_ip,
|
||||||
rigctld_port=HamlibParam.hamlib_rigctld_port,
|
rigctld_port=self.rigctld_port,
|
||||||
)
|
)
|
||||||
hamlib_thread = threading.Thread(
|
hamlib_thread = threading.Thread(
|
||||||
target=self.update_rig_data, name="HAMLIB_THREAD", daemon=True
|
target=self.update_rig_data, name="HAMLIB_THREAD", daemon=True
|
||||||
|
@ -1296,31 +1290,26 @@ class RF:
|
||||||
def update_rig_data(self) -> None:
|
def update_rig_data(self) -> None:
|
||||||
"""
|
"""
|
||||||
Request information about the current state of the radio via hamlib
|
Request information about the current state of the radio via hamlib
|
||||||
Side effect: sets
|
|
||||||
- HamlibParam.hamlib_frequency
|
|
||||||
- HamlibParam.hamlib_mode
|
|
||||||
- HamlibParam.hamlib_bandwidth
|
|
||||||
"""
|
"""
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
# this looks weird, but is necessary for avoiding rigctld packet colission sock
|
# this looks weird, but is necessary for avoiding rigctld packet colission sock
|
||||||
threading.Event().wait(0.25)
|
threading.Event().wait(0.25)
|
||||||
HamlibParam.hamlib_frequency = self.radio.get_frequency()
|
self.states.set("radio_frequency", self.radio.get_frequency())
|
||||||
threading.Event().wait(0.1)
|
threading.Event().wait(0.1)
|
||||||
HamlibParam.hamlib_mode = self.radio.get_mode()
|
self.states.set("radio_mode", self.radio.get_mode())
|
||||||
threading.Event().wait(0.1)
|
threading.Event().wait(0.1)
|
||||||
HamlibParam.hamlib_bandwidth = self.radio.get_bandwidth()
|
self.states.set("radio_bandwidth", self.radio.get_bandwidth())
|
||||||
threading.Event().wait(0.1)
|
threading.Event().wait(0.1)
|
||||||
HamlibParam.hamlib_status = self.radio.get_status()
|
self.states.set("radio_status", self.radio.get_status())
|
||||||
threading.Event().wait(0.1)
|
threading.Event().wait(0.1)
|
||||||
if Modem.transmitting:
|
if self.states.is_transmitting:
|
||||||
HamlibParam.alc = self.radio.get_alc()
|
self.radio_alc = self.radio.get_alc()
|
||||||
threading.Event().wait(0.1)
|
threading.Event().wait(0.1)
|
||||||
# HamlibParam.hamlib_rf = self.radio.get_level()
|
# HamlibParam.hamlib_rf = self.radio.get_level()
|
||||||
# threading.Event().wait(0.1)
|
# threading.Event().wait(0.1)
|
||||||
HamlibParam.hamlib_strength = self.radio.get_strength()
|
self.states.set("radio_rf_power", self.radio.get_strength())
|
||||||
|
|
||||||
# print(f"ALC: {HamlibParam.alc}, RF: {HamlibParam.hamlib_rf}, STRENGTH: {HamlibParam.hamlib_strength}")
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.log.warning(
|
self.log.warning(
|
||||||
"[MDM] error getting radio data",
|
"[MDM] error getting radio data",
|
||||||
|
@ -1355,7 +1344,7 @@ class RF:
|
||||||
# Therefore we are setting it to 100 so it will be highlighted
|
# Therefore we are setting it to 100 so it will be highlighted
|
||||||
# Have to do this when we are not transmitting so our
|
# Have to do this when we are not transmitting so our
|
||||||
# own sending data will not affect this too much
|
# own sending data will not affect this too much
|
||||||
if not Modem.transmitting:
|
if not self.states.is_transmitting:
|
||||||
dfft[dfft > avg + 15] = 100
|
dfft[dfft > avg + 15] = 100
|
||||||
|
|
||||||
# Calculate audio dbfs
|
# Calculate audio dbfs
|
||||||
|
@ -1411,12 +1400,11 @@ class RF:
|
||||||
range_start = range[0]
|
range_start = range[0]
|
||||||
range_end = range[1]
|
range_end = range[1]
|
||||||
# define the area, we are detecting busy state
|
# define the area, we are detecting busy state
|
||||||
#dfft = dfft[120:176] if Modem.low_bandwidth_mode else dfft[65:231]
|
|
||||||
slotdfft = dfft[range_start:range_end]
|
slotdfft = dfft[range_start:range_end]
|
||||||
# Check for signals higher than average by checking for "100"
|
# Check for signals higher than average by checking for "100"
|
||||||
# If we have a signal, increment our channel_busy delay counter
|
# If we have a signal, increment our channel_busy delay counter
|
||||||
# so we have a smoother state toggle
|
# so we have a smoother state toggle
|
||||||
if np.sum(slotdfft[slotdfft > avg + 15]) >= 200 and not Modem.transmitting:
|
if np.sum(slotdfft[slotdfft > avg + 15]) >= 200 and not self.states.is_transmitting:
|
||||||
addDelay=True
|
addDelay=True
|
||||||
self.states.channel_busy_slot[slot] = True
|
self.states.channel_busy_slot[slot] = True
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -2,20 +2,36 @@ import time
|
||||||
import ujson as json
|
import ujson as json
|
||||||
class STATES:
|
class STATES:
|
||||||
def __init__(self, statequeue):
|
def __init__(self, statequeue):
|
||||||
|
|
||||||
|
# state related settings
|
||||||
self.statequeue = statequeue
|
self.statequeue = statequeue
|
||||||
self.newstate = None
|
self.newstate = None
|
||||||
|
self.last = time.time()
|
||||||
|
|
||||||
|
# modem related states
|
||||||
|
# not every state is needed to publish, yet
|
||||||
|
# TODO can we reduce them?
|
||||||
self.channel_busy = False
|
self.channel_busy = False
|
||||||
self.channel_busy_slot = [False, False, False, False, False]
|
self.channel_busy_slot = [False, False, False, False, False]
|
||||||
self.is_codec2_traffic = False
|
self.is_codec2_traffic = False
|
||||||
self.is_modem_running = False
|
self.is_modem_running = False
|
||||||
|
self.is_modem_busy = False
|
||||||
self.is_beacon_running = False
|
self.is_beacon_running = False
|
||||||
self.is_arq_state = False
|
self.is_arq_state = False
|
||||||
self.is_arq_session = False
|
self.is_arq_session = False
|
||||||
|
self.is_transmitting = False
|
||||||
self.arq_session_state = 'disconnected'
|
self.arq_session_state = 'disconnected'
|
||||||
self.audio_dbfs = 0
|
self.audio_dbfs = 0
|
||||||
|
self.dxcallsign: bytes = b"ZZ9YY-0"
|
||||||
|
self.dxgrid: bytes = b"------"
|
||||||
|
|
||||||
|
self.radio_frequency = 0
|
||||||
|
self.radio_mode = None
|
||||||
|
self.radio_bandwidth = 0
|
||||||
|
self.radio_rf_power = 0
|
||||||
|
|
||||||
def sendStateUpdate (self):
|
def sendStateUpdate (self):
|
||||||
self.statequeue.put(self.newstate)
|
self.statequeue.put(self.newstate)
|
||||||
|
|
||||||
|
|
||||||
def set(self, key, value):
|
def set(self, key, value):
|
||||||
|
|
Loading…
Reference in a new issue