first working data channel

This commit is contained in:
DJ2LS 2021-02-28 15:24:14 +01:00 committed by GitHub
parent c9c869e802
commit 9a263757b1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 298 additions and 147 deletions

View file

@ -16,6 +16,8 @@ import modem
modem = modem.RF() modem = modem.RF()
import helpers import helpers
import asyncio
############################################################################################################# #############################################################################################################
# ARQ DATA HANDLER # ARQ DATA HANDLER
@ -42,7 +44,7 @@ def data_received(data_in):
arq_percent_burst = int((static.ARQ_N_FRAME / static.ARQ_N_RX_FRAMES_PER_BURSTS)*100) arq_percent_burst = int((static.ARQ_N_FRAME / static.ARQ_N_RX_FRAMES_PER_BURSTS)*100)
arq_percent_frame = int(((static.ARQ_RX_N_CURRENT_ARQ_FRAME)/static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME)*100) arq_percent_frame = int(((static.ARQ_RX_N_CURRENT_ARQ_FRAME)/static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME)*100)
logging.log(24, "ARQ | RX | F:[" + str(static.ARQ_N_FRAME) + "/" + str(static.ARQ_N_RX_FRAMES_PER_BURSTS) + "] [" + str(arq_percent_burst).zfill(3) + "%] --- T:[" + str(static.ARQ_RX_N_CURRENT_ARQ_FRAME) + "/" + str(static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME) + "] [" + str(arq_percent_frame).zfill(3) + "%]" ) logging.log(24, "ARQ | RX | " + str(static.ARQ_DATA_CHANNEL_MODE) + " | F:[" + str(static.ARQ_N_FRAME) + "/" + str(static.ARQ_N_RX_FRAMES_PER_BURSTS) + "] [" + str(arq_percent_burst).zfill(3) + "%] --- T:[" + str(static.ARQ_RX_N_CURRENT_ARQ_FRAME) + "/" + str(static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME) + "] [" + str(arq_percent_frame).zfill(3) + "%]" )
@ -190,6 +192,7 @@ def data_received(data_in):
static.ARQ_FRAME_EOF_RECEIVED = False static.ARQ_FRAME_EOF_RECEIVED = False
static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME = 0 static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME = 0
static.TNC_STATE = 'IDLE' static.TNC_STATE = 'IDLE'
static.ARQ_SEND_KEEP_ALIVE = True
#print("----------------------------------------------------------------") #print("----------------------------------------------------------------")
#print(static.RX_BUFFER[-1]) #print(static.RX_BUFFER[-1])
@ -198,14 +201,33 @@ def data_received(data_in):
else: else:
logging.error("ARQ | RX | DATA FRAME NOT SUCESSFULLY RECEIVED!") logging.error("ARQ | RX | DATA FRAME NOT SUCESSFULLY RECEIVED!")
static.ARQ_STATE = 'IDLE' static.ARQ_STATE = 'IDLE'
static.ARQ_SEND_KEEP_ALIVE = True
def transmit(data_out): def transmit(data_out):
if static.ARQ_DATA_CHANNEL_MODE == 10:
payload_per_frame = 512-2
elif static.ARQ_DATA_CHANNEL_MODE == 11:
payload_per_frame = 256-2
elif static.ARQ_DATA_CHANNEL_MODE == 12:
payload_per_frame = 128-2
elif static.ARQ_DATA_CHANNEL_MODE == 14:
payload_per_frame = 16-2
else:
payload_per_frame = 16-2
static.ARQ_PAYLOAD_PER_FRAME = payload_per_frame - 8
print("static.ARQ_DATA_PAYLOAD_PER_FRAME " + str(static.FREEDV_DATA_PAYLOAD_PER_FRAME))
print("static.ARQ_PAYLOAD_PER_FRAME " + str(static.ARQ_PAYLOAD_PER_FRAME))
static.ARQ_PAYLOAD_PER_FRAME = static.FREEDV_DATA_PAYLOAD_PER_FRAME - 8
frame_header_length = 6 #4 frame_header_length = 6 #4
n_arq_frames_per_data_frame = (len(data_out)+frame_header_length) // static.ARQ_PAYLOAD_PER_FRAME + ((len(data_out)+frame_header_length) % static.ARQ_PAYLOAD_PER_FRAME > 0) n_arq_frames_per_data_frame = (len(data_out)+frame_header_length) // static.ARQ_PAYLOAD_PER_FRAME + ((len(data_out)+frame_header_length) % static.ARQ_PAYLOAD_PER_FRAME > 0)
@ -250,7 +272,7 @@ def transmit(data_out):
for static.TX_N_RETRIES in range(static.TX_N_MAX_RETRIES): for static.TX_N_RETRIES in range(static.TX_N_MAX_RETRIES):
if static.ARQ_N_SENT_FRAMES + 1 <= static.TX_BUFFER_SIZE: if static.ARQ_N_SENT_FRAMES + 1 <= static.TX_BUFFER_SIZE:
logging.log(24, "ARQ | TX | F:[" + str(static.ARQ_N_SENT_FRAMES+1) + "-" + str(static.ARQ_N_SENT_FRAMES + static.ARQ_TX_N_FRAMES_PER_BURST) + "] | T:[" + str(static.ARQ_N_SENT_FRAMES) + "/" + str(static.TX_BUFFER_SIZE) + "] [" + str(int(static.ARQ_N_SENT_FRAMES/(static.TX_BUFFER_SIZE)*100)).zfill(3) + "%] | A:[" + str(static.TX_N_RETRIES+1) + "/" + str(static.TX_N_MAX_RETRIES) + "]") logging.log(24, "ARQ | TX | " + str(static.ARQ_DATA_CHANNEL_MODE) + " | F:[" + str(static.ARQ_N_SENT_FRAMES+1) + "-" + str(static.ARQ_N_SENT_FRAMES + static.ARQ_TX_N_FRAMES_PER_BURST) + "] | T:[" + str(static.ARQ_N_SENT_FRAMES) + "/" + str(static.TX_BUFFER_SIZE) + "] [" + str(int(static.ARQ_N_SENT_FRAMES/(static.TX_BUFFER_SIZE)*100)).zfill(3) + "%] | A:[" + str(static.TX_N_RETRIES+1) + "/" + str(static.TX_N_MAX_RETRIES) + "]")
# lets start a thread to transmit nonblocking # lets start a thread to transmit nonblocking
@ -447,94 +469,204 @@ def burst_rpt_received(data_in):
# ARQ CONNECT HANDLER # ARQ CONNECT HANDLER
############################################################################################################# #############################################################################################################
def arq_connect(callsign): def arq_connect():
static.ARQ_STATE = 'CONNECTING' static.ARQ_STATE = 'CONNECTING'
logging.info("CONNECTING ["+ str(static.MYCALLSIGN, 'utf-8') + "]-> <-["+ callsign + "]") logging.info("CONN ["+ str(static.MYCALLSIGN, 'utf-8') + "]-> <-["+ str(static.DXCALLSIGN, 'utf-8') + "]")
frame_type = bytes([220]) frame_type = bytes([220])
connection_frame = frame_type + static.MYCALLSIGN
connection_frame = bytearray(14)
connection_frame[:1] = frame_type
connection_frame[1:2] = static.DXCALLSIGN_CRC8
connection_frame[2:3] = static.MYCALLSIGN_CRC8
connection_frame[3:9] = static.MYCALLSIGN # we need the full CALLSIGN, if we are doing a connect without ping and cq
#connection_frame[12:13] = bytes([static.ARQ_DATA_CHANNEL_MODE])
#connection_frame[13:14] = bytes([static.ARQ_READY_FOR_DATA])
#print(connection_frame)
TRANSMIT_CONNECT_THREAD = threading.Thread(target=modem.transmit_signalling, args=[connection_frame], name="TRANSMIT_ARQ") TRANSMIT_CONNECT_THREAD = threading.Thread(target=modem.transmit_signalling, args=[connection_frame], name="TRANSMIT_ARQ")
TRANSMIT_CONNECT_THREAD.start() TRANSMIT_CONNECT_THREAD.start()
def arq_received_connect(data_in): def arq_received_connect(data_in):
static.ARQ_STATE = 'CONNECTING' static.ARQ_STATE = 'CONNECTING'
dxcallsign = data_in[1:6]
static.DXCALLSIGN = bytes(dxcallsign) static.DXCALLSIGN = bytes(data_in[3:9]).rstrip(b'\x00')
static.DXCALLSIGN_CRC8 = helpers.get_crc_8(static.DXCALLSIGN) static.DXCALLSIGN_CRC8 = helpers.get_crc_8(static.DXCALLSIGN)
logging.info("CONNECTING ["+ str(static.MYCALLSIGN, 'utf-8') + "]-> <-["+ str(static.DXCALLSIGN, 'utf-8') + "]") #static.FREEDV_DATA_MODE = int.from_bytes(bytes(data_in[12:13]), "big")
logging.info("CONN ["+ str(static.MYCALLSIGN, 'utf-8') + "]-> <-["+ str(static.DXCALLSIGN, 'utf-8') + "]")
frame_type = bytes([221]) frame_type = bytes([221])
connection_frame = frame_type + static.MYCALLSIGN connection_frame = bytearray(14)
connection_frame[:1] = frame_type
connection_frame[1:2] = static.DXCALLSIGN_CRC8
connection_frame[2:3] = static.MYCALLSIGN_CRC8
#connection_frame[12:13] = bytes([static.FREEDV_DATA_MODE])
#send ACK for connect
TRANSMIT_CONNECT_THREAD = threading.Thread(target=modem.transmit_signalling, args=[connection_frame], name="TRANSMIT_ARQ") TRANSMIT_CONNECT_THREAD = threading.Thread(target=modem.transmit_signalling, args=[connection_frame], name="TRANSMIT_ARQ")
TRANSMIT_CONNECT_THREAD.start() TRANSMIT_CONNECT_THREAD.start()
def arq_received_connect_keep_alive(data_in):
if static.ARQ_STATE == 'CONNECTED' or static.ARQ_STATE == 'CONNECTING':
static.ARQ_STATE = 'CONNECTED'
logging.info("CONNECTED ["+ str(static.MYCALLSIGN, 'utf-8') + "] >< ["+ str(static.DXCALLSIGN, 'utf-8') + "]")
frame_type = bytes([221])
connection_frame = frame_type + static.MYCALLSIGN
acktimer = threading.Timer(3.0, modem.transmit_signalling, args=[connection_frame])
def arq_received_connect_keep_alive(data_in):
if static.ARQ_SEND_KEEP_ALIVE == True and (static.ARQ_STATE == 'CONNECTING' or static.ARQ_STATE == 'CONNECTED'):
logging.info("CONN ["+ str(static.MYCALLSIGN, 'utf-8') + "] >|< ["+ str(static.DXCALLSIGN, 'utf-8') + "]")
static.ARQ_STATE = 'CONNECTED'
frame_type = bytes([221])
connection_frame = bytearray(14)
connection_frame[:1] = frame_type
connection_frame[1:2] = static.DXCALLSIGN_CRC8
connection_frame[2:3] = static.MYCALLSIGN_CRC8
connection_frame[12:13] = bytes([static.ARQ_DATA_CHANNEL_MODE])
connection_frame[13:14] = bytes([0])
#lets wait a second before sending
acktimer = threading.Timer(1.0, modem.transmit_signalling, args=[connection_frame])
acktimer.start() acktimer.start()
#TRANSMIT_CONNECT_THREAD = threading.Thread(target=modem.transmit_signalling, args=[connection_frame], name="TRANSMIT_ARQ") else:
#TRANSMIT_CONNECT_THREAD.start() print("keep alive = False")
#############################################################################################################
# ARQ DATA CHANNEL HANDLER
#############################################################################################################
async def arq_open_data_channel():
# we need to wait until the last keep alive has been sent.
logging.info("OPEN DATA CHANNEL ["+ str(static.MYCALLSIGN, 'utf-8') + "] >> << ["+ str(static.DXCALLSIGN, 'utf-8') + "]")
static.ARQ_SEND_KEEP_ALIVE = False
static.ARQ_DATA_CHANNEL_MODE = 12
while static.CHANNEL_STATE == 'SENDING_SIGNALLING':
time.sleep(0.01)
print("wir warten 10 sekunden...")
await asyncio.sleep(10)
connection_frame = bytearray(14)
connection_frame[:1] = bytes([225])
connection_frame[1:2] = static.DXCALLSIGN_CRC8
connection_frame[2:3] = static.MYCALLSIGN_CRC8
connection_frame[12:13] = bytes([static.ARQ_DATA_CHANNEL_MODE])
connection_frame[13:14] = bytes([225])
TRANSMIT_CONNECT_THREAD = threading.Thread(target=modem.transmit_signalling, args=[connection_frame], name="TRANSMIT_ARQ")
TRANSMIT_CONNECT_THREAD.start()
while static.CHANNEL_STATE == 'SENDING_SIGNALLING':
time.sleep(0.01)
def arq_received_data_channel_opener(data_in):
logging.info("OPEN DATA CHANNEL ["+ str(static.MYCALLSIGN, 'utf-8') + "] >> << ["+ str(static.DXCALLSIGN, 'utf-8') + "]")
static.ARQ_SEND_KEEP_ALIVE = False
static.ARQ_DATA_CHANNEL_MODE = int.from_bytes(bytes(data_in[12:13]), "big")
#static.ARQ_READY_FOR_DATA = int.from_bytes(bytes(data_in[13:14]), "big")
connection_frame = bytearray(14)
connection_frame[:1] = bytes([226])
connection_frame[1:2] = static.DXCALLSIGN_CRC8
connection_frame[2:3] = static.MYCALLSIGN_CRC8
connection_frame[12:13] = bytes([static.ARQ_DATA_CHANNEL_MODE])
connection_frame[13:14] = bytes([226])
TRANSMIT_CONNECT_THREAD = threading.Thread(target=modem.transmit_signalling, args=[connection_frame], name="TRANSMIT_ARQ")
TRANSMIT_CONNECT_THREAD.start()
while static.CHANNEL_STATE == 'SENDING_SIGNALLING':
time.sleep(0.01)
print("waiting for data....")
static.CHANNEL_STATE = 'RECEIVING_DATA'
# einen timeout benötigen wir auch noch....
# und ab hier geht es dann in den "RECEIVING_DATA" mode....
def arq_received_channel_is_open(data_in):
static.ARQ_SEND_KEEP_ALIVE == False
if static.ARQ_DATA_CHANNEL_MODE == int.from_bytes(bytes(data_in[12:13]), "big"):
logging.info("OPEN DATA CHANNEL ["+ str(static.MYCALLSIGN, 'utf-8') + "] >>|<< ["+ str(static.DXCALLSIGN, 'utf-8') + "]")
time.sleep(1)
static.ARQ_READY_FOR_DATA = True
#static.CHANNEL_STATE = 'RECEIVING_DATA':
def arq_disconnect(): def arq_disconnect():
# we need to create a "force ignore all" so we don't receive frames any more... Then we don't need a timer
static.ARQ_STATE = 'DISCONNECTING' static.ARQ_STATE = 'DISCONNECTING'
logging.info("DISCONNECTING ["+ str(static.MYCALLSIGN, 'utf-8') + "] <--> ["+ str(static.DXCALLSIGN, 'utf-8') + "]") logging.info("DISC ["+ str(static.MYCALLSIGN, 'utf-8') + "] <--> ["+ str(static.DXCALLSIGN, 'utf-8') + "]")
frame_type = bytes([222]) frame_type = bytes([222])
disconnection_frame = frame_type + static.MYCALLSIGN disconnection_frame = frame_type + static.MYCALLSIGN
disconnect_timer = threading.Timer(5.0, helpers.arq_disconnect_timeout)
disconnect_timer.start()
TRANSMIT_DISCONNECT_THREAD = threading.Thread(target=modem.transmit_signalling, args=[disconnection_frame], name="TRANSMIT_ARQ") TRANSMIT_DISCONNECT_THREAD = threading.Thread(target=modem.transmit_signalling, args=[disconnection_frame], name="TRANSMIT_ARQ")
TRANSMIT_DISCONNECT_THREAD.start() TRANSMIT_DISCONNECT_THREAD.start()
while static.CHANNEL_STATE == 'SENDING_SIGNALLING' or static.ARQ_WAIT_FOR_DISCONNECT == False:
time.sleep(0.01)
logging.info("DISCONNECTED ["+ str(static.MYCALLSIGN, 'utf-8') + "] < > ["+ str(static.DXCALLSIGN, 'utf-8') + "]") logging.info("DISC ["+ str(static.MYCALLSIGN, 'utf-8') + "]< X >["+ str(static.DXCALLSIGN, 'utf-8') + "]")
static.ARQ_STATE = 'IDLE' static.ARQ_STATE = 'IDLE'
static.DXCALLSIGN = b'' static.DXCALLSIGN = b''
static.DXCALLSIGN_CRC8 = b'' static.DXCALLSIGN_CRC8 = b''
def arq_disconnect_received(data_in): def arq_disconnect_received(data_in):
static.ARQ_STATE = 'DISCONNECTED' static.ARQ_STATE = 'DISCONNECTED'
logging.info("DISCONNECTED ["+ str(static.MYCALLSIGN, 'utf-8') + "] < > ["+ str(static.DXCALLSIGN, 'utf-8') + "]") logging.info("DISC ["+ str(static.MYCALLSIGN, 'utf-8') + "] < > ["+ str(static.DXCALLSIGN, 'utf-8') + "]")
static.ARQ_STATE = 'DISCONNECTED' static.ARQ_STATE = 'DISCONNECTED'
static.TNC_STATE = 'IDLE' static.TNC_STATE = 'IDLE'
static.DXCALLSIGN = b'' static.DXCALLSIGN = b''
static.DXCALLSIGN_CRC8 = b'' static.DXCALLSIGN_CRC8 = b''
############################################################################################################# #############################################################################################################
# PING HANDLER # PING HANDLER
############################################################################################################# #############################################################################################################
def transmit_ping(callsign): def transmit_ping(callsign):
static.DXCALLSIGN = bytes(callsign, 'utf-8') static.DXCALLSIGN = bytes(callsign, 'utf-8')
logging.info("PING ["+ str(static.MYCALLSIGN, 'utf-8') + "] > ["+ callsign + "]") logging.info("PING ["+ str(static.MYCALLSIGN, 'utf-8') + "] >>> [" + str(static.DXCALLSIGN, 'utf-8') + "]")
frame_type = bytes([210]) frame_type = bytes([210])
ping_payload = b'PING' ping_payload = b'PING'
ping_frame = frame_type + ping_payload ping_frame = frame_type + ping_payload
TRANSMIT_PING_THREAD = threading.Thread(target=modem.transmit_signalling, args=[ping_frame], name="TRANSMIT_ARQ") TRANSMIT_PING_THREAD = threading.Thread(target=modem.transmit_signalling, args=[ping_frame], name="TRANSMIT_ARQ")
TRANSMIT_PING_THREAD.start() TRANSMIT_PING_THREAD.start()
# wait while sending....
while static.CHANNEL_STATE == 'SENDING_SIGNALLING':
time.sleep(0.01)
def received_ping(data_in): def received_ping(data_in):
logging.info("TX PING ACK")
logging.info("PING ["+ str(static.MYCALLSIGN, 'utf-8') + "] <<< ["+ str(static.DXCALLSIGN, 'utf-8') + "]")
frame_type = bytes([211]) frame_type = bytes([211])
ping_payload = b'PING_ACK' ping_payload = b'PING_ACK'
ping_frame = frame_type + static.MYCALLSIGN + ping_payload ping_frame = frame_type + static.MYCALLSIGN + ping_payload
TRANSMIT_PING_THREAD = threading.Thread(target=modem.transmit_signalling, args=[ping_frame], name="TRANSMIT_ARQ") TRANSMIT_PING_THREAD = threading.Thread(target=modem.transmit_signalling, args=[ping_frame], name="TRANSMIT_ARQ")
TRANSMIT_PING_THREAD.start() TRANSMIT_PING_THREAD.start()
# wait while sending....
while static.CHANNEL_STATE == 'SENDING_SIGNALLING':
time.sleep(0.01)
def received_ping_ack(data_in): def received_ping_ack(data_in):
dxcallsign = data_in[1:6] dxcallsign = data_in[1:6]
static.DXCALLSIGN = bytes(dxcallsign) static.DXCALLSIGN = bytes(dxcallsign)
static.DXCALLSIGN_CRC8 = helpers.get_crc_8(static.DXCALLSIGN) static.DXCALLSIGN_CRC8 = helpers.get_crc_8(static.DXCALLSIGN)
logging.info("PING ACK [" + str(static.DXCALLSIGN) + "]>[" + str(static.MYCALLSIGN) + "]") logging.info("PING [" + str(static.DXCALLSIGN, 'utf-8') + "] >|< [" + str(static.MYCALLSIGN, 'utf-8') + "]")
static.TNC_STATE = 'IDLE' static.TNC_STATE = 'IDLE'
############################################################################################################# #############################################################################################################
@ -544,7 +676,6 @@ def received_ping_ack(data_in):
def transmit_cq(): def transmit_cq():
logging.info("CQ CQ CQ") logging.info("CQ CQ CQ")
frame_type = bytes([200]) frame_type = bytes([200])
print(frame_type)
cq_frame = frame_type + static.MYCALLSIGN cq_frame = frame_type + static.MYCALLSIGN
modem.transmit_signalling(cq_frame) modem.transmit_signalling(cq_frame)

