From 9a263757b12bcc19414bcf290fcc2309aab58d68 Mon Sep 17 00:00:00 2001 From: DJ2LS <75909252+DJ2LS@users.noreply.github.com> Date: Sun, 28 Feb 2021 15:24:14 +0100 Subject: [PATCH] first working data channel --- data_handler.py | 199 +++++++++++++++++++++++++++++++++++++++--------- modem.py | 189 +++++++++++++++++++++++---------------------- sock.py | 42 ++++++---- static.py | 15 +++- 4 files changed, 298 insertions(+), 147 deletions(-) diff --git a/data_handler.py b/data_handler.py index ba88629f..ccb62916 100644 --- a/data_handler.py +++ b/data_handler.py @@ -16,6 +16,8 @@ import modem modem = modem.RF() import helpers +import asyncio + ############################################################################################################# # 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_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_N_ARQ_FRAMES_PER_DATA_FRAME = 0 static.TNC_STATE = 'IDLE' + static.ARQ_SEND_KEEP_ALIVE = True #print("----------------------------------------------------------------") #print(static.RX_BUFFER[-1]) @@ -198,14 +201,33 @@ def data_received(data_in): else: logging.error("ARQ | RX | DATA FRAME NOT SUCESSFULLY RECEIVED!") static.ARQ_STATE = 'IDLE' + static.ARQ_SEND_KEEP_ALIVE = True 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 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): 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 @@ -447,60 +469,167 @@ def burst_rpt_received(data_in): # ARQ CONNECT HANDLER ############################################################################################################# -def arq_connect(callsign): +def arq_connect(): 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]) - 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.start() + def arq_received_connect(data_in): static.ARQ_STATE = 'CONNECTING' - dxcallsign = data_in[1:6] - static.DXCALLSIGN = bytes(dxcallsign) - static.DXCALLSIGN_CRC8 = helpers.get_crc_8(static.DXCALLSIGN) - logging.info("CONNECTING ["+ str(static.MYCALLSIGN, 'utf-8') + "]-> <-["+ str(static.DXCALLSIGN, 'utf-8') + "]") + + static.DXCALLSIGN = bytes(data_in[3:9]).rstrip(b'\x00') + static.DXCALLSIGN_CRC8 = helpers.get_crc_8(static.DXCALLSIGN) + #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]) - 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.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() - #TRANSMIT_CONNECT_THREAD = threading.Thread(target=modem.transmit_signalling, args=[connection_frame], name="TRANSMIT_ARQ") - #TRANSMIT_CONNECT_THREAD.start() + else: + 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(): + + # 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' - 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]) 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.start() - - logging.info("DISCONNECTED ["+ str(static.MYCALLSIGN, 'utf-8') + "] < > ["+ str(static.DXCALLSIGN, 'utf-8') + "]") + while static.CHANNEL_STATE == 'SENDING_SIGNALLING' or static.ARQ_WAIT_FOR_DISCONNECT == False: + time.sleep(0.01) + + logging.info("DISC ["+ str(static.MYCALLSIGN, 'utf-8') + "]< X >["+ str(static.DXCALLSIGN, 'utf-8') + "]") static.ARQ_STATE = 'IDLE' static.DXCALLSIGN = b'' static.DXCALLSIGN_CRC8 = b'' def arq_disconnect_received(data_in): 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.TNC_STATE = 'IDLE' static.DXCALLSIGN = b'' static.DXCALLSIGN_CRC8 = b'' + + ############################################################################################################# # PING HANDLER @@ -508,33 +637,36 @@ def arq_disconnect_received(data_in): def transmit_ping(callsign): 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]) ping_payload = b'PING' - ping_frame = frame_type + ping_payload TRANSMIT_PING_THREAD = threading.Thread(target=modem.transmit_signalling, args=[ping_frame], name="TRANSMIT_ARQ") TRANSMIT_PING_THREAD.start() - + # wait while sending.... + while static.CHANNEL_STATE == 'SENDING_SIGNALLING': + time.sleep(0.01) + 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]) ping_payload = b'PING_ACK' - 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.start() - + # wait while sending.... + while static.CHANNEL_STATE == 'SENDING_SIGNALLING': + time.sleep(0.01) + def received_ping_ack(data_in): dxcallsign = data_in[1:6] static.DXCALLSIGN = bytes(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' ############################################################################################################# @@ -544,7 +676,6 @@ def received_ping_ack(data_in): def transmit_cq(): logging.info("CQ CQ CQ") frame_type = bytes([200]) - print(frame_type) cq_frame = frame_type + static.MYCALLSIGN modem.transmit_signalling(cq_frame) diff --git a/modem.py b/modem.py index 3c792d7b..75656bfe 100644 --- a/modem.py +++ b/modem.py @@ -24,11 +24,6 @@ import Hamlib - - - - - class RF(): def __init__(self): @@ -59,9 +54,17 @@ class RF(): output_device_index=static.AUDIO_OUTPUT_DEVICE, #static.AUDIO_OUTPUT_DEVICE ) #--------------------------------------------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.start() + FREEDV_DECODER_THREAD_10 = threading.Thread(target=self.receive, args=[10], name="FREEDV_DECODER_THREAD") + 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 @@ -248,29 +251,35 @@ class RF(): static.PTT_STATE = False self.my_rig.set_ptt(self.hamlib_ptt_type,0) #-------------------------------------------------------------------------------------------------------- - def receive(self,data_mode,signalling_mode): + + def receive(self,mode): 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) + + bytes_per_frame = int(self.c_lib.freedv_get_bits_per_modem_frame(freedv)/8) + + if mode == static.FREEDV_SIGNALLING_MODE: + static.FREEDV_SIGNALLING_BYTES_PER_FRAME = bytes_per_frame + static.FREEDV_SIGNALLING_PAYLOAD_PER_FRAME = bytes_per_frame - 2 + + self.c_lib.freedv_set_frames_per_burst(freedv, 1); - freedv_data = self.c_lib.freedv_open(data_mode) - freedv_signalling = self.c_lib.freedv_open(signalling_mode) + elif mode == static.ARQ_DATA_CHANNEL_MODE: + 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, 0); + 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 - static.FREEDV_DATA_BYTES_PER_FRAME = int(self.c_lib.freedv_get_bits_per_modem_frame(freedv_data)/8) - static.FREEDV_DATA_PAYLOAD_PER_FRAME = static.FREEDV_DATA_BYTES_PER_FRAME -2 - 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 = static.FREEDV_SIGNALLING_BYTES_PER_FRAME -2 - - data_bytes_out = (ctypes.c_ubyte * static.FREEDV_DATA_BYTES_PER_FRAME) - data_bytes_out = data_bytes_out() #get pointer to bytes_out - - signalling_bytes_out = (ctypes.c_ubyte * static.FREEDV_SIGNALLING_BYTES_PER_FRAME) - signalling_bytes_out = signalling_bytes_out() #get pointer to bytes_out - - self.c_lib.freedv_set_frames_per_burst(freedv_data, 0); - self.c_lib.freedv_set_frames_per_burst(freedv_signalling, 1); - - # with this we can interrupt receiving while static.FREEDV_RECEIVE == True: time.sleep(0.01) @@ -279,47 +288,53 @@ class RF(): stuck_in_sync_10_counter = 0 # - while static.CHANNEL_STATE == 'RECEIVING_DATA': - time.sleep(0.01) + 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): - nin = self.c_lib.freedv_nin(freedv_data) + + static.FREEDV_DATA_BYTES_PER_FRAME = bytes_per_frame + static.FREEDV_DATA_PAYLOAD_PER_FRAME = bytes_per_frame - 2 + + time.sleep(0.01) + nin = self.c_lib.freedv_nin(freedv) #nin = int(nin*(static.AUDIO_SAMPLE_RATE_RX/static.MODEM_SAMPLE_RATE)) - data_in = self.stream_rx.read(nin, exception_on_overflow = False) #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 - nbytes = self.c_lib.freedv_rawdatarx(freedv_data, data_bytes_out, data_in) # demodulate audio - logging.debug(self.c_lib.freedv_get_rx_status(freedv_data)) - + nbytes = self.c_lib.freedv_rawdatarx(freedv, bytes_out, data_in) # demodulate audio + #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_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 - 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") - 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_10_counter = 0 if stuck_in_sync_counter >= 66 and stuck_in_sync_10_counter >= 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_10_counter = 0 #----------------------------------- # get bit errors - Tbits = self.c_lib.freedv_get_total_bits(freedv_data) - Terrs = self.c_lib.freedv_get_total_bit_errors(freedv_data) + Tbits = self.c_lib.freedv_get_total_bits(freedv) + Terrs = self.c_lib.freedv_get_total_bit_errors(freedv) if Tbits != 0: static.UNCODED_BER = Terrs/Tbits - if nbytes == static.FREEDV_DATA_BYTES_PER_FRAME: - rxstatus = self.c_lib.freedv_get_rx_status(freedv_data) - logging.debug("DATA-" + str(rxstatus)) + if nbytes == bytes_per_frame:###################################################################################################FREEDV_DATA_BYTES_PER_FRAME + + + + rxstatus = self.c_lib.freedv_get_rx_status(freedv) + #logging.debug("DATA-" + str(rxstatus)) # counter reset for stuck in sync counter stuck_in_sync_counter = 0 @@ -327,61 +342,28 @@ class RF(): # # 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 - 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); if 50 >= frametype >= 10: 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))) if static.ARQ_RX_BURST_BUFFER.count(None) <= 1: logging.debug("FULL BURST BUFFER ---> UNSYNC") - self.c_lib.freedv_set_sync(freedv_data, 0) + self.c_lib.freedv_set_sync(freedv, 0) else: logging.critical("---------------------------SIMULATED MISSING FRAME") 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 - if frametype == 60: + elif frametype == 60: logging.debug("ACK RECEIVED....") data_handler.burst_ack_received() @@ -393,7 +375,7 @@ class RF(): # FRAME RPT elif frametype == 62: logging.debug("REPEAT REQUEST RECEIVED....") - data_handler.burst_rpt_received(signalling_bytes_out[:-2]) + data_handler.burst_rpt_received(bytes_out[:-2]) # CQ FRAME elif frametype == 200: @@ -402,42 +384,59 @@ class RF(): # PING FRAME elif frametype == 210: logging.debug("PING RECEIVED....") - data_handler.received_ping(signalling_bytes_out[:-2]) + data_handler.received_ping(bytes_out[:-2]) # PING ACK elif frametype == 211: logging.debug("PING ACK RECEIVED....") - data_handler.received_ping_ack(signalling_bytes_out[:-2]) + data_handler.received_ping_ack(bytes_out[:-2]) # ARQ CONNECT elif frametype == 220: 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 elif frametype == 221: 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 elif frametype == 222: 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 elif frametype == 230: logging.debug("BEACON RECEIVED") else: - logging.info("OTHER FRAME: " + str(signalling_bytes_out[:-2])) + logging.info("OTHER FRAME: " + str(bytes_out[:-2])) 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) - logging.debug("ACK-" + str(rxstatus)) - if rxstatus == 10: - #self.c_lib.freedv_set_sync(freedv_signalling, 0) #FORCE UNSYNC - 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 + #reset bit error counters + 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: + self.c_lib.freedv_set_sync(freedv, 0) #FORCE UNSYNC + print("SIGNALLING -SYNC 10- Trigger") + diff --git a/sock.py b/sock.py index 15f38bd4..e0f0d077 100644 --- a/sock.py +++ b/sock.py @@ -16,6 +16,7 @@ import data_handler import helpers import fec +import asyncio class CMDTCPRequestHandler(socketserver.BaseRequestHandler): @@ -60,14 +61,17 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler): if data.startswith('ARQ:CONNECT:'): arqconnectcommand = data.split('ARQ:CONNECT:') dxcallsign = arqconnectcommand[1] + static.DXCALLSIGN = bytes(dxcallsign, 'utf-8') + static.DXCALLSIGN_CRC8 = helpers.get_crc_8(static.DXCALLSIGN) + if static.ARQ_STATE == 'CONNECTED': - # here we should disconnect + # here we could disconnect pass if static.TNC_STATE == 'IDLE': # 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 DISCONNECT FROM CALLSIGN ---------------------------------------- @@ -81,28 +85,39 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler): # 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 - 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") - static.TNC_STATE = 'BUSY' - arqdata = data.split('ARQ:') - data_out = bytes(arqdata[1], 'utf-8') + 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' + arqdata = data.split('ARQ:') + data_out = bytes(arqdata[1], 'utf-8') - TRANSMIT_ARQ = threading.Thread(target=data_handler.transmit, args=[data_out], name="TRANSMIT_ARQ") - TRANSMIT_ARQ.start() + TRANSMIT_ARQ = threading.Thread(target=data_handler.transmit, args=[data_out], name="TRANSMIT_ARQ") + TRANSMIT_ARQ.start() # SETTINGS AND STATUS --------------------------------------------- if data.startswith('SET:MYCALLSIGN:'): - data = data.split('SET:MYCALLSIGN:') - if bytes(data[1], encoding) == b'': + callsign = data.split('SET:MYCALLSIGN:') + if bytes(callsign[1], encoding) == b'': self.request.sendall(b'INVALID CALLSIGN') else: - static.MYCALLSIGN = bytes(data[1], encoding) + static.MYCALLSIGN = bytes(callsign[1], encoding) static.MYCALLSIGN_CRC8 = helpers.get_crc_8(static.MYCALLSIGN) self.request.sendall(static.MYCALLSIGN) logging.info("CMD | MYCALLSIGN: " + str(static.MYCALLSIGN)) - + if data == 'GET:MYCALLSIGN': self.request.sendall(bytes(static.MYCALLSIGN, encoding)) @@ -118,9 +133,6 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler): if data == 'GET:PTT_STATE': self.request.sendall(bytes(str(static.PTT_STATE), encoding)) - - - # ARQ if data == 'GET:ARQ_STATE': diff --git a/static.py b/static.py index e48afc49..f6b5adb9 100644 --- a/static.py +++ b/static.py @@ -62,7 +62,7 @@ PTT_STATE = False # FreeDV Defaults FREEDV_RECEIVE = True -FREEDV_DATA_MODE = 10 +FREEDV_DATA_MODE = 12 FREEDV_SIGNALLING_MODE = 14 FREEDV_DATA_BYTES_PER_FRAME = 0 @@ -157,11 +157,20 @@ ARQ_STATE = 'IDLE' CHANNEL_STATE = 'RECEIVING_SIGNALLING' # IDLE -# CONNECTING -# DISCONNECTING +# BUSY 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_SIZE = 0