173
modem.py
View file

@ -24,11 +24,6 @@ import Hamlib
class RF(): class RF():
def __init__(self): def __init__(self):
@ -59,9 +54,17 @@ class RF():
output_device_index=static.AUDIO_OUTPUT_DEVICE, #static.AUDIO_OUTPUT_DEVICE output_device_index=static.AUDIO_OUTPUT_DEVICE, #static.AUDIO_OUTPUT_DEVICE
) )
#--------------------------------------------START DECODER THREAD #--------------------------------------------START DECODER THREAD
FREEDV_DECODER_THREAD = threading.Thread(target=self.receive, args=[static.FREEDV_DATA_MODE,static.FREEDV_SIGNALLING_MODE], name="FREEDV_DECODER_THREAD") FREEDV_DECODER_THREAD_10 = threading.Thread(target=self.receive, args=[10], name="FREEDV_DECODER_THREAD")
FREEDV_DECODER_THREAD.start() FREEDV_DECODER_THREAD_10.start()
FREEDV_DECODER_THREAD_11 = threading.Thread(target=self.receive, args=[11], name="FREEDV_DECODER_THREAD")
FREEDV_DECODER_THREAD_11.start()
FREEDV_DECODER_THREAD_12 = threading.Thread(target=self.receive, args=[12], name="FREEDV_DECODER_THREAD")
FREEDV_DECODER_THREAD_12.start()
FREEDV_DECODER_THREAD_14 = threading.Thread(target=self.receive, args=[static.FREEDV_SIGNALLING_MODE], name="FREEDV_DECODER_THREAD")
FREEDV_DECODER_THREAD_14.start()
#--------------------------------------------CONFIGURE HAMLIB #--------------------------------------------CONFIGURE HAMLIB
@ -248,29 +251,35 @@ class RF():
static.PTT_STATE = False static.PTT_STATE = False
self.my_rig.set_ptt(self.hamlib_ptt_type,0) self.my_rig.set_ptt(self.hamlib_ptt_type,0)
#-------------------------------------------------------------------------------------------------------- #--------------------------------------------------------------------------------------------------------
def receive(self,data_mode,signalling_mode):
def receive(self,mode):
force = True force = True
self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte) self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte)
freedv = self.c_lib.freedv_open(mode)
freedv_data = self.c_lib.freedv_open(data_mode) bytes_per_frame = int(self.c_lib.freedv_get_bits_per_modem_frame(freedv)/8)
freedv_signalling = self.c_lib.freedv_open(signalling_mode)
static.FREEDV_DATA_BYTES_PER_FRAME = int(self.c_lib.freedv_get_bits_per_modem_frame(freedv_data)/8) if mode == static.FREEDV_SIGNALLING_MODE:
static.FREEDV_DATA_PAYLOAD_PER_FRAME = static.FREEDV_DATA_BYTES_PER_FRAME -2 static.FREEDV_SIGNALLING_BYTES_PER_FRAME = bytes_per_frame
static.FREEDV_SIGNALLING_BYTES_PER_FRAME = int(self.c_lib.freedv_get_bits_per_modem_frame(freedv_signalling)/8) static.FREEDV_SIGNALLING_PAYLOAD_PER_FRAME = bytes_per_frame - 2
static.FREEDV_SIGNALLING_PAYLOAD_PER_FRAME = static.FREEDV_SIGNALLING_BYTES_PER_FRAME -2
data_bytes_out = (ctypes.c_ubyte * static.FREEDV_DATA_BYTES_PER_FRAME) self.c_lib.freedv_set_frames_per_burst(freedv, 1);
data_bytes_out = data_bytes_out() #get pointer to bytes_out
signalling_bytes_out = (ctypes.c_ubyte * static.FREEDV_SIGNALLING_BYTES_PER_FRAME) elif mode == static.ARQ_DATA_CHANNEL_MODE:
signalling_bytes_out = signalling_bytes_out() #get pointer to bytes_out static.FREEDV_DATA_BYTES_PER_FRAME = bytes_per_frame
static.FREEDV_DATA_PAYLOAD_PER_FRAME = bytes_per_frame - 2
self.c_lib.freedv_set_frames_per_burst(freedv_data, 0); self.c_lib.freedv_set_frames_per_burst(freedv, 0);
self.c_lib.freedv_set_frames_per_burst(freedv_signalling, 1); else:
pass
#vars()['food']
bytes_out = (ctypes.c_ubyte * bytes_per_frame) ################################################################## DATA BYTES PER FRAME SETZEN!
bytes_out = bytes_out() #get pointer to bytes_out
# with this we can interrupt receiving
while static.FREEDV_RECEIVE == True: while static.FREEDV_RECEIVE == True:
time.sleep(0.01) time.sleep(0.01)
@ -279,47 +288,53 @@ class RF():
stuck_in_sync_10_counter = 0 stuck_in_sync_10_counter = 0
# #
while static.CHANNEL_STATE == 'RECEIVING_DATA': while (static.CHANNEL_STATE == 'RECEIVING_DATA' and static.ARQ_DATA_CHANNEL_MODE == mode) or (static.CHANNEL_STATE == 'RECEIVING_SIGNALLING' and static.FREEDV_SIGNALLING_MODE == mode):
static.FREEDV_DATA_BYTES_PER_FRAME = bytes_per_frame
static.FREEDV_DATA_PAYLOAD_PER_FRAME = bytes_per_frame - 2
time.sleep(0.01) time.sleep(0.01)
nin = self.c_lib.freedv_nin(freedv)
nin = self.c_lib.freedv_nin(freedv_data)
#nin = int(nin*(static.AUDIO_SAMPLE_RATE_RX/static.MODEM_SAMPLE_RATE)) #nin = int(nin*(static.AUDIO_SAMPLE_RATE_RX/static.MODEM_SAMPLE_RATE))
data_in = self.stream_rx.read(nin, exception_on_overflow = False) data_in = self.stream_rx.read(nin, exception_on_overflow = False)
#print(audioop.rms(data_in, 2)) #print(audioop.rms(data_in, 2))
#self.c_lib.freedv_rawdatarx.argtype = [ctypes.POINTER(ctypes.c_ubyte), data_bytes_out, data_in] # check if really neccessary #self.c_lib.freedv_rawdatarx.argtype = [ctypes.POINTER(ctypes.c_ubyte), data_bytes_out, data_in] # check if really neccessary
nbytes = self.c_lib.freedv_rawdatarx(freedv_data, data_bytes_out, data_in) # demodulate audio nbytes = self.c_lib.freedv_rawdatarx(freedv, bytes_out, data_in) # demodulate audio
logging.debug(self.c_lib.freedv_get_rx_status(freedv_data)) #logging.debug(self.c_lib.freedv_get_rx_status(freedv))
#print("listening-" + str(mode) + "-" + str(self.c_lib.freedv_get_rx_status(freedv)))
#-------------STUCK IN SYNC DETECTOR #-------------STUCK IN SYNC DETECTOR
stuck_in_sync_counter += 1 stuck_in_sync_counter += 1
if self.c_lib.freedv_get_rx_status(freedv_data) == 10: if self.c_lib.freedv_get_rx_status(freedv) == 10:
stuck_in_sync_10_counter += 1 stuck_in_sync_10_counter += 1
if stuck_in_sync_counter == 33 and self.c_lib.freedv_get_rx_status(freedv_data) == 10: if stuck_in_sync_counter == 33 and self.c_lib.freedv_get_rx_status(freedv) == 10:
logging.critical("stuck in sync #1") logging.critical("stuck in sync #1")
self.c_lib.freedv_set_sync(freedv_data, 0) #FORCE UNSYNC self.c_lib.freedv_set_sync(freedv, 0) #FORCE UNSYNC
stuck_in_sync_counter = 0 stuck_in_sync_counter = 0
stuck_in_sync_10_counter = 0 stuck_in_sync_10_counter = 0
if stuck_in_sync_counter >= 66 and stuck_in_sync_10_counter >= 2: if stuck_in_sync_counter >= 66 and stuck_in_sync_10_counter >= 2:
logging.critical("stuck in sync #2") logging.critical("stuck in sync #2")
self.c_lib.freedv_set_sync(freedv_data, 0) #FORCE UNSYNC self.c_lib.freedv_set_sync(freedv, 0) #FORCE UNSYNC
stuck_in_sync_counter = 0 stuck_in_sync_counter = 0
stuck_in_sync_10_counter = 0 stuck_in_sync_10_counter = 0
#----------------------------------- #-----------------------------------
# get bit errors # get bit errors
Tbits = self.c_lib.freedv_get_total_bits(freedv_data) Tbits = self.c_lib.freedv_get_total_bits(freedv)
Terrs = self.c_lib.freedv_get_total_bit_errors(freedv_data) Terrs = self.c_lib.freedv_get_total_bit_errors(freedv)
if Tbits != 0: if Tbits != 0:
static.UNCODED_BER = Terrs/Tbits static.UNCODED_BER = Terrs/Tbits
if nbytes == static.FREEDV_DATA_BYTES_PER_FRAME: if nbytes == bytes_per_frame:###################################################################################################FREEDV_DATA_BYTES_PER_FRAME
rxstatus = self.c_lib.freedv_get_rx_status(freedv_data)
logging.debug("DATA-" + str(rxstatus))
rxstatus = self.c_lib.freedv_get_rx_status(freedv)
#logging.debug("DATA-" + str(rxstatus))
# counter reset for stuck in sync counter # counter reset for stuck in sync counter
stuck_in_sync_counter = 0 stuck_in_sync_counter = 0
@ -327,61 +342,28 @@ class RF():
# #
# CHECK IF FRAMETYPE IS BETWEEN 10 and 50 ------------------------ # CHECK IF FRAMETYPE IS BETWEEN 10 and 50 ------------------------
frametype = int.from_bytes(bytes(data_bytes_out[:1]), "big") frametype = int.from_bytes(bytes(bytes_out[:1]), "big")
frame = frametype - 10 frame = frametype - 10
n_frames_per_burst = int.from_bytes(bytes(data_bytes_out[1:2]), "big") n_frames_per_burst = int.from_bytes(bytes(bytes_out[1:2]), "big")
#self.c_lib.freedv_set_frames_per_burst(freedv_data, n_frames_per_burst); #self.c_lib.freedv_set_frames_per_burst(freedv_data, n_frames_per_burst);
if 50 >= frametype >= 10: if 50 >= frametype >= 10:
if frame != 3 or force == True: if frame != 3 or force == True:
data_handler.data_received(bytes(data_bytes_out[:-2])) #send payload data to arq checker without CRC16 data_handler.data_received(bytes(bytes_out[:-2])) #send payload data to arq checker without CRC16
#print("static.ARQ_RX_BURST_BUFFER.count(None) " + str(static.ARQ_RX_BURST_BUFFER.count(None))) #print("static.ARQ_RX_BURST_BUFFER.count(None) " + str(static.ARQ_RX_BURST_BUFFER.count(None)))
if static.ARQ_RX_BURST_BUFFER.count(None) <= 1: if static.ARQ_RX_BURST_BUFFER.count(None) <= 1:
logging.debug("FULL BURST BUFFER ---> UNSYNC") logging.debug("FULL BURST BUFFER ---> UNSYNC")
self.c_lib.freedv_set_sync(freedv_data, 0) self.c_lib.freedv_set_sync(freedv, 0)
else: else:
logging.critical("---------------------------SIMULATED MISSING FRAME") logging.critical("---------------------------SIMULATED MISSING FRAME")
force = True force = True
else:
logging.info("MODE: " + str(data_mode) + " DATA: " + str(bytes(data_bytes_out)))
# DO UNSYNC AFTER LAST BURST by checking the frame numbers agains the total frames per burst
if frame == n_frames_per_burst:
#reset bit error counters
self.c_lib.freedv_set_total_bit_errors(freedv_data,0)
self.c_lib.freedv_set_total_bits(freedv_data,0)
logging.debug("LAST FRAME ---> UNSYNC")
self.c_lib.freedv_set_sync(freedv_data, 0) #FORCE UNSYNC
#while static.ARQ_STATE == 'IDLE' or static.ARQ_STATE == 'RECEIVING_SIGNALLING':
while static.CHANNEL_STATE == 'RECEIVING_SIGNALLING':
time.sleep(0.01)
nin = self.c_lib.freedv_nin(freedv_signalling)
#nin = int(nin*(static.AUDIO_SAMPLE_RATE_RX/static.MODEM_SAMPLE_RATE))
data_in = self.stream_rx.read(nin, exception_on_overflow = False)
#self.c_lib.freedv_rawdatarx.argtype = [ctypes.POINTER(ctypes.c_ubyte), signalling_bytes_out, data_in] # check if really neccessary
nbytes = self.c_lib.freedv_rawdatarx(freedv_signalling, signalling_bytes_out, data_in) # demodulate audio
# CHECK IF FRAME CONTAINS ACK------------------------
if nbytes == static.FREEDV_SIGNALLING_BYTES_PER_FRAME:
#self.c_lib.freedv_set_sync(freedv_signalling, 0)
frametype = int.from_bytes(bytes(signalling_bytes_out[:1]), "big")
# BURST ACK # BURST ACK
if frametype == 60: elif frametype == 60:
logging.debug("ACK RECEIVED....") logging.debug("ACK RECEIVED....")
data_handler.burst_ack_received() data_handler.burst_ack_received()
@ -393,7 +375,7 @@ class RF():
# FRAME RPT # FRAME RPT
elif frametype == 62: elif frametype == 62:
logging.debug("REPEAT REQUEST RECEIVED....") logging.debug("REPEAT REQUEST RECEIVED....")
data_handler.burst_rpt_received(signalling_bytes_out[:-2]) data_handler.burst_rpt_received(bytes_out[:-2])
# CQ FRAME # CQ FRAME
elif frametype == 200: elif frametype == 200:
@ -402,42 +384,59 @@ class RF():
# PING FRAME # PING FRAME
elif frametype == 210: elif frametype == 210:
logging.debug("PING RECEIVED....") logging.debug("PING RECEIVED....")
data_handler.received_ping(signalling_bytes_out[:-2]) data_handler.received_ping(bytes_out[:-2])
# PING ACK # PING ACK
elif frametype == 211: elif frametype == 211:
logging.debug("PING ACK RECEIVED....") logging.debug("PING ACK RECEIVED....")
data_handler.received_ping_ack(signalling_bytes_out[:-2]) data_handler.received_ping_ack(bytes_out[:-2])
# ARQ CONNECT # ARQ CONNECT
elif frametype == 220: elif frametype == 220:
logging.debug("ARQ CONNECT RECEIVED....") logging.debug("ARQ CONNECT RECEIVED....")
data_handler.arq_received_connect(signalling_bytes_out[:-2]) data_handler.arq_received_connect(bytes_out[:-2])
# ARQ CONNECT ACK / KEEP ALIVE # ARQ CONNECT ACK / KEEP ALIVE
elif frametype == 221: elif frametype == 221:
logging.debug("ARQ CONNECT ACK RECEIVED / KEEP ALIVE....") logging.debug("ARQ CONNECT ACK RECEIVED / KEEP ALIVE....")
data_handler.arq_received_connect_keep_alive(signalling_bytes_out[:-2]) data_handler.arq_received_connect_keep_alive(bytes_out[:-2])
# ARQ CONNECT ACK / KEEP ALIVE # ARQ CONNECT ACK / KEEP ALIVE
elif frametype == 222: elif frametype == 222:
logging.debug("ARQ DISCONNECT RECEIVED") logging.debug("ARQ DISCONNECT RECEIVED")
data_handler.arq_disconnect_received(signalling_bytes_out[:-2]) data_handler.arq_disconnect_received(bytes_out[:-2])
# ARQ FILE TRANSFER RECEIVED!
elif frametype == 225:
logging.debug("ARQ arq_received_data_channel_opener RECEIVED")
data_handler.arq_received_data_channel_opener(bytes_out[:-2])
# ARQ CHANNEL IS OPENED
elif frametype == 226:
logging.debug("ARQ arq_received_channel_is_open RECEIVED")
data_handler.arq_received_channel_is_open(bytes_out[:-2])
# ARQ CONNECT ACK / KEEP ALIVE # ARQ CONNECT ACK / KEEP ALIVE
elif frametype == 230: elif frametype == 230:
logging.debug("BEACON RECEIVED") logging.debug("BEACON RECEIVED")
else: else:
logging.info("OTHER FRAME: " + str(signalling_bytes_out[:-2])) logging.info("OTHER FRAME: " + str(bytes_out[:-2]))
print(frametype) print(frametype)
# DO UNSYNC AFTER LAST BURST by checking the frame numbers agains the total frames per burst
if frame == n_frames_per_burst:
rxstatus = self.c_lib.freedv_get_rx_status(freedv_signalling) #reset bit error counters
logging.debug("ACK-" + str(rxstatus)) self.c_lib.freedv_set_total_bit_errors(freedv,0)
self.c_lib.freedv_set_total_bits(freedv,0)
logging.debug("LAST FRAME ---> UNSYNC")
self.c_lib.freedv_set_sync(freedv, 0) #FORCE UNSYNC
rxstatus = self.c_lib.freedv_get_rx_status(freedv)
#logging.info("DATA-" + str(rxstatus))
if rxstatus == 10: if rxstatus == 10:
#self.c_lib.freedv_set_sync(freedv_signalling, 0) #FORCE UNSYNC self.c_lib.freedv_set_sync(freedv, 0) #FORCE UNSYNC
print("SIGNALLING -SYNC 10- Trigger") print("SIGNALLING -SYNC 10- Trigger")
#if nbytes == static.FREEDV_SIGNALLING_BYTES_PER_FRAME or rxstatus == 10:
# self.c_lib.freedv_set_sync(freedv_signalling, 0) #FORCE UNSYNC

30
sock.py
View file

@ -16,6 +16,7 @@ import data_handler
import helpers import helpers
import fec import fec
import asyncio
class CMDTCPRequestHandler(socketserver.BaseRequestHandler): class CMDTCPRequestHandler(socketserver.BaseRequestHandler):
@ -60,14 +61,17 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler):
if data.startswith('ARQ:CONNECT:'): if data.startswith('ARQ:CONNECT:'):
arqconnectcommand = data.split('ARQ:CONNECT:') arqconnectcommand = data.split('ARQ:CONNECT:')
dxcallsign = arqconnectcommand[1] dxcallsign = arqconnectcommand[1]
static.DXCALLSIGN = bytes(dxcallsign, 'utf-8')
static.DXCALLSIGN_CRC8 = helpers.get_crc_8(static.DXCALLSIGN)
if static.ARQ_STATE == 'CONNECTED': if static.ARQ_STATE == 'CONNECTED':
# here we should disconnect # here we could disconnect
pass pass
if static.TNC_STATE == 'IDLE': if static.TNC_STATE == 'IDLE':
# here we send an "CONNECT FRAME # here we send an "CONNECT FRAME
ARQ_CONNECT_THREAD = threading.Thread(target=data_handler.arq_connect, args=[dxcallsign], name="ARQ_CONNECT") ARQ_CONNECT_THREAD = threading.Thread(target=data_handler.arq_connect, name="ARQ_CONNECT")
ARQ_CONNECT_THREAD.start() ARQ_CONNECT_THREAD.start()
# ARQ DISCONNECT FROM CALLSIGN ---------------------------------------- # ARQ DISCONNECT FROM CALLSIGN ----------------------------------------
@ -81,8 +85,19 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler):
# TRANSMIT ARQ MESSAGE ------------------------------------------ # TRANSMIT ARQ MESSAGE ------------------------------------------
# wen need to change the TNC_STATE to "CONNECTE" and need to make sure we have a valid callsign and callsign crc8 of the DX station # wen need to change the TNC_STATE to "CONNECTE" and need to make sure we have a valid callsign and callsign crc8 of the DX station
if data.startswith('ARQ:DATA') and static.TNC_STATE == b'IDLE': print(static.ARQ_STATE)
if data.startswith('ARQ:DATA') and static.ARQ_STATE == 'CONNECTED':
static.ARQ_READY_FOR_DATA = False
logging.info("CMD | NEW ARQ DATA") logging.info("CMD | NEW ARQ DATA")
asyncio.run(data_handler.arq_open_data_channel())
#wait until we set the data mode
# here we need a timeout as well!!!
while static.ARQ_READY_FOR_DATA == False:
time.sleep(0.01)
if static.ARQ_READY_FOR_DATA == True:
logging.info("CMD | SENDING ARQ DATA")
static.TNC_STATE = 'BUSY' static.TNC_STATE = 'BUSY'
arqdata = data.split('ARQ:') arqdata = data.split('ARQ:')
data_out = bytes(arqdata[1], 'utf-8') data_out = bytes(arqdata[1], 'utf-8')
@ -94,11 +109,11 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler):
# SETTINGS AND STATUS --------------------------------------------- # SETTINGS AND STATUS ---------------------------------------------
if data.startswith('SET:MYCALLSIGN:'): if data.startswith('SET:MYCALLSIGN:'):
data = data.split('SET:MYCALLSIGN:') callsign = data.split('SET:MYCALLSIGN:')
if bytes(data[1], encoding) == b'': if bytes(callsign[1], encoding) == b'':
self.request.sendall(b'INVALID CALLSIGN') self.request.sendall(b'INVALID CALLSIGN')
else: else:
static.MYCALLSIGN = bytes(data[1], encoding) static.MYCALLSIGN = bytes(callsign[1], encoding)
static.MYCALLSIGN_CRC8 = helpers.get_crc_8(static.MYCALLSIGN) static.MYCALLSIGN_CRC8 = helpers.get_crc_8(static.MYCALLSIGN)
self.request.sendall(static.MYCALLSIGN) self.request.sendall(static.MYCALLSIGN)
logging.info("CMD | MYCALLSIGN: " + str(static.MYCALLSIGN)) logging.info("CMD | MYCALLSIGN: " + str(static.MYCALLSIGN))
@ -119,9 +134,6 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler):
if data == 'GET:PTT_STATE': if data == 'GET:PTT_STATE':
self.request.sendall(bytes(str(static.PTT_STATE), encoding)) self.request.sendall(bytes(str(static.PTT_STATE), encoding))
# ARQ # ARQ
if data == 'GET:ARQ_STATE': if data == 'GET:ARQ_STATE':
self.request.sendall(bytes(static.ARQ_STATE, encoding)) self.request.sendall(bytes(static.ARQ_STATE, encoding))

View file

@ -62,7 +62,7 @@ PTT_STATE = False
# FreeDV Defaults # FreeDV Defaults
FREEDV_RECEIVE = True FREEDV_RECEIVE = True
FREEDV_DATA_MODE = 10 FREEDV_DATA_MODE = 12
FREEDV_SIGNALLING_MODE = 14 FREEDV_SIGNALLING_MODE = 14
FREEDV_DATA_BYTES_PER_FRAME = 0 FREEDV_DATA_BYTES_PER_FRAME = 0
@ -157,11 +157,20 @@ ARQ_STATE = 'IDLE'
CHANNEL_STATE = 'RECEIVING_SIGNALLING' CHANNEL_STATE = 'RECEIVING_SIGNALLING'
# IDLE # IDLE
# CONNECTING # BUSY
# DISCONNECTING
TNC_STATE = 'IDLE' TNC_STATE = 'IDLE'
# MODE FOR SENDING AN RECEIVING DATA DURING ARQ SESSION
# 0 = NOT WAITING FOR DATA
# 1 = TELL DX STATION WE WANT TO SEND DATA
# 2 = DX STATION IS READY FOR DATA
# 3 = DX STATION SAID, THEY ARE READY FOR DATA
ARQ_READY_FOR_DATA = False
ARQ_DATA_CHANNEL_MODE = 12
# SEND KEEP ALIVE ONLY IF WE WANT
ARQ_SEND_KEEP_ALIVE = True
ARQ_WAIT_FOR_DISCONNECT = False
# ------- TX BUFFER # ------- TX BUFFER
TX_BUFFER_SIZE = 0 TX_BUFFER_SIZE = 0